Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 90f8c7b

Browse files
committed
minor #7440 Add tests for the nested embedded properties search fix (javiereguiluz)
This PR was squashed before being merged into the 4.x branch. Discussion ---------- Add tests for the nested embedded properties search fix Add tests for #7427. Commits ------- 18fb3b4 Add tests for the nested embedded properties search fix
2 parents ed9ee4d + 18fb3b4 commit 90f8c7b

10 files changed

Lines changed: 967 additions & 515 deletions

File tree

tests/Functional/Apps/AdminRouteApp/config/reference.php

Lines changed: 520 additions & 509 deletions
Large diffs are not rendered by default.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
namespace EasyCorp\Bundle\EasyAdminBundle\Tests\Functional\Apps\DefaultApp\Controller\Synthetic;
4+
5+
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
6+
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
7+
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
8+
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
9+
use EasyCorp\Bundle\EasyAdminBundle\Tests\Functional\Apps\DefaultApp\Entity\ProjectDomain\Project;
10+
11+
/**
12+
* CRUD controller for testing search on root-level embedded properties.
13+
* Searches in name and price.currency (embedded Money).
14+
*
15+
* @extends AbstractCrudController<Project>
16+
*/
17+
class SearchEmbeddedCrudController extends AbstractCrudController
18+
{
19+
public static function getEntityFqcn(): string
20+
{
21+
return Project::class;
22+
}
23+
24+
public function configureCrud(Crud $crud): Crud
25+
{
26+
return parent::configureCrud($crud)
27+
->setSearchFields(['name', 'price.currency']);
28+
}
29+
30+
public function configureFields(string $pageName): iterable
31+
{
32+
yield IdField::new('id')->hideOnForm();
33+
yield TextField::new('name');
34+
}
35+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace EasyCorp\Bundle\EasyAdminBundle\Tests\Functional\Apps\DefaultApp\Controller\Synthetic;
4+
5+
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
6+
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
7+
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
8+
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
9+
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
10+
use EasyCorp\Bundle\EasyAdminBundle\Tests\Functional\Apps\DefaultApp\Entity\ProjectDomain\Project;
11+
12+
/**
13+
* CRUD controller for testing search on multi-level association traversal.
14+
* Searches in latestRelease.category.name (2-level association chain).
15+
*
16+
* @extends AbstractCrudController<Project>
17+
*/
18+
class SearchMultiLevelAssocCrudController extends AbstractCrudController
19+
{
20+
public static function getEntityFqcn(): string
21+
{
22+
return Project::class;
23+
}
24+
25+
public function configureCrud(Crud $crud): Crud
26+
{
27+
return parent::configureCrud($crud)
28+
->setSearchFields(['latestRelease.category.name']);
29+
}
30+
31+
public function configureFields(string $pageName): iterable
32+
{
33+
yield IdField::new('id')->hideOnForm();
34+
yield TextField::new('name');
35+
yield AssociationField::new('latestRelease');
36+
}
37+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace EasyCorp\Bundle\EasyAdminBundle\Tests\Functional\Apps\DefaultApp\Controller\Synthetic;
4+
5+
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
6+
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
7+
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
8+
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
9+
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
10+
use EasyCorp\Bundle\EasyAdminBundle\Tests\Functional\Apps\DefaultApp\Entity\Synthetic\SearchTestEntity;
11+
12+
/**
13+
* CRUD controller for testing search on association + embedded properties.
14+
* Searches in author.address.city (association to embedded).
15+
*
16+
* @extends AbstractCrudController<SearchTestEntity>
17+
*/
18+
class SearchNestedEmbeddedCrudController extends AbstractCrudController
19+
{
20+
public static function getEntityFqcn(): string
21+
{
22+
return SearchTestEntity::class;
23+
}
24+
25+
public function configureCrud(Crud $crud): Crud
26+
{
27+
return parent::configureCrud($crud)
28+
->setSearchFields(['author.address.city']);
29+
}
30+
31+
public function configureFields(string $pageName): iterable
32+
{
33+
yield IdField::new('id')->hideOnForm();
34+
yield TextField::new('searchableTextField');
35+
yield AssociationField::new('author');
36+
}
37+
}

tests/Functional/Apps/DefaultApp/src/DataFixtures/AppFixtures.php

Lines changed: 91 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@
88
use EasyCorp\Bundle\EasyAdminBundle\Tests\Functional\Apps\DefaultApp\Entity\BlogPost;
99
use EasyCorp\Bundle\EasyAdminBundle\Tests\Functional\Apps\DefaultApp\Entity\Category;
1010
use EasyCorp\Bundle\EasyAdminBundle\Tests\Functional\Apps\DefaultApp\Entity\Customer;
11+
use EasyCorp\Bundle\EasyAdminBundle\Tests\Functional\Apps\DefaultApp\Entity\EntityFactory\Address;
1112
use EasyCorp\Bundle\EasyAdminBundle\Tests\Functional\Apps\DefaultApp\Entity\Page;
13+
use EasyCorp\Bundle\EasyAdminBundle\Tests\Functional\Apps\DefaultApp\Entity\ProjectDomain\Developer;
14+
use EasyCorp\Bundle\EasyAdminBundle\Tests\Functional\Apps\DefaultApp\Entity\ProjectDomain\Money;
15+
use EasyCorp\Bundle\EasyAdminBundle\Tests\Functional\Apps\DefaultApp\Entity\ProjectDomain\Project;
16+
use EasyCorp\Bundle\EasyAdminBundle\Tests\Functional\Apps\DefaultApp\Entity\ProjectDomain\ProjectRelease;
17+
use EasyCorp\Bundle\EasyAdminBundle\Tests\Functional\Apps\DefaultApp\Entity\ProjectDomain\ProjectReleaseCategory;
1218
use EasyCorp\Bundle\EasyAdminBundle\Tests\Functional\Apps\DefaultApp\Entity\Synthetic\ActionTestEntity;
1319
use EasyCorp\Bundle\EasyAdminBundle\Tests\Functional\Apps\DefaultApp\Entity\Synthetic\BatchActionTestEntity;
1420
use EasyCorp\Bundle\EasyAdminBundle\Tests\Functional\Apps\DefaultApp\Entity\Synthetic\DefaultCrudTestEntity;
@@ -80,6 +86,8 @@ public function load(ObjectManager $manager): void
8086

8187
$this->addActionTestFixtures($manager);
8288

89+
$this->addProjectDomainSearchFixtures($manager);
90+
8391
$manager->flush();
8492
}
8593

@@ -604,16 +612,17 @@ private function addSearchTestFixtures(ObjectManager $manager): void
604612
// create authors first
605613
$authors = [];
606614
$authorData = [
607-
['name' => 'John Smith', 'email' => '[email protected]'],
608-
['name' => 'Jane Doe', 'email' => '[email protected]'],
609-
['name' => 'Alice Johnson', 'email' => '[email protected]'],
610-
['name' => 'Bob Williams', 'email' => '[email protected]'],
615+
['name' => 'John Smith', 'email' => '[email protected]', 'addressStreet' => 10, 'addressCity' => 'New York'],
616+
['name' => 'Jane Doe', 'email' => '[email protected]', 'addressStreet' => 20, 'addressCity' => 'London'],
617+
['name' => 'Alice Johnson', 'email' => '[email protected]', 'addressStreet' => 30, 'addressCity' => 'New York'],
618+
['name' => 'Bob Williams', 'email' => '[email protected]', 'addressStreet' => 40, 'addressCity' => 'Paris'],
611619
];
612620

613621
foreach ($authorData as $index => $data) {
614622
$author = new SearchTestAuthor();
615623
$author->setName($data['name']);
616624
$author->setEmail($data['email']);
625+
$author->setAddress((new Address())->setStreet($data['addressStreet'])->setCity($data['addressCity']));
617626
$manager->persist($author);
618627
$authors[$index] = $author;
619628
$this->addReference('searchAuthor'.$index, $author);
@@ -721,4 +730,82 @@ private function addActionTestFixtures(ObjectManager $manager): void
721730
$this->addReference('actionTest'.$index, $entity);
722731
}
723732
}
733+
734+
private function addProjectDomainSearchFixtures(ObjectManager $manager): void
735+
{
736+
// create release categories (separate entities because ProjectRelease→category is OneToOne)
737+
$categoryNames = ['Major', 'Minor', 'Major'];
738+
$categories = [];
739+
foreach ($categoryNames as $index => $name) {
740+
$category = new ProjectReleaseCategory();
741+
$category->setName($name);
742+
$manager->persist($category);
743+
$categories[$index] = $category;
744+
}
745+
746+
// create releases
747+
$releaseData = [
748+
['name' => 'v1.0', 'categoryIndex' => 0],
749+
['name' => 'v1.1', 'categoryIndex' => 1],
750+
['name' => 'v2.0', 'categoryIndex' => 2],
751+
];
752+
$releases = [];
753+
foreach ($releaseData as $index => $data) {
754+
$release = new ProjectRelease();
755+
$release->setName($data['name']);
756+
$release->setCategory($categories[$data['categoryIndex']]);
757+
$manager->persist($release);
758+
$releases[$index] = $release;
759+
}
760+
761+
// create developers
762+
$developerNames = ['Alice Dev', 'Bob Dev', 'Carol Dev'];
763+
$developers = [];
764+
foreach ($developerNames as $index => $name) {
765+
$developer = new Developer();
766+
$developer->setName($name);
767+
$manager->persist($developer);
768+
$developers[$index] = $developer;
769+
}
770+
771+
// create projects
772+
$defaultDate = new \DateTime('2024-01-01 10:00:00');
773+
$defaultDateImmutable = new \DateTimeImmutable('2024-01-01 10:00:00');
774+
$defaultTime = new \DateTime('10:00:00');
775+
$defaultTimeImmutable = new \DateTimeImmutable('10:00:00');
776+
777+
$projectData = [
778+
['name' => 'Alpha Project', 'amount' => 1000, 'currency' => 'USD', 'developerIndex' => 0, 'releaseIndex' => 0],
779+
['name' => 'Beta Project', 'amount' => 2000, 'currency' => 'EUR', 'developerIndex' => 1, 'releaseIndex' => 1],
780+
['name' => 'Gamma Project', 'amount' => 3000, 'currency' => 'USD', 'developerIndex' => 2, 'releaseIndex' => 2],
781+
['name' => 'Delta Project', 'amount' => 500, 'currency' => 'GBP', 'developerIndex' => 0, 'releaseIndex' => null],
782+
];
783+
784+
foreach ($projectData as $data) {
785+
$project = new Project();
786+
$project->setName($data['name']);
787+
$project->setPrice((new Money())->setAmount($data['amount'])->setCurrency($data['currency']));
788+
$project->setLeadDeveloper($developers[$data['developerIndex']]);
789+
$project->setDescription('Test project '.$data['name']);
790+
$project->setStartDateMutable(clone $defaultDate);
791+
$project->setStartDateImmutable($defaultDateImmutable);
792+
$project->setStartDateTimeMutable(clone $defaultDate);
793+
$project->setStartDateTimeImmutable($defaultDateImmutable);
794+
$project->setStartDateTimeTzMutable(clone $defaultDate);
795+
$project->setStartDateTimeTzImmutable($defaultDateImmutable);
796+
$project->setCountInteger(1);
797+
$project->setCountSmallint(1);
798+
$project->setPriceDecimal('100');
799+
$project->setPriceFloat(100.0);
800+
$project->setStartTimeMutable(clone $defaultTime);
801+
$project->setStartTimeImmutable($defaultTimeImmutable);
802+
$project->setStatesSimpleArray(['active']);
803+
804+
if (null !== $data['releaseIndex']) {
805+
$project->setLatestRelease($releases[$data['releaseIndex']]);
806+
}
807+
808+
$manager->persist($project);
809+
}
810+
}
724811
}

