add price feature
All checks were successful
/ ls (pull_request) Successful in 1m37s

This commit is contained in:
lubiana 2025-06-29 23:18:23 +02:00
parent 15f8db46a0
commit 64f5341371
Signed by: lubiana
SSH key fingerprint: SHA256:vW1EA0fRR3Fw+dD/sM0K+x3Il2gSry6YRYHqOeQwrfk
18 changed files with 484 additions and 157 deletions

View file

@ -36,6 +36,7 @@
"symfony/validator": "7.3.*", "symfony/validator": "7.3.*",
"symfony/yaml": "7.3.*", "symfony/yaml": "7.3.*",
"twig/extra-bundle": "^2.12|^3.0", "twig/extra-bundle": "^2.12|^3.0",
"twig/intl-extra": "^3.21",
"twig/twig": "^2.12|^3.0" "twig/twig": "^2.12|^3.0"
}, },
"require-dev": { "require-dev": {

152
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "bc8674fb48687aeee3da991cd7c8d0ad", "content-hash": "b2a06a767859688f71a67ddab0976aea",
"packages": [ "packages": [
{ {
"name": "api-platform/doctrine-common", "name": "api-platform/doctrine-common",
@ -4918,6 +4918,92 @@
], ],
"time": "2025-06-28T08:24:55+00:00" "time": "2025-06-28T08:24:55+00:00"
}, },
{
"name": "symfony/intl",
"version": "v7.3.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/intl.git",
"reference": "bd50940329ac1cfc4af0491cc4468f477d967e45"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/intl/zipball/bd50940329ac1cfc4af0491cc4468f477d967e45",
"reference": "bd50940329ac1cfc4af0491cc4468f477d967e45",
"shasum": ""
},
"require": {
"php": ">=8.2",
"symfony/deprecation-contracts": "^2.5|^3"
},
"conflict": {
"symfony/string": "<7.1"
},
"require-dev": {
"symfony/filesystem": "^6.4|^7.0",
"symfony/var-exporter": "^6.4|^7.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Intl\\": ""
},
"exclude-from-classmap": [
"/Tests/",
"/Resources/data/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
},
{
"name": "Eriksen Costa",
"email": "eriksen.costa@infranology.com.br"
},
{
"name": "Igor Wiedler",
"email": "igor@wiedler.ch"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides access to the localization data of the ICU library",
"homepage": "https://symfony.com",
"keywords": [
"i18n",
"icu",
"internationalization",
"intl",
"l10n",
"localization"
],
"support": {
"source": "https://github.com/symfony/intl/tree/v7.3.1"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2025-06-06T16:10:07+00:00"
},
{ {
"name": "symfony/monolog-bridge", "name": "symfony/monolog-bridge",
"version": "v7.3.0", "version": "v7.3.0",
@ -7375,6 +7461,70 @@
], ],
"time": "2025-02-19T14:29:33+00:00" "time": "2025-02-19T14:29:33+00:00"
}, },
{
"name": "twig/intl-extra",
"version": "v3.21.0",
"source": {
"type": "git",
"url": "https://github.com/twigphp/intl-extra.git",
"reference": "05bc5d46b9df9e62399eae53e7c0b0633298b146"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/intl-extra/zipball/05bc5d46b9df9e62399eae53e7c0b0633298b146",
"reference": "05bc5d46b9df9e62399eae53e7c0b0633298b146",
"shasum": ""
},
"require": {
"php": ">=8.1.0",
"symfony/intl": "^5.4|^6.4|^7.0",
"twig/twig": "^3.13|^4.0"
},
"require-dev": {
"symfony/phpunit-bridge": "^6.4|^7.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Twig\\Extra\\Intl\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": "http://fabien.potencier.org",
"role": "Lead Developer"
}
],
"description": "A Twig extension for Intl",
"homepage": "https://twig.symfony.com",
"keywords": [
"intl",
"twig"
],
"support": {
"source": "https://github.com/twigphp/intl-extra/tree/v3.21.0"
},
"funding": [
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/twig/twig",
"type": "tidelift"
}
],
"time": "2025-01-31T20:45:36+00:00"
},
{ {
"name": "twig/twig", "name": "twig/twig",
"version": "v3.21.1", "version": "v3.21.1",

View file

@ -4,6 +4,7 @@ namespace App\Controller;
use App\Entity\FoodOrder; use App\Entity\FoodOrder;
use App\Form\FoodOrderType; use App\Form\FoodOrderType;
use App\Form\OrderFinalize;
use App\Repository\FoodOrderRepository; use App\Repository\FoodOrderRepository;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
@ -104,11 +105,21 @@ final class FoodOrderController extends AbstractController
], Response::HTTP_SEE_OTHER); ], Response::HTTP_SEE_OTHER);
} }
#[Route('/{id}', name: 'app_food_order_show', methods: ['GET'])] #[Route('/{id}', name: 'app_food_order_show', methods: ['GET', 'POST'])]
public function show(FoodOrder $foodOrder): Response public function show(Request $request, FoodOrder $foodOrder, EntityManagerInterface $entityManager): Response
{ {
$form = null;
if ($foodOrder->isClosed()) {
$form = $this->createForm(OrderFinalize::class, $foodOrder);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->persist($foodOrder);
$entityManager->flush();
}
}
return $this->render('food_order/show.html.twig', [ return $this->render('food_order/show.html.twig', [
'food_order' => $foodOrder, 'food_order' => $foodOrder,
'form' => $form,
]); ]);
} }
} }

View file

@ -3,7 +3,6 @@
namespace App\Controller; namespace App\Controller;
use App\Entity\FoodOrder; use App\Entity\FoodOrder;
use App\Entity\MenuItem;
use App\Entity\OrderItem; use App\Entity\OrderItem;
use App\Form\OrderItemType; use App\Form\OrderItemType;
use App\Repository\MenuItemRepository; use App\Repository\MenuItemRepository;
@ -108,24 +107,6 @@ final class OrderItemController extends AbstractController
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
$menuItem = $menuItemRepository->findOneBy([
'name' => $orderItem->getName(),
'foodVendor' => $foodOrder->getFoodVendor(),
]);
if ($menuItem === null) {
$menuItem = new MenuItem;
$menuItem->setName($orderItem->getName());
$menuItem->setFoodVendor($foodOrder->getFoodVendor());
$entityManager->persist($menuItem);
}
if ($menuItem->getAliasOf() !== null) {
$menuItem = $menuItem->getAliasOf();
$orderItem->setName($menuItem->getName());
}
$orderItem->setMenuItem($menuItem);
$orderItem->setFoodOrder($foodOrder); $orderItem->setFoodOrder($foodOrder);
$entityManager->persist($orderItem); $entityManager->persist($orderItem);
$entityManager->flush(); $entityManager->flush();

View file

