mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-10-30 17:27:09 +00:00
test(cli): CLI tests run with a home folder of their own, never the user's (#4587)
* test(cli): CLI tests run with a home folder of their own, never the user's * style(cli): format the test home check * test(cli): the skills test lane also runs with a home folder of its own * style(cli): format the test home check * ci: the test reachability map follows the skills lane's new command
This commit is contained in:
@@ -560,7 +560,7 @@ jobs:
|
||||
SKILLS_TESTS+=(scripts/check-media-use-copy-parity.test.mjs scripts/creator-editing-capabilities.test.mjs)
|
||||
printf 'Running %d skills test file(s):\n' "${#SKILLS_TESTS[@]}"
|
||||
printf ' * %s\n' "${SKILLS_TESTS[@]}"
|
||||
node --test "${SKILLS_TESTS[@]}"
|
||||
node --import ./packages/cli/scripts/test-home.mjs --test "${SKILLS_TESTS[@]}"
|
||||
|
||||
test-skill-bootstrap-windows:
|
||||
name: "Test: skill bootstrap (Windows, Node 24)"
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@
|
||||
"knip": "knip",
|
||||
"test:scripts": "node --import tsx --test scripts/animejs-v4-guidance.test.mjs scripts/check-tracked-artifacts.test.mjs scripts/check-registry-set-delta.test.mjs scripts/check-no-main-deletions.test.mjs scripts/check-pr-captures.test.mjs scripts/check-comment-citations.test.mjs scripts/comments-workflow.test.mjs scripts/comment-ratchet.test.mjs scripts/check-docs-snippet-motion.test.mjs scripts/registry-target-paths.test.mjs scripts/check-workspace-contracts.test.mjs scripts/check-media-use-copy-parity.test.mjs scripts/check-svg-sanitize-parity.test.mjs scripts/check-media-use-svg-sanitize-generated.test.mjs scripts/check-package-cycles.test.mjs scripts/check-cli-process-ownership.test.mjs scripts/check-large-files.test.mjs scripts/prune-fallow-audit-caches.test.mjs scripts/package-subpaths.test.mjs scripts/validate-release-channel.test.mjs scripts/publish-workflow.test.mjs scripts/pr-edit-concurrency.test.mjs scripts/merge-queue-workflows.test.mjs scripts/install-workspace-dependencies.test.mjs scripts/draft-changelog.test.ts scripts/set-version.test.ts scripts/release-prepare.test.ts scripts/cli-options.test.ts scripts/changelog-weekly.test.ts scripts/claude-plugin-compression.test.ts scripts/catalog-payload-assets.test.ts scripts/host-registry-assets.test.ts scripts/catalog-preview-temp.test.ts scripts/catalog-hosted-files.test.ts scripts/player-cdn-pin.test.ts scripts/studio-runtime-smoke.test.mjs scripts/verify-packed-manifests.test.mjs scripts/lint-skills.test.mjs scripts/creator-editing-recipes.test.mjs packages/gcp-cloud-run/check-dockerfile-workspaces.test.mjs packages/core/scripts/writeGeneratedFile.test.ts scripts/catalog-publication.test.mjs scripts/ci/resolve-workflow-pr.test.mjs scripts/check-catalog-source-pr.test.mjs scripts/generate-registry-items.test.ts scripts/catalog-drift.test.ts scripts/catalog-fetch-mirror.test.ts scripts/catalog-script-inlining.test.ts scripts/catalog-detail.test.ts scripts/generate-catalog-pages.test.ts scripts/verify-catalog-payloads.test.ts scripts/registry-skill-files.test.ts scripts/creator-editing-capabilities.test.mjs scripts/generate-catalog-previews.test.ts scripts/registry-primitive-payloads.test.ts registry/components/pan-stations/pan-stations.test.mjs && vitest run scripts/catalog/ scripts/contrastRatchet.test.ts scripts/generate-catalog-payloads.test.ts",
|
||||
"typecheck:scripts": "tsc --noEmit -p scripts/tsconfig.json",
|
||||
"test:skills": "HYPERFRAMES_MEDIA_HOME_REQUIRED=1 node --test 'skills/**/*.test.mjs' 'packages/cli/src/media-use/**/*.test.mjs'",
|
||||
"test:skills": "HYPERFRAMES_MEDIA_HOME_REQUIRED=1 node --import ./packages/cli/scripts/test-home.mjs --test 'skills/**/*.test.mjs' 'packages/cli/src/media-use/**/*.test.mjs'",
|
||||
"generate:previews": "tsx scripts/generate-template-previews.ts",
|
||||
"generate:catalog-previews": "tsx scripts/generate-catalog-previews.ts",
|
||||
"package:codex-plugin": "node scripts/package-codex-plugin.mjs",
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// Loaded before any CLI test module: the cache, config and state paths the CLI builds from the home
|
||||
// folder, or from these variables, land in a temp dir removed on exit, never in the user's own.
|
||||
import { mkdtempSync, rmSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
|
||||
const home = mkdtempSync(join(tmpdir(), "hf-test-home-"));
|
||||
process.once("exit", () => rmSync(home, { recursive: true, force: true }));
|
||||
process.env.HOME = process.env.USERPROFILE = home;
|
||||
for (const name of [
|
||||
"XDG_CACHE_HOME",
|
||||
"XDG_CONFIG_HOME",
|
||||
"XDG_STATE_HOME",
|
||||
"XDG_DATA_HOME",
|
||||
"CODEX_HOME",
|
||||
"CLAUDE_CONFIG_DIR",
|
||||
"HEYGEN_CONFIG_DIR",
|
||||
"HYPERFRAMES_CATALOG_ARTIFACT_DIR",
|
||||
"HYPERFRAMES_MEDIA_HOME",
|
||||
"HF_HOME",
|
||||
"HUGGINGFACE_HUB_CACHE",
|
||||
]) {
|
||||
delete process.env[name];
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { realpathSync } from "node:fs";
|
||||
import { homedir, tmpdir, userInfo } from "node:os";
|
||||
import { sep } from "node:path";
|
||||
import { test } from "node:test";
|
||||
|
||||
test("the skills test run has a home folder of its own, not the user's", () => {
|
||||
assert.ok(realpathSync(homedir()).startsWith(realpathSync(tmpdir()) + sep));
|
||||
assert.notEqual(homedir(), userInfo().homedir);
|
||||
});
|
||||
@@ -1,13 +1,14 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { existsSync, readFileSync } from "node:fs";
|
||||
import { homedir } from "node:os";
|
||||
import { userInfo } from "node:os";
|
||||
import { join } from "node:path";
|
||||
|
||||
import { configFromTokenizerJson, encode, normalize, preTokenize, wordPiece } from "./wordpiece.js";
|
||||
|
||||
const REFERENCE_PATH = join(import.meta.dirname, "__fixtures__", "wordpiece-reference.json");
|
||||
// Read-only from the user's real home: tests run with a temp one, and the model is downloaded there.
|
||||
const TOKENIZER_PATH = join(
|
||||
homedir(),
|
||||
userInfo().homedir,
|
||||
".hyperframes",
|
||||
"models",
|
||||
"bge-small-en-v1.5.tokenizer.json",
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import { existsSync, realpathSync, rmSync } from "node:fs";
|
||||
import { homedir, tmpdir, userInfo } from "node:os";
|
||||
import { join, sep } from "node:path";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { fetchRegistryManifest } from "./registry/remote.js";
|
||||
|
||||
afterEach(() => {
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
describe("the CLI test run", () => {
|
||||
it("has a home folder of its own, not the user's", () => {
|
||||
expect(realpathSync(homedir()).startsWith(realpathSync(tmpdir()) + sep)).toBe(true);
|
||||
expect(homedir()).not.toBe(userInfo().homedir);
|
||||
});
|
||||
|
||||
it("caches a registry read in that home", async () => {
|
||||
const registry = `https://test.invalid/${crypto.randomUUID()}`;
|
||||
const items: unknown[] = [];
|
||||
const $schema = "https://hyperframes.heygen.com/schema/registry.json";
|
||||
const manifest = { $schema, name: "t", homepage: "https://example.com", items };
|
||||
vi.stubGlobal(
|
||||
"fetch",
|
||||
vi.fn(async (input: string | URL) =>
|
||||
String(input) === `${registry}/registry.json`
|
||||
? new Response(JSON.stringify(manifest))
|
||||
: new Response("not found", { status: 404 }),
|
||||
),
|
||||
);
|
||||
|
||||
await fetchRegistryManifest(registry);
|
||||
|
||||
const slug = registry.replace(/[^a-zA-Z0-9]/g, "_");
|
||||
const cacheFile = (home: string) =>
|
||||
join(home, ".hyperframes", "cache", `${slug}__registry.json`);
|
||||
const leaked = existsSync(cacheFile(userInfo().homedir));
|
||||
rmSync(cacheFile(userInfo().homedir), { force: true });
|
||||
expect(existsSync(cacheFile(homedir()))).toBe(true);
|
||||
expect(leaked).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -2,6 +2,8 @@ import { copyFileSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join, resolve } from "node:path";
|
||||
import { defineConfig } from "vitest/config";
|
||||
// Before workers fork, as below: the test run gets a home folder of its own.
|
||||
import "./scripts/test-home.mjs";
|
||||
|
||||
// Windows: sharp's first text render builds Fontconfig's cache for every OS font (about 9 s on a
|
||||
// fresh runner). Set here, before workers fork, because an in-process env write never reaches it.
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"runners": [
|
||||
{
|
||||
"cwd": ".",
|
||||
"command": "set -euo pipefail\nmapfile -t SKILLS_TESTS < <(find skills packages/cli/src/media-use -type f -name \"*.test.mjs\" | sort)\nif [ \"${#SKILLS_TESTS[@]}\" -eq 0 ]; then\necho \"::error::No skills/**/*.test.mjs files found. Did the layout change?\"\nexit 1\nfi\nSKILLS_TESTS+=(scripts/check-media-use-copy-parity.test.mjs scripts/creator-editing-capabilities.test.mjs)\nprintf 'Running %d skills test file(s):\\n' \"${#SKILLS_TESTS[@]}\"\nprintf ' * %s\\n' \"${SKILLS_TESTS[@]}\"\nnode --test \"${SKILLS_TESTS[@]}\"",
|
||||
"command": "set -euo pipefail\nmapfile -t SKILLS_TESTS < <(find skills packages/cli/src/media-use -type f -name \"*.test.mjs\" | sort)\nif [ \"${#SKILLS_TESTS[@]}\" -eq 0 ]; then\necho \"::error::No skills/**/*.test.mjs files found. Did the layout change?\"\nexit 1\nfi\nSKILLS_TESTS+=(scripts/check-media-use-copy-parity.test.mjs scripts/creator-editing-capabilities.test.mjs)\nprintf 'Running %d skills test file(s):\\n' \"${#SKILLS_TESTS[@]}\"\nprintf ' * %s\\n' \"${SKILLS_TESTS[@]}\"\nnode --import ./packages/cli/scripts/test-home.mjs --test \"${SKILLS_TESTS[@]}\"",
|
||||
"tests": [
|
||||
"skills/**/*.test.mjs",
|
||||
"packages/cli/src/media-use/**/*.test.mjs",
|
||||
|
||||
Reference in New Issue
Block a user