tests/Functional/Apps/DefaultApp/src/Entity/Synthetic/SearchTestAuthor.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace EasyCorp\Bundle\EasyAdminBundle\Tests\Functional\Apps\DefaultApp\Entity\Synthetic;
44

55
use Doctrine\ORM\Mapping as ORM;
6+
use EasyCorp\Bundle\EasyAdminBundle\Tests\Functional\Apps\DefaultApp\Entity\EntityFactory\Address;
67

78
/**
89
* Author entity for SearchTestEntity relationship testing.
@@ -21,6 +22,14 @@ class SearchTestAuthor
2122
#[ORM\Column(length: 255)]
2223
private ?string $email = null;
2324

25+
#[ORM\Embedded]
26+
private Address $address;
27+
28+
public function __construct()
29+
{
30+
$this->address = new Address();
31+
}
32+
2433
public function getId(): ?int
2534
{
2635
return $this->id;
@@ -50,6 +59,18 @@ public function setEmail(string $email): self
5059
return $this;
5160
}
5261

62+
public function getAddress(): Address
63+
{
64+
return $this->address;
65+
}
66+
67+
public function setAddress(Address $address): self
68+
{
69+
$this->address = $address;
70+
71+
return $this;
72+
}
73+
5374
public function __toString(): string
5475
{
5576
return $this->name ?? '';

tests/Functional/Autocomplete/AutocompleteCustomizationTest.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace EasyCorp\Bundle\EasyAdminBundle\Tests\Functional\Autocomplete;
44

5+
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
56
use Doctrine\ORM\EntityRepository;
67
use EasyCorp\Bundle\EasyAdminBundle\Test\AbstractCrudTestCase;
78
use EasyCorp\Bundle\EasyAdminBundle\Tests\Functional\Apps\DefaultApp\Controller\DashboardController;
@@ -61,7 +62,7 @@ private function createProject(string $name): Project
6162
public function testAutocompleteWithFieldLevelCallback(): void
6263
{
6364
// Create a test project
64-
$project = $this->createProject('Test Project Alpha');
65+
$project = $this->createProject('Unicorn Sparkle');
6566

6667
$this->entityManager->persist($project);
6768
$this->entityManager->flush();
@@ -72,6 +73,7 @@ public function testAutocompleteWithFieldLevelCallback(): void
7273
->setController(ProjectCrudController::class)
7374
->setAction('autocomplete')
7475
->set('page', 1)
76+
->set('query', 'Unicorn Sparkle')
7577
->set('autocompleteContext', [
7678
'crudControllerFqcn' => ProjectIssueWithAutocompleteCrudController::class,
7779
'propertyName' => 'project',
@@ -92,7 +94,7 @@ public function testAutocompleteWithFieldLevelCallback(): void
9294
// The field-level callback should format as "Project: {name} (ID: {id})"
9395
$firstResult = $data['results'][0]['entityAsString'];
9496
$this->assertStringContainsString('Project:', $firstResult);
95-
$this->assertStringContainsString('Test Project Alpha', $firstResult);
97+
$this->assertStringContainsString('Unicorn Sparkle', $firstResult);
9698
$this->assertStringContainsString('(ID:', $firstResult);
9799
}
98100

@@ -175,6 +177,10 @@ public function testAutocompleteEscapesHtmlByDefault(): void
175177

176178
public function testAutocompleteReturnsValidJsonStructure(): void
177179
{
180+
if (!class_exists(PostgreSQLPlatform::class)) {
181+
$this->markTestSkipped('Doctrine DBAL 3.x+ is required.');
182+
}
183+
178184
$project = $this->createProject('JSON Test Project');
179185

180186
$this->entityManager->persist($project);

0 commit comments

Comments
 (0)