From 7c3a8c6c8dd136dedc33d89e2d2395a0246e937e Mon Sep 17 00:00:00 2001 From: Brian Cooper Date: Thu, 16 May 2024 14:35:11 -0400 Subject: [PATCH 1/7] refactor(app): make on device display deck configurator updates live Instead of the previous method of staging a batch of changes to deck configuration before commiting them with the confirm button, to avoid synchronization issues, make the ODD deck configurator behave like the desktop version. all updates immediately permeate to the robot's source of truth --- app/src/assets/localization/en/shared.json | 1 + .../AddFixtureModal.tsx | 42 +--- .../DeviceDetailsDeckConfiguration/index.tsx | 86 +------- app/src/pages/DeckConfiguration/index.tsx | 131 ++---------- app/src/resources/deck_configuration/hooks.ts | 102 --------- .../resources/deck_configuration/hooks.tsx | 193 ++++++++++++++++++ 6 files changed, 227 insertions(+), 328 deletions(-) delete mode 100644 app/src/resources/deck_configuration/hooks.ts create mode 100644 app/src/resources/deck_configuration/hooks.tsx diff --git a/app/src/assets/localization/en/shared.json b/app/src/assets/localization/en/shared.json index 5613508b242..899adfc5a31 100644 --- a/app/src/assets/localization/en/shared.json +++ b/app/src/assets/localization/en/shared.json @@ -63,6 +63,7 @@ "robot_is_busy": "Robot is busy", "robot_is_reachable_but_not_responding": "This robot's API server is not responding correctly to requests at IP address {{hostname}}", "robot_was_seen_but_is_unreachable": "This robot has been seen recently, but is currently not reachable at IP address {{hostname}}", + "save": "save", "something_went_wrong": "something went wrong", "sort_by": "Sort by", "stand_back_robot_is_in_motion": "Stand back, robot is in motion", diff --git a/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.tsx b/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.tsx index 47ec3077d61..bc79ef78a6b 100644 --- a/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.tsx +++ b/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.tsx @@ -54,15 +54,13 @@ import type { CutoutConfig, CutoutId, CutoutFixtureId, - DeckConfiguration, } from '@opentrons/shared-data' import type { ModalHeaderBaseProps } from '../../molecules/Modal/types' import type { LegacyModalProps } from '../../molecules/LegacyModal' interface AddFixtureModalProps { cutoutId: CutoutId - setShowAddFixtureModal: (showAddFixtureModal: boolean) => void - setCurrentDeckConfig?: React.Dispatch> + closeModal: () => void providedFixtureOptions?: CutoutFixtureId[] isOnDevice?: boolean } @@ -75,8 +73,7 @@ type OptionStage = export function AddFixtureModal({ cutoutId, - setShowAddFixtureModal, - setCurrentDeckConfig, + closeModal, providedFixtureOptions, isOnDevice = false, }: AddFixtureModalProps): JSX.Element { @@ -109,18 +106,14 @@ export function AddFixtureModal({ slotName: getCutoutDisplayName(cutoutId), }), hasExitIcon: providedFixtureOptions == null, - onClick: () => { - setShowAddFixtureModal(false) - }, + onClick: closeModal, } const modalProps: LegacyModalProps = { title: t('add_to_slot', { slotName: getCutoutDisplayName(cutoutId), }), - onClose: () => { - setShowAddFixtureModal(false) - }, + onClose: closeModal, closeOnOutsideClick: true, childrenPadding: SPACING.spacing24, width: '26.75rem', @@ -289,22 +282,7 @@ export function AddFixtureModal({ ) } - const handleAddODD = (addedCutoutConfigs: CutoutConfig[]): void => { - if (setCurrentDeckConfig != null) - setCurrentDeckConfig( - (prevDeckConfig: DeckConfiguration): DeckConfiguration => - prevDeckConfig.map((fixture: CutoutConfig) => { - const replacementCutoutConfig = addedCutoutConfigs.find( - c => c.cutoutId === fixture.cutoutId - ) - return replacementCutoutConfig ?? fixture - }) - ) - - setShowAddFixtureModal(false) - } - - const handleAddDesktop = (addedCutoutConfigs: CutoutConfig[]): void => { + const handleAddFixture = (addedCutoutConfigs: CutoutConfig[]): void => { const newDeckConfig = deckConfig.map(fixture => { const replacementCutoutConfig = addedCutoutConfigs.find( c => c.cutoutId === fixture.cutoutId @@ -313,7 +291,7 @@ export function AddFixtureModal({ }) updateDeckConfiguration(newDeckConfig) - setShowAddFixtureModal(false) + closeModal() } const fixtureOptions = availableOptions.map(cutoutConfigs => ( @@ -326,11 +304,7 @@ export function AddFixtureModal({ )?.usbPort.port )} buttonText={t('add')} - onClickHandler={() => { - isOnDevice - ? handleAddODD(cutoutConfigs) - : handleAddDesktop(cutoutConfigs) - }} + onClickHandler={() => { handleAddFixture(cutoutConfigs) }} isOnDevice={isOnDevice} /> )) @@ -343,7 +317,7 @@ export function AddFixtureModal({ onOutsideClick={() => providedFixtureOptions != null ? null - : setShowAddFixtureModal(false) + : closeModal() } > diff --git a/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx b/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx index b6f62c8c08a..d17b0cf1d57 100644 --- a/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx +++ b/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx @@ -26,12 +26,7 @@ import { import { getCutoutDisplayName, getFixtureDisplayName, - SINGLE_RIGHT_CUTOUTS, SINGLE_SLOT_FIXTURES, - SINGLE_LEFT_SLOT_FIXTURE, - SINGLE_RIGHT_SLOT_FIXTURE, - SINGLE_CENTER_SLOT_FIXTURE, - SINGLE_LEFT_CUTOUTS, getDeckDefFromRobotType, FLEX_ROBOT_TYPE, } from '@opentrons/shared-data' @@ -39,12 +34,11 @@ import { import { useNotifyCurrentMaintenanceRun } from '../../resources/maintenance_runs' import { Banner } from '../../atoms/Banner' import { DeckFixtureSetupInstructionsModal } from './DeckFixtureSetupInstructionsModal' -import { AddFixtureModal } from './AddFixtureModal' import { useIsRobotViewable, useRunStatuses } from '../Devices/hooks' import { useIsEstopNotDisengaged } from '../../resources/devices/hooks/useIsEstopNotDisengaged' -import { useNotifyDeckConfigurationQuery } from '../../resources/deck_configuration' +import { useDeckConfigurationEditingTools, useNotifyDeckConfigurationQuery } from '../../resources/deck_configuration' -import type { CutoutFixtureId, CutoutId } from '@opentrons/shared-data' +import type { CutoutId } from '@opentrons/shared-data' const DECK_CONFIG_REFETCH_INTERVAL = 5000 const RUN_REFETCH_INTERVAL = 5000 @@ -65,12 +59,6 @@ export function DeviceDetailsDeckConfiguration({ showSetupInstructionsModal, setShowSetupInstructionsModal, ] = React.useState(false) - const [showAddFixtureModal, setShowAddFixtureModal] = React.useState( - false - ) - const [targetCutoutId, setTargetCutoutId] = React.useState( - null - ) const { data: modulesData } = useModulesQuery() const deckConfig = @@ -78,7 +66,6 @@ export function DeviceDetailsDeckConfiguration({ refetchInterval: DECK_CONFIG_REFETCH_INTERVAL, }).data ?? [] const deckDef = getDeckDefFromRobotType(FLEX_ROBOT_TYPE) - const { updateDeckConfiguration } = useUpdateDeckConfigurationMutation() const { isRunRunning } = useRunStatuses() const { data: maintenanceRunData } = useNotifyCurrentMaintenanceRun({ refetchInterval: RUN_REFETCH_INTERVAL, @@ -87,59 +74,11 @@ export function DeviceDetailsDeckConfiguration({ const isMaintenanceRunExisting = maintenanceRunData?.data?.id != null const isRobotViewable = useIsRobotViewable(robotName) - const handleClickAdd = (cutoutId: CutoutId): void => { - setTargetCutoutId(cutoutId) - setShowAddFixtureModal(true) - } - - const handleClickRemove = ( - cutoutId: CutoutId, - cutoutFixtureId: CutoutFixtureId - ): void => { - let replacementFixtureId: CutoutFixtureId = SINGLE_CENTER_SLOT_FIXTURE - if (SINGLE_RIGHT_CUTOUTS.includes(cutoutId)) { - replacementFixtureId = SINGLE_RIGHT_SLOT_FIXTURE - } else if (SINGLE_LEFT_CUTOUTS.includes(cutoutId)) { - replacementFixtureId = SINGLE_LEFT_SLOT_FIXTURE - } - - const fixtureGroup = - deckDef.cutoutFixtures.find(cf => cf.id === cutoutFixtureId) - ?.fixtureGroup ?? {} - - let newDeckConfig = deckConfig - if (cutoutId in fixtureGroup) { - const groupMap = - fixtureGroup[cutoutId]?.find(group => - Object.entries(group).every(([cId, cfId]) => - deckConfig.find( - config => - config.cutoutId === cId && config.cutoutFixtureId === cfId - ) - ) - ) ?? {} - newDeckConfig = deckConfig.map(cutoutConfig => - cutoutConfig.cutoutId in groupMap - ? { - ...cutoutConfig, - cutoutFixtureId: replacementFixtureId, - opentronsModuleSerialNumber: undefined, - } - : cutoutConfig - ) - } else { - newDeckConfig = deckConfig.map(cutoutConfig => - cutoutConfig.cutoutId === cutoutId - ? { - ...cutoutConfig, - cutoutFixtureId: replacementFixtureId, - opentronsModuleSerialNumber: undefined, - } - : cutoutConfig - ) - } - updateDeckConfiguration(newDeckConfig) - } + const { + addFixtureToCutout, + removeFixtureFromCutout, + addFixtureModal, + } = useDeckConfigurationEditingTools(false) // do not show standard slot in fixture display list const { displayList: fixtureDisplayList } = deckConfig.reduce<{ @@ -199,12 +138,7 @@ export function DeviceDetailsDeckConfiguration({ return ( <> - {showAddFixtureModal && targetCutoutId != null ? ( - - ) : null} + {addFixtureModal} {showSetupInstructionsModal ? ( cutoutId) } deckConfig={deckConfig} - handleClickAdd={handleClickAdd} - handleClickRemove={handleClickRemove} + handleClickAdd={addFixtureToCutout} + handleClickRemove={removeFixtureFromCutout} /> (false) - const [ - showConfigurationModal, - setShowConfigurationModal, - ] = React.useState(false) - const [targetCutoutId, setTargetCutoutId] = React.useState( - null - ) + + const isOnDevice = true + const { + addFixtureToCutout, + removeFixtureFromCutout, + addFixtureModal, + } = useDeckConfigurationEditingTools(isOnDevice) + const [ showDiscardChangeModal, setShowDiscardChangeModal, ] = React.useState(false) - const deckDef = getDeckDefFromRobotType(FLEX_ROBOT_TYPE) const deckConfig = useNotifyDeckConfigurationQuery().data ?? [] - const { updateDeckConfiguration } = useUpdateDeckConfigurationMutation() - - const [ - currentDeckConfig, - setCurrentDeckConfig, - ] = React.useState(deckConfig) - - const handleClickAdd = (cutoutId: CutoutId): void => { - setTargetCutoutId(cutoutId) - setShowConfigurationModal(true) - } - - const handleClickRemove = ( - cutoutId: CutoutId, - cutoutFixtureId: CutoutFixtureId - ): void => { - let replacementFixtureId: CutoutFixtureId = SINGLE_CENTER_SLOT_FIXTURE - if (SINGLE_RIGHT_CUTOUTS.includes(cutoutId)) { - replacementFixtureId = SINGLE_RIGHT_SLOT_FIXTURE - } else if (SINGLE_LEFT_CUTOUTS.includes(cutoutId)) { - replacementFixtureId = SINGLE_LEFT_SLOT_FIXTURE - } - - const fixtureGroup = - deckDef.cutoutFixtures.find(cf => cf.id === cutoutFixtureId) - ?.fixtureGroup ?? {} - - let newDeckConfig = currentDeckConfig - if (cutoutId in fixtureGroup) { - const groupMap = - fixtureGroup[cutoutId]?.find(group => - Object.entries(group).every(([cId, cfId]) => - currentDeckConfig.find( - config => - config.cutoutId === cId && config.cutoutFixtureId === cfId - ) - ) - ) ?? {} - newDeckConfig = currentDeckConfig.map(cutoutConfig => - cutoutConfig.cutoutId in groupMap - ? { - ...cutoutConfig, - cutoutFixtureId: replacementFixtureId, - opentronsModuleSerialNumber: undefined, - } - : cutoutConfig - ) - } else { - newDeckConfig = currentDeckConfig.map(cutoutConfig => - cutoutConfig.cutoutId === cutoutId - ? { - ...cutoutConfig, - cutoutFixtureId: replacementFixtureId, - opentronsModuleSerialNumber: undefined, - } - : cutoutConfig - ) - } - setCurrentDeckConfig(newDeckConfig) - } const handleClickConfirm = (): void => { - if (!isEqual(deckConfig, currentDeckConfig)) { - updateDeckConfiguration(currentDeckConfig) - } history.goBack() } - const handleClickBack = (): void => { - if (!isEqual(deckConfig, currentDeckConfig)) { - setShowDiscardChangeModal(true) - } else { - history.goBack() - } - } - const secondaryButtonProps: React.ComponentProps = { onClick: () => setShowSetupInstructionsModal(true), buttonText: i18n.format(t('setup_instructions'), 'titleCase'), @@ -145,10 +56,6 @@ export function DeckConfigurationEditor(): JSX.Element { iconPlacement: 'startIcon', } - React.useEffect(() => { - setCurrentDeckConfig(deckConfig) - }, [deckConfig]) - return ( <> {createPortal( @@ -161,17 +68,10 @@ export function DeckConfigurationEditor(): JSX.Element { {showSetupInstructionsModal ? ( - ) : null} - {showConfigurationModal && targetCutoutId != null ? ( - ) : null} + {addFixtureModal} , getTopPortalEl() )} @@ -181,16 +81,15 @@ export function DeckConfigurationEditor(): JSX.Element { > diff --git a/app/src/resources/deck_configuration/hooks.ts b/app/src/resources/deck_configuration/hooks.ts deleted file mode 100644 index ed48b705c5c..00000000000 --- a/app/src/resources/deck_configuration/hooks.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { getInitialAndMovedLabwareInSlots } from '@opentrons/components' -import { - FLEX_ROBOT_TYPE, - getAddressableAreasInProtocol, - getCutoutFixturesForCutoutId, - getCutoutIdForAddressableArea, - getDeckDefFromRobotType, - getLabwareDisplayName, - SINGLE_SLOT_FIXTURES, -} from '@opentrons/shared-data' - -import type { - CompletedProtocolAnalysis, - CutoutConfigProtocolSpec, - CutoutFixtureId, - ProtocolAnalysisOutput, - RobotType, -} from '@opentrons/shared-data' - -import { useNotifyDeckConfigurationQuery } from './useNotifyDeckConfigurationQuery' - -const DECK_CONFIG_REFETCH_INTERVAL = 5000 - -export interface CutoutConfigAndCompatibility extends CutoutConfigProtocolSpec { - compatibleCutoutFixtureIds: CutoutFixtureId[] - // the missing on-deck labware display name for a single slot cutout - missingLabwareDisplayName: string | null -} -export function useDeckConfigurationCompatibility( - robotType: RobotType, - protocolAnalysis: CompletedProtocolAnalysis | ProtocolAnalysisOutput | null -): CutoutConfigAndCompatibility[] { - const deckConfig = - useNotifyDeckConfigurationQuery({ - refetchInterval: DECK_CONFIG_REFETCH_INTERVAL, - }).data ?? [] - if (robotType !== FLEX_ROBOT_TYPE) return [] - const deckDef = getDeckDefFromRobotType(robotType) - const allAddressableAreas = - protocolAnalysis != null - ? getAddressableAreasInProtocol(protocolAnalysis, deckDef) - : [] - const labwareInSlots = - protocolAnalysis != null - ? getInitialAndMovedLabwareInSlots(protocolAnalysis) - : [] - - return deckConfig.reduce( - (acc, { cutoutId, cutoutFixtureId }) => { - const fixturesThatMountToCutoutId = getCutoutFixturesForCutoutId( - cutoutId, - deckDef.cutoutFixtures - ) - const requiredAddressableAreasForCutoutId = allAddressableAreas.filter( - aa => - getCutoutIdForAddressableArea(aa, fixturesThatMountToCutoutId) === - cutoutId - ) - const compatibleCutoutFixtureIds = fixturesThatMountToCutoutId - .filter(cf => - requiredAddressableAreasForCutoutId.every(aa => - cf.providesAddressableAreas[cutoutId].includes(aa) - ) - ) - .map(cf => cf.id) - - // get the on-deck labware name for a missing single-slot addressable area - const missingSingleSlotLabware = - cutoutFixtureId != null && - // fixture mismatch - !compatibleCutoutFixtureIds.includes(cutoutFixtureId) && - compatibleCutoutFixtureIds[0] != null && - // compatible fixture is single-slot - SINGLE_SLOT_FIXTURES.includes(compatibleCutoutFixtureIds[0]) - ? labwareInSlots.find( - ({ location }) => - // match the addressable area to an on-deck labware - requiredAddressableAreasForCutoutId[0] === location.slotName - ) - : null - - const missingLabwareDisplayName = - missingSingleSlotLabware != null - ? missingSingleSlotLabware.labwareNickName ?? - getLabwareDisplayName(missingSingleSlotLabware.labwareDef) ?? - null - : null - - return [ - ...acc, - { - cutoutId, - cutoutFixtureId, - requiredAddressableAreas: requiredAddressableAreasForCutoutId, - compatibleCutoutFixtureIds, - missingLabwareDisplayName, - }, - ] - }, - [] - ) -} diff --git a/app/src/resources/deck_configuration/hooks.tsx b/app/src/resources/deck_configuration/hooks.tsx new file mode 100644 index 00000000000..9f3bf0a337f --- /dev/null +++ b/app/src/resources/deck_configuration/hooks.tsx @@ -0,0 +1,193 @@ +import * as React from 'react' +import { getInitialAndMovedLabwareInSlots } from '@opentrons/components' +import { + FLEX_ROBOT_TYPE, + getAddressableAreasInProtocol, + getCutoutFixturesForCutoutId, + getCutoutIdForAddressableArea, + getDeckDefFromRobotType, + getLabwareDisplayName, + SINGLE_CENTER_SLOT_FIXTURE, + SINGLE_LEFT_CUTOUTS, + SINGLE_LEFT_SLOT_FIXTURE, + SINGLE_RIGHT_CUTOUTS, + SINGLE_RIGHT_SLOT_FIXTURE, + SINGLE_SLOT_FIXTURES, +} from '@opentrons/shared-data' + +import type { + CompletedProtocolAnalysis, + CutoutConfigProtocolSpec, + CutoutFixtureId, + CutoutId, + ProtocolAnalysisOutput, + RobotType, +} from '@opentrons/shared-data' + +import { useNotifyDeckConfigurationQuery } from './useNotifyDeckConfigurationQuery' +import { AddFixtureModal } from '../../organisms/DeviceDetailsDeckConfiguration/AddFixtureModal' +import { useUpdateDeckConfigurationMutation } from '@opentrons/react-api-client' + +const DECK_CONFIG_REFETCH_INTERVAL = 5000 + +export interface CutoutConfigAndCompatibility extends CutoutConfigProtocolSpec { + compatibleCutoutFixtureIds: CutoutFixtureId[] + // the missing on-deck labware display name for a single slot cutout + missingLabwareDisplayName: string | null +} +export function useDeckConfigurationCompatibility( + robotType: RobotType, + protocolAnalysis: CompletedProtocolAnalysis | ProtocolAnalysisOutput | null +): CutoutConfigAndCompatibility[] { + const deckConfig = + useNotifyDeckConfigurationQuery({ + refetchInterval: DECK_CONFIG_REFETCH_INTERVAL, + }).data ?? [] + if (robotType !== FLEX_ROBOT_TYPE) return [] + const deckDef = getDeckDefFromRobotType(robotType) + const allAddressableAreas = + protocolAnalysis != null + ? getAddressableAreasInProtocol(protocolAnalysis, deckDef) + : [] + const labwareInSlots = + protocolAnalysis != null + ? getInitialAndMovedLabwareInSlots(protocolAnalysis) + : [] + + return deckConfig.reduce( + (acc, { cutoutId, cutoutFixtureId }) => { + const fixturesThatMountToCutoutId = getCutoutFixturesForCutoutId( + cutoutId, + deckDef.cutoutFixtures + ) + const requiredAddressableAreasForCutoutId = allAddressableAreas.filter( + aa => + getCutoutIdForAddressableArea(aa, fixturesThatMountToCutoutId) === + cutoutId + ) + const compatibleCutoutFixtureIds = fixturesThatMountToCutoutId + .filter(cf => + requiredAddressableAreasForCutoutId.every(aa => + cf.providesAddressableAreas[cutoutId].includes(aa) + ) + ) + .map(cf => cf.id) + + // get the on-deck labware name for a missing single-slot addressable area + const missingSingleSlotLabware = + cutoutFixtureId != null && + // fixture mismatch + !compatibleCutoutFixtureIds.includes(cutoutFixtureId) && + compatibleCutoutFixtureIds[0] != null && + // compatible fixture is single-slot + SINGLE_SLOT_FIXTURES.includes(compatibleCutoutFixtureIds[0]) + ? labwareInSlots.find( + ({ location }) => + // match the addressable area to an on-deck labware + requiredAddressableAreasForCutoutId[0] === location.slotName + ) + : null + + const missingLabwareDisplayName = + missingSingleSlotLabware != null + ? missingSingleSlotLabware.labwareNickName ?? + getLabwareDisplayName(missingSingleSlotLabware.labwareDef) ?? + null + : null + + return [ + ...acc, + { + cutoutId, + cutoutFixtureId, + requiredAddressableAreas: requiredAddressableAreasForCutoutId, + compatibleCutoutFixtureIds, + missingLabwareDisplayName, + }, + ] + }, + [] + ) +} + +interface DeckConfigurationEditingTools { + addFixtureToCutout: (cutoutId: CutoutId) => void, + removeFixtureFromCutout: (cutoutId: CutoutId, cutoutFixtureId: CutoutFixtureId) => void + addFixtureModal: React.ReactNode +} +export function useDeckConfigurationEditingTools(isOnDevice: boolean): DeckConfigurationEditingTools { + const deckDef = getDeckDefFromRobotType(FLEX_ROBOT_TYPE) + const deckConfig = + useNotifyDeckConfigurationQuery({ + refetchInterval: DECK_CONFIG_REFETCH_INTERVAL, + }).data ?? [] + const { updateDeckConfiguration } = useUpdateDeckConfigurationMutation() + const [targetCutoutId, setTargetCutoutId] = React.useState( + null + ) + + const addFixtureToCutout = (cutoutId: CutoutId): void => { + setTargetCutoutId(cutoutId) + } + + const removeFixtureFromCutout = ( + cutoutId: CutoutId, + cutoutFixtureId: CutoutFixtureId + ): void => { + let replacementFixtureId: CutoutFixtureId = SINGLE_CENTER_SLOT_FIXTURE + if (SINGLE_RIGHT_CUTOUTS.includes(cutoutId)) { + replacementFixtureId = SINGLE_RIGHT_SLOT_FIXTURE + } else if (SINGLE_LEFT_CUTOUTS.includes(cutoutId)) { + replacementFixtureId = SINGLE_LEFT_SLOT_FIXTURE + } + + const fixtureGroup = + deckDef.cutoutFixtures.find(cf => cf.id === cutoutFixtureId) + ?.fixtureGroup ?? {} + + let newDeckConfig = deckConfig + if (cutoutId in fixtureGroup) { + const groupMap = + fixtureGroup[cutoutId]?.find(group => + Object.entries(group).every(([cId, cfId]) => + deckConfig.find( + config => + config.cutoutId === cId && config.cutoutFixtureId === cfId + ) + ) + ) ?? {} + newDeckConfig = deckConfig.map(cutoutConfig => + cutoutConfig.cutoutId in groupMap + ? { + ...cutoutConfig, + cutoutFixtureId: replacementFixtureId, + opentronsModuleSerialNumber: undefined, + } + : cutoutConfig + ) + } else { + newDeckConfig = deckConfig.map(cutoutConfig => + cutoutConfig.cutoutId === cutoutId + ? { + ...cutoutConfig, + cutoutFixtureId: replacementFixtureId, + opentronsModuleSerialNumber: undefined, + } + : cutoutConfig + ) + } + updateDeckConfiguration(newDeckConfig) + } + + return { + addFixtureToCutout, + removeFixtureFromCutout, + addFixtureModal: targetCutoutId != null ? ( + setTargetCutoutId(null)} + isOnDevice={isOnDevice} + /> + ) : null + } +} From 80b2cb4e8c3328c0bcc42c729015981f48a5e9bd Mon Sep 17 00:00:00 2001 From: Brian Cooper Date: Thu, 16 May 2024 15:04:49 -0400 Subject: [PATCH 2/7] remove staging changes from odd protocol setup add fixture --- .../AddFixtureModal.stories.tsx | 2 +- .../AddFixtureModal.tsx | 8 +-- .../__tests__/AddFixtureModal.test.tsx | 7 ++- .../DeviceDetailsDeckConfiguration/index.tsx | 5 +- .../ProtocolSetupDeckConfiguration/index.tsx | 13 ++--- app/src/pages/DeckConfiguration/index.tsx | 5 +- .../resources/deck_configuration/hooks.tsx | 50 +++++++++++-------- 7 files changed, 47 insertions(+), 43 deletions(-) diff --git a/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.stories.tsx b/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.stories.tsx index 034a18c1e77..de7c062f9d1 100644 --- a/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.stories.tsx +++ b/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.stories.tsx @@ -26,6 +26,6 @@ const Template: Story> = args => ( export const Default = Template.bind({}) Default.args = { fixtureLocation: 'cutoutD3', - setShowAddFixtureModal: () => {}, + closeModal: () => {}, isOnDevice: true, } diff --git a/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.tsx b/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.tsx index bc79ef78a6b..c7452bd4ebc 100644 --- a/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.tsx +++ b/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.tsx @@ -304,7 +304,9 @@ export function AddFixtureModal({ )?.usbPort.port )} buttonText={t('add')} - onClickHandler={() => { handleAddFixture(cutoutConfigs) }} + onClickHandler={() => { + handleAddFixture(cutoutConfigs) + }} isOnDevice={isOnDevice} /> )) @@ -315,9 +317,7 @@ export function AddFixtureModal({ - providedFixtureOptions != null - ? null - : closeModal() + providedFixtureOptions != null ? null : closeModal() } > diff --git a/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/AddFixtureModal.test.tsx b/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/AddFixtureModal.test.tsx index 38cc283f8e9..1b101dab4b6 100644 --- a/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/AddFixtureModal.test.tsx +++ b/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/AddFixtureModal.test.tsx @@ -23,7 +23,7 @@ import type { Modules } from '@opentrons/api-client' vi.mock('@opentrons/react-api-client') vi.mock('../../../resources/deck_configuration') -const mockSetShowAddFixtureModal = vi.fn() +const mockCloseModal = vi.fn() const mockUpdateDeckConfiguration = vi.fn() const mockSetCurrentDeckConfig = vi.fn() @@ -39,8 +39,7 @@ describe('Touchscreen AddFixtureModal', () => { beforeEach(() => { props = { cutoutId: 'cutoutD3', - setShowAddFixtureModal: mockSetShowAddFixtureModal, - setCurrentDeckConfig: mockSetCurrentDeckConfig, + closeModal: mockCloseModal, isOnDevice: true, } vi.mocked(useUpdateDeckConfigurationMutation).mockReturnValue({ @@ -96,7 +95,7 @@ describe('Desktop AddFixtureModal', () => { beforeEach(() => { props = { cutoutId: 'cutoutD3', - setShowAddFixtureModal: mockSetShowAddFixtureModal, + closeModal: mockCloseModal, } vi.mocked(useUpdateDeckConfigurationMutation).mockReturnValue({ updateDeckConfiguration: mockUpdateDeckConfiguration, diff --git a/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx b/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx index d17b0cf1d57..8d2503e1391 100644 --- a/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx +++ b/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx @@ -36,7 +36,10 @@ import { Banner } from '../../atoms/Banner' import { DeckFixtureSetupInstructionsModal } from './DeckFixtureSetupInstructionsModal' import { useIsRobotViewable, useRunStatuses } from '../Devices/hooks' import { useIsEstopNotDisengaged } from '../../resources/devices/hooks/useIsEstopNotDisengaged' -import { useDeckConfigurationEditingTools, useNotifyDeckConfigurationQuery } from '../../resources/deck_configuration' +import { + useDeckConfigurationEditingTools, + useNotifyDeckConfigurationQuery, +} from '../../resources/deck_configuration' import type { CutoutId } from '@opentrons/shared-data' diff --git a/app/src/organisms/ProtocolSetupDeckConfiguration/index.tsx b/app/src/organisms/ProtocolSetupDeckConfiguration/index.tsx index c3c65e6318f..b8be7125017 100644 --- a/app/src/organisms/ProtocolSetupDeckConfiguration/index.tsx +++ b/app/src/organisms/ProtocolSetupDeckConfiguration/index.tsx @@ -76,11 +76,7 @@ export function ProtocolSetupDeckConfiguration({ : config ) - const [ - currentDeckConfig, - setCurrentDeckConfig, - ] = React.useState(mergedDeckConfig) - const modulesOnDeck = currentDeckConfig.reduce( + const modulesOnDeck = mergedDeckConfig.reduce( (acc, cutoutConfig) => { const matchingFixtureIdsAndModel = Object.entries( MODULE_FIXTURES_BY_MODEL @@ -117,9 +113,7 @@ export function ProtocolSetupDeckConfiguration({ [] ) - const { updateDeckConfiguration } = useUpdateDeckConfigurationMutation() const handleClickConfirm = (): void => { - updateDeckConfiguration(currentDeckConfig) setSetupScreen('modules') } @@ -135,9 +129,8 @@ export function ProtocolSetupDeckConfiguration({ {showConfigurationModal && cutoutId != null ? ( setShowConfigurationModal(false)} providedFixtureOptions={providedFixtureOptions} - setCurrentDeckConfig={setCurrentDeckConfig} isOnDevice /> ) : null} @@ -158,7 +151,7 @@ export function ProtocolSetupDeckConfiguration({ height="28.4375rem" > diff --git a/app/src/pages/DeckConfiguration/index.tsx b/app/src/pages/DeckConfiguration/index.tsx index cd78c86adc7..2ed8530bcbd 100644 --- a/app/src/pages/DeckConfiguration/index.tsx +++ b/app/src/pages/DeckConfiguration/index.tsx @@ -16,7 +16,10 @@ import { ChildNavigation } from '../../organisms/ChildNavigation' import { DeckFixtureSetupInstructionsModal } from '../../organisms/DeviceDetailsDeckConfiguration/DeckFixtureSetupInstructionsModal' import { DeckConfigurationDiscardChangesModal } from '../../organisms/DeviceDetailsDeckConfiguration/DeckConfigurationDiscardChangesModal' import { getTopPortalEl } from '../../App/portal' -import { useDeckConfigurationEditingTools, useNotifyDeckConfigurationQuery } from '../../resources/deck_configuration' +import { + useDeckConfigurationEditingTools, + useNotifyDeckConfigurationQuery, +} from '../../resources/deck_configuration' export function DeckConfigurationEditor(): JSX.Element { const { t, i18n } = useTranslation([ diff --git a/app/src/resources/deck_configuration/hooks.tsx b/app/src/resources/deck_configuration/hooks.tsx index 9f3bf0a337f..a3bf96173c3 100644 --- a/app/src/resources/deck_configuration/hooks.tsx +++ b/app/src/resources/deck_configuration/hooks.tsx @@ -76,23 +76,23 @@ export function useDeckConfigurationCompatibility( // get the on-deck labware name for a missing single-slot addressable area const missingSingleSlotLabware = cutoutFixtureId != null && - // fixture mismatch - !compatibleCutoutFixtureIds.includes(cutoutFixtureId) && - compatibleCutoutFixtureIds[0] != null && - // compatible fixture is single-slot - SINGLE_SLOT_FIXTURES.includes(compatibleCutoutFixtureIds[0]) + // fixture mismatch + !compatibleCutoutFixtureIds.includes(cutoutFixtureId) && + compatibleCutoutFixtureIds[0] != null && + // compatible fixture is single-slot + SINGLE_SLOT_FIXTURES.includes(compatibleCutoutFixtureIds[0]) ? labwareInSlots.find( - ({ location }) => - // match the addressable area to an on-deck labware - requiredAddressableAreasForCutoutId[0] === location.slotName - ) + ({ location }) => + // match the addressable area to an on-deck labware + requiredAddressableAreasForCutoutId[0] === location.slotName + ) : null const missingLabwareDisplayName = missingSingleSlotLabware != null ? missingSingleSlotLabware.labwareNickName ?? - getLabwareDisplayName(missingSingleSlotLabware.labwareDef) ?? - null + getLabwareDisplayName(missingSingleSlotLabware.labwareDef) ?? + null : null return [ @@ -110,12 +110,17 @@ export function useDeckConfigurationCompatibility( ) } -interface DeckConfigurationEditingTools { - addFixtureToCutout: (cutoutId: CutoutId) => void, - removeFixtureFromCutout: (cutoutId: CutoutId, cutoutFixtureId: CutoutFixtureId) => void +interface DeckConfigurationEditingTools { + addFixtureToCutout: (cutoutId: CutoutId) => void + removeFixtureFromCutout: ( + cutoutId: CutoutId, + cutoutFixtureId: CutoutFixtureId + ) => void addFixtureModal: React.ReactNode } -export function useDeckConfigurationEditingTools(isOnDevice: boolean): DeckConfigurationEditingTools { +export function useDeckConfigurationEditingTools( + isOnDevice: boolean +): DeckConfigurationEditingTools { const deckDef = getDeckDefFromRobotType(FLEX_ROBOT_TYPE) const deckConfig = useNotifyDeckConfigurationQuery({ @@ -182,12 +187,13 @@ export function useDeckConfigurationEditingTools(isOnDevice: boolean): DeckConfi return { addFixtureToCutout, removeFixtureFromCutout, - addFixtureModal: targetCutoutId != null ? ( - setTargetCutoutId(null)} - isOnDevice={isOnDevice} - /> - ) : null + addFixtureModal: + targetCutoutId != null ? ( + setTargetCutoutId(null)} + isOnDevice={isOnDevice} + /> + ) : null, } } From c8e19eb1ae88bd4efdb5f2a513ec10abce41155e Mon Sep 17 00:00:00 2001 From: Brian Cooper Date: Thu, 16 May 2024 15:39:17 -0400 Subject: [PATCH 3/7] remove redundant tc viz --- .../ProtocolSetupDeckConfiguration/index.tsx | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/app/src/organisms/ProtocolSetupDeckConfiguration/index.tsx b/app/src/organisms/ProtocolSetupDeckConfiguration/index.tsx index b8be7125017..7f6f78bc343 100644 --- a/app/src/organisms/ProtocolSetupDeckConfiguration/index.tsx +++ b/app/src/organisms/ProtocolSetupDeckConfiguration/index.tsx @@ -15,9 +15,9 @@ import { MAGNETIC_BLOCK_V1_FIXTURE, MODULE_FIXTURES_BY_MODEL, STAGING_AREA_SLOT_WITH_MAGNETIC_BLOCK_V1_FIXTURE, + THERMOCYCLER_V2_REAR_FIXTURE, getSimplestDeckConfigForProtocol, } from '@opentrons/shared-data' -import { useUpdateDeckConfigurationMutation } from '@opentrons/react-api-client' import { ChildNavigation } from '../ChildNavigation' import { AddFixtureModal } from '../DeviceDetailsDeckConfiguration/AddFixtureModal' @@ -29,7 +29,6 @@ import { useNotifyDeckConfigurationQuery } from '../../resources/deck_configurat import type { CutoutFixtureId, CutoutId, - DeckConfiguration, ModuleModel, } from '@opentrons/shared-data' import type { ModuleOnDeck } from '@opentrons/components' @@ -48,7 +47,11 @@ export function ProtocolSetupDeckConfiguration({ setSetupScreen, providedFixtureOptions, }: ProtocolSetupDeckConfigurationProps): JSX.Element { - const { t } = useTranslation(['protocol_setup', 'devices_landing', 'shared']) + const { i18n, t } = useTranslation([ + 'protocol_setup', + 'devices_landing', + 'shared', + ]) const [ showConfigurationModal, @@ -66,13 +69,14 @@ export function ProtocolSetupDeckConfiguration({ mostRecentAnalysis ).map(({ cutoutId, cutoutFixtureId }) => ({ cutoutId, cutoutFixtureId })) - const targetDeckConfig = simplestDeckConfig.find( + const targetCutoutConfig = simplestDeckConfig.find( deck => deck.cutoutId === cutoutId ) const mergedDeckConfig = deckConfig.map(config => - targetDeckConfig != null && config.cutoutId === targetDeckConfig.cutoutId - ? targetDeckConfig + targetCutoutConfig != null && + config.cutoutId === targetCutoutConfig.cutoutId + ? targetCutoutConfig : config ) @@ -83,7 +87,10 @@ export function ProtocolSetupDeckConfiguration({ ).find(([_moduleModel, moduleFixtureIds]) => moduleFixtureIds.includes(cutoutConfig.cutoutFixtureId) ) - if (matchingFixtureIdsAndModel != null) { + if ( + matchingFixtureIdsAndModel != null && + cutoutConfig.cutoutFixtureId !== THERMOCYCLER_V2_REAR_FIXTURE + ) { const [matchingModel] = matchingFixtureIdsAndModel return [ ...acc, @@ -140,8 +147,7 @@ export function ProtocolSetupDeckConfiguration({ setSetupScreen('modules')} - buttonText={t('shared:confirm')} + buttonText={i18n.format(t('shared:save'), 'capitalize')} onClickButton={handleClickConfirm} /> Date: Thu, 16 May 2024 16:35:40 -0400 Subject: [PATCH 4/7] fix failing tests --- .../__tests__/AddFixtureModal.test.tsx | 2 -- .../DeviceDetailsDeckConfiguration.test.tsx | 16 ++++++++----- .../DeviceDetailsDeckConfiguration/index.tsx | 5 +--- .../ProtocolSetupDeckConfiguration.test.tsx | 4 ++-- .../__tests__/DeckConfiguration.test.tsx | 24 +------------------ 5 files changed, 14 insertions(+), 37 deletions(-) diff --git a/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/AddFixtureModal.test.tsx b/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/AddFixtureModal.test.tsx index 1b101dab4b6..17ae8511513 100644 --- a/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/AddFixtureModal.test.tsx +++ b/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/AddFixtureModal.test.tsx @@ -25,7 +25,6 @@ vi.mock('../../../resources/deck_configuration') const mockCloseModal = vi.fn() const mockUpdateDeckConfiguration = vi.fn() -const mockSetCurrentDeckConfig = vi.fn() const render = (props: React.ComponentProps) => { return renderWithProviders(, { @@ -68,7 +67,6 @@ describe('Touchscreen AddFixtureModal', () => { render(props) fireEvent.click(screen.getAllByText('Select options')[1]) fireEvent.click(screen.getAllByText('Add')[0]) - expect(mockSetCurrentDeckConfig).toHaveBeenCalled() }) it('when fixture options are provided, should only render those options', () => { diff --git a/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/DeviceDetailsDeckConfiguration.test.tsx b/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/DeviceDetailsDeckConfiguration.test.tsx index e6d048bcf52..5ef61630951 100644 --- a/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/DeviceDetailsDeckConfiguration.test.tsx +++ b/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/DeviceDetailsDeckConfiguration.test.tsx @@ -16,10 +16,10 @@ import { DeckFixtureSetupInstructionsModal } from '../DeckFixtureSetupInstructio import { useIsEstopNotDisengaged } from '../../../resources/devices/hooks/useIsEstopNotDisengaged' import { DeviceDetailsDeckConfiguration } from '../' import { useNotifyCurrentMaintenanceRun } from '../../../resources/maintenance_runs' -import { useNotifyDeckConfigurationQuery } from '../../../resources/deck_configuration' import type { MaintenanceRun } from '@opentrons/api-client' import type * as OpentronsComponents from '@opentrons/components' +import type * as DeckConfigResources from '../../../resources/deck_configuration' vi.mock('@opentrons/components', async importOriginal => { const actual = await importOriginal() @@ -33,7 +33,15 @@ vi.mock('../DeckFixtureSetupInstructionsModal') vi.mock('../../Devices/hooks') vi.mock('../../../resources/maintenance_runs') vi.mock('../../../resources/devices/hooks/useIsEstopNotDisengaged') -vi.mock('../../../resources/deck_configuration') +vi.mock('../../../resources/deck_configuration', async importOriginal => { + const actual = await importOriginal() + return { + ...actual, + useNotifyDeckConfigurationQuery: vi + .fn() + .mockReturnValue({ data: [] } as any), + } +}) const ROBOT_NAME = 'otie' const mockUpdateDeckConfiguration = vi.fn() @@ -63,9 +71,6 @@ describe('DeviceDetailsDeckConfiguration', () => { robotName: ROBOT_NAME, } vi.mocked(useModulesQuery).mockReturnValue({ data: { data: [] } } as any) - vi.mocked(useNotifyDeckConfigurationQuery).mockReturnValue({ - data: [], - } as any) vi.mocked(useUpdateDeckConfigurationMutation).mockReturnValue({ updateDeckConfiguration: mockUpdateDeckConfiguration, } as any) @@ -132,7 +137,6 @@ describe('DeviceDetailsDeckConfiguration', () => { }) it('should render no deck fixtures, if deck configs are not set', () => { - vi.mocked(useNotifyDeckConfigurationQuery).mockReturnValue([] as any) render(props) screen.getByText('No deck fixtures') }) diff --git a/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx b/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx index 8d2503e1391..d28df33bf69 100644 --- a/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx +++ b/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx @@ -19,10 +19,7 @@ import { StyledText, TYPOGRAPHY, } from '@opentrons/components' -import { - useModulesQuery, - useUpdateDeckConfigurationMutation, -} from '@opentrons/react-api-client' +import { useModulesQuery } from '@opentrons/react-api-client' import { getCutoutDisplayName, getFixtureDisplayName, diff --git a/app/src/organisms/ProtocolSetupDeckConfiguration/__tests__/ProtocolSetupDeckConfiguration.test.tsx b/app/src/organisms/ProtocolSetupDeckConfiguration/__tests__/ProtocolSetupDeckConfiguration.test.tsx index 18c678d74e6..7ed6940bd38 100644 --- a/app/src/organisms/ProtocolSetupDeckConfiguration/__tests__/ProtocolSetupDeckConfiguration.test.tsx +++ b/app/src/organisms/ProtocolSetupDeckConfiguration/__tests__/ProtocolSetupDeckConfiguration.test.tsx @@ -88,7 +88,7 @@ describe('ProtocolSetupDeckConfiguration', () => { render(props) screen.getByText('Deck configuration') screen.getByText('mock BaseDeck') - screen.getByText('Confirm') + screen.getByText('Save') }) it('should call a mock function when tapping the back button', () => { @@ -99,7 +99,7 @@ describe('ProtocolSetupDeckConfiguration', () => { it('should call a mock function when tapping confirm button', () => { render(props) - fireEvent.click(screen.getByText('Confirm')) + fireEvent.click(screen.getByText('Save')) expect(mockUpdateDeckConfiguration).toHaveBeenCalled() }) }) diff --git a/app/src/pages/DeckConfiguration/__tests__/DeckConfiguration.test.tsx b/app/src/pages/DeckConfiguration/__tests__/DeckConfiguration.test.tsx index 9efe3bc0aa2..531dae46d62 100644 --- a/app/src/pages/DeckConfiguration/__tests__/DeckConfiguration.test.tsx +++ b/app/src/pages/DeckConfiguration/__tests__/DeckConfiguration.test.tsx @@ -77,7 +77,7 @@ describe('DeckConfigurationEditor', () => { render() screen.getByText('Deck configuration') screen.getByText('Setup Instructions') - screen.getByText('Confirm') + screen.getByText('Save') expect(vi.mocked(DeckConfigurator)).toHaveBeenCalled() }) @@ -86,26 +86,4 @@ describe('DeckConfigurationEditor', () => { fireEvent.click(screen.getByText('Setup Instructions')) expect(vi.mocked(DeckFixtureSetupInstructionsModal)).toHaveBeenCalled() }) - - it('should call a mock function when tapping confirm', () => { - // (kk:10/26/2023) - // Once get approval, I will be able to update this case - // render() - // screen.getByText('Confirm').click() - // expect(mockUpdateDeckConfiguration).toHaveBeenCalled() - }) - - it('should call a mock function when tapping back button if there is no change', () => { - render() - fireEvent.click(screen.getByTestId('ChildNavigation_Back_Button')) - expect(mockGoBack).toHaveBeenCalled() - }) - - it('should render modal when tapping back button if there is a change', () => { - // (kk:10/26/2023) - // Once get approval, I will be able to update this case - // render() - // screen.getByTestId('ChildNavigation_Back_Button').click() - // expect(mockGoBack).toHaveBeenCalled() - }) }) From 5e7f0c841c817de69c1426504fe02ec6388eb03c Mon Sep 17 00:00:00 2001 From: Brian Cooper Date: Thu, 16 May 2024 18:30:28 -0400 Subject: [PATCH 5/7] fix up unused mocks --- .../ProtocolSetupDeckConfiguration.test.tsx | 16 ++++------------ .../__tests__/DeckConfiguration.test.tsx | 10 +++++++++- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/app/src/organisms/ProtocolSetupDeckConfiguration/__tests__/ProtocolSetupDeckConfiguration.test.tsx b/app/src/organisms/ProtocolSetupDeckConfiguration/__tests__/ProtocolSetupDeckConfiguration.test.tsx index 7ed6940bd38..b489892b8ac 100644 --- a/app/src/organisms/ProtocolSetupDeckConfiguration/__tests__/ProtocolSetupDeckConfiguration.test.tsx +++ b/app/src/organisms/ProtocolSetupDeckConfiguration/__tests__/ProtocolSetupDeckConfiguration.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react' import { when } from 'vitest-when' import { fireEvent, screen } from '@testing-library/react' -import { describe, it, vi, beforeEach, expect, afterEach } from 'vitest' +import { describe, it, vi, beforeEach, afterEach } from 'vitest' import { BaseDeck } from '@opentrons/components' import { @@ -28,7 +28,6 @@ vi.mock('../../LabwarePositionCheck/useMostRecentCompletedAnalysis') vi.mock('../../../resources/deck_configuration') const mockSetSetupScreen = vi.fn() -const mockUpdateDeckConfiguration = vi.fn() const PROTOCOL_DETAILS = { displayName: 'fake protocol', protocolData: ({ @@ -69,12 +68,12 @@ describe('ProtocolSetupDeckConfiguration', () => { when(vi.mocked(useMostRecentCompletedAnalysis)) .calledWith('mockRunId') .thenReturn(PROTOCOL_DETAILS.protocolData) - vi.mocked(useUpdateDeckConfigurationMutation).mockReturnValue({ - updateDeckConfiguration: mockUpdateDeckConfiguration, - } as any) vi.mocked(useNotifyDeckConfigurationQuery).mockReturnValue(({ data: [], } as unknown) as UseQueryResult) + vi.mocked(useUpdateDeckConfigurationMutation).mockReturnValue({ + updateDeckConfiguration: vi.fn(), + } as any) vi.mocked(useModulesQuery).mockReturnValue(({ data: { data: [] }, } as unknown) as UseQueryResult) @@ -91,15 +90,8 @@ describe('ProtocolSetupDeckConfiguration', () => { screen.getByText('Save') }) - it('should call a mock function when tapping the back button', () => { - render(props) - fireEvent.click(screen.getByTestId('ChildNavigation_Back_Button')) - expect(mockSetSetupScreen).toHaveBeenCalledWith('modules') - }) - it('should call a mock function when tapping confirm button', () => { render(props) fireEvent.click(screen.getByText('Save')) - expect(mockUpdateDeckConfiguration).toHaveBeenCalled() }) }) diff --git a/app/src/pages/DeckConfiguration/__tests__/DeckConfiguration.test.tsx b/app/src/pages/DeckConfiguration/__tests__/DeckConfiguration.test.tsx index 531dae46d62..d0fab1277b0 100644 --- a/app/src/pages/DeckConfiguration/__tests__/DeckConfiguration.test.tsx +++ b/app/src/pages/DeckConfiguration/__tests__/DeckConfiguration.test.tsx @@ -12,7 +12,10 @@ import { TRASH_BIN_ADAPTER_FIXTURE } from '@opentrons/shared-data' import { i18n } from '../../../i18n' import { DeckFixtureSetupInstructionsModal } from '../../../organisms/DeviceDetailsDeckConfiguration/DeckFixtureSetupInstructionsModal' import { DeckConfigurationEditor } from '..' -import { useNotifyDeckConfigurationQuery } from '../../../resources/deck_configuration' +import { + useNotifyDeckConfigurationQuery, + useDeckConfigurationEditingTools, +} from '../../../resources/deck_configuration' import type { UseQueryResult } from 'react-query' import type { DeckConfiguration } from '@opentrons/shared-data' @@ -71,6 +74,11 @@ describe('DeckConfigurationEditor', () => { vi.mocked(useUpdateDeckConfigurationMutation).mockReturnValue({ updateDeckConfiguration: mockUpdateDeckConfiguration, } as any) + vi.mocked(useDeckConfigurationEditingTools).mockReturnValue({ + addFixtureToCutout: vi.fn(), + removeFixtureFromCutout: vi.fn(), + addFixtureModal: null, + }) }) it('should render text, button and DeckConfigurator', () => { From 83672720a1f31d2beac8ce9f11135d4bf9e75fd7 Mon Sep 17 00:00:00 2001 From: Brian Cooper Date: Thu, 16 May 2024 18:57:34 -0400 Subject: [PATCH 6/7] fixup --- .../DeviceDetailsDeckConfiguration.test.tsx | 39 +++++++++++++------ 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/DeviceDetailsDeckConfiguration.test.tsx b/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/DeviceDetailsDeckConfiguration.test.tsx index 5ef61630951..93d62462710 100644 --- a/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/DeviceDetailsDeckConfiguration.test.tsx +++ b/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/DeviceDetailsDeckConfiguration.test.tsx @@ -3,6 +3,10 @@ import { fireEvent, screen } from '@testing-library/react' import { when } from 'vitest-when' import { describe, it, beforeEach, vi, afterEach } from 'vitest' +import { + DeckConfiguration, + TRASH_BIN_ADAPTER_FIXTURE, +} from '@opentrons/shared-data' import { DeckConfigurator } from '@opentrons/components' import { useModulesQuery, @@ -16,10 +20,14 @@ import { DeckFixtureSetupInstructionsModal } from '../DeckFixtureSetupInstructio import { useIsEstopNotDisengaged } from '../../../resources/devices/hooks/useIsEstopNotDisengaged' import { DeviceDetailsDeckConfiguration } from '../' import { useNotifyCurrentMaintenanceRun } from '../../../resources/maintenance_runs' +import { + useDeckConfigurationEditingTools, + useNotifyDeckConfigurationQuery, +} from '../../../resources/deck_configuration' +import type { UseQueryResult } from 'react-query' import type { MaintenanceRun } from '@opentrons/api-client' import type * as OpentronsComponents from '@opentrons/components' -import type * as DeckConfigResources from '../../../resources/deck_configuration' vi.mock('@opentrons/components', async importOriginal => { const actual = await importOriginal() @@ -33,16 +41,14 @@ vi.mock('../DeckFixtureSetupInstructionsModal') vi.mock('../../Devices/hooks') vi.mock('../../../resources/maintenance_runs') vi.mock('../../../resources/devices/hooks/useIsEstopNotDisengaged') -vi.mock('../../../resources/deck_configuration', async importOriginal => { - const actual = await importOriginal() - return { - ...actual, - useNotifyDeckConfigurationQuery: vi - .fn() - .mockReturnValue({ data: [] } as any), - } -}) - +vi.mock('../../../resources/deck_configuration') + +const mockDeckConfig = [ + { + cutoutId: 'cutoutC3', + cutoutFixtureId: TRASH_BIN_ADAPTER_FIXTURE, + }, +] const ROBOT_NAME = 'otie' const mockUpdateDeckConfiguration = vi.fn() const RUN_STATUSES = { @@ -88,6 +94,14 @@ describe('DeviceDetailsDeckConfiguration', () => { .calledWith(ROBOT_NAME) .thenReturn(false) when(vi.mocked(useIsRobotViewable)).calledWith(ROBOT_NAME).thenReturn(true) + vi.mocked(useNotifyDeckConfigurationQuery).mockReturnValue({ + data: mockDeckConfig, + } as UseQueryResult) + vi.mocked(useDeckConfigurationEditingTools).mockReturnValue({ + addFixtureToCutout: vi.fn(), + removeFixtureFromCutout: vi.fn(), + addFixtureModal: null, + }) }) afterEach(() => { @@ -137,6 +151,9 @@ describe('DeviceDetailsDeckConfiguration', () => { }) it('should render no deck fixtures, if deck configs are not set', () => { + vi.mocked(useNotifyDeckConfigurationQuery).mockReturnValue({ + data: [], + } as UseQueryResult) render(props) screen.getByText('No deck fixtures') }) From 2d2a5e5e3abf7b99039926d4e43c289f35779697 Mon Sep 17 00:00:00 2001 From: Brian Cooper Date: Thu, 16 May 2024 19:09:39 -0400 Subject: [PATCH 7/7] remove problematic test type --- .../__tests__/DeviceDetailsDeckConfiguration.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/DeviceDetailsDeckConfiguration.test.tsx b/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/DeviceDetailsDeckConfiguration.test.tsx index 93d62462710..27b6bbad2ba 100644 --- a/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/DeviceDetailsDeckConfiguration.test.tsx +++ b/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/DeviceDetailsDeckConfiguration.test.tsx @@ -153,7 +153,7 @@ describe('DeviceDetailsDeckConfiguration', () => { it('should render no deck fixtures, if deck configs are not set', () => { vi.mocked(useNotifyDeckConfigurationQuery).mockReturnValue({ data: [], - } as UseQueryResult) + } as any) render(props) screen.getByText('No deck fixtures') })