Skip to content

Commit

Permalink
feat(protocol-designer): Implement presaved step form for TC state (#…
Browse files Browse the repository at this point in the history
…5641)

closes #5596
  • Loading branch information
Kadee80 authored May 12, 2020
1 parent e61e731 commit 32b191b
Show file tree
Hide file tree
Showing 9 changed files with 281 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import {
MAGNETIC_MODULE_V2,
TEMPERATURE_MODULE_TYPE,
TEMPERATURE_MODULE_V2,
THERMOCYCLER_MODULE_TYPE,
THERMOCYCLER_MODULE_V1,
} from '@opentrons/shared-data'
import { fixtureP10Single } from '@opentrons/shared-data/pipette/fixtures/name'
import {
Expand Down Expand Up @@ -56,6 +58,12 @@ beforeEach(() => {
model: TEMPERATURE_MODULE_V2,
slot: '3',
},
someThermocyclerModuleId: {
id: 'someTemperatureModuleId',
type: THERMOCYCLER_MODULE_TYPE,
model: THERMOCYCLER_MODULE_V1,
slot: '3',
},
},
pipettes: { leftPipetteId: { ...leftPipette, mount: 'left' } },
},
Expand Down Expand Up @@ -257,4 +265,26 @@ describe('createPresavedStepForm', () => {
stepDetails: '',
})
})

