diff --git a/test/landscape.jpg b/test/landscape.jpg new file mode 100644 index 0000000..ca1f30f Binary files /dev/null and b/test/landscape.jpg differ diff --git a/test/man.jpg b/test/man.jpg new file mode 100644 index 0000000..7848ac6 Binary files /dev/null and b/test/man.jpg differ diff --git a/test/v2.test.ts b/test/v2.test.ts index 5935414..5bb79ef 100644 --- a/test/v2.test.ts +++ b/test/v2.test.ts @@ -1,5 +1,5 @@ -import { assertEquals } from "jsr:@std/assert"; -import { createProdia } from "../v2/index.ts"; +import { assert, assertEquals } from "jsr:@std/assert"; +import { createProdia, ProdiaUserError } from "../v2/index.ts"; const token = Deno.env.get("PRODIA_TOKEN"); @@ -32,3 +32,44 @@ await Deno.test("Example Job: JPEG Output", async () => { assertEquals(isJpeg(image), true, "Image should be a JPEG"); }); + +await Deno.test("Example Job: Bad Face Swap", async () => { + const client = createProdia({ + token, + }); + + try { + const job = await client.job( + { + type: "inference.faceswap.v1", + config: {}, + }, + { + inputs: [ + new Blob([await Deno.readFile("./test/landscape.jpg")], { + type: "image/jpeg", + }), + new Blob([await Deno.readFile("./test/man.jpg")], { + type: "image/jpeg", + }), + ], + }, + ); + + const image = await job.arrayBuffer(); + + assertEquals(isJpeg(image), true, "Image should be a JPEG"); + + throw new Error("FaceSwap should fail"); + } catch (error) { + assert( + error instanceof ProdiaUserError, + `Error should be a ProdiaUserError, got ${error}`, + ); + assertEquals( + error.message, + "No face detected in the source image.", + "Error message should be 'No face detected in the source image.'", + ); + } +}); diff --git a/v2/index.ts b/v2/index.ts index 1ab5393..1a2ca91 100644 --- a/v2/index.ts +++ b/v2/index.ts @@ -162,28 +162,42 @@ export const createProdia = ({ retries <= maxRetries ); + if (response.headers.get("Content-Type") === "application/json") { + const body = await response.json() as ProdiaJob; + + if ("error" in body && typeof body.error === "string") { + throw new ProdiaUserError(body.error); + } else { + throw new ProdiaBadResponseError( + `${response.status} ${response.statusText}`, + ); + } + } + if (response.status === 429) { throw new ProdiaCapacityError( "Unable to schedule the job with current token.", ); } + if (response.status < 200 || response.status > 299) { + throw new ProdiaBadResponseError( + `${response.status} ${response.statusText}`, + ); + } + const body = await response.formData(); + const job = JSON.parse( new TextDecoder().decode( await (body.get("job") as Blob).arrayBuffer(), ), ) as ProdiaJob; + if ("error" in job && typeof job.error === "string") { throw new ProdiaUserError(job.error); } - if (response.status < 200 || response.status > 299) { - throw new ProdiaBadResponseError( - `${response.status} ${response.statusText}`, - ); - } - const buffer = await new Promise((resolve, reject) => { const output = body.get("output") as File; const reader = new FileReader();