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

Bhbc 964 #236

Merged
merged 3 commits into from
Apr 16, 2021
Merged
Show file tree
Hide file tree
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
3 changes: 1 addition & 2 deletions api/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,10 @@ const app: express.Express = express();
app.use(function (req: any, res: any, next: any) {
defaultLog.info(`${req.method} ${req.url}`);

res.setHeader('Access-Control-Allow-Credentials', true);
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Authorization, responseType');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE, HEAD');
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
res.setHeader('Cache-Control', 'no-store');

next();
});
Expand Down
156 changes: 31 additions & 125 deletions app/src/components/attachments/FileUpload.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { fireEvent, render, waitFor } from '@testing-library/react';
import { APIError } from 'hooks/api/useAxios';
import { useBiohubApi } from 'hooks/useBioHubApi';
import React from 'react';
import FileUpload from './FileUpload';
Expand Down Expand Up @@ -27,154 +26,61 @@ describe('FileUpload', () => {
mockBiohubApi().project.uploadProjectAttachments.mockClear();
});

it('matches the snapshot', () => {
const { asFragment } = renderContainer();
it('renders the dropZone component', async () => {
const { getByText } = renderContainer();

expect(asFragment()).toMatchSnapshot();
expect(getByText('Drag your files here', { exact: false })).toBeVisible();
});

it('handles file upload success', async () => {
let resolveRef: (value: unknown) => void;
it('renders an item in the list for each file added', async () => {
mockBiohubApi().project.uploadProjectAttachments.mockReturnValue(Promise.resolve());

const mockUploadPromise = new Promise(function (resolve: any, reject: any) {
resolveRef = resolve;
});

mockBiohubApi().project.uploadProjectAttachments.mockReturnValue(mockUploadPromise);

const { asFragment, getByTestId, getByText } = renderContainer();

const testFile = new File(['test png content'], 'testpng.txt', { type: 'text/plain' });
const { getByTestId, getByText } = renderContainer();

const dropZoneInput = getByTestId('drop-zone-input');

fireEvent.change(dropZoneInput, { target: { files: [testFile] } });

await waitFor(() => {
expect(mockBiohubApi().project.uploadProjectAttachments).toHaveBeenCalledWith(
projectId,
[testFile],
expect.any(Object),
expect.any(Function)
);

expect(getByText('testpng.txt')).toBeVisible();

expect(getByText('Uploading')).toBeVisible();
fireEvent.change(dropZoneInput, {
target: {
files: [
new File([`test png content`], `testpng0.txt`, { type: 'text/plain' }),
new File([`test png content`], `testpng1.txt`, { type: 'text/plain' }),
new File([`test png content`], `testpng2.txt`, { type: 'text/plain' }),
new File([`test png content`], `testpng3.txt`, { type: 'text/plain' }),
new File([`test png content`], `testpng4.txt`, { type: 'text/plain' })
]
}
});

// Manually trigger the upload resolve to simulate a successful upload
// @ts-ignore
resolveRef(null);

await waitFor(() => {
expect(getByText('Complete')).toBeVisible();
expect(getByText('testpng0.txt')).toBeVisible();
expect(getByText('testpng1.txt')).toBeVisible();
expect(getByText('testpng2.txt')).toBeVisible();
expect(getByText('testpng3.txt')).toBeVisible();
expect(getByText('testpng4.txt')).toBeVisible();
});

// expect file list item to show complete state
expect(asFragment()).toMatchSnapshot();
});

it('handles file upload API rejection', async () => {
let rejectRef: (reason: unknown) => void;

const mockUploadPromise = new Promise(function (resolve: any, reject: any) {
rejectRef = reject;
});

mockBiohubApi().project.uploadProjectAttachments.mockReturnValue(mockUploadPromise);

const { asFragment, getByTestId, getByText, getByTitle } = renderContainer();
it('removes an item from the list when the onCancel callback is triggered', async () => {
mockBiohubApi().project.uploadProjectAttachments.mockReturnValue(new Promise(() => {}));

const testFile = new File(['test png content'], 'testpng.txt', { type: 'text/plain' });
const { getByTestId, getByText, getByTitle, queryByText } = renderContainer();

const dropZoneInput = getByTestId('drop-zone-input');

fireEvent.change(dropZoneInput, { target: { files: [testFile] } });

await waitFor(() => {
expect(mockBiohubApi().project.uploadProjectAttachments).toHaveBeenCalledWith(
projectId,
[testFile],
expect.any(Object),
expect.any(Function)
);

expect(getByText('testpng.txt')).toBeVisible();

expect(getByText('Uploading')).toBeVisible();
});

// Manually trigger the upload reject to simulate an unsuccessful upload
// @ts-ignore
rejectRef(new APIError({ response: { data: { message: 'File was evil!' } } } as any));

await waitFor(() => {
expect(getByText('File was evil!')).toBeVisible();
});

// expect file list item to show error state
expect(asFragment()).toMatchSnapshot();

const removeButton = getByTitle('Clear File');

await waitFor(() => {
expect(removeButton).toBeVisible();
fireEvent.change(dropZoneInput, {
target: {
files: [new File([`test png content`], `testpng0.txt`, { type: 'text/plain' })]
}
});

fireEvent.click(removeButton);

// expect file list item to be removed
expect(asFragment()).toMatchSnapshot();
});

it('handles file upload DropZone rejection for file too large', async () => {
const { asFragment, getByTestId, getByText } = renderContainer();

const testFile = new File(['test png content'], 'testpng.txt', { type: 'text/plain' });
// force file size to be 500MB
Object.defineProperty(testFile, 'size', { value: 1024 * 1024 * 500 }); // 500MB file

const dropZoneInput = getByTestId('drop-zone-input');

fireEvent.change(dropZoneInput, { target: { files: [testFile] } });

await waitFor(() => {
expect(getByText('testpng.txt')).toBeVisible();

expect(getByText('File size exceeds maximum')).toBeVisible();
expect(getByText('testpng0.txt')).toBeVisible();
});

// expect file list item to show error state
expect(asFragment()).toMatchSnapshot();
});

it('handles file upload DropZone rejection for too many files uploaded at once', async () => {
const { asFragment, getByTestId, getByText, getAllByText } = renderContainer();

const getTestFiles = (num: number): File[] => {
const files = [];
for (let i = 0; i < num; i++) {
files.push(new File([`test png ${i} content`], `testpng${i}.txt`, { type: 'text/plain' }));
}
return files;
};

const dropZoneInput = getByTestId('drop-zone-input');

fireEvent.change(dropZoneInput, { target: { files: getTestFiles(11) } });
fireEvent.click(getByTitle('Cancel Upload'));

await waitFor(() => {
const errorMessages = getAllByText('Number of files uploaded at once exceeds maximum');
expect(errorMessages.length).toEqual(11);
expect(queryByText('testpng0.txt')).not.toBeInTheDocument();
});

expect(getByText('testpng1.txt')).toBeVisible();
expect(getByText('testpng3.txt')).toBeVisible();
expect(getByText('testpng7.txt')).toBeVisible();
expect(getByText('testpng10.txt')).toBeVisible();

// expect file list item to show error state
expect(asFragment()).toMatchSnapshot();
});
});
Loading