mirror of
https://github.com/mathuo/dockview
synced 2025-09-02 23:46:31 +00:00
test: add comprehensive unit tests for disableDnd functionality
- Add unit tests for Tab draggable attribute with disableDnd option - Add unit tests for VoidContainer draggable attribute with disableDnd option - Add unit tests for updateDragAndDropState methods in all components - Add integration tests for updateOptions with disableDnd changes - Fix existing test mocks to include required options property Tests cover both initial state and dynamic updates when option changes. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
ad9f884847
commit
ac6154196e
@ -12,12 +12,14 @@ import { fromPartial } from '@total-typescript/shoehorn';
|
||||
|
||||
describe('tab', () => {
|
||||
test('that empty tab has inactive-tab class', () => {
|
||||
const accessorMock = jest.fn();
|
||||
const accessor = fromPartial<DockviewComponent>({
|
||||
options: {}
|
||||
});
|
||||
const groupMock = jest.fn();
|
||||
|
||||
const cut = new Tab(
|
||||
{ id: 'panelId' } as IDockviewPanel,
|
||||
new accessorMock(),
|
||||
accessor,
|
||||
new groupMock()
|
||||
);
|
||||
|
||||
@ -25,12 +27,14 @@ describe('tab', () => {
|
||||
});
|
||||
|
||||
test('that active tab has active-tab class', () => {
|
||||
const accessorMock = jest.fn();
|
||||
const accessor = fromPartial<DockviewComponent>({
|
||||
options: {}
|
||||
});
|
||||
const groupMock = jest.fn();
|
||||
|
||||
const cut = new Tab(
|
||||
{ id: 'panelId' } as IDockviewPanel,
|
||||
new accessorMock(),
|
||||
accessor,
|
||||
new groupMock()
|
||||
);
|
||||
|
||||
@ -42,26 +46,20 @@ describe('tab', () => {
|
||||
});
|
||||
|
||||
test('that an external event does not render a drop target and calls through to the group model', () => {
|
||||
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => {
|
||||
return {
|
||||
id: 'testcomponentid',
|
||||
};
|
||||
const accessor = fromPartial<DockviewComponent>({
|
||||
id: 'testcomponentid',
|
||||
options: {}
|
||||
});
|
||||
|
||||
const groupView = fromPartial<DockviewGroupPanelModel>({
|
||||
canDisplayOverlay: jest.fn(),
|
||||
});
|
||||
|
||||
const groupPanelMock = jest.fn<Partial<DockviewGroupPanel>, []>(() => {
|
||||
return {
|
||||
id: 'testgroupid',
|
||||
model: groupView,
|
||||
};
|
||||
const groupPanel = fromPartial<DockviewGroupPanel>({
|
||||
id: 'testgroupid',
|
||||
model: groupView,
|
||||
});
|
||||
|
||||
const accessor = new accessorMock() as DockviewComponent;
|
||||
const groupPanel = new groupPanelMock() as DockviewGroupPanel;
|
||||
|
||||
const cut = new Tab(
|
||||
{ id: 'panelId' } as IDockviewPanel,
|
||||
accessor,
|
||||
@ -86,26 +84,20 @@ describe('tab', () => {
|
||||
});
|
||||
|
||||
test('that if you drag over yourself a drop target is shown', () => {
|
||||
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => {
|
||||
return {
|
||||
id: 'testcomponentid',
|
||||
};
|
||||
const accessor = fromPartial<DockviewComponent>({
|
||||
id: 'testcomponentid',
|
||||
options: {}
|
||||
});
|
||||
|
||||
const groupView = fromPartial<DockviewGroupPanelModel>({
|
||||
canDisplayOverlay: jest.fn(),
|
||||
});
|
||||
|
||||
const groupPanelMock = jest.fn<Partial<DockviewGroupPanel>, []>(() => {
|
||||
return {
|
||||
id: 'testgroupid',
|
||||
model: groupView,
|
||||
};
|
||||
const groupPanel = fromPartial<DockviewGroupPanel>({
|
||||
id: 'testgroupid',
|
||||
model: groupView,
|
||||
});
|
||||
|
||||
const accessor = new accessorMock() as DockviewComponent;
|
||||
const groupPanel = new groupPanelMock() as DockviewGroupPanel;
|
||||
|
||||
const cut = new Tab(
|
||||
{ id: 'panel1' } as IDockviewPanel,
|
||||
accessor,
|
||||
@ -135,30 +127,19 @@ describe('tab', () => {
|
||||
});
|
||||
|
||||
test('that if you drag over another tab a drop target is shown', () => {
|
||||
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => {
|
||||
return {
|
||||
id: 'testcomponentid',
|
||||
};
|
||||
});
|
||||
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
|
||||
() => {
|
||||
return {
|
||||
canDisplayOverlay: jest.fn(),
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const groupView = new groupviewMock() as DockviewGroupPanelModel;
|
||||
|
||||
const groupPanelMock = jest.fn<Partial<DockviewGroupPanel>, []>(() => {
|
||||
return {
|
||||
id: 'testgroupid',
|
||||
model: groupView,
|
||||
};
|
||||
const accessor = fromPartial<DockviewComponent>({
|
||||
id: 'testcomponentid',
|
||||
options: {}
|
||||
});
|
||||
|
||||
const accessor = new accessorMock() as DockviewComponent;
|
||||
const groupPanel = new groupPanelMock() as DockviewGroupPanel;
|
||||
const groupView = fromPartial<DockviewGroupPanelModel>({
|
||||
canDisplayOverlay: jest.fn(),
|
||||
});
|
||||
|
||||
const groupPanel = fromPartial<DockviewGroupPanel>({
|
||||
id: 'testgroupid',
|
||||
model: groupView,
|
||||
});
|
||||
|
||||
const cut = new Tab(
|
||||
{ id: 'panel1' } as IDockviewPanel,
|
||||
@ -189,30 +170,19 @@ describe('tab', () => {
|
||||
});
|
||||
|
||||
test('that dropping on a tab with the same id but from a different component should not render a drop over and call through to the group model', () => {
|
||||
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => {
|
||||
return {
|
||||
id: 'testcomponentid',
|
||||
};
|
||||
});
|
||||
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
|
||||
() => {
|
||||
return {
|
||||
canDisplayOverlay: jest.fn(),
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const groupView = new groupviewMock() as DockviewGroupPanelModel;
|
||||
|
||||
const groupPanelMock = jest.fn<Partial<DockviewGroupPanel>, []>(() => {
|
||||
return {
|
||||
id: 'testgroupid',
|
||||
model: groupView,
|
||||
};
|
||||
const accessor = fromPartial<DockviewComponent>({
|
||||
id: 'testcomponentid',
|
||||
options: {}
|
||||
});
|
||||
|
||||
const accessor = new accessorMock() as DockviewComponent;
|
||||
const groupPanel = new groupPanelMock() as DockviewGroupPanel;
|
||||
const groupView = fromPartial<DockviewGroupPanelModel>({
|
||||
canDisplayOverlay: jest.fn(),
|
||||
});
|
||||
|
||||
const groupPanel = fromPartial<DockviewGroupPanel>({
|
||||
id: 'testgroupid',
|
||||
model: groupView,
|
||||
});
|
||||
|
||||
const cut = new Tab(
|
||||
{ id: 'panel1' } as IDockviewPanel,
|
||||
@ -249,30 +219,19 @@ describe('tab', () => {
|
||||
});
|
||||
|
||||
test('that dropping on a tab from a different component should not render a drop over and call through to the group model', () => {
|
||||
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => {
|
||||
return {
|
||||
id: 'testcomponentid',
|
||||
};
|
||||
});
|
||||
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
|
||||
() => {
|
||||
return {
|
||||
canDisplayOverlay: jest.fn(),
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const groupView = new groupviewMock() as DockviewGroupPanelModel;
|
||||
|
||||
const groupPanelMock = jest.fn<Partial<DockviewGroupPanel>, []>(() => {
|
||||
return {
|
||||
id: 'testgroupid',
|
||||
model: groupView,
|
||||
};
|
||||
const accessor = fromPartial<DockviewComponent>({
|
||||
id: 'testcomponentid',
|
||||
options: {}
|
||||
});
|
||||
|
||||
const accessor = new accessorMock() as DockviewComponent;
|
||||
const groupPanel = new groupPanelMock() as DockviewGroupPanel;
|
||||
const groupView = fromPartial<DockviewGroupPanelModel>({
|
||||
canDisplayOverlay: jest.fn(),
|
||||
});
|
||||
|
||||
const groupPanel = fromPartial<DockviewGroupPanel>({
|
||||
id: 'testgroupid',
|
||||
model: groupView,
|
||||
});
|
||||
|
||||
const cut = new Tab(
|
||||
{ id: 'panel1' } as IDockviewPanel,
|
||||
@ -307,4 +266,77 @@ describe('tab', () => {
|
||||
cut.element.getElementsByClassName('dv-drop-target-dropzone').length
|
||||
).toBe(0);
|
||||
});
|
||||
|
||||
describe('disableDnd option', () => {
|
||||
test('that tab is draggable by default (disableDnd not set)', () => {
|
||||
const accessor = fromPartial<DockviewComponent>({
|
||||
options: {}
|
||||
});
|
||||
const groupMock = jest.fn();
|
||||
|
||||
const cut = new Tab(
|
||||
{ id: 'panelId' } as IDockviewPanel,
|
||||
accessor,
|
||||
new groupMock()
|
||||
);
|
||||
|
||||
expect(cut.element.draggable).toBe(true);
|
||||
});
|
||||
|
||||
test('that tab is draggable when disableDnd is false', () => {
|
||||
const accessor = fromPartial<DockviewComponent>({
|
||||
options: { disableDnd: false }
|
||||
});
|
||||
const groupMock = jest.fn();
|
||||
|
||||
const cut = new Tab(
|
||||
{ id: 'panelId' } as IDockviewPanel,
|
||||
accessor,
|
||||
new groupMock()
|
||||
);
|
||||
|
||||
expect(cut.element.draggable).toBe(true);
|
||||
});
|
||||
|
||||
test('that tab is not draggable when disableDnd is true', () => {
|
||||
const accessor = fromPartial<DockviewComponent>({
|
||||
options: { disableDnd: true }
|
||||
});
|
||||
const groupMock = jest.fn();
|
||||
|
||||
const cut = new Tab(
|
||||
{ id: 'panelId' } as IDockviewPanel,
|
||||
accessor,
|
||||
new groupMock()
|
||||
);
|
||||
|
||||
expect(cut.element.draggable).toBe(false);
|
||||
});
|
||||
|
||||
test('that updateDragAndDropState updates draggable attribute based on disableDnd option', () => {
|
||||
const options = { disableDnd: false };
|
||||
const accessor = fromPartial<DockviewComponent>({
|
||||
options
|
||||
});
|
||||
const groupMock = jest.fn();
|
||||
|
||||
const cut = new Tab(
|
||||
{ id: 'panelId' } as IDockviewPanel,
|
||||
accessor,
|
||||
new groupMock()
|
||||
);
|
||||
|
||||
expect(cut.element.draggable).toBe(true);
|
||||
|
||||
// Simulate option change
|
||||
options.disableDnd = true;
|
||||
cut.updateDragAndDropState();
|
||||
expect(cut.element.draggable).toBe(false);
|
||||
|
||||
// Change back
|
||||
options.disableDnd = false;
|
||||
cut.updateDragAndDropState();
|
||||
expect(cut.element.draggable).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -63,4 +63,33 @@ describe('tabs', () => {
|
||||
).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateDragAndDropState', () => {
|
||||
test('that updateDragAndDropState calls updateDragAndDropState on all tabs', () => {
|
||||
const cut = new Tabs(
|
||||
fromPartial<DockviewGroupPanel>({}),
|
||||
fromPartial<DockviewComponent>({
|
||||
options: {},
|
||||
}),
|
||||
{
|
||||
showTabsOverflowControl: true,
|
||||
}
|
||||
);
|
||||
|
||||
// Mock tab to verify the method is called
|
||||
const mockTab1 = { updateDragAndDropState: jest.fn() };
|
||||
const mockTab2 = { updateDragAndDropState: jest.fn() };
|
||||
|
||||
// Add mock tabs to the internal tabs array
|
||||
(cut as any)._tabs = [
|
||||
{ value: mockTab1 },
|
||||
{ value: mockTab2 }
|
||||
];
|
||||
|
||||
cut.updateDragAndDropState();
|
||||
|
||||
expect(mockTab1.updateDragAndDropState).toHaveBeenCalledTimes(1);
|
||||
expect(mockTab2.updateDragAndDropState).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -864,4 +864,34 @@ describe('tabsContainer', () => {
|
||||
cut.closePanel(panel2);
|
||||
expect(cut.element.classList.contains('dv-single-tab')).toBeFalsy();
|
||||
});
|
||||
|
||||
describe('updateDragAndDropState', () => {
|
||||
test('that updateDragAndDropState calls updateDragAndDropState on tabs and voidContainer', () => {
|
||||
const accessor = fromPartial<DockviewComponent>({
|
||||
onDidAddPanel: jest.fn(),
|
||||
onDidRemovePanel: jest.fn(),
|
||||
options: {},
|
||||
onDidOptionsChange: jest.fn(),
|
||||
});
|
||||
|
||||
const groupPanel = fromPartial<DockviewGroupPanel>({
|
||||
id: 'testgroupid',
|
||||
model: fromPartial<DockviewGroupPanelModel>({}),
|
||||
});
|
||||
|
||||
const cut = new TabsContainer(accessor, groupPanel);
|
||||
|
||||
// Mock the tabs and voidContainer to verify methods are called
|
||||
const mockTabs = { updateDragAndDropState: jest.fn() };
|
||||
const mockVoidContainer = { updateDragAndDropState: jest.fn() };
|
||||
|
||||
(cut as any).tabs = mockTabs;
|
||||
(cut as any).voidContainer = mockVoidContainer;
|
||||
|
||||
cut.updateDragAndDropState();
|
||||
|
||||
expect(mockTabs.updateDragAndDropState).toHaveBeenCalledTimes(1);
|
||||
expect(mockVoidContainer.updateDragAndDropState).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -8,6 +8,7 @@ describe('voidContainer', () => {
|
||||
test('that `pointerDown` triggers activation', () => {
|
||||
const accessor = fromPartial<DockviewComponent>({
|
||||
doSetGroupActive: jest.fn(),
|
||||
options: {}
|
||||
});
|
||||
const group = fromPartial<DockviewGroupPanel>({});
|
||||
const cut = new VoidContainer(accessor, group);
|
||||
@ -17,4 +18,57 @@ describe('voidContainer', () => {
|
||||
fireEvent.pointerDown(cut.element);
|
||||
expect(accessor.doSetGroupActive).toHaveBeenCalledWith(group);
|
||||
});
|
||||
|
||||
describe('disableDnd option', () => {
|
||||
test('that void container is draggable by default (disableDnd not set)', () => {
|
||||
const accessor = fromPartial<DockviewComponent>({
|
||||
options: {}
|
||||
});
|
||||
const group = fromPartial<DockviewGroupPanel>({});
|
||||
const cut = new VoidContainer(accessor, group);
|
||||
|
||||
expect(cut.element.draggable).toBe(true);
|
||||
});
|
||||
|
||||
test('that void container is draggable when disableDnd is false', () => {
|
||||
const accessor = fromPartial<DockviewComponent>({
|
||||
options: { disableDnd: false }
|
||||
});
|
||||
const group = fromPartial<DockviewGroupPanel>({});
|
||||
const cut = new VoidContainer(accessor, group);
|
||||
|
||||
expect(cut.element.draggable).toBe(true);
|
||||
});
|
||||
|
||||
test('that void container is not draggable when disableDnd is true', () => {
|
||||
const accessor = fromPartial<DockviewComponent>({
|
||||
options: { disableDnd: true }
|
||||
});
|
||||
const group = fromPartial<DockviewGroupPanel>({});
|
||||
const cut = new VoidContainer(accessor, group);
|
||||
|
||||
expect(cut.element.draggable).toBe(false);
|
||||
});
|
||||
|
||||
test('that updateDragAndDropState updates draggable attribute based on disableDnd option', () => {
|
||||
const options = { disableDnd: false };
|
||||
const accessor = fromPartial<DockviewComponent>({
|
||||
options
|
||||
});
|
||||
const group = fromPartial<DockviewGroupPanel>({});
|
||||
const cut = new VoidContainer(accessor, group);
|
||||
|
||||
expect(cut.element.draggable).toBe(true);
|
||||
|
||||
// Simulate option change
|
||||
options.disableDnd = true;
|
||||
cut.updateDragAndDropState();
|
||||
expect(cut.element.draggable).toBe(false);
|
||||
|
||||
// Change back
|
||||
options.disableDnd = false;
|
||||
cut.updateDragAndDropState();
|
||||
expect(cut.element.draggable).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -144,6 +144,102 @@ describe('dockviewComponent', () => {
|
||||
);
|
||||
});
|
||||
|
||||
describe('disableDnd option integration', () => {
|
||||
test('that updateOptions with disableDnd updates all tabs and void containers', () => {
|
||||
dockview = new DockviewComponent(container, {
|
||||
createComponent(options) {
|
||||
switch (options.name) {
|
||||
case 'default':
|
||||
return new PanelContentPartTest(
|
||||
options.id,
|
||||
options.name
|
||||
);
|
||||
default:
|
||||
throw new Error(`unsupported`);
|
||||
}
|
||||
},
|
||||
disableDnd: false,
|
||||
});
|
||||
|
||||
// Add some panels to create tabs
|
||||
const panel1 = dockview.addPanel({
|
||||
id: 'panel1',
|
||||
component: 'default',
|
||||
});
|
||||
const panel2 = dockview.addPanel({
|
||||
id: 'panel2',
|
||||
component: 'default',
|
||||
});
|
||||
|
||||
// Get all tab elements and void containers
|
||||
const tabElements = Array.from(dockview.element.querySelectorAll('.dv-tab')) as HTMLElement[];
|
||||
const voidContainers = Array.from(dockview.element.querySelectorAll('.dv-void-container')) as HTMLElement[];
|
||||
|
||||
// Initially tabs should be draggable (disableDnd: false)
|
||||
tabElements.forEach(tab => {
|
||||
expect(tab.draggable).toBe(true);
|
||||
});
|
||||
voidContainers.forEach(container => {
|
||||
expect(container.draggable).toBe(true);
|
||||
});
|
||||
|
||||
// Update options to disable DnD
|
||||
dockview.updateOptions({ disableDnd: true });
|
||||
|
||||
// Now tabs should not be draggable
|
||||
tabElements.forEach(tab => {
|
||||
expect(tab.draggable).toBe(false);
|
||||
});
|
||||
voidContainers.forEach(container => {
|
||||
expect(container.draggable).toBe(false);
|
||||
});
|
||||
|
||||
// Update options to enable DnD again
|
||||
dockview.updateOptions({ disableDnd: false });
|
||||
|
||||
// Tabs should be draggable again
|
||||
tabElements.forEach(tab => {
|
||||
expect(tab.draggable).toBe(true);
|
||||
});
|
||||
voidContainers.forEach(container => {
|
||||
expect(container.draggable).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
test('that new tabs respect current disableDnd option when added after option change', () => {
|
||||
dockview = new DockviewComponent(container, {
|
||||
createComponent(options) {
|
||||
switch (options.name) {
|
||||
case 'default':
|
||||
return new PanelContentPartTest(
|
||||
options.id,
|
||||
options.name
|
||||
);
|
||||
default:
|
||||
throw new Error(`unsupported`);
|
||||
}
|
||||
},
|
||||
disableDnd: false,
|
||||
});
|
||||
|
||||
// Set disableDnd to true
|
||||
dockview.updateOptions({ disableDnd: true });
|
||||
|
||||
// Add a panel after the option change
|
||||
const panel = dockview.addPanel({
|
||||
id: 'panel1',
|
||||
component: 'default',
|
||||
});
|
||||
|
||||
// New tab should not be draggable
|
||||
const tabElement = dockview.element.querySelector('.dv-tab') as HTMLElement;
|
||||
const voidContainer = dockview.element.querySelector('.dv-void-container') as HTMLElement;
|
||||
|
||||
expect(tabElement.draggable).toBe(false);
|
||||
expect(voidContainer.draggable).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('memory leakage', () => {
|
||||
beforeEach(() => {
|
||||
window.open = () => setupMockWindow();
|
||||
|
Loading…
x
Reference in New Issue
Block a user