Organization Controller Tests

This commit is contained in:
Charles 2026-01-06 14:29:29 +01:00
parent 68864b3997
commit d26d1cb118
13 changed files with 501 additions and 24 deletions

View File

@ -8,6 +8,8 @@ export default class extends Controller {
id: String, id: String,
activities: Boolean, activities: Boolean,
table: Boolean, table: Boolean,
sadmin: Boolean,
user: Number
}; };
static targets = ["activityList", "emptyMessage"] static targets = ["activityList", "emptyMessage"]
@ -18,7 +20,7 @@ export default class extends Controller {
this.loadActivities(); this.loadActivities();
}, 60000); // Refresh every 60 seconds }, 60000); // Refresh every 60 seconds
} }
if (this.tableValue){ if (this.tableValue && this.sadminValue) {
this.table(); this.table();
} }
@ -31,7 +33,7 @@ export default class extends Controller {
placeholder: "Aucun résultat trouvé pour cette recherche", placeholder: "Aucun résultat trouvé pour cette recherche",
locale: "fr", //'en' for English, 'fr' for French (en is default, no need to include it) locale: "fr", //'en' for English, 'fr' for French (en is default, no need to include it)
ajaxURL: "/organization/data", ajaxURL: `/organization/data/${this.userValue}`,
ajaxConfig: "GET", ajaxConfig: "GET",
pagination: true, pagination: true,
paginationMode: "remote", paginationMode: "remote",

View File

@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20260105152103 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE UNIQUE INDEX UNIQ_IDENTIFIER_EMAIL ON organizations (email)');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE SCHEMA public');
$this->addSql('DROP INDEX UNIQ_IDENTIFIER_EMAIL');
}
}

View File

@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20260106080636 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE UNIQUE INDEX UNIQ_ORGANIZATION_EMAIL ON organizations (email)');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE SCHEMA public');
$this->addSql('DROP INDEX UNIQ_ORGANIZATION_EMAIL');
}
}

View File

@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20260106084653 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE organizations ALTER logo_url DROP NOT NULL');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE SCHEMA public');
$this->addSql('ALTER TABLE organizations ALTER logo_url SET NOT NULL');
}
}

View File