@ -11,6 +11,7 @@ use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\IdGenerator\UlidGenerator; use Symfony\Bridge\Doctrine\IdGenerator\UlidGenerator;
use Symfony\Bridge\Doctrine\Types\UlidType; use Symfony\Bridge\Doctrine\Types\UlidType;
use Symfony\Component\Uid\Ulid; use Symfony\Component\Uid\Ulid;
use Symfony\Component\Validator\Constraints\Positive;
#[ApiResource] #[ApiResource]
#[ORM\Entity(repositoryClass: MenuItemRepository::class)] #[ORM\Entity(repositoryClass: MenuItemRepository::class)]
@ -38,6 +39,7 @@ class MenuItem
#[ORM\Column(type: 'integer', options: [ #[ORM\Column(type: 'integer', options: [
'default' => 0, 'default' => 0,
])] ])]
#[Positive]
private int $priceCents = 0; private int $priceCents = 0;
public function __construct( public function __construct(

View file

@ -47,6 +47,7 @@ class OrderItem
#[ORM\Column(type: 'integer', options: [ #[ORM\Column(type: 'integer', options: [
'default' => 0, 'default' => 0,
])] ])]
#[Positive]
private int $priceCents = 0; private int $priceCents = 0;
public function __construct( public function __construct(

View file

@ -0,0 +1,52 @@
<?php declare(strict_types=1);
namespace App\EventListener;
use App\Entity\MenuItem;
use App\Entity\OrderItem;
use App\Repository\MenuItemRepository;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
use Doctrine\ORM\Event\PreFlushEventArgs;
use Doctrine\ORM\Events;
use Doctrine\Persistence\ObjectManager;
#[AsDoctrineListener(event: Events::preFlush)]
final readonly class OrderItemPreFlush
{
public function __construct(
private MenuItemRepository $menuItemRepository,
) {}
public function preFlush(PreFlushEventArgs $eventArgs): void
{
foreach (($eventArgs->getObjectManager()->getUnitOfWork()->getIdentityMap()[OrderItem::class] ?? []) as $orderItem) {
$this->checkOrderItem($orderItem, $eventArgs->getObjectManager());
}
}
private function checkOrderItem(OrderItem $orderItem, ObjectManager $objectManager): void
{
$menuItem = $this->menuItemRepository->findOneBy([
'name' => $orderItem->getName(),
'foodVendor' => $orderItem->getFoodOrder()
->getFoodVendor(),
]);
if ($menuItem === null) {
$menuItem = new MenuItem;
$menuItem->setName($orderItem->getName());
$menuItem->setFoodVendor($orderItem->getFoodOrder()->getFoodVendor());
$objectManager->persist($menuItem);
}
if ($menuItem->getAliasOf() !== null) {
$menuItem = $menuItem->getAliasOf();
$orderItem->setName($menuItem->getName());
}
$orderItem->setMenuItem($menuItem);
if ($orderItem->getPriceCents() === 0) {
$orderItem->setPriceCents($menuItem->getPriceCents());
} elseif ($orderItem->getPriceCents() !== $menuItem->getPriceCents()) {
$menuItem->setPriceCents($orderItem->getPriceCents());
$objectManager->persist($menuItem);
}
}
}

View file

@ -1,35 +0,0 @@
<?php declare(strict_types=1);
namespace App\EventListener;
use App\Entity\MenuItem;
use App\Entity\OrderItem;
use App\Repository\MenuItemRepository;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsEntityListener;
use Doctrine\ORM\Event\PrePersistEventArgs;
use Doctrine\ORM\Events;
#[AsEntityListener(event: Events::prePersist, method: 'prePersist', entity: OrderItem::class)]
final readonly class OrderItemPrePersist
{
public function __construct(
private MenuItemRepository $menuItemRepository,
) {}
public function prePersist(OrderItem $orderItem, PrePersistEventArgs $eventArgs): void
{
$menuItem = $this->menuItemRepository->findOneBy([
'name' => $orderItem->getName(),
'foodVendor' => $orderItem->getFoodOrder()
->getFoodVendor(),
]);
if ($menuItem === null) {
$menuItem = new MenuItem;
$menuItem->setName($orderItem->getName());
$menuItem->setFoodVendor($orderItem->getFoodOrder()->getFoodVendor());
$eventArgs->getObjectManager()
->persist($menuItem);
}
$orderItem->setMenuItem($menuItem);
}
}

View file

@ -8,6 +8,7 @@ use Doctrine\ORM\QueryBuilder;
use Override; use Override;
use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
@ -29,6 +30,10 @@ final class MenuItemType extends AbstractType
]), ]),
], ],
]); ]);
$builder->add('priceCents', MoneyType::class, [
'label' => 'Price',
'divisor' => 100,
]);
$builder->add('aliases', EntityType::class, [ $builder->add('aliases', EntityType::class, [
'class' => MenuItem::class, 'class' => MenuItem::class,
'choice_label' => 'name', 'choice_label' => 'name',

View file

@ -0,0 +1,32 @@
<?php declare(strict_types=1);
namespace App\Form;
use App\Entity\FoodOrder;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
final class OrderFinalize extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add('orderItems', CollectionType::class, [
'entry_type' => OrderItemFinalize::class,
'entry_options' => [
'label' => false,
],
])
->add('save', SubmitType::class)
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => FoodOrder::class,
]);
}
}

