Skip to content

Commit c312bcd

Browse files
authored
Merge pull request #66 from DDecoene/feature/61-demo-lookups
feat: demos adopt LOOKUP columns — overtime + CRM (#61)
2 parents 28e976a + 774efdb commit c312bcd

6 files changed

Lines changed: 64 additions & 12 deletions

File tree

CHANGELOG.md

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

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

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ npm run coverage # Vitest + v8 coverage report (reporting only, no thresh
378378
npx playwright test # E2E browser tests — requires dev server on :5173/:3000
379379
```
380380

381-
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).
381+
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).
382382

383383
## Test discipline
384384

demos/crm.prg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ IF RECCOUNT() == 0
4545

4646
SELECT DEAL
4747
DROP TABLE DEALS
48-
CREATE TABLE DEALS (DEALID CHAR(6), COMPID CHAR(5), TITLE CHAR(40), STAGE CHAR(12), VALUE NUM(12,2), CLOSEMONTH NUM(6))
48+
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))
4949
INDEX ON DEALID TO BYDEAL
5050
INDEX ON COMPID TO DEALCOMP
5151
APPEND RECORD

demos/overtime.prg

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ SELECT SCH
3131
USE DATABASE OVERTIME
3232
USE SCHEDULEDAYS
3333

34+
SELECT SCD
35+
USE DATABASE OVERTIME
36+
USE SCHEDULES
37+
3438
SELECT TS
3539
USE DATABASE OVERTIME
3640
USE TIMESHEET
@@ -52,8 +56,17 @@ USE LEAVETAKEN
5256
* wipe TIMESHEET and WEEKSUMMARY — on every run until someone used it.
5357
SELECT EMP
5458
IF RECCOUNT() == 0
59+
SELECT SCD
60+
DROP TABLE SCHEDULES
61+
CREATE TABLE SCHEDULES (SCHEDID CHAR(4), DESCR CHAR(30))
62+
APPEND RECORD
63+
REPLACE SCHEDID WITH "S001", DESCR WITH "Standard 40h (08:00-16:30)"
64+
APPEND RECORD
65+
REPLACE SCHEDID WITH "S002", DESCR WITH "Short 31.25h (09:00-16:00)"
66+
67+
SELECT EMP
5568
DROP TABLE EMPLOYEES
56-
CREATE TABLE EMPLOYEES (EMPID CHAR(4), NAME CHAR(30), SCHEDID CHAR(4))
69+
CREATE TABLE EMPLOYEES (EMPID CHAR(4), NAME CHAR(30), SCHEDID CHAR(4) LOOKUP SCHEDULES.SCHEDID DISPLAY DESCR)
5770
INDEX ON EMPID TO BYEMP
5871
APPEND RECORD
5972
REPLACE EMPID WITH "E001", NAME WITH "Ada Lovelace", SCHEDID WITH "S001"
@@ -139,21 +152,24 @@ DO WHILE running
139152
CASE UPPER(TRIM(choice)) == "1"
140153
CLEAR
141154
@ 2, 5 SAY "--- ADD EMPLOYEE ---"
142-
STORE SPACE(4) TO m_emp
143-
STORE SPACE(30) TO m_name
144-
STORE SPACE(4) TO m_sch
145-
@ 4, 5 SAY "Employee ID (4): " GET m_emp
146-
@ 5, 5 SAY "Name (30): " GET m_name
147-
@ 6, 5 SAY "Schedule ID (4): " GET m_sch
148-
READ
149155
SELECT EMP
150156
SET INDEX TO BYEMP
157+
STORE SPACE(4) TO m_emp
158+
@ 4, 5 SAY "Employee ID (4): " GET m_emp
159+
READ
151160
SEEK TRIM(m_emp)
152161
IF FOUND()
153162
@ 8, 5 SAY "Employee already exists: " + TRIM(m_emp)
154163
ELSE
164+
* Create in natural order: writing the key under an active index
165+
* would move the record out from under the form.
166+
SET INDEX TO
155167
APPEND RECORD
156-
REPLACE EMPID WITH TRIM(m_emp), NAME WITH TRIM(m_name), SCHEDID WITH TRIM(m_sch)
168+
REPLACE EMPID WITH TRIM(m_emp)
169+
@ 5, 5 SAY "Name (30): " GET NAME
170+
@ 6, 5 SAY "Schedule : " GET SCHEDID
171+
READ
172+
SET INDEX TO BYEMP
157173
@ 8, 5 SAY "Employee added: " + TRIM(m_emp)
158174
ENDIF
159175
INPUT "Press Enter to continue" TO pause

tests/DemoSchemas.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const DEMO_SCHEMAS: Record<string, string[]> = {
2525

2626
// overtime.prg (#46)
2727
EMPLOYEES: ['EMPID', 'NAME', 'SCHEDID'],
28+
SCHEDULES: ['SCHEDID', 'DESCR'],
2829
SCHEDULEDAYS: ['SCHEDID', 'DOW', 'TIMEIN', 'BSTART', 'BEND', 'TIMEOUT'],
2930
TIMESHEET: ['EMPID', 'WEEKDATE', 'DOW', 'WORKDATE', 'TIMEIN', 'BSTART', 'BEND', 'TIMEOUT', 'WORKEDHOURS'],
3031
WEEKSUMMARY: ['EMPID', 'WEEKDATE', 'WEEKNO', 'WORKEDHOURS', 'STANDARDHOURS', 'OVERTIME'],

tests/overtime.spec.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ test.describe('Overtime demo', () => {
7979
await seedProgram(page);
8080
// Clean slate: the OVERTIME database persists server-side across suites.
8181
await cmd(page, 'USE DATABASE OVERTIME');
82-
for (const t of ['EMPLOYEES', 'SCHEDULEDAYS', 'TIMESHEET', 'WEEKSUMMARY', 'LEAVETAKEN']) {
82+
for (const t of ['EMPLOYEES', 'SCHEDULES', 'SCHEDULEDAYS', 'TIMESHEET', 'WEEKSUMMARY', 'LEAVETAKEN']) {
8383
await cmd(page, `DROP TABLE ${t}`, 150);
8484
}
8585
await cmd(page, `DO ${PRG_NAME}`, 2000);
@@ -100,6 +100,35 @@ test.describe('Overtime demo', () => {
100100
await ack(page);
101101
});
102102

103+
test('Add Employee: the schedule is picked from a lookup dropdown, not typed', async ({ page }) => {
104+
await menuChoice(page, '1'); // Add Employee → form 1 (id)
105+
await expect(page.locator('#form-view')).toContainText('ADD EMPLOYEE', { timeout: 6000 });
106+
const idInput = page.locator('#form-view input.f-get').last();
107+
await idInput.fill('E003');
108+
await idInput.press('Enter');
109+
110+
// Form 2: NAME is a text field, SCHEDID is a <select> fed by SCHEDULES.
111+
const sched = page.locator('#form-view select.f-get');
112+
await expect(sched).toBeVisible({ timeout: 6000 });
113+
await expect(sched).toBeInViewport();
114+
// DISPLAY label + code are both shown in the option text.
115+
await expect(sched.locator('option', { hasText: 'Standard 40h' })).toHaveCount(1);
116+
117+
const name = page.locator('#form-view input.f-get').first();
118+
await name.fill('Alan Turing');
119+
await sched.selectOption('S001');
120+
await sched.press('Enter'); // last control → submit
121+
122+
await expect(page.locator('#form-view')).toContainText('Employee added: E003', { timeout: 6000 });
123+
await ack(page);
124+
125+
// Verify through the table tour that the record landed with the code.
126+
await menuChoice(page, '9');
127+
await expect(page.locator('#terminal-output')).toContainText('Alan Turing');
128+
await expect(page.locator('#terminal-output')).toContainText('S001');
129+
await ack(page);
130+
});
131+
103132
test('prep week derives Mon-Fri work dates with DATEADD and shows the ISO week', async ({ page }) => {
104133
await menuChoice(page, '3');
105134
await fillForm(page, ['E001', WEEK], 2000);

0 commit comments

Comments
 (0)