* Refactored drag n drop functionality to a hook and component. * Add the snackbar to the article editor. * Now you can drag and drop images in the post body content. * Cleaning up a few things. * Now post cover images can be dragged and dropped. * Removed unused empty function. * Added @testing-library/preact-hooks so that we can test hooks. * Some renaming, small refactor. * Added tests * Added more tests. * Added more tests. * Added message about dropping only one image in post body. * Added message about dropping only one image for cover image. * put onDrop into it's own meethod. * More tests. * Added some API documentation. * Updated editor help with drag and drop image help. * Changed wording. * Now the alt text for markdown removes the file extension. * Updated help wording. Thanks @rhymes * Now the image markdown adds a new line at the end as we currently do not support inline images.
179 lines
5.2 KiB
JavaScript
179 lines
5.2 KiB
JavaScript
import { h } from 'preact';
|
|
import { render } from '@testing-library/preact';
|
|
import { renderHook, act } from '@testing-library/preact-hooks';
|
|
import { DragAndDropZone, useDragAndDrop } from '@utilities/dragAndDrop';
|
|
|
|
describe('drag and drop for components', () => {
|
|
describe('useDragAndDrop', () => {
|
|
it('should not add drag and drop event listeners when DOM element is null', () => {
|
|
const onDrop = jest.fn();
|
|
const onDragOver = jest.fn();
|
|
const onDragExit = jest.fn();
|
|
|
|
HTMLElement.prototype.addEventListener = jest.fn();
|
|
HTMLDocument.prototype.addEventListener = jest.fn();
|
|
|
|
const { result } = renderHook(() =>
|
|
useDragAndDrop({
|
|
onDrop,
|
|
onDragOver,
|
|
onDragExit,
|
|
}),
|
|
);
|
|
|
|
act(() => {
|
|
result.current.setElement(null);
|
|
});
|
|
|
|
expect(HTMLElement.prototype.addEventListener).not.toHaveBeenCalled();
|
|
expect(HTMLDocument.prototype.addEventListener).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should attach drag and drop events when setElement receives a DOM node', () => {
|
|
const onDrop = jest.fn();
|
|
const onDragOver = jest.fn();
|
|
const onDragExit = jest.fn();
|
|
|
|
HTMLElement.prototype.addEventListener = jest.fn();
|
|
HTMLDocument.prototype.addEventListener = jest.fn();
|
|
|
|
const { result } = renderHook(() =>
|
|
useDragAndDrop({
|
|
onDrop,
|
|
onDragOver,
|
|
onDragExit,
|
|
}),
|
|
);
|
|
|
|
act(() => {
|
|
result.current.setElement(document.createElement('textarea'));
|
|
});
|
|
|
|
expect(HTMLElement.prototype.addEventListener).toHaveBeenCalledTimes(4);
|
|
expect(HTMLDocument.prototype.addEventListener).toHaveBeenCalledTimes(2);
|
|
});
|
|
|
|
it('should remove drag and drop event listeners when the hook is unmounted', () => {
|
|
const onDrop = jest.fn();
|
|
const onDragOver = jest.fn();
|
|
const onDragExit = jest.fn();
|
|
|
|
HTMLElement.prototype.removeEventListener = jest.fn();
|
|
HTMLDocument.prototype.removeEventListener = jest.fn();
|
|
|
|
const { unmount, result } = renderHook(() =>
|
|
useDragAndDrop({
|
|
onDrop,
|
|
onDragOver,
|
|
onDragExit,
|
|
}),
|
|
);
|
|
|
|
act(() => {
|
|
result.current.setElement(document.createElement('textarea'));
|
|
});
|
|
|
|
unmount();
|
|
expect(HTMLDocument.prototype.removeEventListener).toHaveBeenCalledTimes(
|
|
2,
|
|
);
|
|
expect(HTMLElement.prototype.removeEventListener).toHaveBeenCalledTimes(
|
|
4,
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('<DragAndDropZone />', () => {
|
|
it('should attach drag and drop events', async () => {
|
|
const onDrop = jest.fn();
|
|
const onDragOver = jest.fn();
|
|
const onDragExit = jest.fn();
|
|
|
|
HTMLElement.prototype.addEventListener = jest.fn();
|
|
HTMLDocument.prototype.addEventListener = jest.fn();
|
|
|
|
const { rerender } = render(
|
|
<DragAndDropZone
|
|
onDragOver={onDragOver}
|
|
onDragExit={onDragExit}
|
|
onDrop={onDrop}
|
|
>
|
|
<textarea>I'm a text area</textarea>
|
|
</DragAndDropZone>,
|
|
);
|
|
|
|
// Rerendering so that the ref gets set to the DOM node.
|
|
// represented by the Preact element <textarea />
|
|
rerender(
|
|
<DragAndDropZone
|
|
onDragOver={onDragOver}
|
|
onDragExit={onDragExit}
|
|
onDrop={onDrop}
|
|
>
|
|
<textarea>I'm a text area</textarea>
|
|
</DragAndDropZone>,
|
|
);
|
|
|
|
expect(HTMLDocument.prototype.addEventListener).toBeCalledTimes(2);
|
|
expect(HTMLElement.prototype.addEventListener).toHaveBeenCalledTimes(4);
|
|
});
|
|
|
|
it('should not attach drag and drop events', async () => {
|
|
const onDrop = jest.fn();
|
|
const onDragOver = jest.fn();
|
|
const onDragExit = jest.fn();
|
|
|
|
HTMLElement.prototype.removeEventListener = jest.fn();
|
|
HTMLDocument.prototype.removeEventListener = jest.fn();
|
|
|
|
const { unmount, rerender } = render(
|
|
<DragAndDropZone
|
|
onDragOver={onDragOver}
|
|
onDragExit={onDragExit}
|
|
onDrop={onDrop}
|
|
>
|
|
<textarea>I'm a text area</textarea>
|
|
</DragAndDropZone>,
|
|
);
|
|
|
|
// Rerendering so that the ref gets set to the DOM node.
|
|
// represented by the Preact element <textarea />
|
|
rerender(
|
|
<DragAndDropZone
|
|
onDragOver={onDragOver}
|
|
onDragExit={onDragExit}
|
|
onDrop={onDrop}
|
|
>
|
|
<textarea>I'm a text area</textarea>
|
|
</DragAndDropZone>,
|
|
);
|
|
|
|
unmount();
|
|
expect(HTMLDocument.prototype.removeEventListener).toBeCalledTimes(2);
|
|
expect(HTMLElement.prototype.removeEventListener).toHaveBeenCalledTimes(
|
|
4,
|
|
);
|
|
});
|
|
|
|
it('should not attach drag and drop events when no children.', async () => {
|
|
const onDrop = jest.fn();
|
|
const onDragOver = jest.fn();
|
|
const onDragExit = jest.fn();
|
|
|
|
HTMLElement.prototype.addEventListener = jest.fn();
|
|
HTMLDocument.prototype.addEventListener = jest.fn();
|
|
|
|
expect(() => {
|
|
render(
|
|
<DragAndDropZone
|
|
onDragOver={onDragOver}
|
|
onDragExit={onDragExit}
|
|
onDrop={onDrop}
|
|
/>,
|
|
);
|
|
}).toThrowError(
|
|
'The <DragAndDropZone /> component children prop is null or was not specified.',
|
|
);
|
|
});
|
|
});
|
|
});
|