Skip to content

Commit

Permalink
implement testing TODO: investigate failing Image test #1075
Browse files Browse the repository at this point in the history
  • Loading branch information
asuresh-code committed Dec 12, 2024
1 parent 157ed0f commit 2b0ae3f
Show file tree
Hide file tree
Showing 5 changed files with 400 additions and 3 deletions.
133 changes: 133 additions & 0 deletions cypress/e2e/with_mock_data/items.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,139 @@ describe('Items', () => {

cy.findByTestId('galleryLightBox').should('not.exist');
});

it('edits an image successfully', () => {
cy.findByText('5YUQDDjKpz2z').click();
cy.findByText(
'High-resolution cameras for beam characterization. 1'
).should('exist');

cy.findByText('Gallery').click();

cy.findAllByLabelText('Card Actions').first().click();
cy.findAllByText('Edit').last().click();

cy.findByRole('dialog')
.should('be.visible')
.within(() => {
cy.findByLabelText('File Name *').clear();
cy.findByLabelText('File Name *').type('test');

cy.findByLabelText('Title').clear();
cy.findByLabelText('Title').type('test');

cy.findByLabelText('Description').clear();
cy.findByLabelText('Description').type('test');
cy.findByLabelText('Description')
.invoke('val')
.should('equal', 'test');
});

cy.startSnoopingBrowserMockedRequest();

cy.findByRole('button', { name: 'Save' }).click();
cy.findByRole('dialog').should('not.exist');

cy.findBrowserMockedRequests({
method: 'PATCH',
url: '/images/:id',
}).should(async (patchRequests) => {
expect(patchRequests.length).equal(1);
const request = patchRequests[0];
expect(JSON.stringify(await request.json())).equal(
'{"file_name":"test","title": "test","description":"test"}'
);
});
});

it('not changing any fields shows error', () => {
cy.findByText('5YUQDDjKpz2z').click();
cy.findByText(
'High-resolution cameras for beam characterization. 1'
).should('exist');

cy.findByText('Gallery').click();

cy.findAllByLabelText('Card Actions').first().click();
cy.findAllByText('Edit').last().click();

cy.findByRole('dialog')
.should('be.visible')
.within(() => {
cy.findByRole('button', { name: 'Save' }).click();
cy.contains(
"There have been no changes made. Please change a field's value or press Cancel to exit."
);
});
cy.findByRole('button', { name: 'Save' }).should('be.disabled');
});

it('Required fields that are cleared are not allowed and show error message', () => {
cy.findByText('5YUQDDjKpz2z').click();
cy.findByText(
'High-resolution cameras for beam characterization. 1'
).should('exist');

cy.findByText('Gallery').click();

cy.findAllByLabelText('Card Actions').first().click();
cy.findAllByText('Edit').last().click();

cy.findByRole('dialog')
.should('be.visible')
.within(() => {
cy.findByLabelText('File Name *').clear();

cy.findByRole('button', { name: 'Save' }).click();
cy.contains('Please enter a file name.');
});
cy.findByRole('button', { name: 'Save' }).should('be.disabled');
});

it('opens edit dialog in lightbox', () => {
cy.findByText('5YUQDDjKpz2z').click();
cy.findByText(
'High-resolution cameras for beam characterization. 1'
).should('exist');

cy.findByText('Gallery').click();

cy.findAllByAltText('test').first().click();
cy.findByTestId('galleryLightBox').within(() => {
cy.findByText('File name: stfc-logo-blue-text.png').should('exist');
cy.findByText('Title: stfc-logo-blue-text').should('exist');
cy.findByText('test').should('exist');

cy.findByAltText('test').should('exist');

cy.findByAltText('test')
.should('have.attr', 'src')
.and(
'include',
'http://localhost:3000/images/stfc-logo-blue-text.png?text=1'
);

cy.findByLabelText('Image Actions').click();
});

cy.findAllByText('Edit').last().click();

cy.findByRole('dialog', { timeout: 10000 }).should('exist');

cy.findByRole('dialog').within(() => {
cy.findByText('Edit Image').should('exist');
});

cy.findByRole('dialog').within(() => {
cy.findByRole('button', { name: 'Cancel' }).click();
});

cy.findByRole('dialog').should('not.exist');

cy.findByLabelText('Close').click();

cy.findByTestId('galleryLightBox').should('not.exist');
});
});

it('delete an item', () => {
Expand Down
27 changes: 26 additions & 1 deletion src/api/images.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { renderHook, waitFor } from '@testing-library/react';
import ImagesJSON from '../mocks/Images.json';
import { hooksWrapperWithProviders } from '../testUtils';
import { useGetImage, useGetImages } from './images';
import { ImagePatch } from './api.types';
import { useGetImage, useGetImages, usePatchImage } from './images';

describe('images api functions', () => {
afterEach(() => {
Expand Down Expand Up @@ -62,4 +63,28 @@ describe('images api functions', () => {
});
});
});

describe('usePatchImage', () => {
let mockDataPatch: ImagePatch;
beforeEach(() => {
mockDataPatch = {
file_name: 'edited_image.jpeg',
title: 'an edited title',
description: 'an edited description',
};
});
it('sends a patch request to edit an image and returns a successful response', async () => {
const { result } = renderHook(() => usePatchImage(), {
wrapper: hooksWrapperWithProviders(),
});

result.current.mutate({ id: '1', image: mockDataPatch });
await waitFor(() => expect(result.current.isSuccess).toBeTruthy());

expect(result.current.data).toEqual({
...ImagesJSON[0],
...mockDataPatch,
});
});
});
});
155 changes: 155 additions & 0 deletions src/common/images/editImageDialog.component.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import { fireEvent, screen, waitFor } from '@testing-library/react';
import userEvent, { UserEvent } from '@testing-library/user-event';
import { http } from 'msw';
import { MockInstance } from 'vitest';
import { storageApi } from '../../api/api';
import handleIMS_APIError from '../../handleIMS_APIError';
import ImagesJSON from '../../mocks/Images.json';
import { server } from '../../mocks/server';
import { renderComponentWithRouterProvider } from '../../testUtils';
import EditImageDialog, { ImageDialogProps } from './editImageDialog.component';

