mirror of
https://github.com/morluto/rea.git
synced 2026-11-11 09:21:16 +00:00
* test(apple): qualify native Interface Builder XML encodings Exercise actual AppKit/Foundation XML archive representations through filesystem and compiled CLI consumers. Preserve independent UID/hierarchy and original-byte provenance oracles. Tests-only candidate qualification on unchanged native Apple CI; no production or workflow changes. Signed-off-by: Rudy Celekli <rudy@gradiahq.com> * fix(apple): share BOM-aware Interface Builder XML decoding Reuse the existing fatal BOM-aware XML plist decoder for Interface Builder archives. Preserve original serialized-byte digests, binary decoding, and frozen native producer/consumer tests. Signed-off-by: Rudy Celekli <rudy@gradiahq.com> * fix(apple): reject unsupported XML encoding declarations --------- Signed-off-by: Rudy Celekli <rudy@gradiahq.com> Co-authored-by: N0zoM1z0 <1705004398@qq.com>
79 lines
2.5 KiB
TypeScript
79 lines
2.5 KiB
TypeScript
import { writeFile } from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
|
|
import { build } from "plist";
|
|
import { expect, it } from "vitest";
|
|
|
|
import { analyzeInterfaceBuilderBundle } from "../../../src/artifacts/apple/InterfaceBuilderAnalysis.js";
|
|
import { inspectBundleKeyedArchive } from "../../../src/artifacts/apple/KeyedArchiveReader.js";
|
|
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
|
|
|
|
const archive = build({
|
|
$archiver: "NSKeyedArchiver",
|
|
$objects: ["$null", "Café"],
|
|
$top: { root: { CF$UID: 1 } },
|
|
});
|
|
|
|
const fixture = async (declaration: string) => {
|
|
const bundlePath = await createTestTempDirectory("rea-xml-declaration-");
|
|
await writeFile(
|
|
join(bundlePath, "Panel.nib"),
|
|
Buffer.from(archive.replace("UTF-8", declaration), "utf8"),
|
|
);
|
|
return { bundlePath, targetSha256: "a".repeat(64) };
|
|
};
|
|
|
|
it.each(["UTF-8", "utf-8"])(
|
|
"retains UTF-8 characters with the supported declaration %s",
|
|
async (declaration) => {
|
|
const input = await fixture(declaration);
|
|
const archiveResult = await inspectBundleKeyedArchive({
|
|
...input,
|
|
parameters: { path: "Panel.nib" },
|
|
});
|
|
expect(archiveResult.objects).toContainEqual(
|
|
expect.objectContaining({ value: "Café" }),
|
|
);
|
|
const interfaceBuilderResult = await analyzeInterfaceBuilderBundle(input);
|
|
expect(interfaceBuilderResult.documents).toHaveLength(1);
|
|
expect(interfaceBuilderResult.documents[0]?.relative_path).toBe(
|
|
"Panel.nib",
|
|
);
|
|
},
|
|
);
|
|
|
|
it.each(["REA-UNSUPPORTED", "ISO-8859-1"])(
|
|
"reports unsupported keyed archive encoding %s instead of substituting UTF-8 text",
|
|
async (declaration) => {
|
|
const input = await fixture(declaration);
|
|
await expect(
|
|
inspectBundleKeyedArchive({
|
|
...input,
|
|
parameters: { path: "Panel.nib" },
|
|
}),
|
|
).rejects.toMatchObject({
|
|
reason: "format",
|
|
message: expect.stringContaining(declaration),
|
|
});
|
|
},
|
|
);
|
|
|
|
it.each(["REA-UNSUPPORTED", "ISO-8859-1"])(
|
|
"reports unsupported Interface Builder encoding %s without graph substitution",
|
|
async (declaration) => {
|
|
const result = await analyzeInterfaceBuilderBundle(
|
|
await fixture(declaration),
|
|
);
|
|
expect(result.documents).toEqual([]);
|
|
expect(result.graph.nodes).toEqual([]);
|
|
expect(result.graph.coverage).toContainEqual(
|
|
expect.objectContaining({
|
|
facet: "archive_decode",
|
|
status: "partial",
|
|
reason: "one_or_more_archives_invalid",
|
|
}),
|
|
);
|
|
expect(result.graph.truncated).toBe(true);
|
|
},
|
|
);
|