View file

@ -0,0 +1,44 @@
<?php declare(strict_types=1);
namespace App\Form;
use App\Entity\OrderItem;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
final class OrderItemFinalize extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add(child: 'name', options: [
'label' => 'order item',
'disabled' => true,
])
->add(child: 'extras', options: [
'disabled' => true,
])
->add(child: 'createdBy', options: [
'disabled' => true,
])
->add(child: 'priceCents', type: MoneyType::class, options: [
'label' => 'price',
'divisor' => 100,
])
->add(child: 'isPaid', type: CheckboxType::class, options: [
'required' => false,
'label' => 'paid?',
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => OrderItem::class,
]);
}
}

View file

@ -39,6 +39,38 @@
</div> </div>
<h2 class="mt-5">Items</h2> <h2 class="mt-5">Items</h2>
{% if (food_order.isClosed and form) %}
{{ form_start(form) }}
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>By</th>
<th>item</th>
<th>extras</th>
<th>price</th>
<th>is paid</th>
</tr>
</thead>
<tbody>
{% for itemForm in form.orderItems %}
<tr>
<td>{{ field_value(itemForm.createdBy) }}</td>
<td>{{ field_value(itemForm.name) }}</td>
<td>{{ field_value(itemForm.extras) }}</td>
<td>{{ form_widget(itemForm.priceCents) }}</td>
<td>{{ form_widget(itemForm.isPaid) }}</td>
</tr>
{% endfor %}
<tr>
<td colspan="4"></td>
<td>{{ form_row(form.save) }} {{ form_row(form._token) }}</td>
</tr>
</tbody>
</table>
</div>
{{ form_end(form, {render_rest: false}) }}
{% else %}
<table class="table table-hover"> <table class="table table-hover">
<thead class="table-light"> <thead class="table-light">
<tr> <tr>
@ -68,6 +100,7 @@
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
{% endif %}
<a class="btn btn-primary mt-2" href="{{ path('app_order_item_new', {'foodOrder': food_order.id}) }}">New Item</a> <a class="btn btn-primary mt-2" href="{{ path('app_order_item_new', {'foodOrder': food_order.id}) }}">New Item</a>
{% endblock %} {% endblock %}

View file

@ -15,6 +15,10 @@
<th>Name</th> <th>Name</th>
<td>{{ menu_item.name }}</td> <td>{{ menu_item.name }}</td>
</tr> </tr>
<tr>
<th>Price</th>
<td>{{ (menu_item.priceCents / 100)|format_currency('EUR') }}</td>
</tr>
{% if(menu_item.aliasOf) %} {% if(menu_item.aliasOf) %}
<tr> <tr>
<th>Alias of</th> <th>Alias of</th>

View file

