Skip to content

Commit e524000

Browse files
committed
Add confirmed independent DB reseed control to login page - PR_26158_038-login-db-reseed-control
1 parent 05c8fe6 commit e524000

10 files changed

Lines changed: 361 additions & 29 deletions

File tree

assets/theme-v2/js/login-session.js

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
setSessionMode,
66
setSessionUser,
77
} from "../../../src/engine/api/session-api-client.js";
8+
import { seedMockDb } from "../../../src/engine/api/mock-db-api-client.js";
89

910
const modeButtons = Array.from(document.querySelectorAll("[data-login-mode]"));
1011
const modeTitle = document.querySelector("[data-login-mode-title]");
@@ -14,11 +15,21 @@ const modeDisabledMessage = document.querySelector("[data-login-mode-disabled-me
1415
const userControls = document.querySelector("[data-login-user-controls]");
1516
const userStatus = document.querySelector("[data-login-user-status]");
1617
const continueLink = document.querySelector("[data-login-continue]");
18+
const reseedFields = {
19+
activeMode: document.querySelector("[data-login-reseed-active-mode]"),
20+
cancelButton: document.querySelector("[data-login-reseed-cancel]"),
21+
confirmButton: document.querySelector("[data-login-reseed-confirm]"),
22+
startButton: document.querySelector("[data-login-reseed-start]"),
23+
status: document.querySelector("[data-login-reseed-status]"),
24+
target: document.querySelector("[data-login-reseed-target]"),
25+
};
1726
const localApiStartCommand = "npm run dev:local-api";
1827
const localApiLoginUrl = "http://127.0.0.1:5501/login.html";
1928
const expectedSessionEndpoint = "/api/session/current";
2029
const apiBackedLoginDiagnostic = `Use the API-backed local server for login. Run ${localApiStartCommand} and open ${localApiLoginUrl}.`;
2130
const staticModeDisabledMessage = `Use the API-backed local server for login. Run ${localApiStartCommand} and open ${localApiLoginUrl}. Local Mem and Local DB are disabled until the local API server is running.`;
31+
let reseedConfirmationPending = false;
32+
let reseedStatusMessage = "";
2233
const localStatusFields = {
2334
api: document.querySelector("[data-login-status-api]"),
2435
apiUrl: document.querySelector("[data-login-status-api-url]"),
@@ -68,6 +79,55 @@ function updateLocalDevelopmentStatus({ apiAvailability, disabledReason, serverM
6879
}
6980
}
7081

82+
function setReseedButtonState(button, disabled) {
83+
if (!button) {
84+
return;
85+
}
86+
button.disabled = disabled;
87+
if (disabled) {
88+
button.setAttribute("aria-disabled", "true");
89+
} else {
90+
button.removeAttribute("aria-disabled");
91+
}
92+
}
93+
94+
function reseedModeLabel(mode) {
95+
return mode?.label || mode?.environment || mode?.id || "selected DB mode";
96+
}
97+
98+
function updateReseedControls({ apiAvailable, mode, statusMessage }) {
99+
const modeLabel = apiAvailable ? reseedModeLabel(mode) : "Unavailable";
100+
const message = statusMessage || (apiAvailable
101+
? `Ready to reseed ${modeLabel} only.`
102+
: "Reseed unavailable until the Local API is available.");
103+
if (reseedFields.activeMode) {
104+
reseedFields.activeMode.textContent = modeLabel;
105+
}
106+
if (reseedFields.target) {
107+
reseedFields.target.textContent = modeLabel;
108+
}
109+
if (reseedFields.status) {
110+
reseedFields.status.textContent = message;
111+
}
112+
setReseedButtonState(reseedFields.startButton, !apiAvailable || reseedConfirmationPending);
113+
setReseedButtonState(reseedFields.confirmButton, !apiAvailable || !reseedConfirmationPending);
114+
setReseedButtonState(reseedFields.cancelButton, !apiAvailable || !reseedConfirmationPending);
115+
if (reseedFields.confirmButton) {
116+
reseedFields.confirmButton.hidden = !apiAvailable || !reseedConfirmationPending;
117+
}
118+
if (reseedFields.cancelButton) {
119+
reseedFields.cancelButton.hidden = !apiAvailable || !reseedConfirmationPending;
120+
}
121+
}
122+
123+
function currentModeForReseed() {
124+
const session = getSessionCurrent();
125+
return getSessionModes().find((item) => item.id === session.mode) || {
126+
id: session.mode,
127+
label: session.environment || session.mode,
128+
};
129+
}
130+
71131
function dispatchSessionChanged() {
72132
window.dispatchEvent(new CustomEvent("gamefoundry:mock-db-session-user-changed", {
73133
detail: getSessionCurrent(),
@@ -147,6 +207,8 @@ function renderError(error) {
147207
const disabledReason = message === apiBackedLoginDiagnostic
148208
? staticModeDisabledMessage
149209
: `Local Mem and Local DB are disabled because ${message}`;
210+
reseedConfirmationPending = false;
211+
reseedStatusMessage = "Reseed unavailable until the Local API is available.";
150212
modeButtons.forEach((button) => {
151213
button.disabled = true;
152214
button.setAttribute("aria-disabled", "true");
@@ -177,6 +239,11 @@ function renderError(error) {
177239
disabledReason,
178240
serverMode,
179241
});
242+
updateReseedControls({
243+
apiAvailable: false,
244+
mode: null,
245+
statusMessage: reseedStatusMessage,
246+
});
180247
updateContinueLink();
181248
}
182249

@@ -216,6 +283,11 @@ function render() {
216283
disabledReason: "Local Mem and Local DB are enabled because the Local API is available.",
217284
serverMode: `API-backed local server (${mode.label || session.mode})`,
218285
});
286+
updateReseedControls({
287+
apiAvailable: true,
288+
mode,
289+
statusMessage: reseedStatusMessage,
290+
});
219291
if (modeDisabledMessage) {
220292
modeDisabledMessage.hidden = true;
221293
modeDisabledMessage.textContent = "";
@@ -235,6 +307,8 @@ modeButtons.forEach((button) => {
235307
return;
236308
}
237309
try {
310+
reseedConfirmationPending = false;
311+
reseedStatusMessage = "";
238312
setSessionMode(modeId);
239313
dispatchModeChanged();
240314
render();
@@ -258,4 +332,51 @@ userControls?.addEventListener("click", (event) => {
258332
}
259333
});
260334

335+
reseedFields.startButton?.addEventListener("click", () => {
336+
try {
337+
const mode = currentModeForReseed();
338+
const modeLabel = reseedModeLabel(mode);
339+
reseedConfirmationPending = true;
340+
reseedStatusMessage = `Confirm reseed for ${modeLabel} only. The other DB mode will not be reseeded.`;
341+
render();
342+
} catch (error) {
343+
reseedConfirmationPending = false;
344+
reseedStatusMessage = `Reseed unavailable: ${errorMessage(error)}`;
345+
renderError(error);
346+
}
347+
});
348+
349+
reseedFields.cancelButton?.addEventListener("click", () => {
350+
try {
351+
const modeLabel = reseedModeLabel(currentModeForReseed());
352+
reseedConfirmationPending = false;
353+
reseedStatusMessage = `Reseed canceled for ${modeLabel}.`;
354+
render();
355+
} catch (error) {
356+
reseedConfirmationPending = false;
357+
reseedStatusMessage = `Reseed canceled. ${errorMessage(error)}`;
358+
renderError(error);
359+
}
360+
});
361+
362+
reseedFields.confirmButton?.addEventListener("click", () => {
363+
try {
364+
const modeLabel = reseedModeLabel(currentModeForReseed());
365+
seedMockDb();
366+
reseedConfirmationPending = false;
367+
reseedStatusMessage = `Reseed complete for ${modeLabel}. Only ${modeLabel} was reseeded.`;
368+
dispatchModeChanged();
369+
render();
370+
} catch (error) {
371+
const message = errorMessage(error);
372+
let modeLabel = "selected DB mode";
373+
try {
374+
modeLabel = reseedModeLabel(currentModeForReseed());
375+
} catch {}
376+
reseedConfirmationPending = false;
377+
reseedStatusMessage = `Reseed failed for ${modeLabel}: ${message}`;
378+
render();
379+
}
380+
});
381+
261382
render();

docs_build/dev/reports/coverage_changed_js_guardrail.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Changed runtime JS files considered:
1111
(0%) toolbox/assets/assets-mock-repository.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
1212
(0%) toolbox/colors/palette-workspace-repository.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
1313
(0%) toolbox/project-journey/project-journey-mock-repository.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
14+
(80%) src/engine/api/mock-db-api-client.js - executed lines 19/19; executed functions 4/5
1415
(87%) src/engine/api/mock-db-viewer-ui.js - executed lines 517/517; executed functions 85/98
1516

1617
Guardrail warnings:
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# PR_26158_038 Login DB Reseed Control Report
2+
3+
## Summary
4+
5+
Added a two-step Reseed control to the login page Local Development Status section. The control uses the existing server API boundary (`/api/mock-db/seed`) and reseeds only the active DB mode: Local Mem or Local DB.
6+
7+
## Files Changed
8+
9+
| File | Change |
10+
| --- | --- |
11+
| `login.html` | Added Local Development Status reseed fields, start/confirm/cancel controls, and visible reseed status text. |
12+
| `assets/theme-v2/js/login-session.js` | Wired reseed UI state, confirmation, cancel, success, failure, and API-unavailable disabled handling. |
13+
| `src/engine/api/mock-db-api-client.js` | Updated seed client context text from Local Mem-specific wording to generic Mock DB seed wording. |
14+
| `src/dev-runtime/server/mock-api-router.mjs` | Updated seed action diagnostics to name Local Mem or Local DB based on the active mode. |
15+
| `tests/dev-runtime/DbSeedIntegrity.test.mjs` | Added independent Local Mem/Local DB reseed API validation. |
16+
| `tests/playwright/tools/LoginSessionMode.spec.mjs` | Added UI coverage for reseed confirmation, cancel, Local Mem success, Local DB success, and visible failure status. |
17+
18+
## Requirement Checklist
19+
20+
| Requirement | Status | Evidence |
21+
| --- | --- | --- |
22+
| Read `docs_build/dev/PROJECT_INSTRUCTIONS.md` first. | PASS | Read before implementation; applied PR completion, HTML, validation, and ZIP/report rules. |
23+
| Add a Reseed control to the login page Local Development Status section. | PASS | `login.html` adds `data-login-reseed-*` controls inside the Local Development Status card. |
24+
| Require confirmation before reseed executes. | PASS | `login-session.js` only calls `seedMockDb()` from the confirm handler; LoginSessionMode verifies start -> confirm/cancel state. |
25+
| Local Mem reseeds only Local Mem. | PASS | Node reseed test mutates Local DB, reseeds Local Mem, and verifies Local DB remains mutated. |
26+
| Local DB reseeds only Local DB. | PASS | Node reseed test reseeds Local DB separately and verifies Local Mem remains unchanged by that action. |
27+
| Do not reseed both DBs from one action. | PASS | `LocalDevMockDataSource.seed()` persists only the current adapter state; Node test validates both directions. |
28+
| Show active DB mode visibly. | PASS | `data-login-reseed-active-mode`; LoginSessionMode verifies Local Mem and Local DB text. |
29+
| Show reseed target visibly. | PASS | `data-login-reseed-target`; LoginSessionMode verifies Local Mem and Local DB text. |
30+
| Show success visibly. | PASS | LoginSessionMode verifies `Reseed complete for Local Mem...` and `Reseed complete for Local DB...`. |
31+
| Show failure visibly. | PASS | LoginSessionMode forces `/api/mock-db/seed` to return `ok:false` and verifies visible failure text. |
32+
| Show canceled status visibly. | PASS | LoginSessionMode verifies `Reseed canceled for Local Mem.` |
33+
| Preserve real runtime timestamps during reseed. | PASS | `DbSeedIntegrity.test.mjs` reuses runtime timestamp assertions after Local Mem and Local DB reseed. |
34+
| Preserve guest tool samples from PR_26158_037. | PASS | Existing seed integrity test still verifies guest samples for every active tool. |
35+
| Preserve unique per-user seeded data from PR_26158_037. | PASS | Existing seed integrity test still verifies unique user-owned project/tool state keys. |
36+
| Preserve SQLite-backed Local DB behind API boundary. | PASS | Local DB reseed and AdminDbViewer tests access Local DB through `/api/*`; no browser DB implementation imports were added. |
37+
| Do not add fallback behavior. | PASS | Static/API-unavailable behavior remains disabled; reseed controls disable through `renderError()`. |
38+
| Do not add UAT/Prod behavior. | PASS | Login options and seed behavior remain Local Mem / Local DB only. |
39+
| Do not add CSS. | PASS | No CSS files or inline/page-local styles were changed. |
40+
41+
## Validation Results
42+
43+
| Validation | Result |
44+
| --- | --- |
45+
| Changed-file syntax checks | PASS |
46+
| Targeted reseed API/DB validation | PASS, `node --test tests/dev-runtime/DbSeedIntegrity.test.mjs` 2/2 |
47+
| LoginSessionMode Playwright | PASS, 6/6 |
48+
| AdminDbViewer Playwright | PASS, 7/7 |
49+
| Changed-file/static validation | PASS |
50+
| Playwright V8 coverage | PASS/WARN advisory report generated |
51+
52+
## Skipped Validation
53+
54+
| Lane | Decision | Reason |
55+
| --- | --- | --- |
56+
| Full samples smoke | SKIP | No sample runtime or loader changed. |
57+
| Full Playwright suite | SKIP | Targeted login, DB Viewer, and reseed API lanes cover this PR scope. |
58+
| ProjectJourneyTool Playwright | SKIP | Project Journey runtime UI was not changed. |
59+
| ToolboxRoutePages Playwright | SKIP | Tool route rendering was not changed. |
60+
61+
## Notes
62+
63+
- The first failure-case Playwright attempt used an intentional HTTP 500 and produced an expected browser resource console error. The test was corrected to use a JSON API failure (`ok:false`) and then passed.
64+
- Existing Node SQLite experimental warnings and seed-only audit fallback diagnostics appeared during validation and did not indicate PR_26158_038 failures.
65+
- The generated V8 coverage report includes advisory entries from the existing stacked HEAD-diff coverage helper; current PR files are listed in `codex_changed_files.txt`.

docs_build/dev/reports/playwright_v8_coverage_report.txt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,28 @@ Note: coverage entries are aggregated across every page/tool where coverageRepor
1414
Exercised tool entry points detected:
1515
(61%) Toolbox Index - exercised 3 runtime JS files
1616
(0%) Tool Template V2 - not exercised by this Playwright run
17-
(81%) Theme V2 Shared JS - exercised 3 runtime JS files
17+
(84%) Theme V2 Shared JS - exercised 3 runtime JS files
1818

1919
Changed runtime JS files covered:
2020
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
2121
(0%) src/dev-runtime/server/mock-api-router.mjs - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
2222
(0%) toolbox/assets/assets-mock-repository.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
2323
(0%) toolbox/colors/palette-workspace-repository.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
2424
(0%) toolbox/project-journey/project-journey-mock-repository.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
25+
(80%) src/engine/api/mock-db-api-client.js - executed lines 19/19; executed functions 4/5
2526
(87%) src/engine/api/mock-db-viewer-ui.js - executed lines 517/517; executed functions 85/98
2627

2728
Files with executed line/function counts where available:
28-
(53%) src/engine/api/server-api-client.js - executed lines 159/159; executed functions 10/19
2929
(55%) toolbox/project-journey/project-journey.js - executed lines 1003/1003; executed functions 54/99
30-
(60%) src/engine/api/mock-db-api-client.js - executed lines 19/19; executed functions 3/5
30+
(58%) src/engine/api/server-api-client.js - executed lines 159/159; executed functions 11/19
3131
(64%) assets/theme-v2/js/tool-display-mode.js - executed lines 201/201; executed functions 9/14
3232
(67%) admin/db-viewer.js - executed lines 53/53; executed functions 4/6
33+
(80%) src/engine/api/mock-db-api-client.js - executed lines 19/19; executed functions 4/5
3334
(81%) toolbox/tool-registry-api-client.js - executed lines 148/148; executed functions 22/27
3435
(83%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 442/442; executed functions 33/40
3536
(87%) src/engine/api/mock-db-viewer-ui.js - executed lines 517/517; executed functions 85/98
3637
(88%) src/engine/api/session-api-client.js - executed lines 34/34; executed functions 7/8
37-
(89%) assets/theme-v2/js/login-session.js - executed lines 243/243; executed functions 17/19
38+
(96%) assets/theme-v2/js/login-session.js - executed lines 357/357; executed functions 26/27
3839
(100%) toolbox/project-journey/project-journey-api-client.js - executed lines 12/12; executed functions 2/2
3940

4041
Uncovered or low-coverage changed JS files:
@@ -50,9 +51,9 @@ Changed JS files considered:
5051
(0%) tests/dev-runtime/DbSeedIntegrity.test.mjs - changed JS file not collected as browser runtime coverage
5152
(0%) tests/playwright/tools/AdminDbViewer.spec.mjs - changed JS file not collected as browser runtime coverage
5253
(0%) tests/playwright/tools/LoginSessionMode.spec.mjs - changed JS file not collected as browser runtime coverage
53-
(0%) tests/playwright/tools/StaticOnlyLoginApiRequired.spec.mjs - changed JS file not collected as browser runtime coverage
5454
(0%) toolbox/assets/assets-mock-repository.js - changed JS file not collected as browser runtime coverage
5555
(0%) toolbox/colors/palette-workspace-repository.js - changed JS file not collected as browser runtime coverage
5656
(0%) toolbox/project-journey/project-journey-mock-repository.js - changed JS file not collected as browser runtime coverage
57+
(80%) src/engine/api/mock-db-api-client.js - changed JS file with browser V8 coverage
5758
(87%) src/engine/api/mock-db-viewer-ui.js - changed JS file with browser V8 coverage
58-
(89%) assets/theme-v2/js/login-session.js - changed JS file with browser V8 coverage
59+
(96%) assets/theme-v2/js/login-session.js - changed JS file with browser V8 coverage

0 commit comments

Comments
 (0)