get ready
This commit is contained in:
parent
ca9819a436
commit
6b0a478ca5
16 changed files with 395 additions and 124 deletions
51
src/Controller/DrinkTypeBulkController.php
Normal file
51
src/Controller/DrinkTypeBulkController.php
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Form\BulkEditDrinkTypeStockForm;
|
||||
use App\Repository\DrinkTypeRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
#[Route('/drink-types')]
|
||||
final class DrinkTypeBulkController extends AbstractController
|
||||
{
|
||||
#[Route('/bulk-edit-stock', name: 'app_drink_type_bulk_edit_stock')]
|
||||
public function bulkEditStock(
|
||||
Request $request,
|
||||
DrinkTypeRepository $drinkTypeRepository,
|
||||
EntityManagerInterface $entityManager
|
||||
): Response {
|
||||
$drinkTypes = $drinkTypeRepository->findAll();
|
||||
|
||||
$form = $this->createForm(BulkEditDrinkTypeStockForm::class, [
|
||||
'drinkTypes' => $drinkTypes,
|
||||
]);
|
||||
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$data = $form->getData();
|
||||
|
||||
foreach ($data['drinkTypes'] as $drinkType) {
|
||||
$entityManager->persist($drinkType);
|
||||
}
|
||||
|
||||
$entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Wanted stock levels updated successfully!');
|
||||
|
||||
return $this->redirectToRoute('app_drink_type_bulk_edit_stock');
|
||||
}
|
||||
|
||||
return $this->render('drink_type/bulk_edit_stock.html.twig', [
|
||||
'form' => $form->createView(),
|
||||
'drinkTypes' => $drinkTypes,
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -8,10 +8,8 @@ use App\Entity\DrinkType;
|
|||
use App\Form\DrinkTypeForm;
|
||||
use App\Form\DrinkTypeFormCurrentStockForm;
|
||||
use App\Repository\DrinkTypeRepository;
|
||||
use App\Repository\PropertyChangeLogRepository;
|
||||
use App\Service\DrinkType\GetStockHistory;
|
||||
use App\Service\DrinkType\GetWantedHistory;
|
||||
use App\Service\InventoryService;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
@ -54,8 +52,7 @@ final class DrinkTypeController extends AbstractController
|
|||
DrinkType $drinkType,
|
||||
GetStockHistory $getStockHistory,
|
||||
GetWantedHistory $getWantedHistory,
|
||||
): Response
|
||||
{
|
||||
): Response {
|
||||
// Get orders that contain this drink type
|
||||
$orderItems = $drinkType->getOrderItems();
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ use DateTimeImmutable;
|
|||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
#[ORM\Entity(repositoryClass: DrinkTypeRepository::class)]
|
||||
#[ORM\Table(name: 'drink_type')]
|
||||
|
@ -33,6 +34,7 @@ class DrinkType
|
|||
#[ORM\Column(type: 'text', nullable: true)]
|
||||
private null|string $description = null;
|
||||
#[ORM\Column(type: 'integer')]
|
||||
#[Assert\GreaterThanOrEqual(0, message: 'Wanted stock must not be negative.')]
|
||||
private int $wantedStock = 10;
|
||||
|
||||
#[ORM\Column(type: 'integer')]
|
||||
|
|
41
src/Form/BulkEditDrinkTypeStockForm.php
Normal file
41
src/Form/BulkEditDrinkTypeStockForm.php
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
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;
|
||||
|
||||
class BulkEditDrinkTypeStockForm extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
->add('drinkTypes', CollectionType::class, [
|
||||
'entry_type' => DrinkTypeStockEditType::class,
|
||||
'entry_options' => [
|
||||
'label' => false,
|
||||
],
|
||||
'allow_add' => false,
|
||||
'allow_delete' => false,
|
||||
'by_reference' => false,
|
||||
])
|
||||
->add('save', SubmitType::class, [
|
||||
'label' => 'Update Wanted Stock Levels',
|
||||
'attr' => [
|
||||
'class' => 'btn btn-primary',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => null,
|
||||
]);
|
||||
}
|
||||
}
|
45
src/Form/DrinkTypeStockEditType.php
Normal file
45
src/Form/DrinkTypeStockEditType.php
Normal file
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Entity\DrinkType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class DrinkTypeStockEditType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
->add('id', HiddenType::class, [
|
||||
'mapped' => false,
|
||||
])
|
||||
->add('name', TextType::class, [
|
||||
'disabled' => true,
|
||||
'attr' => [
|
||||
'readonly' => true,
|
||||
],
|
||||
])
|
||||
->add('wantedStock', NumberType::class, [
|
||||
'label' => 'Wanted Stock',
|
||||
'attr' => [
|
||||
'min' => 0,
|
||||
'step' => 1,
|
||||
'class' => 'form-control',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => DrinkType::class,
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@ final readonly class CreateNewOrderItems
|
|||
public function __invoke(Order $order): void
|
||||
{
|
||||
new ArrayCollection($this->drinkTypeRepository->findWanted())->forAll(
|
||||
function (int $index, DrinkType $drinkType) use ($order) {
|
||||
function (int $index, DrinkType $drinkType) use ($order): true {
|
||||
$quantity = $drinkType->getWantedStock() - $drinkType->getCurrentStock();
|
||||
if ($quantity > 0) {
|
||||
$order->addOrderItem(
|
||||
|
|
49
templates/drink_type/bulk_edit_stock.html.twig
Normal file
49
templates/drink_type/bulk_edit_stock.html.twig
Normal file
|
@ -0,0 +1,49 @@
|
|||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Bulk Edit Drink Type Wanted Stock{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="container mt-4">
|
||||
<h1>Bulk Edit Drink Type Wanted Stock</h1>
|
||||
|
||||
{% for message in app.flashes('success') %}
|
||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
{{ message }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{{ form_start(form) }}
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Drink Type</th>
|
||||
<th>Wanted Stock</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for drinkTypeForm in form.drinkTypes %}
|
||||
<tr>
|
||||
<td>
|
||||
{{ form_widget(drinkTypeForm.id) }}
|
||||
{{ form_widget(drinkTypeForm.name) }}
|
||||
</td>
|
||||
<td>
|
||||
{{ form_widget(drinkTypeForm.wantedStock) }}
|
||||
{{ form_errors(drinkTypeForm.wantedStock) }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="mt-3">
|
||||
{{ form_widget(form.save) }}
|
||||
</div>
|
||||
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,4 +0,0 @@
|
|||
<form method="post" action="{{ path('app_inventory_record_delete', {'id': inventory_record.id}) }}" onsubmit="return confirm('Are you sure you want to delete this item?');">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token('delete' ~ inventory_record.id) }}">
|
||||
<button class="btn">Delete</button>
|
||||
</form>
|
|
@ -1,4 +0,0 @@
|
|||
{{ form_start(form) }}
|
||||
{{ form_widget(form) }}
|
||||
<button class="btn">{{ button_label|default('Save') }}</button>
|
||||
{{ form_end(form) }}
|
|
@ -1,7 +0,0 @@
|
|||
{{ form_start(form, {'attr': {'hx-post': form.vars.action, 'hx-target': '#htmxModalBody'}}) }}
|
||||
{{ form_widget(form) }}
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||
<button type="submit" class="btn btn-primary">{{ button_label|default('Save') }}</button>
|
||||
</div>
|
||||
{{ form_end(form) }}
|
|
@ -1,13 +0,0 @@
|
|||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Edit InventoryRecord{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Edit InventoryRecord</h1>
|
||||
|
||||
{{ include('inventory_record/_form.html.twig', {'button_label': 'Update'}) }}
|
||||
|
||||
<a href="{{ path('app_inventory_record_index') }}">back to list</a>
|
||||
|
||||
{{ include('inventory_record/_delete_form.html.twig') }}
|
||||
{% endblock %}
|
|
@ -1,41 +0,0 @@
|
|||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}InventoryRecord index{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>InventoryRecord index</h1>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th>Quantity</th>
|
||||
<th>Timestamp</th>
|
||||
<th>CreatedAt</th>
|
||||
<th>UpdatedAt</th>
|
||||
<th>actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for inventory_record in inventory_records %}
|
||||
<tr>
|
||||
<td>{{ inventory_record.id }}</td>
|
||||
<td>{{ inventory_record.quantity }}</td>
|
||||
<td>{{ inventory_record.timestamp ? inventory_record.timestamp|date('Y-m-d H:i:s') : '' }}</td>
|
||||
<td>{{ inventory_record.createdAt ? inventory_record.createdAt|date('Y-m-d H:i:s') : '' }}</td>
|
||||
<td>{{ inventory_record.updatedAt ? inventory_record.updatedAt|date('Y-m-d H:i:s') : '' }}</td>
|
||||
<td>
|
||||
<a href="{{ path('app_inventory_record_show', {'id': inventory_record.id}) }}">show</a>
|
||||
<a href="{{ path('app_inventory_record_edit', {'id': inventory_record.id}) }}">edit</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="6">no records found</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a href="{{ path('app_inventory_record_new') }}">Create new</a>
|
||||
{% endblock %}
|
|
@ -1,11 +0,0 @@
|
|||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}New InventoryRecord{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Create new InventoryRecord</h1>
|
||||
|
||||
{{ include('inventory_record/_form.html.twig') }}
|
||||
|
||||
<a href="{{ path('app_inventory_record_index') }}">back to list</a>
|
||||
{% endblock %}
|
|
@ -1,38 +0,0 @@
|
|||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}InventoryRecord{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>InventoryRecord</h1>
|
||||
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<td>{{ inventory_record.id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Quantity</th>
|
||||
<td>{{ inventory_record.quantity }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Timestamp</th>
|
||||
<td>{{ inventory_record.timestamp ? inventory_record.timestamp|date('Y-m-d H:i:s') : '' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>CreatedAt</th>
|
||||
<td>{{ inventory_record.createdAt ? inventory_record.createdAt|date('Y-m-d H:i:s') : '' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>UpdatedAt</th>
|
||||
<td>{{ inventory_record.updatedAt ? inventory_record.updatedAt|date('Y-m-d H:i:s') : '' }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a href="{{ path('app_inventory_record_index') }}">back to list</a>
|
||||
|
||||
<a href="{{ path('app_inventory_record_edit', {'id': inventory_record.id}) }}">edit</a>
|
||||
|
||||
{{ include('inventory_record/_delete_form.html.twig') }}
|
||||
{% endblock %}
|
|
@ -84,7 +84,7 @@ test('CreateNewOrderItems adds order items for wanted drink types', function ():
|
|||
expect($orderItem2->getQuantity())->toBe(6); // 8 wanted - 2 current = 6 to order
|
||||
|
||||
// Verify that drink types 3 and 4 don't have order items
|
||||
$drinkType3Names = array_map(fn($item) => $item->getDrinkType()->getName(), $orderItems->toArray());
|
||||
$drinkType3Names = array_map(fn($item): string => $item->getDrinkType()->getName(), $orderItems->toArray());
|
||||
expect($drinkType3Names)->not->toContain('Drink Type 3');
|
||||
expect($drinkType3Names)->not->toContain('Drink Type 4');
|
||||
});
|
||||
|
|
204
tests/Feature/Web/BulkEditFormTest.php
Normal file
204
tests/Feature/Web/BulkEditFormTest.php
Normal file
|
@ -0,0 +1,204 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Entity\DrinkType;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
test('Bulk Edit Form displays correctly with drink types', function (): void {
|
||||
$this->ensureKernelShutdown();
|
||||
$client = static::createClient();
|
||||
|
||||
// Create test drink types
|
||||
$em = $this->getContainer()->get(EntityManagerInterface::class);
|
||||
|
||||
$drinkType1 = new DrinkType();
|
||||
$drinkType1->setName('Cola');
|
||||
$drinkType1->setWantedStock(10);
|
||||
$drinkType1->setCurrentStock(5);
|
||||
|
||||
$drinkType2 = new DrinkType();
|
||||
$drinkType2->setName('Beer');
|
||||
$drinkType2->setWantedStock(20);
|
||||
$drinkType2->setCurrentStock(15);
|
||||
|
||||
$em->persist($drinkType1);
|
||||
$em->persist($drinkType2);
|
||||
$em->flush();
|
||||
|
||||
// Request the bulk edit page
|
||||
$crawler = $client->request('GET', '/drink-types/bulk-edit-stock');
|
||||
|
||||
// Validate successful response
|
||||
$this->assertResponseIsSuccessful();
|
||||
|
||||
// Check page title
|
||||
$this->assertSelectorTextContains('h1', 'Bulk Edit Drink Type Wanted Stock');
|
||||
|
||||
// Check that drink types are displayed in the table (they're in the value attribute of disabled inputs)
|
||||
$this->assertSelectorExists('input[value="Cola"]');
|
||||
$this->assertSelectorExists('input[value="Beer"]');
|
||||
|
||||
// Check that the form has the correct submit button
|
||||
$this->assertSelectorTextContains('button[type="submit"]', 'Update Wanted Stock Levels');
|
||||
|
||||
// Check that input fields exist for each drink type
|
||||
$this->assertCount(2, $crawler->filter('input[name*="[wantedStock]"]'));
|
||||
});
|
||||
|
||||
test('Bulk Edit Form submission updates drink type wanted stock levels', function (): void {
|
||||
$this->ensureKernelShutdown();
|
||||
$client = static::createClient();
|
||||
|
||||
// Create test drink types
|
||||
$em = $this->getContainer()->get(EntityManagerInterface::class);
|
||||
|
||||
$drinkType1 = new DrinkType();
|
||||
$drinkType1->setName('Cola');
|
||||
$drinkType1->setWantedStock(10);
|
||||
$drinkType1->setCurrentStock(5);
|
||||
|
||||
$drinkType2 = new DrinkType();
|
||||
$drinkType2->setName('Beer');
|
||||
$drinkType2->setWantedStock(20);
|
||||
$drinkType2->setCurrentStock(15);
|
||||
|
||||
$em->persist($drinkType1);
|
||||
$em->persist($drinkType2);
|
||||
$em->flush();
|
||||
|
||||
// Get the bulk edit page to get the form
|
||||
$crawler = $client->request('GET', '/drink-types/bulk-edit-stock');
|
||||
|
||||
// Submit the form with updated values
|
||||
$form = $crawler->selectButton('Update Wanted Stock Levels')->form();
|
||||
|
||||
// Update the wanted stock values - note: drink types are ordered by wantedStock DESC
|
||||
// So Beer (wantedStock 20) comes first [0], Cola (wantedStock 10) comes second [1]
|
||||
$form['bulk_edit_drink_type_stock_form[drinkTypes][0][wantedStock]'] = 25; // Beer
|
||||
$form['bulk_edit_drink_type_stock_form[drinkTypes][1][wantedStock]'] = 15; // Cola
|
||||
|
||||
$client->submit($form);
|
||||
|
||||
// Check that we're redirected back to the same page
|
||||
$this->assertResponseRedirects('/drink-types/bulk-edit-stock');
|
||||
|
||||
// Follow the redirect
|
||||
$client->followRedirect();
|
||||
|
||||
// Check for success message
|
||||
$this->assertSelectorTextContains('.alert-success', 'Wanted stock levels updated successfully!');
|
||||
|
||||
// Verify the database was updated
|
||||
$em->clear(); // Clear entity manager to reload from database
|
||||
|
||||
$updatedDrinkType1 = $em->find(DrinkType::class, $drinkType1->getId());
|
||||
$updatedDrinkType2 = $em->find(DrinkType::class, $drinkType2->getId());
|
||||
|
||||
expect($updatedDrinkType1->getWantedStock())->toBe(15); // Cola
|
||||
expect($updatedDrinkType2->getWantedStock())->toBe(25); // Beer
|
||||
});
|
||||
|
||||
test('Bulk Edit Form handles empty drink types list', function (): void {
|
||||
$this->ensureKernelShutdown();
|
||||
$client = static::createClient();
|
||||
|
||||
// Clear existing drink types
|
||||
$em = $this->getContainer()->get(EntityManagerInterface::class);
|
||||
$drinkTypeRepository = $em->getRepository(DrinkType::class);
|
||||
$existingDrinkTypes = $drinkTypeRepository->findAll();
|
||||
foreach ($existingDrinkTypes as $drinkType) {
|
||||
$em->remove($drinkType);
|
||||
}
|
||||
$em->flush();
|
||||
|
||||
// Request the bulk edit page
|
||||
$crawler = $client->request('GET', '/drink-types/bulk-edit-stock');
|
||||
|
||||
// Validate successful response
|
||||
$this->assertResponseIsSuccessful();
|
||||
|
||||
// Check page title
|
||||
$this->assertSelectorTextContains('h1', 'Bulk Edit Drink Type Wanted Stock');
|
||||
|
||||
// Check that the table exists but has no rows (no tbody content)
|
||||
$this->assertSelectorExists('table');
|
||||
$this->assertCount(0, $crawler->filter('table tbody tr'));
|
||||
|
||||
// Check that the form still has the submit button
|
||||
$this->assertSelectorTextContains('button[type="submit"]', 'Update Wanted Stock Levels');
|
||||
});
|
||||
|
||||
test('Bulk Edit Form rejects negative values (validation)', function (): void {
|
||||
$this->ensureKernelShutdown();
|
||||
$client = static::createClient();
|
||||
|
||||
// Create test drink type
|
||||
$em = $this->getContainer()->get(EntityManagerInterface::class);
|
||||
|
||||
$drinkType = new DrinkType();
|
||||
$drinkType->setName('Test Drink');
|
||||
$drinkType->setWantedStock(10);
|
||||
$drinkType->setCurrentStock(5);
|
||||
|
||||
$em->persist($drinkType);
|
||||
$em->flush();
|
||||
|
||||
// Get the bulk edit page
|
||||
$crawler = $client->request('GET', '/drink-types/bulk-edit-stock');
|
||||
|
||||
// Submit the form with negative value
|
||||
$form = $crawler->selectButton('Update Wanted Stock Levels')->form();
|
||||
$form['bulk_edit_drink_type_stock_form[drinkTypes][0][wantedStock]'] = -5;
|
||||
|
||||
$client->submit($form);
|
||||
|
||||
// The form should NOT redirect, but show the validation error
|
||||
$this->assertResponseIsSuccessful();
|
||||
$this->assertSelectorTextContains('h1', 'Bulk Edit Drink Type Wanted Stock');
|
||||
$this->assertSelectorTextContains('.form-error-message, .invalid-feedback', 'Wanted stock must not be negative');
|
||||
|
||||
// Verify the database was not updated
|
||||
$em->clear();
|
||||
$updatedDrinkType = $em->find(DrinkType::class, $drinkType->getId());
|
||||
expect($updatedDrinkType->getWantedStock())->toBe(10); // Should remain unchanged
|
||||
});
|
||||
|
||||
test('Bulk Edit Form preserves drink type names as read-only', function (): void {
|
||||
$this->ensureKernelShutdown();
|
||||
$client = static::createClient();
|
||||
|
||||
// Create test drink type
|
||||
$em = $this->getContainer()->get(EntityManagerInterface::class);
|
||||
|
||||
$drinkType = new DrinkType();
|
||||
$drinkType->setName('Original Name');
|
||||
$drinkType->setWantedStock(10);
|
||||
$drinkType->setCurrentStock(5);
|
||||
|
||||
$em->persist($drinkType);
|
||||
$em->flush();
|
||||
|
||||
// Get the bulk edit page
|
||||
$crawler = $client->request('GET', '/drink-types/bulk-edit-stock');
|
||||
|
||||
// Check that the name field is read-only
|
||||
$nameInput = $crawler->filter('input[name*="[name]"]')->first();
|
||||
expect($nameInput->attr('readonly'))->toBe('readonly');
|
||||
expect($nameInput->attr('disabled'))->toBe('disabled');
|
||||
|
||||
// Submit the form
|
||||
$form = $crawler->selectButton('Update Wanted Stock Levels')->form();
|
||||
$form['bulk_edit_drink_type_stock_form[drinkTypes][0][wantedStock]'] = 15;
|
||||
|
||||
$client->submit($form);
|
||||
|
||||
// Follow the redirect
|
||||
$client->followRedirect();
|
||||
|
||||
// Verify the name was not changed
|
||||
$em->clear();
|
||||
$updatedDrinkType = $em->find(DrinkType::class, $drinkType->getId());
|
||||
expect($updatedDrinkType->getName())->toBe('Original Name');
|
||||
expect($updatedDrinkType->getWantedStock())->toBe(15);
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue