Skip to content

Commit

Permalink
Add error handling tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sam-schu committed Sep 27, 2024
1 parent d431baf commit cd539bb
Showing 1 changed file with 238 additions and 1 deletion.
239 changes: 238 additions & 1 deletion src/pages/workflows/workflow/WorkflowWrapper.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ import { act, fireEvent, screen, within } from '@testing-library/react';
import userEvent, { UserEvent } from '@testing-library/user-event';
import _ from 'lodash';
import React from 'react';
import * as breadcrumbs from 'src/components/breadcrumbs';
import { Ajax, AjaxContract } from 'src/libs/ajax';
import { MethodsAjaxContract } from 'src/libs/ajax/methods/Methods';
import * as ExportWorkflowToWorkspaceProvider from 'src/libs/ajax/workspaces/providers/ExportWorkflowToWorkspaceProvider';
import { errorWatcher } from 'src/libs/error.mock';
import { goToPath } from 'src/libs/nav';
import { forwardRefWithName } from 'src/libs/react-utils';
import { snapshotsListStore, snapshotStore, TerraUser, TerraUserState, userStore } from 'src/libs/state';
import { WorkflowsContainer } from 'src/pages/workflows/workflow/WorkflowWrapper';
import { BaseWorkflowSummary } from 'src/pages/workflows/workflow/WorkflowSummary';
import { WorkflowsContainer, wrapWorkflows } from 'src/pages/workflows/workflow/WorkflowWrapper';
import { Snapshot } from 'src/snapshots/Snapshot';
import { asMockedFn, renderWithAppContexts as render, SelectHelper } from 'src/testing/test-utils';
import { useWorkspaces } from 'src/workspaces/common/state/useWorkspaces';
Expand Down Expand Up @@ -429,6 +432,240 @@ describe('workflows container', () => {
expect(errorWatcher).toHaveBeenCalledWith('Error deleting snapshot', expect.anything());
});

it('displays the method not found page if a method does not exist or the user does not have access', async () => {
// Arrange
mockAjax({ listImpl: jest.fn().mockReturnValue([]) });

// set the user's email
jest.spyOn(userStore, 'get').mockImplementation(jest.fn().mockReturnValue(mockUserState('hello@world.org')));

const WorkflowSummary = _.flow(
forwardRefWithName('WorkflowSummary'),
wrapWorkflows({
breadcrumbs: () => breadcrumbs.commonPaths.workflowList(),
title: 'Methods',
activeTab: 'dashboard',
})
)(() => {
return <BaseWorkflowSummary />;
});

// Act
await act(async () => {
render(
<WorkflowSummary
namespace={mockSnapshot.namespace}
name={mockSnapshot.name}
snapshotId={mockSnapshot.snapshotId}
tabName='dashboard'
/>
);
});

// Assert

// should not display the loading spinner
const spinner = document.querySelector('[data-icon="loadingSpinner"]');
expect(spinner).not.toBeInTheDocument();

// should not display an error toast
expect(errorWatcher).not.toHaveBeenCalled();

// should not display the tab bar
expect(screen.queryByText(/dashboard/i)).not.toBeInTheDocument();
expect(screen.queryByText(/wdl/i)).not.toBeInTheDocument();
expect(screen.queryByText(/snapshot:/i)).not.toBeInTheDocument();
expect(screen.queryByText(`${mockSnapshot.snapshotId}`)).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: /export to workspace/i })).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: 'Snapshot action menu' })).not.toBeInTheDocument();

// should not display the base workflow summary
expect(screen.queryByText(/snapshot information/i)).not.toBeInTheDocument();

// should only display the 404 error page, with the correct info filled in
expect(screen.getByText('Could not display method')).toBeInTheDocument();
expect(
screen.getByText(
'You cannot access this method because either it does not exist or you do not have access to it.'
)
).toBeInTheDocument();
expect(screen.getByText('hello@world.org')).toBeInTheDocument();
expect(
screen.getByText(
'To view a snapshot of an existing method, an owner of the snapshot must give you permission to view it or make it publicly readable.'
)
).toBeInTheDocument();
expect(screen.getByText('The method may also have been deleted by one of its owners.')).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Return to Methods List' })).toBeInTheDocument();
});

it('displays an error toast when there is an unexpected error loading a method', async () => {
// Arrange
mockAjax({
listImpl: jest.fn(() => {
throw new Error('BOOM');
}),
});

const WorkflowSummary = _.flow(
forwardRefWithName('WorkflowSummary'),
wrapWorkflows({
breadcrumbs: () => breadcrumbs.commonPaths.workflowList(),
title: 'Methods',
activeTab: 'dashboard',
})
)(() => {
return <BaseWorkflowSummary />;
});

// Act
await act(async () => {
render(
<WorkflowSummary
namespace={mockSnapshot.namespace}
name={mockSnapshot.name}
snapshotId={mockSnapshot.snapshotId}
tabName='dashboard'
/>
);
});

// Assert

// should not display the loading spinner
const spinner = document.querySelector('[data-icon="loadingSpinner"]');
expect(spinner).not.toBeInTheDocument();

// should not display the tab bar
expect(screen.queryByText(/dashboard/i)).not.toBeInTheDocument();
expect(screen.queryByText(/wdl/i)).not.toBeInTheDocument();
expect(screen.queryByText(/snapshot:/i)).not.toBeInTheDocument();
expect(screen.queryByText(`${mockSnapshot.snapshotId}`)).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: /export to workspace/i })).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: 'Snapshot action menu' })).not.toBeInTheDocument();

