isSubclassOf(ProviderInterface::class)); } #[Test] public function normalizesMimeTypesAndMatchesWildcards(): void { self::assertSame('image/jpeg', MimeType::normalize(' Image/JPEG; charset=binary ')); self::assertTrue(MimeType::matches('image/*', 'IMAGE/WEBP')); self::assertTrue(MimeType::matches('application/pdf', 'application/pdf')); self::assertFalse(MimeType::matches('image/*', 'application/pdf')); } #[Test] public function requestHasADeterministicNormalizedRepresentation(): void { $request = new PreviewRequest('popover', 640, 440, 'IMAGE/WEBP', 80, page: 1); self::assertSame([ 'variant' => 'popover', 'maxWidth' => 640, 'maxHeight' => 440, 'preferredMimeType' => 'image/webp', 'quality' => 80, 'page' => 1, 'timestamp' => null, ], $request->normalized()); } #[Test] public function sourceDoesNotOpenUntilRequested(): void { $opened = 0; $source = new PreviewSource( sourceType: 'document', identity: 'provider/service/entity', signature: 'revision-1', mimeType: 'image/jpeg', size: 7, resourceFactory: function () use (&$opened): BinaryResource { $opened++; return $this->resource('source'); }, ); self::assertSame(0, $opened); self::assertInstanceOf(BinaryResource::class, $source->open()); self::assertSame(1, $opened); } #[Test] public function sourceRejectsAnInvalidFactoryResult(): void { $source = new PreviewSource('document', 'entity', 'revision', 'image/jpeg', 1, fn() => 'invalid'); $this->expectException(PreviewException::class); $source->open(); } #[Test] public function resultUsesItsBinaryResourceMimeType(): void { $result = new PreviewResult($this->resource('preview'), 320, 200); self::assertSame('image/webp', $result->resource->mimeType()); self::assertSame(320, $result->width); self::assertSame(200, $result->height); } private function resource(string $content): BinaryResource { return new BinaryResource( 'preview.webp', 'image/webp', (function () use ($content): \Generator { yield $content; })(), ); } }