fix: validate schema exists in json-cas put command #58
@@ -315,6 +315,207 @@ describe("ucas render command", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("Schema Hash Validation in put command", () => {
|
||||
test("put with non-existent literal hash should fail", async () => {
|
||||
await runCliAlias("init");
|
||||
|
||||
const payloadFile = join(testDir, "payload.json");
|
||||
writeFileSync(payloadFile, JSON.stringify({ test: "data" }));
|
||||
|
||||
const { stderr, exitCode } = await runCliAlias(
|
||||
"put",
|
||||
"AAAAAAAAAAAAA",
|
||||
payloadFile,
|
||||
);
|
||||
|
||||
expect(exitCode).not.toBe(0);
|
||||
expect(stderr).toContain("Schema not found: AAAAAAAAAAAAA");
|
||||
});
|
||||
|
||||
test("put with different non-existent literal hash should fail", async () => {
|
||||
await runCliAlias("init");
|
||||
|
||||
const payloadFile = join(testDir, "payload.json");
|
||||
writeFileSync(payloadFile, JSON.stringify({ test: "data" }));
|
||||
|
||||
const { stderr, exitCode } = await runCliAlias(
|
||||
"put",
|
||||
"ZZZZZZZZZZZZZ",
|
||||
payloadFile,
|
||||
);
|
||||
|
||||
expect(exitCode).not.toBe(0);
|
||||
expect(stderr).toContain("Schema not found: ZZZZZZZZZZZZZ");
|
||||
});
|
||||
|
||||
test("put with malformed hash should fail", async () => {
|
||||
await runCliAlias("init");
|
||||
|
||||
const payloadFile = join(testDir, "payload.json");
|
||||
writeFileSync(payloadFile, JSON.stringify({ test: "data" }));
|
||||
|
||||
const { stderr, exitCode } = await runCliAlias(
|
||||
"put",
|
||||
"INVALID_HASH",
|
||||
payloadFile,
|
||||
);
|
||||
|
||||
expect(exitCode).not.toBe(0);
|
||||
expect(stderr.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
test("put with non-existent @alias should fail with clear message", async () => {
|
||||
await runCliAlias("init");
|
||||
|
||||
const payloadFile = join(testDir, "payload.json");
|
||||
writeFileSync(payloadFile, JSON.stringify({ test: "data" }));
|
||||
|
||||
const { stderr, exitCode } = await runCliAlias(
|
||||
"put",
|
||||
"@nonexistent",
|
||||
payloadFile,
|
||||
);
|
||||
|
||||
expect(exitCode).not.toBe(0);
|
||||
expect(stderr).toContain("Schema not found");
|
||||
expect(stderr).toContain("@nonexistent");
|
||||
});
|
||||
|
||||
test("put with valid @string alias should succeed (regression)", async () => {
|
||||
await runCliAlias("init");
|
||||
|
||||
const payloadFile = join(testDir, "payload.json");
|
||||
writeFileSync(payloadFile, JSON.stringify("hello"));
|
||||
|
||||
const { stdout, stderr, exitCode } = await runCliAlias(
|
||||
"put",
|
||||
"@string",
|
||||
payloadFile,
|
||||
);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
expect(stderr).toBe("");
|
||||
expect(stdout).toMatch(/^[0-9A-HJKMNP-TV-Z]{13}$/);
|
||||
});
|
||||
|
||||
test("put with valid @number alias should succeed (regression)", async () => {
|
||||
await runCliAlias("init");
|
||||
|
||||
const payloadFile = join(testDir, "payload.json");
|
||||
writeFileSync(payloadFile, "42");
|
||||
|
||||
const { stdout, stderr, exitCode } = await runCliAlias(
|
||||
"put",
|
||||
"@number",
|
||||
payloadFile,
|
||||
);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
expect(stderr).toBe("");
|
||||
expect(stdout).toMatch(/^[0-9A-HJKMNP-TV-Z]{13}$/);
|
||||
});
|
||||
|
||||
test("put with valid @object alias should succeed (regression)", async () => {
|
||||
await runCliAlias("init");
|
||||
|
||||
const payloadFile = join(testDir, "payload.json");
|
||||
writeFileSync(payloadFile, JSON.stringify({ key: "value" }));
|
||||
|
||||
const { stdout, stderr, exitCode } = await runCliAlias(
|
||||
"put",
|
||||
"@object",
|
||||
payloadFile,
|
||||
);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
expect(stderr).toBe("");
|
||||
expect(stdout).toMatch(/^[0-9A-HJKMNP-TV-Z]{13}$/);
|
||||
});
|
||||
|
||||
test("put with explicit valid schema hash should succeed (regression)", async () => {
|
||||
await runCliAlias("init");
|
||||
|
||||
// First, create a custom schema
|
||||
const schemaFile = join(testDir, "schema.json");
|
||||
writeFileSync(
|
||||
schemaFile,
|
||||
JSON.stringify({
|
||||
type: "object",
|
||||
properties: { name: { type: "string" } },
|
||||
}),
|
||||
);
|
||||
const { stdout: schemaHash } = await runCliAlias(
|
||||
"schema",
|
||||
"put",
|
||||
schemaFile,
|
||||
);
|
||||
|
||||
// Now create a node with that schema
|
||||
const payloadFile = join(testDir, "payload.json");
|
||||
writeFileSync(payloadFile, JSON.stringify({ name: "test" }));
|
||||
|
||||
const { stdout, stderr, exitCode } = await runCliAlias(
|
||||
"put",
|
||||
schemaHash.trim(),
|
||||
payloadFile,
|
||||
);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
expect(stderr).toBe("");
|
||||
expect(stdout).toMatch(/^[0-9A-HJKMNP-TV-Z]{13}$/);
|
||||
});
|
||||
|
||||
test("all bootstrap schema aliases should work (regression)", async () => {
|
||||
await runCliAlias("init");
|
||||
|
||||
const aliases = ["@string", "@number", "@object", "@array", "@bool"];
|
||||
const payloads = [
|
||||
JSON.stringify("test"),
|
||||
"123",
|
||||
JSON.stringify({}),
|
||||
JSON.stringify([]),
|
||||
"true",
|
||||
];
|
||||
|
||||
for (let i = 0; i < aliases.length; i++) {
|
||||
const payloadFile = join(testDir, `payload-${i}.json`);
|
||||
writeFileSync(payloadFile, payloads[i] ?? "");
|
||||
|
||||
const { exitCode } = await runCliAlias(
|
||||
"put",
|
||||
aliases[i] ?? "",
|
||||
payloadFile,
|
||||
);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
}
|
||||
});
|
||||
|
||||
test("error message should preserve original input (hash)", async () => {
|
||||
await runCliAlias("init");
|
||||
|
||||
const payloadFile = join(testDir, "payload.json");
|
||||
writeFileSync(payloadFile, JSON.stringify({ test: "data" }));
|
||||
|
||||
const { stderr } = await runCliAlias("put", "AAAAAAAAAAAAA", payloadFile);
|
||||
|
||||
// Error should show the original hash, not a resolved version
|
||||
expect(stderr).toContain("AAAAAAAAAAAAA");
|
||||
});
|
||||
|
||||
test("error message should preserve original input (alias)", async () => {
|
||||
await runCliAlias("init");
|
||||
|
||||
const payloadFile = join(testDir, "payload.json");
|
||||
writeFileSync(payloadFile, JSON.stringify({ test: "data" }));
|
||||
|
||||
const { stderr } = await runCliAlias("put", "@invalid", payloadFile);
|
||||
|
||||
// Error should show the original alias, not a resolved hash
|
||||
expect(stderr).toContain("@invalid");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Suite 6: CLI Integration with Templates", () => {
|
||||
test("6.1 CLI with Template (Default Parameters)", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
|
||||
@@ -294,6 +294,12 @@ async function cmdPut(args: string[]): Promise<void> {
|
||||
const typeHash = await resolveTypeHash(typeHashOrAlias);
|
||||
const payload = readJsonFile(file);
|
||||
const store = openStore();
|
||||
|
||||
// Check if schema exists before storing
|
||||
if (!store.has(typeHash)) {
|
||||
die(`Schema not found: ${typeHashOrAlias}`);
|
||||
}
|
||||
|
||||
const hash = await store.put(typeHash, payload);
|
||||
console.log(hash);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user