mirror of
https://github.com/software-mansion/argent.git
synced 2026-09-14 19:27:14 +08:00
d45306d7f3
Fixes #1077 **Cause** - three tool-server tests remove their temp dir as the *last statement of the test body*, so any assertion above it throwing abandons the directory in the shared system temp dir. **Fix** - a module-scope list pushed to at the mint site and drained in an `afterEach` (the shape #1057 used), replacing the trailing `rm`. `render-annotations.test.ts` had no hook at all; `workspace-reader.test.ts`'s describe-level `afterEach` becomes redundant once `createTempDir` registers every dir it hands out, so it goes. Test-only. No tool, CLI, config key, flow file or user-facing capability changes, so no docs update. **Verified** - break one assertion per file, run under a scoped `TMPDIR`, list what survives. | file | before | after | |---|---|---| | `metro/source-resolver-empty-root.test.ts` | `real-app-ouDGWh` | *(none)* | | `react-profiler/render-annotations.test.ts` | `argent-render-annotations-…zmt1onhl4wj`, `…sriq0gyjyo` | *(none)* | | `workspace-reader.test.ts` | `ws-reader-test-SIWls6` | *(none)* | Same failure count on both sides (1, 2, 1) - only the leftovers differ. <details> <summary>Repro, both sides</summary> Mutations applied to each file (`git show HEAD:<path>` for the "before" column, the branch for "after"): ``` sed -i '' 's/expect(out).toContain("IN_PROJECT");/expect(out).toContain("NOPE");/' \ test/metro/source-resolver-empty-root.test.ts sed -i '' 's/expect(after50).toContain("(t=192.3s)");/expect(after50).toContain("(t=999.9s)");/; s/expect(report).not.toMatch(\/> After:\/);/expect(report).toMatch(\/> After:\/);/' \ test/react-profiler/render-annotations.test.ts sed -i '' 's/expect(snap.lockfile).toBe(lockName);/expect(snap.lockfile).toBe("NOPE");/' \ test/workspace-reader.test.ts ``` Each run, from `packages/tool-server`: ``` d=/tmp/scope/<label>; rm -rf $d; mkdir -p $d TMPDIR=$d TMP=$d TEMP=$d npx vitest run <file> ls -A $d ``` Before (unfixed, mutated): ``` unfixed_sr: Tests 1 failed | 4 passed -> node-compile-cache real-app-ouDGWh unfixed_ra: Tests 2 failed -> node-compile-cache argent-render-annotations-1788965985023-zmt1onhl4wj argent-render-annotations-1788965985027-sriq0gyjyo unfixed_wr: Tests 1 failed | 34 passed -> node-compile-cache ws-reader-test-SIWls6 ``` After (this branch, same mutations): identical failure counts, `node-compile-cache` only. </details> <details> <summary>Checks</summary> From the worktree root: - `npx tsc --build` - clean - `npm run typecheck:tests -w @argent/tool-server` - clean - `npm test -w @argent/tool-server` - `368 passed (368)` files, `4832 passed | 1 skipped` - `npx prettier --write` on the three files - unchanged Class sweep: scanned every `*.test.ts` under `packages/tool-server/test` for an `rm`/`rmSync`/`unlink` as the final statement of an `it` body. Besides these three, only `react-profiler/dump.test.ts` and `screen-recording.test.ts` match, and both already point `os.tmpdir()` at a per-test scratch reaped in `afterEach`, so their unlinks strand nothing. The same shape in other packages is #1074 / #1075 and is left to those. </details> 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Tests** - Improved test cleanup by consistently removing temporary and debug directories after each test. - Consolidated cleanup handling across source resolution, profiler annotations, and workspace reader tests. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
114 lines
3.5 KiB
TypeScript
114 lines
3.5 KiB
TypeScript
import { describe, it, expect, afterEach } from "vitest";
|
|
import { promises as fs } from "node:fs";
|
|
import { join } from "node:path";
|
|
import { tmpdir } from "node:os";
|
|
import { renderProfilingReport } from "../../src/utils/react-profiler/pipeline/05-render";
|
|
import type { HotCommitSummary } from "../../src/utils/react-profiler/types/output";
|
|
import type { SessionContext } from "../../src/utils/react-profiler/types/pipeline";
|
|
|
|
// `summary.timestampMs` and `annotation.offsetMs` are both "ms since
|
|
// profile-start", so the renderer compares them directly, with no anchor.
|
|
|
|
const COMMIT_0_OFFSET = 17_587;
|
|
const COMMIT_50_OFFSET = 192_287;
|
|
|
|
const SUMMARIES: HotCommitSummary[] = [
|
|
{
|
|
commitIndex: 0,
|
|
timestampMs: COMMIT_0_OFFSET,
|
|
totalRenderMs: 100,
|
|
isMargin: false,
|
|
tier: "hot",
|
|
components: [],
|
|
totalComponentCount: 0,
|
|
},
|
|
{
|
|
commitIndex: 50,
|
|
timestampMs: COMMIT_50_OFFSET,
|
|
totalRenderMs: 100,
|
|
isMargin: false,
|
|
tier: "hot",
|
|
components: [],
|
|
totalComponentCount: 0,
|
|
},
|
|
];
|
|
|
|
const ANNOTATIONS = [
|
|
{ offsetMs: 173_110, label: "scroll feed" },
|
|
{ offsetMs: 192_071, label: "tap post" },
|
|
];
|
|
|
|
const SESSION_CONTEXT: SessionContext = {
|
|
reactCompilerEnabled: false,
|
|
strictModeEnabled: false,
|
|
buildMode: "dev",
|
|
rnArchitecture: "bridgeless",
|
|
projectRoot: "/tmp/fake-project",
|
|
platform: "ios",
|
|
};
|
|
|
|
const debugDirs: string[] = [];
|
|
|
|
afterEach(async () => {
|
|
for (const dir of debugDirs.splice(0)) await fs.rm(dir, { recursive: true, force: true });
|
|
});
|
|
|
|
async function makeDebugDir(): Promise<string> {
|
|
const dir = join(
|
|
tmpdir(),
|
|
`argent-render-annotations-${Date.now()}-${Math.random().toString(36).slice(2)}`
|
|
);
|
|
await fs.mkdir(dir, { recursive: true });
|
|
debugDirs.push(dir);
|
|
return dir;
|
|
}
|
|
|
|
describe("renderProfilingReport — annotation reference frame", () => {
|
|
it("matches the annotation immediately preceding a commit (regression for the user's scenario)", async () => {
|
|
const debugDir = await makeDebugDir();
|
|
const { report } = await renderProfilingReport({
|
|
hotCommitSummaries: SUMMARIES,
|
|
componentFindings: [],
|
|
sessionContext: SESSION_CONTEXT,
|
|
recordingMs: 200_000,
|
|
anyRuntimeCompilerDetected: false,
|
|
reactCommits: 51,
|
|
annotations: ANNOTATIONS,
|
|
debugDir,
|
|
});
|
|
|
|
// 216ms after "tap post".
|
|
const commit50Idx = report.indexOf("### Commit #50");
|
|
expect(commit50Idx).toBeGreaterThanOrEqual(0);
|
|
const after50 = report.slice(commit50Idx, commit50Idx + 200);
|
|
expect(after50).toMatch(/> After: "tap post" \(0\.2s prior\)/);
|
|
expect(after50).not.toContain('"scroll feed"');
|
|
|
|
// commit #0 (t=17.6s) precedes every annotation.
|
|
const commit0Idx = report.indexOf("### Commit #0");
|
|
expect(commit0Idx).toBeGreaterThanOrEqual(0);
|
|
const between = report.slice(commit0Idx, commit50Idx);
|
|
expect(between).not.toMatch(/> After:/);
|
|
|
|
expect(between).toContain("(t=17.6s)");
|
|
expect(after50).toContain("(t=192.3s)");
|
|
});
|
|
|
|
it("renders without annotations when none are provided", async () => {
|
|
const debugDir = await makeDebugDir();
|
|
const { report } = await renderProfilingReport({
|
|
hotCommitSummaries: SUMMARIES,
|
|
componentFindings: [],
|
|
sessionContext: SESSION_CONTEXT,
|
|
recordingMs: 200_000,
|
|
anyRuntimeCompilerDetected: false,
|
|
reactCommits: 51,
|
|
debugDir,
|
|
});
|
|
|
|
expect(report).toContain("### Commit #50");
|
|
expect(report).toContain("### Commit #0");
|
|
expect(report).not.toMatch(/> After:/);
|
|
});
|
|
});
|