<?php
|
declare(strict_types=1);
|
|
namespace App\Tests\Functional;
|
|
use App\Entity\OustedBook;
|
use App\Tests\DatabaseTestCase;
|
use Symfony\Component\DomCrawler\Crawler;
|
|
final class BulkOustTest extends DatabaseTestCase {
|
protected function setUp(): void {
|
parent::setUp();
|
|
$this->createBook(1, 'Never seen');
|
$this->createBook(2, 'Seen long ago')->setLastSeen(new \DateTimeImmutable('2026-01-10 12:00'));
|
$this->createBook(3, 'Seen on the day')->setLastSeen(new \DateTimeImmutable('2026-11-01 00:00'));
|
$this->createBook(4, 'Seen later')->setLastSeen(new \DateTimeImmutable('2026-11-05 18:00'));
|
$this->createBook(5, 'Lent out')->lendTo('A Reader', new \DateTimeImmutable('2026-01-01'));
|
$this->entityManager()->flush();
|
}
|
|
public function testPreviewListsBooksNotSeenSinceTheDate(): void {
|
$crawler = $this->preview('2026-11-01');
|
|
self::assertResponseIsSuccessful();
|
self::assertSame([1, 2], $crawler->filter('.results .tile .label-primary')->each(static fn($node): int => (int)$node->text()));
|
self::assertSelectorTextContains('.bulk-oust-confirm', '2 books were not seen on or after 2026-11-01');
|
self::assertSelectorTextContains('.bulk-oust-borrowed', '1 borrowed books');
|
self::assertNotNull($this->findBook(1));
|
}
|
|
public function testConfirmingOustsTheListedBooks(): void {
|
$crawler = $this->preview('2026-11-01');
|
$this->client->submit($crawler->selectButton('Take them all out')->form());
|
|
self::assertResponseRedirects('/ousted');
|
$this->client->followRedirect();
|
self::assertSelectorTextContains('.flash', '2 books have been taken out');
|
|
self::assertNull($this->findBook(1));
|
self::assertNull($this->findBook(2));
|
self::assertNotNull($this->findBook(3));
|
self::assertNotNull($this->findBook(4));
|
self::assertNotNull($this->findBook(5));
|
self::assertSame('Inventory 2026', $this->entityManager()->find(OustedBook::class, 2)?->getReason());
|
}
|
|
public function testNothingIsOustedIfTheSelectionChanged(): void {
|
$crawler = $this->preview('2026-11-01');
|
$form = $crawler->selectButton('Take them all out')->form();
|
|
// One book found and another added: the count stays the same, the books do not.
|
$this->findBook(2)?->setLastSeen(new \DateTimeImmutable('2026-11-02'));
|
$this->entityManager()->flush();
|
$this->createBook(6, 'Added meanwhile');
|
$this->client->submit($form);
|
|
self::assertResponseRedirects();
|
$this->client->followRedirect();
|
self::assertSelectorTextContains('.flash', 'has changed');
|
self::assertNotNull($this->findBook(1));
|
self::assertNotNull($this->findBook(6));
|
}
|
|
public function testConfirmationRequiresAValidCsrfToken(): void {
|
$this->client->request('POST', '/ousted/bulk', ['bulk_oust' => [
|
'notSeenSince' => '2026-11-01',
|
'reason' => 'Forged',
|
'selection' => 'anything',
|
'_token' => 'forged',
|
]]);
|
|
self::assertResponseRedirects('/ousted/bulk');
|
self::assertNotNull($this->findBook(1));
|
}
|
|
public function testPreviewWithNothingToOust(): void {
|
$this->findBook(1)?->setLastSeen(new \DateTimeImmutable('2026-03-01'));
|
$this->entityManager()->flush();
|
|
$this->preview('2026-01-01');
|
|
self::assertSelectorTextContains('.toast-success', 'Every book on the shelves was seen');
|
self::assertSelectorNotExists('.bulk-oust-confirm');
|
}
|
|
private function preview(string $date): Crawler {
|
$crawler = $this->client->request('GET', '/ousted/bulk');
|
|
return $this->client->submit($crawler->selectButton('Show the books')->form([
|
'bulk_oust[notSeenSince]' => $date,
|
'bulk_oust[reason]' => 'Inventory 2026',
|
]));
|
}
|
}
|