fix(ui): resolve round one shell findings

This commit is contained in:
sechmachine
2026-08-15 02:17:01 +07:00
parent c5c143c3cd
commit 8388b4cc9b
18 changed files with 526 additions and 24 deletions
@@ -1,18 +1,18 @@
# Test Evidence: attendance shell integration
- **Test type:** Web
- **Requirement IDs:** `UI-001`, `UI-002`, `UI-003`, `UI-008`, `I1-ATT-03`, `I1-UI-04`
- **Requirement IDs:** `UI-001`, `UI-002`, `UI-003`, `UI-008`, `UI-013`, `I1-ATT-03`, `I1-UI-04`
- **Scenario IDs:** `AC-ATT-003`, `AC-ATT-004`, `AC-UI-001`, `AC-UI-005`
- **Test class/method:** `com.lab.labtimesheet.feature.reporting.controller.AttendanceTemplateIntegrationTest`
- **Implementation commit:** `3064485`
## Protected behavior
The Intern attendance-history and Admin global-calendar pages consume the role-aware shared shell while preserving their existing routes, CSRF-protected mutation forms, filter values, empty states, and local theme assets.
The Intern attendance-history and Admin global-calendar pages consume the role-aware shared shell while preserving their existing routes, CSRF-protected mutation forms, filter values, empty states, and local theme assets. Populated history presents `dd/MM/yyyy` dates and 24-hour times in the attached policy timezone and does not collapse simultaneous violations.
## Test method
A focused MockMvc slice supplies empty production-shaped models to the two production Attendance templates and renders them with role-specific Spring Security principals. The owning feature's `AttendanceControllerTest` remains the affected behavioral suite for authorization, punch actions, calendar mutation, and view selection.
A focused MockMvc slice supplies empty and populated production-shaped models to the two production Attendance templates and renders them with role-specific Spring Security principals. The populated fixture uses UTC instants, the attached `Asia/Ho_Chi_Minh` seeded policy, and late-plus-early and late-plus-missing combinations. The owning feature's `AttendanceControllerTest` remains the affected behavioral suite for authorization, punch actions, calendar mutation, and view selection.
## Hand-derived expected result
@@ -9,7 +9,7 @@
## Protected behavior
Every Iteration 1 Project and Task page uses the same authenticated desktop shell, local assets, role-aware Project navigation, table containment, form controls, empty states, status badges, and `dd/MM/yyyy` date presentation. Existing capability-gated actions, server routes, validation, authentication, and CSRF contracts remain unchanged.
Project and Task forms provide both an error summary and inline field errors for failed server validation.
Project and Task forms provide both an error summary and inline field errors for failed server validation. Every inline error has a stable ID and every invalid control references that ID through `aria-describedby`.
## Test method
@@ -0,0 +1,93 @@
# Test Evidence: round-one shared UI corrections
- **Test type:** Web
- **Requirement IDs:** `AUTH-002`, `UI-003`, `UI-004`, `UI-010`, `UI-013`, `UI-014`, `ERR-001`, `I1-UI-01`, `I1-UI-02`, `I1-UI-04`
- **Scenario IDs:** `AC-AUTH-001`, `AC-UI-002`, `AC-UI-003`, `AC-UI-005`
- **Test class/method:** `com.lab.labtimesheet.ui.UiContractWebTest`, `com.lab.labtimesheet.feature.reporting.controller.AttendanceTemplateIntegrationTest#populatedHistoryUsesPolicyLocalPresentationAndListsEveryViolation`, `com.lab.labtimesheet.feature.reporting.controller.SharedErrorTemplateWebTest`, `com.lab.labtimesheet.feature.reporting.controller.ProjectTaskFormAccessibilityWebTest`, `com.lab.labtimesheet.feature.reporting.controller.RoleDashboardWebIntegrationTest#mentorAndInternDashboardsRenderRealScopedProjectTaskAndAttendanceData`
- **Implementation commit:** `pending`
## Protected behavior
The authenticated shell exposes only reachable role-authorized links. Intern attendance uses `/attendance`; Mentor attendance, profile, and notification links remain hidden until their authorized destination flows exist. Every rendered role-navigation link resolves through an actual authenticated GET. Attendance history uses the row's attached policy timezone for 24-hour times, formats business dates as `dd/MM/yyyy`, and renders every simultaneous violation. Project and Task field errors have stable IDs associated to invalid controls. Generic 404 and 409 pages use the shared shell and safe caller-supplied copy without rendering exception details.
## Test method
MockMvc renders the production shell and templates with real Spring Security principals and production-shaped Attendance DTOs. Project and Task invalid POSTs pass through their real controllers and validation, with only feature services replaced at the slice boundary. The full Spring/PostgreSQL role journey creates accounts, internship, Project, and Task through public services, renders each role's real dashboard, extracts every visible shell link, and performs an authenticated GET against each extracted path.
## Hand-derived expected result
Mentor navigation contains only overview and owned Projects; Intern navigation contains overview, `/attendance`, and Projects; Admin navigation contains overview, account creation, and global calendar. No role receives `/attendance/me`, `/profile`, `/notifications`, or a selector-less Mentor attendance destination. `2026-08-14T02:05:00Z` under `Asia/Ho_Chi_Minh` renders as `14/08/2026 09:05`; `09:00:00Z` renders as `16:00`. Late plus early-departure and late plus missing-checkout labels are both retained. Every rendered validation message has a stable referenced ID. Error pages expose only status and generic copy.
## RED
**Command**
```text
export JAVA_HOME=/opt/homebrew/opt/openjdk@25
export PATH="/opt/homebrew/opt/node@24/bin:$JAVA_HOME/bin:$PATH"
export DOCKER_HOST=unix:///Users/sechmachine/.orbstack/run/docker.sock
./mvnw -Dtest=UiContractWebTest,AttendanceTemplateIntegrationTest,SharedErrorTemplateWebTest,ProjectTaskFormAccessibilityWebTest test
./mvnw -Dtest=RoleDashboardWebIntegrationTest test
```
**Observed result**
```text
Focused templates: Tests run: 13, Failures: 6, Errors: 2, Skipped: 0
Navigation exposed /attendance/me, selector-less Mentor attendance, /profile, and /notifications.
Attendance rendered ISO dates/raw UTC instants and only one violation.
error/generic did not exist.
Invalid controls had no aria-describedby and inline errors had no stable IDs.
PostgreSQL 18.4 role journey: Tests run: 1, Failures: 1, Errors: 0, Skipped: 0
Following the Admin shell's visible /profile link returned 404 instead of 200.
BUILD FAILURE
```
The failures occurred after real template rendering and controller validation; they identify the missing reviewed behavior rather than fixture or environment failure.
## GREEN
**Command**
```text
export JAVA_HOME=/opt/homebrew/opt/openjdk@25
export PATH="/opt/homebrew/opt/node@24/bin:$JAVA_HOME/bin:$PATH"
export DOCKER_HOST=unix:///Users/sechmachine/.orbstack/run/docker.sock
./mvnw -Dtest=UiContractWebTest,AttendanceTemplateIntegrationTest,SharedErrorTemplateWebTest,ProjectTaskFormAccessibilityWebTest test
./mvnw -Dtest=RoleDashboardWebIntegrationTest test
```
**Observed result**
```text
Focused templates: Tests run: 13, Failures: 0, Errors: 0, Skipped: 0
PostgreSQL 18.4 role journey: Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS
```
## Affected suite
**Command and result**
```text
export JAVA_HOME=/opt/homebrew/opt/openjdk@25
export PATH="/opt/homebrew/opt/node@24/bin:$JAVA_HOME/bin:$PATH"
export DOCKER_HOST=unix:///Users/sechmachine/.orbstack/run/docker.sock
npm run build
./mvnw -Dtest=UiContractWebTest,AttendanceTemplateIntegrationTest,AttendanceControllerTest,SharedErrorTemplateWebTest,ProjectTaskFormAccessibilityWebTest,ProjectControllerTest,TaskControllerTest,RoleDashboardWebIntegrationTest test
./mvnw -DskipTests compile
./mvnw -DskipTests -Ddoclint=all javadoc:javadoc
Node v24.19.0; npm 11.17.0
Tailwind CSS v4.3.3: Done in 68ms
PostgreSQL 18.4 via Testcontainers
Tests run: 40, Failures: 0, Errors: 0, Skipped: 0
Compile: success
Javadoc/doclint: success
BUILD SUCCESS
```
## External-test boundaries
The automated checks prove rendering, controller validation, role-scoped navigation targets, attached-policy formatting, and generic error copy. They do not prove first-paint timing, keyboard focus/tooltips, runtime `aria-expanded` synchronization, or viewport overflow; those remain mandatory live desktop browser gates after the corrected producer pins are merged.
+2 -2
View File
@@ -8,7 +8,7 @@
## Protected behavior
Domain-owned Thymeleaf pages can render inside one desktop shell with role-filtered navigation, accessible controls/states, pre-paint local theme loading, and committed local CSS/JavaScript/Lucide assets. The tests catch missing fragments, unauthorized navigation leakage, inaccessible shared form/status markup, remote icon references, or a theme bootstrap loaded after CSS.
Domain-owned Thymeleaf pages can render inside one desktop shell with role-filtered navigation, accessible controls/states, pre-paint local theme loading, and committed local CSS/JavaScript/Lucide assets. The tests catch missing fragments, unauthorized or dead navigation links, inaccessible shared form/status markup, remote icon references, or a theme bootstrap loaded after CSS.
## Test method
@@ -16,7 +16,7 @@ A test-only domain page consumes the production layout fragment through MockMvc
## Hand-derived expected result
A Mentor sees `Owned Projects`, theme, profile identity, and logout, but not Admin `Accounts` or Intern `My attendance`. The theme script occurs before the stylesheet. Form label/control IDs match, errors use `role="alert"`, status includes a textual accessible name, confirmation copy is described, and the reduced sprite contains the selected symbols without remote resource references.
A Mentor sees `Owned Projects`, account identity, theme, and logout, but not Admin `Accounts`, Intern `My attendance`, or selector-less Intern attendance. An Intern's attendance link targets the real `/attendance` route. Unimplemented profile and notification destinations are not exposed. The theme script occurs before the stylesheet. Form label/control IDs match, errors use `role="alert"`, status includes a textual accessible name, confirmation copy is described, and the reduced sprite contains the selected symbols without remote resource references.
## RED