Skip to content

Commit 58a4e05

Browse files
authored
fix(app): ensure disabled touch tip value is null (#19156)
Add logic to `useAspirateSettingsConfig` and `useDispenseSettingsConfig` hooks to appropriately check if source/destination is compatible with touch tip. Refactors this check to a util.
1 parent 338c0a8 commit 58a4e05

File tree

6 files changed

+61
-10
lines changed

6 files changed

+61
-10
lines changed

app/src/organisms/ODD/QuickTransferFlow/Aspirate/hooks/useAspirateSettingsConfig.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next'
33
import { useToaster } from '/app/organisms/ToasterOven'
44

55
import { ASPIRATE_SETTING_OPTIONS as SETTING_OPTIONS } from '../../constants'
6+
import { getIsTouchTipEnabled } from '../../utils/getIsTouchTipEnabled'
67

78
import type { Dispatch } from 'react'
89
import type {
@@ -28,8 +29,7 @@ export function useAspirateSettingsConfig({
2829
const { t } = useTranslation(['quick_transfer', 'shared'])
2930
const { makeSnackbar } = useToaster()
3031

31-
const sourceIsReservoir =
32-
state.source.metadata.displayCategory === 'reservoir'
32+
const touchTipEnabled = getIsTouchTipEnabled(state.source)
3333

3434
const aspirateSettingsItems: SettingItem[] = [
3535
{
@@ -148,15 +148,15 @@ export function useAspirateSettingsConfig({
148148
option: SETTING_OPTIONS.ASPIRATE_TOUCH_TIP,
149149
copy: t('touch_tip'),
150150
value:
151-
state.touchTipAspirate !== undefined
151+
state.touchTipAspirate !== undefined && touchTipEnabled
152152
? t('touch_tip_value', {
153153
speed: state.touchTipAspirateSpeed,
154154
position: state.touchTipAspirate,
155155
})
156156
: t('option_disabled'),
157-
enabled: !sourceIsReservoir,
157+
enabled: touchTipEnabled,
158158
onClick: () => {
159-
if (!sourceIsReservoir) {
159+
if (touchTipEnabled) {
160160
setSelectedSetting(SETTING_OPTIONS.ASPIRATE_TOUCH_TIP)
161161
} else {
162162
makeSnackbar(t('aspirate_setting_disabled') as string)

app/src/organisms/ODD/QuickTransferFlow/Dispense/hooks/useDispenseSettingsConfig.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { SOURCE_WELL_BLOWOUT_DESTINATION } from '@opentrons/step-generation'
99
import { useToaster } from '/app/organisms/ToasterOven'
1010

1111
import { DISPENSE_SETTING_OPTIONS as SETTING_OPTIONS } from '../../constants'
12+
import { getIsTouchTipEnabled } from '../../utils/getIsTouchTipEnabled'
1213

1314
import type {
1415
DispenseSettingOption,
@@ -54,6 +55,8 @@ export function useDispenseSettingsConfig({
5455
}
5556
}
5657

58+
const touchTipEnabled = getIsTouchTipEnabled(state.destination)
59+
5760
const dispenseSettingsItems = [
5861
{
5962
option: 'dispense_flow_rate',
@@ -202,15 +205,19 @@ export function useDispenseSettingsConfig({
202205
option: 'dispense_touch_tip',
203206
copy: t('touch_tip'),
204207
value:
205-
state.touchTipDispense !== undefined
208+
state.touchTipDispense !== undefined && touchTipEnabled
206209
? t('touch_tip_value', {
207210
speed: state.touchTipDispenseSpeed,
208211
position: state.touchTipDispense,
209212
})
210213
: t('option_disabled'),
211-
enabled: true,
214+
enabled: touchTipEnabled,
212215
onClick: () => {
213-
setSelectedSetting('dispense_touch_tip')
216+
if (touchTipEnabled) {
217+
setSelectedSetting('dispense_touch_tip')
218+
} else {
219+
makeSnackbar(t('dispense_setting_disabled') as string)
220+
}
214221
},
215222
},
216223
{

app/src/organisms/ODD/QuickTransferFlow/__tests__/Dispense/Dispense.test.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ import { Dispense } from '../../Dispense'
88
import { DispenseSettingDetail } from '../../Dispense/DispenseSettingDetail'
99
import { DispenseSettingItem } from '../../Dispense/DispenseSettingItem'
1010
import { ResetAdvancedSettingsModal } from '../../QuickTransferAdvancedSettings/ResetAdvancedSettingsModal'
11+
import { getIsTouchTipEnabled } from '../../utils/getIsTouchTipEnabled'
1112

1213
import type { ComponentProps } from 'react'
1314

1415
vi.mock('../../Dispense/DispenseSettingItem')
1516
vi.mock('../../Dispense/DispenseSettingDetail')
1617
vi.mock('../../Dispense/hooks/useAspirateSettingsConfig')
1718
vi.mock('../../QuickTransferAdvancedSettings/ResetAdvancedSettingsModal')
19+
vi.mock('../../utils/getIsTouchTipEnabled')
1820

1921
const render = (props: ComponentProps<typeof Dispense>) => {
2022
return renderWithProviders(<Dispense {...props} />, {
@@ -95,6 +97,7 @@ describe('Dispense', () => {
9597
vi.mocked(ResetAdvancedSettingsModal).mockReturnValue(
9698
<div>mock ResetAdvancedSettingsModal</div>
9799
)
100+
vi.mocked(getIsTouchTipEnabled).mockReturnValue(true)
98101
})
99102

100103
it('renders mock components and reset button', () => {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { describe, expect, it } from 'vitest'
2+
3+
import { getIsTouchTipEnabled } from '../../utils/getIsTouchTipEnabled'
4+
5+
import type { LabwareDefinition2 } from '@opentrons/shared-data'
6+
7+
describe('getIsTouchTipEnabled', () => {
8+
it('should return true if the source or destination does not have quirks', () => {
9+
const sourceOrDestination = {
10+
parameters: {},
11+
} as LabwareDefinition2
12+
expect(getIsTouchTipEnabled(sourceOrDestination)).toBe(true)
13+
})
14+
it('should return true if the source or destination does not have touchTipDisabled quirk', () => {
15+
const sourceOrDestination = {
16+
parameters: { quirks: ['someQuirk'] },
17+
} as LabwareDefinition2
18+
expect(getIsTouchTipEnabled(sourceOrDestination)).toBe(true)
19+
})
20+
it('should return false if the source or destination has touchTipDisabled quirk', () => {
21+
const sourceOrDestination = {
22+
parameters: { quirks: ['touchTipDisabled'] },
23+
} as LabwareDefinition2
24+
expect(getIsTouchTipEnabled(sourceOrDestination)).toBe(false)
25+
})
26+
it('should return true if the source or destination is "source"', () => {
27+
const sourceOrDestination = 'source'
28+
expect(getIsTouchTipEnabled(sourceOrDestination)).toBe(true)
29+
})
30+
})

app/src/organisms/ODD/QuickTransferFlow/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ export interface QuickTransferSummaryState {
8383
delayAspirate?: {
8484
delayDuration: number
8585
}
86-
touchTipAspirate?: number
86+
touchTipAspirate?: number // specifies the tip position from the top of the well
8787
touchTipAspirateSpeed?: number
8888
airGapAspirate?: number
8989
tipPositionDispense: number
@@ -104,7 +104,7 @@ export interface QuickTransferSummaryState {
104104
delayDispense?: {
105105
delayDuration: number
106106
}
107-
touchTipDispense?: number
107+
touchTipDispense?: number // specifies the tip position from the top of the well
108108
touchTipDispenseSpeed?: number
109109
disposalVolume?: number
110110
blowOutDispense?: {
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import type { QuickTransferSummaryState } from '../types'
2+
3+
export const getIsTouchTipEnabled = (
4+
sourceOrDestination:
5+
| QuickTransferSummaryState['source']
6+
| QuickTransferSummaryState['destination']
7+
): boolean =>
8+
sourceOrDestination === 'source' ||
9+
!(
10+
sourceOrDestination.parameters.quirks?.includes('touchTipDisabled') ?? false
11+
)

0 commit comments

Comments
 (0)