test: add tests

This commit is contained in:
mathuo 2024-10-26 21:54:13 +01:00
parent 3c680b251f
commit f557e9080a
No known key found for this signature in database
GPG Key ID: C6EEDEFD6CA07281
5 changed files with 113 additions and 36 deletions

View File

@ -0,0 +1,35 @@
import { fromPartial } from "@total-typescript/shoehorn";
export function setupMockWindow() {
const listeners: Record<string, (() => void)[]> = {};
let width = 1000;
let height = 2000;
return fromPartial<Window>({
addEventListener: (type: string, listener: () => void) => {
if (!listeners[type]) {
listeners[type] = [];
}
listeners[type].push(listener);
if (type === 'load') {
listener();
}
},
dispatchEvent: (event: Event) => {
const items = listeners[event.type];
if (!items) {
return;
}
items.forEach((item) => item());
},
document: document,
close: jest.fn(),
get innerWidth() {
return width++;
},
get innerHeight() {
return height++;
},
});
}

View File

@ -19,6 +19,8 @@ import {
import { fromPartial } from '@total-typescript/shoehorn'; import { fromPartial } from '@total-typescript/shoehorn';
import { DockviewApi } from '../../api/component.api'; import { DockviewApi } from '../../api/component.api';
import { DockviewDndOverlayEvent } from '../../dockview/options'; import { DockviewDndOverlayEvent } from '../../dockview/options';
import { SizeEvent } from '../../api/gridviewPanelApi';
import { setupMockWindow } from '../__mocks__/mockWindow';
class PanelContentPartTest implements IContentRenderer { class PanelContentPartTest implements IContentRenderer {
element: HTMLElement = document.createElement('div'); element: HTMLElement = document.createElement('div');
@ -115,7 +117,7 @@ describe('dockviewComponent', () => {
}, },
}); });
window.open = jest.fn(); // not implemented by jest window.open = jest.fn();
}); });
test('update className', () => { test('update className', () => {
@ -4817,6 +4819,8 @@ describe('dockviewComponent', () => {
test('add a popout group', async () => { test('add a popout group', async () => {
const container = document.createElement('div'); const container = document.createElement('div');
window.open = () => setupMockWindow();
const dockview = new DockviewComponent(container, { const dockview = new DockviewComponent(container, {
createComponent(options) { createComponent(options) {
switch (options.name) { switch (options.name) {
@ -4848,12 +4852,36 @@ describe('dockviewComponent', () => {
expect(dockview.groups.length).toBe(1); expect(dockview.groups.length).toBe(1);
expect(dockview.panels.length).toBe(2); expect(dockview.panels.length).toBe(2);
await dockview.addPopoutGroup(panel2.group); const events: SizeEvent[] = [];
panel2.api.onDidDimensionsChange((event) => {
events.push(event);
});
const originalGroup = panel2.group;
expect(await dockview.addPopoutGroup(panel2.group)).toBeTruthy();
expect(events).toEqual([{ height: 2000, width: 1000 }]);
expect(originalGroup.api.location.type).toBe('grid');
expect(originalGroup.api.isVisible).toBeFalsy();
expect(panel1.group.api.location.type).toBe('popout'); expect(panel1.group.api.location.type).toBe('popout');
expect(panel2.group.api.location.type).toBe('popout'); expect(panel2.group.api.location.type).toBe('popout');
expect(dockview.groups.length).toBe(2); expect(dockview.groups.length).toBe(2);
expect(dockview.panels.length).toBe(2); expect(dockview.panels.length).toBe(2);
if (panel2.api.location.type !== 'popout') {
fail('unexpected');
}
const alternativeWindow = panel2.api.location.getWindow();
alternativeWindow.dispatchEvent(new Event('resize'));
expect(events).toEqual([
{ height: 2000, width: 1000 },
{ height: 2001, width: 1001 },
]);
}); });
test('remove all panels from popout group', async () => { test('remove all panels from popout group', async () => {
@ -4892,7 +4920,7 @@ describe('dockviewComponent', () => {
position: { referencePanel: panel2 }, position: { referencePanel: panel2 },
}); });
await dockview.addPopoutGroup(panel2.group); expect(await dockview.addPopoutGroup(panel2.group)).toBeTruthy();
expect(panel1.group.api.location.type).toBe('grid'); expect(panel1.group.api.location.type).toBe('grid');
expect(panel2.group.api.location.type).toBe('popout'); expect(panel2.group.api.location.type).toBe('popout');
@ -4934,7 +4962,7 @@ describe('dockviewComponent', () => {
component: 'default', component: 'default',
}); });
await dockview.addPopoutGroup(panel1); expect(await dockview.addPopoutGroup(panel1)).toBeTruthy();
expect(dockview.panels.length).toBe(1); expect(dockview.panels.length).toBe(1);
expect(dockview.groups.length).toBe(2); expect(dockview.groups.length).toBe(2);
@ -4989,7 +5017,7 @@ describe('dockviewComponent', () => {
expect(dockview.groups.length).toBe(2); expect(dockview.groups.length).toBe(2);
expect(dockview.panels.length).toBe(3); expect(dockview.panels.length).toBe(3);
await dockview.addPopoutGroup(panel2.group); expect(await dockview.addPopoutGroup(panel2.group)).toBeTruthy();
expect(panel1.group.api.location.type).toBe('popout'); expect(panel1.group.api.location.type).toBe('popout');
expect(panel2.group.api.location.type).toBe('popout'); expect(panel2.group.api.location.type).toBe('popout');

View File

@ -913,7 +913,7 @@ export class DockviewApi implements CommonApi<SerializedDockview> {
onDidOpen?: (event: { id: string; window: Window }) => void; onDidOpen?: (event: { id: string; window: Window }) => void;
onWillClose?: (event: { id: string; window: Window }) => void; onWillClose?: (event: { id: string; window: Window }) => void;
} }
): Promise<void> { ): Promise<boolean> {
return this.component.addPopoutGroup(item, options); return this.component.addPopoutGroup(item, options);
} }

View File

@ -218,7 +218,7 @@ export interface IDockviewComponent extends IBaseGrid<DockviewGroupPanel> {
onDidOpen?: (event: { id: string; window: Window }) => void; onDidOpen?: (event: { id: string; window: Window }) => void;
onWillClose?: (event: { id: string; window: Window }) => void; onWillClose?: (event: { id: string; window: Window }) => void;
} }
): Promise<void>; ): Promise<boolean>;
} }
export class DockviewComponent export class DockviewComponent
@ -548,7 +548,7 @@ export class DockviewComponent
onWillClose?: (event: { id: string; window: Window }) => void; onWillClose?: (event: { id: string; window: Window }) => void;
overridePopoutGroup?: DockviewGroupPanel; overridePopoutGroup?: DockviewGroupPanel;
} }
): Promise<void> { ): Promise<boolean> {
if ( if (
itemToPopout instanceof DockviewPanel && itemToPopout instanceof DockviewPanel &&
itemToPopout.group.size === 1 itemToPopout.group.size === 1
@ -579,10 +579,6 @@ export class DockviewComponent
const groupId = const groupId =
options?.overridePopoutGroup?.id ?? this.getNextGroupId(); options?.overridePopoutGroup?.id ?? this.getNextGroupId();
if (itemToPopout.api.location.type === 'grid') {
itemToPopout.api.setVisible(false);
}
const _window = new PopoutWindow( const _window = new PopoutWindow(
`${this.id}-${groupId}`, // unique id `${this.id}-${groupId}`, // unique id
theme ?? '', theme ?? '',
@ -608,12 +604,12 @@ export class DockviewComponent
.open() .open()
.then((popoutContainer) => { .then((popoutContainer) => {
if (_window.isDisposed) { if (_window.isDisposed) {
return; return false;
} }
if (popoutContainer === null) { if (popoutContainer === null) {
popoutWindowDisposable.dispose(); popoutWindowDisposable.dispose();
return; return false;
} }
const gready = document.createElement('div'); const gready = document.createElement('div');
@ -635,7 +631,10 @@ export class DockviewComponent
options?.overridePopoutGroup ?? options?.overridePopoutGroup ??
this.createGroup({ id: groupId }); this.createGroup({ id: groupId });
group.model.renderContainer = overlayRenderContainer; group.model.renderContainer = overlayRenderContainer;
group.layout(_window.window!.innerWidth, _window.window!.innerHeight); group.layout(
_window.window!.innerWidth,
_window.window!.innerHeight
);
if (!options?.overridePopoutGroup) { if (!options?.overridePopoutGroup) {
this._onDidAddGroup.fire(group); this._onDidAddGroup.fire(group);
@ -677,6 +676,10 @@ export class DockviewComponent
getWindow: () => _window.window!, getWindow: () => _window.window!,
}; };
if (itemToPopout.api.location.type === 'grid') {
itemToPopout.api.setVisible(false);
}
this.doSetGroupAndPanelActive(group); this.doSetGroupAndPanelActive(group);
popoutWindowDisposable.addDisposables( popoutWindowDisposable.addDisposables(
@ -716,7 +719,10 @@ export class DockviewComponent
_window.window!, _window.window!,
'resize', 'resize',
() => { () => {
group.layout(_window.window!.innerWidth, _window.window!.innerHeight); group.layout(
_window.window!.innerWidth,
_window.window!.innerHeight
);
} }
), ),
overlayRenderContainer, overlayRenderContainer,
@ -753,9 +759,12 @@ export class DockviewComponent
this._popoutGroups.push(value); this._popoutGroups.push(value);
this.updateWatermark(); this.updateWatermark();
return true;
}) })
.catch((err) => { .catch((err) => {
console.error('dockview: failed to create popout window', err); console.error('dockview: failed to create popout window', err);
return false;
}); });
} }

View File

@ -124,7 +124,7 @@ export class PopoutWindow extends CompositeDisposable {
window: externalWindow, window: externalWindow,
}); });
return new Promise<HTMLElement | null>((resolve) => { return new Promise<HTMLElement | null>((resolve, reject) => {
externalWindow.addEventListener('unload', (e) => { externalWindow.addEventListener('unload', (e) => {
// if page fails to load before unloading // if page fails to load before unloading
// this.close(); // this.close();
@ -135,29 +135,34 @@ export class PopoutWindow extends CompositeDisposable {
* @see https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event * @see https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event
*/ */
const externalDocument = externalWindow.document; try {
externalDocument.title = document.title; const externalDocument = externalWindow.document;
externalDocument.title = document.title;
externalDocument.body.appendChild(container); externalDocument.body.appendChild(container);
addStyles(externalDocument, window.document.styleSheets); addStyles(externalDocument, window.document.styleSheets);
/** /**
* beforeunload must be registered after load for reasons I could not determine * beforeunload must be registered after load for reasons I could not determine
* otherwise the beforeunload event will not fire when the window is closed * otherwise the beforeunload event will not fire when the window is closed
*/ */
addDisposableWindowListener( addDisposableWindowListener(
externalWindow, externalWindow,
'beforeunload', 'beforeunload',
() => { () => {
/** /**
* @see https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event * @see https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event
*/ */
this.close(); this.close();
} }
); );
resolve(container); resolve(container);
} catch (err) {
// only except this is the DOM isn't setup. e.g. in a in correctly configured test
reject(err);
}
}); });
}); });
} }