diff --git a/src/geometry/polygon.ts b/src/geometry/polygon.ts index 878a8e000..104a77cb8 100644 --- a/src/geometry/polygon.ts +++ b/src/geometry/polygon.ts @@ -47,6 +47,7 @@ export class Polygon extends Array { } toString(): string { - return this.map((point) => `(${point})`).join(", "); + const points = this.map((point) => `(${point})`).join(", "); + return `(${points})`; } } diff --git a/src/v2/parsing/inference/field/fieldLocation.ts b/src/v2/parsing/inference/field/fieldLocation.ts index dbb314af2..58f012f3e 100644 --- a/src/v2/parsing/inference/field/fieldLocation.ts +++ b/src/v2/parsing/inference/field/fieldLocation.ts @@ -2,21 +2,20 @@ import { Polygon } from "@/geometry/index.js"; import { StringDict } from "@/parsing/stringDict.js"; /** - * Location of a field. + * A field's location on the document. */ export class FieldLocation { - /** Free polygon made up of points (can be null when not provided). */ - readonly polygon: Polygon | null; - - /** Page ID. */ - readonly page: number | undefined; + /** Position information as a list of points in clockwise order. */ + readonly polygon: Polygon; + /** 0-based page index of where the polygon is located. */ + readonly page; constructor(serverResponse: StringDict) { - this.polygon = "polygon" in serverResponse ? new Polygon(...serverResponse["polygon"]) : null; - this.page = "page" in serverResponse ? serverResponse["page"] : undefined; + this.polygon = new Polygon(...serverResponse["polygon"]); + this.page = serverResponse["page"]; } toString(): string { - return this.polygon?.toString() ?? ""; + return `${this.polygon} on page ${this.page}`; } } diff --git a/src/v2/parsing/job/job.ts b/src/v2/parsing/job/job.ts index f1262428d..dce9d172c 100644 --- a/src/v2/parsing/job/job.ts +++ b/src/v2/parsing/job/job.ts @@ -16,9 +16,13 @@ export class Job { */ public error?: ErrorResponse; /** - * Timestamp of the job creation. + * Date and time of the Job creation. */ public createdAt: Date | null; + /** + * Date and time of the Job completion. Filled once processing is finished. + */ + public completedAt: Date | null | undefined; /** * ID of the model. */ @@ -53,19 +57,22 @@ export class Job { if (serverResponse["status"] !== undefined) { this.status = serverResponse["status"]; } - if ( - serverResponse["error"] !== undefined && - serverResponse["error"] !== null && - Object.keys(serverResponse["error"]).length > 0 - ) { + if (serverResponse["error"]) { this.error = new ErrorResponse(serverResponse["error"]); } this.createdAt = parseDate(serverResponse["created_at"]); + if (!serverResponse["completed_at"]) { + this.completedAt = undefined; + } else { + this.completedAt = parseDate(serverResponse["completed_at"]); + } this.modelId = serverResponse["model_id"]; this.pollingUrl = serverResponse["polling_url"]; this.filename = serverResponse["filename"]; this.resultUrl = serverResponse["result_url"]; this.alias = serverResponse["alias"]; - this.webhooks = serverResponse["webhooks"]; + this.webhooks = (serverResponse["webhooks"] ?? []).map( + (webhook: StringDict) => new JobWebhook(webhook) + ); } } diff --git a/src/v2/parsing/job/jobWebhook.ts b/src/v2/parsing/job/jobWebhook.ts index 48491e95a..9a19ec0b8 100644 --- a/src/v2/parsing/job/jobWebhook.ts +++ b/src/v2/parsing/job/jobWebhook.ts @@ -26,7 +26,7 @@ export class JobWebhook { this.id = serverResponse["id"]; this.createdAt = parseDate(serverResponse["created_at"]); this.status = serverResponse["status"]; - if (serverResponse["error"] !== undefined) { + if (serverResponse["error"]) { this.error = new ErrorResponse(serverResponse["error"]); } } diff --git a/src/v2/product/crop/cropItem.ts b/src/v2/product/crop/cropItem.ts index a36c37167..c49c38723 100644 --- a/src/v2/product/crop/cropItem.ts +++ b/src/v2/product/crop/cropItem.ts @@ -11,6 +11,6 @@ export class CropItem { } toString(): string { - return `${this.objectType}: ${this.location}`; + return `* :Location: ${this.location}\n :Object Type: ${this.objectType}`; } } diff --git a/src/v2/product/crop/cropResult.ts b/src/v2/product/crop/cropResult.ts index e15dc5278..9a0c527ac 100644 --- a/src/v2/product/crop/cropResult.ts +++ b/src/v2/product/crop/cropResult.ts @@ -12,7 +12,7 @@ export class CropResult { } toString(): string { - const crops = this.crops.map(item => item.toString()).join("\n * "); - return `Crop\n====\n * ${crops}`; + const crops = this.crops.map(item => item.toString()).join("\n"); + return `Crops\n=====\n${crops}`; } } diff --git a/tests/data b/tests/data index a4b3fbe94..c2e36f5b6 160000 --- a/tests/data +++ b/tests/data @@ -1 +1 @@ -Subproject commit a4b3fbe943ac2be84847e11f97538fd6d6e75b1d +Subproject commit c2e36f5b635386cb9bb922b517c4e02039b0a122 diff --git a/tests/v2/parsing/job.spec.ts b/tests/v2/parsing/job.spec.ts index 17da39162..31340f4d5 100644 --- a/tests/v2/parsing/job.spec.ts +++ b/tests/v2/parsing/job.spec.ts @@ -18,21 +18,43 @@ async function loadV2Job(resourcePath: string): Promise { } describe("MindeeV2 - Job Response", async () => { + describe("Success", async () => { it("should load when status is Processing", async () => { const response = await loadV2Job( path.join(jobPath, "ok_processing.json") ); assert.ok(response.job); + assert.strictEqual(response.job.status, "Processing"); + assert.ok(response.job.createdAt instanceof Date); + assert.strictEqual(response.job.completedAt, undefined); + assert.strictEqual(response.job.error, undefined); + }); + + it("should load when status is Processed", async () => { + const response = await loadV2Job( + path.join(jobPath, "ok_processed_webhooks_ok.json") + ); + assert.ok(response.job); + assert.strictEqual(response.job.status, "Processed"); + assert.ok(response.job.createdAt instanceof Date); + assert.ok(response.job.completedAt instanceof Date); assert.strictEqual(response.job.error, undefined); + response.job.webhooks.forEach((webhook) => { + assert.ok(webhook.id); + assert.ok(webhook.createdAt instanceof Date); + }); }); }); + describe("Failure", async () => { it("should load with 422 error", async () => { const response = await loadV2Job( path.join(jobPath, "fail_422.json") ); assert.ok(response.job); + assert.ok(response.job.createdAt instanceof Date); + assert.ok(response.job.completedAt instanceof Date); assert.ok(response.job.error instanceof ErrorResponse); assert.strictEqual(response.job.error?.status, 422); assert.ok(response.job.error?.code.startsWith("422-")); diff --git a/tests/v2/product/crop.spec.ts b/tests/v2/product/crop.spec.ts index eef9e7b5b..8063aad7a 100644 --- a/tests/v2/product/crop.spec.ts +++ b/tests/v2/product/crop.spec.ts @@ -47,6 +47,11 @@ describe("MindeeV2 - Crop Response", async () => { assert.strictEqual(polygon[2][1], 0.947); assert.strictEqual(polygon[3][0], 0.15); assert.strictEqual(polygon[3][1], 0.947); + + const rstString = await fs.readFile( + path.join(V2_PRODUCT_PATH, "crop", "crop_single.rst"), "utf8" + ); + assert.strictEqual(response.inference.toString(), rstString); }); it("should load multiple results", async () => { @@ -101,19 +106,10 @@ describe("MindeeV2 - Crop Response", async () => { assert.strictEqual(secondPolygon[2][1], 0.97); assert.strictEqual(secondPolygon[3][0], 0.547); assert.strictEqual(secondPolygon[3][1], 0.97); - }); - describe("RST Display", async () => { - it("to be properly exposed", async () => { - const response = await loadV2Response( - crop.CropResponse, - path.join(V2_PRODUCT_PATH, "crop", "crop_single.json") - ); - const rstString = await fs.readFile( - path.join(V2_PRODUCT_PATH, "crop", "crop_single.rst"), "utf8" - ); - assert.notStrictEqual(response.inference, null); - assert.strictEqual(response.inference.toString(), rstString); - }); + const rstString = await fs.readFile( + path.join(V2_PRODUCT_PATH, "crop", "crop_multiple.rst"), "utf8" + ); + assert.strictEqual(response.inference.toString(), rstString); }); });