<?php
|
declare(strict_types=1);
|
|
namespace App\Tests\Functional;
|
|
use App\Entity\Book;
|
use App\Entity\OustedBook;
|
use App\Tests\DatabaseTestCase;
|
use App\Tests\LegacyDatabase;
|
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
use Symfony\Component\Console\Command\Command;
|
use Symfony\Component\Console\Tester\CommandTester;
|
|
final class ImportLegacyCommandTest extends DatabaseTestCase {
|
use LegacyDatabase;
|
|
protected function setUp(): void {
|
parent::setUp();
|
|
$this->createLegacyTables();
|
}
|
|
public function testImportMapsBooks(): void {
|
$this->addLegacyBook(['id' => 0, 'tytul' => 'Zerowa', 'autor' => 'A', 'jezyk' => 'polski', 'rok' => 2005, 'miejsce' => 'Wrocław', 'wydawnictwo' => 'W', 'wydanie' => '2', 'ISBN' => '9788373843455', 'regal' => 'HOL', 'polka' => '4', 'rzad' => '1']);
|
$this->addLegacyBook(['id' => 1, 'tytul' => 'Bez danych', 'autor' => 'B', 'jezyk' => '', 'rok' => 0]);
|
$this->addLegacyBook(['id' => 2, 'tytul' => 'Częściowa lokalizacja', 'autor' => 'C', 'jezyk' => 'eng', 'regal' => 'K', 'ISBN' => '306406152', 'ISSN' => '3161234']);
|
$this->addLegacyBook(['id' => 3, 'tytul' => 'Wycofana', 'autor' => 'D', 'jezyk' => 'polski', 'regal' => 'JK', 'polka' => '1', 'ISBN' => '9788303001795', 'wycofana' => '1', 'powod' => 'Zniszczona']);
|
|
$tester = $this->runImport();
|
|
$tester->assertCommandIsSuccessful();
|
$this->entityManager()->clear();
|
|
$full = $this->findBook(0);
|
self::assertSame('Zerowa', $full?->getTitle());
|
self::assertSame('polski', $full?->getLanguage());
|
self::assertSame(2005, $full?->getPublicationYear());
|
self::assertSame('9788373843455', $full?->getIsbn());
|
self::assertSame('HOL/4/1', $full?->getPlacement());
|
|
$sparse = $this->findBook(1);
|
self::assertNull($sparse?->getLanguage());
|
self::assertNull($sparse?->getPublicationYear());
|
self::assertNull($sparse?->getPlacement());
|
|
$partial = $this->findBook(2);
|
self::assertSame('K', $partial?->getPlacement());
|
self::assertSame('9780306406157', $partial?->getIsbn());
|
self::assertSame('03161234', $partial?->getIssn());
|
|
$ousted = $this->entityManager()->find(OustedBook::class, 3);
|
self::assertSame('Zniszczona', $ousted?->getReason());
|
self::assertSame('JK/1', $ousted?->getPlacement());
|
self::assertSame('9788303001795', $ousted?->getIsbn());
|
self::assertNull($this->findBook(3));
|
}
|
|
public function testInvalidIsbnIsKeptAsATextLabel(): void {
|
$this->addLegacyBook(['id' => 1, 'tytul' => 'Zły numer', 'autor' => 'A', 'jezyk' => 'polski', 'ISBN' => '9788373843456']);
|
|
$tester = $this->runImport();
|
|
$tester->assertCommandIsSuccessful();
|
self::assertStringContainsString('book 1: 9788373843456', $tester->getDisplay());
|
$book = $this->findBook(1);
|
self::assertNull($book?->getIsbn());
|
self::assertSame('9788373843456', $book?->getTextLabels()[0]->getLabel());
|
}
|
|
public function testImportedBooksAreSearchable(): void {
|
$this->addLegacyBook(['id' => 1, 'tytul' => 'Łódź', 'autor' => 'A', 'jezyk' => 'polski']);
|
|
$this->runImport();
|
|
$crawler = $this->client->request('GET', '/search', ['q' => 'Łódź']);
|
self::assertCount(1, $crawler->filter('.tile'));
|
}
|
|
public function testImportMapsLoans(): void {
|
$this->addLegacyBook(['id' => 1, 'tytul' => 'Na półce', 'autor' => 'A', 'jezyk' => 'polski']);
|
$this->addLegacyBook(['id' => 2, 'tytul' => 'Wycofana', 'autor' => 'B', 'jezyk' => 'polski', 'wycofana' => '1', 'powod' => 'Prezent']);
|
$this->legacy->insert('pozycz', ['id' => 1, 'kto' => 'Osoba A', 'od' => 1556909792]);
|
$this->legacy->insert('pozycz_historia', ['id' => 1, 'kto' => 'Osoba B', 'od' => 1212076475, '"do"' => 1212176475]);
|
$this->legacy->insert('pozycz_historia', ['id' => 2, 'kto' => 'Osoba C', 'od' => 1212076475, '"do"' => 1212176475]);
|
|
$tester = $this->runImport();
|
$tester->assertCommandIsSuccessful();
|
|
$book = $this->findBook(1);
|
self::assertSame('Osoba A', $book?->getBorrow()?->getWho());
|
self::assertSame(1556909792, $book?->getBorrow()?->getAt()->getTimestamp());
|
|
$entry = $book?->getBorrowHistory()->first();
|
self::assertSame('Osoba B', $entry->getWho());
|
self::assertSame(1212176475, $entry->getTill()->getTimestamp());
|
|
self::assertCount(1, $this->entityManager()->find(OustedBook::class, 2)?->getBorrowHistory() ?? []);
|
self::assertStringNotContainsString('left out', $tester->getDisplay());
|
}
|
|
public function testRowsWithoutAPlaceInTheNewSchemaAreReported(): void {
|
$this->addLegacyBook(['id' => 1, 'tytul' => 'Dwa razy', 'autor' => 'A', 'jezyk' => 'polski']);
|
$this->addLegacyBook(['id' => 2, 'tytul' => 'Wycofana', 'autor' => 'B', 'jezyk' => 'polski', 'wycofana' => '1', 'powod' => 'Prezent']);
|
$this->legacy->insert('pozycz', ['id' => 1, 'kto' => 'Starsze', 'od' => 1000]);
|
$this->legacy->insert('pozycz', ['id' => 1, 'kto' => 'Nowsze', 'od' => 2000]);
|
$this->legacy->insert('pozycz', ['id' => 2, 'kto' => 'Osoba', 'od' => 1000]);
|
$this->legacy->insert('pozycz', ['id' => 99, 'kto' => 'Osoba', 'od' => 1000]);
|
$this->legacy->insert('pozycz_historia', ['id' => 99, 'kto' => 'Osoba', 'od' => 1000, '"do"' => 2000]);
|
$this->legacy->insert('pozycz_historia', ['id' => 1, 'kto' => 'Osoba', 'od' => 1000, '"do"' => null]);
|
|
$tester = $this->runImport();
|
|
$tester->assertCommandIsSuccessful();
|
self::assertSame('Nowsze', $this->findBook(1)?->getBorrow()?->getWho());
|
|
$display = preg_replace('/\s+/', ' ', $tester->getDisplay());
|
self::assertStringContainsString('5 rows were left out', $display);
|
self::assertStringContainsString('book 1 has more than one open loan', $display);
|
self::assertStringContainsString('book 2 is on loan but ousted', $display);
|
self::assertStringContainsString('pozycz: book 99 does not exist', $display);
|
self::assertStringContainsString('pozycz_historia: book 99 does not exist', $display);
|
self::assertStringContainsString('has no end date', $display);
|
}
|
|
public function testDryRunSavesNothing(): void {
|
$this->addLegacyBook(['id' => 1, 'tytul' => 'Książka', 'autor' => 'A', 'jezyk' => 'polski']);
|
|
$tester = $this->runImport(['--dry-run' => true]);
|
|
$tester->assertCommandIsSuccessful();
|
self::assertStringContainsString('nothing was saved', $tester->getDisplay());
|
self::assertSame(0, $this->entityManager()->getRepository(Book::class)->count());
|
}
|
|
public function testImportKeepsBooksAlreadyInTheTarget(): void {
|
$this->createBook(1, 'Edited title');
|
$ousted = new OustedBook('Lost')->setId(2)->setTitle('Ousted since')->setAuthor('B');
|
$this->entityManager()->persist($ousted);
|
$this->entityManager()->flush();
|
$this->addLegacyBook(['id' => 1, 'tytul' => 'Legacy title', 'autor' => 'A', 'jezyk' => 'polski']);
|
$this->addLegacyBook(['id' => 2, 'tytul' => 'Na półce', 'autor' => 'B', 'jezyk' => 'polski']);
|
$this->addLegacyBook(['id' => 3, 'tytul' => 'Nowa', 'autor' => 'C', 'jezyk' => 'polski']);
|
$this->legacy->insert('pozycz', ['id' => 1, 'kto' => 'Osoba A', 'od' => 1000]);
|
$this->legacy->insert('pozycz_historia', ['id' => 2, 'kto' => 'Osoba B', 'od' => 1000, '"do"' => 2000]);
|
|
$tester = $this->runImport();
|
|
$tester->assertCommandIsSuccessful();
|
$book = $this->findBook(1);
|
self::assertSame('Edited title', $book?->getTitle());
|
self::assertNull($book?->getBorrow());
|
self::assertNull($this->findBook(2));
|
self::assertCount(0, $this->entityManager()->find(OustedBook::class, 2)?->getBorrowHistory() ?? [1]);
|
self::assertSame('Nowa', $this->findBook(3)?->getTitle());
|
self::assertMatchesRegularExpression('/already in target, kept\s+2/', $tester->getDisplay());
|
self::assertStringNotContainsString('left out', $tester->getDisplay());
|
}
|
|
public function testRunningTheImportTwiceChangesNothing(): void {
|
$this->addLegacyBook(['id' => 1, 'tytul' => 'Książka', 'autor' => 'A', 'jezyk' => 'polski', 'ISBN' => '9788373843456']);
|
$this->addLegacyBook(['id' => 2, 'tytul' => 'Wycofana', 'autor' => 'B', 'jezyk' => 'polski', 'wycofana' => '1', 'powod' => 'Prezent']);
|
$this->legacy->insert('pozycz', ['id' => 1, 'kto' => 'Osoba A', 'od' => 2000]);
|
$this->legacy->insert('pozycz_historia', ['id' => 1, 'kto' => 'Osoba B', 'od' => 1000, '"do"' => 1500]);
|
$this->legacy->insert('pozycz_historia', ['id' => 2, 'kto' => 'Osoba C', 'od' => 1000, '"do"' => 1500]);
|
$this->runImport()->assertCommandIsSuccessful();
|
|
$tester = $this->runImport();
|
|
$tester->assertCommandIsSuccessful();
|
self::assertSame(1, $this->entityManager()->getRepository(Book::class)->count());
|
self::assertSame(1, $this->entityManager()->getRepository(OustedBook::class)->count());
|
$book = $this->findBook(1);
|
self::assertSame('Osoba A', $book?->getBorrow()?->getWho());
|
self::assertCount(1, $book?->getBorrowHistory() ?? []);
|
self::assertCount(1, $book?->getTextLabels() ?? []);
|
self::assertCount(1, $this->entityManager()->find(OustedBook::class, 2)?->getBorrowHistory() ?? []);
|
self::assertMatchesRegularExpression('/already in target, kept\s+2/', $tester->getDisplay());
|
}
|
|
public function testFailureLeavesTheTargetUntouched(): void {
|
$this->addLegacyBook(['id' => 1, 'tytul' => 'Książka', 'autor' => 'A', 'jezyk' => 'polski']);
|
$this->legacy->executeStatement('ALTER TABLE pozycz RENAME TO pozycz_missing');
|
|
try {
|
$this->runImport();
|
self::fail('The import should have failed.');
|
} catch (\Doctrine\DBAL\Exception) {
|
self::assertSame(0, $this->entityManager()->getRepository(Book::class)->count());
|
}
|
}
|
|
/**
|
* @param array<string, mixed> $row
|
*/
|
private function addLegacyBook(array $row): void {
|
$this->legacy->insert('ksiazki', $row);
|
}
|
|
/**
|
* @param array<string, mixed> $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;
|
}
|
}
|