Skip to content

test(report): pin the property and worker lookup fixes from #1078 and #1079 - #1109

Open
renemadsen wants to merge 1 commit into
stablefrom
test/report-service-regression-tests
Open

test(report): pin the property and worker lookup fixes from #1078 and #1079#1109
renemadsen wants to merge 1 commit into
stablefrom
test/report-service-regression-tests

Conversation

@renemadsen

Copy link
Copy Markdown
Member

Regression coverage for the two report-service fixes, #1078 and #1079.

BackendConfigurationReportService had no test coverage at all — zero references in either test project — and it has now produced two production bugs of the same shape: an unguarded .First(...) or null dereference inside the per-planning-case loop. Because both GenerateReport and GenerateReportV2 wrap their entire body in a single try/catch, each of those is a report-wide outage rather than one bad cell.

Tests (8)

Test Pins
GenerateReport_WhenPropertyIsUnresolvable_... #1078, V1, AreaRulesPlanningVersions fallback
GenerateReport_WhenLivePlanningPropertyIsUnresolvable_... #1078, V1, live AreaRulePlannings row
GenerateReportV2_WhenPropertyIsUnresolvable_... #1078, V2, fallback
GenerateReportV2_WhenLivePlanningPropertyIsUnresolvable_... #1078, V2, live row
GenerateReport_WhenPropertyResolves_ReturnsItemWithPropertyName positive control, V1
GenerateReportV2_WhenSiteHasNoWorker_ReturnsItemWithBlankEmployeeNo #1079 worker-less site + positive control, V2
GenerateReportV2_WhenCaseIsMissing_SkipsCaseAndReturnsOtherItems #1079 dbCase guard ordering — proves continue, not abort
GenerateReportV2_WhenSiteWorkerIsRemoved_UsesActiveSiteWorker #1079 WorkflowState != "removed" filter

Between them these cover all four Properties.First(...) call sites that #1078 patched — the live AreaRulePlannings branch and the version fallback, in each method.

Why these aren't vacuous

GenerateReport unconditionally appends a trailing OldReportEformModel and returns Success = true, so a Success-only assertion passes even when zero real rows were built. Every test therefore asserts item count, the seeded row's id, and the actual field value. ReportEformItemModel.PropertyName/.EmployeeNo default to null (no initializer), so Is.EqualTo("") genuinely pins the ?? "" assignment rather than passing by model default.

Validation

Each fix was reverse-applied and the suite re-run:

Mutation Result
baseline 8 passed
both fix commits reverted 5 failed — Sequence contains no elements / wrapped LINQ-parameter NRE; only the positive control passed, by design
only the two live-branch call sites reverted 2 failed — exactly the two new live-branch tests; the 6 fallback tests still passed
V2 fallback hardcoded to propertyName = "" 1 failed — the new V2 positive-control assertion

That third row is the point: it proves the new tests pin code the pre-existing ones never reach.

Reviewed by subagent; both Important findings (the unpinned live branch, and the missing V2 positive control) were fixed before this PR. Two doc-comment accuracy nits also fixed — the fixture previously implied the removed-site-worker test pinned OrderBy(x => x.Id), which by id arithmetic it does not; it pins the WorkflowState filter only.

Notes

  • Runtime ~6 min for the fixture (real MariaDB Testcontainer). Full integration suite remains 10+ min.
  • No production code is touched — BackendConfigurationReportService.cs is byte-identical to stable.
  • Deliberately not covered: the warn-once-per-site HashSet from fix(report): guard missing case, site worker and worker in GenerateReportV2 #1079. Asserting ILogger call counts through NSubstitute is brittle generics work, and a regression there is log noise, not incorrect output.

🤖 Generated with Claude Code

https://claude.ai/code/session_01A9DDHNWkLapbuXHjFSqFt9

…1079

BackendConfigurationReportService had no test coverage at all, and it has
now produced two production bugs of the same shape: an unguarded .First()
or null dereference inside the per-planning-case loop, which aborts the
entire report because both GenerateReport and GenerateReportV2 wrap their
whole body in a single try/catch.

Add an integration fixture covering both fixes:

- #1078: a planning case whose property cannot be resolved must still be
  reported with a blank PropertyName. Covered for both the live
  AreaRulePlannings row and the AreaRulesPlanningVersions fallback, in
  both methods - all four call sites the fix touched.
- #1079: in GenerateReportV2, a missing SDK case must be skipped rather
  than throwing, a site with no active SiteWorkers row must yield a blank
  EmployeeNo, and a soft-deleted site worker must not win over the active
  one.

Two positive controls (one per method) assert that a resolvable property
still yields its real name, so a future "blank everything" over-fix fails.

Every test asserts on the produced items, never on Success alone:
GenerateReport unconditionally appends a trailing model and so reports
success even when zero rows were built, which would make a Success-only
assertion pass vacuously whenever the seed is wrong.

Validated by reverse-applying each fix and confirming the matching tests
fail - including a targeted revert of only the live-branch call sites, to
prove the new tests pin code the fallback tests do not reach.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A9DDHNWkLapbuXHjFSqFt9
Copilot AI lite review requested due to automatic review settings August 13, 2026 13:59

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds new MariaDB-backed integration regression tests to pin two previously production-breaking failure modes in BackendConfigurationReportService report generation (property resolution and worker lookup), ensuring per-case failures degrade to blank cells / skipped rows rather than aborting the entire report.

Changes:

  • Introduces an integration test fixture covering GenerateReport and GenerateReportV2 behavior when property resolution fails (live AreaRulePlannings and version fallback branches).
  • Adds GenerateReportV2 regression coverage for missing SDK cases and for worker resolution (no site worker, removed site worker).

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +212 to +229
private async Task<Worker> SeedWorker(string employeeNo)
{
var worker = new Worker
{
FirstName = "Regression",
LastName = employeeNo,
Email = $"{Guid.NewGuid():N}@example.com",
EmployeeNo = employeeNo,
MicrotingUid = Random.Shared.Next(100000, 999999),
WorkflowState = Constants.WorkflowStates.Created,
CreatedAt = DateTime.UtcNow,
UpdatedAt = DateTime.UtcNow,
Version = 1
};
await MicrotingDbContext!.Workers.AddAsync(worker);
await MicrotingDbContext.SaveChangesAsync();
return worker;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants