feat: hive setup data model and API (Beute L1)
Backend Image / build-and-push (push) Successful in 5m5s
Frontend Image / build-and-push (push) Successful in 11m2s

Each colony can now hold its hive setup (Ist-Zustand) as validated
JSON with an append-only change log:

- catalog: hive systems and part types with dimensions, placement
  rules and state fields; Liebig-Zander 10 seeded with fixed ids
  (owner's equipment incl. Bausperre, Futterzarge, Nassenheider)
- pure domain module (operations, validator, derived facts) with
  shared JSON fixtures the frontend runs too
- API: catalog (hive-systems:manage), setup create/change/history/
  state at a day (colonies:read/update), 409 HIVE_CONFLICT with the
  current state, idempotent writes, HiveChanged event
- inspections can carry hive ops saved in the same transaction
- backup export/import of the new tables (backup wins per colony)
- docs: ARCHITECTURE section 13, Annahmen 95-100

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
Nick SzaunigandClaude Opus 5.5 committed 2026-10-15 21:23:23 +02:00
1 parent 8982d0796a
commit b48fb157c8
141 files changed
+15211 -17

No files matched your search

+150
View File
@@ -601,6 +601,156 @@ describe('Backup round trip (e2e)', () => {
).toBeNull();
});
it(
'restores hive setup and history into a fresh install with the seeded catalog',
async () => {
const systemId = 'hive-system-zander-liebig-10';
const day = new Date('2026-07-02T00:00:00.000Z');
const state = { schemaVersion: 1, stack: [{ id: 'p1', kind: 'FLOOR' }] };
const apiary = await prisma.apiary.create({
data: { name: `Hive-Stand ${suffix}` },
});
const colony = await prisma.colony.create({
data: {
code: `HV-${suffix}`,
apiaryId: apiary.id,
colonyType: 'PRODUCTION_COLONY',
},
});
const inspection = await prisma.inspection.create({
data: { colonyId: colony.id, userId, date: day },
});
await prisma.hiveSetup.create({
data: { colonyId: colony.id, systemId, version: 2, state },
});
await prisma.hiveChange.createMany({
data: [
{
colonyId: colony.id,
version: 1,
occurredOn: day,
source: 'INIT',
userId,
ops: [],
stateAfter: state,
},
{
colonyId: colony.id,
version: 2,
occurredOn: day,
source: 'INSPECTION',
inspectionId: inspection.id,
userId,
ops: [{ op: 'SET_NOTE' }],
stateAfter: state,
note: 'Beute',
},
],
});
const catalogCounts = async () => ({
systems: await prisma.hiveSystem.count(),
partTypes: await prisma.hivePartType.count(),
});
const catalogBefore = await catalogCounts();
expect(catalogBefore.systems).toBeGreaterThan(0);
expect(catalogBefore.partTypes).toBeGreaterThan(0);
const hiveRows = async () => ({
setup: await prisma.hiveSetup.findUnique({
where: { colonyId: colony.id },
}),
changes: await prisma.hiveChange.findMany({
where: { colonyId: colony.id },
orderBy: { version: 'asc' },
}),
});
const before = await hiveRows();
try {
const bundle = await backup.exportAll();
const ownColonyRows = (bundle.data.colony as Row[]).filter(
(row) => row.id === colony.id,
);
const exportedHive = {
hiveSystem: bundle.data.hiveSystem as Row[],
hivePartType: bundle.data.hivePartType as Row[],
colony: ownColonyRows,
inspection: (bundle.data.inspection as Row[]).filter(
(row) => row.id === inspection.id,
),
hiveSetup: (bundle.data.hiveSetup as Row[]).filter(
(row) => row.colonyId === colony.id,
),
hiveChange: (bundle.data.hiveChange as Row[]).filter(
(row) => row.colonyId === colony.id,
),
};
expect(exportedHive.hiveSetup).toHaveLength(1);
expect(exportedHive.hiveChange).toHaveLength(2);
expect(exportedHive.hiveSystem.some((row) => row.id === systemId)).toBe(
true,
);
// The colony is lost; the catalog rows stay, as a fresh install has
// them from the migration.
await prisma.hiveChange.deleteMany({ where: { colonyId: colony.id } });
await prisma.hiveSetup.delete({ where: { colonyId: colony.id } });
await prisma.inspection.delete({ where: { id: inspection.id } });
await prisma.colony.delete({ where: { id: colony.id } });
const summary = await backup.importAll(
{
version: 3,
exportedAt: new Date().toISOString(),
data: exportedHive,
},
userId,
{ trusted: true },
);
expect(summary.imported).toMatchObject({
hiveSetup: 1,
hiveChange: 2,
});
expect(await hiveRows()).toEqual(before);
expect(await catalogCounts()).toEqual(catalogBefore);
// A second restore over an existing, diverged setup: the backup wins.
await prisma.hiveSetup.update({
where: { colonyId: colony.id },
data: { version: 9 },
});
await prisma.hiveChange.create({
data: {
colonyId: colony.id,
version: 9,
occurredOn: day,
source: 'CARD',
userId,
ops: [],
stateAfter: state,
},
});
await backup.importAll(
{
version: 3,
exportedAt: new Date().toISOString(),
data: exportedHive,
},
userId,
{ trusted: true },
);
expect(await hiveRows()).toEqual(before);
expect(await catalogCounts()).toEqual(catalogBefore);
} finally {
await prisma.hiveChange.deleteMany({ where: { colonyId: colony.id } });
await prisma.hiveSetup.deleteMany({ where: { colonyId: colony.id } });
await prisma.inspection.deleteMany({ where: { colonyId: colony.id } });
await prisma.colony.deleteMany({ where: { id: colony.id } });
await prisma.apiary.deleteMany({ where: { id: apiary.id } });
}
},
ROUND_TRIP_TIMEOUT_MS,
);
it('removes the file a restored document row replaced', async () => {
const directory = path.join(
path.resolve(process.env.DOCUMENTS_STORAGE_PATH ?? './uploads'),
@@ -0,0 +1,146 @@
{
"name": "addPart inserts at index",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addPart",
"part": {
"id": "q1",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
"at": 2
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "q1",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
}
}
}
@@ -0,0 +1,136 @@
{
"name": "addPart at beyond end is clamped to end",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
}
]
},
"ops": [
{
"op": "addPart",
"part": {
"id": "q1",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
"at": 99
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "q1",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
}
]
}
}
}
@@ -0,0 +1,136 @@
{
"name": "addPart box brings its own frames",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addPart",
"part": {
"id": "b2",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "EMPTY_COMB"
},
{
"slot": 2,
"type": "EMPTY_COMB"
},
{
"slot": 3,
"type": "EMPTY_COMB"
},
{
"slot": 4,
"type": "EMPTY_COMB"
},
{
"slot": 5,
"type": "EMPTY_COMB"
},
{
"slot": 6,
"type": "EMPTY_COMB"
},
{
"slot": 7,
"type": "EMPTY_COMB"
},
{
"slot": 8,
"type": "EMPTY_COMB"
},
{
"slot": 9,
"type": "EMPTY_COMB"
},
{
"slot": 10,
"type": "EMPTY_COMB"
}
]
},
"at": 1
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b2",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "EMPTY_COMB"
},
{
"slot": 2,
"type": "EMPTY_COMB"
},
{
"slot": 3,
"type": "EMPTY_COMB"
},
{
"slot": 4,
"type": "EMPTY_COMB"
},
{
"slot": 5,
"type": "EMPTY_COMB"
},
{
"slot": 6,
"type": "EMPTY_COMB"
},
{
"slot": 7,
"type": "EMPTY_COMB"
},
{
"slot": 8,
"type": "EMPTY_COMB"
},
{
"slot": 9,
"type": "EMPTY_COMB"
},
{
"slot": 10,
"type": "EMPTY_COMB"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
}
}
}
@@ -0,0 +1,148 @@
{
"name": "addInsert floor insert into floor",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addInsert",
"hostId": "f1",
"part": {
"id": "fi1",
"partTypeId": "hive-part-zl10-floor-insert",
"state": {}
}
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {},
"inserts": [
{
"id": "fi1",
"partTypeId": "hive-part-zl10-floor-insert",
"state": {}
}
]
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
}
}
}
@@ -0,0 +1,70 @@
{
"name": "addInsert evaporator into empty box",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "e1",
"partTypeId": "hive-part-zl10-box-empty",
"state": {},
"frames": []
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addInsert",
"hostId": "e1",
"part": {
"id": "ev1",
"partTypeId": "hive-part-zl10-evaporator",
"state": {
"acidMl": 250
}
}
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "e1",
"partTypeId": "hive-part-zl10-box-empty",
"state": {},
"frames": [],
"inserts": [
{
"id": "ev1",
"partTypeId": "hive-part-zl10-evaporator",
"state": {
"acidMl": 250
}
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
}
}
}
@@ -0,0 +1,89 @@
{
"name": "removePart removes a stack part",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "removePart",
"id": "b1"
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
}
}
}
@@ -0,0 +1,143 @@
{
"name": "removePart removes an insert",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {},
"inserts": [
{
"id": "fi1",
"partTypeId": "hive-part-zl10-floor-insert",
"state": {}
}
]
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "removePart",
"id": "fi1"
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
}
}
}
@@ -0,0 +1,231 @@
{
"name": "movePart moves within the stack",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "b2",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "movePart",
"id": "b2",
"to": 1
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b2",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
}
}
}
@@ -0,0 +1,137 @@
{
"name": "movePart target beyond end is clamped",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "q1",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
}
]
},
"ops": [
{
"op": "movePart",
"id": "b1",
"to": 50
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "q1",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
}
]
}
}
}
@@ -0,0 +1,56 @@
{
"name": "setState sets a level",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "fd1",
"partTypeId": "hive-part-zl10-feeder",
"state": {}
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setState",
"id": "fd1",
"key": "syrupLiters",
"value": 2.5
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "fd1",
"partTypeId": "hive-part-zl10-feeder",
"state": {
"syrupLiters": 2.5
}
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
}
}
}
@@ -0,0 +1,140 @@
{
"name": "setState sets a choice",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setState",
"id": "f1",
"key": "entrance",
"value": "NARROW"
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {
"entrance": "NARROW"
}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
}
}
}
@@ -0,0 +1,63 @@
{
"name": "setState accepts the level maximum",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "fd1",
"partTypeId": "hive-part-zl10-feeder",
"state": {}
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setState",
"id": "fd1",
"key": "syrupLiters",
"value": 3
},
{
"op": "setState",
"id": "fd1",
"key": "fondantKg",
"value": 2.5
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "fd1",
"partTypeId": "hive-part-zl10-feeder",
"state": {
"syrupLiters": 3,
"fondantKg": 2.5
}
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
}
}
}
@@ -0,0 +1,72 @@
{
"name": "setState on an insert",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "e1",
"partTypeId": "hive-part-zl10-box-empty",
"state": {},
"frames": [],
"inserts": [
{
"id": "ev1",
"partTypeId": "hive-part-zl10-evaporator",
"state": {}
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setState",
"id": "ev1",
"key": "acidMl",
"value": 290
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "e1",
"partTypeId": "hive-part-zl10-box-empty",
"state": {},
"frames": [],
"inserts": [
{
"id": "ev1",
"partTypeId": "hive-part-zl10-evaporator",
"state": {
"acidMl": 290
}
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
}
}
}
@@ -0,0 +1,140 @@
{
"name": "setFrame sets type and name",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setFrame",
"boxId": "b1",
"slot": 3,
"type": "BROOD",
"name": "Königin"
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "BROOD",
"name": "Königin"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
}
}
}
@@ -0,0 +1,140 @@
{
"name": "setFrame with null name removes the name",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "BROOD",
"name": "x"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setFrame",
"boxId": "b1",
"slot": 3,
"type": "HONEY",
"name": null
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "HONEY"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
}
}
}
@@ -0,0 +1,178 @@
{
"name": "setFrames replaces all frames",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setFrames",
"boxId": "b1",
"frames": [
{
"slot": 1,
"type": "BROOD"
},
{
"slot": 2,
"type": "BROOD"
},
{
"slot": 3,
"type": "BROOD"
},
{
"slot": 4,
"type": "BROOD"
},
{
"slot": 5,
"type": "BROOD"
},
{
"slot": 6,
"type": "BROOD"
},
{
"slot": 7,
"type": "BROOD"
},
{
"slot": 8,
"type": "BROOD"
},
{
"slot": 9,
"type": "BROOD"
},
{
"slot": 10,
"type": "BROOD"
}
]
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "BROOD"
},
{
"slot": 2,
"type": "BROOD"
},
{
"slot": 3,
"type": "BROOD"
},
{
"slot": 4,
"type": "BROOD"
},
{
"slot": 5,
"type": "BROOD"
},
{
"slot": 6,
"type": "BROOD"
},
{
"slot": 7,
"type": "BROOD"
},
{
"slot": 8,
"type": "BROOD"
},
{
"slot": 9,
"type": "BROOD"
},
{
"slot": 10,
"type": "BROOD"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
}
}
}
@@ -0,0 +1,148 @@
{
"name": "setLabel sets and clears a label",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setLabel",
"id": "b1",
"label": "Honigraum 1"
},
{
"op": "setLabel",
"id": "f1",
"label": "Boden"
},
{
"op": "setLabel",
"id": "b1",
"label": null
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {},
"label": "Boden"
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
}
}
}
@@ -0,0 +1,146 @@
{
"name": "multiple ops apply in order",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
}
]
},
"ops": [
{
"op": "addPart",
"part": {
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
"at": 1
},
{
"op": "addPart",
"part": {
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
},
"at": 2
},
{
"op": "setFrame",
"boxId": "b1",
"slot": 1,
"type": "POLLEN"
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "POLLEN"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
}
}
}
@@ -0,0 +1,131 @@
{
"name": "empty ops return the state unchanged",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
}
}
}
@@ -0,0 +1,141 @@
{
"name": "existing parts with an inactive part type stay valid",
"inactivePartTypeIds": [
"hive-part-zl10-roof"
],
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setLabel",
"id": "r1",
"label": "Dach"
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {},
"label": "Dach"
}
]
}
}
}
@@ -0,0 +1,76 @@
{
"name": "removing the floor fails",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "removePart",
"id": "f1"
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "RULE_FLOOR_BOTTOM"
}
}
@@ -0,0 +1,81 @@
{
"name": "second floor fails",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addPart",
"part": {
"id": "f2",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
"at": 1
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "RULE_FLOOR_BOTTOM"
}
}
@@ -0,0 +1,81 @@
{
"name": "part below the floor fails",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addPart",
"part": {
"id": "q1",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
"at": 0
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "RULE_FLOOR_BOTTOM"
}
}
@@ -0,0 +1,81 @@
{
"name": "negative at is clamped to 0 and then fails the floor rule",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addPart",
"part": {
"id": "q1",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
"at": -7
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "RULE_FLOOR_BOTTOM"
}
}
@@ -0,0 +1,81 @@
{
"name": "part above the roof fails",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addPart",
"part": {
"id": "q1",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
"at": 3
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "RULE_ROOF_TOP"
}
}
@@ -0,0 +1,81 @@
{
"name": "at beyond the end is clamped and fails the roof rule",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addPart",
"part": {
"id": "q1",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
"at": 99
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "RULE_ROOF_TOP"
}
}
@@ -0,0 +1,81 @@
{
"name": "second roof fails",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addPart",
"part": {
"id": "r2",
"partTypeId": "hive-part-zl10-roof",
"state": {}
},
"at": 3
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "RULE_ROOF_TOP"
}
}
@@ -0,0 +1,81 @@
{
"name": "floor insert cannot sit in the stack",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addPart",
"part": {
"id": "fi1",
"partTypeId": "hive-part-zl10-floor-insert",
"state": {}
},
"at": 1
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "RULE_INSERT_HOST"
}
}
@@ -0,0 +1,81 @@
{
"name": "evaporator cannot sit in the stack",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addPart",
"part": {
"id": "ev1",
"partTypeId": "hive-part-zl10-evaporator",
"state": {}
},
"at": 1
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "RULE_INSERT_HOST"
}
}
@@ -0,0 +1,81 @@
{
"name": "evaporator cannot go into a floor",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addInsert",
"hostId": "f1",
"part": {
"id": "ev1",
"partTypeId": "hive-part-zl10-evaporator",
"state": {}
}
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "RULE_INSERT_HOST"
}
}
@@ -0,0 +1,81 @@
{
"name": "floor insert cannot go into a box",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addInsert",
"hostId": "b1",
"part": {
"id": "fi1",
"partTypeId": "hive-part-zl10-floor-insert",
"state": {}
}
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "RULE_INSERT_HOST"
}
}
@@ -0,0 +1,81 @@
{
"name": "feeder cannot be an insert",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addInsert",
"hostId": "b1",
"part": {
"id": "fd1",
"partTypeId": "hive-part-zl10-feeder",
"state": {}
}
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "RULE_INSERT_HOST"
}
}
@@ -0,0 +1,88 @@
{
"name": "only one floor insert per floor",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {},
"inserts": [
{
"id": "fi1",
"partTypeId": "hive-part-zl10-floor-insert",
"state": {}
}
]
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addInsert",
"hostId": "f1",
"part": {
"id": "fi2",
"partTypeId": "hive-part-zl10-floor-insert",
"state": {}
}
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "RULE_INSERT_LIMIT"
}
}
@@ -0,0 +1,47 @@
{
"name": "only one evaporator per box",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "e1",
"partTypeId": "hive-part-zl10-box-empty",
"state": {},
"frames": [],
"inserts": [
{
"id": "ev1",
"partTypeId": "hive-part-zl10-evaporator",
"state": {}
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addInsert",
"hostId": "e1",
"part": {
"id": "ev2",
"partTypeId": "hive-part-zl10-evaporator",
"state": {}
}
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "RULE_INSERT_LIMIT"
}
}
@@ -0,0 +1,84 @@
{
"name": "movePart cannot move an insert",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {},
"inserts": [
{
"id": "fi1",
"partTypeId": "hive-part-zl10-floor-insert",
"state": {}
}
]
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "movePart",
"id": "fi1",
"to": 1
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "RULE_INSERT_HOST"
}
}
@@ -0,0 +1,77 @@
{
"name": "movePart past the roof fails the roof rule",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "movePart",
"id": "b1",
"to": 99
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "RULE_ROOF_TOP"
}
}
@@ -0,0 +1,78 @@
{
"name": "setState with unknown key",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setState",
"id": "f1",
"key": "nope",
"value": 1
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "STATE_UNKNOWN_KEY"
}
}
@@ -0,0 +1,36 @@
{
"name": "setState level above max",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "fd1",
"partTypeId": "hive-part-zl10-feeder",
"state": {}
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setState",
"id": "fd1",
"key": "syrupLiters",
"value": 3.5
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "STATE_OUT_OF_RANGE"
}
}
@@ -0,0 +1,36 @@
{
"name": "setState level below zero",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "fd1",
"partTypeId": "hive-part-zl10-feeder",
"state": {}
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setState",
"id": "fd1",
"key": "syrupLiters",
"value": -0.5
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "STATE_OUT_OF_RANGE"
}
}
@@ -0,0 +1,36 @@
{
"name": "setState level off step",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "fd1",
"partTypeId": "hive-part-zl10-feeder",
"state": {}
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setState",
"id": "fd1",
"key": "syrupLiters",
"value": 0.3
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "STATE_STEP"
}
}
@@ -0,0 +1,44 @@
{
"name": "setState evaporator off step of 10",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "e1",
"partTypeId": "hive-part-zl10-box-empty",
"state": {},
"frames": [],
"inserts": [
{
"id": "ev1",
"partTypeId": "hive-part-zl10-evaporator",
"state": {}
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setState",
"id": "ev1",
"key": "acidMl",
"value": 255
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "STATE_STEP"
}
}
@@ -0,0 +1,78 @@
{
"name": "setState choice not in options",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setState",
"id": "f1",
"key": "entrance",
"value": "HALF"
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "STATE_OUT_OF_RANGE"
}
}
@@ -0,0 +1,36 @@
{
"name": "setState string on a level",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "fd1",
"partTypeId": "hive-part-zl10-feeder",
"state": {}
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setState",
"id": "fd1",
"key": "syrupLiters",
"value": "2"
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "STATE_OUT_OF_RANGE"
}
}
@@ -0,0 +1,78 @@
{
"name": "setState number on a choice",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setState",
"id": "f1",
"key": "entrance",
"value": 1
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "STATE_OUT_OF_RANGE"
}
}
@@ -0,0 +1,78 @@
{
"name": "setState on missing id",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setState",
"id": "zzz",
"key": "entrance",
"value": "OPEN"
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "MISSING_ID"
}
}
@@ -0,0 +1,83 @@
{
"name": "addPart with unknown state key",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addPart",
"part": {
"id": "q1",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {
"foo": 1
}
},
"at": 2
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "STATE_UNKNOWN_KEY"
}
}
@@ -0,0 +1,114 @@
{
"name": "setFrames with too few frames",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setFrames",
"boxId": "b1",
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
}
]
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "FRAMES_LENGTH"
}
}
@@ -0,0 +1,122 @@
{
"name": "setFrames with too many frames",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setFrames",
"boxId": "b1",
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
},
{
"slot": 11,
"type": "FOUNDATION"
}
]
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "FRAMES_LENGTH"
}
}
@@ -0,0 +1,118 @@
{
"name": "setFrames with wrong slot numbers",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setFrames",
"boxId": "b1",
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 1,
"type": "FOUNDATION"
}
]
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "FRAMES_LENGTH"
}
}
@@ -0,0 +1,78 @@
{
"name": "setFrame slot above frameSlots",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setFrame",
"boxId": "b1",
"slot": 11,
"type": "BROOD"
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "FRAMES_LENGTH"
}
}
@@ -0,0 +1,78 @@
{
"name": "setFrame slot zero",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setFrame",
"boxId": "b1",
"slot": 0,
"type": "BROOD"
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "FRAMES_LENGTH"
}
}
@@ -0,0 +1,78 @@
{
"name": "setFrame on a non-box",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setFrame",
"boxId": "f1",
"slot": 1,
"type": "BROOD"
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "FRAMES_LENGTH"
}
}
@@ -0,0 +1,37 @@
{
"name": "setFrame on a box with zero slots",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "e1",
"partTypeId": "hive-part-zl10-box-empty",
"state": {},
"frames": []
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setFrame",
"boxId": "e1",
"slot": 1,
"type": "BROOD"
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "FRAMES_LENGTH"
}
}
@@ -0,0 +1,78 @@
{
"name": "setFrame with unknown frame type",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setFrame",
"boxId": "b1",
"slot": 1,
"type": "GOLD"
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "STATE_OUT_OF_RANGE"
}
}
@@ -0,0 +1,68 @@
{
"name": "addPart box with wrong frame count",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addPart",
"part": {
"id": "b2",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
}
]
},
"at": 1
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "FRAMES_LENGTH"
}
}
@@ -0,0 +1,34 @@
{
"name": "addPart box without frames",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addPart",
"part": {
"id": "b2",
"partTypeId": "hive-part-zl10-box-10",
"state": {}
},
"at": 1
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "FRAMES_LENGTH"
}
}
@@ -0,0 +1,87 @@
{
"name": "frames on a non-box part",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addPart",
"part": {
"id": "q1",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
}
]
},
"at": 2
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "FRAMES_LENGTH"
}
}
@@ -0,0 +1,174 @@
{
"name": "the 31st part in the stack fails",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "q0",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q1",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q2",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q3",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q4",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q5",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q6",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q7",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q8",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q9",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q10",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q11",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q12",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q13",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q14",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q15",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q16",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q17",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q18",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q19",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q20",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q21",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q22",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q23",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q24",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q25",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q26",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q27",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q28",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
}
]
},
"ops": [
{
"op": "addPart",
"part": {
"id": "q99",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
"at": 30
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "LIMIT_PARTS"
}
}
@@ -0,0 +1,322 @@
{
"name": "a stack of 30 parts is allowed",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "q0",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q1",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q2",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q3",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q4",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q5",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q6",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q7",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q8",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q9",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q10",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q11",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q12",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q13",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q14",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q15",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q16",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q17",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q18",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q19",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q20",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q21",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q22",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q23",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q24",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q25",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q26",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q27",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
}
]
},
"ops": [
{
"op": "addPart",
"part": {
"id": "q28",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
"at": 29
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "q0",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q1",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q2",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q3",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q4",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q5",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q6",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q7",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q8",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q9",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q10",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q11",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q12",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q13",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q14",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q15",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q16",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q17",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q18",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q19",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q20",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q21",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q22",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q23",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q24",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q25",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q26",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q27",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
{
"id": "q28",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
}
]
}
}
}
@@ -0,0 +1,77 @@
{
"name": "label of 41 characters",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setLabel",
"id": "b1",
"label": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "LIMIT_TEXT"
}
}
@@ -0,0 +1,138 @@
{
"name": "label of 40 characters",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setLabel",
"id": "b1",
"label": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
],
"label": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
}
}
}
@@ -0,0 +1,79 @@
{
"name": "frame name of 41 characters",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setFrame",
"boxId": "b1",
"slot": 1,
"type": "BROOD",
"name": "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "LIMIT_TEXT"
}
}
@@ -0,0 +1,577 @@
{
"name": "more than 100 ops",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
}
],
"expect": {
"ok": false,
"opIndex": 100,
"reasonCode": "LIMIT_OPS"
}
}
@@ -0,0 +1,633 @@
{
"name": "exactly 100 ops",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
},
{
"op": "setLabel",
"id": "b1",
"label": "a"
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
],
"label": "a"
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
}
}
}
@@ -0,0 +1,81 @@
{
"name": "duplicate id on addPart",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addPart",
"part": {
"id": "b1",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
"at": 2
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "DUPLICATE_ID"
}
}
@@ -0,0 +1,81 @@
{
"name": "duplicate id between insert and stack part",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addInsert",
"hostId": "f1",
"part": {
"id": "b1",
"partTypeId": "hive-part-zl10-floor-insert",
"state": {}
}
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "DUPLICATE_ID"
}
}
@@ -0,0 +1,81 @@
{
"name": "addPart with empty id",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addPart",
"part": {
"id": "",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
"at": 2
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "MISSING_ID"
}
}
@@ -0,0 +1,76 @@
{
"name": "removePart with missing id",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "removePart",
"id": "zzz"
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "MISSING_ID"
}
}
@@ -0,0 +1,77 @@
{
"name": "movePart with missing id",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "movePart",
"id": "zzz",
"to": 1
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "MISSING_ID"
}
}
@@ -0,0 +1,77 @@
{
"name": "setLabel with missing id",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setLabel",
"id": "zzz",
"label": "a"
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "MISSING_ID"
}
}
@@ -0,0 +1,81 @@
{
"name": "addInsert with missing host",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addInsert",
"hostId": "zzz",
"part": {
"id": "fi1",
"partTypeId": "hive-part-zl10-floor-insert",
"state": {}
}
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "MISSING_ID"
}
}
@@ -0,0 +1,78 @@
{
"name": "setFrame with missing box",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setFrame",
"boxId": "zzz",
"slot": 1,
"type": "BROOD"
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "MISSING_ID"
}
}
@@ -0,0 +1,81 @@
{
"name": "foreign part type",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addPart",
"part": {
"id": "x1",
"partTypeId": "hive-part-other-system-box",
"state": {}
},
"at": 2
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "FOREIGN_PART_TYPE"
}
}
@@ -0,0 +1,84 @@
{
"name": "inactive part type on addPart",
"inactivePartTypeIds": [
"hive-part-zl10-queen-excluder"
],
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addPart",
"part": {
"id": "q1",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {}
},
"at": 2
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "INACTIVE_PART_TYPE"
}
}
@@ -0,0 +1,84 @@
{
"name": "inactive part type on addInsert",
"inactivePartTypeIds": [
"hive-part-zl10-floor-insert"
],
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addInsert",
"hostId": "f1",
"part": {
"id": "fi1",
"partTypeId": "hive-part-zl10-floor-insert",
"state": {}
}
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "INACTIVE_PART_TYPE"
}
}
@@ -0,0 +1,86 @@
{
"name": "failing op index is reported",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setLabel",
"id": "b1",
"label": "ok"
},
{
"op": "removePart",
"id": "zzz"
},
{
"op": "setLabel",
"id": "b1",
"label": "never"
}
],
"expect": {
"ok": false,
"opIndex": 1,
"reasonCode": "MISSING_ID"
}
}
@@ -0,0 +1,76 @@
{
"name": "unknown op",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "explode",
"id": "b1"
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "UNKNOWN_OP"
}
}
@@ -0,0 +1,140 @@
{
"name": "setFrame without name keeps an existing name",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "BROOD",
"name": "Königin"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setFrame",
"boxId": "b1",
"slot": 3,
"type": "HONEY"
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "HONEY",
"name": "Königin"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
}
}
}
@@ -0,0 +1,138 @@
{
"name": "setFrame without name on an unnamed frame stays unnamed",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setFrame",
"boxId": "b1",
"slot": 2,
"type": "HONEY"
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "HONEY"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
}
}
}
@@ -0,0 +1,56 @@
{
"name": "setState accepts a value within the 1e-9 step tolerance",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "fd1",
"partTypeId": "hive-part-zl10-feeder",
"state": {}
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setState",
"id": "fd1",
"key": "syrupLiters",
"value": 2.5000000001
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "fd1",
"partTypeId": "hive-part-zl10-feeder",
"state": {
"syrupLiters": 2.5000000001
}
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
}
}
}
@@ -0,0 +1,36 @@
{
"name": "setState rejects a value just beyond the step tolerance",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "fd1",
"partTypeId": "hive-part-zl10-feeder",
"state": {}
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setState",
"id": "fd1",
"key": "syrupLiters",
"value": 2.500001
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "STATE_STEP"
}
}
@@ -0,0 +1,77 @@
{
"name": "setLabel with a non-string label",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setLabel",
"id": "b1",
"label": 5
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "STATE_OUT_OF_RANGE"
}
}
@@ -0,0 +1,79 @@
{
"name": "setFrame with a non-string name",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setFrame",
"boxId": "b1",
"slot": 1,
"type": "BROOD",
"name": 5
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "STATE_OUT_OF_RANGE"
}
}
@@ -0,0 +1,137 @@
{
"name": "addPart normalises an empty inserts array away",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addPart",
"part": {
"id": "b2",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
],
"inserts": []
},
"at": 1
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b2",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
}
}
}
@@ -0,0 +1,145 @@
{
"name": "addInsert then removePart leaves no empty inserts array",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addInsert",
"hostId": "f1",
"part": {
"id": "fi1",
"partTypeId": "hive-part-zl10-floor-insert",
"state": {}
}
},
{
"op": "removePart",
"id": "fi1"
}
],
"expect": {
"ok": true,
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
}
}
}
@@ -0,0 +1,78 @@
{
"name": "unknown key on the state root",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
],
"extra": 1
},
"ops": [
{
"op": "setLabel",
"id": "b1",
"label": "a"
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "UNKNOWN_FIELD"
}
}
@@ -0,0 +1,82 @@
{
"name": "unknown key on a part",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addPart",
"part": {
"id": "q1",
"partTypeId": "hive-part-zl10-queen-excluder",
"state": {},
"extra": 1
},
"at": 2
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "UNKNOWN_FIELD"
}
}
@@ -0,0 +1,82 @@
{
"name": "unknown key on an insert",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "addInsert",
"hostId": "f1",
"part": {
"id": "fi1",
"partTypeId": "hive-part-zl10-floor-insert",
"state": {},
"extra": 1
}
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "UNKNOWN_FIELD"
}
}
@@ -0,0 +1,128 @@
{
"name": "unknown key on a frame",
"state": {
"schemaVersion": 1,
"stack": [
{
"id": "f1",
"partTypeId": "hive-part-zl10-floor",
"state": {}
},
{
"id": "b1",
"partTypeId": "hive-part-zl10-box-10",
"state": {},
"frames": [
{
"slot": 1,
"type": "FOUNDATION"
},
{
"slot": 2,
"type": "FOUNDATION"
},
{
"slot": 3,
"type": "FOUNDATION"
},
{
"slot": 4,
"type": "FOUNDATION"
},
{
"slot": 5,
"type": "FOUNDATION"
},
{
"slot": 6,
"type": "FOUNDATION"
},
{
"slot": 7,
"type": "FOUNDATION"
},
{
"slot": 8,
"type": "FOUNDATION"
},
{
"slot": 9,
"type": "FOUNDATION"
},
{
"slot": 10,
"type": "FOUNDATION"
}
]
},
{
"id": "r1",
"partTypeId": "hive-part-zl10-roof",
"state": {}
}
]
},
"ops": [
{
"op": "setFrames",
"boxId": "b1",
"frames": [
{
"slot": 1,
"type": "FOUNDATION",
"extra": 1
},
{
"slot": 2,
"type": "FOUNDATION",
"extra": 1
},
{
"slot": 3,
"type": "FOUNDATION",
"extra": 1
},
{
"slot": 4,
"type": "FOUNDATION",
"extra": 1
},
{
"slot": 5,
"type": "FOUNDATION",
"extra": 1
},
{
"slot": 6,
"type": "FOUNDATION",
"extra": 1
},
{
"slot": 7,
"type": "FOUNDATION",
"extra": 1
},
{
"slot": 8,
"type": "FOUNDATION",
"extra": 1
},
{
"slot": 9,
"type": "FOUNDATION",
"extra": 1
},
{
"slot": 10,
"type": "FOUNDATION",
"extra": 1
}
]
}
],
"expect": {
"ok": false,
"opIndex": 0,
"reasonCode": "UNKNOWN_FIELD"
}
}
+246
View File
@@ -0,0 +1,246 @@
{
"systemId": "hive-system-zander-liebig-10",
"partTypes": [
{
"id": "hive-part-zl10-floor",
"kind": "FLOOR",
"name": "Liebig Wanderboden",
"lengthMm": 525,
"widthMm": 430,
"heightMm": 120,
"frameSlots": null,
"stateSchema": [
{
"key": "entrance",
"label": "Flugloch",
"kind": "choice",
"options": [
"OPEN",
"NARROW",
"CLOSED"
],
"optionLabels": [
"offen",
"eng",
"zu"
]
},
{
"key": "varroaTray",
"label": "Varroa-Schublade",
"kind": "choice",
"options": [
"IN",
"OUT"
],
"optionLabels": [
"drin",
"draußen"
]
}
],
"active": true
},
{
"id": "hive-part-zl10-floor-insert",
"kind": "FLOOR_INSERT",
"name": "Liebig Bausperre",
"lengthMm": 475,
"widthMm": 375,
"heightMm": 5,
"frameSlots": null,
"stateSchema": [],
"active": true
},
{
"id": "hive-part-zl10-box-10",
"kind": "BOX",
"name": "Liebig Zander Ganzzarge, 10 Rähmchen",
"lengthMm": 525,
"widthMm": 430,
"heightMm": 230,
"frameSlots": 10,
"stateSchema": [],
"active": true
},
{
"id": "hive-part-zl10-box-empty",
"kind": "BOX",
"name": "Leerzarge (Liebig Zander Ganzzarge ohne Rähmchen)",
"lengthMm": 525,
"widthMm": 430,
"heightMm": 230,
"frameSlots": 0,
"stateSchema": [],
"active": true
},
{
"id": "hive-part-zl10-divider-board",
"kind": "DIVIDER_BOARD",
"name": "Liebig Zwischenboden",
"lengthMm": 525,
"widthMm": 430,
"heightMm": 50,
"frameSlots": null,
"stateSchema": [
{
"key": "bungHoles",
"label": "Spundlöcher",
"kind": "choice",
"options": [
"OPEN",
"CLOSED",
"BEE_ESCAPE"
],
"optionLabels": [
"offen",
"zu",
"Bienenflucht"
]
}
],
"active": true
},
{
"id": "hive-part-zl10-queen-excluder",
"kind": "QUEEN_EXCLUDER",
"name": "Niro-Absperrgitter Zander Liebig",
"lengthMm": 478,
"widthMm": 376,
"heightMm": 2,
"frameSlots": null,
"stateSchema": [],
"active": true
},
{
"id": "hive-part-zl10-feeder",
"kind": "FEEDER",
"name": "Liebig Zweikammer-Futterzarge",
"lengthMm": 520,
"widthMm": 420,
"heightMm": 70,
"frameSlots": null,
"stateSchema": [
{
"key": "syrupLiters",
"label": "Flüssigfutter",
"kind": "level",
"unit": "l",
"max": 3,
"step": 0.5,
"feedType": "SUGAR_WATER"
},
{
"key": "fondantKg",
"label": "Futterteig",
"kind": "level",
"unit": "kg",
"max": 2.5,
"step": 0.5,
"feedType": "FEED_PASTE"
}
],
"active": true
},
{
"id": "hive-part-zl10-cover-abdeckfix",
"kind": "COVER_SHEET",
"name": "Abdeck-Fix (Folie, klar, 0,4 mm)",
"lengthMm": 478,
"widthMm": 378,
"heightMm": 1,
"frameSlots": null,
"stateSchema": [],
"active": true
},
{
"id": "hive-part-zl10-cover-lotus",
"kind": "COVER_SHEET",
"name": "Imgut Lotus-Abdeckung (0,5 mm)",
"lengthMm": 478,
"widthMm": 378,
"heightMm": 1,
"frameSlots": null,
"stateSchema": [],
"active": true
},
{
"id": "hive-part-zl10-propolis-screen",
"kind": "PROPOLIS_SCREEN",
"name": "Imgut Propolisgitter",
"lengthMm": 478,
"widthMm": 378,
"heightMm": 3,
"frameSlots": null,
"stateSchema": [],
"active": true
},
{
"id": "hive-part-zl10-inner-lid",
"kind": "INNER_LID",
"name": "Liebig Holzdeckel",
"lengthMm": 525,
"widthMm": 430,
"heightMm": 35,
"frameSlots": null,
"stateSchema": [
{
"key": "feedHole",
"label": "Futterloch",
"kind": "choice",
"options": [
"OPEN",
"CLOSED"
],
"optionLabels": [
"offen",
"zu"
]
}
],
"active": true
},
{
"id": "hive-part-zl10-insulation",
"kind": "INSULATION",
"name": "Styropor-Einlage (selbst gebaut)",
"lengthMm": 465,
"widthMm": 365,
"heightMm": 20,
"frameSlots": null,
"stateSchema": [],
"active": true
},
{
"id": "hive-part-zl10-roof",
"kind": "ROOF",
"name": "Edelstahldeckel konisch Liebig",
"lengthMm": 525,
"widthMm": 430,
"heightMm": 60,
"frameSlots": null,
"stateSchema": [],
"active": true
},
{
"id": "hive-part-zl10-evaporator",
"kind": "EVAPORATOR",
"name": "Nassenheider Verdunster Professional",
"lengthMm": 200,
"widthMm": 140,
"heightMm": 120,
"frameSlots": null,
"stateSchema": [
{
"key": "acidMl",
"label": "Ameisensäure",
"kind": "level",
"unit": "ml",
"max": 290,
"step": 10
}
],
"active": true
}
]
}
@@ -0,0 +1,176 @@
import { PERMISSION_CATALOG } from '../src/auth/permissions/permission-catalog';
import { PermissionCatalogSyncService } from '../src/auth/permissions/permission-catalog-sync.service';
import { PrismaService } from '../src/prisma/prisma.service';
const SYSTEM_ID = 'hive-system-zander-liebig-10';
const PART_PREFIX = 'hive-part-zl10-';
const PART_SLUGS = [
'floor',
'floor-insert',
'box-10',
'box-empty',
'divider-board',
'queen-excluder',
'feeder',
'cover-abdeckfix',
'cover-lotus',
'propolis-screen',
'inner-lid',
'insulation',
'roof',
'evaporator',
] as const;
interface StateField {
key: string;
kind: string;
feedType?: string;
[extra: string]: unknown;
}
/**
* The Liebig-Zander start catalog arrives with the migration (fixed ids) and
* `hive-systems:manage` joins ADMIN through the boot-time catalog sync.
* Checked against the migrated test database.
*/
describe('Hive catalog seed (e2e)', () => {
let prisma: PrismaService;
beforeAll(() => {
prisma = new PrismaService();
});
afterAll(async () => {
await prisma.$disconnect();
});
async function partType(slug: string) {
return prisma.hivePartType.findUniqueOrThrow({
where: { id: `${PART_PREFIX}${slug}` },
});
}
it('seeds the Zander-Liebig system with its geometry and template', async () => {
const system = await prisma.hiveSystem.findUniqueOrThrow({
where: { id: SYSTEM_ID },
});
expect(system).toMatchObject({
name: 'Zander nach Dr. Liebig, 10 Rähmchen',
frameWidthMm: 477,
frameHeightMm: 220,
footprintLMm: 525,
footprintWMm: 430,
active: true,
});
});
it('seeds 14 active part types for the system under fixed ids', async () => {
const types = await prisma.hivePartType.findMany({
where: { systemId: SYSTEM_ID, active: true },
orderBy: { id: 'asc' },
});
expect(types.map((t) => t.id)).toEqual(
PART_SLUGS.map((slug) => `${PART_PREFIX}${slug}`).sort(),
);
});
it('describes the 10-frame box with 10 slots and 230 mm height', async () => {
const box = await partType('box-10');
expect(box).toMatchObject({
kind: 'BOX',
boxDepth: 'FULL',
frameSlots: 10,
heightMm: 230,
lengthMm: 525,
widthMm: 430,
});
expect((await partType('box-empty')).frameSlots).toBe(0);
});
it('gives the feeder two level fields with a feed type each', async () => {
const feeder = await partType('feeder');
const fields = feeder.stateSchema as unknown as StateField[];
expect(fields).toHaveLength(2);
expect(fields.every((f) => f.kind === 'level')).toBe(true);
expect(fields.map((f) => [f.key, f.feedType])).toEqual([
['syrupLiters', 'SUGAR_WATER'],
['fondantKg', 'FEED_PASTE'],
]);
});
it('gives the other stateful parts their choice and level fields', async () => {
const keysOf = async (slug: string) =>
((await partType(slug)).stateSchema as unknown as StateField[]).map(
(f) => f.key,
);
expect(await keysOf('floor')).toEqual(['entrance', 'varroaTray']);
expect(await keysOf('divider-board')).toEqual(['bungHoles']);
expect(await keysOf('inner-lid')).toEqual(['feedHole']);
expect(await keysOf('evaporator')).toEqual(['acidMl']);
expect(await keysOf('roof')).toEqual([]);
});
it('stores the system template without ids, with 10 foundation frames', async () => {
const system = await prisma.hiveSystem.findUniqueOrThrow({
where: { id: SYSTEM_ID },
});
const template = system.template as unknown as {
schemaVersion: number;
stack: {
id?: string;
partTypeId: string;
state: Record<string, unknown>;
frames?: { slot: number; type: string }[];
}[];
};
expect(template.schemaVersion).toBe(1);
expect(template.stack.map((p) => p.partTypeId)).toEqual([
`${PART_PREFIX}floor`,
`${PART_PREFIX}box-10`,
`${PART_PREFIX}cover-abdeckfix`,
`${PART_PREFIX}inner-lid`,
`${PART_PREFIX}insulation`,
`${PART_PREFIX}roof`,
]);
for (const part of template.stack) {
expect(part.id).toBeUndefined();
expect(part.state).toEqual({});
}
const frames = template.stack[1].frames ?? [];
expect(frames).toHaveLength(10);
expect(frames.map((f) => f.slot)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
expect(frames.every((f) => f.type === 'FOUNDATION')).toBe(true);
});
it('lists hive-systems:manage in the permission catalog', () => {
const entry = PERMISSION_CATALOG.find(
(e) => e.key === 'hive-systems:manage',
);
expect(entry).toMatchObject({
resource: 'hive-systems',
action: 'manage',
labelDe: 'Pflegen',
groupDe: 'Beutensysteme',
});
});
it('grants hive-systems:manage to ADMIN after the catalog sync', async () => {
await new PermissionCatalogSyncService(prisma).onModuleInit();
const grant = await prisma.rolePermission.findFirst({
where: {
role: { key: 'ADMIN' },
permission: { key: 'hive-systems:manage' },
},
});
expect(grant).not.toBeNull();
});
});
@@ -0,0 +1,303 @@
import { readFileSync } from 'node:fs';
import { join } from 'node:path';
import { INestApplication } from '@nestjs/common';
import * as bcrypt from 'bcryptjs';
import request from 'supertest';
import { App } from 'supertest/types';
import { HiveCatalogService } from '../src/hive/hive-catalog.service';
import { validateHiveState } from '../src/hive/hive-validate';
import { PrismaService } from '../src/prisma/prisma.service';
import { login } from './utils/api';
import { createTestApp } from './utils/create-test-app';
const SYSTEM_ID = 'hive-system-zander-liebig-10';
interface FixturePartType {
id: string;
kind: string;
name: string;
lengthMm: number;
widthMm: number;
heightMm: number;
frameSlots: number | null;
stateSchema: unknown[];
active: boolean;
}
interface TemplateBody {
schemaVersion: number;
stack: { id: string; inserts?: { id: string }[] }[];
}
interface SystemBody {
id: string;
partTypes: { id: string }[];
}
const fixture = JSON.parse(
readFileSync(join(__dirname, 'fixtures', 'hive-ops', 'catalog.json'), 'utf8'),
) as { systemId: string; partTypes: FixturePartType[] };
const FLOOR_SCHEMA: unknown[] =
fixture.partTypes.find((p) => p.kind === 'FLOOR')?.stateSchema ?? [];
/** Hive catalog against the real database: seed, permissions, row lock SQL. */
describe('Hive catalog (e2e)', () => {
let app: INestApplication<App>;
let prisma: PrismaService;
const suffix = `${Date.now()}-${Math.round(Math.random() * 1e6)}`;
const password = 'SuperSecret123!';
const roleIds: string[] = [];
const userIds: string[] = [];
const systemIds: string[] = [];
const tokens = { manager: '', reader: '' };
const api = () => request(app.getHttpServer());
const auth = (token: string) => ({ Authorization: `Bearer ${token}` });
const systemBody = (name: string) => ({
name,
frameWidthMm: 480,
frameHeightMm: 220,
footprintLMm: 520,
footprintWMm: 430,
});
const floorTypeBody = (stateSchema: unknown[]) => ({
kind: 'FLOOR',
name: `E2E Boden ${suffix}`,
lengthMm: 525,
widthMm: 430,
heightMm: 120,
stateSchema,
});
async function createUser(label: string, permissions: string[]) {
const role = await prisma.role.create({
data: {
key: `HIVE_CAT_${label.toUpperCase()}_${suffix}`,
name: `Hive catalog ${label}`,
permissions: {
create: permissions.map((p) => ({
permission: { connect: { key: p } },
})),
},
},
});
roleIds.push(role.id);
const email = `hive-cat-${label}-${suffix}@example.com`;
const user = await prisma.user.create({
data: {
email,
passwordHash: await bcrypt.hash(password, 12),
name: `Hive catalog ${label}`,
role: { connect: { id: role.id } },
},
});
userIds.push(user.id);
return (await login(app, email, password)).accessToken;
}
async function createSystem(name: string): Promise<string> {
const res = await api()
.post('/api/v1/hive-systems')
.set(auth(tokens.manager))
.send(systemBody(name))
.expect(201);
const id = (res.body as SystemBody).id;
systemIds.push(id);
return id;
}
async function createFloorType(systemId: string, stateSchema: unknown[]) {
const res = await api()
.post(`/api/v1/hive-systems/${systemId}/part-types`)
.set(auth(tokens.manager))
.send(floorTypeBody(stateSchema))
.expect(201);
return (res.body as { id: string }).id;
}
beforeAll(async () => {
app = await createTestApp();
prisma = app.get(PrismaService);
tokens.manager = await createUser('manager', [
'colonies:read',
'hive-systems:manage',
]);
tokens.reader = await createUser('reader', ['colonies:read']);
});
afterAll(async () => {
await prisma.hivePartType.deleteMany({
where: { systemId: { in: systemIds } },
});
await prisma.hiveSystem.deleteMany({ where: { id: { in: systemIds } } });
await prisma.auditLog.deleteMany({ where: { userId: { in: userIds } } });
await prisma.refreshToken.deleteMany({
where: { userId: { in: userIds } },
});
await prisma.user.deleteMany({ where: { id: { in: userIds } } });
await prisma.role.deleteMany({ where: { id: { in: roleIds } } });
await app.close();
});
it('seeds a catalog equal to test/fixtures/hive-ops/catalog.json', async () => {
const rows = await prisma.hivePartType.findMany({
where: { systemId: fixture.systemId },
orderBy: { id: 'asc' },
});
expect(rows.map((r) => r.id)).toEqual(
fixture.partTypes.map((p) => p.id).sort(),
);
for (const expected of fixture.partTypes) {
const row = rows.find((r) => r.id === expected.id);
expect({
id: row?.id,
kind: row?.kind,
name: row?.name,
lengthMm: row?.lengthMm,
widthMm: row?.widthMm,
heightMm: row?.heightMm,
frameSlots: row?.frameSlots,
stateSchema: row?.stateSchema,
active: row?.active,
}).toEqual(expected);
}
});
it('lists the systems with their part types for colonies:read', async () => {
const res = await api()
.get('/api/v1/hive-systems')
.set(auth(tokens.reader))
.expect(200);
const seeded = (res.body as SystemBody[]).find((s) => s.id === SYSTEM_ID);
expect(seeded?.partTypes).toHaveLength(fixture.partTypes.length);
});
it('refuses catalog writes without hive-systems:manage', async () => {
const attempts = [
() => api().post('/api/v1/hive-systems').send(systemBody('x')),
() =>
api().patch(`/api/v1/hive-systems/${SYSTEM_ID}`).send({ active: true }),
() =>
api()
.post(`/api/v1/hive-systems/${SYSTEM_ID}/part-types`)
.send(floorTypeBody([])),
() =>
api()
.patch(`/api/v1/hive-part-types/${fixture.partTypes[0].id}`)
.send({ name: 'x' }),
];
for (const attempt of attempts) {
await attempt().set(auth(tokens.reader)).expect(403);
}
});
it('creates and updates a system and a part type with the permission', async () => {
const systemId = await createSystem(`E2E System ${suffix}`);
await api()
.patch(`/api/v1/hive-systems/${systemId}`)
.set(auth(tokens.manager))
.send({ footprintLMm: 530 })
.expect(200);
const partTypeId = await createFloorType(systemId, FLOOR_SCHEMA);
const patched = await api()
.patch(`/api/v1/hive-part-types/${partTypeId}`)
.set(auth(tokens.manager))
.send({ heightMm: 125 })
.expect(200);
expect(patched.body).toMatchObject({ id: partTypeId, heightMm: 125 });
});
it('answers 400 SCHEMA_NOT_ADDITIVE when a state field is removed', async () => {
const systemId = await createSystem(`E2E Schema ${suffix}`);
const partTypeId = await createFloorType(systemId, FLOOR_SCHEMA);
const res = await api()
.patch(`/api/v1/hive-part-types/${partTypeId}`)
.set(auth(tokens.manager))
.send({ stateSchema: FLOOR_SCHEMA.slice(0, 1) })
.expect(400);
expect(res.body).toMatchObject({ code: 'SCHEMA_NOT_ADDITIVE' });
});
it('serialises two concurrent schema updates of one part type (row lock)', async () => {
const systemId = await createSystem(`E2E Lock ${suffix}`);
const partTypeId = await createFloorType(systemId, FLOOR_SCHEMA);
const url = `/api/v1/hive-part-types/${partTypeId}`;
const extra = (key: string) => ({
key,
label: key,
kind: 'choice',
options: ['A', 'B'],
optionLabels: ['a', 'b'],
});
const patch = (key: string) =>
api()
.patch(url)
.set(auth(tokens.manager))
.send({ stateSchema: [...FLOOR_SCHEMA, extra(key)] })
.then((res) => res);
const results = await Promise.all([patch('extraA'), patch('extraB')]);
// Without the lock both read the old schema and both would answer 200.
// Serialised, the loser sees the winner's field and is not additive.
expect(results.map((r) => r.status).sort()).toEqual([200, 400]);
const loser = results.find((r) => r.status === 400);
expect(loser?.body).toMatchObject({ code: 'SCHEMA_NOT_ADDITIVE' });
const row = await prisma.hivePartType.findUniqueOrThrow({
where: { id: partTypeId },
});
const keys = (row.stateSchema as unknown as { key: string }[]).map(
(f) => f.key,
);
expect(keys).toHaveLength(FLOOR_SCHEMA.length + 1);
});
it('answers 409 TEMPLATE_NOT_SET for a system without a template', async () => {
const systemId = await createSystem(`E2E Vorlage ${suffix}`);
const res = await api()
.get(`/api/v1/hive-systems/${systemId}/template`)
.set(auth(tokens.reader))
.expect(409);
expect(res.body).toMatchObject({ code: 'TEMPLATE_NOT_SET' });
});
it('answers 400 TEMPLATE_INVALID for a template with an empty stack', async () => {
const systemId = await createSystem(`E2E Leer ${suffix}`);
const res = await api()
.patch(`/api/v1/hive-systems/${systemId}`)
.set(auth(tokens.manager))
.send({ template: { schemaVersion: 1, stack: [] } })
.expect(400);
expect(res.body).toMatchObject({ code: 'TEMPLATE_INVALID' });
});
it('returns a valid template with fresh ids on every call', async () => {
const get = async () =>
(
await api()
.get(`/api/v1/hive-systems/${SYSTEM_ID}/template`)
.set(auth(tokens.reader))
.expect(200)
).body as TemplateBody;
const first = await get();
const second = await get();
const catalog = await app.get(HiveCatalogService).loadCatalog(SYSTEM_ID);
expect(validateHiveState(first, catalog)).toEqual([]);
const firstIds = first.stack.map((p) => p.id);
expect(firstIds.every((id) => typeof id === 'string' && id !== '')).toBe(
true,
);
expect(new Set(firstIds).size).toBe(firstIds.length);
const overlap = second.stack.filter((p) => firstIds.includes(p.id));
expect(overlap).toEqual([]);
});
});
+494
View File
@@ -0,0 +1,494 @@
import { INestApplication } from '@nestjs/common';
import * as bcrypt from 'bcryptjs';
import request from 'supertest';
import { App } from 'supertest/types';
import { addDays, berlinToday } from '../src/common/dates';
import { PrismaService } from '../src/prisma/prisma.service';
import { login } from './utils/api';
import { createTestApp } from './utils/create-test-app';
const SYSTEM_ID = 'hive-system-zander-liebig-10';
const FLOOR = 'hive-part-zl10-floor';
const BOX = 'hive-part-zl10-box-10';
const ROOF = 'hive-part-zl10-roof';
const frames = Array.from({ length: 10 }, (_, i) => ({
slot: i + 1,
type: 'FOUNDATION',
}));
const state = {
schemaVersion: 1,
stack: [
{ id: 'e2e-floor', partTypeId: FLOOR, state: {} },
{ id: 'e2e-box', partTypeId: BOX, state: {}, frames },
{ id: 'e2e-roof', partTypeId: ROOF, state: {} },
],
};
interface ViewBody {
version: number;
state: { schemaVersion: number; stack: { label?: string }[] };
facts: { boxCount: number };
}
interface HistoryBody {
items: { version: number; userName: string; stateAfter?: unknown }[];
nextCursor: string | null;
}
interface ConflictBody {
current: { version: number; state: { schemaVersion: number } };
}
const versionsOf = (body: HistoryBody) => body.items.map((i) => i.version);
/** Hive setup API against the real database: locks, unique keys, outbox. */
describe('Hive setup (e2e)', () => {
let app: INestApplication<App>;
let prisma: PrismaService;
const suffix = `${Date.now()}-${Math.round(Math.random() * 1e6)}`;
const password = 'SuperSecret123!';
const today = berlinToday();
const initDay = addDays(today, -5);
let apiaryId: string;
let colonyId: string;
const roleIds: string[] = [];
const userIds: string[] = [];
const tokens = { writer: '', reader: '' };
let counter = 0;
const key = () => `hive-e2e-${suffix}-${(counter += 1)}-key`;
const api = () => request(app.getHttpServer());
const auth = (token: string) => ({ Authorization: `Bearer ${token}` });
const url = (path = '') => `/api/v1/colonies/${colonyId}/hive${path}`;
async function createUser(label: string, permissions: string[]) {
const role = await prisma.role.create({
data: {
key: `HIVE_E2E_${label.toUpperCase()}_${suffix}`,
name: `Hive e2e ${label}`,
permissions: {
create: permissions.map((p) => ({
permission: { connect: { key: p } },
})),
},
},
});
roleIds.push(role.id);
const email = `hive-e2e-${label}-${suffix}@example.com`;
const user = await prisma.user.create({
data: {
email,
passwordHash: await bcrypt.hash(password, 12),
name: `Hive ${label}`,
role: { connect: { id: role.id } },
},
});
userIds.push(user.id);
return (await login(app, email, password)).accessToken;
}
const change = (overrides: object = {}) =>
api()
.post(url('/changes'))
.set(auth(tokens.writer))
.set('Idempotency-Key', key())
.send({
occurredOn: today,
source: 'CARD',
ops: [{ op: 'setLabel', id: 'e2e-box', label: 'Brutraum' }],
...overrides,
});
beforeAll(async () => {
app = await createTestApp();
prisma = app.get(PrismaService);
apiaryId = (
await prisma.apiary.create({ data: { name: `Hive e2e ${suffix}` } })
).id;
colonyId = (
await prisma.colony.create({
data: {
code: `HV-${suffix}`,
apiaryId,
colonyType: 'PRODUCTION_COLONY',
},
})
).id;
tokens.writer = await createUser('writer', [
'colonies:read',
'colonies:update',
]);
tokens.reader = await createUser('reader', ['colonies:read']);
});
afterAll(async () => {
await prisma.hiveChange.deleteMany({ where: { colonyId } });
await prisma.hiveSetup.deleteMany({ where: { colonyId } });
await prisma.domainEvent.deleteMany({ where: { aggregateId: colonyId } });
await prisma.colony.delete({ where: { id: colonyId } });
await prisma.apiary.delete({ where: { id: apiaryId } });
await prisma.idempotencyRecord.deleteMany({
where: { userId: { in: userIds } },
});
await prisma.refreshToken.deleteMany({
where: { userId: { in: userIds } },
});
await prisma.auditLog.deleteMany({ where: { userId: { in: userIds } } });
await prisma.user.deleteMany({ where: { id: { in: userIds } } });
await prisma.role.deleteMany({ where: { id: { in: roleIds } } });
await app.close();
});
it('answers 404 HIVE_NOT_FOUND before a setup exists', async () => {
const res = await api().get(url()).set(auth(tokens.reader)).expect(404);
expect(res.body).toMatchObject({ code: 'HIVE_NOT_FOUND' });
});
it('refuses a writer without colonies:update', async () => {
await api()
.post(url())
.set(auth(tokens.reader))
.set('Idempotency-Key', key())
.send({ systemId: SYSTEM_ID, state, occurredOn: initDay })
.expect(403);
});
it('creates the setup with version 1, an INIT change and an event', async () => {
const res = await api()
.post(url())
.set(auth(tokens.writer))
.set('Idempotency-Key', key())
.send({ systemId: SYSTEM_ID, state, occurredOn: initDay })
.expect(201);
expect(res.body).toMatchObject({ colonyId, version: 1 });
expect((res.body as ViewBody).facts.boxCount).toBe(1);
const init = await prisma.hiveChange.findUniqueOrThrow({
where: { colonyId_version: { colonyId, version: 1 } },
});
expect(init.source).toBe('INIT');
expect(init.occurredOn.toISOString().slice(0, 10)).toBe(initDay);
const events = await prisma.domainEvent.findMany({
where: { aggregateId: colonyId, type: 'HiveChanged' },
});
expect(events).toHaveLength(1);
expect(events[0].payload).toEqual({
colonyId,
version: 1,
source: 'INIT',
inspectionId: null,
});
});
it('answers 409 HIVE_EXISTS for a second setup', async () => {
const res = await api()
.post(url())
.set(auth(tokens.writer))
.set('Idempotency-Key', key())
.send({ systemId: SYSTEM_ID, state, occurredOn: initDay })
.expect(409);
expect(res.body).toMatchObject({ code: 'HIVE_EXISTS' });
});
it('applies a change, then a backdated one, and lists them by day', async () => {
const first = await change().expect(201);
const firstView = first.body as ViewBody;
expect(firstView.version).toBe(2);
expect(firstView.state.stack[1].label).toBe('Brutraum');
const backdated = await change({
occurredOn: addDays(initDay, 2),
ops: [{ op: 'setLabel', id: 'e2e-box', label: 'Nachtrag' }],
}).expect(201);
expect((backdated.body as ViewBody).version).toBe(3);
const history = await api()
.get(url('/changes'))
.set(auth(tokens.reader))
.expect(200);
const list = history.body as HistoryBody;
expect(versionsOf(list)).toEqual([2, 3, 1]);
expect(list.items[0].userName).toBe('Hive writer');
expect(list.items[0].stateAfter).toBeUndefined();
const page = await api()
.get(url('/changes?limit=1'))
.set(auth(tokens.reader))
.expect(200);
const firstPage = page.body as HistoryBody;
expect(firstPage.items).toHaveLength(1);
expect(firstPage.nextCursor).toMatch(/^[A-Za-z0-9_-]+$/);
const next = await api()
.get(
url(
`/changes?limit=5&cursor=${encodeURIComponent(firstPage.nextCursor ?? '')}`,
),
)
.set(auth(tokens.reader))
.expect(200);
expect(versionsOf(next.body as HistoryBody)).toEqual([3, 1]);
});
it('returns the state at a day and 404 before INIT', async () => {
const at = await api()
.get(url(`/at?day=${addDays(initDay, 2)}`))
.set(auth(tokens.reader))
.expect(200);
expect((at.body as ViewBody).version).toBe(3);
await api()
.get(url(`/at?day=${addDays(initDay, -1)}`))
.set(auth(tokens.reader))
.expect(404);
});
it('answers 409 HIVE_CONFLICT with the current state', async () => {
const res = await change({
ops: [{ op: 'removePart', id: 'gone' }],
}).expect(409);
expect(res.body).toMatchObject({
code: 'HIVE_CONFLICT',
opIndex: 0,
current: { version: 3 },
});
expect((res.body as ConflictBody).current.state.schemaVersion).toBe(1);
});
it('answers 400 for shape errors, AI_SUGGESTION and wrong days', async () => {
await change({ ops: [{ op: 'explode' }] }).expect(400);
await change({ source: 'AI_SUGGESTION' }).expect(400);
await change({ ops: [] }).expect(400);
await change({ occurredOn: addDays(today, 1) }).expect(400);
await change({ occurredOn: addDays(initDay, -1) }).expect(400);
});
it('replays an idempotent retry without a second change', async () => {
const retryKey = key();
const send = () =>
api()
.post(url('/changes'))
.set(auth(tokens.writer))
.set('Idempotency-Key', retryKey)
.send({
occurredOn: today,
source: 'EDITOR',
ops: [{ op: 'setLabel', id: 'e2e-box', label: 'Retry' }],
});
const first = await send().expect(201);
const second = await send().expect(201);
const firstVersion = (first.body as ViewBody).version;
expect((second.body as ViewBody).version).toBe(firstVersion);
expect(await prisma.hiveChange.count({ where: { colonyId } })).toBe(
firstVersion,
);
});
it('makes a colony that no longer lives read-only', async () => {
await prisma.colony.update({
where: { id: colonyId },
data: { status: 'SOLD' },
});
await change().expect(409);
await prisma.colony.update({
where: { id: colonyId },
data: { status: 'ACTIVE' },
});
});
});
/** An inspection carries hive operations that are saved with it atomically. */
describe('Inspection with hiveChange (e2e)', () => {
let app: INestApplication<App>;
let prisma: PrismaService;
const suffix = `${Date.now()}-${Math.round(Math.random() * 1e6)}`;
const password = 'SuperSecret123!';
const today = berlinToday();
let apiaryId: string;
let colonyId: string;
let bareColonyId: string;
const roleIds: string[] = [];
const userIds: string[] = [];
const tokens = { full: '', inspectorOnly: '' };
let counter = 0;
const key = () => `hive-insp-${suffix}-${(counter += 1)}-key`;
const api = () => request(app.getHttpServer());
const auth = (token: string) => ({ Authorization: `Bearer ${token}` });
async function createUser(label: string, permissions: string[]) {
const role = await prisma.role.create({
data: {
key: `HIVE_INSP_${label.toUpperCase()}_${suffix}`,
name: `Hive inspection ${label}`,
permissions: {
create: permissions.map((p) => ({
permission: { connect: { key: p } },
})),
},
},
});
roleIds.push(role.id);
const email = `hive-insp-${label}-${suffix}@example.com`;
const user = await prisma.user.create({
data: {
email,
passwordHash: await bcrypt.hash(password, 12),
name: `Hive inspection ${label}`,
role: { connect: { id: role.id } },
},
});
userIds.push(user.id);
return (await login(app, email, password)).accessToken;
}
const inspect = (token: string, body: object, targetColony = colonyId) =>
api()
.post('/api/v1/inspections')
.set(auth(token))
.set('Idempotency-Key', key())
.send({
colonyId: targetColony,
date: new Date().toISOString(),
...body,
});
const labelOp = (label: string, id = 'e2e-box') => ({
op: 'setLabel',
id,
label,
});
const inspectionCount = (id = colonyId) =>
prisma.inspection.count({ where: { colonyId: id } });
beforeAll(async () => {
app = await createTestApp();
prisma = app.get(PrismaService);
apiaryId = (
await prisma.apiary.create({ data: { name: `Hive insp ${suffix}` } })
).id;
const make = async (code: string) =>
(
await prisma.colony.create({
data: {
code: `${code}-${suffix}`,
apiaryId,
colonyType: 'PRODUCTION_COLONY',
},
})
).id;
colonyId = await make('HI');
bareColonyId = await make('HB');
tokens.full = await createUser('full', [
'colonies:read',
'colonies:update',
'inspections:create',
]);
tokens.inspectorOnly = await createUser('inspector', [
'colonies:read',
'inspections:create',
]);
await api()
.post(`/api/v1/colonies/${colonyId}/hive`)
.set(auth(tokens.full))
.set('Idempotency-Key', key())
.send({
systemId: SYSTEM_ID,
state,
occurredOn: addDays(today, -5),
})
.expect(201);
});
afterAll(async () => {
const colonyIds = [colonyId, bareColonyId];
await prisma.hiveChange.deleteMany({
where: { colonyId: { in: colonyIds } },
});
await prisma.hiveSetup.deleteMany({
where: { colonyId: { in: colonyIds } },
});
await prisma.inspection.deleteMany({
where: { colonyId: { in: colonyIds } },
});
await prisma.domainEvent.deleteMany({
where: { aggregateId: { in: colonyIds } },
});
await prisma.colony.deleteMany({ where: { id: { in: colonyIds } } });
await prisma.apiary.delete({ where: { id: apiaryId } });
await prisma.idempotencyRecord.deleteMany({
where: { userId: { in: userIds } },
});
await prisma.refreshToken.deleteMany({
where: { userId: { in: userIds } },
});
await prisma.auditLog.deleteMany({ where: { userId: { in: userIds } } });
await prisma.user.deleteMany({ where: { id: { in: userIds } } });
await prisma.role.deleteMany({ where: { id: { in: roleIds } } });
await app.close();
});
it('saves the inspection and its hive change together', async () => {
const res = await inspect(tokens.full, {
hiveChange: { ops: [labelOp('Brutraum')] },
}).expect(201);
const body = res.body as { id: string; hive: ViewBody };
expect(body.hive.version).toBe(2);
const change = await prisma.hiveChange.findUniqueOrThrow({
where: { colonyId_version: { colonyId, version: 2 } },
});
expect(change).toMatchObject({
source: 'INSPECTION',
inspectionId: body.id,
});
expect(change.occurredOn.toISOString().slice(0, 10)).toBe(today);
expect(await inspectionCount()).toBe(1);
});
it('leaves no inspection row when an operation conflicts', async () => {
const before = await inspectionCount();
const res = await inspect(tokens.full, {
hiveChange: { ops: [labelOp('x', 'does-not-exist')] },
}).expect(409);
expect(res.body).toMatchObject({ code: 'HIVE_CONFLICT', opIndex: 0 });
expect(await inspectionCount()).toBe(before);
expect(await prisma.hiveChange.count({ where: { colonyId } })).toBe(2);
});
it('leaves no inspection row for a colony without a hive setup', async () => {
const res = await inspect(
tokens.full,
{ hiveChange: { ops: [labelOp('x')] } },
bareColonyId,
).expect(404);
expect(res.body).toMatchObject({ code: 'HIVE_NOT_FOUND' });
expect(await inspectionCount(bareColonyId)).toBe(0);
});
it('answers 403 HIVE_FORBIDDEN without colonies:update and writes nothing', async () => {
const before = await inspectionCount();
const res = await inspect(tokens.inspectorOnly, {
hiveChange: { ops: [labelOp('Nein')] },
}).expect(403);
expect(res.body).toMatchObject({ code: 'HIVE_FORBIDDEN' });
expect(await inspectionCount()).toBe(before);
expect(await prisma.hiveChange.count({ where: { colonyId } })).toBe(2);
});
it('answers 400 for a future inspection date and one before the INIT day', async () => {
const before = await inspectionCount();
const future = new Date(Date.now() + 3 * 86_400_000).toISOString();
const early = new Date(Date.now() - 30 * 86_400_000).toISOString();
for (const date of [future, early]) {
await inspect(tokens.full, {
date,
hiveChange: { ops: [labelOp('Datum')] },
}).expect(400);
}
expect(await inspectionCount()).toBe(before);
});
it('answers 400 for an empty ops list and still saves a plain inspection', async () => {
await inspect(tokens.full, { hiveChange: { ops: [] } }).expect(400);
const plain = await inspect(tokens.inspectorOnly, {}).expect(201);
expect(plain.body).not.toHaveProperty('hive');
});
});