mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-13 23:39:21 +02:00
test: recognize review-ready registered artifacts
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
bca7c850d5
commit
c144ca97f0
2 files changed
+25
-4
No files matched your search
@@ -13,18 +13,37 @@ function fixture() {
|
||||
return { product, attachment, download, get, api: { get, request: { get: download } } as unknown as RunnerApi };
|
||||
}
|
||||
|
||||
it("downloads the exact registered run-attributed output through its public path", async () => {
|
||||
const { api, download } = fixture();
|
||||
it.each(["active", "ready_for_review", "approved"])("downloads the exact registered run-attributed %s output through its public path", async status => {
|
||||
const { api, product, download } = fixture();
|
||||
product.status = status;
|
||||
const artifacts = await readRegisteredArtifacts(api, "issue", "run", ["proof.txt"]);
|
||||
expect(download).toHaveBeenCalledWith("/api/attachments/attachment/content?download=1");
|
||||
expect((await evaluateMatcher({ kind: "artifact_exact", name: "proof.txt", expected: "verified\n", mimeType: "text/plain" }, { artifacts })).passed).toBe(true);
|
||||
});
|
||||
|
||||
it.each(["unregistered", "old-run", "unattributed", "hash-mismatch", "download-failure"])("refuses %s output evidence", async reason => {
|
||||
it.each(["draft", "changes_requested", "merged", "closed", "failed", "archived", "superseded", "withdrawn", "unknown"])("refuses %s artifact registrations before downloading", async status => {
|
||||
const { api, product, download } = fixture();
|
||||
product.status = status;
|
||||
await expect(readRegisteredArtifacts(api, "issue", "run", ["proof.txt"])).rejects.toThrow("Expected one registered artifact");
|
||||
expect(download).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it.each(["unregistered", "duplicate", "old-run", "unattributed", "wrong-issue", "wrong-attachment-issue", "wrong-type", "wrong-title", "wrong-filename", "wrong-attachment-id", "negative-size", "excessive-size", "size-mismatch", "hash-mismatch", "download-failure"])("refuses %s output evidence even when ready for review", async reason => {
|
||||
const { api, product, attachment, get, download } = fixture();
|
||||
product.status = "ready_for_review";
|
||||
if (reason === "unregistered") get.mockImplementation(async (path: string) => path.endsWith("work-products") ? [] : [attachment]);
|
||||
if (reason === "duplicate") get.mockImplementation(async (path: string) => path.endsWith("work-products") ? [product, { ...product, id: "duplicate", status: "approved" }] : [attachment]);
|
||||
if (reason === "old-run") product.createdByRunId = "other-run";
|
||||
if (reason === "unattributed") attachment.originatingRunId = "other-run";
|
||||
if (reason === "wrong-issue") product.issueId = "other-issue";
|
||||
if (reason === "wrong-attachment-issue") attachment.issueId = "other-issue";
|
||||
if (reason === "wrong-type") product.type = "document";
|
||||
if (reason === "wrong-title") product.title = "other.txt";
|
||||
if (reason === "wrong-filename") attachment.originalFilename = "other.txt";
|
||||
if (reason === "wrong-attachment-id") product.metadata.attachmentId = "other-attachment";
|
||||
if (reason === "negative-size") attachment.byteSize = -1;
|
||||
if (reason === "excessive-size") attachment.byteSize = 262_145;
|
||||
if (reason === "size-mismatch") attachment.byteSize += 1;
|
||||
if (reason === "hash-mismatch") attachment.sha256 = "incorrect";
|
||||
if (reason === "download-failure") download.mockResolvedValue({ ok: () => false, status: () => 404 });
|
||||
await expect(readRegisteredArtifacts(api, "issue", "run", ["proof.txt"])).rejects.toThrow();
|
||||
|
||||
@@ -3,6 +3,8 @@ import type { IssueAttachment } from "../../packages/shared/src/types/issue.js";
|
||||
import type { IssueWorkProduct } from "../../packages/shared/src/types/work-product.js";
|
||||
import type { RunnerApi } from "./api.js";
|
||||
|
||||
const REGISTERED_ARTIFACT_STATUSES = new Set(["active", "ready_for_review", "approved"]);
|
||||
|
||||
/** Registration, attribution and downloaded bytes must agree independently. */
|
||||
export async function readRegisteredArtifacts(api: RunnerApi, issueId: string, runId: string, names: readonly string[]) {
|
||||
if (names.length === 0) return [];
|
||||
@@ -13,7 +15,7 @@ export async function readRegisteredArtifacts(api: RunnerApi, issueId: string, r
|
||||
return Promise.all(names.map(async name => {
|
||||
const registered = products.filter(product => product.issueId === issueId &&
|
||||
product.createdByRunId === runId && product.type === "artifact" &&
|
||||
product.status === "active" && product.title === name);
|
||||
REGISTERED_ARTIFACT_STATUSES.has(product.status) && product.title === name);
|
||||
if (registered.length !== 1) throw new Error(`Expected one registered artifact ${name} from the tested run; observed ${registered.length}`);
|
||||
const product = registered[0]!;
|
||||
const attachmentId = product.metadata?.attachmentId;
|
||||
|
||||
Reference in new issue
Block a user