diff --git a/packages/dockview-core/src/__tests__/dnd/ghost.spec.ts b/packages/dockview-core/src/__tests__/dnd/ghost.spec.ts new file mode 100644 index 000000000..32d978b2e --- /dev/null +++ b/packages/dockview-core/src/__tests__/dnd/ghost.spec.ts @@ -0,0 +1,31 @@ +import { addGhostImage } from '../../dnd/ghost'; + +describe('ghost', () => { + beforeEach(() => { + jest.useFakeTimers(); + jest.clearAllTimers(); + }); + + test('that a custom class is added, the element is added to the document and all is removed afterwards', () => { + const dataTransferMock = jest.fn, []>(() => { + return { + setDragImage: jest.fn(), + }; + }); + + const element = document.createElement('div'); + const dataTransfer = new dataTransferMock(); + + addGhostImage(dataTransfer, element); + + expect(element.className).toBe('dv-dragged'); + expect(element.parentElement).toBe(document.body); + expect(dataTransfer.setDragImage).toBeCalledTimes(1); + expect(dataTransfer.setDragImage).toBeCalledWith(element, 0, 0); + + jest.runAllTimers(); + + expect(element.className).toBe(''); + expect(element.parentElement).toBe(null); + }); +}); diff --git a/packages/dockview-core/src/dnd/ghost.ts b/packages/dockview-core/src/dnd/ghost.ts index 04262544d..2ff9c569f 100644 --- a/packages/dockview-core/src/dnd/ghost.ts +++ b/packages/dockview-core/src/dnd/ghost.ts @@ -1,4 +1,4 @@ -import { addClasses } from '../dom'; +import { addClasses, removeClasses } from '../dom'; export function addGhostImage( dataTransfer: DataTransfer, @@ -11,6 +11,7 @@ export function addGhostImage( dataTransfer.setDragImage(ghostElement, 0, 0); setTimeout(() => { + removeClasses(ghostElement, 'dv-dragged'); ghostElement.remove(); }, 0); } diff --git a/packages/dockview/src/__tests__/dockview/dockview.spec.tsx b/packages/dockview/src/__tests__/dockview/dockview.spec.tsx new file mode 100644 index 000000000..0a9887e7b --- /dev/null +++ b/packages/dockview/src/__tests__/dockview/dockview.spec.tsx @@ -0,0 +1,52 @@ +import * as React from 'react'; +import { render } from '@testing-library/react'; +import { DockviewApi } from 'dockview-core'; +import { + IDockviewPanelProps, + DockviewReact, + DockviewReadyEvent, +} from '../../dockview/dockview'; +import { PanelCollection } from '../../types'; +import { setMockRefElement } from '../__test_utils__/utils'; + +describe('gridview react', () => { + let components: PanelCollection; + + beforeEach(() => { + components = { + default: (props: IDockviewPanelProps) => { + return
hello world
; + }, + }; + }); + + test('default', () => { + let api: DockviewApi | undefined; + + const onReady = (event: DockviewReadyEvent) => { + api = event.api; + }; + + render(); + + expect(api).toBeTruthy(); + }); + + test('is sized to container', () => { + setMockRefElement({ + clientHeight: 450, + clientWidth: 650, + appendChild: jest.fn(), + }); + let api: DockviewApi | undefined; + + const onReady = (event: DockviewReadyEvent) => { + api = event.api; + }; + + render(); + + expect(api.width).toBe(650); + expect(api.height).toBe(450); + }); +}); diff --git a/packages/dockview/src/__tests__/dockview/groupControlsRenderer.spec.ts b/packages/dockview/src/__tests__/dockview/groupControlsRenderer.spec.ts new file mode 100644 index 000000000..dc645d007 --- /dev/null +++ b/packages/dockview/src/__tests__/dockview/groupControlsRenderer.spec.ts @@ -0,0 +1,58 @@ +import { + DockviewGroupPanel, + DockviewGroupPanelApi, + DockviewGroupPanelModel, +} from 'dockview-core'; +import { ReactGroupControlsRendererPart } from '../../dockview/groupControlsRenderer'; + +describe('groupControlsRenderer', () => { + test('#1', () => { + const groupviewMock = jest.fn, []>( + () => { + return { + onDidAddPanel: jest.fn(), + onDidRemovePanel: jest.fn(), + onDidActivePanelChange: jest.fn(), + }; + } + ); + + const groupview = new groupviewMock() as DockviewGroupPanelModel; + + const groupPanelMock = jest.fn, []>(() => { + return { + api: {} as DockviewGroupPanelApi as any, + model: groupview, + }; + }); + + const groupPanel = new groupPanelMock() as DockviewGroupPanel; + + const cut = new ReactGroupControlsRendererPart( + jest.fn(), + { + addPortal: jest.fn(), + }, + groupPanel + ); + + expect(cut.element.childNodes.length).toBe(0); + expect(cut.element.className).toBe('dockview-react-part'); + expect(cut.part).toBeUndefined(); + + cut.init({ + containerApi: jest.fn(), + api: { + onDidActiveChange: jest.fn(), + }, + }); + + const update = jest.fn(); + + jest.spyOn(cut.part!, 'update').mockImplementation(update); + + cut.update({ params: { valueA: 'A' } }); + + expect(update).toBeCalledWith({ valueA: 'A' }); + }); +}); diff --git a/packages/dockview/src/__tests__/gridview/gridview.spec.tsx b/packages/dockview/src/__tests__/gridview/gridview.spec.tsx new file mode 100644 index 000000000..ac4c5c24e --- /dev/null +++ b/packages/dockview/src/__tests__/gridview/gridview.spec.tsx @@ -0,0 +1,64 @@ +import * as React from 'react'; +import { render } from '@testing-library/react'; +import { GridviewApi, Orientation } from 'dockview-core'; +import { + IGridviewPanelProps, + GridviewReact, + GridviewReadyEvent, +} from '../../gridview/gridview'; +import { PanelCollection } from '../../types'; +import { setMockRefElement } from '../__test_utils__/utils'; + +describe('gridview react', () => { + let components: PanelCollection; + + beforeEach(() => { + components = { + default: (props: IGridviewPanelProps) => { + return
hello world
; + }, + }; + }); + + test('default', () => { + let api: GridviewApi | undefined; + + const onReady = (event: GridviewReadyEvent) => { + api = event.api; + }; + + render( + + ); + + expect(api).toBeTruthy(); + }); + + test('is sized to container', () => { + setMockRefElement({ + clientHeight: 450, + clientWidth: 650, + appendChild: jest.fn(), + }); + let api: GridviewApi | undefined; + + const onReady = (event: GridviewReadyEvent) => { + api = event.api; + }; + + render( + + ); + + expect(api.width).toBe(650); + expect(api.height).toBe(450); + }); +}); diff --git a/packages/dockview/src/__tests__/paneview/paneview.spec.tsx b/packages/dockview/src/__tests__/paneview/paneview.spec.tsx new file mode 100644 index 000000000..0a69965f0 --- /dev/null +++ b/packages/dockview/src/__tests__/paneview/paneview.spec.tsx @@ -0,0 +1,52 @@ +import * as React from 'react'; +import { render } from '@testing-library/react'; +import { PaneviewApi } from 'dockview-core'; +import { + IPaneviewPanelProps, + PaneviewReact, + PaneviewReadyEvent, +} from '../../paneview/paneview'; +import { PanelCollection } from '../../types'; +import { setMockRefElement } from '../__test_utils__/utils'; + +describe('gridview react', () => { + let components: PanelCollection; + + beforeEach(() => { + components = { + default: (props: IPaneviewPanelProps) => { + return
hello world
; + }, + }; + }); + + test('default', () => { + let api: PaneviewApi | undefined; + + const onReady = (event: PaneviewReadyEvent) => { + api = event.api; + }; + + render(); + + expect(api).toBeTruthy(); + }); + + test('is sized to container', () => { + setMockRefElement({ + clientHeight: 450, + clientWidth: 650, + appendChild: jest.fn(), + }); + let api: PaneviewApi | undefined; + + const onReady = (event: PaneviewReadyEvent) => { + api = event.api; + }; + + render(); + + expect(api.width).toBe(650); + expect(api.height).toBe(450); + }); +}); diff --git a/packages/dockview/src/__tests__/react.spec.tsx b/packages/dockview/src/__tests__/react.spec.tsx new file mode 100644 index 000000000..2abf76845 --- /dev/null +++ b/packages/dockview/src/__tests__/react.spec.tsx @@ -0,0 +1,90 @@ +import { ReactPart } from '../react'; +import * as React from 'react'; +import { render, screen, act } from '@testing-library/react'; + +interface TestInterface { + valueA: string; + valueB: number; +} + +describe('react', () => { + describe('ReactPart', () => { + test('update underlying component via ReactPart class', () => { + let api: ReactPart; + + const onReady = (_api: ReactPart) => { + api = _api; + }; + + render(); + + expect(api).toBeTruthy(); + + expect(screen.getByTestId('valueA').textContent).toBe('stringA'); + expect(screen.getByTestId('valueB').textContent).toBe('42'); + + act(() => { + api.update({ valueB: '32' }); + }); + + expect(screen.getByTestId('valueA').textContent).toBe('stringA'); + expect(screen.getByTestId('valueB').textContent).toBe('32'); + + act(() => { + api.update({ valueA: 'anotherStringA', valueB: '22' }); + }); + + expect(screen.getByTestId('valueA').textContent).toBe( + 'anotherStringA' + ); + expect(screen.getByTestId('valueB').textContent).toBe('22'); + }); + }); +}); + +const Component = (props: TestInterface) => { + return ( +
+
{props.valueA}
+
{props.valueB}
+
+ ); +}; + +const TestWrapper = (props: { + component: React.FunctionComponent; + onReady: (api: ReactPart) => void; +}) => { + const [portal, setPortal] = React.useState([]); + const ref = React.useRef(null); + + React.useEffect(() => { + const cut = new ReactPart( + ref.current, + { + addPortal: (portal: React.ReactPortal) => { + setPortal((_) => [..._, portal]); + + return { + dispose: () => { + setPortal((_) => _.filter((_) => _ !== portal)); + }, + }; + }, + }, + props.component, + { + valueA: 'stringA', + valueB: 42, + } + ); + + props.onReady(cut); + + return () => { + cut.dispose(); + }; + }, []); + + return
{portal}
; +}; diff --git a/packages/dockview/src/__tests__/splitview/splitview.spec.tsx b/packages/dockview/src/__tests__/splitview/splitview.spec.tsx new file mode 100644 index 000000000..e0da9dd72 --- /dev/null +++ b/packages/dockview/src/__tests__/splitview/splitview.spec.tsx @@ -0,0 +1,64 @@ +import * as React from 'react'; +import { render } from '@testing-library/react'; +import { SplitviewApi, Orientation } from 'dockview-core'; +import { + ISplitviewPanelProps, + SplitviewReact, + SplitviewReadyEvent, +} from '../../splitview/splitview'; +import { PanelCollection } from '../../types'; +import { setMockRefElement } from '../__test_utils__/utils'; + +describe('splitview react', () => { + let components: PanelCollection; + + beforeEach(() => { + components = { + default: (props: ISplitviewPanelProps) => { + return
hello world
; + }, + }; + }); + + test('default', () => { + let api: SplitviewApi | undefined; + + const onReady = (event: SplitviewReadyEvent) => { + api = event.api; + }; + + render( + + ); + + expect(api).toBeTruthy(); + }); + + test('is sized to container', () => { + setMockRefElement({ + clientHeight: 450, + clientWidth: 650, + appendChild: jest.fn(), + }); + let api: SplitviewApi | undefined; + + const onReady = (event: SplitviewReadyEvent) => { + api = event.api; + }; + + render( + + ); + + expect(api.width).toBe(650); + expect(api.height).toBe(450); + }); +});