mirror of
https://github.com/mathuo/dockview
synced 2025-05-02 17:48:25 +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', () => {
|
||||
test('mutable disposable', () => {
|
||||
@ -23,4 +23,29 @@ describe('lifecycle', () => {
|
||||
|
||||
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 {
|
||||
constructor() {
|
||||
//
|
||||
}
|
||||
constructor() {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { addDisposableListener, Emitter } from '../events';
|
||||
import { CompositeDisposable, IDisposable } from '../lifecycle';
|
||||
import { LocalSelectionTransfer } from './dataTransfer';
|
||||
import { addDisposableListener } from '../events';
|
||||
import { CompositeDisposable } from '../lifecycle';
|
||||
|
||||
export interface IDragAndDropObserverCallbacks {
|
||||
onDragEnter: (e: DragEvent) => void;
|
||||
@ -85,97 +84,3 @@ export interface ICompositeDragAndDropObserverCallbacks {
|
||||
onDragStart?: (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[]) {
|
||||
args?.forEach((arg) => this.disposables.push(arg));
|
||||
args.forEach((arg) => this.disposables.push(arg));
|
||||
}
|
||||
|
||||
public dispose() {
|
||||
|
Loading…
Reference in New Issue
Block a user