vi.mock('../../handleIMS_APIError');

describe('Edit image dialog', () => {
const onClose = vi.fn();
let props: ImageDialogProps;
let user: UserEvent;
const createView = () => {
return renderComponentWithRouterProvider(<EditImageDialog {...props} />);
};

beforeEach(() => {
props = {
open: true,
onClose: onClose,
};
user = userEvent.setup();
});

afterEach(() => {
vi.clearAllMocks();
});
const modifyImageValues = (values: {
file_name?: string;
title?: string;
description?: string;
}) => {
if (values.file_name !== undefined)
fireEvent.change(screen.getByLabelText('File Name *'), {
target: { value: values.file_name },
});

if (values.title !== undefined)
fireEvent.change(screen.getByLabelText('Title'), {
target: { value: values.title },
});

if (values.description !== undefined)
fireEvent.change(screen.getByLabelText('Description'), {
target: { value: values.description },
});
};

describe('Edit an image', () => {
let axiosPatchSpy: MockInstance;
beforeEach(() => {
props = {
...props,
selectedImage: ImagesJSON[0],
};

axiosPatchSpy = vi.spyOn(storageApi, 'patch');
});

it('disables save button and shows circular progress indicator when request is pending', async () => {
server.use(
http.patch('/images/:id', () => {
return new Promise(() => {});
})
);

createView();

modifyImageValues({
file_name: 'Image A',
});

const saveButton = screen.getByRole('button', { name: 'Save' });
await user.click(saveButton);

expect(saveButton).toBeDisabled();
expect(await screen.findByRole('progressbar')).toBeInTheDocument();
});

it('Edits an image correctly', async () => {
createView();
modifyImageValues({
file_name: 'test_file_name.jpeg',
title: 'Test Title',
description: 'Test Description',
});

const saveButton = screen.getByRole('button', { name: 'Save' });

await user.click(saveButton);

expect(axiosPatchSpy).toHaveBeenCalledWith('/images/1', {
file_name: 'test_file_name.jpeg',
title: 'Test Title',
description: 'Test Description',
});

expect(onClose).toHaveBeenCalled();
});

it('No values changed shows correct error message', async () => {
createView();

const saveButton = screen.getByRole('button', { name: 'Save' });

await user.click(saveButton);

expect(
screen.getByText(
"There have been no changes made. Please change a field's value or press Cancel to exit."
)
).toBeInTheDocument();
});

it('Required fields show error if they are whitespace or current value just removed', async () => {
createView();
modifyImageValues({
file_name: '',
});
const saveButton = screen.getByRole('button', { name: 'Save' });

await user.click(saveButton);

expect(screen.getByText('Please enter a file name.')).toBeInTheDocument();
expect(onClose).not.toHaveBeenCalled();
});

it('CatchAllError request works correctly and displays refresh page message', async () => {
createView();
modifyImageValues({
file_name: 'Error 500',
});
const saveButton = screen.getByRole('button', { name: 'Save' });

await user.click(saveButton);

expect(handleIMS_APIError).toHaveBeenCalled();
});

it('calls onClose when Close button is clicked', async () => {
createView();
const cancelButton = screen.getByRole('button', { name: 'Cancel' });
await user.click(cancelButton);

await waitFor(() => {
expect(onClose).toHaveBeenCalled();
});
});
});
});
9 changes: 7 additions & 2 deletions src/common/images/editImageDialog.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import handleIMS_APIError from '../../handleIMS_APIError';
export interface ImageDialogProps {
open: boolean;
onClose: () => void;
selectedImage: APIImage;
selectedImage?: APIImage;
}

const EditImageDialog = (props: ImageDialogProps) => {
Expand All @@ -33,7 +33,12 @@ const EditImageDialog = (props: ImageDialogProps) => {
const { mutateAsync: patchImage, isPending: isEditPending } = usePatchImage();

const initalImage: ImagePatch = React.useMemo(
() => selectedImage,
() =>
selectedImage ?? {
file_name: '',
title: '',
description: '',
},

Check warning on line 41 in src/common/images/editImageDialog.component.tsx

View check run for this annotation

Codecov / codecov/patch

src/common/images/editImageDialog.component.tsx#L38-L41

Added lines #L38 - L41 were not covered by tests
[selectedImage]
);

Expand Down
Loading

0 comments on commit 2b0ae3f

Please sign in to comment.