Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ Versions follow [Semantic Versioning](https://semver.org/) — minor bump per su
Writes target the row captured at `GET` time, mirroring how `grid-edit` already writes by
rowid. This is the PR that promotes `LOOKUP` to the README command reference in full —
both BROWSE and forms now declare, enforce, and render it end to end.
- **Demos adopt `LOOKUP`** (#61). `demos/overtime.prg` gains a `SCHEDULES` catalog table
(`SCHEDID`, `DESCR`) as the lookup source for `EMPLOYEES.SCHEDID` — Add Employee is now a
check-first, two-form flow where the schedule is picked from a dropdown showing the
description ("Standard 40h (08:00-16:30)") instead of typed from memory. `demos/crm.prg`'s
`DEALS.STAGE` is constrained to a literal `LOOKUP` list matching its own seeded vocabulary
exactly, exercising the other lookup kind in a real, working demo.

## [1.2.0] — 2026-07-09 — TIME columns, WEEK()/DATEADD(), BROWSE cell validation, Overtime demo

Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ npm run coverage # Vitest + v8 coverage report (reporting only, no thresh
npx playwright test # E2E browser tests — requires dev server on :5173/:3000
```

Playwright suites (94 tests): `tests/assistant.spec.ts` (23 tests — sidebar, wizards, report designer, MODIFY STRUCTURE round-trip, `TIME(15)` column + REPLACE validation, `NUM(p,s)` wizard, Browse-action grid validation, program run, CSV/SORT/SUM-AVERAGE/REINDEX/PACK actions, demo launchers), `tests/integration.spec.ts` (20 tests — full REPL scenario), `tests/overtime.spec.ts` (9 tests — overtime.prg: menu, seeding, DATEADD week prep, TIME(15) grid rejection, recalculation, live balance, quarter-hour leave check, report, CSV), `tests/inventory.spec.ts` (8 tests — INVENTORY.prg menu + valuation/low-stock report/sort/CSV/JOIN), `tests/crm.spec.ts` (6 tests — CRM demo menu, pipeline summary, sort, report, CSV, JOIN), `tests/parity-commands.spec.ts` (6 tests — `?`/`??`, built-in functions, `WEEK()`, `DATEADD()`, `SUM`/`AVERAGE`, `SORT ON … TO`), `tests/multiarea.spec.ts` (4 tests — multi-work-area, relations, alias.field), `tests/demos.spec.ts` (4 tests — demo program + report seeding), `tests/grid-validation.spec.ts` (3 tests — BROWSE per-cell validation: TIME(15), NUM(p,s)/DATE, Esc abandons), `tests/schema-errors.spec.ts` (3 tests — malformed CREATE TABLE errors, NUM(p,s) column count, bare INPUT stores its value), `tests/copycsv.spec.ts` (2 tests — COPY TO download + APPEND FROM upload), `tests/splash.spec.ts` (2 tests — version banner + demo discoverability), `tests/join.spec.ts` (1 test — JOIN materialization), `tests/propagation.spec.ts` (1 test — live multiuser refresh), `tests/program-side-effects.spec.ts` (1 test — CSV/report side-effects fire from inside a program block).
Playwright suites (95 tests): `tests/assistant.spec.ts` (23 tests — sidebar, wizards, report designer, MODIFY STRUCTURE round-trip, `TIME(15)` column + REPLACE validation, `NUM(p,s)` wizard, Browse-action grid validation, program run, CSV/SORT/SUM-AVERAGE/REINDEX/PACK actions, demo launchers), `tests/integration.spec.ts` (20 tests — full REPL scenario), `tests/overtime.spec.ts` (10 tests — overtime.prg: menu, seeding, DATEADD week prep, TIME(15) grid rejection, recalculation, live balance, quarter-hour leave check, report, CSV, Add-Employee lookup dropdown), `tests/inventory.spec.ts` (8 tests — INVENTORY.prg menu + valuation/low-stock report/sort/CSV/JOIN), `tests/crm.spec.ts` (6 tests — CRM demo menu, pipeline summary, sort, report, CSV, JOIN), `tests/parity-commands.spec.ts` (6 tests — `?`/`??`, built-in functions, `WEEK()`, `DATEADD()`, `SUM`/`AVERAGE`, `SORT ON … TO`), `tests/multiarea.spec.ts` (4 tests — multi-work-area, relations, alias.field), `tests/demos.spec.ts` (4 tests — demo program + report seeding), `tests/grid-validation.spec.ts` (3 tests — BROWSE per-cell validation: TIME(15), NUM(p,s)/DATE, Esc abandons), `tests/schema-errors.spec.ts` (3 tests — malformed CREATE TABLE errors, NUM(p,s) column count, bare INPUT stores its value), `tests/copycsv.spec.ts` (2 tests — COPY TO download + APPEND FROM upload), `tests/splash.spec.ts` (2 tests — version banner + demo discoverability), `tests/join.spec.ts` (1 test — JOIN materialization), `tests/propagation.spec.ts` (1 test — live multiuser refresh), `tests/program-side-effects.spec.ts` (1 test — CSV/report side-effects fire from inside a program block).

## Test discipline

Expand Down
2 changes: 1 addition & 1 deletion demos/crm.prg
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ IF RECCOUNT() == 0

SELECT DEAL
DROP TABLE DEALS
CREATE TABLE DEALS (DEALID CHAR(6), COMPID CHAR(5), TITLE CHAR(40), STAGE CHAR(12), VALUE NUM(12,2), CLOSEMONTH NUM(6))
CREATE TABLE DEALS (DEALID CHAR(6), COMPID CHAR(5), TITLE CHAR(40), STAGE CHAR(12) LOOKUP ("Lead","Qualified","Proposal","Won","Lost"), VALUE NUM(12,2), CLOSEMONTH NUM(6))
INDEX ON DEALID TO BYDEAL
INDEX ON COMPID TO DEALCOMP
APPEND RECORD
Expand Down
34 changes: 25 additions & 9 deletions demos/overtime.prg
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ SELECT SCH
USE DATABASE OVERTIME
USE SCHEDULEDAYS

SELECT SCD
USE DATABASE OVERTIME
USE SCHEDULES

SELECT TS
USE DATABASE OVERTIME
USE TIMESHEET
Expand All @@ -52,8 +56,17 @@ USE LEAVETAKEN
* wipe TIMESHEET and WEEKSUMMARY — on every run until someone used it.
SELECT EMP
IF RECCOUNT() == 0
SELECT SCD
DROP TABLE SCHEDULES
CREATE TABLE SCHEDULES (SCHEDID CHAR(4), DESCR CHAR(30))
APPEND RECORD
REPLACE SCHEDID WITH "S001", DESCR WITH "Standard 40h (08:00-16:30)"
APPEND RECORD
REPLACE SCHEDID WITH "S002", DESCR WITH "Short 31.25h (09:00-16:00)"

SELECT EMP
DROP TABLE EMPLOYEES
CREATE TABLE EMPLOYEES (EMPID CHAR(4), NAME CHAR(30), SCHEDID CHAR(4))
CREATE TABLE EMPLOYEES (EMPID CHAR(4), NAME CHAR(30), SCHEDID CHAR(4) LOOKUP SCHEDULES.SCHEDID DISPLAY DESCR)
INDEX ON EMPID TO BYEMP
APPEND RECORD
REPLACE EMPID WITH "E001", NAME WITH "Ada Lovelace", SCHEDID WITH "S001"
Expand Down Expand Up @@ -139,21 +152,24 @@ DO WHILE running
CASE UPPER(TRIM(choice)) == "1"
CLEAR
@ 2, 5 SAY "--- ADD EMPLOYEE ---"
STORE SPACE(4) TO m_emp
STORE SPACE(30) TO m_name
STORE SPACE(4) TO m_sch
@ 4, 5 SAY "Employee ID (4): " GET m_emp
@ 5, 5 SAY "Name (30): " GET m_name
@ 6, 5 SAY "Schedule ID (4): " GET m_sch
READ
SELECT EMP
SET INDEX TO BYEMP
STORE SPACE(4) TO m_emp
@ 4, 5 SAY "Employee ID (4): " GET m_emp
READ
SEEK TRIM(m_emp)
IF FOUND()
@ 8, 5 SAY "Employee already exists: " + TRIM(m_emp)
ELSE
* Create in natural order: writing the key under an active index
* would move the record out from under the form.
SET INDEX TO
APPEND RECORD
REPLACE EMPID WITH TRIM(m_emp), NAME WITH TRIM(m_name), SCHEDID WITH TRIM(m_sch)
REPLACE EMPID WITH TRIM(m_emp)
@ 5, 5 SAY "Name (30): " GET NAME
@ 6, 5 SAY "Schedule : " GET SCHEDID
READ
SET INDEX TO BYEMP
@ 8, 5 SAY "Employee added: " + TRIM(m_emp)
ENDIF
INPUT "Press Enter to continue" TO pause
Expand Down
1 change: 1 addition & 0 deletions tests/DemoSchemas.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const DEMO_SCHEMAS: Record<string, string[]> = {

// overtime.prg (#46)
EMPLOYEES: ['EMPID', 'NAME', 'SCHEDID'],
SCHEDULES: ['SCHEDID', 'DESCR'],
SCHEDULEDAYS: ['SCHEDID', 'DOW', 'TIMEIN', 'BSTART', 'BEND', 'TIMEOUT'],
TIMESHEET: ['EMPID', 'WEEKDATE', 'DOW', 'WORKDATE', 'TIMEIN', 'BSTART', 'BEND', 'TIMEOUT', 'WORKEDHOURS'],
WEEKSUMMARY: ['EMPID', 'WEEKDATE', 'WEEKNO', 'WORKEDHOURS', 'STANDARDHOURS', 'OVERTIME'],
Expand Down
31 changes: 30 additions & 1 deletion tests/overtime.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ test.describe('Overtime demo', () => {
await seedProgram(page);
// Clean slate: the OVERTIME database persists server-side across suites.
await cmd(page, 'USE DATABASE OVERTIME');
for (const t of ['EMPLOYEES', 'SCHEDULEDAYS', 'TIMESHEET', 'WEEKSUMMARY', 'LEAVETAKEN']) {
for (const t of ['EMPLOYEES', 'SCHEDULES', 'SCHEDULEDAYS', 'TIMESHEET', 'WEEKSUMMARY', 'LEAVETAKEN']) {
await cmd(page, `DROP TABLE ${t}`, 150);
}
await cmd(page, `DO ${PRG_NAME}`, 2000);
Expand All @@ -100,6 +100,35 @@ test.describe('Overtime demo', () => {
await ack(page);
});

test('Add Employee: the schedule is picked from a lookup dropdown, not typed', async ({ page }) => {
await menuChoice(page, '1'); // Add Employee → form 1 (id)
await expect(page.locator('#form-view')).toContainText('ADD EMPLOYEE', { timeout: 6000 });
const idInput = page.locator('#form-view input.f-get').last();
await idInput.fill('E003');
await idInput.press('Enter');

// Form 2: NAME is a text field, SCHEDID is a <select> fed by SCHEDULES.
const sched = page.locator('#form-view select.f-get');
await expect(sched).toBeVisible({ timeout: 6000 });
await expect(sched).toBeInViewport();
// DISPLAY label + code are both shown in the option text.
await expect(sched.locator('option', { hasText: 'Standard 40h' })).toHaveCount(1);

const name = page.locator('#form-view input.f-get').first();
await name.fill('Alan Turing');
await sched.selectOption('S001');
await sched.press('Enter'); // last control → submit

await expect(page.locator('#form-view')).toContainText('Employee added: E003', { timeout: 6000 });
await ack(page);

// Verify through the table tour that the record landed with the code.
await menuChoice(page, '9');
await expect(page.locator('#terminal-output')).toContainText('Alan Turing');
await expect(page.locator('#terminal-output')).toContainText('S001');
await ack(page);
});

test('prep week derives Mon-Fri work dates with DATEADD and shows the ISO week', async ({ page }) => {
await menuChoice(page, '3');
await fillForm(page, ['E001', WEEK], 2000);
Expand Down
Loading