From 529efc54d01012f6eb75c45f8d19c739394ff708 Mon Sep 17 00:00:00 2001 From: Jamey Huffnagle Date: Tue, 13 Feb 2024 14:16:14 -0500 Subject: [PATCH] fix(app): fix RecentRunProtocolCard redirecting to /protocols before /runs/:runId/setup Notification changes uncovered a bug in which a RecentRunProtocolCard caused redirection to the /runs/:runId/setup page before the actual run had loaded, which caused the TopLevelRedirect hook to bounce back to the /protocols page until the run loads. Instead of relying on run within TopLevelRedirect for this one off route case, move the redirect within ProtocolSetup and redirect if run status is stopped. This creates the same end behavior without the temporary redirect to /protocols. --- app/src/App/hooks.ts | 4 ---- .../__tests__/ProtocolSetup.test.tsx | 17 ++++++++++++++++- app/src/pages/ProtocolSetup/index.tsx | 8 ++++++-- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/app/src/App/hooks.ts b/app/src/App/hooks.ts index 4c0faf2c7e8..cbc40b396eb 100644 --- a/app/src/App/hooks.ts +++ b/app/src/App/hooks.ts @@ -2,7 +2,6 @@ import * as React from 'react' import difference from 'lodash/difference' import { useTranslation } from 'react-i18next' import { useQueryClient } from 'react-query' -import { useRouteMatch } from 'react-router-dom' import { useDispatch } from 'react-redux' import { useInterval, truncateString } from '@opentrons/components' @@ -146,9 +145,6 @@ export function useCurrentRunRoute(): string | null { enabled: currentRunId != null, }) - const isRunSetupRoute = useRouteMatch('/runs/:runId/setup') - if (isRunSetupRoute != null && runRecord == null) return '/protocols' - const runStatus = runRecord?.data.status const runActions = runRecord?.data.actions if (runRecord == null || runStatus == null || runActions == null) return null diff --git a/app/src/pages/ProtocolSetup/__tests__/ProtocolSetup.test.tsx b/app/src/pages/ProtocolSetup/__tests__/ProtocolSetup.test.tsx index ca6d6b275f0..d08d1d010d0 100644 --- a/app/src/pages/ProtocolSetup/__tests__/ProtocolSetup.test.tsx +++ b/app/src/pages/ProtocolSetup/__tests__/ProtocolSetup.test.tsx @@ -4,7 +4,7 @@ import { MemoryRouter } from 'react-router-dom' import { fireEvent, screen } from '@testing-library/react' import { when, resetAllWhenMocks } from 'jest-when' -import { RUN_STATUS_IDLE } from '@opentrons/api-client' +import { RUN_STATUS_IDLE, RUN_STATUS_STOPPED } from '@opentrons/api-client' import { useAllPipetteOffsetCalibrationsQuery, useInstrumentsQuery, @@ -72,6 +72,8 @@ Object.defineProperty(window, 'IntersectionObserver', { value: IntersectionObserver, }) +let mockHistoryPush: jest.Mock + jest.mock('@opentrons/shared-data/js/helpers') jest.mock('@opentrons/react-api-client') jest.mock('../../../organisms/LabwarePositionCheck/useLaunchLPC') @@ -91,6 +93,12 @@ jest.mock('../ConfirmAttachedModal') jest.mock('../../../organisms/ToasterOven') jest.mock('../../../resources/deck_configuration/hooks') jest.mock('../../../resources/runs/useNotifyRunQuery') +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useHistory: () => ({ + push: mockHistoryPush, + }), +})) const mockGetDeckDefFromRobotType = getDeckDefFromRobotType as jest.MockedFunction< typeof getDeckDefFromRobotType @@ -252,6 +260,7 @@ describe('ProtocolSetup', () => { let mockLaunchLPC: jest.Mock beforeEach(() => { mockLaunchLPC = jest.fn() + mockHistoryPush = jest.fn() mockUseLPCDisabledReason.mockReturnValue(null) mockUseAttachedModules.mockReturnValue([]) mockProtocolSetupModulesAndDeck.mockReturnValue( @@ -462,4 +471,10 @@ describe('ProtocolSetup', () => { properties: {}, }) }) + + it('should redirect to the protocols page when a run is stopped', () => { + mockUseRunStatus.mockReturnValue(RUN_STATUS_STOPPED) + render(`/runs/${RUN_ID}/setup/`) + expect(mockHistoryPush).toHaveBeenCalledWith('/protocols') + }) }) diff --git a/app/src/pages/ProtocolSetup/index.tsx b/app/src/pages/ProtocolSetup/index.tsx index 950eb60991e..e305920746f 100644 --- a/app/src/pages/ProtocolSetup/index.tsx +++ b/app/src/pages/ProtocolSetup/index.tsx @@ -269,6 +269,11 @@ function PrepareToRun({ } ) + const runStatus = useRunStatus(runId) + if (runStatus === RUN_STATUS_STOPPED) { + history.push('/protocols') + } + React.useEffect(() => { if (mostRecentAnalysis?.status === 'completed') { setIsPollingForCompletedAnalysis(false) @@ -305,7 +310,6 @@ function PrepareToRun({ const protocolHasFixtures = requiredFixtures.length > 0 - const runStatus = useRunStatus(runId) const isHeaterShakerInProtocol = useIsHeaterShakerInProtocol() const deckDef = getDeckDefFromRobotType(robotType) @@ -450,7 +454,7 @@ function PrepareToRun({ if ( isHeaterShakerInProtocol && isReadyToRun && - (runStatus === RUN_STATUS_IDLE || runStatus === RUN_STATUS_STOPPED) + runStatus === RUN_STATUS_IDLE ) { confirmAttachment() } else {