+
- back to list
+
+ known menuitems
+
+ {% for item in food_vendor.menuItems %}
+
+ {{ item.name }}
+ {% if(item.aliasOf) %}
+ (alias of: {{ item.aliasOf.name }})
+ {% endif %}
+
+ {% endfor %}
+
+
- edit
+
{% endblock %}
diff --git a/templates/menu_item/_delete_form.html.twig b/templates/menu_item/_delete_form.html.twig
new file mode 100644
index 0000000..1a820c8
--- /dev/null
+++ b/templates/menu_item/_delete_form.html.twig
@@ -0,0 +1,4 @@
+
diff --git a/templates/menu_item/_form.html.twig b/templates/menu_item/_form.html.twig
new file mode 100644
index 0000000..e0ed7ee
--- /dev/null
+++ b/templates/menu_item/_form.html.twig
@@ -0,0 +1,4 @@
+{{ form_start(form, {'attr': {'class': 'mb-3'}}) }}
+ {{ form_widget(form, {'attr': {'class': 'form-control'}}) }}
+ {{ button_label|default('Save') }}
+{{ form_end(form) }}
diff --git a/templates/menu_item/edit.html.twig b/templates/menu_item/edit.html.twig
new file mode 100644
index 0000000..c1c755e
--- /dev/null
+++ b/templates/menu_item/edit.html.twig
@@ -0,0 +1,15 @@
+{% extends 'base.html.twig' %}
+
+{% block title %}Edit MenuItem{% endblock %}
+
+{% block body %}
+ Edit MenuItem
+
+
+ {{ include('menu_item/_form.html.twig', {'button_label': 'Update'}) }}
+
+
+
+ {{ include('menu_item/_delete_form.html.twig') }}
+
+{% endblock %}
diff --git a/templates/menu_item/index.html.twig b/templates/menu_item/index.html.twig
new file mode 100644
index 0000000..26cb0a4
--- /dev/null
+++ b/templates/menu_item/index.html.twig
@@ -0,0 +1,35 @@
+{% extends 'base.html.twig' %}
+
+{% block title %}MenuItem index{% endblock %}
+
+{% block body %}
+ MenuItem index
+
+
+
+
+ Id
+ Name
+ actions
+
+
+
+ {% for menu_item in menu_items %}
+
+ {{ menu_item.id }}
+ {{ menu_item.name }}
+
+ show
+ edit
+
+
+ {% else %}
+
+ no records found
+
+ {% endfor %}
+
+
+
+ Create new
+{% endblock %}
diff --git a/templates/menu_item/new.html.twig b/templates/menu_item/new.html.twig
new file mode 100644
index 0000000..0c42fd8
--- /dev/null
+++ b/templates/menu_item/new.html.twig
@@ -0,0 +1,13 @@
+{% extends 'base.html.twig' %}
+
+{% block title %}New MenuItem{% endblock %}
+
+{% block body %}
+ Create new MenuItem
+
+
+ {{ include('menu_item/_form.html.twig') }}
+
+
+ back to list
+{% endblock %}
diff --git a/templates/menu_item/show.html.twig b/templates/menu_item/show.html.twig
new file mode 100644
index 0000000..973fd91
--- /dev/null
+++ b/templates/menu_item/show.html.twig
@@ -0,0 +1,48 @@
+{% extends 'base.html.twig' %}
+
+{% block title %}MenuItem{% endblock %}
+
+{% block body %}
+ MenuItem
+
+
+
+
+ Id
+ {{ menu_item.id }}
+
+
+ Name
+ {{ menu_item.name }}
+
+
+ Price
+ {{ (menu_item.priceCents / 100)|format_currency('EUR') }}
+
+ {% if(menu_item.aliasOf) %}
+
+ Alias of
+ {{ menu_item.aliasOf.name }}
+
+ {% endif %}
+ {% if(menu_item.aliases|length > 0) %}
+
+ Aliases
+
+
+ {% for alias in menu_item.aliases %}
+ {{ alias.name }}
+ {% endfor %}
+
+
+
+ {% endif %}
+
+
+
+
+{% endblock %}
diff --git a/templates/order_item/_form.html.twig b/templates/order_item/_form.html.twig
index bf20b98..e0ed7ee 100644
--- a/templates/order_item/_form.html.twig
+++ b/templates/order_item/_form.html.twig
@@ -1,4 +1,4 @@
-{{ form_start(form) }}
- {{ form_widget(form) }}
- {{ button_label|default('Save') }}
+{{ form_start(form, {'attr': {'class': 'mb-3'}}) }}
+ {{ form_widget(form, {'attr': {'class': 'form-control'}}) }}
+ {{ button_label|default('Save') }}
{{ form_end(form) }}
diff --git a/templates/order_item/edit.html.twig b/templates/order_item/edit.html.twig
index 2f85f44..5eb4309 100644
--- a/templates/order_item/edit.html.twig
+++ b/templates/order_item/edit.html.twig
@@ -3,9 +3,11 @@
{% block title %}Edit OrderItem{% endblock %}
{% block body %}
- Edit OrderItem
+ Edit OrderItem
- {{ include('order_item/_form.html.twig', {'button_label': 'Update'}) }}
+
+ {{ include('order_item/_form.html.twig', {'button_label': 'Update'}) }}
+
- back to list
+ back to list
{% endblock %}
diff --git a/templates/order_item/new.html.twig b/templates/order_item/new.html.twig
index bd4ac99..0418010 100644
--- a/templates/order_item/new.html.twig
+++ b/templates/order_item/new.html.twig
@@ -3,9 +3,39 @@
{% block title %}New OrderItem{% endblock %}
{% block body %}
- Create new OrderItem
+ Create new OrderItem
- {{ include('order_item/_form.html.twig') }}
+
+ {{ include('order_item/_form.html.twig') }}
+
- back to list
+
+
+ {% if food_order.foodVendor.menuLink != '' %}
+
+ External link to Menu
+
+ {% endif %}
+
+
+ click a button to select a given menuitem
+
+
+
+
+
+ back to list
+
+
{% endblock %}
diff --git a/templates/username.html.twig b/templates/username.html.twig
new file mode 100644
index 0000000..2ebc1c9
--- /dev/null
+++ b/templates/username.html.twig
@@ -0,0 +1,11 @@
+{% extends 'base.html.twig' %}
+
+{% block title %}Tell me your name{% endblock %}
+
+{% block body %}
+ Tell me your name
+ By submitting the form, you agree that your username will be stored as a cookie.
+
+ {{ include('_form.html.twig') }}
+
+{% endblock %}
\ No newline at end of file
diff --git a/tests/Controller/FoodOrderControllerTest.php b/tests/Controller/FoodOrderControllerTest.php
deleted file mode 100644
index 9e72792..0000000
--- a/tests/Controller/FoodOrderControllerTest.php
+++ /dev/null
@@ -1,67 +0,0 @@
-vendor = new FoodVendor;
- $this->vendor->setName('Food Vendor');
-
- $this->manager->persist($this->vendor);
- $this->manager->flush();
- }
-
- #[Override]
- public function getEntityClass(): string
- {
- return FoodOrder::class;
- }
-
- public function testIndex(): void
- {
- $order = new FoodOrder;
- $order->setFoodVendor($this->vendor);
-
- $this->manager->persist($order);
- $this->manager->persist($this->vendor);
- $this->manager->flush();
-
- $crawler = $this->client->request('GET', $this->path);
- self::assertResponseStatusCodeSame(200);
- self::assertPageTitleContains('FoodOrder index');
- $this->assertCount(
- 1,
- $crawler->filter('td')
- ->reduce(fn(Crawler $node, $i): bool => $node->text() === $this->vendor->getName()),
- );
- }
-
- public function testNew(): void
- {
- $this->client->request('GET', sprintf('%snew', $this->path));
-
- self::assertResponseStatusCodeSame(200);
-
- $this->client->submitForm('Save', [
- 'food_order[foodVendor]' => $this->vendor->getId(),
- ]);
-
- self::assertResponseRedirects($this->path);
- self::assertSame(1, $this->repository->count([]));
- }
-}
diff --git a/tests/Controller/FoodVendorControllerTest.php b/tests/Controller/FoodVendorControllerTest.php
deleted file mode 100644
index 42ef9f9..0000000
--- a/tests/Controller/FoodVendorControllerTest.php
+++ /dev/null
@@ -1,78 +0,0 @@
-client->request('GET', $this->path);
-
- self::assertResponseStatusCodeSame(200);
- self::assertPageTitleContains('FoodVendor index');
- }
-
- public function testNew(): void
- {
- $this->client->request('GET', sprintf('%snew', $this->path));
-
- self::assertResponseStatusCodeSame(200);
-
- $this->client->submitForm('Save', [
- 'food_vendor[name]' => 'Testing',
- ]);
-
- self::assertSame(1, $this->repository->count([]));
- }
-
- public function testShow(): void
- {
- $fixture = new FoodVendor;
- $fixture->setName('My Title');
-
- $this->manager->persist($fixture);
- $this->manager->flush();
-
- $crawler = $this->client->request('GET', sprintf('%s%s', $this->path, $fixture->getId()));
-
- $this->assertResponseIsSuccessful();
- $nameNode = $crawler->filter('td')
- ->last();
- $this->assertSame('My Title', $nameNode->text());
- }
-
- public function testEdit(): void
- {
- $fixture = new FoodVendor;
- $fixture->setName('Value');
-
- $this->manager->persist($fixture);
- $this->manager->flush();
-
- $this->client->request('GET', sprintf('%s%s/edit', $this->path, $fixture->getId()));
-
- $this->client->submitForm('Update', [
- 'food_vendor[name]' => 'Something New',
- ]);
-
- self::assertResponseRedirects('/food/vendor/');
-
- $fixture = $this->repository->findAll();
-
- self::assertSame('Something New', $fixture[0]->getName());
- }
-
- #[Override]
- public function getEntityClass(): string
- {
- return FoodVendor::class;
- }
-}
diff --git a/tests/Controller/OrderItemControllerTest.php b/tests/Controller/OrderItemControllerTest.php
deleted file mode 100644
index c8762df..0000000
--- a/tests/Controller/OrderItemControllerTest.php
+++ /dev/null
@@ -1,98 +0,0 @@
-vendor = new FoodVendor;
- $this->vendor->setName('Food Vendor');
-
- $this->manager->persist($this->vendor);
- $this->order = new FoodOrder;
- $this->order->setFoodVendor($this->vendor);
-
- $this->manager->persist($this->order);
- $this->manager->flush();
- }
-
- public function testNew(): void
- {
- $this->client->request(
- 'GET',
- sprintf('%snew/%s', $this->path, $this->order->getId())
- );
-
- self::assertResponseStatusCodeSame(200);
-
- $this->client->submitForm('Save', [
- 'order_item[name]' => 'Testing',
- 'order_item[extras]' => 'Testing',
- ]);
-
- self::assertResponseRedirects(sprintf('/food/order/%s', $this->order->getId()));
-
- self::assertSame(1, $this->repository->count([]));
- }
-
- public function testRemove(): void
- {
- $fixture = new OrderItem;
- $fixture->setName('Value');
- $fixture->setExtras('Value');
- $fixture->setFoodOrder($this->order);
-
- $this->manager->persist($fixture);
- $this->manager->flush();
-
- $this->client->request('GET', sprintf('%sdelete/%s', $this->path, $fixture->getId()));
-
- self::assertResponseRedirects(sprintf('/food/order/%s', $this->order->getId()));
- self::assertSame(0, $this->repository->count([]));
- }
-
- public function testCopy(): void
- {
- $orderItem = new OrderItem;
- $orderItem->setName('My Title');
- $orderItem->setExtras('My Title');
- $orderItem->setFoodOrder($this->order);
-
- $this->manager->persist($orderItem);
- $this->manager->flush();
-
- $this->client->request('GET', sprintf('%s%s/copy', $this->path, $orderItem->getId()));
- self::assertResponseRedirects(sprintf('/food/order/%s', $this->order->getId()));
-
- $result = $this->repository->findBy([
- 'foodOrder' => $this->order->getId(),
- ]);
- $this->assertCount(2, $result);
- foreach ($result as $item) {
- $this->assertSame($orderItem->getName(), $item->getName());
- $this->assertSame($orderItem->getExtras(), $item->getExtras());
- }
-
- }
-
- #[Override]
- public function getEntityClass(): string
- {
- return OrderItem::class;
- }
-}
diff --git a/tests/DbWebTest.php b/tests/DbWebTest.php
index cbcf5c9..6751c3d 100644
--- a/tests/DbWebTest.php
+++ b/tests/DbWebTest.php
@@ -2,19 +2,25 @@
namespace App\Tests;
+use DateInterval;
+use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Tools\SchemaTool;
use Override;
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
+use Symfony\Component\DomCrawler\Crawler;
+use Symfony\Component\Uid\Ulid;
+
+use function str_contains;
abstract class DbWebTest extends WebTestCase
{
- abstract public function getEntityClass(): string;
-
protected KernelBrowser $client;
+ protected string $entityClass = '';
protected EntityManagerInterface $manager;
+ protected string $path = '';
protected EntityRepository $repository;
#[Override]
@@ -25,13 +31,36 @@ abstract class DbWebTest extends WebTestCase
$schemaTool = new SchemaTool($this->manager);
$metadata = $this->manager->getMetadataFactory()
->getAllMetadata();
+ $schemaTool->dropDatabase();
$schemaTool->updateSchema($metadata);
+ }
- $this->repository = $this->manager->getRepository($this->getEntityClass());
- foreach ($this->repository->findAll() as $object) {
- $this->manager->remove($object);
- }
+ protected function assertElementContainsCount(Crawler $crawler, string $element, int $count, string $text): void
+ {
+ $this->assertCount(
+ $count,
+ $crawler->filter($element)
+ ->reduce(
+ static fn(Crawler $node, $i): bool => str_contains($node->text(), $text),
+ )
+ );
+ }
- $this->manager->flush();
+ protected function generateOldUlid(int $daysToSubtract = 10): Ulid
+ {
+ $date = (new DateTimeImmutable)->sub(new DateInterval('P' . $daysToSubtract . 'D'));
+ $ulidString = Ulid::generate($date);
+ return Ulid::fromString($ulidString);
+ }
+
+ protected function setEntityClass(string $entityClass): void
+ {
+ $this->entityClass = $entityClass;
+ $this->repository = $this->manager->getRepository($this->entityClass);
+ }
+
+ protected function setPath(string $path): void
+ {
+ $this->path = $path;
}
}
diff --git a/tests/Feature/Controller/FoodOrderControllerTest.php b/tests/Feature/Controller/FoodOrderControllerTest.php
new file mode 100644
index 0000000..235b7d6
--- /dev/null
+++ b/tests/Feature/Controller/FoodOrderControllerTest.php
@@ -0,0 +1,268 @@
+beforeEach(function (): void {
+ $this->setEntityClass(FoodOrder::class);
+ $this->setPath('/food/order/');
+ $this->repository = $this->manager->getRepository($this->entityClass);
+ $this->vendor = new FoodVendor;
+ $this->vendor->setName('Food Vendor');
+
+ $this->manager->persist($this->vendor);
+ $this->manager->flush();
+ });
+
+describe(FoodOrderController::class, function (): void {
+ test('index', function (): void {
+ $order = new FoodOrder;
+ $order->setFoodVendor($this->vendor);
+
+ $this->manager->persist($order);
+ $this->manager->persist($this->vendor);
+ $this->manager->flush();
+
+ $crawler = $this->client->request('GET', "{$this->path}list");
+ $this->assertResponseStatusCodeSame(200);
+ $this->assertPageTitleContains('FoodOrder index');
+ $this->assertCount(
+ 1,
+ $crawler->filter('td')
+ ->reduce(fn(Crawler $node, $i): bool => $node->text() === $this->vendor->getName()),
+ );
+ });
+
+ test('orderedItems', function (): void {
+ $order = new FoodOrder;
+ $order->setFoodVendor($this->vendor);
+
+ $this->manager->persist($order);
+ $this->manager->persist($this->vendor);
+
+ $menuItemA = new MenuItem;
+ $menuItemA->setName('A');
+ $menuItemA->setFoodVendor($this->vendor);
+
+ $this->manager->persist($menuItemA);
+ $itemA = new OrderItem;
+ $itemA->setMenuItem($menuItemA);
+ $itemA->setName($menuItemA->getName());
+
+ $order->addOrderItem($itemA);
+ $this->manager->persist($itemA);
+
+ $menuItemC = new MenuItem;
+ $menuItemC->setName('C');
+ $menuItemC->setFoodVendor($this->vendor);
+
+ $this->manager->persist($menuItemC);
+ $itemC = new OrderItem;
+ $itemC->setMenuItem($menuItemC);
+ $itemC->setName($menuItemC->getName());
+
+ $order->addOrderItem($itemC);
+ $this->manager->persist($itemC);
+
+ $menuItemB = new MenuItem;
+ $menuItemB->setName('B');
+ $menuItemB->setFoodVendor($this->vendor);
+
+ $this->manager->persist($menuItemB);
+ $itemB = new OrderItem;
+ $itemB->setMenuItem($menuItemB);
+ $itemB->setName($menuItemB->getName());
+
+ $order->addOrderItem($itemB);
+ $this->manager->persist($itemB);
+
+ $this->manager->flush();
+
+ $crawler = $this->client->request('GET', "{$this->path}{$order->getId()}");
+ $this->assertResponseIsSuccessful();
+ $tdContent = $crawler->filter(
+ 'table.table-hover tbody tr:nth-child(1) td:nth-child(3)'
+ )->text();
+ $this->assertEquals('A', $tdContent);
+ $tdContent = $crawler->filter(
+ 'table.table-hover tbody tr:nth-child(2) td:nth-child(3)'
+ )->text();
+ $this->assertEquals('B', $tdContent);
+ $tdContent = $crawler->filter(
+ 'table.table-hover tbody tr:nth-child(3) td:nth-child(3)'
+ )->text();
+ $this->assertEquals('C', $tdContent);
+ });
+
+ test('paginatedIndex', function (): void {
+ foreach (range(1, 35) as $i) {
+ $order = new FoodOrder($this->generateOldUlid());
+ $order->setFoodVendor($this->vendor);
+ $order->close();
+ $this->manager->persist($order);
+
+ }
+ $this->manager->flush();
+ $crawler = $this->client->request('GET', "{$this->path}list");
+ $this->assertResponseStatusCodeSame(200);
+ $this->assertPageTitleContains('FoodOrder index');
+ $this->assertElementContainsCount(
+ $crawler,
+ 'td',
+ 1,
+ 'older orders'
+ );
+ $this->assertElementContainsCount(
+ $crawler,
+ 'td',
+ 0,
+ 'next page'
+ );
+ });
+
+ test('paginatedFirstPage', function (int $page, int $prevPage, int $nextPage, int $items = 10): void {
+ foreach (range(1, 35) as $i) {
+ $order = new FoodOrder($this->generateOldUlid());
+ $order->setFoodVendor($this->vendor);
+ $order->close();
+ $this->manager->persist($order);
+
+ }
+ $this->manager->flush();
+ $crawler = $this->client->request('GET', "{$this->path}list/archive/{$page}");
+ $this->assertResponseStatusCodeSame(200);
+ $this->assertPageTitleContains('FoodOrder index');
+ $this->assertElementContainsCount(
+ $crawler,
+ 'td',
+ $items,
+ 'nobody'
+ );
+ if ($prevPage > 0) {
+ $prevPage = $prevPage === 1 ? '' : "/{$prevPage}";
+ $node = $crawler->filter('a')
+ ->reduce(static fn(Crawler $node, $i): bool => $node->text() === 'previous page')
+ ->first();
+ $target = $node->attr('href');
+ $this->assertTrue(str_ends_with((string) $target, $prevPage));
+ }
+ if ($prevPage > 3) {
+ $node = $crawler->filter('a')
+ ->reduce(static fn(Crawler $node, $i): bool => $node->text() === 'next page')
+ ->first();
+ $target = $node->attr('href');
+ $this->assertTrue(str_ends_with((string) $target, "/{$nextPage}"));
+ }
+ })
+ ->with(
+ [
+ [1, 0, 2],
+ [2, 1, 3],
+ [3, 2, 4],
+ [4, 3, 0, 5],
+ ]
+ );
+
+ test('new', function (): void {
+ $this->client->getCookieJar()
+ ->set(new Cookie('username', 'Testing-1'));
+ $this->client->request('GET', sprintf('%snew', $this->path));
+
+ $this->assertResponseStatusCodeSame(200);
+
+ $this->client->submitForm('Save', [
+ 'food_order[foodVendor]' => $this->vendor->getId(),
+ ]);
+
+ $this->assertResponseRedirects("{$this->path}list");
+ $this->assertSame(1, $this->repository->count([]));
+ $order = $this->repository->findOneBy([
+ 'createdBy' => 'Testing-1',
+ ]);
+ assert($order instanceof FoodOrder);
+ });
+
+ test('open', function (): void {
+ $order = new FoodOrder;
+ $order->setFoodVendor($this->vendor);
+ $order->close();
+
+ $this->assertTrue($order->isClosed());
+ $this->manager->persist($order);
+ $this->manager->flush();
+
+ $this->client->request('GET', sprintf('%s%s/open', $this->path, $order->getId()));
+ $this->assertResponseRedirects("{$this->path}{$order->getId()}");
+ $openOrder = $this->repository->find($order->getId());
+ $this->assertFalse($openOrder->isClosed());
+ });
+
+ test('close', function (): void {
+ $order = new FoodOrder;
+ $order->setClosedAt();
+ $order->setFoodVendor($this->vendor);
+
+ $this->assertFalse($order->isClosed());
+ $this->manager->persist($order);
+ $this->manager->flush();
+
+ $this->client->request('GET', sprintf('%s%s/close', $this->path, $order->getId()));
+ $this->assertResponseRedirects("{$this->path}{$order->getId()}");
+ $openOrder = $this->repository->find($order->getId());
+ $this->assertTrue($openOrder->isClosed());
+ });
+
+ test('orderRowOpacity', function (): void {
+ // Create an open order
+ $openOrder = new FoodOrder;
+ $openOrder->setFoodVendor($this->vendor);
+
+ // Create a closed order
+ $closedOrder = new FoodOrder;
+ $closedOrder->setFoodVendor($this->vendor);
+ $closedOrder->close();
+
+ $this->manager->persist($openOrder);
+ $this->manager->persist($closedOrder);
+ $this->manager->flush();
+
+ $crawler = $this->client->request('GET', "{$this->path}list");
+ $this->assertResponseIsSuccessful();
+
+ // In a real environment, closed orders would be displayed with opacity-25 class
+ // and open orders with opacity-100 class as defined in the table_row.html.twig template.
+ // However, in the test environment, we can only verify that the orders are displayed.
+
+ // Verify that we have the expected number of table rows (2 orders + 1 archive link row)
+ $this->assertCount(1, $crawler->filter('tr.opacity-100'));
+ });
+})
+ ->covers(
+ FoodOrderController::class,
+ FoodOrder::class,
+ FoodVendor::class,
+ FoodOrderRepository::class,
+ MenuItem::class,
+ OrderItem::class,
+ FoodOrderType::class,
+ FoodVendorRepository::class
+ );
diff --git a/tests/Feature/Controller/FoodVendorControllerTest.php b/tests/Feature/Controller/FoodVendorControllerTest.php
new file mode 100644
index 0000000..8761330
--- /dev/null
+++ b/tests/Feature/Controller/FoodVendorControllerTest.php
@@ -0,0 +1,184 @@
+beforeEach(function (): void {
+ $this->setEntityClass(FoodVendor::class);
+ $this->setPath('/food/vendor/');
+ $this->repository = $this->manager->getRepository($this->entityClass);
+ });
+
+describe(FoodVendorController::class, function (): void {
+ test('index', function (): void {
+ $this->client->request('GET', $this->path);
+
+ $this->assertResponseStatusCodeSame(200);
+ $this->assertPageTitleContains('FoodVendor index');
+ });
+
+ test('new', function (): void {
+ $this->assertSame(0, $this->repository->count([]));
+ $this->client->request('GET', sprintf('%snew', $this->path));
+
+ $this->assertResponseStatusCodeSame(200);
+
+ $this->client->submitForm('Save', [
+ 'food_vendor[name]' => 'TestingNew',
+ ]);
+
+ $newVendor = $this->repository->findOneBy([
+ 'name' => 'TestingNew',
+ ]);
+ $this->assertInstanceof(FoodVendor::class, $newVendor);
+ $this->assertSame(1, $this->repository->count([]));
+
+ });
+
+ test('show', function (): void {
+ $fixture = new FoodVendor;
+ $fixture->setName('My Title');
+ $fixture->setMenuLink('https://example.com/');
+
+ $this->manager->persist($fixture);
+ $this->manager->flush();
+
+ $crawler = $this->client->request('GET', sprintf('%s%s', $this->path, $fixture->getId()));
+
+ $this->assertResponseIsSuccessful();
+
+ $nameNode = $crawler->filter('td')
+ ->last();
+ $nameNode = $crawler->filter(
+ '.table > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(2)'
+ )->text();
+ $menuLinkNode = $crawler->filter(
+ '.table > tbody:nth-child(1) > tr:nth-child(2) > td:nth-child(2) > a:nth-child(1)'
+ )->text();
+ $this->assertSame('My Title', $nameNode);
+ $this->assertSame('https://example.com/', $menuLinkNode);
+ });
+
+ test('show with menu items', function (): void {
+ $fixture = new FoodVendor;
+ $fixture->setName('My Title');
+
+ $this->manager->persist($fixture);
+
+ $this->manager->flush();
+
+ $itemOne = new MenuItem;
+ $itemOne->setName('Item One');
+
+ $fixture->addMenuItem($itemOne);
+ $this->manager->persist($itemOne);
+
+ $itemTwo = new MenuItem;
+ $itemTwo->setName('Item Two');
+ $itemTwo->setFoodVendor($fixture);
+
+ $fixture->addMenuItem($itemTwo);
+ $this->manager->persist($itemTwo);
+
+ $itemThree = new MenuItem;
+ $itemThree->setName('Item Three');
+ $itemThree->setFoodVendor($fixture);
+
+ $fixture->addMenuItem($itemThree);
+ $this->manager->persist($itemThree);
+
+ $itemFour = new MenuItem;
+ $itemFour->setName('Item Four');
+ $itemFour->setFoodVendor($fixture);
+
+ $fixture->addMenuItem($itemFour);
+ $this->manager->persist($itemFour);
+
+ $this->manager->flush();
+
+ $crawler = $this->client->request('GET', sprintf('%s%s', $this->path, $fixture->getId()));
+
+ $this->assertResponseIsSuccessful();
+ $nameNode = $crawler->filter(
+ '.table > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(2)'
+ )->text();
+ $this->assertSame('My Title', $nameNode);
+
+ $itemNodes = $crawler->filter('ul.list-group li.list-group-item');
+
+ $this->assertCount(4, $itemNodes);
+ });
+
+ test('edit', function (): void {
+ $fixture = new FoodVendor;
+ $fixture->setName('Value');
+ $fixture->setMenuLink('Value');
+ $fixture->setPhone('Value');
+
+ $this->manager->persist($fixture);
+ $this->manager->flush();
+
+ $crawler = $this->client->request('GET', sprintf('%s%s/edit', $this->path, $fixture->getId()));
+ $this->assertSame(
+ $crawler->filter('#food_vendor_name')
+ ->last()
+ ->attr('value', ''),
+ 'Value'
+ );
+ $this->assertSame(
+ $crawler->filter('#food_vendor_menuLink')
+ ->last()
+ ->attr('value', ''),
+ 'Value'
+ );
+ $this->assertSame(
+ $crawler->filter('#food_vendor_phone')
+ ->last()
+ ->attr('value', ''),
+ 'Value'
+ );
+
+ $this->client->submitForm('Update', [
+ 'food_vendor[name]' => 'Something New',
+ 'food_vendor[menuLink]' => 'https://example.com/',
+ 'food_vendor[phone]' => '1234567890',
+ ]);
+
+ $this->assertResponseRedirects('/food/vendor/');
+
+ $fixture = $this->repository->findAll();
+
+ $this->assertSame('Something New', $fixture[0]->getName());
+ $this->assertSame('https://example.com/', $fixture[0]->getMenuLink());
+ $this->assertSame('1234567890', $fixture[0]->getPhone());
+ });
+
+})
+ ->covers(
+ FoodOrder::class,
+ FoodVendor::class,
+ FoodOrderRepository::class,
+ MenuItem::class,
+ OrderItem::class,
+ FoodOrderType::class,
+ FoodVendorRepository::class,
+ FoodVendorController::class,
+ FoodVendorType::class
+ )
+
+;
diff --git a/tests/Feature/Controller/HomeControllerTest.php b/tests/Feature/Controller/HomeControllerTest.php
new file mode 100644
index 0000000..76152b6
--- /dev/null
+++ b/tests/Feature/Controller/HomeControllerTest.php
@@ -0,0 +1,71 @@
+client->request(
+ 'GET',
+ '/'
+ );
+
+ $this->assertResponseStatusCodeSame(302);
+ $this->assertResponseHeaderSame('Location', '/food/order/list');
+
+ });
+
+ test('username', function (): void {
+ $this->client->request(
+ 'GET',
+ '/username',
+ );
+
+ $this->assertResponseStatusCodeSame(200);
+
+ $this->client->submitForm('Save', [
+ 'user_name_form[username]' => 'Testing-1',
+ ]);
+ $this->assertResponseStatusCodeSame(302);
+ $this->assertResponseHeaderSame('Location', '/food/order/list');
+ $this->assertResponseCookieValueSame('username', 'Testing-1');
+
+ $crawler = $this->client->request(
+ 'GET',
+ '/username',
+ );
+
+ $this->assertResponseStatusCodeSame(200);
+
+ $this->assertSame(
+ $crawler->filter('#user_name_form_username')
+ ->last()
+ ->attr('value', ''),
+ 'Testing-1'
+ );
+
+ });
+
+ test('username empty', function (): void {
+ $this->client->request(
+ 'GET',
+ '/username',
+ );
+
+ $this->assertResponseStatusCodeSame(200);
+
+ $this->client->submitForm('Save', [
+ 'user_name_form[username]' => '',
+ ]);
+ $this->assertResponseStatusCodeSame(302);
+ $this->assertResponseHeaderSame('Location', '/food/order/list');
+ $this->assertResponseCookieValueSame('username', '');
+ });
+})
+ ->covers(HomeController::class, UserNameFormType::class);
diff --git a/tests/Feature/Controller/MenuItemControllerTest.php b/tests/Feature/Controller/MenuItemControllerTest.php
new file mode 100644
index 0000000..fc2c537
--- /dev/null
+++ b/tests/Feature/Controller/MenuItemControllerTest.php
@@ -0,0 +1,160 @@
+beforeEach(function (): void {
+ $this->setEntityClass(MenuItem::class);
+ $this->setPath('/menu/item/');
+
+ $this->repository = $this->manager->getRepository($this->entityClass);
+
+ $this->vendor = new FoodVendor;
+ $this->vendor->setName('Food Vendor');
+
+ $this->manager->persist($this->vendor);
+ $this->menuItem = new MenuItem;
+ $this->menuItem->setName('Testing 1 2');
+
+ $this->vendor->addMenuItem($this->menuItem);
+ $this->manager->persist($this->vendor);
+ $this->manager->persist($this->menuItem);
+
+ $this->aliasOne = new MenuItem;
+ $this->aliasOne->setName('AliasOne');
+ $this->aliasOne->setFoodVendor($this->vendor);
+
+ $this->menuItem->addAlias($this->aliasOne);
+
+ $this->aliasTwo = new MenuItem;
+ $this->aliasTwo->setName('AliasTwo');
+ $this->aliasTwo->setFoodVendor($this->vendor);
+ $this->aliasTwo->setAliasOf($this->menuItem);
+
+ $this->menuItem->addAlias($this->aliasTwo);
+
+ $this->manager->persist($this->aliasOne);
+ $this->manager->persist($this->aliasTwo);
+ $this->manager->persist($this->menuItem);
+ $this->manager->flush();
+
+ });
+covers(
+ MenuItemController::class,
+ OrderItemController::class,
+ OrderItemType::class,
+ MenuItemRepository::class,
+ FoodOrder::class,
+ FoodVendor::class,
+ MenuItem::class,
+ OrderItem::class,
+ FoodOrderRepository::class,
+ MenuItemType::class,
+);
+
+it('show', function (): void {
+
+ $crawler = $this->client->request('GET', "{$this->path}{$this->menuItem->getId()}");
+ $idValue = $crawler->filter(
+ '.table > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(2)'
+ )->text();
+ $nameValue = $crawler->filter(
+ '.table > tbody:nth-child(1) > tr:nth-child(2) > td:nth-child(2)'
+ )->text();
+
+ $aliasTwoNameValue = $crawler->filter(
+ '.table > tbody:nth-child(1) > tr:nth-child(4) > td:nth-child(2) > ul:nth-child(1) > li:nth-child(1)'
+ )->text();
+ $aliasOneNameValue = $crawler->filter(
+ '.table > tbody:nth-child(1) > tr:nth-child(4) > td:nth-child(2) > ul:nth-child(1) > li:nth-child(2)'
+ )->text();
+ $this->assertResponseStatusCodeSame(200);
+ $this->assertEquals($idValue, $this->menuItem->getId());
+ $this->assertEquals($nameValue, $this->menuItem->getName());
+ $this->assertEquals($aliasTwoNameValue, $this->aliasOne->getName());
+ $this->assertEquals($aliasOneNameValue, $this->aliasTwo->getName());
+});
+
+test('edit', function (): void {
+ $crawler = $this->client->request('GET', sprintf('%s%s/edit', $this->path, $this->menuItem->getId()));
+ $nameElem = $crawler->filter('#menu_item_name');
+ $this->assertEquals(
+ 'Testing 1 2',
+ $nameElem->attr('value')
+ );
+
+ $form = $crawler->selectButton('Update')
+ ->form();
+ $form['menu_item[name]'] = 'Testing-1';
+ $form['menu_item[priceCents]'] = '1.23';
+ $form['menu_item[aliases]'][0]->untick();
+
+ $this->client->submit($form);
+
+ $this->assertResponseRedirects(sprintf('/menu/item/%s', $this->menuItem->getId()));
+ $menuItem = $this->repository->find($this->menuItem->getId());
+ $this->assertEquals('Testing-1', $menuItem->getName());
+ $this->assertEquals(123, $menuItem->getPriceCents());
+ $this->assertEquals(1, $menuItem->getAliases()->count());
+ $aliasOne = $this->repository->find($this->aliasOne->getId());
+ $this->assertNull($aliasOne->getAliasOf());
+});
+
+test('edit invalid', function (): void {
+ $crawler = $this->client->request('GET', sprintf('%s%s/edit', $this->path, $this->menuItem->getId()));
+ $nameElem = $crawler->filter('#menu_item_name');
+ $this->assertEquals(
+ 'Testing 1 2',
+ $nameElem->attr('value')
+ );
+
+ $form = $crawler->selectButton('Update')
+ ->form();
+ $form['menu_item[name]'] = 'a';
+
+ $this->client->submit($form);
+
+ $this->assertResponseStatusCodeSame(422);
+});
+
+test('delete', function (): void {
+ $order = new FoodOrder;
+ $order->setFoodVendor($this->vendor);
+
+ $this->manager->persist($order);
+ $this->manager->flush();
+ $this->assertFalse($this->menuItem->isDeleted());
+
+ $this->client->request('GET', "{$this->path}{$this->menuItem->getId()}");
+ $this->client->submitForm('Delete', []);
+
+ $menuItem = $this->repository->find($this->menuItem->getId());
+
+ $this->assertTrue($menuItem->isDeleted());
+
+ $crawler = $this->client->request('GET', '/order/item/new/' . $order->getId());
+ $count = $crawler->filter('body > main:nth-child(2) > div:nth-child(5)')
+ ->children()
+ ->count();
+ $this->assertSame(2, $count);
+
+ $this->assertResponseIsSuccessful();
+
+});
diff --git a/tests/Feature/Controller/OrderItemControllerTest.php b/tests/Feature/Controller/OrderItemControllerTest.php
new file mode 100644
index 0000000..afbed56
--- /dev/null
+++ b/tests/Feature/Controller/OrderItemControllerTest.php
@@ -0,0 +1,261 @@
+beforeEach(function (): void {
+ $this->setEntityClass(OrderItem::class);
+ $this->setPath('/order/item/');
+ $this->repository = $this->manager->getRepository($this->entityClass);
+
+ $this->vendor = new FoodVendor;
+ $this->vendor->setName('Food Vendor');
+
+ $this->manager->persist($this->vendor);
+ $this->order = new FoodOrder;
+ $this->order->setFoodVendor($this->vendor);
+
+ $this->manager->persist($this->order);
+
+ $this->menuItem = new MenuItem;
+ $this->menuItem->setName('Testing');
+ $this->menuItem->setFoodVendor($this->vendor);
+
+ $vendor2 = new FoodVendor;
+ $vendor2->setName('Vendor 2');
+
+ $menuItem2 = new MenuItem;
+ $menuItem2->setName('Testing2');
+ $menuItem2->setFoodVendor($vendor2);
+
+ $this->manager->persist($vendor2);
+ $this->manager->persist($menuItem2);
+
+ $this->manager->persist($this->menuItem);
+ $this->manager->flush();
+
+ $this->menuItemRepository = $this::getContainer()->get(MenuItemRepository::class);
+ });
+
+describe(OrderItemController::class, function (): void {
+ test('new', function (): void {
+ $crawler = $this->client->request(
+ 'GET',
+ sprintf('%snew/%s', $this->path, $this->order->getId())
+ );
+
+ $children = $crawler->filter('body > main:nth-child(2) > div:nth-child(5)')
+ ->children();
+
+ $this->assertCount(1, $children);
+
+ $this->assertResponseStatusCodeSame(200);
+
+ $this->client->submitForm('Save', [
+ 'order_item[name]' => 'Testing',
+ 'order_item[extras]' => 'Testing',
+ ]);
+
+ $this->assertResponseRedirects(sprintf('/food/order/%s', $this->order->getId()));
+
+ $this->assertSame(1, $this->repository->count([]));
+ $this->assertSame(1, $this->menuItemRepository->count([
+ 'foodVendor' => $this->vendor->getId(),
+ ]));
+ });
+
+ test('new order closed', function (): void {
+
+ $this->order->setClosedAt(new DateTimeImmutable('-1 Hour'));
+ $this->manager->persist($this->order);
+ $this->manager->flush();
+
+ $this->client->request(
+ 'GET',
+ sprintf('%snew/%s', $this->path, $this->order->getId())
+ );
+
+ $this->assertResponseRedirects(sprintf('/food/order/%s', $this->order->getId()));
+
+ $this->assertSame(0, $this->repository->count([]));
+ });
+
+ test('new create menu item', function (): void {
+ $this->client->request(
+ 'GET',
+ sprintf('%snew/%s', $this->path, $this->order->getId())
+ );
+
+ $this->assertResponseStatusCodeSame(200);
+
+ $this->client->submitForm('Save', [
+ 'order_item[name]' => 'Testing-1',
+ 'order_item[extras]' => 'Testing-1',
+ ]);
+
+ $this->assertResponseRedirects(sprintf('/food/order/%s', $this->order->getId()));
+
+ $this->assertSame(1, $this->repository->count([]));
+ $this->assertSame(3, $this->menuItemRepository->count([]));
+ });
+
+ test('remove', function (): void {
+ $fixture = new OrderItem;
+ $fixture->setName('Testing');
+ $fixture->setExtras('Value');
+ $fixture->setMenuItem($this->menuItem);
+
+ $fixture->setFoodOrder($this->order);
+
+ $this->manager->persist($fixture);
+ $this->manager->flush();
+
+ $this->client->request('GET', sprintf('%sdelete/%s', $this->path, $fixture->getId()));
+
+ $this->assertResponseRedirects(sprintf('/food/order/%s', $this->order->getId()));
+ $this->assertSame(0, $this->repository->count([]));
+ });
+
+ test('order closed', function (): void {
+ $fixture = new OrderItem;
+ $fixture->setName('Testing');
+ $fixture->setExtras('Value');
+ $fixture->setMenuItem($this->menuItem);
+ $fixture->setFoodOrder($this->order);
+
+ $this->order->close();
+
+ $this->manager->persist($this->order);
+ $this->manager->persist($fixture);
+ $this->manager->flush();
+
+ $this->client->request('GET', sprintf('%sdelete/%s', $this->path, $fixture->getId()));
+
+ $this->assertResponseRedirects(sprintf('/food/order/%s', $this->order->getId()));
+ $this->assertSame(1, $this->repository->count([]));
+ });
+
+ test('edit', function (): void {
+ $orderItem = new OrderItem;
+ $orderItem->setName('Testing');
+ $orderItem->setExtras('My Extra');
+ $orderItem->setFoodOrder($this->order);
+ $orderItem->setMenuItem($this->menuItem);
+
+ $this->manager->persist($orderItem);
+ $this->manager->flush();
+
+ $crawler = $this->client->request('GET', sprintf('%s%s/edit', $this->path, $orderItem->getId()));
+ $nameElem = $crawler->filter('#order_item_name');
+ $extrasElem = $crawler->filter('#order_item_extras');
+ $this->assertEquals(
+ 'Testing',
+ $nameElem->attr('value')
+ );
+
+ $this->assertEquals(
+ 'My Extra',
+ $extrasElem->attr('value')
+ );
+
+ $this->client->submitForm('Update', [
+ 'order_item[name]' => 'Testing-1',
+ 'order_item[extras]' => 'Testing-1',
+ ]);
+
+ $this->assertResponseRedirects(sprintf('/food/order/%s', $this->order->getId()));
+
+ $this->assertSame(1, $this->repository->count([]));
+ $this->assertSame(3, $this->menuItemRepository->count([]));
+
+ });
+
+ test('edit order closed', function (): void {
+ $orderItem = new OrderItem;
+ $orderItem->setName('Testing');
+ $orderItem->setExtras('My Extra');
+ $orderItem->setFoodOrder($this->order);
+ $orderItem->setMenuItem($this->menuItem);
+
+ $this->order->close();
+
+ $this->manager->persist($orderItem);
+ $this->manager->persist($this->order);
+ $this->manager->flush();
+
+ $this->client->request('GET', sprintf('%s%s/edit', $this->path, $orderItem->getId()));
+ $this->assertResponseRedirects(sprintf('/food/order/%s', $this->order->getId()));
+ });
+
+ test('copy', function (): void {
+ $orderItem = new OrderItem;
+ $orderItem->setName('My Title');
+ $orderItem->setExtras('My Title');
+ $orderItem->setFoodOrder($this->order);
+ $orderItem->setMenuItem($this->menuItem);
+
+ $this->manager->persist($orderItem);
+ $this->manager->flush();
+
+ $this->client->request('GET', sprintf('%s%s/copy', $this->path, $orderItem->getId()));
+ $this->assertResponseRedirects(sprintf('/food/order/%s', $this->order->getId()));
+
+ $result = $this->repository->findBy([
+ 'foodOrder' => $this->order->getId(),
+ ]);
+ $this->assertCount(2, $result);
+ foreach ($result as $item) {
+ $this->assertSame($orderItem->getName(), $item->getName());
+ $this->assertSame($orderItem->getExtras(), $item->getExtras());
+ }
+ });
+
+ test('copy order closed', function (): void {
+ $orderItem = new OrderItem;
+ $orderItem->setName('My Title');
+ $orderItem->setExtras('My Title');
+ $orderItem->setFoodOrder($this->order);
+ $orderItem->setMenuItem($this->menuItem);
+
+ $this->order->close();
+ $this->manager->persist($this->order);
+ $this->manager->persist($orderItem);
+ $this->manager->flush();
+
+ $this->client->request('GET', sprintf('%s%s/copy', $this->path, $orderItem->getId()));
+ $this->assertResponseRedirects(sprintf('/food/order/%s', $this->order->getId()));
+
+ $result = $this->repository->findBy([
+ 'foodOrder' => $this->order->getId(),
+ ]);
+ $this->assertCount(1, $result);
+ });
+
+})
+ ->covers(
+ OrderItemController::class,
+ MenuItemRepository::class,
+ OrderItemRepository::class,
+ OrderItemType::class,
+ FoodOrder::class,
+ FoodVendor::class,
+ MenuItem::class,
+ OrderItem::class,
+ FoodOrderRepository::class,
+ );
diff --git a/tests/Feature/EventListener/OrderItemPreFlushTest.php b/tests/Feature/EventListener/OrderItemPreFlushTest.php
new file mode 100644
index 0000000..0dac100
--- /dev/null
+++ b/tests/Feature/EventListener/OrderItemPreFlushTest.php
@@ -0,0 +1,45 @@
+beforeEach(function (): void {
+ $this->setEntityClass(FoodOrder::class);
+ $this->setPath('/food/order/');
+ $this->repository = $this->manager->getRepository($this->entityClass);
+ $this->vendor = new FoodVendor;
+ $this->vendor->setName('Food Vendor');
+
+ $this->manager->persist($this->vendor);
+
+ $this->order = new FoodOrder;
+ $this->order->setFoodVendor($this->vendor);
+
+ $this->manager->persist($this->order);
+ $this->manager->flush();
+ });
+
+it('updates the menu item price', function (): void {
+ $orderItem = new OrderItem;
+ $orderItem->setFoodOrder($this->order);
+ $orderItem->setName('Item');
+ $orderItem->setPriceCents(100);
+
+ $this->manager->persist($orderItem);
+ $this->manager->flush();
+
+ expect($orderItem->getMenuItem()->getPriceCents())
+ ->toBe(100);
+
+ $orderItem->setPriceCents(200);
+ $this->manager->persist($orderItem);
+ $this->manager->flush();
+
+ $id = $orderItem->getId();
+
+ $orderItem = $this->manager->find(OrderItem::class, $id);
+ expect($orderItem->getMenuItem()->getPriceCents())
+ ->toBe(200);
+});
diff --git a/tests/Pest.php b/tests/Pest.php
new file mode 100644
index 0000000..53d7387
--- /dev/null
+++ b/tests/Pest.php
@@ -0,0 +1,33 @@
+extends(DbWebTest::class)->in('Feature/Controller/*.php', 'Feature/EventListener/*.php');
+
+/*
+|--------------------------------------------------------------------------
+| Functions
+|--------------------------------------------------------------------------
+|
+| While Pest is very powerful out-of-the-box, you may have some testing code specific to your
+| project that you don't want to repeat in every file. Here you can also expose helpers as
+| global functions to help you to reduce the number of lines of code in your test files.
+|
+*/
+
+function something(): void
+{
+ // ..
+}
diff --git a/tests/TestCase.php b/tests/TestCase.php
new file mode 100644
index 0000000..6265b96
--- /dev/null
+++ b/tests/TestCase.php
@@ -0,0 +1,10 @@
+getOrderItems())
+ ->toBeEmpty();
+ $order->addOrderItem($orderItem);
+ $order->addOrderItem($orderItem);
+
+ expect($order->getOrderItems())
+ ->toHaveCount(1)
+ ->and($orderItem->getFoodOrder())
+ ->toBe($order);
+
+ $order->removeOrderItem($orderItem);
+
+ expect($order->getOrderItems())
+ ->toBeEmpty()
+ ->and($orderItem->getFoodOrder())
+ ->toBeNull();
+
+})
+ ->covers(FoodOrder::class, OrderItem::class);
diff --git a/tests/Unit/Entity/FoodVendorTest.php b/tests/Unit/Entity/FoodVendorTest.php
new file mode 100644
index 0000000..ee00ece
--- /dev/null
+++ b/tests/Unit/Entity/FoodVendorTest.php
@@ -0,0 +1,76 @@
+setName('Test');
+ $this->assertEquals('Test', $vendor->getName());
+ $this->assertInstanceOf(Ulid::class, $vendor->getId());
+ $this->assertEmpty($vendor->getPhone());
+ $vendor->setPhone('1234567890');
+ $this->assertEquals('1234567890', $vendor->getPhone());
+
+ // Test emojis field
+ $this->assertNull($vendor->getEmojis());
+ $emojis = '😀😂🎉👍❤️';
+ $vendor->setEmojis($emojis);
+ $this->assertEquals($emojis, $vendor->getEmojis());
+
+ // Test emojis validation
+ $tooManyEmojis = '😀😂🎉👍❤️🚀🎈🎁🎊🎋🎍🎎🎏🎐🎑🎒🎓🎔🎕🎖🎗🎘🎙🎚🎛🎜🎝🎞🎟🎠🎡🎢';
+ $this->expectException(InvalidArgumentException::class);
+ $vendor->setEmojis($tooManyEmojis);
+
+ $this->assertCount(0, $vendor->getFoodOrders());
+ $order1 = new FoodOrder;
+ $vendor->addFoodOrder($order1);
+ $vendor->addFoodOrder($order1);
+ $this->assertCount(1, $vendor->getFoodOrders());
+ $this->assertSame($vendor, $order1->getFoodVendor());
+ $vendor->removeFoodOrder($order1);
+ $this->assertCount(0, $vendor->getFoodOrders());
+ $this->assertNull($order1->getFoodVendor());
+ });
+
+ test('MenutItem entity', function (): void {
+ $vendor = new FoodVendor;
+ $menuItem1 = new MenuItem;
+ $menuItem2 = new MenuItem;
+ $this->assertCount(0, $vendor->getMenuItems());
+ $vendor->addMenuItem($menuItem1);
+ $vendor->addMenuItem($menuItem1);
+ $this->assertCount(1, $vendor->getMenuItems());
+ $vendor->removeMenuItem($menuItem1);
+ $this->assertCount(0, $vendor->getMenuItems());
+ $this->assertNull($menuItem1->getFoodVendor());
+ $vendor->addMenuItem($menuItem1);
+ $menuItem2->delete();
+ $vendor->addMenuItem($menuItem2);
+ $this->assertCount(1, $vendor->getMenuItems());
+ $this->assertCount(2, $vendor->getMenuItems(true));
+ });
+
+ test('remove foreign menu item', function (): void {
+ $vendor1 = new FoodVendor;
+ $vendor2 = new FoodVendor;
+ $item1 = new MenuItem;
+
+ $vendor1->addMenuItem($item1);
+ $this->assertCount(1, $vendor1->getMenuItems());
+ $vendor2->removeMenuItem($item1);
+ $this->assertCount(1, $vendor1->getMenuItems());
+ $this->assertSame($vendor1, $item1->getFoodVendor());
+ });
+
+})->covers(FoodVendor::class, FoodOrder::class, MenuItem::class);
diff --git a/tests/Unit/Entity/MenuItemTest.php b/tests/Unit/Entity/MenuItemTest.php
new file mode 100644
index 0000000..5e01b05
--- /dev/null
+++ b/tests/Unit/Entity/MenuItemTest.php
@@ -0,0 +1,53 @@
+setName('Test');
+ $this->assertEquals('Test', $item->getName());
+
+ $vendor = new FoodVendor;
+ $vendor->setName('Test');
+
+ $item->setFoodVendor($vendor);
+ $this->assertEquals($vendor, $item->getFoodVendor());
+
+ $this->assertFalse($item->isDeleted());
+ $this->assertNull($item->getDeletedAt());
+ $item->delete();
+ $this->assertTrue($item->isDeleted());
+ $this->assertInstanceOf(DateTimeImmutable::class, $item->getDeletedAt());
+ });
+ test('MenuItem alias', function (): void {
+ $item = new MenuItem;
+ $item->setName('Test');
+ $this->assertEquals('Test', $item->getName());
+
+ $vendor = new FoodVendor;
+ $vendor->setName('Test');
+
+ $item->setFoodVendor($vendor);
+
+ $item2 = new MenuItem;
+ $item2->setName('Test2');
+ $item2->setFoodVendor($vendor);
+
+ $item->addAlias($item2);
+
+ $this->assertCount(1, $item->getAliases());
+ $this->assertSame($item, $item2->getAliasOf());
+
+ $item->removeAlias($item2);
+ $this->assertCount(0, $item->getAliases());
+ $this->assertNull($item2->getAliasOf());
+ });
+})->covers(MenuItem::class, FoodVendor::class);
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index e717c59..11702bc 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -1,13 +1,19 @@
bootEnv(dirname(__DIR__) . '/.env');
+ $token = $_SERVER['TEST_TOKEN'] ?? '';
+ $_ENV['DATABASE_URL'] .= $token;
}
if ($_SERVER['APP_DEBUG']) {
umask(0o000);
}
+
+$fs = new Filesystem;
+$fs->remove(dirname(__DIR__) . '/../var/cache/*');