it('should set a default thermocycler module when a Thermocycler step is added', () => {
const args = {
...defaultArgs,
stepType: 'thermocycler',
}

expect(createPresavedStepForm(args)).toEqual({
id: stepId,
stepType: 'thermocycler',
moduleId: 'someThermocyclerModuleId',
// TC Default field
stepName: 'thermocycler',
stepDetails: '',
thermocyclerFormType: 'thermocyclerState',
blockIsActive: false,
blockTargetTemp: null,
lidIsActive: false,
lidTargetTemp: null,
lidOpen: null,
})
})
})
30 changes: 30 additions & 0 deletions protocol-designer/src/step-forms/utils/createPresavedStepForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
getNextDefaultMagnetAction,
getNextDefaultPipetteId,
getNextDefaultTemperatureModuleId,
getNextDefaultThermocyclerModuleId,
handleFormChange,
} from '../../steplist/formLevel'
import {
Expand Down Expand Up @@ -140,6 +141,27 @@ const _patchTemperatureModuleId = (args: {|
return null
}

const _patchThermocyclerModuleId = (args: {|
initialDeckSetup: InitialDeckSetup,
orderedStepIds: OrderedStepIdsState,
savedStepForms: SavedStepFormState,
stepType: StepType,
|}): FormUpdater => () => {
const { initialDeckSetup, orderedStepIds, savedStepForms, stepType } = args

const hasThermocyclerModuleId = stepType === 'thermocycler'

if (hasThermocyclerModuleId) {
const moduleId = getNextDefaultThermocyclerModuleId(
savedStepForms,
orderedStepIds,
initialDeckSetup.modules
)
return { moduleId }
}
return null
}

export const createPresavedStepForm = ({
initialDeckSetup,
labwareEntities,
Expand Down Expand Up @@ -176,11 +198,19 @@ export const createPresavedStepForm = ({
stepType,
})

const updateThermocyclerModuleId = _patchThermocyclerModuleId({
initialDeckSetup,
orderedStepIds,
savedStepForms,
stepType,
})

// finally, compose and apply all the updaters in order,
// passing the applied result from one updater as the input of the next
return [
updateDefaultPipette,
updateTemperatureModuleId,
updateThermocyclerModuleId,
updateMagneticModuleId,
].reduce<FormData>(
(acc, updater: FormUpdater) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ export function getDefaultsForStepType(
blockIsActive: false,
blockTargetTemp: null,
lidIsActive: false,
lidTargetTemp: null,
lidOpen: null,
}
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
THERMOCYCLER_MODULE_V1,
} from '@opentrons/shared-data'
import { TEMPERATURE_DEACTIVATED } from '../../../../constants'
import { getNextDefaultTemperatureModuleId } from '..'
import { getNextDefaultTemperatureModuleId } from '../getNextDefaultTemperatureModuleId'

const getThermocycler = () => ({
id: 'tcId',
Expand Down Expand Up @@ -54,13 +54,6 @@ describe('getNextDefaultTemperatureModuleId', () => {
},
expected: 'tempId',
},
{
testMsg: 'thermocycler only: use tc',
equippedModulesById: {
tcId: getThermocycler(),
},
expected: 'tcId',
},
{
testMsg: 'only mag module present: return null',
equippedModulesById: {
Expand All @@ -85,7 +78,7 @@ describe('getNextDefaultTemperatureModuleId', () => {
})
})
})
// TODO (ka 2019-12-20): Add in tests for existing temperature form steps once wired up

describe('previous forms', () => {
const testCases = [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
// @flow
import {
MAGNETIC_MODULE_TYPE,
TEMPERATURE_MODULE_TYPE,
THERMOCYCLER_MODULE_TYPE,
MAGNETIC_MODULE_V1,
TEMPERATURE_MODULE_V1,
THERMOCYCLER_MODULE_V1,
} from '@opentrons/shared-data'
import { TEMPERATURE_DEACTIVATED } from '../../../../constants'
import { getNextDefaultThermocyclerModuleId } from '../getNextDefaultThermocyclerModuleId'

const getThermocycler = () => ({
id: 'tcId',
type: THERMOCYCLER_MODULE_TYPE,
model: THERMOCYCLER_MODULE_V1,
slot: '_span781011',
moduleState: {
type: THERMOCYCLER_MODULE_TYPE,
blockTargetTemp: null,
lidTargetTemp: null,
lidOpen: null,
},
})

const getMag = () => ({
id: 'magId',
type: MAGNETIC_MODULE_TYPE,
model: MAGNETIC_MODULE_V1,
slot: '_span781011',
moduleState: { type: MAGNETIC_MODULE_TYPE, engaged: false },
})

const getTemp = () => ({
id: 'tempId',
type: TEMPERATURE_MODULE_TYPE,
model: TEMPERATURE_MODULE_V1,
slot: '3',
moduleState: {
type: TEMPERATURE_MODULE_TYPE,
status: TEMPERATURE_DEACTIVATED,
targetTemperature: null,
},
})

describe('getNextDefaultThermocyclerModuleId', () => {
describe('NO previous forms', () => {
const testCases = [
{
testMsg: 'temp and TC module present: use TC',
equippedModulesById: {
tempId: getTemp(),
tcId: getThermocycler(),
},
expected: 'tcId',
},
{
testMsg: 'only TC module present: use TC',
equippedModulesById: {
tcId: getThermocycler(),
},
expected: 'tcId',
},

{
testMsg: 'only mag module present: return null',
equippedModulesById: {
magId: getMag(),
},
expected: null,
},
]

testCases.forEach(({ testMsg, equippedModulesById, expected }) => {
it(testMsg, () => {
const savedForms = {}
const orderedStepIds = []

const result = getNextDefaultThermocyclerModuleId(
savedForms,
orderedStepIds,
equippedModulesById
)

expect(result).toBe(expected)
})
})
})

describe('previous forms', () => {
const testCases = [
{
testMsg: 'temp and tc present, last step was tc: use tc mod',
equippedModulesById: {
tempId: getTemp(),
tcId: getThermocycler(),
},
savedForms: {
tempStepId: {
id: 'tempStepId',
stepType: 'temperature',
stepName: 'temperature',
moduleId: 'tempId',
},
tcStepId: {
id: 'tcStepId',
stepType: THERMOCYCLER_MODULE_TYPE,
stepName: THERMOCYCLER_MODULE_TYPE,
moduleId: 'tcId',
},
},
orderedStepIds: ['tempStepId', 'tcStepId'],
expected: 'tcId',
},
{
testMsg: 'temp and mag present return null',
equippedModulesById: {
magId: {
id: 'magId',
type: MAGNETIC_MODULE_TYPE,
model: MAGNETIC_MODULE_V1,
slot: '_span781011',
moduleState: { type: MAGNETIC_MODULE_TYPE, engaged: false },
},
tempId: {
id: 'tempId',
type: TEMPERATURE_MODULE_TYPE,
model: TEMPERATURE_MODULE_V1,
slot: '3',
moduleState: {
type: TEMPERATURE_MODULE_TYPE,
status: TEMPERATURE_DEACTIVATED,
targetTemperature: null,
},
},
},
savedForms: {
tempStepId: {
id: 'tempStepId',
stepType: 'temperature',
stepName: 'temperature',
moduleId: 'tempId',
},
magStepId: {
id: 'magStepId',
stepType: 'magnet',
stepName: 'magnet',
moduleId: 'magdeckId',
},
},
orderedStepIds: ['tempStepId', 'magStepId'],
expected: null,
},
]

testCases.forEach(
({
testMsg,
savedForms = {},
equippedModulesById,
orderedStepIds = [],
expected,
}) => {
it(testMsg, () => {
const result = getNextDefaultThermocyclerModuleId(
savedForms,
orderedStepIds,
equippedModulesById
)

expect(result).toBe(expected)
})
}
)
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// @flow
import findKey from 'lodash/findKey'

import { TEMPERATURE_MODULE_TYPE } from '@opentrons/shared-data'

import type { ModuleOnDeck } from '../../../step-forms'
import type { StepIdType, FormData } from '../../../form-types'

export function getNextDefaultTemperatureModuleId(
savedForms: { [StepIdType]: FormData },
orderedStepIds: Array<StepIdType>,
equippedModulesById: { [moduleId: string]: ModuleOnDeck }
): string | null {
return (
findKey(equippedModulesById, m => m.type === TEMPERATURE_MODULE_TYPE) ||
null
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// @flow
import findKey from 'lodash/findKey'
import { THERMOCYCLER_MODULE_TYPE } from '@opentrons/shared-data'

import type { ModuleOnDeck } from '../../../step-forms'
import type { StepIdType, FormData } from '../../../form-types'

export function getNextDefaultThermocyclerModuleId(
savedForms: { [StepIdType]: FormData },
orderedStepIds: Array<StepIdType>,
equippedModulesById: { [moduleId: string]: ModuleOnDeck }
): string | null {
return (
findKey(equippedModulesById, m => m.type === THERMOCYCLER_MODULE_TYPE) ||
null
)
}
Original file line number Diff line number Diff line change
@@ -1,35 +1,4 @@
// @flow
import findKey from 'lodash/findKey'
import last from 'lodash/last'
import {
TEMPERATURE_MODULE_TYPE,
THERMOCYCLER_MODULE_TYPE,
} from '@opentrons/shared-data'
import { getNextDefaultTemperatureModuleId } from './getNextDefaultTemperatureModuleId'
import { getNextDefaultThermocyclerModuleId } from './getNextDefaultThermocyclerModuleId'

import type { ModuleOnDeck } from '../../../step-forms'
import type { StepIdType, FormData } from '../../../form-types'

const isLastStepTemp = (lastModuleStep: FormData = {}): boolean =>
!!(lastModuleStep.moduleId && lastModuleStep.stepType === 'temperature')

export function getNextDefaultTemperatureModuleId(
savedForms: { [StepIdType]: FormData },
orderedStepIds: Array<StepIdType>,
equippedModulesById: { [moduleId: string]: ModuleOnDeck }
): string | null {
const prevModuleSteps = orderedStepIds
.map(stepId => savedForms[stepId])
.filter(form => form && form.moduleId)

const lastModuleStep = last(prevModuleSteps)

// TODO (ka 2019-12-20): Since we are hiding the thermocylcer module as an option for now,
// should we simplify this to only return temperature modules?
const nextDefaultModule: string | null =
(isLastStepTemp(lastModuleStep) && lastModuleStep.moduleId) ||
findKey(equippedModulesById, m => m.type === TEMPERATURE_MODULE_TYPE) ||
findKey(equippedModulesById, m => m.type === THERMOCYCLER_MODULE_TYPE) ||
null

return nextDefaultModule || null
}
export { getNextDefaultTemperatureModuleId, getNextDefaultThermocyclerModuleId }
Loading

0 comments on commit 32b191b

Please sign in to comment.