@riebeckite/test 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,100 @@
1
+ import { type RequiredInstallPath } from "./assertions.js";
2
+ import { type Logger } from "./logger.js";
3
+ import { type PackageSpec, type PackedPackages } from "./pack.js";
4
+ import { type NodeNextProjectSpec } from "./stage.js";
5
+ /** Fixture directories copied into the temporary workspace. */
6
+ export interface ExternalSiteFixture {
7
+ /** Site fixture, copied to `<temp>/site`. */
8
+ site: string;
9
+ /** Vault fixture, copied to `<temp>/vault` (next to the site). */
10
+ vault: string;
11
+ }
12
+ /** One CLI invocation performed against the installed site. */
13
+ export interface CliCommandSpec {
14
+ /** Positional arguments, e.g. `["inspect", "config"]`. */
15
+ args: readonly string[];
16
+ /** Optional assertion over the combined CLI output. */
17
+ assertOutput?: (output: string) => void;
18
+ }
19
+ /** A repo-specific programmatic check run after the generic install checks. */
20
+ export type SiteCheck = (workspace: ExternalSiteWorkspace, logger: Logger) => void;
21
+ /** The temporary workspace shared by the engine and the caller's callbacks. */
22
+ export interface ExternalSiteWorkspace {
23
+ repoRoot: string;
24
+ tempRoot: string;
25
+ siteDir: string;
26
+ vaultDir: string;
27
+ tarballDir: string;
28
+ packed: PackedPackages;
29
+ }
30
+ /** Repo-specific assertions supplied by the driver. */
31
+ export interface ExternalSiteAssertions {
32
+ /** Assert on the built `dist/` output (and, if needed, the vault). */
33
+ buildOutput(siteDir: string, vaultDir: string): void;
34
+ }
35
+ export interface ExternalSiteE2EConfig {
36
+ /** Absolute repository root. */
37
+ repoRoot: string;
38
+ /** Packages to pack and inject as local tarball dependencies. */
39
+ packages: readonly PackageSpec[];
40
+ /** Fixture site and vault directories. */
41
+ fixture: ExternalSiteFixture;
42
+ /** Absolute path to the undeclared-dependency checker script. */
43
+ dependencyCheckScript: string;
44
+ /** Published package scope, e.g. `"@riebeckite"`. */
45
+ scope: string;
46
+ /** CLI name shown in step lines, e.g. `"riebeckite"`. */
47
+ cliName: string;
48
+ /** Resolve the installed CLI entry point from the site directory. */
49
+ resolveCliEntry(siteDir: string): string;
50
+ /** CLI invocations, in order, run after the install checks. */
51
+ cliCommands: readonly CliCommandSpec[];
52
+ /** Directory (relative to the site) the CLI runs from. Defaults to the site. */
53
+ cliWorkingDirectory?: string;
54
+ /** TypeScript projects to type-check after the build. */
55
+ typecheckProjects?: readonly string[];
56
+ /** Extra type libraries beyond `node`; verified after writing. */
57
+ additionalTypeLibraries?: readonly string[];
58
+ /** Extra `exclude` entries for the bundler project. */
59
+ bundlerTypeExclude?: readonly string[];
60
+ /** NodeNext project whose `include` is replaced, or omitted to skip. */
61
+ nodeNextProject?: NodeNextProjectSpec;
62
+ /** Paths that must exist inside the isolated install. */
63
+ requiredInstallPaths?: readonly RequiredInstallPath[];
64
+ /** Directory site sources must not traverse into. Defaults to `packages`. */
65
+ monorepoPackagesDirectory?: string;
66
+ /** Repo-specific checks run after the generic install assertions. */
67
+ siteChecks?: readonly SiteCheck[];
68
+ /** Build-output assertion supplied by the driver. */
69
+ assertions: ExternalSiteAssertions;
70
+ /**
71
+ * Run after the build and type-checks, before the workspace is removed. Lets
72
+ * a driver reuse the packed tarballs for a secondary site.
73
+ */
74
+ afterSiteChecks?: (workspace: ExternalSiteWorkspace) => void | Promise<void>;
75
+ /** `pnpm pack` concurrency. Defaults to 4. */
76
+ concurrency?: number;
77
+ /** Logger label. Defaults to `"e2e"`. */
78
+ stepLabel?: string;
79
+ /** Final success message appended after `PASS: `. */
80
+ passMessage?: string;
81
+ /** Environment variable that keeps the temporary workspace. */
82
+ keepEnv: string;
83
+ /** Prefix for the temporary directory. Defaults to `"riebeckite-e2e-"`. */
84
+ tempPrefix?: string;
85
+ /** Logger to reuse; a new one is created when omitted. */
86
+ logger?: Logger;
87
+ }
88
+ /**
89
+ * Run the generic external-consumer end-to-end sequence:
90
+ *
91
+ * pack -> make temp workspace -> copy fixture -> write consumer manifest and
92
+ * tsconfig -> `npm install` -> isolation / escape-hatch / artifact /
93
+ * declared-dependency assertions -> repo-specific checks -> CLI checks ->
94
+ * build-output assertion -> type-checks -> optional `afterSiteChecks`.
95
+ *
96
+ * Everything repo-specific (repository root, package list, fixtures, marker
97
+ * assertions, CLI shape, keep-temp variable) is injected through `config`. The
98
+ * temporary workspace is removed in `finally` unless `config.keepEnv` is set.
99
+ */
100
+ export declare function runExternalSiteE2E(config: ExternalSiteE2EConfig): Promise<void>;
@@ -0,0 +1,55 @@
1
+ import type { Logger } from "./logger.js";
2
+ import type { PackedPackages } from "./pack.js";
3
+ export interface StageIsolatedSiteOptions {
4
+ /** Fixture site directory copied to `siteDir`. */
5
+ fixtureSite: string;
6
+ /** Fixture vault directory copied to `vaultDir` (next to the site). */
7
+ fixtureVault: string;
8
+ /** Destination site directory. */
9
+ siteDir: string;
10
+ /** Destination vault directory. */
11
+ vaultDir: string;
12
+ }
13
+ /**
14
+ * Copy the fixture site and vault into the temporary workspace. The vault is
15
+ * staged next to the site, not inside it, so any code that assumes content
16
+ * lives under the site root fails immediately.
17
+ */
18
+ export declare function stageIsolatedSite(options: StageIsolatedSiteOptions): void;
19
+ /**
20
+ * Rewrite the staged site manifest so every packed package resolves to its
21
+ * local tarball. Packages already declared as dev dependencies stay there;
22
+ * everything else moves to `dependencies`. An `overrides` entry is added for
23
+ * each package so transitive requirements also resolve locally.
24
+ */
25
+ export declare function writeFileDependencies(siteDir: string, packed: PackedPackages): void;
26
+ /** A NodeNext TypeScript project to constrain after staging. */
27
+ export interface NodeNextProjectSpec {
28
+ /** Config path relative to the site directory. */
29
+ config: string;
30
+ /** Replacement `include` entries. */
31
+ include: readonly string[];
32
+ }
33
+ export interface LayerExternalConsumerTypesOptions {
34
+ /**
35
+ * Type libraries to layer on top of the always-added `node` types. The
36
+ * engine verifies each one after writing.
37
+ */
38
+ additionalTypeLibraries: readonly string[];
39
+ /** Extra `exclude` entries for the bundler project. */
40
+ exclude?: readonly string[];
41
+ /** NodeNext project whose `include` is replaced, or omitted to skip. */
42
+ nodeNext?: NodeNextProjectSpec;
43
+ logger: Logger;
44
+ }
45
+ /**
46
+ * Layer the external-consumer type requirement onto the staged site before
47
+ * installation:
48
+ *
49
+ * - add `node` plus `additionalTypeLibraries` to `site/tsconfig.json` and
50
+ * exclude the editor-only declarations;
51
+ * - optionally restrict a NodeNext project to its published-entry import test.
52
+ *
53
+ * Everything is verified after writing so a silent no-op cannot pass.
54
+ */
55
+ export declare function layerExternalConsumerTypes(siteDir: string, options: LayerExternalConsumerTypesOptions): void;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Dependency-free golden assertion for `node:test`.
3
+ *
4
+ * Node's built-in snapshot assertion (`t.assert.snapshot`) needs Node 22.3+,
5
+ * but Riebeckite supports Node 20.19+, so tests record expected output as
6
+ * committed golden files and compare against them here instead.
7
+ *
8
+ * A missing golden file fails the test. Run `pnpm test:update` at the
9
+ * repository root (or set `UPDATE_GOLDEN=1` for a single package) to write the
10
+ * current output.
11
+ */
12
+ export interface GoldenOptions {
13
+ /**
14
+ * Normalize CRLF/CR to LF and collapse trailing newlines to one. Defaults to
15
+ * true so golden files stay stable across platforms and editors.
16
+ */
17
+ normalize?: boolean;
18
+ /** Extra context shown when the assertion fails. */
19
+ message?: string;
20
+ }
21
+ export declare function assertGolden(actual: string, golden: URL, options?: GoldenOptions): void;
22
+ export declare function assertGoldenJson(value: unknown, golden: URL, options?: GoldenOptions): void;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Shared unit-test utilities for Riebeckite packages.
3
+ *
4
+ * This entry point stays dependency-free and platform-neutral so any package
5
+ * can use it in its own `test/*.test.ts` without pulling in build tooling.
6
+ *
7
+ * The external-consumer end-to-end engine lives in the separate
8
+ * `@riebeckite/test/e2e` entry point because it orchestrates processes, the
9
+ * filesystem, and published tarballs.
10
+ */
11
+ export { assertGolden, assertGoldenJson, type GoldenOptions, } from "./golden.js";
package/dist/index.js ADDED
@@ -0,0 +1,40 @@
1
+ // golden.ts
2
+ import assert from "node:assert/strict";
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ function normalizeText(value) {
7
+ return `${value.replace(/\r\n?/g, "\n").replace(/\n+$/, "")}
8
+ `;
9
+ }
10
+ function relative(file) {
11
+ return path.relative(process.cwd(), file) || file;
12
+ }
13
+ function assertGolden(actual, golden, options = {}) {
14
+ const normalize = options.normalize ?? true;
15
+ const value = normalize ? normalizeText(actual) : actual;
16
+ const file = fileURLToPath(golden);
17
+ const label = options.message ? `${options.message}: ` : "";
18
+ if (process.env.UPDATE_GOLDEN === "1") {
19
+ fs.mkdirSync(path.dirname(file), { recursive: true });
20
+ fs.writeFileSync(file, value, "utf8");
21
+ return;
22
+ }
23
+ assert.ok(
24
+ fs.existsSync(file),
25
+ `${label}Missing golden file ${relative(file)}. Run \`pnpm test:update\` to create it.`
26
+ );
27
+ const recorded = fs.readFileSync(file, "utf8");
28
+ assert.equal(
29
+ value,
30
+ normalize ? normalizeText(recorded) : recorded,
31
+ `${label}Golden mismatch for ${relative(file)}. Run \`pnpm test:update\` to accept the new output.`
32
+ );
33
+ }
34
+ function assertGoldenJson(value, golden, options = {}) {
35
+ assertGolden(JSON.stringify(value, null, 2), golden, options);
36
+ }
37
+ export {
38
+ assertGolden,
39
+ assertGoldenJson
40
+ };
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@riebeckite/test",
3
+ "version": "0.0.6",
4
+ "license": "Apache-2.0",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "source": "./index.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "./e2e": {
16
+ "types": "./dist/e2e/index.d.ts",
17
+ "import": "./dist/e2e/index.js",
18
+ "source": "./e2e/index.ts",
19
+ "default": "./dist/e2e/index.js"
20
+ }
21
+ },
22
+ "files": [
23
+ "LICENSE",
24
+ "README.md",
25
+ "README_ja.md",
26
+ "dist"
27
+ ],
28
+ "publishConfig": {
29
+ "access": "public"
30
+ },
31
+ "devDependencies": {
32
+ "tsx": "^4.22.4"
33
+ },
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "https://github.com/Rerurate514/riebeckite.git",
37
+ "directory": "packages/test"
38
+ },
39
+ "homepage": "https://github.com/Rerurate514/riebeckite#readme",
40
+ "bugs": {
41
+ "url": "https://github.com/Rerurate514/riebeckite/issues"
42
+ },
43
+ "description": "Shared test utilities and a generic external-site end-to-end engine for Riebeckite packages.",
44
+ "keywords": [
45
+ "riebeckite",
46
+ "testing",
47
+ "test-utilities",
48
+ "golden",
49
+ "e2e"
50
+ ],
51
+ "engines": {
52
+ "node": "^20.19.0 || >=22.12.0"
53
+ },
54
+ "sideEffects": false,
55
+ "scripts": {
56
+ "build": "node ../../scripts/build_package.mjs",
57
+ "test": "node --import tsx --test \"test/*.test.ts\""
58
+ }
59
+ }