@riebeckite/test 0.0.21 → 0.0.23
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.
- package/dist/e2e/index.js +79 -25
- package/dist/e2e/pack.d.ts +0 -5
- package/dist/fixtures.d.ts +3 -0
- package/dist/fixtures.js +33 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +40 -8
- package/package.json +7 -1
package/dist/e2e/index.js
CHANGED
|
@@ -317,8 +317,52 @@ function createLogger(label = "e2e") {
|
|
|
317
317
|
// e2e/pack.ts
|
|
318
318
|
import fs3 from "node:fs";
|
|
319
319
|
import path4 from "node:path";
|
|
320
|
+
function assertPackArtifacts(packageDir, pkg) {
|
|
321
|
+
const manifest = JSON.parse(
|
|
322
|
+
fs3.readFileSync(path4.join(packageDir, "package.json"), "utf8")
|
|
323
|
+
);
|
|
324
|
+
if (manifest.files?.includes("dist") && !fs3.existsSync(path4.join(packageDir, "dist"))) {
|
|
325
|
+
throw new Error(
|
|
326
|
+
`Cannot pack ${pkg.name}: dist/ is missing. Build workspace packages before running isolated package tests.`
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
function packageLevels(repoRoot, packages) {
|
|
331
|
+
const byName = new Map(packages.map((pkg) => [pkg.name, pkg]));
|
|
332
|
+
const dependencies = /* @__PURE__ */ new Map();
|
|
333
|
+
for (const pkg of packages) {
|
|
334
|
+
const manifest = JSON.parse(
|
|
335
|
+
fs3.readFileSync(
|
|
336
|
+
path4.join(repoRoot, pkg.directory, "package.json"),
|
|
337
|
+
"utf8"
|
|
338
|
+
)
|
|
339
|
+
);
|
|
340
|
+
dependencies.set(
|
|
341
|
+
pkg.name,
|
|
342
|
+
Object.keys(manifest.dependencies ?? {}).filter(
|
|
343
|
+
(name) => byName.has(name)
|
|
344
|
+
)
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
const remaining = new Set(byName.keys());
|
|
348
|
+
const levels = [];
|
|
349
|
+
while (remaining.size > 0) {
|
|
350
|
+
const level = packages.filter(
|
|
351
|
+
(pkg) => remaining.has(pkg.name) && (dependencies.get(pkg.name) ?? []).every(
|
|
352
|
+
(dependency) => !remaining.has(dependency)
|
|
353
|
+
)
|
|
354
|
+
);
|
|
355
|
+
if (level.length === 0) {
|
|
356
|
+
throw new Error("Workspace package dependency cycle");
|
|
357
|
+
}
|
|
358
|
+
levels.push(level);
|
|
359
|
+
for (const pkg of level) remaining.delete(pkg.name);
|
|
360
|
+
}
|
|
361
|
+
return levels;
|
|
362
|
+
}
|
|
320
363
|
async function packPackages(tarballDir, options) {
|
|
321
364
|
const { repoRoot, packages, logger, concurrency = 4 } = options;
|
|
365
|
+
const levels = packageLevels(repoRoot, packages);
|
|
322
366
|
logger.step(
|
|
323
367
|
`packing ${packages.length} packages with pnpm pack (concurrency ${concurrency})`
|
|
324
368
|
);
|
|
@@ -327,12 +371,20 @@ async function packPackages(tarballDir, options) {
|
|
|
327
371
|
if (!fs3.existsSync(packageDir)) {
|
|
328
372
|
logger.fail(`Package directory is missing: ${pkg.directory}`);
|
|
329
373
|
}
|
|
374
|
+
assertPackArtifacts(packageDir, pkg);
|
|
330
375
|
const manifest = JSON.parse(
|
|
331
376
|
fs3.readFileSync(path4.join(packageDir, "package.json"), "utf8")
|
|
332
377
|
);
|
|
333
|
-
await runAsync(
|
|
334
|
-
|
|
335
|
-
|
|
378
|
+
await runAsync(
|
|
379
|
+
"pnpm",
|
|
380
|
+
[
|
|
381
|
+
"--config.ignore-scripts=true",
|
|
382
|
+
"pack",
|
|
383
|
+
"--pack-destination",
|
|
384
|
+
tarballDir
|
|
385
|
+
],
|
|
386
|
+
{ cwd: packageDir }
|
|
387
|
+
);
|
|
336
388
|
const sanitized = pkg.name.replace(/^@/, "").replace(/\//g, "-");
|
|
337
389
|
const tarball = path4.join(
|
|
338
390
|
tarballDir,
|
|
@@ -344,28 +396,30 @@ async function packPackages(tarballDir, options) {
|
|
|
344
396
|
console.log(` packed ${pkg.name} -> ${path4.basename(tarball)}`);
|
|
345
397
|
return { pkg, version: manifest.version, tarball };
|
|
346
398
|
};
|
|
347
|
-
const results =
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
nextIndex
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
(
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
399
|
+
const results = [];
|
|
400
|
+
for (const level of levels) {
|
|
401
|
+
const levelResults = new Array(level.length);
|
|
402
|
+
let nextIndex = 0;
|
|
403
|
+
const worker = async () => {
|
|
404
|
+
while (nextIndex < level.length) {
|
|
405
|
+
const index = nextIndex;
|
|
406
|
+
nextIndex += 1;
|
|
407
|
+
const pkg = level[index];
|
|
408
|
+
if (pkg === void 0) continue;
|
|
409
|
+
levelResults[index] = await packOne(pkg);
|
|
410
|
+
}
|
|
411
|
+
};
|
|
412
|
+
const batch = await Promise.allSettled(
|
|
413
|
+
Array.from(
|
|
414
|
+
{ length: Math.min(concurrency, level.length) },
|
|
415
|
+
() => worker()
|
|
416
|
+
)
|
|
417
|
+
);
|
|
418
|
+
const failure = batch.find(
|
|
419
|
+
(result) => result.status === "rejected"
|
|
420
|
+
);
|
|
421
|
+
if (failure) throw failure.reason;
|
|
422
|
+
results.push(...levelResults);
|
|
369
423
|
}
|
|
370
424
|
const packed = /* @__PURE__ */ new Map();
|
|
371
425
|
for (const result of results) {
|
package/dist/e2e/pack.d.ts
CHANGED
|
@@ -22,9 +22,4 @@ export interface PackPackagesOptions {
|
|
|
22
22
|
concurrency?: number;
|
|
23
23
|
logger: Logger;
|
|
24
24
|
}
|
|
25
|
-
/**
|
|
26
|
-
* Pack every package with `pnpm pack` into `tarballDir`, using a
|
|
27
|
-
* limited-concurrency pool. Returns a map from package name to its tarball and
|
|
28
|
-
* version. The first failure rejects the returned promise.
|
|
29
|
-
*/
|
|
30
25
|
export declare function packPackages(tarballDir: string, options: PackPackagesOptions): Promise<PackedPackages>;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export type Frontmatter = Readonly<Record<string, string | number | boolean | readonly string[]>>;
|
|
2
|
+
export declare function markdown(body: string, frontmatter?: Frontmatter): string;
|
|
3
|
+
export declare function withTemporaryDirectory<T>(prefixOrCallback: string | ((directory: string) => Promise<T>), callback?: (directory: string) => Promise<T>): Promise<T>;
|
package/dist/fixtures.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// fixtures.ts
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
function frontmatterValue(value) {
|
|
6
|
+
if (Array.isArray(value))
|
|
7
|
+
return `[${value.map((item) => JSON.stringify(item)).join(", ")}]`;
|
|
8
|
+
return String(value);
|
|
9
|
+
}
|
|
10
|
+
function markdown(body, frontmatter) {
|
|
11
|
+
if (!frontmatter || Object.keys(frontmatter).length === 0) return body;
|
|
12
|
+
const fields = Object.entries(frontmatter).map(([key, value]) => `${key}: ${frontmatterValue(value)}`).join("\n");
|
|
13
|
+
return `---
|
|
14
|
+
${fields}
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
${body}`;
|
|
18
|
+
}
|
|
19
|
+
async function withTemporaryDirectory(prefixOrCallback, callback) {
|
|
20
|
+
const prefix = typeof prefixOrCallback === "string" ? prefixOrCallback : "riebeckite-test-";
|
|
21
|
+
const operation = typeof prefixOrCallback === "function" ? prefixOrCallback : callback;
|
|
22
|
+
if (!operation) throw new Error("A temporary directory callback is required");
|
|
23
|
+
const directory = await fs.mkdtemp(path.join(os.tmpdir(), prefix));
|
|
24
|
+
try {
|
|
25
|
+
return await operation(directory);
|
|
26
|
+
} finally {
|
|
27
|
+
await fs.rm(directory, { recursive: true, force: true, maxRetries: 3 });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export {
|
|
31
|
+
markdown,
|
|
32
|
+
withTemporaryDirectory
|
|
33
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -8,4 +8,5 @@
|
|
|
8
8
|
* `@riebeckite/test/e2e` entry point because it orchestrates processes, the
|
|
9
9
|
* filesystem, and published tarballs.
|
|
10
10
|
*/
|
|
11
|
+
export { type Frontmatter, markdown, withTemporaryDirectory, } from "./fixtures.js";
|
|
11
12
|
export { assertGolden, assertGoldenJson, type GoldenOptions, } from "./golden.js";
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,44 @@
|
|
|
1
|
+
// fixtures.ts
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
function frontmatterValue(value) {
|
|
6
|
+
if (Array.isArray(value))
|
|
7
|
+
return `[${value.map((item) => JSON.stringify(item)).join(", ")}]`;
|
|
8
|
+
return String(value);
|
|
9
|
+
}
|
|
10
|
+
function markdown(body, frontmatter) {
|
|
11
|
+
if (!frontmatter || Object.keys(frontmatter).length === 0) return body;
|
|
12
|
+
const fields = Object.entries(frontmatter).map(([key, value]) => `${key}: ${frontmatterValue(value)}`).join("\n");
|
|
13
|
+
return `---
|
|
14
|
+
${fields}
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
${body}`;
|
|
18
|
+
}
|
|
19
|
+
async function withTemporaryDirectory(prefixOrCallback, callback) {
|
|
20
|
+
const prefix = typeof prefixOrCallback === "string" ? prefixOrCallback : "riebeckite-test-";
|
|
21
|
+
const operation = typeof prefixOrCallback === "function" ? prefixOrCallback : callback;
|
|
22
|
+
if (!operation) throw new Error("A temporary directory callback is required");
|
|
23
|
+
const directory = await fs.mkdtemp(path.join(os.tmpdir(), prefix));
|
|
24
|
+
try {
|
|
25
|
+
return await operation(directory);
|
|
26
|
+
} finally {
|
|
27
|
+
await fs.rm(directory, { recursive: true, force: true, maxRetries: 3 });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
1
31
|
// golden.ts
|
|
2
32
|
import assert from "node:assert/strict";
|
|
3
|
-
import
|
|
4
|
-
import
|
|
33
|
+
import fs2 from "node:fs";
|
|
34
|
+
import path2 from "node:path";
|
|
5
35
|
import { fileURLToPath } from "node:url";
|
|
6
36
|
function normalizeText(value) {
|
|
7
37
|
return `${value.replace(/\r\n?/g, "\n").replace(/\n+$/, "")}
|
|
8
38
|
`;
|
|
9
39
|
}
|
|
10
40
|
function relative(file) {
|
|
11
|
-
return
|
|
41
|
+
return path2.relative(process.cwd(), file) || file;
|
|
12
42
|
}
|
|
13
43
|
function assertGolden(actual, golden, options = {}) {
|
|
14
44
|
const normalize = options.normalize ?? true;
|
|
@@ -16,15 +46,15 @@ function assertGolden(actual, golden, options = {}) {
|
|
|
16
46
|
const file = fileURLToPath(golden);
|
|
17
47
|
const label = options.message ? `${options.message}: ` : "";
|
|
18
48
|
if (process.env.UPDATE_GOLDEN === "1") {
|
|
19
|
-
|
|
20
|
-
|
|
49
|
+
fs2.mkdirSync(path2.dirname(file), { recursive: true });
|
|
50
|
+
fs2.writeFileSync(file, value, "utf8");
|
|
21
51
|
return;
|
|
22
52
|
}
|
|
23
53
|
assert.ok(
|
|
24
|
-
|
|
54
|
+
fs2.existsSync(file),
|
|
25
55
|
`${label}Missing golden file ${relative(file)}. Run \`pnpm test:update\` to create it.`
|
|
26
56
|
);
|
|
27
|
-
const recorded =
|
|
57
|
+
const recorded = fs2.readFileSync(file, "utf8");
|
|
28
58
|
assert.equal(
|
|
29
59
|
value,
|
|
30
60
|
normalize ? normalizeText(recorded) : recorded,
|
|
@@ -36,5 +66,7 @@ function assertGoldenJson(value, golden, options = {}) {
|
|
|
36
66
|
}
|
|
37
67
|
export {
|
|
38
68
|
assertGolden,
|
|
39
|
-
assertGoldenJson
|
|
69
|
+
assertGoldenJson,
|
|
70
|
+
markdown,
|
|
71
|
+
withTemporaryDirectory
|
|
40
72
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@riebeckite/test",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.23",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -17,6 +17,12 @@
|
|
|
17
17
|
"import": "./dist/e2e/index.js",
|
|
18
18
|
"source": "./e2e/index.ts",
|
|
19
19
|
"default": "./dist/e2e/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./fixtures": {
|
|
22
|
+
"types": "./dist/fixtures.d.ts",
|
|
23
|
+
"import": "./dist/fixtures.js",
|
|
24
|
+
"source": "./fixtures.ts",
|
|
25
|
+
"default": "./dist/fixtures.js"
|
|
20
26
|
}
|
|
21
27
|
},
|
|
22
28
|
"files": [
|