Luigit
repositories / pi-ext

pi-ext

bugabingas pi extensions

owned by admin

extensions/strata/__tests__/fixture.test.ts

Raw
import { execFile } from "node:child_process";
import { existsSync } from "node:fs";
import { mkdtemp, readFile, rm } from "node:fs/promises";
import { tmpdir } from "node:os";
import path from "node:path";
import { promisify } from "node:util";
import { aroundEach, expect, it, vi } from "vitest";
import {
	cleanupNative,
	git,
	nativeOperation,
	nativeTest,
	openFixture,
	testSignal,
	withFakeGh,
} from "./fixture.js";

const exec = promisify(execFile);
aroundEach(nativeTest);

it("isolates fixture repositories from inherited hook Git variables", async () => {
	const sentinel = await openFixture();
	const gitDir = path.join(sentinel.root, ".git");
	const files = ["config", "HEAD", "index"];
	const before = await Promise.all(
		files.map((file) => readFile(path.join(gitDir, file))),
	);
	const refs = await git(sentinel.root, "show-ref");
	const bare = await mkdtemp(path.join(tmpdir(), "strata-bare-"));
	cleanupNative(() => rm(bare, { recursive: true, force: true }));
	try {
		for (const [key, value] of Object.entries({
			GIT_DIR: gitDir,
			GIT_COMMON_DIR: gitDir,
			GIT_WORK_TREE: sentinel.root,
			GIT_INDEX_FILE: path.join(gitDir, "index"),
			GIT_OBJECT_DIRECTORY: path.join(gitDir, "objects"),
			GIT_PREFIX: "nested/",
			GIT_CONFIG_COUNT: "1",
			GIT_CONFIG_KEY_0: "core.bare",
			GIT_CONFIG_VALUE_0: "true",
		}))
			vi.stubEnv(key, value);

		await git(bare, "init", "--quiet", "--bare");
		expect(existsSync(path.join(bare, "config"))).toBe(true);
		const isolated = await openFixture();
		expect(
			path.normalize(
				await git(isolated.root, "rev-parse", "--absolute-git-dir"),
			),
		).toBe(path.join(isolated.root, ".git"));
		await git(isolated.root, "add", ".");
		await git(isolated.root, "commit", "--quiet", "-m", "isolated change");
		expect(await git(isolated.root, "log", "-1", "--format=%s")).toBe(
			"isolated change",
		);
	} finally {
		vi.unstubAllEnvs();
	}
	for (const [index, file] of files.entries())
		expect(await readFile(path.join(gitDir, file))).toEqual(before[index]);
	expect(await git(sentinel.root, "show-ref")).toBe(refs);
});

it.for(["failure", "abort"])(
	"drains %s cleanup before the next fake command",
	async (mode, context) => {
		const before = {
			PATH: process.env.PATH,
			NODE_OPTIONS: process.env.NODE_OPTIONS,
			STRATA_FAKE_GH_PRELOAD: process.env.STRATA_FAKE_GH_PRELOAD,
		};
		const controller = new AbortController();
		const reason = new Error("controlled cleanup");
		let fixture!: Awaited<ReturnType<typeof openFixture>>;
		let preload = "";
		let finished = 0;
		let result!: Promise<unknown>;
		const scope = nativeOperation(() =>
			nativeTest(
				async () => {
					fixture = await openFixture();
					const started = Promise.withResolvers<void>();
					const release = Promise.withResolvers<void>();
					result = withFakeGh('process.stdout.write("first");', async () => {
						preload = process.env.STRATA_FAKE_GH_PRELOAD ?? "";
						try {
							// The preload must not intercept either Node or the required Node Git wrapper.
							expect(
								(
									await exec(
										process.execPath,
										["-e", 'process.stdout.write("helper")'],
										{ signal: testSignal() },
									)
								).stdout,
							).toBe("helper");
							expect(await git(fixture.root, "--version")).toMatch(
								/^git version /,
							);
							started.resolve();
							await release.promise;
							testSignal().throwIfAborted();
							throw reason;
						} finally {
							finished++;
							started.resolve();
						}
					}).catch((error: unknown) => error);
					await started.promise;
					if (mode === "abort") controller.abort(reason);
					release.resolve();
					if (mode === "failure") throw await result;
					// Like Vitest's timeout: runTest returns while its callback is still unwinding.
				},
				{ signal: AbortSignal.any([context.signal, controller.signal]) },
			),
		);
		if (mode === "failure") await expect(scope).rejects.toBe(reason);
		else await scope;
		expect(await result).toBe(reason);
		expect(finished).toBe(1);
		expect(existsSync(preload)).toBe(false);
		expect(existsSync(fixture.root)).toBe(false);
		for (const [key, value] of Object.entries(before))
			expect(process.env[key]).toBe(value);

		await withFakeGh('process.stdout.write("later");', async () => {
			const activePreload = process.env.STRATA_FAKE_GH_PRELOAD;
			await fixture.close();
			expect(
				(await exec("gh", ["pr", "view"], { signal: context.signal })).stdout,
			).toBe("later");
			expect(process.env.STRATA_FAKE_GH_PRELOAD).toBe(activePreload);
			expect(finished).toBe(1);
		});
		for (const [key, value] of Object.entries(before))
			expect(process.env[key]).toBe(value);
	},
);