Skip to content

Commit

Permalink
refactor(app): correct command text for trashing tips
Browse files Browse the repository at this point in the history
  • Loading branch information
mjhuff committed Oct 25, 2024
1 parent 870271d commit 5d543bc
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 5 deletions.
9 changes: 5 additions & 4 deletions app/src/assets/localization/en/protocol_command_text.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"absorbance_reader_open_lid": "Opening Absorbance Reader lid",
"absorbance_reader_close_lid": "Closing Absorbance Reader lid",
"absorbance_reader_initialize": "Initializing Absorbance Reader to perform {{mode}} measurement at {{wavelengths}}",
"absorbance_reader_open_lid": "Opening Absorbance Reader lid",
"absorbance_reader_read": "Reading plate in Absorbance Reader",
"adapter_in_mod_in_slot": "{{adapter}} on {{module}} in {{slot}}",
"adapter_in_slot": "{{adapter}} in {{slot}}",
Expand All @@ -27,6 +27,7 @@
"dispense_push_out": "Dispensing {{volume}} µL into well {{well_name}} of {{labware}} in {{labware_location}} at {{flow_rate}} µL/sec and pushing out {{push_out_volume}} µL",
"drop_tip": "Dropping tip in {{well_name}} of {{labware}}",
"drop_tip_in_place": "Dropping tip in place",
"dropping_tip_in_trash": "Dropping tip in {{trash}}",
"engaging_magnetic_module": "Engaging Magnetic Module",
"fixed_trash": "Fixed Trash",
"home_gantry": "Homing all gantry, pipette, and plunger axes",
Expand Down Expand Up @@ -73,16 +74,16 @@
"setting_thermocycler_lid_temp": "Setting Thermocycler lid temperature to {{temp}}",
"single": "single",
"slot": "Slot {{slot_name}}",
"turning_rail_lights_off": "Turning rail lights off",
"turning_rail_lights_on": "Turning rail lights on",
"target_temperature": "target temperature",
"tc_awaiting_for_duration": "Waiting for Thermocycler profile to complete",
"tc_run_profile_steps": "Temperature: {{celsius}}°C, hold time: {{duration}}",
"tc_starting_extended_profile_cycle": "{{repetitions}} repetitions of the following steps:",
"tc_starting_extended_profile": "Running thermocycler profile with {{elementCount}} total steps and cycles:",
"tc_starting_extended_profile_cycle": "{{repetitions}} repetitions of the following steps:",
"tc_starting_profile": "Running thermocycler profile with {{stepCount}} steps:",
"touch_tip": "Touching tip",
"trash_bin_in_slot": "Trash Bin in {{slot_name}}",
"turning_rail_lights_off": "Turning rail lights off",
"turning_rail_lights_on": "Turning rail lights on",
"unlatching_hs_latch": "Unlatching labware on Heater-Shaker",
"wait_for_duration": "Pausing for {{seconds}} seconds. {{message}}",
"wait_for_resume": "Pausing protocol",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
import { screen } from '@testing-library/react'
import { vi, describe, it, beforeEach } from 'vitest'
import { useTranslation } from 'react-i18next'

import { renderWithProviders } from '/app/__testing-utils__'
import { i18n } from '/app/i18n'
import {
getLabwareDefinitionsFromCommands,
getLabwareName,
getLoadedLabware,
getLabwareDisplayLocation,
} from '/app/local-resources/labware'
import { getPipettingCommandText } from '../getPipettingCommandText'
import { getLabwareDefURI } from '@opentrons/shared-data'
import { getFinalLabwareLocation } from '../../getFinalLabwareLocation'
import { getWellRange } from '../../getWellRange'
import { getFinalMoveToAddressableAreaCmd } from '../../getFinalAddressableAreaCmd'
import { getAddressableAreaDisplayName } from '../../getAddressableAreaDisplayName'

vi.mock('@opentrons/shared-data')
vi.mock('../../getFinalLabwareLocation')
vi.mock('../../getWellRange')
vi.mock('/app/local-resources/labware')
vi.mock('../../getFinalAddressableAreaCmd')
vi.mock('../../getAddressableAreaDisplayName')

const baseCommandData = {
allRunDefs: {},
robotType: 'OT-2',
commandTextData: {
commands: [],
labware: [],
modules: [],
pipettes: [{ id: 'pipette-1', pipetteName: 'p300_single' }],
},
} as any

function TestWrapper({ command }: { command: any }): JSX.Element {
const { t } = useTranslation('protocol_command_text')
const text = getPipettingCommandText({
command,
...baseCommandData,
t,
})

return <div>{text}</div>
}

const render = (command: any) => {
return renderWithProviders(<TestWrapper command={command} />, {
i18nInstance: i18n,
})
}

