createLegacyTables(); $this->coversDir = sys_get_temp_dir() . '/legacy-covers-test-' . bin2hex(random_bytes(4)); $filesystem = new Filesystem(); $filesystem->mkdir($this->coversDir . '/own'); $filesystem->remove(static::getContainer()->getParameter('kernel.project_dir') . '/var/test/covers'); } protected function tearDown(): void { new Filesystem()->remove($this->coversDir); parent::tearDown(); } public function testCoversArePickedByPreference(): void { $this->createBookWithIsbn(1, self::ISBN_A); $this->createBookWithIsbn(2, self::ISBN_B); $this->createBookWithIsbn(3, self::ISBN_C); $this->createBook(4); $generic = $this->createImage(self::ISBN_A); $this->createImage(self::ISBN_B); $this->createImage(self::ISBN_C); $ownByIsbn = $this->createImage('own/' . self::ISBN_B); $this->createImage('own/' . self::ISBN_C); $ownById = $this->createImage('own/00000003'); $this->createImage('own/00000004'); $tester = $this->runImport(['--covers' => $this->coversDir]); $tester->assertCommandIsSuccessful(); self::assertStringContainsString('4 covers imported', $tester->getDisplay()); self::assertFileEquals($generic, $this->originalOf(1)); self::assertFileEquals($ownByIsbn, $this->originalOf(2)); self::assertFileEquals($ownById, $this->originalOf(3)); self::assertNotNull($this->findBook(4)?->getCover()); self::assertFileExists($generic, 'The source files stay in place.'); } public function testOustedBooksGetCoversToo(): void { $book = new OustedBook('Zniszczona')->setId(7)->setTitle('T')->setAuthor('A')->setIsbn(self::ISBN_A); $this->entityManager()->persist($book); $this->entityManager()->flush(); $this->createImage(self::ISBN_A); $this->runImport(['--covers' => $this->coversDir])->assertCommandIsSuccessful(); $this->entityManager()->clear(); self::assertNotNull($this->entityManager()->find(OustedBook::class, 7)?->getCover()); } public function testUnreadableFilesGiveWayAndOddFilesAreReported(): void { $this->createBookWithIsbn(1, self::ISBN_A); $generic = $this->createImage(self::ISBN_A); $this->createImage(self::ISBN_B); $this->createImage('own/00000099'); file_put_contents($this->coversDir . '/notes.txt', 'x'); file_put_contents($this->coversDir . '/own/00000001', 'not an image'); $tester = $this->runImport(['--covers' => $this->coversDir]); $tester->assertCommandIsSuccessful(); self::assertFileEquals($generic, $this->originalOf(1)); $display = preg_replace('/\s+/', ' ', $tester->getDisplay()); self::assertStringContainsString('1 files could not be imported', $display); self::assertStringContainsString('own/00000001: Unsupported image type.', $display); self::assertStringContainsString('2 files match no book', $display); self::assertStringContainsString(self::ISBN_B, $display); self::assertStringContainsString('own/00000099', $display); self::assertStringContainsString('1 files are named neither', $display); self::assertStringContainsString('notes.txt', $display); } public function testBooksWithACoverKeepIt(): void { $this->createBookWithIsbn(1, self::ISBN_A); $this->createImage(self::ISBN_A); $this->runImport(['--covers' => $this->coversDir])->assertCommandIsSuccessful(); $cover = $this->findBook(1)?->getCover(); $this->createImage('own/00000001'); $tester = $this->runImport(['--covers' => $this->coversDir]); $tester->assertCommandIsSuccessful(); self::assertSame($cover, $this->findBook(1)?->getCover()); self::assertStringContainsString('0 covers imported', $tester->getDisplay()); } public function testDryRunStoresNothing(): void { $this->createBookWithIsbn(1, self::ISBN_A); $this->createImage(self::ISBN_A); $tester = $this->runImport(['--covers' => $this->coversDir, '--dry-run' => true]); $tester->assertCommandIsSuccessful(); self::assertNull($this->findBook(1)?->getCover()); $originals = static::getContainer()->getParameter('app.cover_originals_dir'); self::assertSame([], is_dir($originals) ? array_diff(scandir($originals), ['.', '..']) : []); } public function testMissingDirectoryFails(): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('is not a readable directory'); $this->runImport(['--covers' => $this->coversDir . '/missing']); } private function createBookWithIsbn(int $id, string $isbn): Book { $book = $this->createBook($id)->setIsbn($isbn); $this->entityManager()->flush(); return $book; } private function createImage(string $name): string { $path = $this->coversDir . '/' . $name; $image = imagecreatetruecolor(20, 30); // Random pixels make each generated file unique. imagesetpixel($image, 0, 0, random_int(1, 0xFFFFFF)); imagepng($image, $path); return $path; } private function originalOf(int $id): string { $cover = $this->findBook($id)?->getCover(); self::assertNotNull($cover); return static::getContainer()->get(CoverStorage::class)->originalPath($cover); } /** * @param array $input */ private function runImport(array $input): CommandTester { $application = new Application(static::$kernel); $tester = new CommandTester($application->find('app:import-legacy')); $tester->execute($input); return $tester; } }