From 32b191b4b2fcaee2b30b23a72895da53f17d0c86 Mon Sep 17 00:00:00 2001
From: Katie Adee <kaa328@nyu.edu>
Date: Tue, 12 May 2020 10:23:41 -0400
Subject: [PATCH] feat(protocol-designer): Implement presaved step form for TC
 state (#5641)

closes #5596
---
 .../test/createPresavedStepForm.test.js       |  30 +++
 .../utils/createPresavedStepForm.js           |  30 +++
 .../formLevel/getDefaultsForStepType.js       |   1 +
 ...getNextDefaultTemperatureModuleId.test.js} |  11 +-
 ...getNextDefaultThermocyclerModuleId.test.js | 176 ++++++++++++++++++
 .../getNextDefaultTemperatureModuleId.js      |  18 ++
 .../getNextDefaultThermocyclerModuleId.js     |  17 ++
 .../formLevel/getNextDefaultModuleId/index.js |  37 +---
 .../src/steplist/formLevel/index.js           |   5 +-
 9 files changed, 281 insertions(+), 44 deletions(-)
 rename protocol-designer/src/steplist/formLevel/getNextDefaultModuleId/__tests__/{getNextDefaultModuleId.test.js => getNextDefaultTemperatureModuleId.test.js} (92%)
 create mode 100644 protocol-designer/src/steplist/formLevel/getNextDefaultModuleId/__tests__/getNextDefaultThermocyclerModuleId.test.js
 create mode 100644 protocol-designer/src/steplist/formLevel/getNextDefaultModuleId/getNextDefaultTemperatureModuleId.js
 create mode 100644 protocol-designer/src/steplist/formLevel/getNextDefaultModuleId/getNextDefaultThermocyclerModuleId.js

diff --git a/protocol-designer/src/step-forms/test/createPresavedStepForm.test.js b/protocol-designer/src/step-forms/test/createPresavedStepForm.test.js
index 3e2d69892cf..3d2451a89fe 100644
--- a/protocol-designer/src/step-forms/test/createPresavedStepForm.test.js
+++ b/protocol-designer/src/step-forms/test/createPresavedStepForm.test.js
@@ -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 {
@@ -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' } },
     },
@@ -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,
+    })
+  })
 })
