@opentrons/shared-data 0.1.2-alpha.0 → 0.1.2-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/js/__tests__/__snapshots__/pipettes.test.ts.snap +5969 -0
- package/js/__tests__/deckSchemas.test.ts +87 -0
- package/js/__tests__/errors.test.js +21 -0
- package/js/__tests__/getAreSlotsAdjacent.test.ts +128 -0
- package/js/__tests__/getWellNamePerMultiTip.test.ts +162 -0
- package/js/__tests__/labwareDefQuirks.test.ts +38 -0
- package/js/__tests__/labwareDefSchemaV1.test.ts +82 -0
- package/js/__tests__/labwareDefSchemaV2.test.ts +298 -0
- package/js/__tests__/moduleAccessors.test.ts +50 -0
- package/js/__tests__/moduleSpecsSchema.test.ts +77 -0
- package/js/__tests__/pipetteSchemaV2.test.ts +107 -0
- package/js/__tests__/pipetteSpecSchemas.test.ts +48 -0
- package/js/__tests__/pipettes.test.ts +58 -0
- package/js/__tests__/protocolSchemaV4.test.ts +137 -0
- package/js/__tests__/protocolSchemaV5.test.ts +137 -0
- package/js/__tests__/protocolSchemaV6.test.ts +132 -0
- package/js/__tests__/protocolSchemaV7.test.ts +64 -0
- package/js/__tests__/protocolValidation.test.ts +83 -0
- package/js/__tests__/sortWells.test.ts +40 -0
- package/js/__tests__/splitWellsOnColumn.test.ts +21 -0
- package/js/__tests__/validateErrors.test.js +34 -0
- package/js/constants.ts +405 -0
- package/js/cypressUtils.ts +35 -0
- package/js/errors.ts +33 -0
- package/js/fixtures.ts +156 -0
- package/js/getLabware.ts +145 -0
- package/js/gripper.ts +29 -0
- package/js/helpers/__tests__/getAdapterName.test.ts +31 -0
- package/js/helpers/__tests__/getDeckDefFromLoadedLabware.test.ts +12 -0
- package/js/helpers/__tests__/getSimplestFlexDeckConfig.test.ts +176 -0
- package/js/helpers/__tests__/getVectorDifference.test.ts +25 -0
- package/js/helpers/__tests__/getVectorSum.test.ts +21 -0
- package/js/helpers/__tests__/labwareInference.test.ts +84 -0
- package/js/helpers/__tests__/orderWells.test.ts +87 -0
- package/js/helpers/__tests__/parseProtocolData.test.ts +165 -0
- package/js/helpers/__tests__/volume.test.ts +108 -0
- package/js/helpers/__tests__/wellSets.test.ts +352 -0
- package/js/helpers/get96Channel384WellPlateWells.ts +44 -0
- package/js/helpers/getAddressableAreasInProtocol.ts +98 -0
- package/js/helpers/getLoadedLabwareDefinitionsByUri.ts +30 -0
- package/js/helpers/getModuleVizDims.ts +118 -0
- package/js/helpers/getOccludedSlotCountForModule.ts +13 -0
- package/js/helpers/getSimplestFlexDeckConfig.ts +183 -0
- package/js/helpers/getVectorDifference.ts +12 -0
- package/js/helpers/getVectorSum.ts +12 -0
- package/js/helpers/getWellNamePerMultiTip.ts +86 -0
- package/js/helpers/getWellTotalVolume.ts +16 -0
- package/js/helpers/index.ts +348 -0
- package/js/helpers/labwareInference.ts +92 -0
- package/js/helpers/orderWells.ts +69 -0
- package/js/helpers/parseProtocolData.ts +141 -0
- package/js/helpers/volume.ts +35 -0
- package/js/helpers/wellIsRect.ts +6 -0
- package/js/helpers/wellSets.ts +155 -0
- package/js/index.ts +14 -0
- package/js/labwareTools/__tests__/__snapshots__/createIrregularLabware.test.ts.snap +3 -0
- package/js/labwareTools/__tests__/__snapshots__/createLabware.test.ts.snap +3 -0
- package/js/labwareTools/__tests__/createDefaultDisplayName.test.ts +111 -0
- package/js/labwareTools/__tests__/createIrregularLabware.test.ts +226 -0
- package/js/labwareTools/__tests__/createLabware.test.ts +147 -0
- package/js/labwareTools/index.ts +452 -0
- package/js/modules.ts +97 -0
- package/js/pipettes.ts +89 -0
- package/js/protocols.ts +290 -0
- package/js/schema.ts +80 -0
- package/js/scripts/generateDeckLayersFromSVG.js +46 -0
- package/js/titleCase.ts +30 -0
- package/js/types.ts +561 -0
- package/lib/js/__tests__/deckSchemas.test.d.ts +1 -0
- package/lib/js/__tests__/getAreSlotsAdjacent.test.d.ts +1 -0
- package/lib/js/__tests__/getWellNamePerMultiTip.test.d.ts +1 -0
- package/lib/js/__tests__/labwareDefQuirks.test.d.ts +1 -0
- package/lib/js/__tests__/labwareDefSchemaV1.test.d.ts +1 -0
- package/lib/js/__tests__/labwareDefSchemaV2.test.d.ts +1 -0
- package/lib/js/__tests__/moduleAccessors.test.d.ts +1 -0
- package/lib/js/__tests__/moduleSpecsSchema.test.d.ts +1 -0
- package/lib/js/__tests__/pipetteSchemaV2.test.d.ts +1 -0
- package/lib/js/__tests__/pipetteSpecSchemas.test.d.ts +1 -0
- package/lib/js/__tests__/pipettes.test.d.ts +1 -0
- package/lib/js/__tests__/protocolSchemaV4.test.d.ts +1 -0
- package/lib/js/__tests__/protocolSchemaV5.test.d.ts +1 -0
- package/lib/js/__tests__/protocolSchemaV6.test.d.ts +1 -0
- package/lib/js/__tests__/protocolSchemaV7.test.d.ts +1 -0
- package/lib/js/__tests__/protocolValidation.test.d.ts +1 -0
- package/lib/js/__tests__/sortWells.test.d.ts +1 -0
- package/lib/js/__tests__/splitWellsOnColumn.test.d.ts +1 -0
- package/lib/js/constants.d.ts +156 -0
- package/lib/js/cypressUtils.d.ts +1 -0
- package/lib/js/errors.d.ts +13 -0
- package/lib/js/fixtures.d.ts +13 -0
- package/lib/js/getLabware.d.ts +8 -0
- package/lib/js/gripper.d.ts +3 -0
- package/lib/js/helpers/__tests__/getAdapterName.test.d.ts +1 -0
- package/lib/js/helpers/__tests__/getDeckDefFromLoadedLabware.test.d.ts +1 -0
- package/lib/js/helpers/__tests__/getSimplestFlexDeckConfig.test.d.ts +1 -0
- package/lib/js/helpers/__tests__/getVectorDifference.test.d.ts +1 -0
- package/lib/js/helpers/__tests__/getVectorSum.test.d.ts +1 -0
- package/lib/js/helpers/__tests__/labwareInference.test.d.ts +1 -0
- package/lib/js/helpers/__tests__/orderWells.test.d.ts +1 -0
- package/lib/js/helpers/__tests__/parseProtocolData.test.d.ts +1 -0
- package/lib/js/helpers/__tests__/volume.test.d.ts +1 -0
- package/lib/js/helpers/__tests__/wellSets.test.d.ts +1 -0
- package/lib/js/helpers/get96Channel384WellPlateWells.d.ts +1 -0
- package/lib/js/helpers/getAddressableAreasInProtocol.d.ts +4 -0
- package/lib/js/helpers/getLoadedLabwareDefinitionsByUri.d.ts +5 -0
- package/lib/js/helpers/getModuleVizDims.d.ts +16 -0
- package/lib/js/helpers/getOccludedSlotCountForModule.d.ts +2 -0
- package/lib/js/helpers/getSimplestFlexDeckConfig.d.ts +14 -0
- package/lib/js/helpers/getVectorDifference.d.ts +2 -0
- package/lib/js/helpers/getVectorSum.d.ts +2 -0
- package/lib/js/helpers/getWellNamePerMultiTip.d.ts +3 -0
- package/lib/js/helpers/getWellTotalVolume.d.ts +2 -0
- package/lib/js/helpers/index.d.ts +44 -0
- package/lib/js/helpers/labwareInference.d.ts +16 -0
- package/lib/js/helpers/orderWells.d.ts +2 -0
- package/lib/js/helpers/parseProtocolData.d.ts +23 -0
- package/lib/js/helpers/volume.d.ts +4 -0
- package/lib/js/helpers/wellIsRect.d.ts +3 -0
- package/lib/js/helpers/wellSets.d.ts +9 -0
- package/lib/js/index.d.ts +14 -0
- package/lib/js/labwareTools/__tests__/createDefaultDisplayName.test.d.ts +1 -0
- package/lib/js/labwareTools/__tests__/createIrregularLabware.test.d.ts +1 -0
- package/lib/js/labwareTools/__tests__/createLabware.test.d.ts +1 -0
- package/lib/js/labwareTools/index.d.ts +65 -0
- package/lib/js/modules.d.ts +6 -0
- package/lib/js/pipettes.d.ts +13 -0
- package/lib/js/protocols.d.ts +3 -0
- package/lib/js/schema.d.ts +90 -0
- package/lib/js/titleCase.d.ts +1 -0
- package/lib/js/types.d.ts +398 -0
- package/package.json +1 -1
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/** Ensure that the deck schema itself functions as intended,
|
|
2
|
+
* and that all v4 protocol fixtures will validate */
|
|
3
|
+
import Ajv from 'ajv'
|
|
4
|
+
import path from 'path'
|
|
5
|
+
import glob from 'glob'
|
|
6
|
+
|
|
7
|
+
import deckSchema from '../../deck/schemas/3.json'
|
|
8
|
+
import deckSchemaV4 from '../../deck/schemas/4.json'
|
|
9
|
+
|
|
10
|
+
const fixtureGlob = path.join(__dirname, '../../deck/fixtures/3/*.json')
|
|
11
|
+
const defGlob = path.join(__dirname, '../../deck/definitions/3/*.json')
|
|
12
|
+
const defV4Glob = path.join(__dirname, '../../deck/definitions/4/*.json')
|
|
13
|
+
|
|
14
|
+
const ajv = new Ajv({ allErrors: true, jsonPointers: true })
|
|
15
|
+
|
|
16
|
+
const validateSchema = ajv.compile(deckSchema)
|
|
17
|
+
const validateSchemaV4 = ajv.compile(deckSchemaV4)
|
|
18
|
+
|
|
19
|
+
describe('validate v3 deck defs and fixtures', () => {
|
|
20
|
+
const fixtures = glob.sync(fixtureGlob)
|
|
21
|
+
|
|
22
|
+
fixtures.forEach(fixturePath => {
|
|
23
|
+
const fixtureDef = require(fixturePath)
|
|
24
|
+
|
|
25
|
+
it('fixture validates against schema', () => {
|
|
26
|
+
const valid = validateSchema(fixtureDef)
|
|
27
|
+
const validationErrors = validateSchema.errors
|
|
28
|
+
|
|
29
|
+
if (validationErrors) {
|
|
30
|
+
console.log(
|
|
31
|
+
path.parse(fixturePath).base +
|
|
32
|
+
' ' +
|
|
33
|
+
JSON.stringify(validationErrors, null, 4)
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
expect(validationErrors).toBe(null)
|
|
38
|
+
expect(valid).toBe(true)
|
|
39
|
+
})
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
const defs = glob.sync(defGlob)
|
|
43
|
+
|
|
44
|
+
defs.forEach(defPath => {
|
|
45
|
+
const deckDef = require(defPath)
|
|
46
|
+
|
|
47
|
+
it('deck validates against v3 schema', () => {
|
|
48
|
+
const valid = validateSchema(deckDef)
|
|
49
|
+
const validationErrors = validateSchema.errors
|
|
50
|
+
|
|
51
|
+
if (validationErrors) {
|
|
52
|
+
console.log(
|
|
53
|
+
path.parse(defPath).base +
|
|
54
|
+
' ' +
|
|
55
|
+
JSON.stringify(validationErrors, null, 4)
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
expect(validationErrors).toBe(null)
|
|
60
|
+
expect(valid).toBe(true)
|
|
61
|
+
})
|
|
62
|
+
})
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
describe('validate v4 deck defs', () => {
|
|
66
|
+
const defs = glob.sync(defV4Glob)
|
|
67
|
+
|
|
68
|
+
defs.forEach(defPath => {
|
|
69
|
+
const deckDef = require(defPath)
|
|
70
|
+
|
|
71
|
+
it('deck validates against v4 schema', () => {
|
|
72
|
+
const valid = validateSchemaV4(deckDef)
|
|
73
|
+
const validationErrors = validateSchemaV4.errors
|
|
74
|
+
|
|
75
|
+
if (validationErrors) {
|
|
76
|
+
console.log(
|
|
77
|
+
path.parse(defPath).base +
|
|
78
|
+
' ' +
|
|
79
|
+
JSON.stringify(validationErrors, null, 4)
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
expect(validationErrors).toBe(null)
|
|
84
|
+
expect(valid).toBe(true)
|
|
85
|
+
})
|
|
86
|
+
})
|
|
87
|
+
})
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// tests for error accessors
|
|
2
|
+
|
|
3
|
+
import { getError } from '../errors'
|
|
4
|
+
|
|
5
|
+
import errorDefinitions from '@opentrons/shared-data/errors/definitions/1/errors.json'
|
|
6
|
+
|
|
7
|
+
Object.keys(errorDefinitions.codes).forEach(errorCode =>
|
|
8
|
+
describe(`error ${errorCode} accessors`, () => {
|
|
9
|
+
it('should be accessible', () => {
|
|
10
|
+
const errorData = getError(errorCode)
|
|
11
|
+
expect(errorData).not.toBeNull()
|
|
12
|
+
expect(errorCode).toMatch(
|
|
13
|
+
new RegExp(`^${errorData.category.codePrefix}.*$`)
|
|
14
|
+
)
|
|
15
|
+
})
|
|
16
|
+
})
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
describe('accessor should handle missing error codes', () =>
|
|
20
|
+
it('should return null for a missing error', () =>
|
|
21
|
+
expect(getError('aaaaa this isnt real')).toBeNull()))
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getAreSlotsAdjacent,
|
|
3
|
+
getAreSlotsHorizontallyAdjacent,
|
|
4
|
+
getAreSlotsVerticallyAdjacent,
|
|
5
|
+
} from '../helpers'
|
|
6
|
+
|
|
7
|
+
describe('getAreSlotsHorizontallyAdjacent', () => {
|
|
8
|
+
it('should return false if a slots are falsey', () => {
|
|
9
|
+
expect(getAreSlotsHorizontallyAdjacent(null, null)).toBe(false)
|
|
10
|
+
expect(getAreSlotsHorizontallyAdjacent()).toBe(false)
|
|
11
|
+
expect(getAreSlotsHorizontallyAdjacent('1')).toBe(false)
|
|
12
|
+
expect(getAreSlotsHorizontallyAdjacent(null, '1')).toBe(false)
|
|
13
|
+
expect(getAreSlotsHorizontallyAdjacent('1', null)).toBe(false)
|
|
14
|
+
})
|
|
15
|
+
it('should return false if called with a non numerical slot', () => {
|
|
16
|
+
expect(getAreSlotsHorizontallyAdjacent('1', 'not a numerical slot')).toBe(
|
|
17
|
+
false
|
|
18
|
+
)
|
|
19
|
+
})
|
|
20
|
+
it('should return false if called with a slot that is larger than the number of slots in the deck def', () => {
|
|
21
|
+
expect(getAreSlotsHorizontallyAdjacent('1', '12')).toBe(false) // trash slot does not count
|
|
22
|
+
expect(getAreSlotsHorizontallyAdjacent('1', '13')).toBe(false)
|
|
23
|
+
})
|
|
24
|
+
it('should return false if the slots vertically adjacent', () => {
|
|
25
|
+
expect(getAreSlotsHorizontallyAdjacent('1', '4')).toBe(false)
|
|
26
|
+
expect(getAreSlotsHorizontallyAdjacent('2', '5')).toBe(false)
|
|
27
|
+
expect(getAreSlotsHorizontallyAdjacent('3', '6')).toBe(false)
|
|
28
|
+
})
|
|
29
|
+
it('should return false if slots are horizontal but separated by a slot', () => {
|
|
30
|
+
expect(getAreSlotsHorizontallyAdjacent('1', '3')).toBe(false)
|
|
31
|
+
expect(getAreSlotsHorizontallyAdjacent('4', '6')).toBe(false)
|
|
32
|
+
expect(getAreSlotsHorizontallyAdjacent('7', '9')).toBe(false)
|
|
33
|
+
})
|
|
34
|
+
it('should return true if the slots horizontally adjacent', () => {
|
|
35
|
+
expect(getAreSlotsHorizontallyAdjacent('1', '2')).toBe(true)
|
|
36
|
+
expect(getAreSlotsHorizontallyAdjacent('2', '3')).toBe(true)
|
|
37
|
+
expect(getAreSlotsHorizontallyAdjacent('4', '5')).toBe(true)
|
|
38
|
+
expect(getAreSlotsHorizontallyAdjacent('5', '6')).toBe(true)
|
|
39
|
+
expect(getAreSlotsHorizontallyAdjacent('7', '8')).toBe(true)
|
|
40
|
+
expect(getAreSlotsHorizontallyAdjacent('8', '9')).toBe(true)
|
|
41
|
+
expect(getAreSlotsHorizontallyAdjacent('8', '9')).toBe(true)
|
|
42
|
+
expect(getAreSlotsHorizontallyAdjacent('10', '11')).toBe(true)
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
describe('getAreSlotsVerticallyAdjacent', () => {
|
|
46
|
+
it('should return false if a slots are falsey', () => {
|
|
47
|
+
expect(getAreSlotsVerticallyAdjacent(null, null)).toBe(false)
|
|
48
|
+
expect(getAreSlotsVerticallyAdjacent()).toBe(false)
|
|
49
|
+
expect(getAreSlotsVerticallyAdjacent('1')).toBe(false)
|
|
50
|
+
expect(getAreSlotsVerticallyAdjacent(null, '1')).toBe(false)
|
|
51
|
+
expect(getAreSlotsVerticallyAdjacent('1', null)).toBe(false)
|
|
52
|
+
})
|
|
53
|
+
it('should return false if called with a non numerical slot', () => {
|
|
54
|
+
expect(getAreSlotsVerticallyAdjacent('1', 'not a numerical slot')).toBe(
|
|
55
|
+
false
|
|
56
|
+
)
|
|
57
|
+
})
|
|
58
|
+
it('should return false if called with a slot that is larger than the number of slots in the deck def', () => {
|
|
59
|
+
expect(getAreSlotsVerticallyAdjacent('1', '12')).toBe(false) // trash slot does not count
|
|
60
|
+
expect(getAreSlotsVerticallyAdjacent('1', '13')).toBe(false)
|
|
61
|
+
})
|
|
62
|
+
it('should return false if the slots horizontally adjacent', () => {
|
|
63
|
+
expect(getAreSlotsVerticallyAdjacent('1', '2')).toBe(false)
|
|
64
|
+
expect(getAreSlotsVerticallyAdjacent('2', '3')).toBe(false)
|
|
65
|
+
expect(getAreSlotsVerticallyAdjacent('4', '5')).toBe(false)
|
|
66
|
+
})
|
|
67
|
+
it('should return false if slots are vetical but separated by a slot', () => {
|
|
68
|
+
expect(getAreSlotsVerticallyAdjacent('1', '7')).toBe(false)
|
|
69
|
+
expect(getAreSlotsVerticallyAdjacent('2', '8')).toBe(false)
|
|
70
|
+
expect(getAreSlotsVerticallyAdjacent('3', '9')).toBe(false)
|
|
71
|
+
})
|
|
72
|
+
it('should return true if the slots vertically adjacent', () => {
|
|
73
|
+
expect(getAreSlotsVerticallyAdjacent('1', '4')).toBe(true)
|
|
74
|
+
expect(getAreSlotsVerticallyAdjacent('2', '5')).toBe(true)
|
|
75
|
+
expect(getAreSlotsVerticallyAdjacent('3', '6')).toBe(true)
|
|
76
|
+
expect(getAreSlotsVerticallyAdjacent('4', '7')).toBe(true)
|
|
77
|
+
expect(getAreSlotsVerticallyAdjacent('5', '8')).toBe(true)
|
|
78
|
+
expect(getAreSlotsVerticallyAdjacent('6', '9')).toBe(true)
|
|
79
|
+
expect(getAreSlotsVerticallyAdjacent('7', '10')).toBe(true)
|
|
80
|
+
expect(getAreSlotsVerticallyAdjacent('8', '11')).toBe(true)
|
|
81
|
+
})
|
|
82
|
+
})
|
|
83
|
+
describe('getAreSlotsAdjacent', () => {
|
|
84
|
+
it('should return false if a slots are falsey', () => {
|
|
85
|
+
expect(getAreSlotsAdjacent(null, null)).toBe(false)
|
|
86
|
+
expect(getAreSlotsAdjacent()).toBe(false)
|
|
87
|
+
expect(getAreSlotsAdjacent('1')).toBe(false)
|
|
88
|
+
expect(getAreSlotsAdjacent(null, '1')).toBe(false)
|
|
89
|
+
expect(getAreSlotsAdjacent('1', null)).toBe(false)
|
|
90
|
+
})
|
|
91
|
+
it('should return false if called with a non numerical slot', () => {
|
|
92
|
+
expect(getAreSlotsAdjacent('1', 'not a numerical slot')).toBe(false)
|
|
93
|
+
})
|
|
94
|
+
it('should return false if called with a slot that is larger than the number of slots in the deck def', () => {
|
|
95
|
+
expect(getAreSlotsAdjacent('1', '12')).toBe(false) // trash slot does not count
|
|
96
|
+
expect(getAreSlotsAdjacent('1', '13')).toBe(false)
|
|
97
|
+
})
|
|
98
|
+
it('should return false if slots are horizontal but separated by a slot', () => {
|
|
99
|
+
expect(getAreSlotsHorizontallyAdjacent('1', '3')).toBe(false)
|
|
100
|
+
expect(getAreSlotsHorizontallyAdjacent('4', '6')).toBe(false)
|
|
101
|
+
expect(getAreSlotsHorizontallyAdjacent('7', '9')).toBe(false)
|
|
102
|
+
})
|
|
103
|
+
it('should return false if slots are vetical but separated by a slot', () => {
|
|
104
|
+
expect(getAreSlotsAdjacent('1', '7')).toBe(false)
|
|
105
|
+
expect(getAreSlotsAdjacent('2', '8')).toBe(false)
|
|
106
|
+
expect(getAreSlotsAdjacent('3', '9')).toBe(false)
|
|
107
|
+
})
|
|
108
|
+
it('should return true if the slots adjacent', () => {
|
|
109
|
+
// horizontally
|
|
110
|
+
expect(getAreSlotsHorizontallyAdjacent('1', '2')).toBe(true)
|
|
111
|
+
expect(getAreSlotsHorizontallyAdjacent('2', '3')).toBe(true)
|
|
112
|
+
expect(getAreSlotsHorizontallyAdjacent('4', '5')).toBe(true)
|
|
113
|
+
expect(getAreSlotsHorizontallyAdjacent('5', '6')).toBe(true)
|
|
114
|
+
expect(getAreSlotsHorizontallyAdjacent('7', '8')).toBe(true)
|
|
115
|
+
expect(getAreSlotsHorizontallyAdjacent('8', '9')).toBe(true)
|
|
116
|
+
expect(getAreSlotsHorizontallyAdjacent('8', '9')).toBe(true)
|
|
117
|
+
expect(getAreSlotsHorizontallyAdjacent('10', '11')).toBe(true)
|
|
118
|
+
// vertically
|
|
119
|
+
expect(getAreSlotsAdjacent('1', '4')).toBe(true)
|
|
120
|
+
expect(getAreSlotsAdjacent('2', '5')).toBe(true)
|
|
121
|
+
expect(getAreSlotsAdjacent('3', '6')).toBe(true)
|
|
122
|
+
expect(getAreSlotsAdjacent('4', '7')).toBe(true)
|
|
123
|
+
expect(getAreSlotsAdjacent('5', '8')).toBe(true)
|
|
124
|
+
expect(getAreSlotsAdjacent('6', '9')).toBe(true)
|
|
125
|
+
expect(getAreSlotsAdjacent('7', '10')).toBe(true)
|
|
126
|
+
expect(getAreSlotsAdjacent('8', '11')).toBe(true)
|
|
127
|
+
})
|
|
128
|
+
})
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import fixture_trash from '@opentrons/shared-data/labware/fixtures/2/fixture_trash.json'
|
|
2
|
+
import fixture_96_plate from '@opentrons/shared-data/labware/fixtures/2/fixture_96_plate.json'
|
|
3
|
+
import fixture_384_plate from '@opentrons/shared-data/labware/fixtures/2/fixture_384_plate.json'
|
|
4
|
+
import fixture_12_trough from '@opentrons/shared-data/labware/fixtures/2/fixture_12_trough.json'
|
|
5
|
+
import fixture_24_tuberack from '@opentrons/shared-data/labware/fixtures/2/fixture_24_tuberack.json'
|
|
6
|
+
|
|
7
|
+
import { getWellNamePerMultiTip } from '../helpers/getWellNamePerMultiTip'
|
|
8
|
+
|
|
9
|
+
import type { LabwareDefinition2 } from '../types'
|
|
10
|
+
|
|
11
|
+
const fixtureTrash = fixture_trash as LabwareDefinition2
|
|
12
|
+
const fixture96Plate = fixture_96_plate as LabwareDefinition2
|
|
13
|
+
const fixture384Plate = fixture_384_plate as LabwareDefinition2
|
|
14
|
+
const fixture12Trough = fixture_12_trough as LabwareDefinition2
|
|
15
|
+
const fixture24Tuberack = fixture_24_tuberack as LabwareDefinition2
|
|
16
|
+
const EIGHT_CHANNEL = 8
|
|
17
|
+
|
|
18
|
+
describe('96 plate', () => {
|
|
19
|
+
const labware = fixture96Plate
|
|
20
|
+
|
|
21
|
+
it('A1 => column 1', () => {
|
|
22
|
+
expect(getWellNamePerMultiTip(labware, 'A1', EIGHT_CHANNEL)).toEqual([
|
|
23
|
+
'A1',
|
|
24
|
+
'B1',
|
|
25
|
+
'C1',
|
|
26
|
+
'D1',
|
|
27
|
+
'E1',
|
|
28
|
+
'F1',
|
|
29
|
+
'G1',
|
|
30
|
+
'H1',
|
|
31
|
+
])
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it('A2 => column 2', () => {
|
|
35
|
+
expect(getWellNamePerMultiTip(labware, 'A2', EIGHT_CHANNEL)).toEqual([
|
|
36
|
+
'A2',
|
|
37
|
+
'B2',
|
|
38
|
+
'C2',
|
|
39
|
+
'D2',
|
|
40
|
+
'E2',
|
|
41
|
+
'F2',
|
|
42
|
+
'G2',
|
|
43
|
+
'H2',
|
|
44
|
+
])
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('B1 => null (cannot access with 8-channel)', () => {
|
|
48
|
+
expect(getWellNamePerMultiTip(labware, 'B1', EIGHT_CHANNEL)).toEqual(null)
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
describe('384 plate', () => {
|
|
53
|
+
const labware = fixture384Plate
|
|
54
|
+
|
|
55
|
+
it('A1 => column 1 ACEGIKMO', () => {
|
|
56
|
+
expect(getWellNamePerMultiTip(labware, 'A1', EIGHT_CHANNEL)).toEqual([
|
|
57
|
+
'A1',
|
|
58
|
+
'C1',
|
|
59
|
+
'E1',
|
|
60
|
+
'G1',
|
|
61
|
+
'I1',
|
|
62
|
+
'K1',
|
|
63
|
+
'M1',
|
|
64
|
+
'O1',
|
|
65
|
+
])
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('A2 => column 2 ACEGIKMO', () => {
|
|
69
|
+
expect(getWellNamePerMultiTip(labware, 'A2', EIGHT_CHANNEL)).toEqual([
|
|
70
|
+
'A2',
|
|
71
|
+
'C2',
|
|
72
|
+
'E2',
|
|
73
|
+
'G2',
|
|
74
|
+
'I2',
|
|
75
|
+
'K2',
|
|
76
|
+
'M2',
|
|
77
|
+
'O2',
|
|
78
|
+
])
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
it('B1 => column 1 BDFHJLNP', () => {
|
|
82
|
+
expect(getWellNamePerMultiTip(labware, 'B1', EIGHT_CHANNEL)).toEqual([
|
|
83
|
+
'B1',
|
|
84
|
+
'D1',
|
|
85
|
+
'F1',
|
|
86
|
+
'H1',
|
|
87
|
+
'J1',
|
|
88
|
+
'L1',
|
|
89
|
+
'N1',
|
|
90
|
+
'P1',
|
|
91
|
+
])
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
it('C1 => null (cannot access with 8-channel)', () => {
|
|
95
|
+
expect(getWellNamePerMultiTip(labware, 'C1', EIGHT_CHANNEL)).toEqual(null)
|
|
96
|
+
})
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
describe('Fixed trash', () => {
|
|
100
|
+
const labware = fixtureTrash
|
|
101
|
+
|
|
102
|
+
it('A1 => all tips in A1', () => {
|
|
103
|
+
expect(getWellNamePerMultiTip(labware, 'A1', EIGHT_CHANNEL)).toEqual([
|
|
104
|
+
'A1',
|
|
105
|
+
'A1',
|
|
106
|
+
'A1',
|
|
107
|
+
'A1',
|
|
108
|
+
'A1',
|
|
109
|
+
'A1',
|
|
110
|
+
'A1',
|
|
111
|
+
'A1',
|
|
112
|
+
])
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
it('A2 => null (well does not exist)', () => {
|
|
116
|
+
expect(getWellNamePerMultiTip(labware, 'A2', EIGHT_CHANNEL)).toEqual(null)
|
|
117
|
+
})
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
describe('tube rack 2mL', () => {
|
|
121
|
+
const labware = fixture24Tuberack
|
|
122
|
+
|
|
123
|
+
it('tube rack 2mL not accessible by 8-channel (return null)', () => {
|
|
124
|
+
;['A1', 'A2', 'B1', 'B2'].forEach(well => {
|
|
125
|
+
expect(getWellNamePerMultiTip(labware, well, EIGHT_CHANNEL)).toEqual(null)
|
|
126
|
+
})
|
|
127
|
+
})
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
describe('12 channel trough', () => {
|
|
131
|
+
const labware = fixture12Trough
|
|
132
|
+
|
|
133
|
+
it('A1 => all tips in A1', () => {
|
|
134
|
+
expect(getWellNamePerMultiTip(labware, 'A1', EIGHT_CHANNEL)).toEqual([
|
|
135
|
+
'A1',
|
|
136
|
+
'A1',
|
|
137
|
+
'A1',
|
|
138
|
+
'A1',
|
|
139
|
+
'A1',
|
|
140
|
+
'A1',
|
|
141
|
+
'A1',
|
|
142
|
+
'A1',
|
|
143
|
+
])
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
it('A2 => all tips in A2', () => {
|
|
147
|
+
expect(getWellNamePerMultiTip(labware, 'A2', EIGHT_CHANNEL)).toEqual([
|
|
148
|
+
'A2',
|
|
149
|
+
'A2',
|
|
150
|
+
'A2',
|
|
151
|
+
'A2',
|
|
152
|
+
'A2',
|
|
153
|
+
'A2',
|
|
154
|
+
'A2',
|
|
155
|
+
'A2',
|
|
156
|
+
])
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
it('B1 => null (well does not exist)', () => {
|
|
160
|
+
expect(getWellNamePerMultiTip(labware, 'B1', EIGHT_CHANNEL)).toEqual(null)
|
|
161
|
+
})
|
|
162
|
+
})
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import path from 'path'
|
|
2
|
+
import glob from 'glob'
|
|
3
|
+
|
|
4
|
+
const definitionsGlobPath = path.join(
|
|
5
|
+
__dirname,
|
|
6
|
+
'../../labware/definitions/2/**/*.json'
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
const EXPECTED_VALID_QUIRKS = [
|
|
10
|
+
'centerMultichannelOnWells',
|
|
11
|
+
'touchTipDisabled',
|
|
12
|
+
'fixedTrash',
|
|
13
|
+
'gripperIncompatible',
|
|
14
|
+
'tiprackAdapterFor96Channel',
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
describe('check quirks for all labware defs', () => {
|
|
18
|
+
const labwarePaths = glob.sync(definitionsGlobPath)
|
|
19
|
+
|
|
20
|
+
beforeAll(() => {
|
|
21
|
+
// Make sure definitions path didn't break, which would give you false positives
|
|
22
|
+
expect(labwarePaths.length).toBeGreaterThan(0)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
labwarePaths.forEach(labwarePath => {
|
|
26
|
+
const defname = path.basename(path.dirname(labwarePath))
|
|
27
|
+
|
|
28
|
+
it(`${defname} has valid quirks`, () => {
|
|
29
|
+
const labwareDef = require(labwarePath)
|
|
30
|
+
|
|
31
|
+
const quirks = labwareDef.parameters.quirks || []
|
|
32
|
+
// we want to test that the quirks in the def are a subset of validQuirks,
|
|
33
|
+
// whereas arrayContaining tests that the expected value is a subset of
|
|
34
|
+
// the value under test. Unfortunately that means we have to do it backwards
|
|
35
|
+
expect(EXPECTED_VALID_QUIRKS).toEqual(expect.arrayContaining(quirks))
|
|
36
|
+
})
|
|
37
|
+
})
|
|
38
|
+
})
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import path from 'path'
|
|
2
|
+
import glob from 'glob'
|
|
3
|
+
import Ajv from 'ajv'
|
|
4
|
+
|
|
5
|
+
import { labwareSchemaV1 } from '../schema'
|
|
6
|
+
import type { LabwareDefinition1 } from '../types'
|
|
7
|
+
|
|
8
|
+
const DEFINITIONS_GLOB_PATTERN = '../../labware/definitions/1/*.json'
|
|
9
|
+
const GLOB_OPTIONS = { absolute: true, cwd: __dirname }
|
|
10
|
+
|
|
11
|
+
// JSON Schema defintion & setup
|
|
12
|
+
const ajv = new Ajv({ allErrors: true, jsonPointers: true })
|
|
13
|
+
const validate = ajv.compile(labwareSchemaV1)
|
|
14
|
+
|
|
15
|
+
describe('test the schema against a minimalist fixture', () => {
|
|
16
|
+
it('...', () => {
|
|
17
|
+
const minimalLabwareDef = {
|
|
18
|
+
metadata: { name: 'test-labware', format: 'trough' },
|
|
19
|
+
ordering: [['A1']],
|
|
20
|
+
wells: {
|
|
21
|
+
A1: {
|
|
22
|
+
depth: 40,
|
|
23
|
+
height: 40,
|
|
24
|
+
length: 70,
|
|
25
|
+
'total-liquid-volume': 22000,
|
|
26
|
+
width: 7,
|
|
27
|
+
x: 10.84,
|
|
28
|
+
y: 7.75,
|
|
29
|
+
z: 0,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
}
|
|
33
|
+
const valid = validate(minimalLabwareDef)
|
|
34
|
+
const validationErrors = validate.errors
|
|
35
|
+
|
|
36
|
+
expect(validationErrors).toBe(null)
|
|
37
|
+
expect(valid).toBe(true)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('fail on bad labware', () => {
|
|
41
|
+
const badDef = {
|
|
42
|
+
metadata: { name: 'bad' },
|
|
43
|
+
ordering: ['A1'],
|
|
44
|
+
// array of strings not array of arrays
|
|
45
|
+
wells: {},
|
|
46
|
+
}
|
|
47
|
+
const valid = validate(badDef)
|
|
48
|
+
const validationErrors = validate.errors
|
|
49
|
+
|
|
50
|
+
expect(
|
|
51
|
+
validationErrors?.find(err => err.dataPath === '/ordering/0')
|
|
52
|
+
).toMatchObject({
|
|
53
|
+
message: 'should be array',
|
|
54
|
+
})
|
|
55
|
+
expect(valid).toBe(false)
|
|
56
|
+
})
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
describe('test schemas of all definitions', () => {
|
|
60
|
+
const labwarePaths = glob.sync(DEFINITIONS_GLOB_PATTERN, GLOB_OPTIONS)
|
|
61
|
+
|
|
62
|
+
beforeAll(() => {
|
|
63
|
+
// Make sure definitions path didn't break, which would give you false positives
|
|
64
|
+
expect(labwarePaths.length).toBeGreaterThan(0)
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
labwarePaths.forEach(labwarePath => {
|
|
68
|
+
const filename = path.parse(labwarePath).name
|
|
69
|
+
const labwareDef = require(labwarePath) as LabwareDefinition1
|
|
70
|
+
|
|
71
|
+
it(filename, () => {
|
|
72
|
+
const valid = validate(labwareDef)
|
|
73
|
+
const validationErrors = validate.errors
|
|
74
|
+
expect(validationErrors).toBe(null)
|
|
75
|
+
expect(valid).toBe(true)
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
it(`file name matches metadata.name: ${filename}`, () => {
|
|
79
|
+
expect(labwareDef.metadata.name).toEqual(filename)
|
|
80
|
+
})
|
|
81
|
+
})
|
|
82
|
+
})
|