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

fix(app): Fix persistent cancelled state #14228

Merged
merged 3 commits into from
Dec 15, 2023
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
16 changes: 13 additions & 3 deletions app/src/organisms/Devices/ProtocolRun/ProtocolRunHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ import { RunProgressMeter } from '../../RunProgressMeter'
import { getIsFixtureMismatch } from '../../../resources/deck_configuration/utils'
import { useDeckConfigurationCompatibility } from '../../../resources/deck_configuration/hooks'
import { useMostRecentCompletedAnalysis } from '../../LabwarePositionCheck/useMostRecentCompletedAnalysis'
import { useMostRecentRunId } from '../../ProtocolUpload/hooks/useMostRecentRunId'

import type { Run, RunError } from '@opentrons/api-client'
import type { State } from '../../../redux/types'
Expand Down Expand Up @@ -161,6 +162,7 @@ export function ProtocolRunHeader({
const { analysisErrors } = useProtocolAnalysisErrors(runId)
const { data: attachedInstruments } = useInstrumentsQuery()
const isRunCurrent = Boolean(useRunQuery(runId)?.data?.data?.current)
const mostRecentRunId = useMostRecentRunId()
const { closeCurrentRun, isClosingCurrentRun } = useCloseCurrentRun()
const { startedAt, stoppedAt, completedAt } = useRunTimestamps(runId)
const [showRunFailedModal, setShowRunFailedModal] = React.useState(false)
Expand Down Expand Up @@ -249,8 +251,9 @@ export function ProtocolRunHeader({
...robotAnalyticsData,
},
})
closeCurrentRun()
}
}, [runStatus, isRunCurrent, runId])
}, [runStatus, isRunCurrent, runId, closeCurrentRun])

