fix(264): log local path scan errors (review finding) + map Scanner.Tests
Build ErsatzTV Image / CI image pin matches docker/ci (pull_request) Successful in 7s
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 6s
Build ErsatzTV Image / decisions.md append-only (pull_request) Successful in 8s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 8s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 47s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 5m28s
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 3m29s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 4m3s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped

Adversarial review (MERGEABLE, no blockers) raised two items worth
folding in rather than deferring:

Medium — ScanLocalLibraryHandler silently swallowed path scan errors,
while the three remote scanners it mirrors all log result.LeftToSeq().
That mattered less when a failed path only skipped the path-level
LastScan, but the previous commit makes a failed path suppress the
library-level scan time too — so the user would see exactly the #264
symptom ("Never scanned") with nothing in the log explaining why. That
is a diagnosis dead-end of the same class as the bug being fixed, so
log it here rather than file a follow-up. No test: the sibling
Synchronize*LibraryByIdHandlerTests don't assert on logging either, and
LogError is an extension method that NSubstitute can't cleanly verify.

Low — docs/testing.md bills itself as the authoritative map of what each
test project covers but omitted ErsatzTV.Scanner.Tests entirely (1471
pre-existing tests). This PR adds a file to that project, so add the row
and include it in the per-PR verification gate.
This commit is contained in:
2026-07-17 14:27:50 +02:00
parent 5c8dd64acf
commit 986ccfaf6c
2 changed files with 13 additions and 1 deletions
@@ -149,6 +149,17 @@ public class ScanLocalLibraryHandler : IRequestHandler<ScanLocalLibrary, Either<
else
{
anyFailed = true;
// a failed path now suppresses the library-level scan time below, so without this the
// user sees "Never scanned" with nothing explaining why. The remote scanners log the
// same way.
foreach (BaseError error in result.LeftToSeq())
{
_logger.LogError(
"Error scanning local library path {Path}: {Error}",
libraryPath.Path,
error);
}
}
}
+2 -1
View File
@@ -9,6 +9,7 @@ before adding tests, not just `docs/contributing.md` §8 (which now just points
|---|---|---|
| `ErsatzTV.Tests` | API controllers + MediatR handlers | In-memory SQLite fixture: a shared `SqliteConnection("Data Source=:memory:;Foreign Keys=False")` kept open + `EnsureCreatedAsync()` (**not** full migration replay) + `PRAGMA foreign_keys=OFF`, then seed; a tiny `IDbContextFactory` wraps `new TvContext(...)`. 828 tests currently. |
| `ErsatzTV.Core.Tests` | Domain logic, scheduling, IPTV/XMLTV generation | References `ErsatzTV.Application` directly — there is no separate `Application.Tests` project. 542 tests + 1 skipped under `TZ=UTC` (the Block playout golden additionally skips under a non-UTC `TZ`; see Golden-file nets). |
| `ErsatzTV.Scanner.Tests` | Library scanning: scan handlers, folder scanners, NFO readers | Handler tests substitute the folder scanners + `ILibraryRepository` and assert the resulting repository writes (e.g. `ScanLocalLibraryHandlerTests` pins which `LastScan` levels a scan records — ersatztv#264). Fakes/`Testably` back the file-system-facing scanners. 1471 tests. |
| `ErsatzTV.Architecture.Tests` | Layering rules via NetArchTest.eNhancedEdition | Core↛Infra/App/EF; FFmpeg↛all; App↛concrete providers. 5 tests. See `docs/contributing.md` §1. |
| `ErsatzTV.FFmpeg.Tests` | FFmpeg command construction | Build a pipeline, assert the exact rendered arg string (`PipelineBuilderBaseTests.cs`). |
| `web/` (vitest) | React SPA unit tests | 330 tests; run alongside typecheck + build (see below). |
@@ -86,7 +87,7 @@ npm run build # tsc -b && vite build
## Per-PR verification gate
Before opening a PR: build the solution, run both .NET test projects (plus
`ErsatzTV.Architecture.Tests` and `ErsatzTV.FFmpeg.Tests` if touched), and run the web test/lint/
`ErsatzTV.Scanner.Tests`, `ErsatzTV.Architecture.Tests` and `ErsatzTV.FFmpeg.Tests` if touched), and run the web test/lint/
typecheck/build steps above. All must be green. A golden-file diff or an architecture-test
failure is a hard stop — fix the code, don't regenerate/relax the test.