kammer/e2e/support/item-factory.ts
Christopher Mühl ba68fb456a test: E2E test suite + handoff documentation
50 Playwright E2E tests across 13 spec files covering all routes and
user flows (items CRUD, check-out/in, locations, labels, scanning,
search/filter). Uses vitest as runner with playwright-core for browser
automation (bun-compatible alternative to @playwright/test).

Includes Gherkin .feature files as living documentation, test support
infrastructure (IDB seeding, item factories, assertion helpers, layout
measurement), and HANDOFF.md covering project state, deployment, and
open design decisions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 20:53:08 +01:00

102 lines
2.4 KiB
TypeScript

import type { Item } from '../../src/lib/types';
let counter = 0;
function nextId(): string {
counter++;
const chars = '23456789abcdefghjkmnpqrstuvwxyz';
let id = '';
let n = counter;
for (let i = 0; i < 7; i++) {
id += chars[n % chars.length];
n = Math.floor(n / chars.length);
}
return id;
}
export interface ItemOverrides extends Partial<Item> {}
export function buildItem(overrides: ItemOverrides = {}): Item {
const shortId = overrides.shortId ?? nextId();
const now = new Date().toISOString();
return {
shortId,
name: `Test Item ${shortId}`,
description: '',
category: '',
brand: '',
serialNumber: '',
color: '',
purchaseDate: null,
itemType: 'durable',
currentQuantity: null,
originalQuantity: null,
quantityUnit: null,
lowThreshold: null,
expiryDate: null,
barcodeFormat: 'qr',
barcodeUri: `https://haus.toph.so/${shortId}`,
photoIds: [],
lastSeenAt: null,
lastSeenTimestamp: null,
lastUsedAt: null,
supposedToBeAt: null,
locationConfidence: 'unknown',
custodyState: 'checked-in',
checkedOutSince: null,
checkedOutReason: null,
checkedOutFrom: null,
checkedOutTo: null,
checkedOutNote: null,
storageTier: 'warm',
storageContainerId: null,
storageContainerLabel: null,
labelPrinted: false,
labelPrintedAt: null,
labelBatchId: null,
createdAt: now,
updatedAt: now,
tags: [],
createdBy: null,
...overrides,
};
}
export function buildCheckedOutItem(overrides: ItemOverrides = {}): Item {
const tenDaysAgo = new Date(Date.now() - 10 * 86400000).toISOString();
return buildItem({
custodyState: 'checked-out',
checkedOutSince: tenDaysAgo,
checkedOutReason: 'in-use',
checkedOutFrom: 'kueche',
checkedOutTo: null,
checkedOutNote: '',
...overrides,
});
}
export function buildConsumableItem(overrides: ItemOverrides = {}): Item {
return buildItem({
itemType: 'consumable',
currentQuantity: 3,
originalQuantity: 10,
quantityUnit: 'pcs',
lowThreshold: 5,
...overrides,
});
}
export function buildItemAtLocation(locationId: string, overrides: ItemOverrides = {}): Item {
const now = new Date().toISOString();
return buildItem({
lastSeenAt: locationId,
lastSeenTimestamp: now,
supposedToBeAt: locationId,
locationConfidence: 'confirmed',
...overrides,
});
}
export function resetCounter() {
counter = 0;
}