driver('none'))->toBeInstanceOf(NoneProvider::class) ->and($manager->driver('klippa'))->toBeInstanceOf(KlippaProvider::class) ->and($manager->driver('mistral'))->toBeInstanceOf(MistralProvider::class) ->and($manager->driver())->toBeInstanceOf(NoneProvider::class); }); test('the none provider returns no suggestions', function () { expect((new NoneProvider)->analyze('/tmp/whatever.pdf', null))->toBe([]); }); test('providers return no suggestions without an api key', function () { Http::fake(); expect((new KlippaProvider)->analyze(__FILE__, null))->toBe([]) ->and((new MistralProvider)->analyze(__FILE__, ''))->toBe([]); Http::assertNothingSent(); }); test('the klippa provider maps parsed fields to suggestions', function () { Http::fake([ 'custom-ocr.klippa.com/*' => Http::response([ 'data' => ['parsed' => [ 'document_subject' => 'Forklift Licence', 'expiry_date' => '2027-05-01', ]], ]), ]); $file = tempnam(sys_get_temp_dir(), 'ocr').'.pdf'; file_put_contents($file, 'dummy'); $result = (new KlippaProvider)->analyze($file, 'test-key'); expect($result)->toBe(['title' => 'Forklift Licence', 'expires_at' => '2027-05-01']); @unlink($file); }); test('the mistral provider parses json content from a vision response', function () { Http::fake([ 'api.mistral.ai/*' => Http::response([ 'choices' => [[ 'message' => ['content' => '{"title":"First Aid","expires_at":"2026-12-31"}'], ]], ]), ]); $file = tempnam(sys_get_temp_dir(), 'ocr').'.png'; // Minimal 1x1 PNG so mime detection reports an image. file_put_contents($file, base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==')); $result = (new MistralProvider)->analyze($file, 'test-key'); expect($result)->toBe(['title' => 'First Aid', 'expires_at' => '2026-12-31']); @unlink($file); }); test('the mistral provider skips non-image files', function () { Http::fake(); $file = tempnam(sys_get_temp_dir(), 'ocr').'.pdf'; file_put_contents($file, '%PDF-1.4 dummy'); expect((new MistralProvider)->analyze($file, 'test-key'))->toBe([]); Http::assertNothingSent(); @unlink($file); });