Skip to content

Commit 34e6bba

Browse files
committed
test(docs-tests): always rebuild dist in OneTimeSetUp
1 parent 1a1ec35 commit 34e6bba

1 file changed

Lines changed: 42 additions & 11 deletions

File tree

tests/MTConnect.NET-Docs-Tests/RouteCheckTests.cs

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ public class RouteCheckTests
7575
private readonly System.Text.StringBuilder _previewLog = new();
7676
private Task? _previewStdoutDrain;
7777
private Task? _previewStderrDrain;
78+
private static DateTime _fixtureStartTime;
79+
private static string _distDir = string.Empty;
7880

7981
// Walk-up bound is intentionally large (32) rather than fitting the
8082
// current `bin/Debug/netN.N/` suffix exactly. A deeper container path,
@@ -98,6 +100,8 @@ public class RouteCheckTests
98100
[OneTimeSetUp]
99101
public async Task OneTimeSetUp()
100102
{
103+
_fixtureStartTime = DateTime.UtcNow;
104+
101105
// Wrap the bootstrap so a partial failure (npm bootstrap throw,
102106
// chromium-install non-zero exit, preview-server bind timeout)
103107
// rethrows with whatever state was captured up to that point —
@@ -109,23 +113,27 @@ public async Task OneTimeSetUp()
109113
{
110114
_docsRoot = Path.Combine(RepoRoot, "docs");
111115
var distDir = Path.Combine(_docsRoot, ".vitepress", "dist");
116+
_distDir = distDir;
112117

113-
// The test owns its build prerequisite. If the dist/ tree
114-
// doesn't already exist, run `npm ci && npm run build` from
115-
// docs/ to produce it. `npm run build` invokes the `prebuild`
116-
// hook (regenerate api + reference), so the rendered site
117-
// matches what CI builds on every push. The presence check
118-
// looks for index.html specifically because a partial /
119-
// stale dist tree (e.g. just an assets/ subdirectory left
120-
// from a prior aborted run) is not a usable preview target.
121-
if (!File.Exists(Path.Combine(distDir, "index.html")))
118+
// Install node_modules if the cache is missing (first run on a
119+
// clean checkout or after `rm -rf node_modules`). Separated from
120+
// the build step so a repeated local run skips the network-bound
121+
// install while still always rebuilding the dist artefact.
122+
if (!Directory.Exists(Path.Combine(_docsRoot, "node_modules")))
122123
{
123124
stage = "npm ci";
124125
RunNpm("ci", _docsRoot);
125-
stage = "npm run build";
126-
RunNpm("run build", _docsRoot);
127126
}
128127

128+
// Always rebuild dist so the test asserts against a tree generated
129+
// from the current source, not a stale artefact from a prior run.
130+
// CI starts every run with a clean checkout (dist never exists),
131+
// so this only matters for repeated local invocations on a persistent
132+
// clone — the 5-min cost is amortised across the whole fixture's
133+
// OneTimeSetUp, not paid per test.
134+
stage = "npm run build";
135+
RunNpm("run build", _docsRoot);
136+
129137
// Install the chromium binary the Playwright .NET binding drives.
130138
// Idempotent: re-installs cleanly if the cache is already warm.
131139
stage = "playwright install chromium";
@@ -428,6 +436,29 @@ public async Task Landing_Hero_Image_Asset_Resolves()
428436
}
429437
}
430438

439+
/// <summary>
440+
/// Negative regression for the always-rebuild invariant per §10a:
441+
/// asserts that <c>dist/index.html</c> was written during this fixture
442+
/// invocation rather than reused from a prior run. A regression back
443+
/// to "rebuild only if missing" would leave the mtime unchanged on a
444+
/// persistent clone where dist already exists, causing the assertion
445+
/// to fail and making the stale-dist defect observable in CI.
446+
/// </summary>
447+
[Test]
448+
[Category("E2E")]
449+
public void OneTimeSetUp_Rebuilds_Dist_Even_When_Index_Exists()
450+
{
451+
// Pin the contract: regardless of pre-existing dist artefacts, the
452+
// fixture's OneTimeSetUp produces a fresh dist whose mtime is no
453+
// older than the test fixture invocation start time. A regression
454+
// back to "rebuild-if-missing" would let mtime fall behind.
455+
var distIndex = Path.Combine(_distDir, "index.html");
456+
var distMtime = File.GetLastWriteTimeUtc(distIndex);
457+
Assert.That(distMtime, Is.GreaterThanOrEqualTo(_fixtureStartTime),
458+
$"dist/index.html mtime {distMtime:O} is older than fixture start " +
459+
$"{_fixtureStartTime:O} — OneTimeSetUp skipped the rebuild");
460+
}
461+
431462
/// <summary>
432463
/// Walks every markdown-backed route the docs/ tree implies and
433464
/// asserts none rendered a 404. Failures are collected across all

0 commit comments

Comments
 (0)