*/ private array $requestedUrls = []; /** @var array{mixed, mixed} the key in $_ENV and $_SERVER before the test */ private array $previousKey; protected function setUp(): void { parent::setUp(); $this->previousKey = [$_ENV['LIBRARYTHING_API_KEY'] ?? null, $_SERVER['LIBRARYTHING_API_KEY'] ?? null]; new Filesystem()->remove(static::getContainer()->getParameter('kernel.project_dir') . '/var/test/covers'); } protected function tearDown(): void { [$_ENV['LIBRARYTHING_API_KEY'], $_SERVER['LIBRARYTHING_API_KEY']] = $this->previousKey; parent::tearDown(); } public function testNewBookGetsTheLibraryThingCover(): void { $image = self::png(120, 180); $this->mockLibraryThing('secret-key', new MockResponse($image, ['response_headers' => ['content-type' => 'image/png']])); $this->addBook(self::ISBN); self::assertSame(['https://covers.librarything.com/devkey/secret-key/large/isbn/' . self::ISBN], $this->requestedUrls); $cover = $this->findBook(5)?->getCover(); self::assertNotNull($cover); self::assertStringEqualsFile(static::getContainer()->get(CoverStorage::class)->originalPath($cover), $image); $this->client->followRedirect(); self::assertAnySelectorTextContains('.flash', 'downloaded from LibraryThing'); } public function testPlaceholderMeansNoCover(): void { $this->mockLibraryThing('secret-key', new MockResponse(self::png(1, 1))); $this->addBook(self::ISBN); self::assertCount(1, $this->requestedUrls); self::assertNull($this->findBook(5)?->getCover()); } public function testFailedDownloadStillSavesTheBook(): void { $this->mockLibraryThing('secret-key', new MockResponse('', ['http_code' => 503])); $this->addBook(self::ISBN); self::assertResponseRedirects('/book/5'); self::assertNull($this->findBook(5)?->getCover()); } public function testNothingIsRequestedWithoutAKey(): void { $this->mockLibraryThing('', new MockResponse(self::png(120, 180))); $this->addBook(self::ISBN); self::assertSame([], $this->requestedUrls); self::assertNull($this->findBook(5)?->getCover()); } public function testNothingIsRequestedWithoutAnIsbn(): void { $this->mockLibraryThing('secret-key', new MockResponse(self::png(120, 180))); $this->addBook(''); self::assertSame([], $this->requestedUrls); } private function mockLibraryThing(string $key, MockResponse $response): void { $_ENV['LIBRARYTHING_API_KEY'] = $_SERVER['LIBRARYTHING_API_KEY'] = $key; // A reboot between the form and its submission would drop the mock. $this->client->disableReboot(); static::getContainer()->set('librarything.client', new MockHttpClient( function (string $method, string $url) use ($response): MockResponse { $this->requestedUrls[] = $url; return $response; }, 'https://covers.librarything.com', )); } private function addBook(string $isbn): void { $crawler = $this->client->request('GET', '/add/form?id=5'); $form = $crawler->selectButton('Save')->form(); $form['book[title]'] = 'Title'; $form['book[author]'] = 'Author'; $form['book[isbn]'] = $isbn; $this->client->submit($form); } private static function png(int $width, int $height): string { $image = imagecreatetruecolor($width, $height); ob_start(); imagepng($image); return (string)ob_get_clean(); } }