From bf263e17e488ff7847879c0b213efa2784349293 Mon Sep 17 00:00:00 2001 From: Jamey Huffnagle Date: Tue, 1 Oct 2024 13:35:29 -0400 Subject: [PATCH] new/fixed testing --- .../__tests__/RetryStep.test.tsx | 91 +-------------- .../__tests__/SkipStepNewTips.test.tsx | 73 +----------- .../__tests__/SkipStepSameTips.test.tsx | 77 ++----------- .../shared/__tests__/RetryStepInfo.test.tsx | 102 +++++++++++++++++ .../shared/__tests__/SkipStepInfo.test.tsx | 104 ++++++++++++++++++ 5 files changed, 223 insertions(+), 224 deletions(-) create mode 100644 app/src/organisms/ErrorRecoveryFlows/shared/__tests__/RetryStepInfo.test.tsx create mode 100644 app/src/organisms/ErrorRecoveryFlows/shared/__tests__/SkipStepInfo.test.tsx diff --git a/app/src/organisms/ErrorRecoveryFlows/RecoveryOptions/__tests__/RetryStep.test.tsx b/app/src/organisms/ErrorRecoveryFlows/RecoveryOptions/__tests__/RetryStep.test.tsx index 3f0c8179bab1..ec39f5b7c180 100644 --- a/app/src/organisms/ErrorRecoveryFlows/RecoveryOptions/__tests__/RetryStep.test.tsx +++ b/app/src/organisms/ErrorRecoveryFlows/RecoveryOptions/__tests__/RetryStep.test.tsx @@ -1,18 +1,14 @@ import type * as React from 'react' -import { describe, it, vi, expect, beforeEach, afterEach } from 'vitest' -import { screen, waitFor } from '@testing-library/react' +import { describe, it, vi, beforeEach, afterEach } from 'vitest' +import { screen } from '@testing-library/react' import { mockRecoveryContentProps } from '../../__fixtures__' import { renderWithProviders } from '/app/__testing-utils__' import { i18n } from '/app/i18n' -import { RetryStep, RetryStepInfo } from '../RetryStep' -import { ERROR_KINDS, RECOVERY_MAP } from '../../constants' +import { RetryStep } from '../RetryStep' +import { RECOVERY_MAP } from '../../constants' import { SelectRecoveryOption } from '../SelectRecoveryOption' -import { clickButtonLabeled } from '../../__tests__/util' - -import type { Mock } from 'vitest' - vi.mock('/app/molecules/Command') vi.mock('../SelectRecoveryOption') @@ -22,14 +18,6 @@ const render = (props: React.ComponentProps) => { })[0] } -const renderRetryStepInfo = ( - props: React.ComponentProps -) => { - return renderWithProviders(, { - i18nInstance: i18n, - })[0] -} - describe('RetryStep', () => { let props: React.ComponentProps @@ -71,74 +59,3 @@ describe('RetryStep', () => { screen.getByText('MOCK_SELECT_RECOVERY_OPTION') }) }) - -describe('RetryStepInfo', () => { - let props: React.ComponentProps - let mockhandleMotionRouting: Mock - let mockRetryFailedCommand: Mock - let mockResumeRun: Mock - - beforeEach(() => { - mockhandleMotionRouting = vi.fn(() => Promise.resolve()) - mockRetryFailedCommand = vi.fn(() => Promise.resolve()) - mockResumeRun = vi.fn() - - props = { - ...mockRecoveryContentProps, - routeUpdateActions: { - handleMotionRouting: mockhandleMotionRouting, - } as any, - recoveryCommands: { - retryFailedCommand: mockRetryFailedCommand, - resumeRun: mockResumeRun, - } as any, - } - }) - - afterEach(() => { - vi.resetAllMocks() - }) - - it(`renders the component with the correct text for ${ERROR_KINDS.TIP_NOT_DETECTED} `, () => { - renderRetryStepInfo({ ...props, errorKind: ERROR_KINDS.TIP_NOT_DETECTED }) - screen.getByText('Retry step') - screen.queryByText( - 'First, take any necessary actions to prepare the robot to retry the failed tip pickup.' - ) - screen.queryByText('Then, close the robot door before proceeding.') - }) - - it('renders the component with the correct text for not specifically handled error kinds', () => { - renderRetryStepInfo(props) - screen.getByText('Retry step') - screen.queryByText( - 'First, take any necessary actions to prepare the robot to retry the failed step.' - ) - screen.queryByText('Then, close the robot door before proceeding.') - }) - - it('calls the correct routeUpdateActions and recoveryCommands in the correct order when the primary button is clicked', async () => { - renderRetryStepInfo(props) - clickButtonLabeled('Retry now') - - await waitFor(() => { - expect(mockhandleMotionRouting).toHaveBeenCalledWith( - true, - RECOVERY_MAP.ROBOT_RETRYING_STEP.ROUTE - ) - }) - await waitFor(() => { - expect(mockRetryFailedCommand).toHaveBeenCalled() - }) - await waitFor(() => { - expect(mockResumeRun).toHaveBeenCalled() - }) - - expect(mockhandleMotionRouting.mock.invocationCallOrder[0]).toBeLessThan( - mockRetryFailedCommand.mock.invocationCallOrder[0] - ) - expect(mockRetryFailedCommand.mock.invocationCallOrder[0]).toBeLessThan( - mockResumeRun.mock.invocationCallOrder[0] - ) - }) -}) diff --git a/app/src/organisms/ErrorRecoveryFlows/RecoveryOptions/__tests__/SkipStepNewTips.test.tsx b/app/src/organisms/ErrorRecoveryFlows/RecoveryOptions/__tests__/SkipStepNewTips.test.tsx index 73d098f5234e..09afa086dca3 100644 --- a/app/src/organisms/ErrorRecoveryFlows/RecoveryOptions/__tests__/SkipStepNewTips.test.tsx +++ b/app/src/organisms/ErrorRecoveryFlows/RecoveryOptions/__tests__/SkipStepNewTips.test.tsx @@ -1,14 +1,13 @@ import type * as React from 'react' -import { describe, it, vi, expect, beforeEach, afterEach } from 'vitest' -import { screen, waitFor } from '@testing-library/react' +import { describe, it, vi, expect, beforeEach } from 'vitest' +import { screen } from '@testing-library/react' import { mockRecoveryContentProps } from '../../__fixtures__' import { renderWithProviders } from '/app/__testing-utils__' import { i18n } from '/app/i18n' -import { SkipStepNewTips, SkipStepWithNewTips } from '../SkipStepNewTips' +import { SkipStepNewTips } from '../SkipStepNewTips' import { RECOVERY_MAP } from '../../constants' import { SelectRecoveryOption } from '../SelectRecoveryOption' -import { clickButtonLabeled } from '../../__tests__/util' import type { Mock } from 'vitest' @@ -18,8 +17,9 @@ vi.mock('../../shared', async () => { const actual = await vi.importActual('../../shared') return { ...actual, - ReplaceTips: vi.fn(() =>
MOCK_REPLACE_TIPS
), SelectTips: vi.fn(() =>
MOCK_SELECT_TIPS
), + TwoColLwInfoAndDeck: vi.fn(() =>
MOCK_REPLACE_TIPS
), + SkipStepInfo: vi.fn(() =>
MOCK_SKIP_STEP_INFO
), } }) @@ -29,14 +29,6 @@ const render = (props: React.ComponentProps) => { })[0] } -const renderSkipStepWithNewTips = ( - props: React.ComponentProps -) => { - return renderWithProviders(, { - i18nInstance: i18n, - })[0] -} - describe('SkipStepNewTips', () => { let props: React.ComponentProps let mockProceedToRouteAndStep: Mock @@ -89,7 +81,7 @@ describe('SkipStepNewTips', () => { }, } render(props) - screen.getByText('Skip to next step with new tips') + screen.getByText('MOCK_SKIP_STEP_INFO') }) it('renders SelectRecoveryOption as a fallback', () => { @@ -119,56 +111,3 @@ describe('SkipStepNewTips', () => { ) }) }) - -describe('SkipStepWithNewTips', () => { - let props: React.ComponentProps - let mockhandleMotionRouting: Mock - let mockSkipFailedCommand: Mock - - beforeEach(() => { - mockhandleMotionRouting = vi.fn(() => Promise.resolve()) - mockSkipFailedCommand = vi.fn(() => Promise.resolve()) - - props = { - ...mockRecoveryContentProps, - routeUpdateActions: { - handleMotionRouting: mockhandleMotionRouting, - } as any, - recoveryCommands: { - skipFailedCommand: mockSkipFailedCommand, - } as any, - } - }) - - afterEach(() => { - vi.resetAllMocks() - }) - - it('renders the component with the correct text', () => { - renderSkipStepWithNewTips(props) - screen.getByText('Skip to next step with new tips') - screen.queryByText( - 'The failed dispense step will not be completed. The run will continue from the next step.' - ) - screen.queryByText('Close the robot door before proceeding.') - }) - - it('calls the correct routeUpdateActions and recoveryCommands in the correct order when the primary button is clicked', async () => { - renderSkipStepWithNewTips(props) - clickButtonLabeled('Continue run now') - - await waitFor(() => { - expect(mockhandleMotionRouting).toHaveBeenCalledWith( - true, - RECOVERY_MAP.ROBOT_SKIPPING_STEP.ROUTE - ) - }) - await waitFor(() => { - expect(mockSkipFailedCommand).toHaveBeenCalled() - }) - - expect(mockhandleMotionRouting.mock.invocationCallOrder[0]).toBeLessThan( - mockSkipFailedCommand.mock.invocationCallOrder[0] - ) - }) -}) diff --git a/app/src/organisms/ErrorRecoveryFlows/RecoveryOptions/__tests__/SkipStepSameTips.test.tsx b/app/src/organisms/ErrorRecoveryFlows/RecoveryOptions/__tests__/SkipStepSameTips.test.tsx index 1a9b7b5dcd22..157825b33222 100644 --- a/app/src/organisms/ErrorRecoveryFlows/RecoveryOptions/__tests__/SkipStepSameTips.test.tsx +++ b/app/src/organisms/ErrorRecoveryFlows/RecoveryOptions/__tests__/SkipStepSameTips.test.tsx @@ -1,19 +1,17 @@ import type * as React from 'react' -import { describe, it, vi, expect, beforeEach, afterEach } from 'vitest' -import { screen, waitFor } from '@testing-library/react' +import { describe, it, vi, beforeEach } from 'vitest' +import { screen } from '@testing-library/react' import { mockRecoveryContentProps } from '../../__fixtures__' import { renderWithProviders } from '/app/__testing-utils__' import { i18n } from '/app/i18n' -import { SkipStepSameTips, SkipStepSameTipsInfo } from '../SkipStepSameTips' +import { SkipStepSameTips } from '../SkipStepSameTips' import { RECOVERY_MAP } from '../../constants' import { SelectRecoveryOption } from '../SelectRecoveryOption' - -import { clickButtonLabeled } from '../../__tests__/util' - -import type { Mock } from 'vitest' +import { SkipStepInfo } from '/app/organisms/ErrorRecoveryFlows/shared' vi.mock('/app/molecules/Command') +vi.mock('/app/organisms/ErrorRecoveryFlows/shared') vi.mock('../SelectRecoveryOption') const render = (props: React.ComponentProps) => { @@ -22,14 +20,6 @@ const render = (props: React.ComponentProps) => { })[0] } -const renderSkipStepSameTipsInfo = ( - props: React.ComponentProps -) => { - return renderWithProviders(, { - i18nInstance: i18n, - })[0] -} - describe('SkipStepSameTips', () => { let props: React.ComponentProps @@ -41,6 +31,7 @@ describe('SkipStepSameTips', () => { vi.mocked(SelectRecoveryOption).mockReturnValue(
MOCK_SELECT_RECOVERY_OPTION
) + vi.mocked(SkipStepInfo).mockReturnValue(
MOCK_SKIP_STEP_INFO
) }) it(`renders SkipStepSameTipsInfo when step is ${RECOVERY_MAP.SKIP_STEP_WITH_SAME_TIPS.STEPS.SKIP}`, () => { @@ -52,7 +43,7 @@ describe('SkipStepSameTips', () => { }, } render(props) - screen.getByText('Skip to next step with same tips') + screen.getByText('MOCK_SKIP_STEP_INFO') }) it('renders SelectRecoveryOption as a fallback', () => { @@ -67,57 +58,3 @@ describe('SkipStepSameTips', () => { screen.getByText('MOCK_SELECT_RECOVERY_OPTION') }) }) - -describe('SkipStepSameTipsInfo', () => { - let props: React.ComponentProps - let mockhandleMotionRouting: Mock - let mockSkipFailedCommand: Mock - - beforeEach(() => { - mockhandleMotionRouting = vi.fn(() => Promise.resolve()) - mockSkipFailedCommand = vi.fn(() => Promise.resolve()) - - props = { - ...mockRecoveryContentProps, - routeUpdateActions: { - handleMotionRouting: mockhandleMotionRouting, - } as any, - recoveryCommands: { - skipFailedCommand: mockSkipFailedCommand, - } as any, - } - }) - - afterEach(() => { - vi.resetAllMocks() - }) - - it('renders the component with the correct text', () => { - renderSkipStepSameTipsInfo(props) - screen.getByText('Skip to next step with same tips') - screen.queryByText( - 'The failed dispense step will not be completed. The run will continue from the next step.' - ) - screen.queryByText('Close the robot door before proceeding.') - }) - - it('calls the correct routeUpdateActions and recoveryCommands in the correct order when the primary button is clicked', async () => { - renderSkipStepSameTipsInfo(props) - clickButtonLabeled('Continue run now') - - await waitFor(() => { - expect(mockhandleMotionRouting).toHaveBeenCalledWith( - true, - RECOVERY_MAP.ROBOT_SKIPPING_STEP.ROUTE - ) - }) - - await waitFor(() => { - expect(mockSkipFailedCommand).toHaveBeenCalled() - }) - - expect(mockhandleMotionRouting.mock.invocationCallOrder[0]).toBeLessThan( - mockSkipFailedCommand.mock.invocationCallOrder[0] - ) - }) -}) diff --git a/app/src/organisms/ErrorRecoveryFlows/shared/__tests__/RetryStepInfo.test.tsx b/app/src/organisms/ErrorRecoveryFlows/shared/__tests__/RetryStepInfo.test.tsx new file mode 100644 index 000000000000..e8b3b771f4c3 --- /dev/null +++ b/app/src/organisms/ErrorRecoveryFlows/shared/__tests__/RetryStepInfo.test.tsx @@ -0,0 +1,102 @@ +import { describe, it, vi, expect, beforeEach } from 'vitest' +import { screen, waitFor } from '@testing-library/react' + +import { renderWithProviders } from '/app/__testing-utils__' +import { i18n } from '/app/i18n' +import { RetryStepInfo } from '../RetryStepInfo' +import { ERROR_KINDS, RECOVERY_MAP } from '../../constants' +import { clickButtonLabeled } from '/app/organisms/ErrorRecoveryFlows/__tests__/util' + +import type { Mock } from 'vitest' + +describe('RetryStepInfo', () => { + let props: React.ComponentProps + let mockHandleMotionRouting: Mock + let mockRetryFailedCommand: Mock + let mockResumeRun: Mock + + beforeEach(() => { + mockHandleMotionRouting = vi.fn(() => Promise.resolve()) + mockRetryFailedCommand = vi.fn(() => Promise.resolve()) + mockResumeRun = vi.fn() + + props = { + routeUpdateActions: { + handleMotionRouting: mockHandleMotionRouting, + } as any, + recoveryCommands: { + retryFailedCommand: mockRetryFailedCommand, + resumeRun: mockResumeRun, + } as any, + errorKind: ERROR_KINDS.GENERAL_ERROR, + } as any + }) + + const render = (props: React.ComponentProps) => { + return renderWithProviders(, { + i18nInstance: i18n, + })[0] + } + + it('calls correct functions when primary button is clicked', async () => { + render(props) + + clickButtonLabeled('Retry now') + + await waitFor(() => { + expect(mockHandleMotionRouting).toHaveBeenCalledWith( + true, + RECOVERY_MAP.ROBOT_RETRYING_STEP.ROUTE + ) + }) + await waitFor(() => { + expect(mockRetryFailedCommand).toHaveBeenCalled() + }) + await waitFor(() => { + expect(mockResumeRun).toHaveBeenCalled() + }) + await waitFor(() => { + expect(mockHandleMotionRouting.mock.invocationCallOrder[0]).toBeLessThan( + mockRetryFailedCommand.mock.invocationCallOrder[0] + ) + }) + await waitFor(() => { + expect(mockRetryFailedCommand.mock.invocationCallOrder[0]).toBeLessThan( + mockResumeRun.mock.invocationCallOrder[0] + ) + }) + }) + + it('renders correct body text for TIP_NOT_DETECTED error', () => { + props.errorKind = ERROR_KINDS.TIP_NOT_DETECTED + + render(props) + + screen.getByText( + 'First, take any necessary actions to prepare the robot to retry the failed tip pickup.' + ) + screen.getByText('Then, close the robot door before proceeding.') + }) + + it('renders correct body text for GRIPPER_ERROR', () => { + props.errorKind = ERROR_KINDS.GRIPPER_ERROR + + render(props) + + screen.getByText( + 'The robot will retry the failed labware movement step from where the labware was replaced on the deck.' + ) + screen.getByText('Close the robot door before proceeding.') + }) + + it('renders default body text for other error kinds', () => { + props.errorKind = ERROR_KINDS.GENERAL_ERROR + + render(props) + + screen.getByText( + 'First, take any necessary actions to prepare the robot to retry the failed step.' + ) + screen.getByText('Then, close the robot door before proceeding.') + }) +}) diff --git a/app/src/organisms/ErrorRecoveryFlows/shared/__tests__/SkipStepInfo.test.tsx b/app/src/organisms/ErrorRecoveryFlows/shared/__tests__/SkipStepInfo.test.tsx new file mode 100644 index 000000000000..fc5acec97b1d --- /dev/null +++ b/app/src/organisms/ErrorRecoveryFlows/shared/__tests__/SkipStepInfo.test.tsx @@ -0,0 +1,104 @@ +import { describe, it, vi, expect, beforeEach } from 'vitest' +import { screen, waitFor } from '@testing-library/react' + +import { renderWithProviders } from '/app/__testing-utils__' +import { i18n } from '/app/i18n' +import { SkipStepInfo } from '../SkipStepInfo' +import { RECOVERY_MAP } from '../../constants' +import { clickButtonLabeled } from '/app/organisms/ErrorRecoveryFlows/__tests__/util' + +import type { Mock } from 'vitest' + +describe('SkipStepInfo', () => { + let props: React.ComponentProps + let mockHandleMotionRouting: Mock + let mockSkipFailedCommand: Mock + + beforeEach(() => { + mockHandleMotionRouting = vi.fn(() => Promise.resolve()) + mockSkipFailedCommand = vi.fn(() => Promise.resolve()) + + props = { + routeUpdateActions: { + handleMotionRouting: mockHandleMotionRouting, + } as any, + recoveryCommands: { + skipFailedCommand: mockSkipFailedCommand, + } as any, + currentRecoveryOptionUtils: { + selectedRecoveryOption: RECOVERY_MAP.SKIP_STEP_WITH_SAME_TIPS.ROUTE, + } as any, + } as any + }) + + const render = (props: React.ComponentProps) => { + return renderWithProviders(, { + i18nInstance: i18n, + })[0] + } + + it('calls correct functions when primary button is clicked', async () => { + render(props) + + clickButtonLabeled('Continue run now') + + await waitFor(() => { + expect(mockHandleMotionRouting).toHaveBeenCalledWith( + true, + RECOVERY_MAP.ROBOT_SKIPPING_STEP.ROUTE + ) + }) + await waitFor(() => { + expect(mockSkipFailedCommand).toHaveBeenCalled() + }) + await waitFor(() => { + expect(mockHandleMotionRouting.mock.invocationCallOrder[0]).toBeLessThan( + mockSkipFailedCommand.mock.invocationCallOrder[0] + ) + }) + }) + + it('renders correct title and body text for SKIP_STEP_WITH_SAME_TIPS', () => { + props.currentRecoveryOptionUtils.selectedRecoveryOption = + RECOVERY_MAP.SKIP_STEP_WITH_SAME_TIPS.ROUTE + render(props) + + screen.getByText('Skip to next step with same tips') + screen.getByText( + 'The failed dispense step will not be completed. The run will continue from the next step with the attached tips.' + ) + screen.getByText('Close the robot door before proceeding.') + }) + + it('renders correct title and body text for SKIP_STEP_WITH_NEW_TIPS', () => { + props.currentRecoveryOptionUtils.selectedRecoveryOption = + RECOVERY_MAP.SKIP_STEP_WITH_NEW_TIPS.ROUTE + render(props) + + screen.getByText('Skip to next step with new tips') + screen.getByText( + 'The failed dispense step will not be completed. The run will continue from the next step with the attached tips.' + ) + screen.getByText('Close the robot door before proceeding.') + }) + + it('renders correct title and body text for MANUAL_MOVE_AND_SKIP', () => { + props.currentRecoveryOptionUtils.selectedRecoveryOption = + RECOVERY_MAP.MANUAL_MOVE_AND_SKIP.ROUTE + render(props) + + screen.getByText('Skip to next step') + screen.getByText( + 'The robot will not attempt to move the labware again. The run will continue from the next step.' + ) + screen.getByText('Close the robot door before proceeding.') + }) + + it('renders error message for unexpected recovery option', () => { + props.currentRecoveryOptionUtils.selectedRecoveryOption = + RECOVERY_MAP.IGNORE_AND_SKIP.ROUTE + render(props) + + expect(screen.getAllByText('UNEXPECTED STEP')[0]).toBeInTheDocument() + }) +})