@ -16,7 +16,10 @@ use App\Service\LoggerService;
use App\Service\OrganizationsService; use App\Service\OrganizationsService;
use App\Service\UserOrganizationService; use App\Service\UserOrganizationService;
use App\Service\UserService; use App\Service\UserService;
use Doctrine\DBAL\Exception\NonUniqueFieldNameException;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\NonUniqueResultException;
use Exception; use Exception;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
@ -48,15 +51,19 @@ class OrganizationController extends AbstractController
public function index(): Response public function index(): Response
{ {
$this->denyAccessUnlessGranted('ROLE_ADMIN'); $this->denyAccessUnlessGranted('ROLE_ADMIN');
$actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier());
if($this->userService->hasAccessTo($actingUser, true)){
$orgCount = $this->organizationsRepository->count(['isDeleted' => false]); $orgCount = $this->organizationsRepository->count(['isDeleted' => false]);
return $this->render('organization/index.html.twig', [ return $this->render('organization/index.html.twig', [
'hasOrganizations' => $orgCount > 0 'hasOrganizations' => $orgCount > 0
]); ]);
} }
$this->loggerService->logAccessDenied($actingUser->getId());
throw new AccessDeniedHttpException('Access denied');
}
#[Route(path: '/new', name: 'new', methods: ['GET', 'POST'])] #[Route(path: '/create', name: 'create', methods: ['GET', 'POST'])]
public function new(Request $request): Response public function new(Request $request): Response
{ {
$this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN'); $this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN');
@ -79,6 +86,7 @@ class OrganizationController extends AbstractController
return $this->redirectToRoute('organization_index'); return $this->redirectToRoute('organization_index');
} catch (Exception $e) { } catch (Exception $e) {
$this->addFlash('error', 'Error creating organization: ' . $e->getMessage()); $this->addFlash('error', 'Error creating organization: ' . $e->getMessage());
$this->loggerService->logError('Error creating organization', ['acting_user_id' => $actingUser->getId(), 'error' => $e->getMessage()]);
} }
} }
return $this->render('organization/new.html.twig', [ return $this->render('organization/new.html.twig', [
@ -266,7 +274,7 @@ class OrganizationController extends AbstractController
} }
// API endpoint to fetch organization data for Tabulator // API endpoint to fetch organization data for Tabulator
#[Route(path: '/data', name: 'data', methods: ['GET'])] #[Route(path: '/data/{id}', name: 'data', methods: ['GET'])]
public function data(Request $request): JsonResponse public function data(Request $request): JsonResponse
{ {
$this->denyAccessUnlessGranted('ROLE_ADMIN'); $this->denyAccessUnlessGranted('ROLE_ADMIN');

View File

@ -4,10 +4,13 @@ namespace App\Entity;
use App\Repository\OrganizationsRepository; use App\Repository\OrganizationsRepository;
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: OrganizationsRepository::class)] #[ORM\Entity(repositoryClass: OrganizationsRepository::class)]
#[ORM\UniqueConstraint(name: 'UNIQ_ORGANIZATION_EMAIL', fields: ['email'])]
#[UniqueEntity(fields: ['email'], message: 'Une organisation avec cet email existe déjà.')]
class Organizations class Organizations
{ {
#[ORM\Id] #[ORM\Id]
@ -24,7 +27,7 @@ class Organizations
#[ORM\Column(length: 255)] #[ORM\Column(length: 255)]
private ?string $address = null; private ?string $address = null;
#[ORM\Column(length: 255)] #[ORM\Column(length: 255, nullable: true)]
private ?string $logo_url = null; private ?string $logo_url = null;
#[ORM\Column(options: ['default' => 'CURRENT_TIMESTAMP'])] #[ORM\Column(options: ['default' => 'CURRENT_TIMESTAMP'])]

View File

@ -9,7 +9,6 @@ use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface; use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
#[ORM\Entity(repositoryClass: UserRepository::class)] #[ORM\Entity(repositoryClass: UserRepository::class)]
#[ORM\Table(name: '`user`')] #[ORM\Table(name: '`user`')]

View File

@ -17,8 +17,8 @@ class OrganizationForm extends AbstractType
$builder $builder
->add('email', EmailType::class, ['required' => true, 'label' => 'Email*']) ->add('email', EmailType::class, ['required' => true, 'label' => 'Email*'])
->add('name', TextType::class, ['required' => true, 'label' => 'Nom de l\'organisation*']) ->add('name', TextType::class, ['required' => true, 'label' => 'Nom de l\'organisation*'])
->add('address', TextType::class, ['required' => false, 'label' => 'Adresse']) ->add('address', TextType::class, ['required' => true, 'label' => 'Adresse'])
->add('number', TextType::class, ['required' => false, 'label' => 'Numéro de téléphone']) ->add('number', TextType::class, ['required' => true, 'label' => 'Numéro de téléphone'])
->add('logoUrl', FileType::class, [ ->add('logoUrl', FileType::class, [
'required' => false, 'required' => false,
'label' => 'Logo', 'label' => 'Logo',

View File

@ -5,9 +5,6 @@
<div class="card no-header-bg p-3 m-3"> <div class="card no-header-bg p-3 m-3">
<div class="card-header border-0"> <div class="card-header border-0">
<h2>Modifier l'organisation</h2> <h2>Modifier l'organisation</h2>
{% if is_granted("ROLE_SUPER_ADMIN") %}
{# <a href="{{ path('organization_delete', {'id': organization.id}) }}" class="btn btn-danger">Supprimer</a>#}
{% endif %}
</div> </div>
<div class="card-body"> <div class="card-body">

View File

@ -11,7 +11,7 @@
</div> </div>
{% if is_granted("ROLE_SUPER_ADMIN") %} {% if is_granted("ROLE_SUPER_ADMIN") %}
<a href="{{ path('organization_new') }}" class="btn btn-primary">Ajouter une organisation</a> <a href="{{ path('organization_create') }}" class="btn btn-primary">Ajouter une organisation</a>
{% endif %} {% endif %}
</div> </div>
@ -21,7 +21,7 @@
<div class="div text-center my-5 py-5"> <div class="div text-center my-5 py-5">
<h1 class="my-5 ty-5"> Aucune organisation trouvée. </h1> <h1 class="my-5 ty-5"> Aucune organisation trouvée. </h1>
<a href="{{ path('organization_new') }}" class="btn btn-primary">Créer une organisation</a> <a href="{{ path('organization_create') }}" class="btn btn-primary">Créer une organisation</a>
</div> </div>
{% else %} {% else %}
@ -29,6 +29,8 @@
<div id="tabulator-org" <div id="tabulator-org"
data-controller="organization" data-controller="organization"
data-organization-table-value="true" data-organization-table-value="true"
data-organization-user-value={{ app.user.getId() }}
data-organization-sadmin-value="{{ is_granted('ROLE_SUPER_ADMIN') ? true : false }}"
data-organization-aws-value="{{ aws_url }}"> data-organization-aws-value="{{ aws_url }}">
</div> </div>

View File

@ -6,13 +6,20 @@
<div class="w-100 h-100 p-5 m-auto"> <div class="w-100 h-100 p-5 m-auto">
<div class="card no-header-bg p-3 m-3"> <div class="card no-header-bg p-3 m-3">
<div class="card-header border-0"> <div class="card-header border-0">
{% for type, messages in app.flashes %}
{% for message in messages %}
<div class="alert alert-{{ type }}">
{{ message }}
</div>
{% endfor %}
{% endfor %}
<div class="card-title d-flex justify-content-between align-items-center"> <div class="card-title d-flex justify-content-between align-items-center">
<h1>Ajouter une organisation</h1> <h1>Ajouter une organisation</h1>
</div> </div>
</div> </div>
<div class="card-body"> <div class="card-body">
<form method="post" action="{{ path('organization_new') }}" enctype="multipart/form-data"> <form method="post" action="{{ path('organization_create') }}" enctype="multipart/form-data">
{{ form_start(form) }} {{ form_start(form) }}
{{ form_widget(form) }} {{ form_widget(form) }}
<button type="submit" class="btn btn-primary">Enregistrer</button> <button type="submit" class="btn btn-primary">Enregistrer</button>

View File

@ -0,0 +1,359 @@
<?php
namespace App\Tests\Controller;
use App\Entity\Apps;
use App\Entity\Organizations;
use App\Entity\Roles;
use App\Entity\UserOrganizatonApp;
use App\Entity\UsersOrganizations;
use App\Service\AwsService;
use App\Tests\Functional\AbstractFunctionalTest;
use PHPUnit\Framework\Attributes\Test;
use Symfony\Component\HttpFoundation\File\UploadedFile;
class OrganizationControllerTest extends AbstractFunctionalTest
{
//region INDEX tests
#[Test]
public function test_index_super_admin_success(): void
{
// 1. Arrange
$admin = $this->createUser('sAdmin@test.com', ['ROLE_SUPER_ADMIN']);
$this->client->loginUser($admin);
// Create at least one org so 'hasOrganizations' becomes true
$this->createOrganization('Organization 1');
$this->createOrganization('Organization 2');
$this->client->request('GET', '/organization/');
self::assertResponseIsSuccessful();
self::assertSelectorTextNotContains('body', 'Aucune organisation trouvée');
self::assertSelectorExists('#tabulator-org');
}
#[Test]
public function test_index_regular_user_forbidden(): void
{
// 1. Arrange
$user = $this->createUser('user@mail.com');
$this->client->loginUser($user);
// 2. Act
$this->client->request('GET', '/organization/');
// 3. Assert
self::assertResponseStatusCodeSame(403);
}
#[Test]
public function test_index_no_organizations(): void
{
// 1. Arrange
$admin = $this->createUser('user@mail.com', ['ROLE_SUPER_ADMIN']);
$this->client->loginUser($admin);
// 2. Act
$this->client->request('GET', '/organization/');
// 3. Assert
self::assertResponseIsSuccessful();
self::assertSelectorTextContains('body', 'Aucune organisation trouvée');
}
//endregion
//region CREATE tests
#[Test]
public function test_create_super_admin_success(): void
{
// 1. Arrange: Disable reboot to keep our AWS mock alive
$this->client->disableReboot();
$admin = $this->createUser('admin@user.com', ['ROLE_SUPER_ADMIN']);
$this->client->loginUser($admin);
// 2. MOCK AWS Service (Crucial!)
// Your code calls $awsService->PutDocObj, so we must intercept that.
// 2. MOCK AWS Service
$awsMock = $this->createMock(AwsService::class);
$awsMock->expects($this->any())
->method('PutDocObj')
->willReturn(1); // <--- FIXED: Return an integer, not a boolean
// Inject the mock into the test container
static::getContainer()->set(AwsService::class, $awsMock);
// 3. Create a Dummy Image File
$tempFile = tempnam(sys_get_temp_dir(), 'test_logo');
file_put_contents($tempFile, 'fake image content'); // Create a dummy file
$logo = new UploadedFile(
$tempFile,
'logo.png',
'image/png',
null,
true // 'test' mode = true
);
// 4. Act: Request the page
$this->client->request('GET', '/organization/create');
// 5. Submit Form with the FILE object and correct field name 'logoUrl'
$this->client->submitForm('Enregistrer', [
'organization_form[name]' => 'New Organization',
'organization_form[email]' => 'unique-' . uniqid('', true) . '@test.com',
'organization_form[address]' => '123 Test Street',
'organization_form[number]' => '0102030405',
'organization_form[logoUrl]' => $logo, // Pass the OBJECT, not a string
]);
// 6. Assert
// Check for redirect (302)
self::assertResponseRedirects('/organization/');
$this->client->followRedirect();
// Ensure we see the success state
self::assertSelectorTextNotContains('body', 'Aucune organisation trouvée');
self::assertSelectorExists('#tabulator-org');
}
#[Test]
public function test_create_regular_user_forbidden(): void
{
// 1. Arrange
$user = $this->createUser('user@email.com');
$this->client->loginUser($user);
// 2. Act
$this->client->request('GET', '/organization/create');
// 3. Assert
self::assertResponseStatusCodeSame(403);
}
#[Test]
public function test_create_super_admin_invalid_data(): void
{
// 1. Arrange
$admin = $this->createUser('admin@email.com', ['ROLE_SUPER_ADMIN']);
$this->client->loginUser($admin);
// 2. Act
$this->client->request('GET', '/organization/create');
$this->client->submitForm('Enregistrer', [
'organization_form[name]' => '', // Invalid: name is required
'organization_form[email]' => 'not-an-email', // Invalid email format
'organization_form[address]' => '123 Test St',
'organization_form[number]' => '0102030405',
]);
// 3. Assert
self::assertResponseIsSuccessful(); // Form isn't redirected
}
#[Test]
public function test_create_super_admin_duplicate_email(): void
{
// 1. Arrange
$admin = $this->createUser('admin@email.com', ['ROLE_SUPER_ADMIN']);
$this->client->loginUser($admin);
$existingOrg = $this->createOrganization('Existing Org');
// 2. Act
$this->client->request('GET', '/organization/create');
$this->client->submitForm('Enregistrer', [
'organization_form[name]' => 'New Org',
'organization_form[email]' => $existingOrg->getEmail(), // Duplicate email
'organization_form[address]' => '123 Test St',
'organization_form[number]' => '0102030405',
]);
// 3. Assert
self::assertResponseIsSuccessful(); // Form isn't redirected
self::assertSelectorTextContains('body', 'Une organisation avec cet email existe déjà.');
}
//endregion
//region EDIT tests
#[Test]
public function test_edit_super_admin_success(): void
{
// 1. Arrange: Disable reboot to keep our AWS mock alive
$this->client->disableReboot();
$admin = $this->createUser('admin@user.com', ['ROLE_SUPER_ADMIN']);
$this->client->loginUser($admin);
// 2. MOCK AWS Service (Crucial!)
// Your code calls $awsService->PutDocObj, so we must intercept that.
// 2. MOCK AWS Service
$awsMock = $this->createMock(AwsService::class);
$awsMock->expects($this->any())
->method('PutDocObj')
->willReturn(1); // <--- FIXED: Return an integer, not a boolean
// Inject the mock into the test container
static::getContainer()->set(AwsService::class, $awsMock);
// 3. Create a Dummy Image File
$tempFile = tempnam(sys_get_temp_dir(), 'test_logo');
file_put_contents($tempFile, 'fake image content'); // Create a dummy file
$logo = new UploadedFile(
$tempFile,
'logo.png',
'image/png',
null,
true // 'test' mode = true
);
// Create an organization to edit
$organization = $this->createOrganization('Org to Edit');
// 4. Act: Request the edit page
$this->client->request('GET', '/organization/edit/' . $organization->getId());
// 5. Submit Form with the FILE object and correct field name 'logoUrl'
$this->client->submitForm('Enregistrer', [
'organization_form[name]' => 'Edited Organization',
'organization_form[email]' => 'edited-' . uniqid('', true) . '@test.com',
'organization_form[address]' => '456 Edited Street',
'organization_form[number]' => '0504030201',
'organization_form[logoUrl]' => $logo, // Pass the OBJECT, not a
]);
// 6. Assert
// Check for redirect (302)
self::assertResponseRedirects('/organization/');
$this->client->followRedirect();
// Ensure we see the success state
self::assertSelectorTextNotContains('body', 'Aucune organisation trouvée');
self::assertSelectorExists('#tabulator-org');
}
#[Test]
public function test_edit_regular_user_forbidden(): void
{
// 1. Arrange
$user = $this->createUser('user@email.com');
$this->client->loginUser($user);
// Create an organization to edit
$organization = $this->createOrganization('Org to Edit');
// 2. Act
$this->client->request('GET', '/organization/edit/' . $organization->getId());
// 3. Assert
self::assertResponseStatusCodeSame(403);
}
#[Test]
public function test_edit_super_admin_invalid_data(): void
{
// 1. Arrange
$admin = $this->createUser('admin@mail.com', ['ROLE_SUPER_ADMIN']);
$this->client->loginUser($admin);
// Create an organization to edit
$organization = $this->createOrganization('Org to Edit');
// 2. Act
$this->client->request('GET', '/organization/edit/' . $organization->getId());
$this->client->submitForm('Enregistrer', [
'organization_form[name]' => '', // Invalid: name is required
'organization_form[email]' => 'not-an-email', // Invalid email format
'organization_form[address]' => '123 Test St',
'organization_form[number]' => '0102030405',
]);
// 3. Assert
self::assertResponseIsSuccessful(); // Form isn't redirected
}
#[Test]
public function test_edit_nonexistent_organization_not_found(): void
{
// 1. Arrange
$admin = $this->createUser('admin@mail.com', ['ROLE_SUPER_ADMIN']);
$this->client->loginUser($admin);
// 2. Act
$this->client->request('GET', '/organization/edit/99999'); // Assuming
// 3. Assert
self::assertResponseStatusCodeSame(302);
self::assertResponseRedirects('/organization/');
}
//endregion
//region DELETE tests
#[Test]
public function test_delete_super_admin_success(): void
{
// 1. Arrange
$admin = $this->createUser('admin@email.com', ['ROLE_SUPER_ADMIN']);
$this->client->loginUser($admin);
$organization = $this->createOrganization('Org to Delete');
// 2. Act
$this->client->request('POST', '/organization/delete/' . $organization->getId());
// 3. Assert
self::assertResponseRedirects('/organization/');
$this->client->followRedirect();
self::assertSelectorTextNotContains('body', 'Org to Delete');
self::assertTrue($this->entityManager->getRepository(Organizations::class)->find($organization->getId())->isDeleted());
}
#[Test]
public function test_delete_regular_user_forbidden(): void
{
// 1. Arrange
$user = $this->createUser('user@mail.com');
$this->client->loginUser($user);
$organization = $this->createOrganization('Org to Delete');
// 2. Act
$this->client->request('POST', '/organization/delete/' . $organization->getId());
// 3. Assert
self::assertResponseStatusCodeSame(403);
}
#[Test]
public function test_delete_nonexistent_organization_not_found(): void
{
// 1. Arrange
$admin = $this->createUser('admin@user.com', ['ROLE_SUPER_ADMIN']);
$this->client->loginUser($admin);
// 2. Act
$this->client->request('POST', '/organization/delete/99999'); // Assuming
// 3. Assert
self::assertResponseStatusCodeSame(404);
}
#[Test]
public function test_delete_organization_with_dependencies(): void
{
// 1. Arrange
$admin = $this->createUser('user@admin.com', ['ROLE_SUPER_ADMIN']);
$this->client->loginUser($admin);
$organization = $this->createOrganization('Org with Deps');
$app = $this->createApp('Dependent App');
$role = $this->createRole('ROLE_USER');
$uoLink = $this->createUOLink($admin, $organization);
$uoaLink = $this->createUOALink($uoLink, $app, $role);
// 2. Act
$this->client->request('POST', '/organization/delete/' . $organization->getId());
// 3. Assert
self::assertResponseRedirects('/organization/');
$this->client->followRedirect();
self::assertSelectorTextContains('body', 'Aucune organisation trouvée');
//link should be deactivated, not deleted
self::assertCount(1, $this->entityManager->getRepository(Apps::class)->findAll());
self::assertCount(1, $this->entityManager->getRepository(Roles::class)->findAll());
self::assertCount(1, $this->entityManager->getRepository(UsersOrganizations::class)->findAll());
self::assertCount(1, $this->entityManager->getRepository(UserOrganizatonApp::class)->findAll());
self::assertTrue($this->entityManager->getRepository(Organizations::class)->find($organization->getId())->isDeleted());
self::assertFalse($this->entityManager->getRepository(UserOrganizatonApp::class)->find($uoLink->getId())->isActive());
self::assertFalse($this->entityManager->getRepository(UserOrganizatonApp::class)->find($uoaLink->getId())->isActive());
self::assertSelectorNotExists('#tabulator-org');
}
//endregion
}

View File

@ -66,7 +66,6 @@ abstract class AbstractFunctionalTest extends WebTestCase
$org->setNumber(100 + rand(1, 900)); // Example number $org->setNumber(100 + rand(1, 900)); // Example number
$org->setAddress('123 ' . $name . ' St'); // Example address $org->setAddress('123 ' . $name . ' St'); // Example address
$org->setLogoUrl('https://example.com/org_logo.png'); $org->setLogoUrl('https://example.com/org_logo.png');
// Add other required fields if Organizations has non-nullable columns
$this->entityManager->persist($org); $this->entityManager->persist($org);
$this->entityManager->flush(); $this->entityManager->flush();
@ -115,4 +114,9 @@ abstract class AbstractFunctionalTest extends WebTestCase
$this->entityManager->flush(); $this->entityManager->flush();
return $notification; return $notification;
} }
protected function countEntities(string $entityClass): int
{
return $this->entityManager->getRepository($entityClass)->count([]);
}
} }