Files
jobtrackingapp/docs/redesign/phase-5/p5-15/p5-15-01/diagnostics/README.md
T

4.4 KiB

P5-15-01 deferred preference diagnostics

These native Playwright probes run separately from the ordinary job-tracker-ui/e2e suite. They assert the intended behavior and fail on a genuine HTTP 500, incorrect persisted readback, or lost unsaved rule draft. There are no success response mocks, expected failures, retries within the probes, real account credentials, or provider calls.

From job-tracker-ui, after the normal Release API build and frontend preparation:

rtk proxy node node_modules/@playwright/test/cli.js test --config=../docs/redesign/phase-5/p5-15/p5-15-01/diagnostics/playwright.config.ts

The config imports the ordinary Playwright config: the same local ports, disposable API database, synthetic administrative bootstrap account, serial worker and retained failure trace apply. The working directory must remain job-tracker-ui. Use the ordinary static-export / prebuilt / server-reuse environment options only when the corresponding local servers or export have already been prepared. Do not run alongside the main suite on the shared ports.

The first probe edits a rule, switches to Notifications and returns without saving. Its attachment records the initial value, draft, displayed return value, API readback status/value and count of rule writes. The second probe uses two pages in one genuine session: language selection and notification Save run alongside four genuine report/notification reads, for three alternating language rounds. Each round records actual mutation/read statuses, persisted language/notification values, document language and alert DOM counts before the success assertions. The raw errorsVisible name is misleading: counts include the Next route announcer and do not establish visible errors. The portable summary labels them accordingly. Partial evidence is retained when a round fails. The final reload checks persisted UI state.

Native results and source characterization

Fresh final execution on 2026-10-09: one pass, one failure, separate from the ordinary browser suite. Portable browser evidence contains actual outcomes, commands, times and fingerprints. Rules started at 14, was edited to 5, then returned to 14 after the tab round trip; API readback remained 14, with zero rule writes. The desired draft-retention assertion fails. No application repair or expected-failure flag is included.

The three native overlap rounds passed: all language writes 204, notification writes 200, concurrent report/notification reads 200, persisted values correct, and final reload retained Bokmål plus disabled notification preference. This did not reproduce the recorded preference-save 500 and does not close it or establish concurrency/load safety. No exception/root cause for the historical 500 is inferred from this run.

  • SettingsView.tsx:43: TabPanel returns null for an inactive tab, unmounting RulesSettingsCard.
  • RulesSettingsCard.tsx:23: rule drafts live in component state; mounting reads /rules again. A tab round trip has no draft owner above the unmounted card. The native failed assertion confirms that draft-loss risk.
  • I18nProvider.tsx:33: setLanguage applies local state/storage immediately and catches the language PUT rejection without displaying it. A visually translated page is not evidence of a persisted successful preference.
  • AuthController.cs:549: the language endpoint loads the local Identity user, sets UiLanguage and calls UserManager.UpdateAsync. Identity-result failure becomes 400; an uncaught storage failure can become 500. This source alone does not establish the historical 500's cause.
  • NotificationSettingsController.cs:29: notification PUT updates another property of the same Identity user through UpdateAsync; unsuccessful Identity results explicitly become 500. Concurrent full-user writes, optimistic concurrency and SQLite contention remain hypotheses until response/server evidence identifies the failure.
  • SettingsView.tsx:70: language-dependent notification reads can overlap the writes. The diagnostic exercises that real caller behavior, rather than substituting successful responses.

No application fix is included. An all-success bounded run cannot establish that an intermittent concurrency defect is resolved; preserve the observed statuses and report that limit. A failed run remains failed, with a separately recorded defect for follow-up ownership.