|
- import * as React from 'react';
- import {
- render,
- screen,
- cleanup,
- fireEvent,
- } from '@testing-library/react';
- import userEvent from '@testing-library/user-event';
- import {
- vi,
- describe,
- it,
- expect,
- afterEach,
- } from 'vitest';
- import matchers from '@testing-library/jest-dom/matchers';
- import {
- FileSelectBox,
- FileSelectBoxDerivedElement,
- DELETE_KEYS, SELECT_KEYS,
- } from '.';
-
- expect.extend(matchers);
-
- const userEventDrop = async (
- dropZoneElement: HTMLElement,
- fileOrFiles: File | File[],
- targetInputElement: HTMLInputElement,
- ) => {
- const dummyInput = window.document.createElement('input');
- dummyInput.type = 'file';
- await userEvent.upload(dummyInput, fileOrFiles);
-
- // targeting change event on the input element
- await userEvent.upload(targetInputElement, fileOrFiles);
-
- fireEvent.drop(dropZoneElement, {
- dataTransfer: {
- files: dummyInput.files,
- },
- });
- };
-
- const userEventPaste = async (
- dropZoneElement: HTMLElement,
- fileOrFiles: File | File[],
- ) => {
- const dummyInput = window.document.createElement('input');
- dummyInput.type = 'file';
- await userEvent.upload(dummyInput, fileOrFiles);
-
- // targeting change event on the input element
- await userEvent.upload(dropZoneElement, fileOrFiles);
-
- fireEvent.paste(dropZoneElement, {
- clipboardData: {
- files: dummyInput.files,
- },
- });
- };
-
- describe('FileSelectBox', () => {
- afterEach(() => {
- cleanup();
- });
-
- it('renders a file input', () => {
- render(
- <FileSelectBox />,
- );
-
- const input = screen.getByTestId('input');
- expect(input).toBeInTheDocument();
- });
-
- it('renders a border', () => {
- render(
- <FileSelectBox
- border
- />,
- );
- const border = screen.getByTestId('border');
- expect(border).toBeInTheDocument();
- });
-
- it('renders a block component', () => {
- render(
- <FileSelectBox
- block
- />,
- );
- const root = screen.getByTestId('root');
- expect(root).toHaveClass('flex w-full');
- });
-
- it('renders a label', () => {
- render(
- <FileSelectBox
- label="foo"
- />,
- );
- const textbox = screen.getByLabelText('foo');
- expect(textbox).toBeInTheDocument();
- const label = screen.getByTestId('label');
- expect(label).toHaveTextContent('foo');
- });
-
- it('renders a hidden label', () => {
- render(
- <FileSelectBox
- label="foo"
- hiddenLabel
- />,
- );
- const textbox = screen.getByLabelText('foo');
- expect(textbox).toBeInTheDocument();
- const label = screen.queryByTestId('label');
- expect(label).toBeInTheDocument();
- expect(label).toHaveClass('sr-only');
- });
-
- it('handles a change event', async () => {
- const onChange = vi.fn();
-
- render(
- <FileSelectBox
- onChange={onChange}
- />,
- );
-
- const input = screen.getByTestId('input') as FileSelectBoxDerivedElement;
- const file = new File(['foo'], 'foo.txt', {type: 'text/plain'});
- await userEvent.upload(input, file);
- expect(onChange).toBeCalledTimes(1);
- });
-
- it('handles a blur event', async () => {
- const onBlur = vi.fn();
-
- render(
- <FileSelectBox
- onBlur={onBlur}
- />,
- );
-
- const input = screen.getByTestId('input') as FileSelectBoxDerivedElement;
- input.focus();
- input.blur();
- expect(onBlur).toBeCalledTimes(1);
- });
-
- describe('when enhanced', () => {
- it('renders a hint', () => {
- render(
- <FileSelectBox
- enhanced
- hint="foo"
- />,
- );
-
- const hint = screen.getByTestId('hint');
- expect(hint).toBeInTheDocument();
- });
-
- it('renders a preview for a single file', async () => {
- render(
- <FileSelectBox
- enhanced
- />,
- );
-
- const input = screen.getByTestId('input') as FileSelectBoxDerivedElement;
- const file = new File(['foo'], 'foo.txt', {type: 'text/plain'});
- await userEvent.upload(input, file);
- expect(input.files).toHaveLength(1);
- const preview = screen.getByTestId('preview');
- expect(preview).toBeInTheDocument();
- });
-
- it('renders a preview for a single file without name', async () => {
- render(
- <FileSelectBox
- enhanced
- />,
- );
-
- const input = screen.getByTestId('input') as FileSelectBoxDerivedElement;
- const file = new Blob(['foo'], {type: 'text/plain'});
- await userEvent.upload(input, file as unknown as File);
- expect(input.files).toHaveLength(1);
- const preview = screen.getByTestId('preview');
- expect(preview).toBeInTheDocument();
- });
-
- it('renders a preview for a single file without name', async () => {
- render(
- <FileSelectBox
- enhanced
- />,
- );
-
- const input = screen.getByTestId('input') as FileSelectBoxDerivedElement;
- const { size: _size, ...partialFile } = new File(['foo'], 'foo.txt', {type: 'text/plain'});
- await userEvent.upload(input, partialFile as unknown as File);
- expect(input.files).toHaveLength(1);
- const preview = screen.getByTestId('preview');
- expect(preview).toBeInTheDocument();
- });
-
- it('renders a preview for multiple files', async () => {
- render(
- <FileSelectBox
- enhanced
- multiple
- />,
- );
-
- const input = screen.getByTestId('input') as FileSelectBoxDerivedElement;
- const files = [
- new File(['foo'], 'foo.txt', {type: 'text/plain'}),
- new File(['bar'], 'bar.txt', {type: 'text/plain'}),
- ];
- await userEvent.upload(input, files);
- expect(input.files).toHaveLength(files.length);
- const preview = screen.getByTestId('preview');
- expect(preview).toBeInTheDocument();
- });
-
- it('renders a preview for multiple files without names', async () => {
- render(
- <FileSelectBox
- enhanced
- multiple
- />,
- );
-
- const input = screen.getByTestId('input') as FileSelectBoxDerivedElement;
- const files = [
- new Blob(['foo'], {type: 'text/plain'}),
- new Blob(['bar'], {type: 'text/plain'}),
- ];
- await userEvent.upload(input, files as unknown as File[]);
- expect(input.files).toHaveLength(files.length);
- const preview = screen.getByTestId('preview');
- expect(preview).toBeInTheDocument();
- });
-
- it('renders actions when at least one file is selected', async () => {
- render(
- <FileSelectBox
- enhanced
- multiple
- />,
- );
-
- const input = screen.getByTestId('input');
- const files = [
- new File(['foo'], 'foo.txt', {type: 'text/plain'}),
- new File(['bar'], 'bar.txt', {type: 'text/plain'}),
- ];
- await userEvent.upload(input, files);
- const actions = screen.getByTestId('actions');
- expect(actions).toBeInTheDocument();
- });
-
- it('clears selected files through the clear button', async () => {
- render(
- <FileSelectBox
- enhanced
- />,
- );
-
- const input = screen.getByTestId('input') as FileSelectBoxDerivedElement;
- const file = new File(['foo'], 'foo.txt', {type: 'text/plain'});
- await userEvent.upload(input, file);
-
- const clearButton = screen.getByTestId('clear');
- await userEvent.click(clearButton);
-
- expect(input.files).toHaveLength(0);
- });
-
- it.each(DELETE_KEYS)('clears selected files through pressing %s key', async (key) => {
- render(
- <FileSelectBox
- enhanced
- />,
- );
-
- const input = screen.getByTestId('input') as FileSelectBoxDerivedElement;
- const file = new File(['foo'], 'foo.txt', {type: 'text/plain'});
- await userEvent.upload(input, file);
- input.focus();
- await userEvent.keyboard(`{${key}}`);
- expect(input.files).toHaveLength(0);
- });
-
- it('ignores other key presses when input is focused', async () => {
- render(
- <FileSelectBox
- enhanced
- />,
- );
-
- const input = screen.getByTestId('input') as FileSelectBoxDerivedElement;
- const file = new File(['foo'], 'foo.txt', {type: 'text/plain'});
- await userEvent.upload(input, file);
- input.focus();
- await userEvent.keyboard('a');
- expect(input.files).toHaveLength(1);
- });
-
- it.each(SELECT_KEYS)('opens picker on pressing %s when input is in focus', async (key) => {
- render(
- <FileSelectBox
- enhanced
- />,
- );
-
- const input = screen.getByTestId('input') as FileSelectBoxDerivedElement;
- const file = new File(['foo'], 'foo.txt', {type: 'text/plain'});
- await userEvent.upload(input, file);
- input.focus();
- await userEvent.keyboard(`{${key}}`);
- // how to assert?
- });
-
- it('opens picker when files are previously selected (showPicker)', async () => {
- render(
- <FileSelectBox
- enhanced
- />,
- );
-
- const input = screen.getByTestId('input') as FileSelectBoxDerivedElement;
- const showPicker = vi.fn();
- input.showPicker = showPicker;
- const file = new File(['foo'], 'foo.txt', {type: 'text/plain'});
- await userEvent.upload(input, file);
-
- const clearButton = screen.getByTestId('reselect');
- await userEvent.click(clearButton);
-
- expect(showPicker).toBeCalledTimes(1);
- });
-
- it('opens picker when files are previously selected (no showPicker)', async () => {
- render(
- <FileSelectBox
- enhanced
- />,
- );
-
- const input = screen.getByTestId('input') as FileSelectBoxDerivedElement;
- const showPicker = vi.spyOn(input, 'click');
- const file = new File(['foo'], 'foo.txt', {type: 'text/plain'});
- await userEvent.upload(input, file);
-
- const clearButton = screen.getByTestId('reselect');
- await userEvent.click(clearButton);
-
- expect(showPicker).toBeCalledTimes(1);
- });
-
- it('accepts drop files', async () => {
- const onChange = vi.fn();
-
- render(
- <FileSelectBox
- enhanced
- onChange={onChange}
- />,
- );
-
- const root = screen.getByTestId('root');
- const file = new File(['foo'], 'foo.txt', { type: 'text/plain' });
- const input = screen.getByTestId('input') as FileSelectBoxDerivedElement;
-
- await userEventDrop(root, file, input);
- expect(onChange).toBeCalledTimes(1);
- });
-
- it('accepts pasted files', async () => {
- const onChange = vi.fn();
-
- render(
- <FileSelectBox
- enhanced
- onChange={onChange}
- />,
- );
-
- const input = screen.getByTestId('input') as FileSelectBoxDerivedElement;
- const file = new File(['foo'], 'foo.txt', { type: 'text/plain' });
-
- await userEventPaste(input, file);
- expect(onChange).toBeCalledTimes(1);
- });
- });
- });
|