diff --git a/protocol-designer/src/step-forms/utils/createPresavedStepForm.js b/protocol-designer/src/step-forms/utils/createPresavedStepForm.js
index 12c8ba63c57..e68cba8a723 100644
--- a/protocol-designer/src/step-forms/utils/createPresavedStepForm.js
+++ b/protocol-designer/src/step-forms/utils/createPresavedStepForm.js
@@ -6,6 +6,7 @@ import {
   getNextDefaultMagnetAction,
   getNextDefaultPipetteId,
   getNextDefaultTemperatureModuleId,
+  getNextDefaultThermocyclerModuleId,
   handleFormChange,
 } from '../../steplist/formLevel'
 import {
@@ -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,
@@ -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) => {
diff --git a/protocol-designer/src/steplist/formLevel/getDefaultsForStepType.js b/protocol-designer/src/steplist/formLevel/getDefaultsForStepType.js
index eade086daf6..64d7119a882 100644
--- a/protocol-designer/src/steplist/formLevel/getDefaultsForStepType.js
+++ b/protocol-designer/src/steplist/formLevel/getDefaultsForStepType.js
@@ -100,6 +100,7 @@ export function getDefaultsForStepType(
         blockIsActive: false,
         blockTargetTemp: null,
         lidIsActive: false,
+        lidTargetTemp: null,
         lidOpen: null,
       }
     default:
diff --git a/protocol-designer/src/steplist/formLevel/getNextDefaultModuleId/__tests__/getNextDefaultModuleId.test.js b/protocol-designer/src/steplist/formLevel/getNextDefaultModuleId/__tests__/getNextDefaultTemperatureModuleId.test.js
similarity index 92%
rename from protocol-designer/src/steplist/formLevel/getNextDefaultModuleId/__tests__/getNextDefaultModuleId.test.js
rename to protocol-designer/src/steplist/formLevel/getNextDefaultModuleId/__tests__/getNextDefaultTemperatureModuleId.test.js
index 27f65e41f93..e666c7625ba 100644
--- a/protocol-designer/src/steplist/formLevel/getNextDefaultModuleId/__tests__/getNextDefaultModuleId.test.js
+++ b/protocol-designer/src/steplist/formLevel/getNextDefaultModuleId/__tests__/getNextDefaultTemperatureModuleId.test.js
@@ -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',
@@ -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: {
@@ -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 = [
       {
diff --git a/protocol-designer/src/steplist/formLevel/getNextDefaultModuleId/__tests__/getNextDefaultThermocyclerModuleId.test.js b/protocol-designer/src/steplist/formLevel/getNextDefaultModuleId/__tests__/getNextDefaultThermocyclerModuleId.test.js
new file mode 100644
index 00000000000..1bf94137184
--- /dev/null
+++ b/protocol-designer/src/steplist/formLevel/getNextDefaultModuleId/__tests__/getNextDefaultThermocyclerModuleId.test.js
@@ -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)
+        })
+      }
+    )
+  })
+})
diff --git a/protocol-designer/src/steplist/formLevel/getNextDefaultModuleId/getNextDefaultTemperatureModuleId.js b/protocol-designer/src/steplist/formLevel/getNextDefaultModuleId/getNextDefaultTemperatureModuleId.js
new file mode 100644
index 00000000000..8399b2d618b
--- /dev/null
+++ b/protocol-designer/src/steplist/formLevel/getNextDefaultModuleId/getNextDefaultTemperatureModuleId.js
@@ -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
+  )
+}
diff --git a/protocol-designer/src/steplist/formLevel/getNextDefaultModuleId/getNextDefaultThermocyclerModuleId.js b/protocol-designer/src/steplist/formLevel/getNextDefaultModuleId/getNextDefaultThermocyclerModuleId.js
new file mode 100644
index 00000000000..b7c6a51b650
--- /dev/null
+++ b/protocol-designer/src/steplist/formLevel/getNextDefaultModuleId/getNextDefaultThermocyclerModuleId.js
@@ -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
+  )
+}
diff --git a/protocol-designer/src/steplist/formLevel/getNextDefaultModuleId/index.js b/protocol-designer/src/steplist/formLevel/getNextDefaultModuleId/index.js
index 252b599e9c9..8da44aafa30 100644
--- a/protocol-designer/src/steplist/formLevel/getNextDefaultModuleId/index.js
+++ b/protocol-designer/src/steplist/formLevel/getNextDefaultModuleId/index.js
@@ -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 }
diff --git a/protocol-designer/src/steplist/formLevel/index.js b/protocol-designer/src/steplist/formLevel/index.js
index 7b6a95b4ecd..92e5dfb3054 100644
--- a/protocol-designer/src/steplist/formLevel/index.js
+++ b/protocol-designer/src/steplist/formLevel/index.js
@@ -30,7 +30,10 @@ export { createBlankForm } from './createBlankForm'
 export { getDefaultsForStepType } from './getDefaultsForStepType'
 export { getDisabledFields } from './getDisabledFields'
 export { getNextDefaultPipetteId } from './getNextDefaultPipetteId'
-export { getNextDefaultTemperatureModuleId } from './getNextDefaultModuleId'
+export {
+  getNextDefaultTemperatureModuleId,
+  getNextDefaultThermocyclerModuleId,
+} from './getNextDefaultModuleId'
 export { getNextDefaultMagnetAction } from './getNextDefaultMagnetAction'
 export { getNextDefaultEngageHeight } from './getNextDefaultEngageHeight'
 export { stepFormToArgs } from './stepFormToArgs'