describe('getPipettingCommandText', () => {
beforeEach(() => {
vi.mocked(getLabwareDefURI).mockImplementation((def: any) => def.uri)
vi.mocked(getFinalLabwareLocation).mockReturnValue('slot-1' as any)
vi.mocked(getWellRange).mockReturnValue('A1')
vi.mocked(getLabwareDefinitionsFromCommands).mockReturnValue([
{ uri: 'tiprack-uri', parameters: { isTiprack: true } },
{ uri: 'plate-uri', parameters: { isTiprack: false } },
] as any)
vi.mocked(getLabwareName).mockReturnValue('Test Labware')
vi.mocked(getLoadedLabware).mockImplementation(
(labware, id) =>
({
definitionUri: id === 'tiprack-id' ? 'tiprack-uri' : 'plate-uri',
} as any)
)
vi.mocked(getLabwareDisplayLocation).mockReturnValue('Slot 1')
vi.mocked(getFinalMoveToAddressableAreaCmd).mockReturnValue({
id: 'cmd-1',
commandType: 'moveToAddressableArea',
} as any)
vi.mocked(getAddressableAreaDisplayName).mockReturnValue('Fixed Trash')
})

it('should render aspirate command text correctly', () => {
const command = {
id: 'cmd-1',
commandType: 'aspirate',
params: {
labwareId: 'labware-1',
wellName: 'A1',
volume: 100,
flowRate: 150,
},
}

render(command)
screen.getByText(
/Aspirating 100 µL from well A1 of Test Labware in Slot 1 at 150 µL\/sec/
)
})

it('should render dispense command text correctly', () => {
const command = {
id: 'cmd-1',
commandType: 'dispense',
params: {
labwareId: 'labware-1',
wellName: 'A1',
volume: 100,
flowRate: 150,
},
}

render(command)
screen.getByText(
/Dispensing 100 µL into well A1 of Test Labware in Slot 1 at 150 µL\/sec/
)
})

it('should render dispense with push out command text correctly', () => {
const command = {
id: 'cmd-1',
commandType: 'dispense',
params: {
labwareId: 'labware-1',
wellName: 'A1',
volume: 100,
flowRate: 150,
pushOut: 10,
},
}

render(command)
screen.getByText(
/Dispensing 100 µL into well A1 of Test Labware in Slot 1 at 150 µL\/sec and pushing out 10 µL/
)
})

it('should render pickup tip command text correctly', () => {
const command = {
id: 'cmd-1',
commandType: 'pickUpTip',
params: {
labwareId: 'tiprack-id',
wellName: 'A1',
pipetteId: 'pipette-1',
},
}

render(command)
screen.getByText(/Picking up tip\(s\) from A1 of Test Labware in Slot 1/)
})

it('should render drop tip in tiprack command text correctly', () => {
const command = {
id: 'cmd-1',
commandType: 'dropTip',
params: {
labwareId: 'tiprack-id',
wellName: 'A1',
},
}

render(command)
screen.getByText(/Returning tip to A1 of Test Labware in Slot 1/)
})

it('should render drop tip in place command text correctly if there is an addressable area name', () => {
const command = {
id: 'cmd-1',
commandType: 'dropTipInPlace',
params: {},
}

render(command)
screen.getByText('Dropping tip in Fixed Trash')
})

it('should render drop tip in place command text correctly if there is not an addressable area name', () => {
const command = {
id: 'cmd-1',
commandType: 'dropTipInPlace',
params: {},
}

vi.mocked(getFinalMoveToAddressableAreaCmd).mockReturnValue(null)

render(command)
screen.getByText('Dropping tip in place')
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import {

import type { PipetteName, RunTimeCommand } from '@opentrons/shared-data'
import type { GetCommandText } from '../..'
import { getFinalMoveToAddressableAreaCmd } from '/app/local-resources/commands/hooks/useCommandTextString/utils/getFinalAddressableAreaCmd'
import { getAddressableAreaDisplayName } from '/app/local-resources/commands/hooks/useCommandTextString/utils/getAddressableAreaDisplayName'

export const getPipettingCommandText = ({
command,
Expand Down Expand Up @@ -186,7 +188,14 @@ export const getPipettingCommandText = ({
})
}
case 'dropTipInPlace': {
return t('drop_tip_in_place')
const cmd = getFinalMoveToAddressableAreaCmd(allPreviousCommands ?? [])

if (cmd != null) {
const displayName = getAddressableAreaDisplayName([cmd], cmd?.id, t)
return t('dropping_tip_in_trash', { trash: displayName })
} else {
return t('drop_tip_in_place')
}
}
case 'dispenseInPlace': {
const { volume, flowRate } = command.params
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { findLastAt } from '/app/local-resources/commands/hooks/useCommandTextString/utils/helpers'

import type { RunTimeCommand } from '@opentrons/shared-data'
/**
* given a list of commands and a labwareId, calculate the resulting location
* of the corresponding labware after all given commands are executed
* @param commands list of commands to search within
* @returns The last command related to addressable areas.
*/
export function getFinalMoveToAddressableAreaCmd(
commands: RunTimeCommand[]
): RunTimeCommand | null {
const [cmd] = findLastAt(
commands,
(c: RunTimeCommand) =>
c.commandType === 'moveToAddressableArea' ||
c.commandType === 'moveToAddressableAreaForDropTip'
)

return cmd ?? null
}

0 comments on commit 5d543bc

Please sign in to comment.