Files
rea/tests/acceptance/keyedArchiveInputValidation.test.ts

104 lines
3.4 KiB
TypeScript

import { mkdir, writeFile } from "node:fs/promises";
import { dirname } from "node:path";
import { Ajv2020 } from "ajv/dist/2020.js";
import { build } from "plist";
import { expect } from "vitest";
import { workspaceCliTest } from "../support/cli/workspaceCliFixture.js";
const archive = build({
$archiver: "NSKeyedArchiver",
$version: 100000,
$objects: ["$null", "leaf"],
$top: { root: { CF$UID: 1 } },
});
workspaceCliTest(
"advertises the shared nonempty, NUL-free archive selector",
async ({ cli }) => {
const result = await cli.run({
arguments: ["inspect-keyed-archive", "--schema", "--json"],
});
expect(result.exitCode, result.stderr).toBe(0);
const output = result.json as { args: Parameters<Ajv2020["compile"]>[0] };
expect(output).toMatchObject({
args: { properties: { archive: { minLength: 1, default: "." } } },
});
const validate = new Ajv2020({ strict: false }).compile(output.args);
expect(validate({ path: "Static.app", archive: "" })).toBe(false);
expect(validate({ path: "Static.app", archive: "Model\u0000.plist" })).toBe(
false,
);
expect(
validate({ path: "Static.app", archive: "Resources/Model.plist" }),
).toBe(true);
expect(validate({ path: "Model.plist" })).toBe(true);
},
);
workspaceCliTest(
"identifies an empty archive argument before target admission",
async ({ cli, workspace }) => {
const bundle = workspace.path("Static.app");
await mkdir(bundle);
await writeFile(
workspace.path("Static.app/Info.plist"),
build({ CFBundleIdentifier: "org.example.staticarchive" }),
);
for (const target of [bundle, workspace.path("Missing.app")]) {
const result = await cli.run({
arguments: ["inspect-keyed-archive", target, "", "--json"],
});
expect(result.exitCode).toBe(1);
expect(result.stderr).toBe("");
expect(result.json).toMatchObject({
code: "VALIDATION_ERROR",
fieldErrors: [{ path: "archive", code: "too_small", missing: false }],
});
}
},
);
workspaceCliTest(
"retains explicit bundle paging and the default standalone selector",
async ({ cli, workspace }) => {
const bundle = workspace.path("Static.app");
const member = "Contents/Resources/Model.plist";
const path = workspace.path(`Static.app/${member}`);
await mkdir(dirname(path), { recursive: true });
await writeFile(
workspace.path("Static.app/Contents/Info.plist"),
build({ CFBundleIdentifier: "org.example.staticarchive" }),
);
await writeFile(path, archive);
for (const [target, selection] of [[bundle, member], [path]] as const) {
const result = await cli.run({
arguments: [
"inspect-keyed-archive",
target,
...(selection === undefined ? [] : [selection]),
...(selection === undefined
? []
: ["--offset", "1", "--limit", "1", "--root", "root"]),
"--json",
],
});
expect(result.exitCode, result.stderr).toBe(0);
expect(result.json).toMatchObject({
normalized_result: {
archive_path: selection ?? "Model.plist",
total_objects: 2,
objects: expect.arrayContaining([
expect.objectContaining({ value: "leaf" }),
]),
},
});
if (selection !== undefined)
expect(result.json).toMatchObject({
normalized_result: { offset: 1, objects: [{ id: 1, value: "leaf" }] },
});
}
},
);