mirror of
https://github.com/mathuo/dockview
synced 2025-09-12 12:18:10 +00:00
Merge pull request #24 from mathuo/23-increase-test-coverage
chore: increase test coverage and delete unused code
This commit is contained in:
commit
ff88de0395
@ -0,0 +1,87 @@
|
|||||||
|
import { fireEvent } from '@testing-library/dom';
|
||||||
|
import { DragHandler } from '../../dnd/abstractDragHandler';
|
||||||
|
import { IDisposable } from '../../lifecycle';
|
||||||
|
|
||||||
|
describe('abstractDragHandler', () => {
|
||||||
|
test('that className dragged is added to element after dragstart event', () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
|
||||||
|
const element = document.createElement('div');
|
||||||
|
|
||||||
|
const handler = new (class TestClass extends DragHandler {
|
||||||
|
constructor(el: HTMLElement) {
|
||||||
|
super(el);
|
||||||
|
}
|
||||||
|
|
||||||
|
getData(): IDisposable {
|
||||||
|
return {
|
||||||
|
dispose: () => {
|
||||||
|
// /
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
dispose(): void {
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
})(element);
|
||||||
|
|
||||||
|
expect(element.classList.contains('dragged')).toBeFalsy();
|
||||||
|
|
||||||
|
fireEvent.dragStart(element);
|
||||||
|
expect(element.classList.contains('dragged')).toBeTruthy();
|
||||||
|
|
||||||
|
jest.runAllTimers();
|
||||||
|
expect(element.classList.contains('dragged')).toBeFalsy();
|
||||||
|
|
||||||
|
handler.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('that iframes and webviews have pointerEvents=none set whilst drag action is in process', () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
|
||||||
|
const element = document.createElement('div');
|
||||||
|
const iframe = document.createElement('iframe');
|
||||||
|
const webview = document.createElement('webview');
|
||||||
|
const span = document.createElement('span');
|
||||||
|
|
||||||
|
document.body.appendChild(element);
|
||||||
|
document.body.appendChild(iframe);
|
||||||
|
document.body.appendChild(webview);
|
||||||
|
document.body.appendChild(span);
|
||||||
|
|
||||||
|
const handler = new (class TestClass extends DragHandler {
|
||||||
|
constructor(el: HTMLElement) {
|
||||||
|
super(el);
|
||||||
|
}
|
||||||
|
|
||||||
|
getData(): IDisposable {
|
||||||
|
return {
|
||||||
|
dispose: () => {
|
||||||
|
// /
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
dispose(): void {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
})(element);
|
||||||
|
|
||||||
|
expect(iframe.style.pointerEvents).toBeFalsy();
|
||||||
|
expect(webview.style.pointerEvents).toBeFalsy();
|
||||||
|
expect(span.style.pointerEvents).toBeFalsy();
|
||||||
|
|
||||||
|
fireEvent.dragStart(element);
|
||||||
|
expect(iframe.style.pointerEvents).toBe('none');
|
||||||
|
expect(webview.style.pointerEvents).toBe('none');
|
||||||
|
expect(span.style.pointerEvents).toBeFalsy();
|
||||||
|
|
||||||
|
fireEvent.dragEnd(element);
|
||||||
|
expect(iframe.style.pointerEvents).toBe('auto');
|
||||||
|
expect(webview.style.pointerEvents).toBe('auto');
|
||||||
|
expect(span.style.pointerEvents).toBeFalsy();
|
||||||
|
|
||||||
|
handler.dispose();
|
||||||
|
});
|
||||||
|
});
|
101
packages/dockview/src/__tests__/dnd/dataTransfer.spec.ts
Normal file
101
packages/dockview/src/__tests__/dnd/dataTransfer.spec.ts
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
import {
|
||||||
|
getPaneData,
|
||||||
|
getPanelData,
|
||||||
|
LocalSelectionTransfer,
|
||||||
|
PanelTransfer,
|
||||||
|
PaneTransfer,
|
||||||
|
} from '../../dnd/dataTransfer';
|
||||||
|
|
||||||
|
describe('dataTransfer', () => {
|
||||||
|
describe('getPanelData', () => {
|
||||||
|
test('should be undefined when there is no local transfer object', () => {
|
||||||
|
expect(getPanelData()).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should be undefined when there is a local transfer object that is not a PanelTransfer', () => {
|
||||||
|
LocalSelectionTransfer.getInstance<PaneTransfer>().setData(
|
||||||
|
[new PaneTransfer('viewId', 'groupId')],
|
||||||
|
PaneTransfer.prototype
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(getPanelData()).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should retrieve the PanelTransfer object when transfer is active', () => {
|
||||||
|
const transferObject = new PanelTransfer(
|
||||||
|
'viewId',
|
||||||
|
'groupId',
|
||||||
|
'panelId'
|
||||||
|
);
|
||||||
|
LocalSelectionTransfer.getInstance<PanelTransfer>().setData(
|
||||||
|
[transferObject],
|
||||||
|
PanelTransfer.prototype
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(getPanelData()).toBe(transferObject);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should retrieve the PanelTransfer when a new transfer overrides an existing one', () => {
|
||||||
|
LocalSelectionTransfer.getInstance<PaneTransfer>().setData(
|
||||||
|
[new PaneTransfer('viewId', 'groupId')],
|
||||||
|
PaneTransfer.prototype
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(getPanelData()).toBeUndefined();
|
||||||
|
|
||||||
|
const transferObject = new PanelTransfer(
|
||||||
|
'viewId',
|
||||||
|
'groupId',
|
||||||
|
'panelId'
|
||||||
|
);
|
||||||
|
LocalSelectionTransfer.getInstance<PanelTransfer>().setData(
|
||||||
|
[transferObject],
|
||||||
|
PanelTransfer.prototype
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(getPanelData()).toBe(transferObject);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getPaneData', () => {
|
||||||
|
test('should be undefined when there is no local transfer object', () => {
|
||||||
|
expect(getPaneData()).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should be undefined when there is a local transfer object that is not a PaneTransfer', () => {
|
||||||
|
LocalSelectionTransfer.getInstance<PanelTransfer>().setData(
|
||||||
|
[new PanelTransfer('viewId', 'groupId', 'panelId')],
|
||||||
|
PanelTransfer.prototype
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(getPaneData()).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should retrieve the PaneTransfer object when transfer is active', () => {
|
||||||
|
const transferObject = new PaneTransfer('viewId', 'groupId');
|
||||||
|
LocalSelectionTransfer.getInstance<PaneTransfer>().setData(
|
||||||
|
[transferObject],
|
||||||
|
PaneTransfer.prototype
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(getPaneData()).toBe(transferObject);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should retrieve the PanelTransfer when a new transfer overrides an existing one', () => {
|
||||||
|
LocalSelectionTransfer.getInstance<PanelTransfer>().setData(
|
||||||
|
[new PanelTransfer('viewId', 'groupId', 'panelId')],
|
||||||
|
PanelTransfer.prototype
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(getPaneData()).toBeUndefined();
|
||||||
|
|
||||||
|
const transferObject = new PaneTransfer('viewId', 'groupId');
|
||||||
|
LocalSelectionTransfer.getInstance<PaneTransfer>().setData(
|
||||||
|
[transferObject],
|
||||||
|
PaneTransfer.prototype
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(getPaneData()).toBe(transferObject);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -1,4 +1,4 @@
|
|||||||
import { MutableDisposable } from '../lifecycle';
|
import { CompositeDisposable, MutableDisposable } from '../lifecycle';
|
||||||
|
|
||||||
describe('lifecycle', () => {
|
describe('lifecycle', () => {
|
||||||
test('mutable disposable', () => {
|
test('mutable disposable', () => {
|
||||||
@ -23,4 +23,29 @@ describe('lifecycle', () => {
|
|||||||
|
|
||||||
mutableDisposable.dispose();
|
mutableDisposable.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('composite disposable', () => {
|
||||||
|
const d1 = {
|
||||||
|
dispose: jest.fn(),
|
||||||
|
};
|
||||||
|
const d2 = {
|
||||||
|
dispose: jest.fn(),
|
||||||
|
};
|
||||||
|
const d3 = {
|
||||||
|
dispose: jest.fn(),
|
||||||
|
};
|
||||||
|
const d4 = {
|
||||||
|
dispose: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const cut = new CompositeDisposable(d1, d2);
|
||||||
|
cut.addDisposables(d3, d4);
|
||||||
|
|
||||||
|
cut.dispose();
|
||||||
|
|
||||||
|
expect(d1.dispose).toHaveBeenCalledTimes(1);
|
||||||
|
expect(d2.dispose).toHaveBeenCalledTimes(1);
|
||||||
|
expect(d3.dispose).toHaveBeenCalledTimes(1);
|
||||||
|
expect(d4.dispose).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
import { PanelOptions } from '../dockview/options';
|
|
||||||
import { tryParseJSON } from '../json';
|
|
||||||
|
|
||||||
class TransferObject {
|
class TransferObject {
|
||||||
constructor() {
|
constructor() {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PanelTransfer extends TransferObject {
|
export class PanelTransfer extends TransferObject {
|
||||||
@ -26,65 +23,6 @@ export class PaneTransfer extends TransferObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const DATA_KEY = 'splitview/transfer';
|
|
||||||
|
|
||||||
export const isPanelTransferEvent = (event: DragEvent) => {
|
|
||||||
if (!event.dataTransfer) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return event.dataTransfer.types.includes(DATA_KEY);
|
|
||||||
};
|
|
||||||
|
|
||||||
export enum DragType {
|
|
||||||
DOCKVIEW_TAB = 'dockview_tab',
|
|
||||||
EXTERNAL = 'external_group_drag',
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DragItem {
|
|
||||||
itemId: string;
|
|
||||||
groupId: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ExternalDragItem extends PanelOptions {}
|
|
||||||
|
|
||||||
export type DataObject = DragItem | ExternalDragItem;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine whether this data belong to that of an event that was started by
|
|
||||||
* dragging a tab component
|
|
||||||
*/
|
|
||||||
export const isTabDragEvent = (data: any): data is DragItem => {
|
|
||||||
return data.type === DragType.DOCKVIEW_TAB;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine whether this data belong to that of an event that was started by
|
|
||||||
* a custom drag-enable component
|
|
||||||
*/
|
|
||||||
export const isCustomDragEvent = (data: any): data is ExternalDragItem => {
|
|
||||||
return data.type === DragType.EXTERNAL;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const extractData = (event: DragEvent): DataObject | null => {
|
|
||||||
if (!event.dataTransfer) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = tryParseJSON(event.dataTransfer.getData(DATA_KEY));
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
console.warn(`[dragEvent] ${DATA_KEY} data is missing`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof data.type !== 'string') {
|
|
||||||
console.warn(`[dragEvent] invalid type ${data.type}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A singleton to store transfer data during drag & drop operations that are only valid within the application.
|
* A singleton to store transfer data during drag & drop operations that are only valid within the application.
|
||||||
*/
|
*/
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { addDisposableListener, Emitter } from '../events';
|
import { addDisposableListener } from '../events';
|
||||||
import { CompositeDisposable, IDisposable } from '../lifecycle';
|
import { CompositeDisposable } from '../lifecycle';
|
||||||
import { LocalSelectionTransfer } from './dataTransfer';
|
|
||||||
|
|
||||||
export interface IDragAndDropObserverCallbacks {
|
export interface IDragAndDropObserverCallbacks {
|
||||||
onDragEnter: (e: DragEvent) => void;
|
onDragEnter: (e: DragEvent) => void;
|
||||||
@ -85,97 +84,3 @@ export interface ICompositeDragAndDropObserverCallbacks {
|
|||||||
onDragStart?: (e: IDraggedCompositeData) => void;
|
onDragStart?: (e: IDraggedCompositeData) => void;
|
||||||
onDragEnd?: (e: IDraggedCompositeData) => void;
|
onDragEnd?: (e: IDraggedCompositeData) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
class DockviewIdentifier<T = {}> {
|
|
||||||
constructor(private readonly data: T) {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class DragAndDrop extends CompositeDisposable {
|
|
||||||
private _onDragStart = new Emitter<any>();
|
|
||||||
private _onDragEnd = new Emitter<any>();
|
|
||||||
private static _instance: DragAndDrop | undefined;
|
|
||||||
static get INSTANCE(): DragAndDrop {
|
|
||||||
if (!DragAndDrop._instance) {
|
|
||||||
DragAndDrop._instance = new DragAndDrop();
|
|
||||||
}
|
|
||||||
return DragAndDrop._instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private transferData =
|
|
||||||
LocalSelectionTransfer.getInstance<DockviewIdentifier>();
|
|
||||||
|
|
||||||
private constructor() {
|
|
||||||
super();
|
|
||||||
|
|
||||||
this.addDisposables(this._onDragStart, this._onDragEnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
registerTarget(
|
|
||||||
element: HTMLElement,
|
|
||||||
callbacks: ICompositeDragAndDropObserverCallbacks
|
|
||||||
): IDisposable {
|
|
||||||
const disposables = new CompositeDisposable();
|
|
||||||
|
|
||||||
disposables.addDisposables(
|
|
||||||
new DragAndDropObserver(element, {
|
|
||||||
onDragEnd: (e) => {
|
|
||||||
// no-op
|
|
||||||
},
|
|
||||||
onDragEnter: (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
},
|
|
||||||
onDragLeave: (e) => {
|
|
||||||
//
|
|
||||||
},
|
|
||||||
onDrop: (e) => {
|
|
||||||
//
|
|
||||||
},
|
|
||||||
onDragOver: (e) => {
|
|
||||||
//
|
|
||||||
},
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
return disposables;
|
|
||||||
}
|
|
||||||
|
|
||||||
registerDraggable(
|
|
||||||
element: HTMLElement,
|
|
||||||
draggedItemProvider: () => { type: string; id: string },
|
|
||||||
callbacks: ICompositeDragAndDropObserverCallbacks
|
|
||||||
): IDisposable {
|
|
||||||
element.draggable = true;
|
|
||||||
|
|
||||||
const disposables = new CompositeDisposable();
|
|
||||||
|
|
||||||
disposables.addDisposables(
|
|
||||||
addDisposableListener(element, 'dragstart', (e) => {
|
|
||||||
this._onDragStart.fire({ event: e });
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
disposables.addDisposables(
|
|
||||||
new DragAndDropObserver(element, {
|
|
||||||
onDragEnd: (e) => {
|
|
||||||
// no-op
|
|
||||||
},
|
|
||||||
onDragEnter: (e) => {
|
|
||||||
//
|
|
||||||
},
|
|
||||||
onDragLeave: (e) => {
|
|
||||||
//
|
|
||||||
},
|
|
||||||
onDrop: (e) => {
|
|
||||||
//
|
|
||||||
},
|
|
||||||
onDragOver: (e) => {
|
|
||||||
//
|
|
||||||
},
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
return disposables;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
export function tryParseJSON(
|
|
||||||
text: string,
|
|
||||||
reviver?: (this: any, key: string, value: any) => any
|
|
||||||
): any | undefined;
|
|
||||||
export function tryParseJSON<T>(
|
|
||||||
text: string,
|
|
||||||
reviver?: (this: any, key: string, value: any) => any
|
|
||||||
): T | undefined {
|
|
||||||
try {
|
|
||||||
return JSON.parse(text, reviver) as T;
|
|
||||||
} catch (err) {
|
|
||||||
console.warn('failed to parse JSON');
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
@ -27,7 +27,7 @@ export class CompositeDisposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public addDisposables(...args: IDisposable[]) {
|
public addDisposables(...args: IDisposable[]) {
|
||||||
args?.forEach((arg) => this.disposables.push(arg));
|
args.forEach((arg) => this.disposables.push(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
public dispose() {
|
public dispose() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user