Skip to content

Commit

Permalink
fix(app): fix incorrect labware render location in TC
Browse files Browse the repository at this point in the history
  • Loading branch information
mjhuff committed Nov 5, 2024
1 parent c04ecdd commit 203249e
Show file tree
Hide file tree
Showing 2 changed files with 206 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
getRunCurrentModulesInfo,
getRunCurrentLabwareOnDeck,
getRunCurrentModulesOnDeck,
updateLabwareInModules,
} from '../useDeckMapUtils'

import type { LabwareDefinition2 } from '@opentrons/shared-data'
Expand Down Expand Up @@ -495,3 +496,161 @@ describe('getIsLabwareMatch', () => {
expect(result).toBe(false)
})
})

describe('updateLabwareInModules', () => {
const mockLabwareDef: LabwareDefinition2 = {
...(fixture96Plate as LabwareDefinition2),
metadata: {
displayName: 'Mock Labware Definition',
displayCategory: 'wellPlate',
displayVolumeUnits: 'mL',
},
}

const mockModule = {
moduleModel: 'temperatureModuleV2',
moduleLocation: { slotName: 'A1' },
innerProps: {},
nestedLabwareDef: null,
highlight: null,
} as any

const mockLabware = {
labwareDef: mockLabwareDef,
labwareLocation: { slotName: 'A1' },
slotName: 'A1',
}

it('should update module with nested labware when they share the same slot', () => {
const result = updateLabwareInModules({
runCurrentModules: [mockModule],
currentLabwareInfo: [mockLabware],
})

expect(result.updatedModules).toEqual([
{
...mockModule,
nestedLabwareDef: mockLabwareDef,
},
])
expect(result.remainingLabware).toEqual([])
})

it('should keep labware separate when slots do not match', () => {
const labwareInDifferentSlot = {
...mockLabware,
labwareLocation: { slotName: 'B1' },
slotName: 'B1',
}

const result = updateLabwareInModules({
runCurrentModules: [mockModule],
currentLabwareInfo: [labwareInDifferentSlot],
})

expect(result.updatedModules).toEqual([mockModule])
expect(result.remainingLabware).toEqual([labwareInDifferentSlot])
})

it('should handle multiple modules and labware', () => {
const mockModuleB1 = {
...mockModule,
moduleLocation: { slotName: 'B1' },
}

const labwareB1 = {
...mockLabware,
labwareLocation: { slotName: 'B1' },
slotName: 'B1',
}

const labwareC1 = {
...mockLabware,
labwareLocation: { slotName: 'C1' },
slotName: 'C1',
}

const result = updateLabwareInModules({
runCurrentModules: [mockModule, mockModuleB1],
currentLabwareInfo: [mockLabware, labwareB1, labwareC1],
})

expect(result.updatedModules).toEqual([
{
...mockModule,
nestedLabwareDef: mockLabwareDef,
},
{
...mockModuleB1,
nestedLabwareDef: mockLabwareDef,
},
])
expect(result.remainingLabware).toEqual([labwareC1])
})

it('should handle empty modules array', () => {
const result = updateLabwareInModules({
runCurrentModules: [],
currentLabwareInfo: [mockLabware],
})

expect(result.updatedModules).toEqual([])
expect(result.remainingLabware).toEqual([mockLabware])
})

it('should handle empty labware array', () => {
const result = updateLabwareInModules({
runCurrentModules: [mockModule],
currentLabwareInfo: [],
})

expect(result.updatedModules).toEqual([mockModule])
expect(result.remainingLabware).toEqual([])
})

it('should handle multiple labware in same slot, nesting only one with module', () => {
const labwareA1Second = {
...mockLabware,
labwareDef: {
...mockLabwareDef,
metadata: {
...mockLabwareDef.metadata,
displayName: 'Second Labware',
},
},
}

const result = updateLabwareInModules({
runCurrentModules: [mockModule],
currentLabwareInfo: [mockLabware, labwareA1Second],
})

expect(result.updatedModules).toEqual([
{
...mockModule,
nestedLabwareDef: mockLabwareDef,
},
])
expect(result.remainingLabware).toEqual([])
})

it('should preserve module properties when updating with nested labware', () => {
const moduleWithProperties = {
...mockModule,
innerProps: { lidMotorState: 'open' },
highlight: 'someHighlight',
}

const result = updateLabwareInModules({
runCurrentModules: [moduleWithProperties],
currentLabwareInfo: [mockLabware],
})

expect(result.updatedModules).toEqual([
{
...moduleWithProperties,
nestedLabwareDef: mockLabwareDef,
},
])
})
})
50 changes: 47 additions & 3 deletions app/src/organisms/ErrorRecoveryFlows/hooks/useDeckMapUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ export function useDeckMapUtils({
const deckConfig = getSimplestDeckConfigForProtocol(protocolAnalysis)
const deckDef = getDeckDefFromRobotType(robotType)

// TODO(jh, 11-05-24): Revisit this logic along with deckmap interfaces after deck map redesign.

const currentModulesInfo = useMemo(
() =>
getRunCurrentModulesInfo({
Expand All @@ -96,12 +98,17 @@ export function useDeckMapUtils({
[runRecord, labwareDefinitionsByUri]
)

const { updatedModules, remainingLabware } = useMemo(
() => updateLabwareInModules({ runCurrentModules, currentLabwareInfo }),
[runCurrentModules, currentLabwareInfo]
)

const runCurrentLabware = useMemo(
() =>
getRunCurrentLabwareOnDeck({
failedLabwareUtils,
runRecord,
currentLabwareInfo,
currentLabwareInfo: remainingLabware,
}),
[failedLabwareUtils, currentLabwareInfo]
)
Expand Down Expand Up @@ -137,7 +144,7 @@ export function useDeckMapUtils({

return {
deckConfig,
modulesOnDeck: runCurrentModules.map(
modulesOnDeck: updatedModules.map(
({ moduleModel, moduleLocation, innerProps, nestedLabwareDef }) => ({
moduleModel,
moduleLocation,
Expand All @@ -149,7 +156,7 @@ export function useDeckMapUtils({
labwareLocation,
definition,
})),
highlightLabwareEventuallyIn: [...runCurrentModules, ...runCurrentLabware]
highlightLabwareEventuallyIn: [...updatedModules, ...runCurrentLabware]
.map(el => el.highlight)
.filter(maybeSlot => maybeSlot != null) as string[],
kind: 'intervention',
Expand Down Expand Up @@ -459,3 +466,40 @@ export function getIsLabwareMatch(
return slotLocation === slotName
}
}

// If any labware share a slot with a module, the labware should be nested within the module for rendering purposes.
// This prevents issues such as TC nested labware rendering in
export function updateLabwareInModules({
runCurrentModules,
currentLabwareInfo,
}: {
runCurrentModules: ReturnType<typeof getRunCurrentModulesOnDeck>
currentLabwareInfo: ReturnType<typeof getRunCurrentLabwareInfo>
}): {
updatedModules: ReturnType<typeof getRunCurrentModulesOnDeck>
remainingLabware: ReturnType<typeof getRunCurrentLabwareInfo>
} {
const usedSlots = new Set<string>()

const updatedModules = runCurrentModules.map(moduleInfo => {
const labwareInSameLoc = currentLabwareInfo.find(
lw => moduleInfo.moduleLocation.slotName === lw.slotName
)

if (labwareInSameLoc != null) {
usedSlots.add(labwareInSameLoc.slotName)
return {
...moduleInfo,
nestedLabwareDef: labwareInSameLoc.labwareDef,
}
} else {
return moduleInfo
}
})

const remainingLabware = currentLabwareInfo.filter(
lw => !usedSlots.has(lw.slotName)
)

return { updatedModules, remainingLabware }
}

0 comments on commit 203249e

Please sign in to comment.