Skip to content

test: add end-to-end coverage for the case filing → hearing → judgment workflow - #1666

Open
Anijesh wants to merge 1 commit into
viru0909-dev:mainfrom
Anijesh:test/1630-e2e-judicial-workflow
Open

test: add end-to-end coverage for the case filing → hearing → judgment workflow#1666
Anijesh wants to merge 1 commit into
viru0909-dev:mainfrom
Anijesh:test/1630-e2e-judicial-workflow

Conversation

@Anijesh

@Anijesh Anijesh commented Jul 30, 2026

Copy link
Copy Markdown

Description

The core judicial path had no automated coverage, as the issue says. Adding it turned out to require fixing something bigger first: the Spring application context could not start at all — not in tests, not anywhere. mvn test could not even compile the test sources.

So this PR does two things: it makes integration testing possible, then it adds the suite.

Issue Resolved

Closes #1630

Part 1 — why nothing could boot

.gitignore has a blanket *.json rule. No JSON file anywhere in the backend is tracked. GroqResponseValidator loads schema/vakil_response_schema.json in @PostConstruct and throws IllegalStateException without it, which takes the entire context down:

Caused by: java.lang.IllegalStateException: Schema not found on classpath: schema/vakil_response_schema.json
Caused by: BeanCreationException: Error creating bean with name 'groqResponseValidator'

The original author almost certainly had this file locally; git add silently skipped it. I reconstructed it from its only consumer — VakilFriendGroqValidatorService#toSchemaNode and the repair prompt both pin the same seven fields and enum values — and added .gitignore negations so application JSON can be committed at all. Without those, the fix would have been swallowed exactly like the original.

pom.xml never declared com.networknt:json-schema-validator, which GroqResponseValidator imports, so main sources didn't compile either. (I reported this in #1664 and offered to fix it separately; including it here because this PR is unrunnable without it. It's a pure addition, so it won't conflict.)

Part 2 — tests that couldn't compile or never ran

File Problem Fix
CaseServiceTest References LegalCase / LegalCaseRepository, renamed to CaseEntity / CaseRepository before it was committed. Blocked all test compilation. Type names only — every CaseService signature it exercises still exists. Now 5/5 green.
SecurityIntegrationTest Imported AutoConfigureMockMvc from its pre-Spring-Boot-4 package. Also blocked all test compilation. See below — it needed three separate fixes.
JwtAuthFilterTest Set a secretKey field JwtService lost when it moved to keyed rotation; all 6 methods errored in setUp. See below.

JwtAuthFilterTest is worth calling out. The failing line set a field on a Mockito mock, so it was a no-op even before JwtService changed. Once I removed it the tests ran — and 3 of 6 failed, because a bare mock returns null from extractUsername instead of throwing, so the filter fell through to 200 and the "401 on a malformed or expired token" guarantee was never actually being tested. Swapped in a real JwtService over a real JwtSigningKeyService; all 6 now pass and genuinely assert the security behaviour.

SecurityIntegrationTest asserted against /cases/pending-assignment, but WebMvcConfig serves every @RestController behind /api/v1, so it was probing URLs that don't exist. It also relied on @WithMockUser, which cannot survive a STATELESS chain — the user() request post-processor can. And SecurityConfig deliberately refuses to start outside dev/test without a real JWT_SECRET, so it needed @ActiveProfiles("test").

Part 3 — the new coverage

JudicialWorkflowE2ETest walks the whole journey over real HTTP through MockMvc — bean validation, the JWT filter, @PreAuthorize and CaseAccessService all run exactly as for a browser client:

  1. Litigant registers and logs in (asserting registration cannot mint a privileged role)
  2. Files a case and sees it in their own list
  3. Proposes a lawyer; the lawyer accepts and the case appears in their portal
  4. A judge takes the case and schedules a hearing
  5. The judge records hearing notes, read back to confirm they persisted
  6. The judge delivers judgment; the litigant reads the decided case and has a notification

Plus authorisation boundaries on the same workflow: a litigant may not schedule a hearing or deliver a verdict on their own case, anonymous filing is refused, and blank required fields are rejected.

application-test.properties gives the integration tests the dedicated profile the issue asks for: in-memory H2, Flyway off, and every outbound integration (Groq, Bhashini, Ollama, LawGPT, the PII NER sidecar) pointed at a closed port so no test can reach the network.

On seeded users: AuthController hard-codes Role.LITIGANT and RegisterRequest has no role field — a deliberate anti-privilege-escalation measure. So litigants are created through the real endpoint, while lawyers and judges are seeded via the repository and then authenticated through the real login to get genuine tokens. That felt better than SQL seeds, which would fight the per-test transaction rollback.

