Test plan: Core HR Transaction Bundle¶
Expands on spec.md's Scope and Acceptance Criteria into concrete scenarios, one group per transaction (five this pass — Bonus and Incentive Awards deferred, see Out of scope) plus cross-cutting scenarios surfaced during implementation-plan.md's cross-scope compensation write finding. One scenario remains genuinely blocked on spec.md's unresolved multi-jurisdiction-tax Open Question; the document/attachment and Job Data Changes storage questions that were open in an earlier pass are now resolved decisions, reflected below rather than marked blocked.
Scenarios¶
Personal Data Updates¶
- Address/contact changes apply immediately, no approval.
- Given a Worker submits a new address or contact-info value
- When the value passes format validation
-
Then it's reflected on their profile immediately, with no approval step and no notification sent to HR.
-
Dependent addition without documentation is blocked. (blocked — depends on
worker-document-managementshipping, a resolved dependency, not an open question) - Given a Worker adds a dependent but attaches no supporting documentation
- When the change is submitted
- Then the submission cannot finalize until documentation is attached.
-
Cannot be verified end-to-end until
worker-document-managementexists — this Feature builds none of that capability itself (decided). -
Dependent/tax-withholding changes route to HR Business Partner.
- Given a Worker submits a dependent or tax-withholding change
- When it's submitted
-
Then a Pending Approval transaction is created and routed to the HR Business Partner; on approval, the Worker record and any linked payroll/benefits fields update and the worker is notified.
-
HR Operations can audit every personal data change.
- Given any number of personal data changes have been submitted for a worker
- When HR Operations queries that worker's history
- Then every change and its approval status is retrievable for periodic compliance audit.
Job Data Changes¶
- A job-level change is rejected and redirected.
- Given a Job Data Change submission includes a change to job level
- When it's validated
-
Then it's rejected with a message directing the initiator to Promotion or Demotion instead of being processed here.
-
Manager approval writes a new effective-dated Job Assignment entry.
- Given a Direct Manager approves a Job Data Change
- When the approval completes
-
Then a new
Job Assignmententry is created carrying the updated job description and/or skill tags, withjob_start_dateset to the change's effective date; the priorJob Assignmententry is closed by setting itsjob_end_dateto that same date rather than being overwritten — the same insert-new/close-old pattern already used by department transfers and manager changes. Reflected in skills-inventory and internal mobility matching. -
Duplicate open Job Data Change for the same effective date is blocked.
- Given a worker already has an open Job Data Change transaction
- When a second one is submitted for the same effective date
- Then it cannot be submitted until the first resolves.
Promotion¶
- Promotion rejected if new level isn't higher.
- Given a Promotion submission where the new job level is not higher than the worker's current level
- When it's validated
-
Then it's rejected.
-
Promotion requires HR Business Partner and Department Head approval.
- Given a valid Promotion submission
- When it's routed for approval
-
Then both the HR Business Partner and Department Head must approve; either denying halts the transaction and notifies the initiator with the stated reason.
-
Full approval updates level, title, and compensation.
- Given a Promotion receives full approval
- When the effective date arrives
- Then the worker's job level and title update in
nova-corehcm-sn-app, and the compensation-band change persists onx_novaw_comp_worker_compensationvia the cross-scopeWorkerCompensationService.upsertCompensation()call — verify both writes, not just the Core HR side, and that the worker is notified.
Demotion¶
-
Demotion rejected if new level isn't lower.
- Given a Demotion submission where the new job level is not lower than the worker's current level
- When it's validated
- Then it's rejected.
-
Demotion requires HR Business Partner and Department Head approval.
- Given a valid Demotion submission
- When it's routed for approval
- Then both approvers must approve; either denying halts the transaction and notifies the initiator with the stated reason.
-
Full approval updates level, title, and compensation, logged separately.
- Given a Demotion receives full approval
- When the effective date arrives
- Then the worker's job level and title update, the compensation-band change
persists on
x_novaw_comp_worker_compensationvia the same cross-scope call as scenario 10, and the change is logged separately in job history vs. compensation-change history.
Salary Changes¶
-
Salary Change routes to HR Business Partner or Compensation reviewer.
- Given a Direct Manager proposes a Salary Change
- When it's submitted
- Then it routes for review before it's applied to the Worker's compensation record.
-
Salary Change exceeding the annual cap is blocked without override.
- Given a Salary Change exceeds the annual increase cap
- When it's submitted without an HR override
- Then it's blocked.
-
Approval updates the compensation record and notifies both parties.
- Given a Salary Change receives approval
- When the effective date arrives
- Then the new compensation amount persists on
x_novaw_comp_worker_compensationviaWorkerCompensationService.upsertCompensation(), and both the worker and the proposing manager are notified.
Cross-cutting¶
-
Compensation write succeeds under the execution script's actual runtime role.
- Given Salary Changes, Promotion, or Demotion's execution script calls
WorkerCompensationService.upsertCompensation() - When the call executes
- Then it succeeds — verify the script's runtime role actually carries
x_novaw_comp.hr_opsorx_novaw_comp.integration_writer, not the genericx_novaw_comp.agentrole, which this table's write ACL does not grant (per implementation-plan.md's ACCESS CONTROL risk). A test running under the wrong role would fail ACL, not silently no-op — confirm this fails loudly if misconfigured.
- Given Salary Changes, Promotion, or Demotion's execution script calls
-
Cross-scope call is allowed, not stuck pending.
- Given
nova-corehcm-sn-appdeclares an outboundCrossScopePrivilegerecord forWorkerCompensationService - When Salary Changes, Promotion, or Demotion runs for the first time in a given instance
- Then the call succeeds immediately — verify the privilege record's
statusis pre-declaredallowed, not left to auto-create asrequested(blocked) on first use, per implementation-plan.md's RCA risk.
- Given
-
HRBP approval gate is testable in isolation. (blocked — no isolable
hrbptest account exists today, pertests/API_integration_tests/INTEGRATION_TESTS.md§3.2)- Given Promotion, Demotion, or Salary Changes requires HR Business Partner approval
- When an integration test attempts to verify that gate specifically (not admin behavior standing in for it)
- Then it needs a dedicated
hrbp-only account — none exists on the test instance today, since every currenthrbpholder also holds fulladmin.
Out of scope for this pass¶
- Bonus and Incentive Awards (#674) — deferred out of the build, not just untested;
no existing home in
nova-compensation-sn-app's schema, skipped rather than pulling that app's team in now (per spec.md's Out of Scope and implementation-plan.md). No scenarios for it here. - Cost Center Change and Org Restructuring/Reorganizations/Hierarchies — deferred to a later Feature under this same Feature Set per spec.md's Out of Scope; no scenarios here.
- Building the document/attachment storage mechanism itself — scenario 2 tests against
it once it exists; building it is
worker-document-management's scope (resolved decision, not an open question). - Exact reason-code values for Job Data Changes — not yet finalized (spec.md Open Questions); scenario set doesn't assert specific codes.
- The chat/utterance-classification layer (whether varied phrasings correctly detect
each of the 5 new intents) — that's
nova-corehcm-agent's existing eval-testset convention (tests/testsets/), not this acceptance-criteria-level plan. nova-test-ci's actual Playwright implementation — held this pass (decided); these scenarios (especially 10, 13, 16, and the cross-cutting group) are what will drive that expansion in a future pass, not built now.