This is a testing challenge, not an implementation challenge. The system is already built — your task is to verify that it behaves correctly.
We expect this to take 2–4 hours. A focused submission that explains its decisions clearly is what we are looking for.
Three things:
-
Automated test suite — Write tests using the existing test infrastructure. JUnit Jupiter, MockK, and AssertJ are already available; you do not need to add testing libraries. Tests must run via
./gradlew testfrom thebackenddirectory. You may also write end-to-end tests through the browser UI if you choose. -
Written bug report (
BUGS.mdor similar) covering:- What issues you found and where
- Why you chose to look in those areas (your exploration and prioritization reasoning)
- What you would test next given more time, and why those areas were lower priority
-
Submission — git bundle (see Submission section below)
The "what would you test next" question is part of the deliverable — it is not optional.
- Java 17 — Required to build and run the backend. Verify with
java -version. - Node.js 18 LTS or later — Required for the frontend. Verify with
node --version. Node 16 is not supported.
cd backend
./gradlew clean build
./gradlew runcd frontend
npm install
npm run devThe frontend dev server proxies /api/* requests to the backend on port 8080. You can reach the workflow endpoint via the browser at http://localhost:3000 or call the backend API directly at http://localhost:8080/workflow.
Light builds invoice approval workflow software. Every time one of a customer's vendors submits an invoice, the system determines who must approve it before payment is authorized. This is a financial control mechanism: approval routing ensures the right person reviews the right invoice before money moves.
The approval decision depends on three inputs: the invoice amount, the department the invoice is submitted to, and whether explicit manager sign-off is required. The system applies tier-based routing with department overrides and an escalation flag. Getting the routing right matters — the wrong approver receiving an invoice means either a payment is delayed (over-escalation) or authorized by someone without sufficient authority (under-escalation). Both outcomes carry real financial and compliance risk.
The following describes the intended behavior of the invoice approval workflow. Your task is to verify that the implementation matches this specification.
The base approver is determined by the invoice amount:
| Amount Range | Approver | Role |
|---|---|---|
| Less than $1,000.00 | System Auto-Approval | AUTO_APPROVED |
| $1,000.00 to $9,999.99 | James Okafor | MANAGER |
| $10,000.00 to $49,999.99 | Sarah Chen | DIRECTOR |
| $50,000.00 and above | Michael Torres | CFO |
Boundary values are exact. An amount of $1,000.00 should route to MANAGER, not AUTO_APPROVED.
After the base tier is determined, department-specific overrides may apply:
| Department | Condition | Override Result |
|---|---|---|
| Engineering | Amount less than $5,000.00 | Elevated to DIRECTOR |
| Finance | Amount greater than $25,000.00 | Elevated to CFO |
| All others | — | No override; base tier applies |
When requiresManagerApproval is true, the final tier should be escalated by one level:
AUTO_APPROVED → MANAGER → DIRECTOR → CFO
CFO does not escalate further. If the final tier before escalation is already CFO, it remains CFO.
This is the intended order in which rules should be applied:
- Determine base tier from amount
- Apply department override (if applicable)
- Apply escalation if
requiresManagerApprovalistrue
When the intended final tier is CFO, the response should contain two approvers: Sarah Chen (DIRECTOR) followed by Michael Torres (CFO). All other tiers should return a single approver.
The workflow endpoint is available at two paths depending on how you are testing:
POST http://localhost:8080/workflow (direct backend)
POST http://localhost:3000/api/workflow (via frontend proxy)
Request body:
{
"amount": "500.00",
"department": "Sales",
"requiresManagerApproval": false
}| Field | Type | Required | Notes |
|---|---|---|---|
amount |
decimal string | yes | Must be greater than 0 |
department |
string | yes | Must be non-blank |
requiresManagerApproval |
boolean | no | Defaults to false if omitted |
Success response (HTTP 200):
{
"approvers": [
{ "name": "<string>", "role": "<string>" }
],
"auditTrail": {
"inputs": {
"amount": "<decimal as string>",
"department": "<string>",
"requiresManagerApproval": "<boolean>"
},
"rulesApplied": ["<rule name>", "..."],
"approvers": ["..."]
}
}Validation error response (HTTP 422):
{ "error": "<message>", "field": "<field name>" }Example 1: amount=500.00, department=Sales, requiresManagerApproval=false
- Base tier: AUTO_APPROVED (amount < $1,000)
- No department override (Sales has no override rule)
- No escalation (flag is false)
- Expected result: one approver — System Auto-Approval (AUTO_APPROVED)
Example 2: amount=1000.00, department=Sales
- Base tier: MANAGER (amount is exactly $1,000.00, which is ≥ $1,000 per the spec)
- No department override
- No escalation
- Expected result: one approver — James Okafor (MANAGER)
Example 3: amount=30000.00, department=Finance, requiresManagerApproval=true
- Base tier: DIRECTOR ($10,000–$49,999 range)
- Finance override applies (amount > $25,000): elevated to CFO
- Escalation applies (flag is true): CFO does not escalate further — remains CFO
- CFO rule: two-approver response
- Expected result: two approvers — Sarah Chen (DIRECTOR) + Michael Torres (CFO)
We evaluate test strategy and coverage decisions — not line coverage or bug count. We want to understand which behaviors you chose to verify and why.
- Your written bug report is evaluated as a primary deliverable, not an afterthought
- A well-chosen set of tests with a clear explanation of coverage decisions is valued over an exhaustive suite with no strategic intent
- We grade your test strategy: which behaviors you chose to verify, how you prioritized, and your coverage reasoning
We explicitly do not score:
- Number of bugs found
- Line coverage percentage
- Test count
This codebase may contain defects. Part of the challenge is deciding where to look and why.
- Commit all your changes.
- Run
git bundle create challenge-<your-name>.bundle --all - Send us the generated bundle file.