test(account): cover missing picker business date
This commit is contained in:
@@ -3,8 +3,8 @@
|
|||||||
- **Test type:** Integration
|
- **Test type:** Integration
|
||||||
- **Requirement IDs:** ACC-014, ACC-019–ACC-021, AUTH-001, PRJ-017, TST-001–TST-010
|
- **Requirement IDs:** ACC-014, ACC-019–ACC-021, AUTH-001, PRJ-017, TST-001–TST-010
|
||||||
- **Scenario IDs:** AC-ACC-009, AC-ACC-010, AC-PRJ-010 (selection-eligibility support)
|
- **Scenario IDs:** AC-ACC-009, AC-ACC-010, AC-PRJ-010 (selection-eligibility support)
|
||||||
- **Test class/method:** com.lab.labtimesheet.feature.account.service.EligibleInternOptionIntegrationTest#listsOnlyActiveInternsWithActiveInclusiveInternshipsInPickerOrder
|
- **Test class/method:** com.lab.labtimesheet.feature.account.service.EligibleInternOptionIntegrationTest#listsOnlyActiveInternsWithActiveInclusiveInternshipsInPickerOrder; #rejectsMissingBusinessDate
|
||||||
- **Implementation commit:** Pending
|
- **Implementation commit:** e70159a81b6445825f6d5f912ecf3c4aa3c1aa85
|
||||||
|
|
||||||
## Protected behavior
|
## Protected behavior
|
||||||
|
|
||||||
@@ -12,6 +12,8 @@ Pending, locked, deactivated, non-Intern, not-started, completed, and date-expir
|
|||||||
Account-owned Intern picker. An option is selectable only when both account and internship are ACTIVE and the
|
Account-owned Intern picker. An option is selectable only when both account and internship are ACTIVE and the
|
||||||
explicit business date lies within the inclusive internship range. The returned numeric user ID is the internal
|
explicit business date lies within the inclusive internship range. The returned numeric user ID is the internal
|
||||||
submission identity, and options sort by display name then student code.
|
submission identity, and options sort by display name then student code.
|
||||||
|
The public query rejects a missing business date with the documented actionable message instead of issuing an
|
||||||
|
ambiguous null-bound database query.
|
||||||
|
|
||||||
## Test method
|
## Test method
|
||||||
|
|
||||||
@@ -19,12 +21,16 @@ The PostgreSQL 18.4 integration test persists valid account/profile combinations
|
|||||||
entities and repositories. It uses SQL only as a test fixture for future lock, deactivation, and completion states
|
entities and repositories. It uses SQL only as a test fixture for future lock, deactivation, and completion states
|
||||||
whose production transitions are outside this change. It calls the public Account service query and compares the
|
whose production transitions are outside this change. It calls the public Account service query and compares the
|
||||||
complete immutable DTO sequence, including both inclusive date boundaries and unique user IDs.
|
complete immutable DTO sequence, including both inclusive date boundaries and unique user IDs.
|
||||||
|
Its separate null-date regression calls the same public service method and asserts the exact
|
||||||
|
<code>IllegalArgumentException</code> message documented by that method.
|
||||||
|
|
||||||
## Hand-derived expected result
|
## Hand-derived expected result
|
||||||
|
|
||||||
For business date 2026-08-14, profiles starting on that date and ending on that date remain eligible. The only
|
For business date 2026-08-14, profiles starting on that date and ending on that date remain eligible. The only
|
||||||
expected options are Alpha / STU-100, Alpha / STU-200, and Zeta / STU-300, in that order. Every other seeded
|
expected options are Alpha / STU-100, Alpha / STU-200, and Zeta / STU-300, in that order. Every other seeded
|
||||||
row fails at least one account role/state, internship state, or inclusive date condition.
|
row fails at least one account role/state, internship state, or inclusive date condition.
|
||||||
|
For a missing business date, the service must immediately throw
|
||||||
|
<code>IllegalArgumentException("Business date is required")</code>.
|
||||||
|
|
||||||
## RED
|
## RED
|
||||||
|
|
||||||
@@ -65,6 +71,49 @@ Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
|
|||||||
BUILD SUCCESS
|
BUILD SUCCESS
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
## Review follow-up: missing business date
|
||||||
|
|
||||||
|
The public guard was temporarily removed solely to prove the new regression fails for the intended reason, then
|
||||||
|
restored exactly before the GREEN checks. The follow-up commit contains only the regression test and evidence.
|
||||||
|
|
||||||
|
### 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=EligibleInternOptionIntegrationTest#rejectsMissingBusinessDate' test
|
||||||
|
~~~
|
||||||
|
|
||||||
|
**Observed result**
|
||||||
|
|
||||||
|
~~~text
|
||||||
|
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0
|
||||||
|
java.lang.AssertionError: Expecting code to raise a throwable.
|
||||||
|
BUILD FAILURE
|
||||||
|
~~~
|
||||||
|
|
||||||
|
### 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=EligibleInternOptionIntegrationTest#rejectsMissingBusinessDate' test
|
||||||
|
~~~
|
||||||
|
|
||||||
|
**Observed result**
|
||||||
|
|
||||||
|
~~~text
|
||||||
|
PostgreSQL 18.4 Testcontainers started and Flyway applied V1 baseline.
|
||||||
|
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
|
||||||
|
BUILD SUCCESS
|
||||||
|
~~~
|
||||||
|
|
||||||
## Affected suite
|
## Affected suite
|
||||||
|
|
||||||
**Command and result**
|
**Command and result**
|
||||||
@@ -90,6 +139,21 @@ Tests run: 105, Failures: 0, Errors: 0, Skipped: 0
|
|||||||
BUILD SUCCESS
|
BUILD SUCCESS
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
### Review follow-up affected account-service checks
|
||||||
|
|
||||||
|
~~~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=EligibleInternOptionIntegrationTest,AccountActivationIntegrationTest,BootstrapIntegrationTest' test
|
||||||
|
|
||||||
|
EligibleInternOptionIntegrationTest: 2 tests, 0 failures, 0 errors, 0 skipped
|
||||||
|
BootstrapIntegrationTest: 4 tests, 0 failures, 0 errors, 0 skipped
|
||||||
|
AccountActivationIntegrationTest: 2 tests, 0 failures, 0 errors, 0 skipped
|
||||||
|
Selected account-service reports: 8 tests, 0 failures, 0 errors, 0 skipped.
|
||||||
|
BUILD SUCCESS
|
||||||
|
~~~
|
||||||
|
|
||||||
## External-test boundaries
|
## External-test boundaries
|
||||||
|
|
||||||
This query does not authorize Project membership itself; the consuming Project transaction must still recheck
|
This query does not authorize Project membership itself; the consuming Project transaction must still recheck
|
||||||
|
|||||||
+8
@@ -1,6 +1,7 @@
|
|||||||
package com.lab.labtimesheet.feature.account.service;
|
package com.lab.labtimesheet.feature.account.service;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
@@ -83,6 +84,13 @@ class EligibleInternOptionIntegrationTest {
|
|||||||
assertThat(options).extracting(EligibleInternOption::userId).doesNotHaveDuplicates();
|
assertThat(options).extracting(EligibleInternOption::userId).doesNotHaveDuplicates();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void rejectsMissingBusinessDate() {
|
||||||
|
assertThatThrownBy(() -> accounts.eligibleInternOptions(null))
|
||||||
|
.isInstanceOf(IllegalArgumentException.class)
|
||||||
|
.hasMessage("Business date is required");
|
||||||
|
}
|
||||||
|
|
||||||
private long activeIntern(String displayName, String studentCode, LocalDate startDate, LocalDate endDate) {
|
private long activeIntern(String displayName, String studentCode, LocalDate startDate, LocalDate endDate) {
|
||||||
long userId = activeUser(GlobalRole.INTERN, displayName);
|
long userId = activeUser(GlobalRole.INTERN, displayName);
|
||||||
activeProfile(userId, studentCode, startDate, endDate);
|
activeProfile(userId, studentCode, startDate, endDate);
|
||||||
|
|||||||
Reference in New Issue
Block a user