// should not display the base workflow summary
expect(screen.queryByText(/snapshot information/i)).not.toBeInTheDocument();

// should not display the 404 error page
expect(screen.queryByText('Could not display method')).not.toBeInTheDocument();
expect(screen.queryByText('Could not display snapshot')).not.toBeInTheDocument();

// should only display an error toast
expect(errorWatcher).toHaveBeenCalledWith('Error loading method', expect.anything());
});

it('displays the snapshot not found page if a snapshot does not exist or the user does not have access', async () => {
// Arrange
mockAjax({ getImpl: jest.fn().mockRejectedValue(new Response('{ "message": "Not found"}', { status: 404 })) });

// set the user's email
jest.spyOn(userStore, 'get').mockImplementation(jest.fn().mockReturnValue(mockUserState('hello@world.org')));

// Act
await act(async () => {
render(
<WorkflowsContainer
namespace={mockSnapshot.namespace}
name={mockSnapshot.name}
snapshotId={`${mockSnapshot.snapshotId}`}
tabName='dashboard'
>
children
</WorkflowsContainer>
);
});

// Assert

// should not display the loading spinner
const spinner = document.querySelector('[data-icon="loadingSpinner"]');
expect(spinner).not.toBeInTheDocument();

// should not display the children
expect(screen.queryByText('children')).not.toBeInTheDocument();

// should not display an error toast
expect(errorWatcher).not.toHaveBeenCalled();

// should display the tab bar, but with the export button and action menu disabled
expect(screen.getByText(/dashboard/i)).toBeInTheDocument();
expect(screen.getByText(/wdl/i)).toBeInTheDocument();
expect(screen.getByText(/snapshot:/i)).toBeInTheDocument();
expect(screen.getByText(`${mockSnapshot.snapshotId}`)).toBeInTheDocument();

const exportButton = screen.getByRole('button', { name: /export to workspace/i });
expect(exportButton).toBeInTheDocument();
expect(exportButton).toHaveAttribute('disabled');
expect(exportButton).toHaveAttribute('aria-disabled');

const actionMenu = screen.getByRole('button', { name: 'Snapshot action menu' });
expect(actionMenu).toBeInTheDocument();
expect(actionMenu).toHaveAttribute('disabled');
expect(actionMenu).toHaveAttribute('aria-disabled');

// should display the 404 error page, with the correct info filled in
expect(screen.getByText('Could not display snapshot')).toBeInTheDocument();
expect(
screen.getByText(
'You cannot access this method snapshot because either it does not exist or you do not have access to it.'
)
).toBeInTheDocument();
expect(screen.getByText('hello@world.org')).toBeInTheDocument();
expect(
screen.getByText(
'To view an existing method snapshot, an owner of the snapshot must give you permission to view it or make it publicly readable.'
)
).toBeInTheDocument();
expect(screen.getByText('The snapshot may also have been deleted by one of its owners.')).toBeInTheDocument();
expect(screen.getByText('Please select a different snapshot from the dropdown above.')).toBeInTheDocument();
});

it('displays an error toast when there is an unexpected error loading a snapshot', async () => {
// Arrange
mockAjax({
getImpl: jest.fn(() => {
throw new Error('BOOM');
}),
});

// Act
await act(async () => {
render(
<WorkflowsContainer
namespace={mockSnapshot.namespace}
name={mockSnapshot.name}
snapshotId={`${mockSnapshot.snapshotId}`}
tabName='dashboard'
>
children
</WorkflowsContainer>
);
});

// Assert

// should not display the loading spinner
const spinner = document.querySelector('[data-icon="loadingSpinner"]');
expect(spinner).not.toBeInTheDocument();

// should not display the tab bar or children
expect(screen.queryByText(/dashboard/i)).not.toBeInTheDocument();
expect(screen.queryByText(/wdl/i)).not.toBeInTheDocument();
expect(screen.queryByText(/snapshot:/i)).not.toBeInTheDocument();
expect(screen.queryByText(`${mockSnapshot.snapshotId}`)).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: /export to workspace/i })).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: 'Snapshot action menu' })).not.toBeInTheDocument();
expect(screen.queryByText('children')).not.toBeInTheDocument();

// should not display the 404 error page
expect(screen.queryByText('Could not display method')).not.toBeInTheDocument();
expect(screen.queryByText('Could not display snapshot')).not.toBeInTheDocument();

// should only display an error toast
expect(errorWatcher).toHaveBeenCalledWith('Error loading snapshot', expect.anything());
});

it('displays export to workspace modal when export button is pressed', async () => {
// Arrange
mockAjax();
Expand Down

0 comments on commit cd539bb

Please sign in to comment.