Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions src/Parsing/V2/Inference.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@
*/
class Inference
{
/**
* @var string ID of the inference.
*/
public string $id;

/**
* @var InferenceJob Job the inference belongs to.
*/
public InferenceJob $job;

/**
* @var InferenceModel Model info for the inference.
*/
Expand All @@ -27,21 +37,17 @@ class Inference
*/
public InferenceResult $result;

/**
* @var string|null ID of the inference.
*/
public ?string $id;

/**
* @param array $serverResponse Raw server response array.
*/
public function __construct(array $serverResponse)
{
$this->id = $serverResponse['id'];
$this->job = new InferenceJob($serverResponse['job']);
$this->model = new InferenceModel($serverResponse['model']);
$this->file = new InferenceFile($serverResponse['file']);
$this->activeOptions = new InferenceActiveOptions($serverResponse['active_options']);
$this->result = new InferenceResult($serverResponse['result']);
$this->id = $serverResponse['id'] ?? null;
}

/**
Expand All @@ -50,6 +56,7 @@ public function __construct(array $serverResponse)
public function __toString(): string
{
return "Inference\n#########\n"
. "{$this->job}\n"
. "{$this->model}\n"
. "{$this->file}\n"
. "{$this->activeOptions}\n"
Expand Down
31 changes: 31 additions & 0 deletions src/Parsing/V2/InferenceJob.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace Mindee\Parsing\V2;

/**
* Information on the Job associated to a given Inference.
*/
class InferenceJob
{
/**
* @var string UUID of the job.
*/
public string $id;

/**
* @param array $serverResponse Raw server response array.
*/
public function __construct(array $serverResponse)
{
$this->id = $serverResponse['id'];
}

/**
* @return string String representation.
*/
public function __toString(): string
{
return "Job\n===\n"
. ":ID: {$this->id}\n" ;
}
}
14 changes: 10 additions & 4 deletions src/Parsing/V2/Job.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,14 @@ class Job
public ?ErrorResponse $error;

/**
* @var DateTime|null Timestamp of the job creation.
* @var DateTime Date and time of the Job creation.
*/
public ?DateTime $createdAt;
public DateTime $createdAt;

/**
* @var DateTime|null Date and time of the Job completion. Filled once processing is finished.
*/
public ?DateTime $completedAt;

/**
* @var string ID of the model.
Expand Down Expand Up @@ -76,8 +81,9 @@ public function __construct(array $serverResponse)
$this->error = new ErrorResponse($serverResponse['error']);
}

$this->createdAt = isset($serverResponse['created_at'])
? $this->parseDate($serverResponse['created_at'])
$this->createdAt = $this->parseDate($serverResponse['created_at']);
$this->completedAt = isset($serverResponse['completed_at'])
? $this->parseDate($serverResponse['completed_at'])
: null;

$this->modelId = $serverResponse['model_id'];
Expand Down
8 changes: 8 additions & 0 deletions tests/TestingUtilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ public static function getV2DataDir(): string
return TestingUtilities::getRootDataDir() . "/v2";
}

/**
* @return string Return the root of the v2 products directory.
*/
public static function getV2ProductDir(): string
{
return TestingUtilities::getV2DataDir() . "/products";
}

/**
* @return string Return the root of the file types directory.
*/
Expand Down
51 changes: 30 additions & 21 deletions tests/V2/Parsing/InferenceResponseTest.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace V2\parsing;
namespace V2\Parsing;

use Mindee\Error\ErrorItem;
use Mindee\Geometry\Point;
Expand All @@ -24,7 +24,7 @@ class InferenceResponseTest extends TestCase
{
private function loadFromResource(string $resourcePath): InferenceResponse
{
$fullPath = TestingUtilities::getRootDataDir() . "/$resourcePath";
$fullPath = TestingUtilities::getV2ProductDir() . "/$resourcePath";
$this->assertFileExists($fullPath, "Resource file must exist: $resourcePath");

$localResponse = new LocalResponse($fullPath);
Expand All @@ -39,11 +39,12 @@ private function readFileAsString(string $path): string
}

/**
* When the async prediction is blank - all properties must be valid
* When the async prediction is blank - all properties must be valid.
* @return void
*/
public function testAsyncPredictWhenEmptyMustHaveValidProperties(): void
{
$response = $this->loadFromResource('v2/products/extraction/financial_document/blank.json');
$response = $this->loadFromResource('extraction/financial_document/blank.json');
$fields = $response->inference->result->fields;

$this->assertCount(21, $fields, 'Expected 21 fields');
Expand Down Expand Up @@ -91,11 +92,12 @@ public function testAsyncPredictWhenEmptyMustHaveValidProperties(): void
}

/**
* When the async prediction is complete - every exposed property must be valid and consistent
* When the async prediction is complete - every exposed property must be valid and consistent.
* @return void
*/
public function testAsyncPredictWhenCompleteMustExposeAllProperties(): void
{
$response = $this->loadFromResource('v2/products/extraction/financial_document/complete.json');
$response = $this->loadFromResource('extraction/financial_document/complete.json');
$inference = $response->inference;

$this->assertNotNull($inference, 'Inference must not be null');
Expand Down Expand Up @@ -154,11 +156,12 @@ public function testAsyncPredictWhenCompleteMustExposeAllProperties(): void
}

/**
* Deep nested fields - all nested structures must be typed correctly
* Deep nested fields - all nested structures must be typed correctly.
* @return void
*/
public function testDeepNestedFieldsMustExposeCorrectTypes(): void
{
$response = $this->loadFromResource('v2/products/extraction/deep_nested_fields.json');
$response = $this->loadFromResource('extraction/deep_nested_fields.json');
$inference = $response->inference;
$this->assertNotNull($inference);

Expand Down Expand Up @@ -198,11 +201,12 @@ public function testDeepNestedFieldsMustExposeCorrectTypes(): void
}

/**
* Standard field types - simple / object / list variants must be recognised
* Standard field types - simple / object / list variants must be recognised.
* @return void
*/
public function testStandardFieldTypesMustExposeCorrectTypes(): void
{
$response = $this->loadFromResource('v2/products/extraction/standard_field_types.json');
$response = $this->loadFromResource('extraction/standard_field_types.json');
$inference = $response->inference;
$this->assertNotNull($inference);

Expand Down Expand Up @@ -279,11 +283,12 @@ public function testStandardFieldTypesMustExposeCorrectTypes(): void
}

/**
* Raw texts option must be parsed and exposed
* Raw texts option must be parsed and exposed.
* @return void
*/
public function testRawTextsMustBeAccessible(): void
{
$response = $this->loadFromResource('v2/products/extraction/raw_texts.json');
$response = $this->loadFromResource('extraction/raw_texts.json');
$inference = $response->inference;
$this->assertNotNull($inference);

Expand All @@ -306,13 +311,14 @@ public function testRawTextsMustBeAccessible(): void
}

/**
* RST display must be parsed and exposed
* RST display must be parsed and exposed.
* @return void
*/
public function testRstDisplayMustBeAccessible(): void
{
$response = $this->loadFromResource('v2/products/extraction/standard_field_types.json');
$response = $this->loadFromResource('extraction/standard_field_types.json');
$expectedRst = $this->readFileAsString(
\TestingUtilities::getV2DataDir() . '/products/extraction/standard_field_types.rst'
\TestingUtilities::getV2ProductDir() . '/extraction/standard_field_types.rst'
);
$inference = $response->inference;
$this->assertNotNull($inference);
Expand All @@ -321,10 +327,11 @@ public function testRstDisplayMustBeAccessible(): void

/**
* Coordinates & location data must be parsed and exposed.
* @return void
*/
public function testCoordinatesAndLocationDataMustBeAccessible(): void
{
$response = $this->loadFromResource('v2/products/extraction/financial_document/complete_with_coordinates.json');
$response = $this->loadFromResource('extraction/financial_document/complete_with_coordinates.json');
$inference = $response->inference;
$this->assertNotNull($inference);

Expand Down Expand Up @@ -383,23 +390,25 @@ public function testCoordinatesAndLocationDataMustBeAccessible(): void

public function testRagMetadataWhenMatched()
{
$response = $this->loadFromResource('v2/products/extraction/rag_matched.json');
$response = $this->loadFromResource('extraction/rag_matched.json');
$inference = $response->inference;
$this->assertNotNull($inference);
$this->assertEquals('12345abc-1234-1234-1234-123456789abc', $inference->result->rag->retrievedDocumentId);
}

public function testRagMetadataWhenNotMatched()
{
$response = $this->loadFromResource('v2/products/extraction/rag_not_matched.json');
$response = $this->loadFromResource('extraction/rag_not_matched.json');
$inference = $response->inference;
$this->assertNotNull($inference);
$this->assertNull($inference->result->rag->retrievedDocumentId);
}

public function testShouldLoadWith422Error()
{
$jsonResponse = json_decode(file_get_contents(\TestingUtilities::getV2DataDir() . '/job/fail_422.json'), true);
$jsonResponse = json_decode(
file_get_contents(\TestingUtilities::getV2DataDir() . '/job/fail_422.json'), true
);
$response = new JobResponse($jsonResponse);
$this->assertNotNull($response->job);
$this->assertInstanceOf(ErrorResponse::class, $response->job->error);
Expand All @@ -411,7 +420,7 @@ public function testShouldLoadWith422Error()

public function testTextContextIsTrue(): void
{
$response = $this->loadFromResource('v2/products/extraction/text_context_enabled.json');
$response = $this->loadFromResource('extraction/text_context_enabled.json');
$inference = $response->inference;
$this->assertNotNull($inference);
$activeOptions = $inference->activeOptions;
Expand All @@ -424,7 +433,7 @@ public function testTextContextIsTrue(): void

public function testTextContextIsFalse(): void
{
$response = $this->loadFromResource('v2/products/extraction/financial_document/complete.json');
$response = $this->loadFromResource('extraction/financial_document/complete.json');
$inference = $response->inference;
$this->assertNotNull($inference);
$activeOptions = $inference->activeOptions;
Expand Down
78 changes: 78 additions & 0 deletions tests/V2/Parsing/JobResponseTest.php
Original file line number Diff line number Diff line change
@@ -1 +1,79 @@
<?php

namespace V2\Parsing;

use DateTime;
use Mindee\Error\ErrorItem;
use Mindee\Parsing\V2\ErrorResponse;
use Mindee\Parsing\V2\JobResponse;
use PHPUnit\Framework\TestCase;
use TestingUtilities;

require_once(__DIR__ . "/../../TestingUtilities.php");

class TestJobResponse extends TestCase
{
/**
* Load a job sample JSON file and return its decoded contents.
*
* @param string $jsonFile Name of the JSON file to load.
* @return array Decoded JSON data.
*/
private static function getJobSamples(string $jsonFile): array
{
$fullPath = TestingUtilities::getV2DataDir() . "/job/$jsonFile";
$content = file_get_contents($fullPath);
return json_decode($content, true);
}

/**
* Should load when status is Processing.
* @return void
*/
public function testShouldLoadWhenStatusIsProcessing(): void
{
$jsonSample = self::getJobSamples('ok_processing.json');
$response = new JobResponse($jsonSample);

$this->assertNotNull($response->job);
$this->assertSame('Processing', $response->job->status);
$this->assertNull($response->job->completedAt);
$this->assertNull($response->job->error);
}

/**
* Should load when status is Processed.
* @return void
*/
public function testShouldLoadWhenStatusIsProcessed(): void
{
$jsonSample = self::getJobSamples('ok_processed_webhooks_ok.json');
$response = new JobResponse($jsonSample);

$this->assertNotNull($response->job);
$this->assertSame('Processed', $response->job->status);
$this->assertInstanceOf(DateTime::class, $response->job->completedAt);
$this->assertNull($response->job->error);
}

/**
* Should load with 422 error.
* @return void
*/
public function testShouldLoadWith422Error(): void
{
$jsonSample = self::getJobSamples('fail_422.json');
$response = new JobResponse($jsonSample);

$this->assertNotNull($response->job);
$this->assertSame('Failed', $response->job->status);
$this->assertInstanceOf(DateTime::class, $response->job->completedAt);

$this->assertInstanceOf(ErrorResponse::class, $response->job->error);
$this->assertSame(422, $response->job->error->status);
$this->assertStringStartsWith('422-', $response->job->error->code);
$this->assertIsArray($response->job->error->errors);
$this->assertCount(1, $response->job->error->errors);
$this->assertInstanceOf(ErrorItem::class, $response->job->error->errors[0]);
}
}