Merge pull request #441 from mathuo/397-gready-rendering-mode

bug: destroy overlay render when detached
This commit is contained in:
mathuo 2024-01-11 11:33:30 +00:00 committed by GitHub
commit 1d9b285bf4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 90 additions and 41 deletions

View File

@ -6,11 +6,22 @@ import { fromPartial } from '@total-typescript/shoehorn';
import { Writable, exhaustMicrotaskQueue } from './__test_utils__/utils'; import { Writable, exhaustMicrotaskQueue } from './__test_utils__/utils';
describe('overlayRenderContainer', () => { describe('overlayRenderContainer', () => {
test('add a view that is not currently in the DOM', async () => { let referenceContainer: IRenderable;
const parentContainer = document.createElement('div'); let parentContainer: HTMLElement;
let cut: OverlayRenderContainer;
const cut = new OverlayRenderContainer(parentContainer); beforeEach(() => {
parentContainer = document.createElement('div');
referenceContainer = {
element: document.createElement('div'),
dropTarget: fromPartial<Droptarget>({}),
};
cut = new OverlayRenderContainer(parentContainer);
});
test('that attach(...) and detach(...) mutate the DOM as expected', () => {
const panelContentEl = document.createElement('div'); const panelContentEl = document.createElement('div');
const onDidVisibilityChange = new Emitter<any>(); const onDidVisibilityChange = new Emitter<any>();
@ -35,14 +46,41 @@ describe('overlayRenderContainer', () => {
}, },
}); });
const dropTarget = fromPartial<Droptarget>({}); cut.attach({ panel, referenceContainer });
const refContainerEl = document.createElement('div'); expect(panelContentEl.parentElement?.parentElement).toBe(
parentContainer
);
const referenceContainer: IRenderable = { cut.detatch(panel);
element: refContainerEl,
dropTarget, expect(panelContentEl.parentElement?.parentElement).toBeUndefined();
}; });
test('add a view that is not currently in the DOM', async () => {
const panelContentEl = document.createElement('div');
const onDidVisibilityChange = new Emitter<any>();
const onDidDimensionsChange = new Emitter<any>();
const panel = fromPartial<IDockviewPanel>({
api: {
id: 'test_panel_id',
onDidVisibilityChange: onDidVisibilityChange.event,
onDidDimensionsChange: onDidDimensionsChange.event,
isVisible: true,
},
view: {
content: {
element: panelContentEl,
},
},
group: {
api: {
location: 'grid',
},
},
});
(parentContainer as jest.Mocked<HTMLDivElement>).getBoundingClientRect = (parentContainer as jest.Mocked<HTMLDivElement>).getBoundingClientRect =
jest jest
@ -72,33 +110,34 @@ describe('overlayRenderContainer', () => {
}) })
); );
(refContainerEl as jest.Mocked<HTMLDivElement>).getBoundingClientRect = (
jest referenceContainer.element as jest.Mocked<HTMLDivElement>
.fn<DOMRect, []>() ).getBoundingClientRect = jest
.mockReturnValueOnce( .fn<DOMRect, []>()
fromPartial<DOMRect>({ .mockReturnValueOnce(
left: 150, fromPartial<DOMRect>({
top: 300, left: 150,
width: 100, top: 300,
height: 200, width: 100,
}) height: 200,
) })
.mockReturnValueOnce( )
fromPartial<DOMRect>({ .mockReturnValueOnce(
left: 150, fromPartial<DOMRect>({
top: 300, left: 150,
width: 101, top: 300,
height: 201, width: 101,
}) height: 201,
) })
.mockReturnValueOnce( )
fromPartial<DOMRect>({ .mockReturnValueOnce(
left: 150, fromPartial<DOMRect>({
top: 300, left: 150,
width: 100, top: 300,
height: 200, width: 100,
}) height: 200,
); })
);
const container = cut.attach({ panel, referenceContainer }); const container = cut.attach({ panel, referenceContainer });
@ -113,7 +152,9 @@ describe('overlayRenderContainer', () => {
expect(container.style.top).toBe('100px'); expect(container.style.top).toBe('100px');
expect(container.style.width).toBe('100px'); expect(container.style.width).toBe('100px');
expect(container.style.height).toBe('200px'); expect(container.style.height).toBe('200px');
expect(refContainerEl.getBoundingClientRect).toHaveBeenCalledTimes(1); expect(
referenceContainer.element.getBoundingClientRect
).toHaveBeenCalledTimes(1);
onDidDimensionsChange.fire({}); onDidDimensionsChange.fire({});
expect(container.style.display).toBe(''); expect(container.style.display).toBe('');
@ -122,12 +163,16 @@ describe('overlayRenderContainer', () => {
expect(container.style.top).toBe('99px'); expect(container.style.top).toBe('99px');
expect(container.style.width).toBe('101px'); expect(container.style.width).toBe('101px');
expect(container.style.height).toBe('201px'); expect(container.style.height).toBe('201px');
expect(refContainerEl.getBoundingClientRect).toHaveBeenCalledTimes(2); expect(
referenceContainer.element.getBoundingClientRect
).toHaveBeenCalledTimes(2);
(panel as Writable<IDockviewPanel>).api.isVisible = false; (panel as Writable<IDockviewPanel>).api.isVisible = false;
onDidVisibilityChange.fire({}); onDidVisibilityChange.fire({});
expect(container.style.display).toBe('none'); expect(container.style.display).toBe('none');
expect(refContainerEl.getBoundingClientRect).toHaveBeenCalledTimes(2); expect(
referenceContainer.element.getBoundingClientRect
).toHaveBeenCalledTimes(2);
(panel as Writable<IDockviewPanel>).api.isVisible = true; (panel as Writable<IDockviewPanel>).api.isVisible = true;
onDidVisibilityChange.fire({}); onDidVisibilityChange.fire({});
@ -137,6 +182,8 @@ describe('overlayRenderContainer', () => {
expect(container.style.top).toBe('100px'); expect(container.style.top).toBe('100px');
expect(container.style.width).toBe('100px'); expect(container.style.width).toBe('100px');
expect(container.style.height).toBe('200px'); expect(container.style.height).toBe('200px');
expect(refContainerEl.getBoundingClientRect).toHaveBeenCalledTimes(3); expect(
referenceContainer.element.getBoundingClientRect
).toHaveBeenCalledTimes(3);
}); });
}); });

View File

@ -43,7 +43,9 @@ export class OverlayRenderContainer extends CompositeDisposable {
detatch(panel: IDockviewPanel): boolean { detatch(panel: IDockviewPanel): boolean {
if (this.map[panel.api.id]) { if (this.map[panel.api.id]) {
this.map[panel.api.id].disposable.dispose(); const { disposable, destroy } = this.map[panel.api.id];
disposable.dispose();
destroy.dispose();
delete this.map[panel.api.id]; delete this.map[panel.api.id];
return true; return true;
} }