@ -13,7 +13,8 @@ use App\Form\OrderItemType;
use App\Repository\FoodOrderRepository; use App\Repository\FoodOrderRepository;
use App\Repository\MenuItemRepository; use App\Repository\MenuItemRepository;
use function describe; use function covers;
use function it;
use function pest; use function pest;
use function sprintf; use function sprintf;
use function test; use function test;
@ -55,105 +56,105 @@ pest()
$this->manager->flush(); $this->manager->flush();
}); });
covers(
MenuItemController::class,
OrderItemController::class,
OrderItemType::class,
MenuItemRepository::class,
FoodOrder::class,
FoodVendor::class,
MenuItem::class,
OrderItem::class,
FoodOrderRepository::class,
MenuItemType::class,
);
describe(MenuItemController::class, function (): void { it('show', function (): void {
test('show', function (): void {
$crawler = $this->client->request('GET', "{$this->path}{$this->menuItem->getId()}"); $crawler = $this->client->request('GET', "{$this->path}{$this->menuItem->getId()}");
$idValue = $crawler->filter( $idValue = $crawler->filter(
'.table > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(2)' '.table > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(2)'
)->text(); )->text();
$nameValue = $crawler->filter( $nameValue = $crawler->filter(
'.table > tbody:nth-child(1) > tr:nth-child(2) > td:nth-child(2)' '.table > tbody:nth-child(1) > tr:nth-child(2) > td:nth-child(2)'
)->text(); )->text();
$aliasTwoNameValue = $crawler->filter( $aliasTwoNameValue = $crawler->filter(
'.table > tbody:nth-child(1) > tr:nth-child(3) > td:nth-child(2) > ul:nth-child(1) > li:nth-child(1)' '.table > tbody:nth-child(1) > tr:nth-child(4) > td:nth-child(2) > ul:nth-child(1) > li:nth-child(1)'
)->text(); )->text();
$aliasOneNameValue = $crawler->filter( $aliasOneNameValue = $crawler->filter(
'.table > tbody:nth-child(1) > tr:nth-child(3) > td:nth-child(2) > ul:nth-child(1) > li:nth-child(2)' '.table > tbody:nth-child(1) > tr:nth-child(4) > td:nth-child(2) > ul:nth-child(1) > li:nth-child(2)'
)->text(); )->text();
$this->assertResponseStatusCodeSame(200); $this->assertResponseStatusCodeSame(200);
$this->assertEquals($idValue, $this->menuItem->getId()); $this->assertEquals($idValue, $this->menuItem->getId());
$this->assertEquals($nameValue, $this->menuItem->getName()); $this->assertEquals($nameValue, $this->menuItem->getName());
$this->assertEquals($aliasTwoNameValue, $this->aliasOne->getName()); $this->assertEquals($aliasTwoNameValue, $this->aliasOne->getName());
$this->assertEquals($aliasOneNameValue, $this->aliasTwo->getName()); $this->assertEquals($aliasOneNameValue, $this->aliasTwo->getName());
}); });
test('edit', function (): void { test('edit', function (): void {
$crawler = $this->client->request('GET', sprintf('%s%s/edit', $this->path, $this->menuItem->getId())); $crawler = $this->client->request('GET', sprintf('%s%s/edit', $this->path, $this->menuItem->getId()));
$nameElem = $crawler->filter('#menu_item_name'); $nameElem = $crawler->filter('#menu_item_name');
$this->assertEquals( $this->assertEquals(
'Testing 1 2', 'Testing 1 2',
$nameElem->attr('value') $nameElem->attr('value')
);
$form = $crawler->selectButton('Update')
->form();
$form['menu_item[name]'] = 'Testing-1';
$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(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();
});
})
->covers(
MenuItemController::class,
OrderItemController::class,
OrderItemType::class,
MenuItemRepository::class,
FoodOrder::class,
FoodVendor::class,
MenuItem::class,
OrderItem::class,
FoodOrderRepository::class,
MenuItemType::class,
); );
$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();
});

View file

@ -182,7 +182,7 @@ describe(OrderItemController::class, function (): void {
$this->assertResponseRedirects(sprintf('/food/order/%s', $this->order->getId())); $this->assertResponseRedirects(sprintf('/food/order/%s', $this->order->getId()));
$this->assertSame(1, $this->repository->count([])); $this->assertSame(1, $this->repository->count([]));
$this->assertSame(2, $this->menuItemRepository->count([])); $this->assertSame(3, $this->menuItemRepository->count([]));
}); });

View file

@ -0,0 +1,45 @@
<?php declare(strict_types=1);
use App\Entity\FoodOrder;
use App\Entity\FoodVendor;
use App\Entity\OrderItem;
pest()
->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);
});

View file

@ -14,7 +14,7 @@ use App\Tests\DbWebTest;
*/ */
pest() pest()
->extends(DbWebTest::class)->in('Feature/Controller/*.php'); ->extends(DbWebTest::class)->in('Feature/Controller/*.php', 'Feature/EventListener/*.php');
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------

View file