Merge commit '8b48e281f7e860af435ae35b16c4edeb139286dc' into work/tasks
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
# Test Evidence: SMTP-gated account creation and activation
|
||||
|
||||
- **Test type:** Integration
|
||||
- **Requirement IDs:** `ACC-008`–`ACC-014`, `ACC-019`, `ACC-020`, `NOT-008`, `SEC-005`, `SEC-007`
|
||||
- **Scenario IDs:** `AC-ACC-001`, `AC-ACC-002`, `AC-ACC-003`, `AC-ACC-007`
|
||||
- **Test class/method:** `com.lab.labtimesheet.feature.account.service.AccountActivationIntegrationTest#smtpGatedCreationHashesSingleUseActivationAndRetainsFailedDeliveryHistory`
|
||||
- **Implementation commit:** `this milestone commit`
|
||||
|
||||
## Protected behavior
|
||||
|
||||
An active Admin can create pending Mentor/Intern accounts only while a tested SMTP revision is active. The raw activation secret exists only in the immediate email, PostgreSQL stores only its SHA-256 hash, activation is single-use, and a failed initial delivery keeps history while invalidating that token. Activating an Intern's lifecycle separately makes the account eligible only inside its inclusive internship dates. Reporting reads account counts through the Account service boundary.
|
||||
|
||||
## Test method
|
||||
|
||||
The PostgreSQL 18.4 integration test bootstraps the first Admin, proves creation is blocked before SMTP activation, activates a recorded SMTP boundary, and exercises production account creation/activation. It independently hashes the captured raw link token, inspects persisted state through platform-owned repositories, simulates delivery failure, activates an Intern lifecycle, checks date boundaries, and checks the service-level summary used by reporting.
|
||||
|
||||
## Hand-derived expected result
|
||||
|
||||
The first non-bootstrap creation attempt adds zero rows. A delivered Mentor is pending with no password until one successful activation; replay fails. A failed Intern delivery leaves one pending account and one invalidated token. After the successful Intern is activated at both account and internship levels, the final state has three active accounts (Admin, Mentor, Intern), one pending account, and one active internship.
|
||||
|
||||
## RED
|
||||
|
||||
**Command**
|
||||
|
||||
```text
|
||||
JAVA_HOME=/opt/homebrew/opt/openjdk@25 DOCKER_HOST=unix:///Users/sechmachine/.orbstack/run/docker.sock ./mvnw -Dtest=AccountActivationIntegrationTest test
|
||||
```
|
||||
|
||||
**Observed result**
|
||||
|
||||
```text
|
||||
BUILD FAILURE. Test compilation reported five missing account-activation API/model symbols, including CreateAccountCommand, TokenPurpose, and UserActionTokenRepository. No test ran.
|
||||
```
|
||||
|
||||
After the first GREEN implementation, the exact-expiry assertion was added and observed RED before exposing the persisted expiry:
|
||||
|
||||
```text
|
||||
BUILD FAILURE. AccountActivationIntegrationTest could not compile because UserActionToken#getExpiresAt() did not exist.
|
||||
```
|
||||
|
||||
## GREEN
|
||||
|
||||
**Command**
|
||||
|
||||
```text
|
||||
JAVA_HOME=/opt/homebrew/opt/openjdk@25 DOCKER_HOST=unix:///Users/sechmachine/.orbstack/run/docker.sock ./mvnw -Dtest=AccountActivationIntegrationTest test
|
||||
```
|
||||
|
||||
**Observed result**
|
||||
|
||||
```text
|
||||
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
|
||||
BUILD SUCCESS
|
||||
```
|
||||
|
||||
## Affected suite
|
||||
|
||||
**Command and result**
|
||||
|
||||
```text
|
||||
JAVA_HOME=/opt/homebrew/opt/openjdk@25 DOCKER_HOST=unix:///Users/sechmachine/.orbstack/run/docker.sock ./mvnw test
|
||||
Tests run: 9, Failures: 0, Errors: 0, Skipped: 0
|
||||
BUILD SUCCESS
|
||||
```
|
||||
|
||||
## External-test boundaries
|
||||
|
||||
The recording SMTP boundary proves the exact in-memory handoff but not Mailpit/network delivery or a browser following the link. MVC activation forms, resend, password reset, session invalidation, lock/deactivation, and production origin/readiness hardening remain separate Iteration 1 or later slices.
|
||||
@@ -0,0 +1,99 @@
|
||||
# Test Evidence: Attendance PostgreSQL persistence and calendar rules
|
||||
|
||||
- **Test type:** Integration
|
||||
- **Requirement IDs:** `ATT-002`, `ATT-005`, `ATT-007`, `ATT-008`, `ATT-010`, `CAL-001`, `CAL-006`, `CAL-007`, `CAL-009`, `AUTH-003`, `RPT-004`
|
||||
- **Scenario IDs:** `AC-ATT-003`, `AC-ATT-004`, `AC-CAL-003`, `AC-CAL-004`
|
||||
- **Test class/method:** `com.lab.labtimesheet.feature.attendance.service.AttendancePersistenceIntegrationTest`
|
||||
- **Implementation commit:** `pending (committed with this evidence)`
|
||||
|
||||
## Protected behavior
|
||||
|
||||
PostgreSQL stores server-time punches with the seeded applied-policy foreign key,
|
||||
enforces one row per Intern/date, and returns the attached policy in history.
|
||||
Admin-only manual calendar changes affect check-in, past events are immutable,
|
||||
stale edits are rejected, and Mentor/Admin/own-history scopes are enforced.
|
||||
|
||||
## Test method
|
||||
|
||||
A Spring Boot integration test migrates a real PostgreSQL 18.4 Testcontainer,
|
||||
creates and activates a valid Intern exclusively through public account and SMTP
|
||||
service/DTO boundaries, invokes the transactional attendance services, and
|
||||
asserts persisted rows and denied state transitions.
|
||||
|
||||
## Hand-derived expected result
|
||||
|
||||
The 1970 seed has ID 1 and a 30-minute checkout grace. An event created for
|
||||
2026-08-14 while server business date is 2026-08-13 blocks check-in on that
|
||||
date. After business date advances to 2026-08-15, that event cannot change.
|
||||
An update from version 0 advances the row, so a second version-0 edit is stale.
|
||||
|
||||
## RED
|
||||
|
||||
**Command**
|
||||
|
||||
```text
|
||||
export JAVA_HOME=/opt/homebrew/opt/openjdk@25
|
||||
export PATH="$JAVA_HOME/bin:$PATH"
|
||||
export DOCKER_HOST=unix:///Users/sechmachine/.orbstack/run/docker.sock
|
||||
./mvnw -Dtest=AttendancePersistenceIntegrationTest test
|
||||
```
|
||||
|
||||
**Observed result**
|
||||
|
||||
```text
|
||||
[ERROR] cannot find symbol: class AttendanceApplicationService
|
||||
[ERROR] cannot find symbol: class CalendarApplicationService
|
||||
[INFO] 8 errors
|
||||
[INFO] BUILD FAILURE
|
||||
Process exited 1 before Testcontainers startup because the required persistence/application services did not exist.
|
||||
```
|
||||
|
||||
The optimistic-edit assertion was separately observed RED:
|
||||
|
||||
```text
|
||||
./mvnw -Dtest=AttendancePersistenceIntegrationTest test
|
||||
[ERROR] method updateManual ... actual and formal argument lists differ in length
|
||||
[INFO] 4 errors
|
||||
[INFO] BUILD FAILURE
|
||||
Process exited 1 because update did not yet accept an expected version.
|
||||
```
|
||||
|
||||
## GREEN
|
||||
|
||||
**Command**
|
||||
|
||||
```text
|
||||
export JAVA_HOME=/opt/homebrew/opt/openjdk@25
|
||||
export PATH="$JAVA_HOME/bin:$PATH"
|
||||
export DOCKER_HOST=unix:///Users/sechmachine/.orbstack/run/docker.sock
|
||||
./mvnw -Dtest=AttendancePersistenceIntegrationTest,AttendanceControllerTest test
|
||||
```
|
||||
|
||||
**Observed result**
|
||||
|
||||
```text
|
||||
PostgreSQL 18.4 container started and Flyway applied V1.
|
||||
AttendancePersistenceIntegrationTest: Tests run: 6, Failures: 0, Errors: 0, Skipped: 0
|
||||
BUILD SUCCESS
|
||||
Process exited 0.
|
||||
```
|
||||
|
||||
## Affected suite
|
||||
|
||||
**Command and result**
|
||||
|
||||
```text
|
||||
export JAVA_HOME=/opt/homebrew/opt/openjdk@25
|
||||
export PATH="$JAVA_HOME/bin:$PATH"
|
||||
export DOCKER_HOST=unix:///Users/sechmachine/.orbstack/run/docker.sock
|
||||
./mvnw -Dtest='*Attendance*Test' test
|
||||
Tests run: 26, Failures: 0, Errors: 0, Skipped: 0
|
||||
BUILD SUCCESS
|
||||
Process exited 0.
|
||||
```
|
||||
|
||||
## External-test boundaries
|
||||
|
||||
This test does not prove cross-request check-in races, production authentication
|
||||
configuration, shared-shell integration, HolidayAPI, leave creation/decision,
|
||||
corrections, schedulers, or later policy scheduling.
|
||||
@@ -0,0 +1,81 @@
|
||||
# Test Evidence: Current business-date attendance state
|
||||
|
||||
- **Test type:** Unit
|
||||
- **Requirement IDs:** `ATT-005`, `I1-UI-03`
|
||||
- **Scenario IDs:** `I1-ATT-03`, `I1-ATT-04`
|
||||
- **Test class/method:** `com.lab.labtimesheet.feature.attendance.service.AttendanceApplicationServiceTest`
|
||||
- **Implementation commit:** `pending (committed with this evidence)`
|
||||
|
||||
## Protected behavior
|
||||
|
||||
The public attendance service reports an eligible Intern's current business-date
|
||||
state as not checked in, checked in, or checked out without exposing attendance
|
||||
repositories/entities to dashboard consumers. Ineligible Interns are rejected.
|
||||
|
||||
## Test method
|
||||
|
||||
A fixed Clock, seeded policy, and mocked Spring Data/account boundaries drive the
|
||||
real application service through all three persisted-record shapes. A separate
|
||||
case makes account eligibility false and asserts the attendance rejection.
|
||||
|
||||
## Hand-derived expected result
|
||||
|
||||
No record means `NOT_CHECKED_IN`; a record without checkout means `CHECKED_IN`;
|
||||
a record with checkout means `CHECKED_OUT`. An ineligible user produces
|
||||
`INACTIVE_INTERN` instead of a state.
|
||||
|
||||
## RED
|
||||
|
||||
**Command**
|
||||
|
||||
```text
|
||||
export JAVA_HOME=/opt/homebrew/opt/openjdk@25
|
||||
export PATH="$JAVA_HOME/bin:$PATH"
|
||||
./mvnw -Dtest=AttendancePersistenceIntegrationTest test
|
||||
```
|
||||
|
||||
**Observed result**
|
||||
|
||||
```text
|
||||
cannot find symbol: class AttendanceCurrentState
|
||||
Tests did not run because the requested public DTO/service behavior did not exist.
|
||||
BUILD FAILURE
|
||||
Process exited 1.
|
||||
```
|
||||
|
||||
## GREEN
|
||||
|
||||
**Command**
|
||||
|
||||
```text
|
||||
export JAVA_HOME=/opt/homebrew/opt/openjdk@25
|
||||
export PATH="$JAVA_HOME/bin:$PATH"
|
||||
./mvnw -Dtest=AttendanceApplicationServiceTest test
|
||||
```
|
||||
|
||||
**Observed result**
|
||||
|
||||
```text
|
||||
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
|
||||
BUILD SUCCESS
|
||||
Process exited 0.
|
||||
```
|
||||
|
||||
## Affected suite
|
||||
|
||||
**Command and result**
|
||||
|
||||
```text
|
||||
export JAVA_HOME=/opt/homebrew/opt/openjdk@25
|
||||
export PATH="$JAVA_HOME/bin:$PATH"
|
||||
export DOCKER_HOST=unix:///Users/sechmachine/.orbstack/run/docker.sock
|
||||
./mvnw -Dtest='*Attendance*Test' test
|
||||
Tests run: 26, Failures: 0, Errors: 0, Skipped: 0
|
||||
BUILD SUCCESS
|
||||
Process exited 0.
|
||||
```
|
||||
|
||||
## External-test boundaries
|
||||
|
||||
The unit test does not prove PostgreSQL persistence, account fixture creation,
|
||||
Spring transaction behavior, MVC rendering, or dashboard composition.
|
||||
@@ -0,0 +1,101 @@
|
||||
# Test Evidence: Attendance feature package and JPA boundaries
|
||||
|
||||
- **Test type:** Unit
|
||||
- **Requirement IDs:** `ARC-005`, `OPS-020`
|
||||
- **Scenario IDs:** `I1-ATT-01` through `I1-ATT-05` structural gate
|
||||
- **Test class/method:** `com.lab.labtimesheet.architecture.AttendanceLayerStructureTest`
|
||||
- **Implementation commit:** `pending (committed with this evidence)`
|
||||
|
||||
## Protected behavior
|
||||
|
||||
Attendance/calendar code lives under one `feature.attendance` boundary with
|
||||
controller, model, model.dto, model.entity, repository, service, and exception
|
||||
layers. The superseded feature-first and global-layer classes are absent, and
|
||||
application services do not depend on `JdbcTemplate`.
|
||||
Attendance does not map or expose the account feature's `app_users` or
|
||||
`intern_profiles` tables.
|
||||
|
||||
## Test method
|
||||
|
||||
Plain JUnit loads the required public classes by authoritative package name,
|
||||
proves superseded class names are absent, verifies the query repository is a
|
||||
Spring Data repository, reflects over application-service dependencies, and
|
||||
proves that attendance-owned account entities/repositories cannot be loaded.
|
||||
|
||||
## Hand-derived expected result
|
||||
|
||||
Seven representative classes load from `feature.attendance` internal layers;
|
||||
the old `attendance.AttendanceService` and global `controller.AttendanceController`
|
||||
do not load; query access implements Spring Data `Repository`; no checked
|
||||
application service has a `JdbcTemplate` field.
|
||||
The four forbidden attendance-owned account entity/repository class names do
|
||||
not load.
|
||||
|
||||
## RED
|
||||
|
||||
**Command**
|
||||
|
||||
```text
|
||||
export JAVA_HOME=/opt/homebrew/opt/openjdk@25
|
||||
export PATH="$JAVA_HOME/bin:$PATH"
|
||||
./mvnw -Dtest=AttendanceLayerStructureTest test
|
||||
```
|
||||
|
||||
**Observed result**
|
||||
|
||||
```text
|
||||
ClassNotFoundException: com.lab.labtimesheet.feature.attendance.controller.AttendanceController
|
||||
ClassNotFoundException: com.lab.labtimesheet.feature.attendance.repository.AttendanceQueryRepository
|
||||
Tests run: 2, Failures: 0, Errors: 2, Skipped: 0
|
||||
BUILD FAILURE
|
||||
Process exited 1 because the implementation still used the superseded package layout.
|
||||
```
|
||||
|
||||
The account-boundary assertion was separately observed RED after the final
|
||||
feature package move:
|
||||
|
||||
```text
|
||||
./mvnw -Dtest=AttendanceLayerStructureTest test
|
||||
AttendanceLayerStructureTest.attendanceDoesNotMapOrExposeAccountFeatureTables:
|
||||
Expecting code to raise a throwable.
|
||||
Tests run: 3, Failures: 1, Errors: 0, Skipped: 0
|
||||
BUILD FAILURE
|
||||
Process exited 1 because attendance still owned shadow AppUser/InternProfile entity and repository types.
|
||||
```
|
||||
|
||||
## GREEN
|
||||
|
||||
**Command**
|
||||
|
||||
```text
|
||||
export JAVA_HOME=/opt/homebrew/opt/openjdk@25
|
||||
export PATH="$JAVA_HOME/bin:$PATH"
|
||||
./mvnw -Dtest=AttendanceLayerStructureTest test
|
||||
```
|
||||
|
||||
**Observed result**
|
||||
|
||||
```text
|
||||
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
|
||||
BUILD SUCCESS
|
||||
Process exited 0.
|
||||
```
|
||||
|
||||
## Affected suite
|
||||
|
||||
**Command and result**
|
||||
|
||||
```text
|
||||
export JAVA_HOME=/opt/homebrew/opt/openjdk@25
|
||||
export PATH="$JAVA_HOME/bin:$PATH"
|
||||
export DOCKER_HOST=unix:///Users/sechmachine/.orbstack/run/docker.sock
|
||||
./mvnw -Dtest='*Attendance*Test' test
|
||||
Tests run: 26, Failures: 0, Errors: 0, Skipped: 0
|
||||
BUILD SUCCESS
|
||||
Process exited 0.
|
||||
```
|
||||
|
||||
## External-test boundaries
|
||||
|
||||
This test proves source/package and dependency shape, not Spring context startup,
|
||||
PostgreSQL queries, MVC behavior, or the final platform account-service wiring.
|
||||
@@ -0,0 +1,77 @@
|
||||
# Test Evidence: Attendance policy defaults and boundaries
|
||||
|
||||
- **Test type:** Unit
|
||||
- **Requirement IDs:** `ATT-001`, `ATT-002`, `ATT-003`, `ATT-004`
|
||||
- **Scenario IDs:** `AC-ATT-001`
|
||||
- **Test class/method:** `com.lab.labtimesheet.feature.attendance.model.AttendancePolicyTest`
|
||||
- **Implementation commit:** `pending (committed with this evidence)`
|
||||
|
||||
## Protected behavior
|
||||
|
||||
The seeded policy applies from 1970-01-01 with the required timezone, schedule,
|
||||
workdays, grace values, leave quota, and penalty. Grace outside 0..720 or a
|
||||
checkout cutoff at midnight is rejected.
|
||||
|
||||
## Test method
|
||||
|
||||
Plain JUnit constructs the immutable policy and timeline directly, resolves two
|
||||
dates, and exercises the validation boundary without Spring or persistence.
|
||||
|
||||
## Hand-derived expected result
|
||||
|
||||
08:30 plus 30 minutes makes the inclusive on-time boundary 09:00. 15:30 plus
|
||||
30 minutes makes the inclusive checkout boundary 16:00. A 23:30 end plus 30
|
||||
minutes reaches midnight and is invalid.
|
||||
|
||||
## RED
|
||||
|
||||
**Command**
|
||||
|
||||
```text
|
||||
export JAVA_HOME=/opt/homebrew/opt/openjdk@25
|
||||
export PATH="$JAVA_HOME/bin:$PATH"
|
||||
./mvnw -Dtest=AttendancePolicyTest test
|
||||
```
|
||||
|
||||
**Observed result**
|
||||
|
||||
```text
|
||||
[ERROR] AttendancePolicyTest.java:[51,20] cannot find symbol
|
||||
symbol: class AttendancePolicy
|
||||
[INFO] BUILD FAILURE
|
||||
Process exited 1. The test reached compilation and failed because the required policy domain did not exist.
|
||||
```
|
||||
|
||||
## GREEN
|
||||
|
||||
**Command**
|
||||
|
||||
```text
|
||||
export JAVA_HOME=/opt/homebrew/opt/openjdk@25
|
||||
export PATH="$JAVA_HOME/bin:$PATH"
|
||||
./mvnw -Dtest=AttendancePolicyTest test
|
||||
```
|
||||
|
||||
**Observed result**
|
||||
|
||||
```text
|
||||
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
|
||||
BUILD SUCCESS
|
||||
Process exited 0.
|
||||
```
|
||||
|
||||
## Affected suite
|
||||
|
||||
**Command and result**
|
||||
|
||||
```text
|
||||
./mvnw -Dtest='*Attendance*Test' test
|
||||
Tests run: 26, Failures: 0, Errors: 0, Skipped: 0
|
||||
BUILD SUCCESS
|
||||
Process exited 0.
|
||||
```
|
||||
|
||||
## External-test boundaries
|
||||
|
||||
This unit test does not prove the platform-owned Flyway seed, PostgreSQL policy
|
||||
loading, policy-management authorization, or web rendering.
|
||||
@@ -0,0 +1,83 @@
|
||||
# Test Evidence: Attendance punch boundaries
|
||||
|
||||
- **Test type:** Unit
|
||||
- **Requirement IDs:** `GOV-011`, `GOV-012`, `ATT-005`, `ATT-007`, `ATT-008`, `ATT-009`, `ATT-010`, `ATT-011`, `ATT-012`, `ATT-016`
|
||||
- **Scenario IDs:** `AC-ATT-002`, `AC-ATT-003`, `AC-ATT-004`, `AC-ATT-005`
|
||||
- **Test class/method:** `com.lab.labtimesheet.feature.attendance.service.AttendanceServiceTest`
|
||||
- **Implementation commit:** `pending (committed with this evidence)`
|
||||
|
||||
## Protected behavior
|
||||
|
||||
Clock-controlled server time determines the local work date and raw punches.
|
||||
Check-in rejects inactive, non-workday, day-off, leave, and duplicate attempts.
|
||||
Exact grace/cutoff instants succeed; later checkout never writes raw checkout;
|
||||
a missed checkout is not also an early departure.
|
||||
|
||||
## Test method
|
||||
|
||||
Plain JUnit uses a fixed `Clock`, the production domain service, and a minimal
|
||||
in-memory repository port. Assertions cover stored state as well as rejection
|
||||
codes, including non-overwrite behavior.
|
||||
|
||||
## Hand-derived expected result
|
||||
|
||||
Asia/Ho_Chi_Minh is UTC+07 for the tested date: 09:00 local is 02:00Z,
|
||||
15:30 local is 08:30Z, and 16:00 local is 09:00Z. Equality is accepted;
|
||||
adding one millisecond crosses each strict-later boundary.
|
||||
|
||||
## RED
|
||||
|
||||
**Command**
|
||||
|
||||
```text
|
||||
export JAVA_HOME=/opt/homebrew/opt/openjdk@25
|
||||
export PATH="$JAVA_HOME/bin:$PATH"
|
||||
./mvnw -Dtest=AttendanceServiceTest test
|
||||
```
|
||||
|
||||
**Observed result**
|
||||
|
||||
```text
|
||||
[ERROR] AttendanceServiceTest.java:[3,46] cannot find symbol
|
||||
symbol: class AttendanceRejection
|
||||
[ERROR] AttendanceServiceTest.java:[136,20] cannot find symbol
|
||||
symbol: class AttendanceService
|
||||
[INFO] 29 errors
|
||||
[INFO] BUILD FAILURE
|
||||
Process exited 1. The test reached compilation and failed because the required attendance domain did not exist.
|
||||
```
|
||||
|
||||
## GREEN
|
||||
|
||||
**Command**
|
||||
|
||||
```text
|
||||
export JAVA_HOME=/opt/homebrew/opt/openjdk@25
|
||||
export PATH="$JAVA_HOME/bin:$PATH"
|
||||
./mvnw -Dtest=AttendanceServiceTest test
|
||||
```
|
||||
|
||||
**Observed result**
|
||||
|
||||
```text
|
||||
Tests run: 5, Failures: 0, Errors: 0, Skipped: 0
|
||||
BUILD SUCCESS
|
||||
Process exited 0.
|
||||
```
|
||||
|
||||
## Affected suite
|
||||
|
||||
**Command and result**
|
||||
|
||||
```text
|
||||
./mvnw -Dtest='*Attendance*Test' test
|
||||
Tests run: 26, Failures: 0, Errors: 0, Skipped: 0
|
||||
BUILD SUCCESS
|
||||
Process exited 0.
|
||||
```
|
||||
|
||||
## External-test boundaries
|
||||
|
||||
This unit test does not prove transaction isolation, PostgreSQL uniqueness,
|
||||
platform account/intern-state queries, approved-leave persistence, Spring
|
||||
Security, controller routing, or Thymeleaf rendering.
|
||||
@@ -0,0 +1,85 @@
|
||||
# Test Evidence: Attendance and global-calendar web authorization
|
||||
|
||||
- **Test type:** Web
|
||||
- **Requirement IDs:** `AUTH-001`, `AUTH-002`, `AUTH-003`, `ATT-007`, `ATT-010`, `CAL-001`, `CAL-007`, `RPT-004`
|
||||
- **Scenario IDs:** `AC-ATT-003`, `AC-ATT-004`, `AC-CAL-004`
|
||||
- **Test class/method:** `com.lab.labtimesheet.feature.attendance.controller.AttendanceControllerTest`
|
||||
- **Implementation commit:** `pending (committed with this evidence)`
|
||||
|
||||
## Protected behavior
|
||||
|
||||
Authenticated Intern punch routes use the server-resolved user ID, own history
|
||||
renders attached policy details, Mentor inspection routes preserve the target
|
||||
scope, and calendar management rejects non-Admin access. Calendar updates carry
|
||||
the submitted optimistic version.
|
||||
|
||||
## Test method
|
||||
|
||||
`@WebMvcTest` runs Spring Security filters, CSRF protection, MVC binding, route
|
||||
selection, controller authorization, Thymeleaf rendering, and service-call
|
||||
arguments while mocking only application-service and current-user boundaries.
|
||||
|
||||
## Hand-derived expected result
|
||||
|
||||
An Intern authenticated as user 42 can punch only ID 42. A Mentor can inspect
|
||||
target 42 but receives HTTP 403 for Admin calendar management. Attached policy
|
||||
grace renders as `30 min`. An event form with version 3 calls update with 3.
|
||||
|
||||
## RED
|
||||
|
||||
**Command**
|
||||
|
||||
```text
|
||||
export JAVA_HOME=/opt/homebrew/opt/openjdk@25
|
||||
export PATH="$JAVA_HOME/bin:$PATH"
|
||||
./mvnw -Dtest=AttendanceControllerTest test
|
||||
```
|
||||
|
||||
**Observed result**
|
||||
|
||||
```text
|
||||
[ERROR] cannot find symbol: class AttendanceCurrentUserService
|
||||
[ERROR] cannot find symbol: class AttendanceController
|
||||
[ERROR] cannot find symbol: class CalendarController
|
||||
[INFO] 3 errors
|
||||
[INFO] BUILD FAILURE
|
||||
Process exited 1 because the required authenticated web endpoints did not exist.
|
||||
```
|
||||
|
||||
## GREEN
|
||||
|
||||
**Command**
|
||||
|
||||
```text
|
||||
export JAVA_HOME=/opt/homebrew/opt/openjdk@25
|
||||
export PATH="$JAVA_HOME/bin:$PATH"
|
||||
./mvnw -Dtest=AttendanceControllerTest test
|
||||
```
|
||||
|
||||
**Observed result**
|
||||
|
||||
```text
|
||||
Tests run: 7, Failures: 0, Errors: 0, Skipped: 0
|
||||
BUILD SUCCESS
|
||||
Process exited 0.
|
||||
```
|
||||
|
||||
## Affected suite
|
||||
|
||||
**Command and result**
|
||||
|
||||
```text
|
||||
export JAVA_HOME=/opt/homebrew/opt/openjdk@25
|
||||
export PATH="$JAVA_HOME/bin:$PATH"
|
||||
export DOCKER_HOST=unix:///Users/sechmachine/.orbstack/run/docker.sock
|
||||
./mvnw -Dtest='*Attendance*Test' test
|
||||
Tests run: 26, Failures: 0, Errors: 0, Skipped: 0
|
||||
BUILD SUCCESS
|
||||
Process exited 0.
|
||||
```
|
||||
|
||||
## External-test boundaries
|
||||
|
||||
This MVC slice does not prove the platform's production login/session setup,
|
||||
shared shell and navigation, browser layout, or accessibility beyond semantic
|
||||
labels, table headers, status roles, CSRF, and route authorization.
|
||||
Reference in New Issue
Block a user