diff --git a/composer.json b/composer.json
index d59ef97..7fbd14b 100644
--- a/composer.json
+++ b/composer.json
@@ -106,7 +106,7 @@
"symfony/browser-kit": "7.0.*",
"symfony/css-selector": "7.0.*",
"symfony/debug-bundle": "7.0.*",
- "symfony/maker-bundle": "^1.0",
+ "symfony/maker-bundle": "^1.59",
"symfony/phpunit-bridge": "^7.0",
"symfony/stopwatch": "7.0.*",
"symfony/web-profiler-bundle": "7.0.*"
diff --git a/composer.lock b/composer.lock
index 9e8ea25..75b7896 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "888e1953f86d0f1fe9b271b85aab0ed0",
+ "content-hash": "c3dc9b5ee79b98f2d1fabe3668860864",
"packages": [
{
"name": "composer/semver",
@@ -3507,16 +3507,16 @@
},
{
"name": "symfony/form",
- "version": "v7.0.7",
+ "version": "v7.0.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/form.git",
- "reference": "b4df6a399a2b03782a0163807239db342659f54f"
+ "reference": "1d0128e2f7e80c346ec51fa4d1ce4fec0d435eeb"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/form/zipball/b4df6a399a2b03782a0163807239db342659f54f",
- "reference": "b4df6a399a2b03782a0163807239db342659f54f",
+ "url": "https://api.github.com/repos/symfony/form/zipball/1d0128e2f7e80c346ec51fa4d1ce4fec0d435eeb",
+ "reference": "1d0128e2f7e80c346ec51fa4d1ce4fec0d435eeb",
"shasum": ""
},
"require": {
@@ -3583,7 +3583,7 @@
"description": "Allows to easily create, process and reuse HTML forms",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/form/tree/v7.0.7"
+ "source": "https://github.com/symfony/form/tree/v7.0.8"
},
"funding": [
{
@@ -3599,7 +3599,7 @@
"type": "tidelift"
}
],
- "time": "2024-04-28T11:44:19+00:00"
+ "time": "2024-05-31T14:55:39+00:00"
},
{
"name": "symfony/framework-bundle",
@@ -6887,16 +6887,16 @@
},
{
"name": "symfony/validator",
- "version": "v7.0.7",
+ "version": "v7.0.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/validator.git",
- "reference": "ab4e75b9d23ba70e78480aecbe4d8da15adf10eb"
+ "reference": "23af65dff1f4dfee9aab3a0123a243e40fa3d9cf"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/validator/zipball/ab4e75b9d23ba70e78480aecbe4d8da15adf10eb",
- "reference": "ab4e75b9d23ba70e78480aecbe4d8da15adf10eb",
+ "url": "https://api.github.com/repos/symfony/validator/zipball/23af65dff1f4dfee9aab3a0123a243e40fa3d9cf",
+ "reference": "23af65dff1f4dfee9aab3a0123a243e40fa3d9cf",
"shasum": ""
},
"require": {
@@ -6941,7 +6941,8 @@
"Symfony\\Component\\Validator\\": ""
},
"exclude-from-classmap": [
- "/Tests/"
+ "/Tests/",
+ "/Resources/bin/"
]
},
"notification-url": "https://packagist.org/downloads/",
@@ -6961,7 +6962,7 @@
"description": "Provides tools to validate values",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/validator/tree/v7.0.7"
+ "source": "https://github.com/symfony/validator/tree/v7.0.8"
},
"funding": [
{
@@ -6977,7 +6978,7 @@
"type": "tidelift"
}
],
- "time": "2024-04-28T11:44:19+00:00"
+ "time": "2024-06-02T15:49:03+00:00"
},
{
"name": "symfony/var-dumper",
diff --git a/src/Controller/PostController.php b/src/Controller/PostController.php
index 0df3016..c8cdd5f 100644
--- a/src/Controller/PostController.php
+++ b/src/Controller/PostController.php
@@ -2,19 +2,84 @@
namespace App\Controller;
+use App\Entity\Post;
+use App\Form\PostType;
use App\Repository\PostRepository;
+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;
+use Symfony\Component\Security\Http\Attribute\IsGranted;
+#[Route('/post')]
class PostController extends AbstractController
{
- #[Route('/', name: 'app_posts')]
- public function index(PostRepository $repository): Response
+ #[Route('/', name: 'app_post_index', methods: ['GET'])]
+ public function index(PostRepository $postRepository): Response
{
- $posts = $repository->findAll();
return $this->render('post/index.html.twig', [
- 'posts' => $posts,
+ 'posts' => $postRepository->findAll(),
]);
}
+
+ #[Route('/new', name: 'app_post_new', methods: ['GET', 'POST'])]
+ #[IsGranted('ROLE_USER')]
+ public function new(Request $request, EntityManagerInterface $entityManager): Response
+ {
+ $post = new Post();
+ $form = $this->createForm(PostType::class, $post);
+ $form->handleRequest($request);
+
+ if ($form->isSubmitted() && $form->isValid()) {
+ $entityManager->persist($post);
+ $entityManager->flush();
+
+ return $this->redirectToRoute('app_post_index', [], Response::HTTP_SEE_OTHER);
+ }
+
+ return $this->render('post/new.html.twig', [
+ 'post' => $post,
+ 'form' => $form,
+ ]);
+ }
+
+ #[Route('/{id}', name: 'app_post_show', methods: ['GET'])]
+ public function show(Post $post): Response
+ {
+ return $this->render('post/show.html.twig', [
+ 'post' => $post,
+ ]);
+ }
+
+ #[Route('/{id}/edit', name: 'app_post_edit', methods: ['GET', 'POST'])]
+ #[IsGranted('ROLE_USER')]
+ public function edit(Request $request, Post $post, EntityManagerInterface $entityManager): Response
+ {
+ $form = $this->createForm(PostType::class, $post);
+ $form->handleRequest($request);
+
+ if ($form->isSubmitted() && $form->isValid()) {
+ $entityManager->flush();
+
+ return $this->redirectToRoute('app_post_index', [], Response::HTTP_SEE_OTHER);
+ }
+
+ return $this->render('post/edit.html.twig', [
+ 'post' => $post,
+ 'form' => $form,
+ ]);
+ }
+
+ #[Route('/{id}', name: 'app_post_delete', methods: ['POST'])]
+ #[IsGranted('ROLE_USER')]
+ public function delete(Request $request, Post $post, EntityManagerInterface $entityManager): Response
+ {
+ if ($this->isCsrfTokenValid('delete'.$post->getId(), (string) $request->getPayload()->get('_token'))) {
+ $entityManager->remove($post);
+ $entityManager->flush();
+ }
+
+ return $this->redirectToRoute('app_post_index', [], Response::HTTP_SEE_OTHER);
+ }
}
diff --git a/src/Controller/RegistrationController.php b/src/Controller/RegistrationController.php
index 6bfc237..43043a9 100644
--- a/src/Controller/RegistrationController.php
+++ b/src/Controller/RegistrationController.php
@@ -34,7 +34,11 @@ class RegistrationController extends AbstractController
// do anything else you need here, like send an email
- return $this->redirectToRoute('_profiler_home');
+ return $this->redirectToRoute('app_login');
+ }
+
+ if ($this->getUser()) {
+ return $this->redirectToRoute('app_posts');
}
return $this->render('registration/register.html.twig', [
diff --git a/src/Controller/SpeciesController.php b/src/Controller/SpeciesController.php
new file mode 100644
index 0000000..b63b960
--- /dev/null
+++ b/src/Controller/SpeciesController.php
@@ -0,0 +1,85 @@
+render('species/index.html.twig', [
+ 'species' => $speciesRepository->findAll(),
+ ]);
+ }
+
+ #[Route('/new', name: 'app_species_new', methods: ['GET', 'POST'])]
+ #[IsGranted('ROLE_USER')]
+ public function new(Request $request, EntityManagerInterface $entityManager): Response
+ {
+ $species = new Species();
+ $form = $this->createForm(SpeciesType::class, $species);
+ $form->handleRequest($request);
+
+ if ($form->isSubmitted() && $form->isValid()) {
+ $entityManager->persist($species);
+ $entityManager->flush();
+
+ return $this->redirectToRoute('app_species_index', [], Response::HTTP_SEE_OTHER);
+ }
+
+ return $this->render('species/new.html.twig', [
+ 'species' => $species,
+ 'form' => $form,
+ ]);
+ }
+
+ #[Route('/{id}', name: 'app_species_show', methods: ['GET'])]
+ public function show(Species $species): Response
+ {
+ return $this->render('species/show.html.twig', [
+ 'species' => $species,
+ ]);
+ }
+
+ #[Route('/{id}/edit', name: 'app_species_edit', methods: ['GET', 'POST'])]
+ #[IsGranted('ROLE_USER')]
+ public function edit(Request $request, Species $species, EntityManagerInterface $entityManager): Response
+ {
+ $form = $this->createForm(SpeciesType::class, $species);
+ $form->handleRequest($request);
+
+ if ($form->isSubmitted() && $form->isValid()) {
+ $entityManager->flush();
+
+ return $this->redirectToRoute('app_species_index', [], Response::HTTP_SEE_OTHER);
+ }
+
+ return $this->render('species/edit.html.twig', [
+ 'species' => $species,
+ 'form' => $form,
+ ]);
+ }
+
+ #[Route('/{id}', name: 'app_species_delete', methods: ['POST'])]
+ #[IsGranted('ROLE_USER')]
+ public function delete(Request $request, Species $species, EntityManagerInterface $entityManager): Response
+ {
+ if ($this->isCsrfTokenValid('delete'.$species->getId(), (string) $request->getPayload()->get('_token'))) {
+ $entityManager->remove($species);
+ $entityManager->flush();
+ }
+
+ return $this->redirectToRoute('app_species_index', [], Response::HTTP_SEE_OTHER);
+ }
+}
diff --git a/src/DataFixtures/AppFixtures.php b/src/DataFixtures/AppFixtures.php
index 12d5f40..3b45990 100644
--- a/src/DataFixtures/AppFixtures.php
+++ b/src/DataFixtures/AppFixtures.php
@@ -4,17 +4,29 @@ namespace App\DataFixtures;
use App\Entity\Post;
use App\Entity\Species;
+use App\Entity\User;
use DateTimeImmutable;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;
+use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
class AppFixtures extends Fixture
{
+ public function __construct(
+ private readonly UserPasswordHasherInterface $passwordHasher
+ )
+ {
+ }
+
public function load(ObjectManager $manager): void
{
+ $user = (new User())->setEmail('test@test.fr');
+ $user->setPassword($this->passwordHasher->hashPassword($user, 'password'));
+ $manager->persist($user);
+
$faker = \Faker\Factory::create();
for ($i = 0; $i < 20; ++$i) {
- $name = $faker->text();
+ $name = $faker->name();
$species = (new Species())
->setScientificName($name)
->setVernacularName($name)
diff --git a/src/Entity/Post.php b/src/Entity/Post.php
index 17ce70c..58f13d2 100644
--- a/src/Entity/Post.php
+++ b/src/Entity/Post.php
@@ -5,8 +5,10 @@ namespace App\Entity;
use App\Repository\PostRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
+use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Entity(repositoryClass: PostRepository::class)]
+#[ORM\HasLifecycleCallbacks]
class Post
{
#[ORM\Id]
@@ -15,21 +17,26 @@ class Post
private ?int $id = null;
#[ORM\Column]
+ #[Assert\NotBlank]
private ?\DateTimeImmutable $foundDate = null;
#[ORM\Column]
private ?\DateTimeImmutable $publicationDate = null;
#[ORM\Column(nullable: true)]
+ #[Assert\NotBlank]
private ?float $latitude = null;
#[ORM\Column(nullable: true)]
+ #[Assert\NotBlank]
private ?float $longitude = null;
#[ORM\Column(nullable: true)]
+ #[Assert\NotBlank]
private ?float $altitude = null;
#[ORM\Column(type: Types::TEXT)]
+ #[Assert\NotBlank]
private ?string $commentary = null;
#[ORM\ManyToOne(inversedBy: 'posts')]
@@ -122,4 +129,12 @@ class Post
return $this;
}
+
+ #[ORM\PrePersist]
+ public function setPublicationDateValue(): void
+ {
+ if ($this->publicationDate === null) {
+ $this->publicationDate = new \DateTimeImmutable();
+ }
+ }
}
diff --git a/src/Entity/Species.php b/src/Entity/Species.php
index 9243896..2dd9528 100644
--- a/src/Entity/Species.php
+++ b/src/Entity/Species.php
@@ -6,6 +6,7 @@ use App\Repository\SpeciesRepository;
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: SpeciesRepository::class)]
class Species
@@ -16,12 +17,15 @@ class Species
private ?int $id = null;
#[ORM\Column(length: 255)]
+ #[Assert\NotBlank]
private ?string $scientific_name = null;
#[ORM\Column(length: 255)]
+ #[Assert\NotBlank]
private ?string $vernacular_name = null;
#[ORM\Column(length: 255)]
+ #[Assert\NotBlank]
private ?string $region = null;
/**
diff --git a/src/Form/PostType.php b/src/Form/PostType.php
new file mode 100644
index 0000000..bea7e6f
--- /dev/null
+++ b/src/Form/PostType.php
@@ -0,0 +1,38 @@
+add('foundDate', null, [
+ 'widget' => 'single_text',
+ ])
+ ->add('latitude')
+ ->add('longitude')
+ ->add('altitude')
+ ->add('commentary')
+ ->add('species', EntityType::class, [
+ 'class' => Species::class,
+ 'choice_label' => 'scientific_name',
+ ])
+
+ ;
+ }
+
+ public function configureOptions(OptionsResolver $resolver): void
+ {
+ $resolver->setDefaults([
+ 'data_class' => Post::class,
+ ]);
+ }
+}
diff --git a/src/Form/SpeciesType.php b/src/Form/SpeciesType.php
new file mode 100644
index 0000000..ae3b919
--- /dev/null
+++ b/src/Form/SpeciesType.php
@@ -0,0 +1,27 @@
+add('scientific_name')
+ ->add('vernacular_name')
+ ->add('region')
+ ;
+ }
+
+ public function configureOptions(OptionsResolver $resolver): void
+ {
+ $resolver->setDefaults([
+ 'data_class' => Species::class,
+ ]);
+ }
+}
diff --git a/src/Repository/UserRepository.php b/src/Repository/UserRepository.php
index 4f2804e..e861224 100644
--- a/src/Repository/UserRepository.php
+++ b/src/Repository/UserRepository.php
@@ -33,6 +33,16 @@ class UserRepository extends ServiceEntityRepository implements PasswordUpgrader
$this->getEntityManager()->flush();
}
+ public function findOneByEmail(string $email): ?User
+ {
+ return $this->createQueryBuilder('u')
+ ->andWhere('u.email = :email')
+ ->setParameter('email', $email)
+ ->getQuery()
+ ->getOneOrNullResult()
+ ;
+ }
+
// /**
// * @return User[] Returns an array of User objects
// */
diff --git a/templates/post/_delete_form.html.twig b/templates/post/_delete_form.html.twig
new file mode 100644
index 0000000..1223c9b
--- /dev/null
+++ b/templates/post/_delete_form.html.twig
@@ -0,0 +1,4 @@
+
diff --git a/templates/post/_form.html.twig b/templates/post/_form.html.twig
new file mode 100644
index 0000000..bf20b98
--- /dev/null
+++ b/templates/post/_form.html.twig
@@ -0,0 +1,4 @@
+{{ form_start(form) }}
+ {{ form_widget(form) }}
+
+{{ form_end(form) }}
diff --git a/templates/post/edit.html.twig b/templates/post/edit.html.twig
new file mode 100644
index 0000000..16b6b5f
--- /dev/null
+++ b/templates/post/edit.html.twig
@@ -0,0 +1,13 @@
+{% extends 'base.html.twig' %}
+
+{% block title %}Edit Post{% endblock %}
+
+{% block body %}
+ Edit Post
+
+ {{ include('post/_form.html.twig', {'button_label': 'Update'}) }}
+
+ back to list
+
+ {{ include('post/_delete_form.html.twig') }}
+{% endblock %}
diff --git a/templates/post/index.html.twig b/templates/post/index.html.twig
index 94f3756..49ca738 100644
--- a/templates/post/index.html.twig
+++ b/templates/post/index.html.twig
@@ -1,11 +1,45 @@
{% extends 'base.html.twig' %}
-{% block title %}Posts!{% endblock %}
+{% block title %}Post index{% endblock %}
{% block body %}
-{% for post in posts %}
-
- #{{ post.id }} trouvé le {{ post.foundDate | date("d/m/Y \\à H \\h") }}
-
-{% endfor %}
+ Post index
+
+
+
+
+ Id |
+ FoundDate |
+ PublicationDate |
+ Latitude |
+ Longitude |
+ Altitude |
+ Commentary |
+ actions |
+
+
+
+ {% for post in posts %}
+
+ {{ post.id }} |
+ {{ post.foundDate ? post.foundDate|date('Y-m-d H:i:s') : '' }} |
+ {{ post.publicationDate ? post.publicationDate|date('Y-m-d H:i:s') : '' }} |
+ {{ post.latitude }} |
+ {{ post.longitude }} |
+ {{ post.altitude }} |
+ {{ post.commentary }} |
+
+ show
+ edit
+ |
+
+ {% else %}
+
+ no records found |
+
+ {% endfor %}
+
+
+
+ Create new
{% endblock %}
diff --git a/templates/post/new.html.twig b/templates/post/new.html.twig
new file mode 100644
index 0000000..b8bc236
--- /dev/null
+++ b/templates/post/new.html.twig
@@ -0,0 +1,11 @@
+{% extends 'base.html.twig' %}
+
+{% block title %}New Post{% endblock %}
+
+{% block body %}
+ Create new Post
+
+ {{ include('post/_form.html.twig') }}
+
+ back to list
+{% endblock %}
diff --git a/templates/post/show.html.twig b/templates/post/show.html.twig
new file mode 100644
index 0000000..a332dba
--- /dev/null
+++ b/templates/post/show.html.twig
@@ -0,0 +1,46 @@
+{% extends 'base.html.twig' %}
+
+{% block title %}Post{% endblock %}
+
+{% block body %}
+ Post
+
+
+
+
+ Id |
+ {{ post.id }} |
+
+
+ FoundDate |
+ {{ post.foundDate ? post.foundDate|date('Y-m-d H:i:s') : '' }} |
+
+
+ PublicationDate |
+ {{ post.publicationDate ? post.publicationDate|date('Y-m-d H:i:s') : '' }} |
+
+
+ Latitude |
+ {{ post.latitude }} |
+
+
+ Longitude |
+ {{ post.longitude }} |
+
+
+ Altitude |
+ {{ post.altitude }} |
+
+
+ Commentary |
+ {{ post.commentary }} |
+
+
+
+
+ back to list
+
+ edit
+
+ {{ include('post/_delete_form.html.twig') }}
+{% endblock %}
diff --git a/templates/species/_delete_form.html.twig b/templates/species/_delete_form.html.twig
new file mode 100644
index 0000000..9e7c05a
--- /dev/null
+++ b/templates/species/_delete_form.html.twig
@@ -0,0 +1,4 @@
+
diff --git a/templates/species/_form.html.twig b/templates/species/_form.html.twig
new file mode 100644
index 0000000..bf20b98
--- /dev/null
+++ b/templates/species/_form.html.twig
@@ -0,0 +1,4 @@
+{{ form_start(form) }}
+ {{ form_widget(form) }}
+
+{{ form_end(form) }}
diff --git a/templates/species/edit.html.twig b/templates/species/edit.html.twig
new file mode 100644
index 0000000..8e4401b
--- /dev/null
+++ b/templates/species/edit.html.twig
@@ -0,0 +1,13 @@
+{% extends 'base.html.twig' %}
+
+{% block title %}Edit Species{% endblock %}
+
+{% block body %}
+ Edit Species
+
+ {{ include('species/_form.html.twig', {'button_label': 'Update'}) }}
+
+ back to list
+
+ {{ include('species/_delete_form.html.twig') }}
+{% endblock %}
diff --git a/templates/species/index.html.twig b/templates/species/index.html.twig
new file mode 100644
index 0000000..39c0d06
--- /dev/null
+++ b/templates/species/index.html.twig
@@ -0,0 +1,39 @@
+{% extends 'base.html.twig' %}
+
+{% block title %}Species index{% endblock %}
+
+{% block body %}
+ Species index
+
+
+
+
+ Id |
+ Scientific_name |
+ Vernacular_name |
+ Region |
+ actions |
+
+
+
+ {% for species in species %}
+
+ {{ species.id }} |
+ {{ species.scientificName }} |
+ {{ species.vernacularName }} |
+ {{ species.region }} |
+
+ show
+ edit
+ |
+
+ {% else %}
+
+ no records found |
+
+ {% endfor %}
+
+
+
+ Create new
+{% endblock %}
diff --git a/templates/species/new.html.twig b/templates/species/new.html.twig
new file mode 100644
index 0000000..8e58597
--- /dev/null
+++ b/templates/species/new.html.twig
@@ -0,0 +1,11 @@
+{% extends 'base.html.twig' %}
+
+{% block title %}New Species{% endblock %}
+
+{% block body %}
+ Create new Species
+
+ {{ include('species/_form.html.twig') }}
+
+ back to list
+{% endblock %}
diff --git a/templates/species/show.html.twig b/templates/species/show.html.twig
new file mode 100644
index 0000000..d0b5a78
--- /dev/null
+++ b/templates/species/show.html.twig
@@ -0,0 +1,34 @@
+{% extends 'base.html.twig' %}
+
+{% block title %}Species{% endblock %}
+
+{% block body %}
+ Species
+
+
+
+
+ Id |
+ {{ species.id }} |
+
+
+ Scientific_name |
+ {{ species.scientificName }} |
+
+
+ Vernacular_name |
+ {{ species.vernacularName }} |
+
+
+ Region |
+ {{ species.region }} |
+
+
+
+
+ back to list
+
+ edit
+
+ {{ include('species/_delete_form.html.twig') }}
+{% endblock %}
diff --git a/tests/Controller/PostControllerTest.php b/tests/Controller/PostControllerTest.php
new file mode 100644
index 0000000..ea52747
--- /dev/null
+++ b/tests/Controller/PostControllerTest.php
@@ -0,0 +1,128 @@
+client = static::createClient();
+ /** @var EntityManagerInterface $manager */
+ $manager = static::getContainer()->get(EntityManagerInterface::class);
+ $this->manager = $manager;
+ $this->repository = $this->manager->getRepository(Post::class);
+
+ foreach ($this->repository->findAll() as $object) {
+ $this->manager->remove($object);
+ }
+
+ $this->manager->flush();
+
+ $userRepository = $this->manager->getRepository(User::class);
+ /** @var User $user */
+ $user = $userRepository->findOneByEmail('test@test.fr');
+ $this->client->loginUser($user);
+ $this->client->request('GET', sprintf('%snew', $this->path));
+ }
+
+ public function testIndex(): void
+ {
+ $crawler = $this->client->request('GET', $this->path);
+
+ self::assertResponseStatusCodeSame(200);
+ self::assertPageTitleContains('Post index');
+
+ // Use the $crawler to perform additional assertions e.g.
+ // self::assertSame('Some text on the page', $crawler->filter('.p')->first());
+ }
+
+ public function testNew(): void
+ {
+ self::assertResponseStatusCodeSame(200);
+
+ $this->client->submitForm('Save', [
+ 'post[foundDate]' => '2024-01-01 00:00:00',
+ 'post[latitude]' => '45.0',
+ 'post[longitude]' => '45.0',
+ 'post[altitude]' => '500.0',
+ 'post[commentary]' => 'Testing',
+ ]);
+
+ self::assertResponseRedirects($this->path);
+
+ self::assertSame(1, $this->repository->count());
+ }
+
+ public function testShow(): void
+ {
+ $fixture = new Post();
+ $fixture->setFoundDate(new \DateTimeImmutable('2024-01-01 00:00:00'));
+ $fixture->setCommentary('Cool stuff');
+
+ $this->manager->persist($fixture);
+ $this->manager->flush();
+
+ $this->client->request('GET', sprintf('%s%s', $this->path, $fixture->getId()));
+
+ self::assertResponseStatusCodeSame(200);
+ self::assertSelectorTextContains('h1', 'Post');
+ }
+
+ public function testEdit(): void
+ {
+ $fixture = new Post();
+ $fixture->setFoundDate(new \DateTimeImmutable('2024-01-01 00:00:00'));
+ $fixture->setCommentary('Cool stuff');
+
+ $this->manager->persist($fixture);
+ $this->manager->flush();
+
+ $this->client->request('GET', sprintf('%s%s/edit', $this->path, $fixture->getId()));
+
+ $this->client->submitForm('Update', [
+ 'post[foundDate]' => '2024-03-25 00:00:00',
+ 'post[latitude]' => '90',
+ 'post[longitude]' => '90',
+ 'post[altitude]' => '200',
+ 'post[commentary]' => 'Something New',
+ ]);
+
+ self::assertResponseRedirects('/post/');
+
+ $fixture = $this->repository->findAll();
+
+ self::assertEquals(new \DateTimeImmutable('2024-03-25 00:00:00'), $fixture[0]->getFoundDate());
+ self::assertSame(90., $fixture[0]->getLatitude());
+ self::assertSame(90., $fixture[0]->getLongitude());
+ self::assertSame(200., $fixture[0]->getAltitude());
+ self::assertSame('Something New', $fixture[0]->getCommentary());
+ }
+
+ public function testRemove(): void
+ {
+ $fixture = new Post();
+ $fixture->setFoundDate(new \DateTimeImmutable('2024-01-01 00:00:00'));
+ $fixture->setCommentary('Cool stuff');
+
+ $this->manager->persist($fixture);
+ $this->manager->flush();
+
+ $this->client->request('GET', sprintf('%s%s', $this->path, $fixture->getId()));
+ $this->client->submitForm('Delete');
+
+ self::assertResponseRedirects('/post/');
+ self::assertSame(0, $this->repository->count());
+ }
+}
diff --git a/tests/Controller/SpeciesControllerTest.php b/tests/Controller/SpeciesControllerTest.php
new file mode 100644
index 0000000..5ce80dd
--- /dev/null
+++ b/tests/Controller/SpeciesControllerTest.php
@@ -0,0 +1,129 @@
+client = static::createClient();
+ /** @var EntityManagerInterface $manager */
+ $manager = static::getContainer()->get(EntityManagerInterface::class);
+ $this->manager = $manager;
+ $this->repository = $this->manager->getRepository(Species::class);
+
+ foreach ($this->repository->findAll() as $object) {
+ $this->manager->remove($object);
+ }
+
+ $this->manager->flush();
+
+ $userRepository = $this->manager->getRepository(User::class);
+ /** @var User $user */
+ $user = $userRepository->findOneByEmail('test@test.fr');
+ $this->client->loginUser($user);
+ $this->client->request('GET', sprintf('%snew', $this->path));
+ }
+
+ public function testIndex(): void
+ {
+ $crawler = $this->client->request('GET', $this->path);
+
+ self::assertResponseStatusCodeSame(200);
+ self::assertPageTitleContains('Species index');
+
+ // Use the $crawler to perform additional assertions e.g.
+ // self::assertSame('Some text on the page', $crawler->filter('.p')->first());
+ }
+
+ public function testNew(): void
+ {
+ $this->client->request('GET', sprintf('%snew', $this->path));
+
+ self::assertResponseStatusCodeSame(200);
+
+ $this->client->submitForm('Save', [
+ 'species[scientific_name]' => 'Testing',
+ 'species[vernacular_name]' => 'Testing',
+ 'species[region]' => 'Testing',
+ ]);
+
+ self::assertResponseRedirects($this->path);
+
+ self::assertSame(1, $this->repository->count([]));
+ }
+
+ public function testShow(): void
+ {
+ $fixture = new Species();
+ $fixture->setScientificName('My Title');
+ $fixture->setVernacularName('My Title');
+ $fixture->setRegion('My Title');
+
+ $this->manager->persist($fixture);
+ $this->manager->flush();
+
+ $this->client->request('GET', sprintf('%s%s', $this->path, $fixture->getId()));
+
+ self::assertResponseStatusCodeSame(200);
+ self::assertPageTitleContains('Species');
+
+ // Use assertions to check that the properties are properly displayed.
+ }
+
+ public function testEdit(): void
+ {
+ $fixture = new Species();
+ $fixture->setScientificName('Value');
+ $fixture->setVernacularName('Value');
+ $fixture->setRegion('Value');
+
+ $this->manager->persist($fixture);
+ $this->manager->flush();
+
+ $this->client->request('GET', sprintf('%s%s/edit', $this->path, $fixture->getId()));
+
+ $this->client->submitForm('Update', [
+ 'species[scientific_name]' => 'Something New',
+ 'species[vernacular_name]' => 'Something New',
+ 'species[region]' => 'Something New',
+ ]);
+
+ self::assertResponseRedirects('/species/');
+
+ $fixture = $this->repository->findAll();
+
+ self::assertSame('Something New', $fixture[0]->getScientificName());
+ self::assertSame('Something New', $fixture[0]->getVernacularName());
+ self::assertSame('Something New', $fixture[0]->getRegion());
+ }
+
+ public function testRemove(): void
+ {
+ $fixture = new Species();
+ $fixture->setScientificName('Value');
+ $fixture->setVernacularName('Value');
+ $fixture->setRegion('Value');
+
+ $this->manager->persist($fixture);
+ $this->manager->flush();
+
+ $this->client->request('GET', sprintf('%s%s', $this->path, $fixture->getId()));
+ $this->client->submitForm('Delete');
+
+ self::assertResponseRedirects('/species/');
+ self::assertSame(0, $this->repository->count([]));
+ }
+}