diff --git a/app/src/organisms/ProtocolSetupLabware/LabwareMapViewModal.tsx b/app/src/organisms/ProtocolSetupLabware/LabwareMapViewModal.tsx
index 4073d7838af..b606eee186c 100644
--- a/app/src/organisms/ProtocolSetupLabware/LabwareMapViewModal.tsx
+++ b/app/src/organisms/ProtocolSetupLabware/LabwareMapViewModal.tsx
@@ -1,32 +1,25 @@
import * as React from 'react'
import map from 'lodash/map'
import { useTranslation } from 'react-i18next'
-import {
- BaseDeck,
- EXTENDED_DECK_CONFIG_FIXTURE,
- LabwareRender,
-} from '@opentrons/components'
-import {
- FLEX_ROBOT_TYPE,
- getDeckDefFromRobotType,
- LabwareDefinition2,
- THERMOCYCLER_MODULE_V1,
-} from '@opentrons/shared-data'
-import { RunTimeCommand } from '@opentrons/shared-data'
+import { BaseDeck, EXTENDED_DECK_CONFIG_FIXTURE } from '@opentrons/components'
+import { FLEX_ROBOT_TYPE, THERMOCYCLER_MODULE_V1 } from '@opentrons/shared-data'
import { Modal } from '../../molecules/Modal'
import { getDeckConfigFromProtocolCommands } from '../../resources/deck_configuration/utils'
import { useFeatureFlag } from '../../redux/config'
import { getStandardDeckViewLayerBlockList } from '../Devices/ProtocolRun/utils/getStandardDeckViewLayerBlockList'
import { getLabwareRenderInfo } from '../Devices/ProtocolRun/utils/getLabwareRenderInfo'
-import { useMostRecentCompletedAnalysis } from '../LabwarePositionCheck/useMostRecentCompletedAnalysis'
import { AttachedProtocolModuleMatch } from '../ProtocolSetupModulesAndDeck/utils'
+import type {
+ CompletedProtocolAnalysis,
+ DeckDefinition,
+ LabwareDefinition2,
+} from '@opentrons/shared-data'
import type { LoadedLabwareByAdapter } from '@opentrons/api-client'
import type { ModalHeaderBaseProps } from '../../molecules/Modal/types'
interface LabwareMapViewModalProps {
- runId: string
attachedProtocolModuleMatches: AttachedProtocolModuleMatch[]
handleLabwareClick: (
labwareDef: LabwareDefinition2,
@@ -34,26 +27,26 @@ interface LabwareMapViewModalProps {
) => void
onCloseClick: () => void
initialLoadedLabwareByAdapter: LoadedLabwareByAdapter
- commands: RunTimeCommand[]
+ deckDef: DeckDefinition
+ mostRecentAnalysis: CompletedProtocolAnalysis | null
}
-export function LabwareMapViewModal({
- handleLabwareClick,
- runId,
- onCloseClick,
- attachedProtocolModuleMatches,
- initialLoadedLabwareByAdapter,
- commands,
-}: LabwareMapViewModalProps): JSX.Element {
+export function LabwareMapViewModal(
+ props: LabwareMapViewModalProps
+): JSX.Element {
+ const {
+ handleLabwareClick,
+ onCloseClick,
+ attachedProtocolModuleMatches,
+ initialLoadedLabwareByAdapter,
+ deckDef,
+ mostRecentAnalysis,
+ } = props
const { t } = useTranslation('protocol_setup')
const enableDeckConfig = useFeatureFlag('enableDeckConfiguration')
-
const deckConfig = enableDeckConfig
? EXTENDED_DECK_CONFIG_FIXTURE
- : getDeckConfigFromProtocolCommands(commands)
-
- const mostRecentAnalysis = useMostRecentCompletedAnalysis(runId)
- const deckDef = getDeckDefFromRobotType(FLEX_ROBOT_TYPE)
+ : getDeckConfigFromProtocolCommands(mostRecentAnalysis?.commands ?? [])
const labwareRenderInfo =
mostRecentAnalysis != null
? getLabwareRenderInfo(mostRecentAnalysis, deckDef)
@@ -65,14 +58,7 @@ export function LabwareMapViewModal({
}
const moduleLocations = attachedProtocolModuleMatches.map(module => {
- const {
- moduleDef,
- nestedLabwareDef,
- nestedLabwareId,
- slotName,
- x,
- y,
- } = module
+ const { moduleDef, nestedLabwareDef, nestedLabwareId, slotName } = module
const labwareInAdapterInMod =
nestedLabwareId != null
? initialLoadedLabwareByAdapter[nestedLabwareId]
@@ -83,6 +69,7 @@ export function LabwareMapViewModal({
labwareInAdapterInMod?.result?.definition ?? nestedLabwareDef
const topLabwareId =
labwareInAdapterInMod?.result?.labwareId ?? nestedLabwareId
+
return {
moduleModel: moduleDef.model,
moduleLocation: { slotName },
@@ -91,25 +78,17 @@ export function LabwareMapViewModal({
? { lidMotorState: 'open' }
: {},
nestedLabwareDef: topLabwareDefinition,
- moduleChildren:
- topLabwareDefinition != null && topLabwareId != null ? (
-
-
- handleLabwareClick(topLabwareDefinition, topLabwareId)
- }
- />
-
- ) : null,
+ onLabwareClick:
+ topLabwareDefinition != null && topLabwareId != null
+ ? () => handleLabwareClick(topLabwareDefinition, topLabwareId)
+ : undefined,
+ moduleChildren: null,
}
})
const labwareLocations = map(
labwareRenderInfo,
- ({ x, y, labwareDef, slotName }, labwareId) => {
+ ({ labwareDef, slotName }, labwareId) => {
const labwareInAdapter = initialLoadedLabwareByAdapter[labwareId]
// only rendering the labware on top most layer so
// either the adapter or the labware are rendered but not both
@@ -121,16 +100,9 @@ export function LabwareMapViewModal({
labwareLocation: { slotName },
definition: topLabwareDefinition,
topLabwareId,
- labwareChildren: (
-
-
- handleLabwareClick(topLabwareDefinition, topLabwareId)
- }
- />
-
- ),
+ onLabwareClick: () =>
+ handleLabwareClick(topLabwareDefinition, topLabwareId),
+ labwareChildren: null,
}
}
)
diff --git a/app/src/organisms/ProtocolSetupLabware/__tests__/LabwareMapViewModal.test.tsx b/app/src/organisms/ProtocolSetupLabware/__tests__/LabwareMapViewModal.test.tsx
new file mode 100644
index 00000000000..391ec650de9
--- /dev/null
+++ b/app/src/organisms/ProtocolSetupLabware/__tests__/LabwareMapViewModal.test.tsx
@@ -0,0 +1,145 @@
+import * as React from 'react'
+import { StaticRouter } from 'react-router-dom'
+import { when, resetAllWhenMocks } from 'jest-when'
+import {
+ renderWithProviders,
+ BaseDeck,
+ EXTENDED_DECK_CONFIG_FIXTURE,
+} from '@opentrons/components'
+import { FLEX_ROBOT_TYPE } from '@opentrons/shared-data'
+import deckDefFixture from '@opentrons/shared-data/deck/fixtures/3/deckExample.json'
+import fixture_tiprack_300_ul from '@opentrons/shared-data/labware/fixtures/2/fixture_tiprack_300_ul.json'
+import { i18n } from '../../../i18n'
+import { getDeckConfigFromProtocolCommands } from '../../../resources/deck_configuration/utils'
+import { useFeatureFlag } from '../../../redux/config'
+import { getLabwareRenderInfo } from '../../Devices/ProtocolRun/utils/getLabwareRenderInfo'
+import { getStandardDeckViewLayerBlockList } from '../../Devices/ProtocolRun/utils/getStandardDeckViewLayerBlockList'
+import { mockProtocolModuleInfo } from '../__fixtures__'
+import { LabwareMapViewModal } from '../LabwareMapViewModal'
+
+import type {
+ CompletedProtocolAnalysis,
+ DeckDefinition,
+ LabwareDefinition2,
+ ModuleModel,
+} from '@opentrons/shared-data'
+
+jest.mock('../../Devices/ProtocolRun/utils/getLabwareRenderInfo')
+jest.mock('@opentrons/components/src/hardware-sim/Labware/LabwareRender')
+jest.mock('@opentrons/components/src/hardware-sim/BaseDeck')
+jest.mock('../../../resources/deck_configuration/utils')
+jest.mock('../../../redux/config')
+
+const mockGetLabwareRenderInfo = getLabwareRenderInfo as jest.MockedFunction<
+ typeof getLabwareRenderInfo
+>
+const mockGetDeckConfigFromProtocolCommands = getDeckConfigFromProtocolCommands as jest.MockedFunction<
+ typeof getDeckConfigFromProtocolCommands
+>
+const mockUseFeatureFlag = useFeatureFlag as jest.MockedFunction<
+ typeof useFeatureFlag
+>
+
+const mockBaseDeck = BaseDeck as jest.MockedFunction
+const MOCK_300_UL_TIPRACK_COORDS = [30, 40, 0]
+
+const render = (props: React.ComponentProps) => {
+ return renderWithProviders(
+
+
+ ,
+ {
+ i18nInstance: i18n,
+ }
+ )[0]
+}
+
+describe('LabwareMapViewModal', () => {
+ beforeEach(() => {
+ mockGetLabwareRenderInfo.mockReturnValue({})
+ mockGetDeckConfigFromProtocolCommands.mockReturnValue([])
+ when(mockUseFeatureFlag)
+ .calledWith('enableDeckConfiguration')
+ .mockReturnValue(true)
+ })
+
+ afterEach(() => {
+ resetAllWhenMocks()
+ })
+ it('should render nothing on the deck and calls exit button', () => {
+ mockBaseDeck.mockReturnValue(mock base deck
)
+
+ const props = {
+ handleLabwareClick: jest.fn(),
+ onCloseClick: jest.fn(),
+ deckDef: (deckDefFixture as unknown) as DeckDefinition,
+ mostRecentAnalysis: ({
+ commands: [],
+ labware: [],
+ } as unknown) as CompletedProtocolAnalysis,
+ initialLoadedLabwareByAdapter: {},
+ attachedProtocolModuleMatches: [],
+ }
+
+ const { getByText, getByLabelText } = render(props)
+ getByText('Map View')
+ getByText('mock base deck')
+ getByLabelText('closeIcon').click()
+ expect(props.onCloseClick).toHaveBeenCalled()
+ })
+
+ it('should render a deck with modules and labware', () => {
+ const mockLabwareLocations = [
+ {
+ labwareLocation: { slotName: 'C1' },
+ definition: fixture_tiprack_300_ul as LabwareDefinition2,
+ topLabwareId: '300_ul_tiprack_id',
+ onLabwareClick: expect.any(Function),
+ labwareChildren: null,
+ },
+ ]
+ const mockModuleLocations = [
+ {
+ moduleModel: 'heaterShakerModuleV1' as ModuleModel,
+ moduleLocation: { slotName: 'B1' },
+ nestedLabwareDef: mockProtocolModuleInfo[0]
+ .nestedLabwareDef as LabwareDefinition2,
+ onLabwareClick: expect.any(Function),
+ moduleChildren: null,
+ innerProps: {},
+ },
+ ]
+ when(mockBaseDeck)
+ .calledWith({
+ robotType: FLEX_ROBOT_TYPE,
+ deckLayerBlocklist: getStandardDeckViewLayerBlockList(FLEX_ROBOT_TYPE),
+ deckConfig: EXTENDED_DECK_CONFIG_FIXTURE,
+ labwareLocations: mockLabwareLocations,
+ moduleLocations: mockModuleLocations,
+ })
+ .mockReturnValue(mock base deck
)
+ mockGetLabwareRenderInfo.mockReturnValue({
+ '300_ul_tiprack_id': {
+ labwareDef: fixture_tiprack_300_ul as LabwareDefinition2,
+ displayName: 'fresh tips',
+ x: MOCK_300_UL_TIPRACK_COORDS[0],
+ y: MOCK_300_UL_TIPRACK_COORDS[1],
+ z: MOCK_300_UL_TIPRACK_COORDS[2],
+ slotName: 'C1',
+ },
+ })
+ render({
+ handleLabwareClick: jest.fn(),
+ onCloseClick: jest.fn(),
+ deckDef: (deckDefFixture as unknown) as DeckDefinition,
+ mostRecentAnalysis: ({} as unknown) as CompletedProtocolAnalysis,
+ initialLoadedLabwareByAdapter: {},
+ attachedProtocolModuleMatches: [
+ {
+ ...mockProtocolModuleInfo[0],
+ },
+ ],
+ })
+ expect(mockBaseDeck).toHaveBeenCalled()
+ })
+})
diff --git a/app/src/organisms/ProtocolSetupLabware/index.tsx b/app/src/organisms/ProtocolSetupLabware/index.tsx
index 683cdb85dcf..65da8173326 100644
--- a/app/src/organisms/ProtocolSetupLabware/index.tsx
+++ b/app/src/organisms/ProtocolSetupLabware/index.tsx
@@ -206,8 +206,8 @@ export function ProtocolSetupLabware({
{showDeckMapModal ? (
setShowDeckMapModal(false)}
diff --git a/components/src/hardware-sim/BaseDeck/BaseDeck.tsx b/components/src/hardware-sim/BaseDeck/BaseDeck.tsx
index a55b4c66245..a29f33028b3 100644
--- a/components/src/hardware-sim/BaseDeck/BaseDeck.tsx
+++ b/components/src/hardware-sim/BaseDeck/BaseDeck.tsx
@@ -43,6 +43,7 @@ interface BaseDeckProps {
definition: LabwareDefinition2
// generic prop to render self-positioned children for each labware
labwareChildren?: React.ReactNode
+ onLabwareClick?: () => void
}>
moduleLocations: Array<{
moduleModel: ModuleModel
@@ -51,6 +52,7 @@ interface BaseDeckProps {
innerProps?: React.ComponentProps['innerProps']
// generic prop to render self-positioned children for each module
moduleChildren?: React.ReactNode
+ onLabwareClick?: () => void
}>
deckConfig?: DeckConfiguration
deckLayerBlocklist?: string[]
@@ -150,6 +152,7 @@ export function BaseDeck(props: BaseDeckProps): JSX.Element {
nestedLabwareDef,
innerProps,
moduleChildren,
+ onLabwareClick,
}) => {
const slotDef = deckDef.locations.orderedSlots.find(
s => s.id === moduleLocation.slotName
@@ -167,7 +170,10 @@ export function BaseDeck(props: BaseDeckProps): JSX.Element {
innerProps={innerProps}
>
{nestedLabwareDef != null ? (
-
+
) : null}
{moduleChildren}
@@ -175,7 +181,7 @@ export function BaseDeck(props: BaseDeckProps): JSX.Element {
}
)}
{labwareLocations.map(
- ({ labwareLocation, definition, labwareChildren }) => {
+ ({ labwareLocation, definition, labwareChildren, onLabwareClick }) => {
const slotDef = deckDef.locations.orderedSlots.find(
s =>
labwareLocation !== 'offDeck' &&
@@ -187,7 +193,10 @@ export function BaseDeck(props: BaseDeckProps): JSX.Element {
key={slotDef.id}
transform={`translate(${slotDef.position[0]},${slotDef.position[1]})`}
>
-
+
{labwareChildren}
) : null
diff --git a/components/src/hardware-sim/Labware/LabwareRender.tsx b/components/src/hardware-sim/Labware/LabwareRender.tsx
index ba515c73b94..12f67ac48b7 100644
--- a/components/src/hardware-sim/Labware/LabwareRender.tsx
+++ b/components/src/hardware-sim/Labware/LabwareRender.tsx
@@ -63,7 +63,7 @@ export interface LabwareRenderProps {
export const LabwareRender = (props: LabwareRenderProps): JSX.Element => {
const { gRef } = props
const cornerOffsetFromSlot = props.definition.cornerOffsetFromSlot
-
+
return (