const startedAtTimestamp =
startedAt != null ? formatTimestamp(startedAt) : EMPTY_TIMESTAMP
Expand Down Expand Up @@ -372,7 +375,9 @@ export function ProtocolRunHeader({
}}
/>
) : null}
{isRunCurrent && showDropTipBanner && pipettesWithTip.length !== 0 ? (
{mostRecentRunId === runId &&
showDropTipBanner &&
pipettesWithTip.length !== 0 ? (
<ProtocolDropTipBanner
onLaunchWizardClick={setShowDropTipWizard}
onCloseClick={() => {
Expand Down Expand Up @@ -786,6 +791,11 @@ function TerminalRunBanner(props: TerminalRunProps): JSX.Element | null {
} = props
const { t } = useTranslation('run_details')

const handleClick = (): void => {
handleClearClick()
setShowRunFailedModal(true)
}

if (runStatus === RUN_STATUS_FAILED || runStatus === RUN_STATUS_SUCCEEDED) {
return (
<>
Expand All @@ -810,7 +820,7 @@ function TerminalRunBanner(props: TerminalRunProps): JSX.Element | null {
</StyledText>

<LinkButton
onClick={() => setShowRunFailedModal(true)}
onClick={handleClick}
textDecoration={TYPOGRAPHY.textDecorationUnderline}
>
{t('view_error')}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
useRunQuery,
useModulesQuery,
usePipettesQuery,
useDismissCurrentRunMutation,
useEstopQuery,
useDoorQuery,
useInstrumentsQuery,
Expand Down Expand Up @@ -91,6 +92,7 @@ import { getPipettesWithTipAttached } from '../../../DropTipWizard/getPipettesWi
import { getIsFixtureMismatch } from '../../../../resources/deck_configuration/utils'
import { useDeckConfigurationCompatibility } from '../../../../resources/deck_configuration/hooks'
import { useMostRecentCompletedAnalysis } from '../../../LabwarePositionCheck/useMostRecentCompletedAnalysis'
import { useMostRecentRunId } from '../../../ProtocolUpload/hooks/useMostRecentRunId'

import type { UseQueryResult } from 'react-query'
import type { Run } from '@opentrons/api-client'
Expand Down Expand Up @@ -139,6 +141,7 @@ jest.mock('../../../DropTipWizard/getPipettesWithTipAttached')
jest.mock('../../../../resources/deck_configuration/utils')
jest.mock('../../../../resources/deck_configuration/hooks')
jest.mock('../../../LabwarePositionCheck/useMostRecentCompletedAnalysis')
jest.mock('../../../ProtocolUpload/hooks/useMostRecentRunId')

const mockGetIsHeaterShakerAttached = getIsHeaterShakerAttached as jest.MockedFunction<
typeof getIsHeaterShakerAttached
Expand Down Expand Up @@ -189,6 +192,9 @@ const mockUsePipettesQuery = usePipettesQuery as jest.MockedFunction<
const mockConfirmCancelModal = ConfirmCancelModal as jest.MockedFunction<
typeof ConfirmCancelModal
>
const mockUseDismissCurrentRunMutation = useDismissCurrentRunMutation as jest.MockedFunction<
typeof useDismissCurrentRunMutation
>
const mockHeaterShakerIsRunningModal = HeaterShakerIsRunningModal as jest.MockedFunction<
typeof HeaterShakerIsRunningModal
>
Expand Down Expand Up @@ -242,6 +248,9 @@ const mockUseDeckConfigurationCompatibility = useDeckConfigurationCompatibility
const mockUseMostRecentCompletedAnalysis = useMostRecentCompletedAnalysis as jest.MockedFunction<
typeof useMostRecentCompletedAnalysis
>
const mockUseMostRecentRunId = useMostRecentRunId as jest.MockedFunction<
typeof useMostRecentRunId
>

const ROBOT_NAME = 'otie'
const RUN_ID = '95e67900-bc9f-4fbf-92c6-cc4d7226a51b'
Expand Down Expand Up @@ -398,6 +407,11 @@ describe('ProtocolRunHeader', () => {
when(mockUseTrackProtocolRunEvent).calledWith(RUN_ID).mockReturnValue({
trackProtocolRunEvent: mockTrackProtocolRunEvent,
})
when(mockUseDismissCurrentRunMutation)
.calledWith()
.mockReturnValue({
dismissCurrentRun: jest.fn(),
} as any)
when(mockUseUnmatchedModulesForProtocol)
.calledWith(ROBOT_NAME, RUN_ID)
.mockReturnValue({ missingModuleIds: [], remainingAttachedModules: [] })
Expand Down Expand Up @@ -429,6 +443,7 @@ describe('ProtocolRunHeader', () => {
} as any)
mockUseDeckConfigurationCompatibility.mockReturnValue([])
when(mockGetIsFixtureMismatch).mockReturnValue(false)
when(mockUseMostRecentRunId).mockReturnValue(RUN_ID)
})

afterEach(() => {
Expand Down Expand Up @@ -514,7 +529,7 @@ describe('ProtocolRunHeader', () => {
data: { data: { ...mockIdleUnstartedRun, current: true } },
} as UseQueryResult<Run>)
render()
expect(mockCloseCurrentRun).not.toBeCalled()
expect(mockCloseCurrentRun).toBeCalled()
expect(mockTrackProtocolRunEvent).toBeCalled()
expect(mockTrackProtocolRunEvent).toBeCalledWith({
name: ANALYTICS_PROTOCOL_RUN_FINISH,
Expand Down Expand Up @@ -822,7 +837,7 @@ describe('ProtocolRunHeader', () => {
const [{ getByText }] = render()

getByText('View error').click()
expect(mockCloseCurrentRun).not.toHaveBeenCalled()
expect(mockCloseCurrentRun).toBeCalled()
getByText('mock RunFailedModal')
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ import {
Flex,
SPACING,
} from '@opentrons/components'
import { useStopRunMutation } from '@opentrons/react-api-client'
import {
useStopRunMutation,
useDismissCurrentRunMutation,
} from '@opentrons/react-api-client'

import { StyledText } from '../../../atoms/text'
import { SmallButton } from '../../../atoms/buttons'
Expand All @@ -37,6 +40,10 @@ export function ConfirmCancelRunModal({
}: ConfirmCancelRunModalProps): JSX.Element {
const { t } = useTranslation(['run_details', 'shared'])
const { stopRun } = useStopRunMutation()
const {
dismissCurrentRun,
isLoading: isDismissing,
} = useDismissCurrentRunMutation()
const runStatus = useRunStatus(runId)
const { trackProtocolRunEvent } = useTrackProtocolRunEvent(runId)
const history = useHistory()
Expand All @@ -61,6 +68,7 @@ export function ConfirmCancelRunModal({
React.useEffect(() => {
if (runStatus === RUN_STATUS_STOPPED) {
trackProtocolRunEvent({ name: ANALYTICS_PROTOCOL_RUN_CANCEL })
dismissCurrentRun(runId)
if (!isActiveRun) {
if (protocolId != null) {
history.push(`/protocols/${protocolId}`)
Expand All @@ -71,7 +79,7 @@ export function ConfirmCancelRunModal({
}
}, [runStatus])

return isCanceling ? (
return isCanceling || isDismissing ? (
<CancelingRunModal />
) : (
<Modal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,15 @@ describe('ConfirmCancelRunModal', () => {
getByText('Cancel run')
})

it('shoudler render the canceling run modal when run is dismissing', () => {
mockUseDismissCurrentRunMutation.mockReturnValue({
dismissCurrentRun: mockDismissCurrentRun,
isLoading: true,
} as any)
const [{ getByText }] = render(props)
getByText('mock CancelingRunModal')
})

it('when tapping go back, the mock function is called', () => {
const [{ getByText }] = render(props)
const button = getByText('Go back')
Expand All @@ -138,7 +147,7 @@ describe('ConfirmCancelRunModal', () => {
.mockReturnValue(RUN_STATUS_STOPPED)
render(props)

expect(mockDismissCurrentRun).not.toHaveBeenCalled()
expect(mockDismissCurrentRun).toHaveBeenCalled()
expect(mockTrackProtocolRunEvent).toHaveBeenCalled()
})

Expand All @@ -152,7 +161,7 @@ describe('ConfirmCancelRunModal', () => {
.mockReturnValue(RUN_STATUS_STOPPED)
render(props)

expect(mockDismissCurrentRun).not.toHaveBeenCalled()
expect(mockDismissCurrentRun).toHaveBeenCalled()
expect(mockTrackProtocolRunEvent).toHaveBeenCalled()
expect(mockPush).toHaveBeenCalledWith('/protocols')
})
Expand Down
8 changes: 7 additions & 1 deletion app/src/pages/OnDeviceDisplay/RunSummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import { formatTimeWithUtcLabel } from '../../resources/runs/utils'
import { handleTipsAttachedModal } from '../../organisms/DropTipWizard/TipsAttachedModal'
import { getPipettesWithTipAttached } from '../../organisms/DropTipWizard/getPipettesWithTipAttached'
import { getPipetteModelSpecs, FLEX_ROBOT_TYPE } from '@opentrons/shared-data'
import { useMostRecentRunId } from '../../organisms/ProtocolUpload/hooks/useMostRecentRunId'

import type { OnDeviceRouteParams } from '../../App/types'
import type { PipetteModelSpecs } from '@opentrons/shared-data'
Expand All @@ -79,6 +80,7 @@ export function RunSummary(): JSX.Element {
const host = useHost()
const { data: runRecord } = useRunQuery(runId, { staleTime: Infinity })
const isRunCurrent = Boolean(runRecord?.data?.current)
const mostRecentRunId = useMostRecentRunId()
const { data: attachedInstruments } = useInstrumentsQuery()
const runStatus = runRecord?.data.status ?? null
const didRunSucceed = runStatus === RUN_STATUS_SUCCEEDED
Expand Down Expand Up @@ -130,7 +132,11 @@ export function RunSummary(): JSX.Element {

const handleReturnToDash = (): void => {
const { mount, specs } = pipettesWithTip[0] || {}
if (isRunCurrent && pipettesWithTip.length !== 0 && specs != null) {
if (
mostRecentRunId === runId &&
pipettesWithTip.length !== 0 &&
specs != null
) {
handleTipsAttachedModal(
mount,
specs,
Expand Down
Loading