Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(useDrop): add some tests #1660

Merged
merged 1 commit into from
Jun 12, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
295 changes: 176 additions & 119 deletions packages/hooks/src/useDrop/__tests__/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,124 +1,181 @@
// import { renderHook } from '@testing-library/react-hooks';
import { useDrag, useDrop } from '../../index';

// const mockUriEvent: any = (text: string) => ({
// dataTransfer: {
// getData: () => text,
// setData: () => {},
// },
// preventDefault: () => {},
// persist: () => {},
// });

// const mockDomEvent: any = (content: any) => ({
// dataTransfer: {
// getData: () => JSON.stringify(content),
// setData: () => {},
// },
// preventDefault: () => {},
// persist: () => {},
// });

// const mockTextEvent: any = (content: string) => ({
// dataTransfer: {
// getData: () => null,
// setData: () => {},
// items: [
// {
// getAsString: (cb) => {
// cb(content);
// },
// },
// ],
// },
// preventDefault: () => {},
// persist: () => {},
// });

// const mockFileEvent: any = (content: string[]) => ({
// dataTransfer: {
// getData: () => null,
// setData: () => {},
// files: content,
// },
// preventDefault: () => {},
// persist: () => {},
// });

describe('useDrag & useDrop', () => {
import { renderHook } from '@testing-library/react-hooks';
import useDrop, { Options } from '../index';
import type { BasicTarget } from '../../utils/domTarget';

const setup = (target: unknown, options?: Options) =>
renderHook(() => useDrop(target as BasicTarget, options));

const events = {};
const mockTarget = {
addEventListener: jest.fn((event, callback) => {
events[event] = callback;
}),
removeEventListener: jest.fn((event) => {
Reflect.deleteProperty(events, event);
}),
};

const mockEvent = {
dataTransfer: {
getData: (format?: string) => 'mock' as unknown,
get items() {
return [] as unknown[];
},
get files() {
return [] as unknown[];
},
},
clipboardData: {
getData: (format?: string) => 'mock' as unknown,
get items() {
return [] as unknown[];
},
get files() {
return [] as unknown[];
},
},
preventDefault: jest.fn(),
stopPropagation: jest.fn(),
};

describe('useDrop', () => {
it('should be defined', () => {
expect(useDrag).toBeDefined();
expect(useDrop).toBeDefined();
});

// it('callback should be called', () => {
// const startFn = jest.fn();
// const endFn = jest.fn();
// const hook = renderHook(() =>
// useDrag({
// onDragStart: startFn,
// onDragEnd: endFn,
// }),
// );

// const getProps = hook.result.current('');
// getProps.onDragStart(mockDomEvent());
// expect(startFn).toBeCalledTimes(1);
// expect(endFn).toBeCalledTimes(0);
// getProps.onDragEnd(mockDomEvent());
// expect(startFn).toBeCalledTimes(1);
// expect(endFn).toBeCalledTimes(1);
// });

// it('test onUri', async () => {
// let uri = '';
// const hook = renderHook(() =>
// useDrop({
// onUri: (u, e) => {
// uri = u;
// },
// }),
// );
// hook.result.current[0].onDrop(mockUriEvent('https://alipay.com'));
// expect(uri).toEqual('https://alipay.com');
// });

// it('test onDom', async () => {
// let custom: any = null;
// const hook = renderHook(() =>
// useDrop({
// onDom: (data, e) => {
// custom = data;
// },
// }),
// );
// hook.result.current[0].onDrop(mockDomEvent({ id: 1, name: 'umi' }));
// expect(custom).toEqual({ id: 1, name: 'umi' });
// });

// it('test onText', async () => {
// let text: string = '';
// const hook = renderHook(() =>
// useDrop({
// onText: (data, e) => {
// text = data;
// },
// }),
// );
// hook.result.current[0].onDrop(mockTextEvent('text'));
// expect(text).toEqual('text');
// });

// it('test onFile', async () => {
// let files: any[] = [];
// const hook = renderHook(() =>
// useDrop({
// onFiles: (data, e) => {
// files = data;
// },
// }),
// );
// hook.result.current[0].onDrop(mockFileEvent(['file1', 'file2']));
// expect(files.length).toEqual(2);
// });
it(`should not work when target don't support addEventListener method`, () => {
const originAddEventListener = mockTarget.addEventListener;
Object.defineProperty(mockTarget, 'addEventListener', {
value: false,
});
setup(mockTarget);
expect(Object.keys(events)).toHaveLength(0);
Object.defineProperty(mockTarget, 'addEventListener', {
value: originAddEventListener,
});
});

it('should add/remove listener on mount/unmount', () => {
const { unmount } = setup(mockTarget);
const eventNames = ['dragenter', 'dragover', 'dragleave', 'drop', 'paste'];
expect(mockTarget.addEventListener).toBeCalledTimes(eventNames.length);
eventNames.forEach((eventName, i) => {
expect(mockTarget.addEventListener.mock.calls[i][0]).toBe(eventName);
});
unmount();
expect(mockTarget.removeEventListener).toBeCalledTimes(eventNames.length);
eventNames.forEach((eventName, i) => {
expect(mockTarget.addEventListener.mock.calls[i][0]).toBe(eventName);
});
});

it('should call callback', () => {
const onDragEnter = jest.fn();
const onDragOver = jest.fn();
const onDragLeave = jest.fn();
const onDrop = jest.fn();
const onPaste = jest.fn();

setup(mockTarget, {
onDragEnter,
onDragOver,
onDragLeave,
onDrop,
onPaste,
});
const callbacks = [onDragEnter, onDragOver, onDragLeave, onDrop, onPaste];
const eventNames = ['dragenter', 'dragover', 'dragleave', 'drop', 'paste'];
eventNames.forEach((event) => {
events[event](mockEvent);
});
callbacks.forEach((callback) => expect(callback).toBeCalled());
});

it('should call onText on drop', async () => {
jest.spyOn(mockEvent.dataTransfer, 'items', 'get').mockReturnValue([
{
getAsString: (callback) => {
callback('drop text');
},
},
]);

const onText = jest.fn();
setup(mockTarget, {
onText,
});
events['dragenter'](mockEvent);
events['drop'](mockEvent);
expect(onText.mock.calls[0][0]).toBe('drop text');
});

it('should call onFiles on drop', async () => {
const file = new File(['hello'], 'hello.png');
jest.spyOn(mockEvent.dataTransfer, 'files', 'get').mockReturnValue([file]);
const onFiles = jest.fn();
setup(mockTarget, {
onFiles,
});
events['dragenter'](mockEvent);
events['drop'](mockEvent);
expect(onFiles.mock.calls[0][0]).toHaveLength(1);
});

it('should call onUri on drop', async () => {
const url = 'https://alipay.com';
jest.spyOn(mockEvent.dataTransfer, 'getData').mockImplementation((format: string) => {
if (format === 'text/uri-list') return url;
});

const onUri = jest.fn();
setup(mockTarget, {
onUri,
});
events['dragenter'](mockEvent);
events['drop'](mockEvent);
expect(onUri.mock.calls[0][0]).toBe(url);
});

it('should call onDom on drop', async () => {
const data = {
value: 'mock',
};
jest.spyOn(mockEvent.dataTransfer, 'getData').mockImplementation((format: string) => {
if (format === 'custom') return data;
});

const onDom = jest.fn();
setup(mockTarget, {
onDom,
});
events['dragenter'](mockEvent);
events['drop'](mockEvent);
expect(onDom.mock.calls[0][0]).toMatchObject(data);

// catch JSON.parse error
jest.spyOn(mockEvent.dataTransfer, 'getData').mockImplementation((format: string) => {
if (format === 'custom') return {};
});
events['dragenter'](mockEvent);
events['drop'](mockEvent);
expect(onDom.mock.calls[0][0]).toMatchObject({});
});

it('should call onText on paste', async () => {
jest.spyOn(mockEvent.clipboardData, 'items', 'get').mockReturnValue([
{
getAsString: (callback) => {
callback('paste text');
},
},
]);

const onText = jest.fn();
setup(mockTarget, {
onText,
});
events['dragenter'](mockEvent);
events['paste'](mockEvent);
expect(onText.mock.calls[0][0]).toBe('paste text');
});
});