Two behaviours pinned as they ship, not as the issue assumed

  • The terminal status is COMPLETED, not CLOSED. Both exist in CaseStatus; CaseManagementService#deliverVerdict sets COMPLETED. The test asserts what ships.
  • Anonymous API calls get a 302 to the OAuth2 login, not a 401. Access is still correctly denied, but a JSON client can't act on a redirect to an HTML form, so this is arguably wrong for /api/**. Changing it is a production security change and out of scope for a test PR — I've pinned the current behaviour so any change has to be deliberate.

Testing Completed

  • mvn test103 tests, 0 failures, 0 errors, BUILD SUCCESS. On main this command cannot compile.
  • Mutation-checked the E2E journey: breaking the terminal-status and judge-notes assertions makes it fail, so it is not passing vacuously.
Before (main):  test sources do not compile; context cannot start
After:          Tests run: 103, Failures: 0, Errors: 0  BUILD SUCCESS

On Playwright

The issue proposes Playwright plus REST Assured/MockMvc. I've done the backend half with MockMvc, which is the layer where the judicial workflow actually lives and which needs no running server or database. A Playwright layer needs the frontend to build first, and it currently doesn't — two files import { api } from a module that only default-exports (detailed in #1665). Happy to follow up with browser coverage once that's resolved; it felt better to ship working backend coverage than a browser suite that can't run.

Breaking Changes

None. Every change is to test sources, test resources, .gitignore, a missing dependency, and a missing resource file. No production code was modified.

The platform's core path — a litigant files a case, a lawyer takes it on, a
judge hears it and delivers judgment — had no automated coverage. Adding it
first meant making integration testing possible at all: the Spring context
could not start, in tests or anywhere else.

Why nothing could boot:
- .gitignore has a blanket *.json rule, so schema/vakil_response_schema.json
  was never committed. GroqResponseValidator loads it in @PostConstruct and
  throws without it, taking the whole context down. Restored the schema,
  reconstructed from VakilFriendGroqValidatorService#toSchemaNode and the
  repair prompt that defines the same seven fields, and added negations so
  application JSON resources can be committed at all
- pom.xml never declared com.networknt:json-schema-validator, which
  GroqResponseValidator imports, so main sources did not compile either

Test sources did not compile either:
- CaseServiceTest referenced LegalCase and LegalCaseRepository, renamed to
  CaseEntity and CaseRepository before it was committed. Only the type names
  were wrong; every CaseService signature it exercises still exists
- SecurityIntegrationTest imported AutoConfigureMockMvc from the package it
  occupied before Spring Boot 4

Tests that compiled but never ran:
- JwtAuthFilterTest set a "secretKey" field that JwtService lost when it moved
  to keyed rotation, so every method errored in setUp. The line was a no-op
  anyway — it targeted a Mockito mock. Replaced with a real JwtService, which
  is what these tests need: against a bare mock extractUsername returned null
  instead of throwing, the filter fell through to 200, and the 401-on-bad-token
  guarantee was never actually exercised
- SecurityIntegrationTest asserted against /cases/... while WebMvcConfig serves
  every @RestController behind /api/v1, so it was probing URLs that do not
  exist. It also relied on @WithMockUser, which cannot survive a STATELESS
  chain; the user() request post-processor does

New coverage:
- JudicialWorkflowE2ETest walks the whole journey over real HTTP through
  MockMvc: register, file, list, propose and accept a lawyer, assign a judge,
  schedule a hearing, record judge's notes, deliver judgment, then confirm the
  litigant sees the decided case and a notification. Bean validation, the JWT
  filter, @PreAuthorize and CaseAccessService all run as they would for a
  browser client
- Plus authorisation boundaries: a litigant may not schedule a hearing or
  deliver a verdict on their own case, anonymous filing is refused, and blank
  required fields are rejected
- application-test.properties gives the integration tests a documented profile
  with in-memory H2, Flyway off and every outbound integration pointed at a
  closed port

Two behaviours are pinned as they ship rather than as the issue assumed:
delivering a verdict sets COMPLETED, not CLOSED; and anonymous API calls get a
302 to the OAuth2 login instead of a 401.

Backend suite goes from not compiling to 103 tests green.

Closes viru0909-dev#1630
@Anijesh
Anijesh requested a review from viru0909-dev as a code owner July 30, 2026 13:03
@vercel

vercel Bot commented Jul 30, 2026

Copy link
Copy Markdown

Someone is attempting to deploy a commit to the CodeBlooded's projects Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions

Copy link
Copy Markdown
Contributor

Hi @Anijesh, thanks for contributing to Nyay Setu! 🎉

I have automatically:

  • 👤 Assigned this PR to you.
  • 🏷️ Applied the gssoc:approved label.

Our workflows will now analyze your changes to classify:

  • 📈 PR Difficulty: level:*
  • 🧩 PR Type: type:*
  • 🌟 PR Quality: quality:*

Tip

Ensure your PR description references the issue it resolves (e.g. Closes #123). This allows the bot to inherit any additional labels from that issue!

Happy coding! 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[TEST] Missing end-to-end tests for the complete case filing → hearing → judgment workflow

1 participant