diff --git a/.changes/unreleased/DX-20250430-144550.yaml b/.changes/unreleased/DX-20250430-144550.yaml deleted file mode 100644 index 7d9f0c32b..000000000 --- a/.changes/unreleased/DX-20250430-144550.yaml +++ /dev/null @@ -1,6 +0,0 @@ -kind: DX -body: Remove dead code for wopi-link module -time: 2025-04-30T14:45:50.406111606+02:00 -custom: - Issue: "352" - SchemaChange: No schema change diff --git a/.changes/unreleased/DX-20250528-165813.yaml b/.changes/unreleased/DX-20250528-165813.yaml deleted file mode 100644 index f13945e76..000000000 --- a/.changes/unreleased/DX-20250528-165813.yaml +++ /dev/null @@ -1,6 +0,0 @@ -kind: DX -body: Replace library node-sass by sass, and upgrade bootstrap to version 5.3 (yarn upgrade / install is required) -time: 2025-05-28T16:58:13.226870341+02:00 -custom: - Issue: "" - SchemaChange: No schema change diff --git a/.changes/unreleased/Feature-20250424-142211.yaml b/.changes/unreleased/Feature-20250424-142211.yaml deleted file mode 100644 index e1f5297c3..000000000 --- a/.changes/unreleased/Feature-20250424-142211.yaml +++ /dev/null @@ -1,7 +0,0 @@ -kind: Feature -body: Add the document file name to the document title when a user upload a document, - unless there is already a document title. -time: 2025-04-24T14:22:11.800975422+02:00 -custom: - Issue: "377" - SchemaChange: No schema change diff --git a/.changes/unreleased/Feature-20250520-095628.yaml b/.changes/unreleased/Feature-20250520-095628.yaml deleted file mode 100644 index 4b1fba30c..000000000 --- a/.changes/unreleased/Feature-20250520-095628.yaml +++ /dev/null @@ -1,6 +0,0 @@ -kind: Feature -body: Add desactivation date for social action and issue csv export -time: 2025-05-20T09:56:28.108941934+02:00 -custom: - Issue: "" - SchemaChange: No schema change diff --git a/.changes/unreleased/Feature-20250523-133341.yaml b/.changes/unreleased/Feature-20250523-133341.yaml deleted file mode 100644 index 1a5513a0d..000000000 --- a/.changes/unreleased/Feature-20250523-133341.yaml +++ /dev/null @@ -1,6 +0,0 @@ -kind: Feature -body: Add Emoji and Fullscreen feature to ckeditor configuration -time: 2025-05-23T13:33:41.645095128+02:00 -custom: - Issue: "" - SchemaChange: No schema change diff --git a/.changes/unreleased/Feature-20250523-133434.yaml b/.changes/unreleased/Feature-20250523-133434.yaml deleted file mode 100644 index 31dced03a..000000000 --- a/.changes/unreleased/Feature-20250523-133434.yaml +++ /dev/null @@ -1,6 +0,0 @@ -kind: Feature -body: Create editor which allow us to toggle between rich and simple text editor -time: 2025-05-23T13:34:34.56795603+02:00 -custom: - Issue: "321" - SchemaChange: No schema change diff --git a/.changes/unreleased/Fixed-20250424-133943.yaml b/.changes/unreleased/Fixed-20250424-133943.yaml deleted file mode 100644 index c11c42ac0..000000000 --- a/.changes/unreleased/Fixed-20250424-133943.yaml +++ /dev/null @@ -1,7 +0,0 @@ -kind: Fixed -body: trying to prevent bug of typeerror in doc-history + improved display of document - history -time: 2025-04-24T13:39:43.878468232+02:00 -custom: - Issue: "376" - SchemaChange: No schema change diff --git a/.changes/unreleased/Fixed-20250424-163746.yaml b/.changes/unreleased/Fixed-20250424-163746.yaml deleted file mode 100644 index 79c07b080..000000000 --- a/.changes/unreleased/Fixed-20250424-163746.yaml +++ /dev/null @@ -1,7 +0,0 @@ -kind: Fixed -body: Display previous participation in acc course work even if the person has left - the acc course -time: 2025-04-24T16:37:46.970203594+02:00 -custom: - Issue: "381" - SchemaChange: No schema change diff --git a/.changes/unreleased/Fixed-20250505-102715.yaml b/.changes/unreleased/Fixed-20250505-102715.yaml deleted file mode 100644 index 5d47c25af..000000000 --- a/.changes/unreleased/Fixed-20250505-102715.yaml +++ /dev/null @@ -1,6 +0,0 @@ -kind: Fixed -body: Fix display of text in calendar events -time: 2025-05-05T10:27:15.461493066+02:00 -custom: - Issue: "372" - SchemaChange: No schema change diff --git a/.changes/unreleased/Fixed-20250514-145339.yaml b/.changes/unreleased/Fixed-20250514-145339.yaml deleted file mode 100644 index 862ea764b..000000000 --- a/.changes/unreleased/Fixed-20250514-145339.yaml +++ /dev/null @@ -1,6 +0,0 @@ -kind: Fixed -body: Add missing translation for user_group.no_user_groups -time: 2025-05-14T14:53:39.53927329+02:00 -custom: - Issue: "" - SchemaChange: No schema change diff --git a/.changes/unreleased/Fixed-20250611-164623.yaml b/.changes/unreleased/Fixed-20250611-164623.yaml new file mode 100644 index 000000000..8bb956c34 --- /dev/null +++ b/.changes/unreleased/Fixed-20250611-164623.yaml @@ -0,0 +1,6 @@ +kind: Fixed +body: Fix admin entity edit actions for event admin entities and activity reason (category) entities +time: 2025-06-11T16:46:23.113506434+02:00 +custom: + Issue: "" + SchemaChange: No schema change diff --git a/.changes/unreleased/UX-20250423-172624.yaml b/.changes/unreleased/UX-20250423-172624.yaml deleted file mode 100644 index 2a17e4195..000000000 --- a/.changes/unreleased/UX-20250423-172624.yaml +++ /dev/null @@ -1,6 +0,0 @@ -kind: UX -body: Remove default filter in_progress for the page 'my tasks'; Allows for new tasks to be displayed upon opening of the page -time: 2025-04-23T17:26:24.45777387+02:00 -custom: - Issue: "374" - SchemaChange: No schema change diff --git a/.changes/unreleased/UX-20250617-192650.yaml b/.changes/unreleased/UX-20250617-192650.yaml new file mode 100644 index 000000000..810758b10 --- /dev/null +++ b/.changes/unreleased/UX-20250617-192650.yaml @@ -0,0 +1,6 @@ +kind: UX +body: Improve labeling of fields in person resource creation form +time: 2025-06-17T19:26:50.599703116+02:00 +custom: + Issue: "" + SchemaChange: No schema change diff --git a/.changes/v3.12.0.md b/.changes/v3.12.0.md new file mode 100644 index 000000000..cfed2e013 --- /dev/null +++ b/.changes/v3.12.0.md @@ -0,0 +1,22 @@ +## v3.12.0 - 2025-06-30 +### Feature +* ([#377](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/377)) Add the document file name to the document title when a user upload a document, unless there is already a document title. +* Add desactivation date for social action and issue csv export +* Add Emoji and Fullscreen feature to ckeditor configuration +* ([#321](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/321)) Create editor which allow us to toggle between rich and simple text editor +* Do not remove workflow which are automatically canceled after staling for more than 30 days +### Fixed +* ([#376](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/376)) trying to prevent bug of typeerror in doc-history + improved display of document history +* ([#381](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/381)) Display previous participation in acc course work even if the person has left the acc course +* ([#372](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/372)) Fix display of text in calendar events +* Add missing translation for user_group.no_user_groups +* Fix admin entity edit actions for event admin entities and activity reason (category) entities +* ([#392](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/392)) Allow null and cast as string to setContent method for NewsItem + +* ([#393](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/393)) Doc Generation: the "dump only" method send the document as an email attachment. +### DX +* ([#352](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/352)) Remove dead code for wopi-link module +* Replace library node-sass by sass, and upgrade bootstrap to version 5.3 (yarn upgrade / install is required) +### UX +* ([#374](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/374)) Remove default filter in_progress for the page 'my tasks'; Allows for new tasks to be displayed upon opening of the page +* Improve labeling of fields in person resource creation form diff --git a/.changes/v3.12.1.md b/.changes/v3.12.1.md new file mode 100644 index 000000000..fbf067913 --- /dev/null +++ b/.changes/v3.12.1.md @@ -0,0 +1,3 @@ +## v3.12.1 - 2025-06-30 +### Fixed +* Fix loading of the list of documents diff --git a/.junie/guidelines.md b/.junie/guidelines.md index 8ef0b7c8d..eace2f4fa 100644 --- a/.junie/guidelines.md +++ b/.junie/guidelines.md @@ -22,7 +22,7 @@ Chill is a comprehensive web application built as a set of Symfony bundles. It i - **Backend**: PHP 8.3+, Symfony 5.4 - **Frontend**: JavaScript/TypeScript, Vue.js 3, Bootstrap 5 - **Build Tools**: Webpack Encore, Yarn -- **Database**: PostgreSQL with materialized views +- **Database**: PostgreSQL with materialized views. We do not support other databases. - **Other Services**: Redis, AMQP (RabbitMQ), SMTP ## Project Structure @@ -149,6 +149,42 @@ Key configuration files: - `package.json`: JavaScript dependencies and scripts - `.env`: Default environment variables. Must usually not be updated: use `.env.local` instead. +### Database migrations + +Each time a doctrine entity is created, we generate migration to adapt the database. + +The migration are created using the command `symfony console doctrine:migrations:diff --no-interaction --namespace `, where the namespace is the relevant namespace for migration. As this is a bash script, do not forget to quote the `\` (`\` must become `\\` in your command). + +Each bundle has his own namespace for migration (always ask me to confirm that command, with a list of updated / created entities so that I can confirm you that it is ok): + +- `Chill\Bundle\ActivityBundle` writes migrations to `Chill\Migrations\Activity`; +- `Chill\Bundle\BudgetBundle` writes migrations to `Chill\Migrations\Budget`; +- `Chill\Bundle\CustomFieldsBundle` writes migrations to `Chill\Migrations\CustomFields`; +- `Chill\Bundle\DocGeneratorBundle` writes migrations to `Chill\Migrations\DocGenerator`; +- `Chill\Bundle\DocStoreBundle` writes migrations to `Chill\Migrations\DocStore`; +- `Chill\Bundle\EventBundle` writes migrations to `Chill\Migrations\Event`; +- `Chill\Bundle\CalendarBundle` writes migrations to `Chill\Migrations\Calendar`; +- `Chill\Bundle\FamilyMembersBundle` writes migrations to `Chill\Migrations\FamilyMembers`; +- `Chill\Bundle\FranceTravailApiBundle` writes migrations to `Chill\Migrations\FranceTravailApi`; +- `Chill\Bundle\JobBundle` writes migrations to `Chill\Migrations\Job`; +- `Chill\Bundle\MainBundle` writes migrations to `Chill\Migrations\Main`; +- `Chill\Bundle\PersonBundle` writes migrations to `Chill\Migrations\Person`; +- `Chill\Bundle\ReportBundle` writes migrations to `Chill\Migrations\Report`; +- `Chill\Bundle\TaskBundle` writes migrations to `Chill\Migrations\Task`; +- `Chill\Bundle\ThirdPartyBundle` writes migrations to `Chill\Migrations\ThirdParty`; +- `Chill\Bundle\TicketBundle` writes migrations to `Chill\Migrations\Ticket`; +- `Chill\Bundle\WopiBundle` writes migrations to `Chill\Migrations\Wopi`; + +Once created the, comment's classes should be removed and a description of the changes made to the entities should be added to the migrations, using the `getDescription` method. The migration should not be cleaned by any artificial intelligence, as modifying this migration is error prone. + +### Guidelines related to code structure and requirements + +#### Usage of clock + +When we need to use a DateTime or DateTimeImmutable that need to express "now", we prefer the usage of +`Symfony\Component\Clock\ClockInterface`, where possible. This is usually not possible in doctrine entities, +where injection does not work when restoring an entity from database, but usually possible in services. + ### Testing Information The project uses PHPUnit for testing. Each bundle has its own test suite, and there's also a global test suite at the root level. @@ -218,7 +254,7 @@ class TicketTest extends TestCase #### Test Database -For tests that require a database, the project uses an in-memory SQLite database by default. You can configure a different database for testing in the `.env.test` file. +For tests that require a database, the project uses postgresql database filled by fixtures (usage of doctrine-fixtures). You can configure a different database for testing in the `.env.test` file. ### Code Quality Tools diff --git a/CHANGELOG.md b/CHANGELOG.md index b1b9aa894..a00af6c44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,53 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html), and is generated by [Changie](https://github.com/miniscruff/changie). +## v3.12.1 - 2025-06-30 +### Fixed +* Fix loading of the list of documents + +## v3.12.0 - 2025-06-30 +### Feature +* ([#377](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/377)) Add the document file name to the document title when a user upload a document, unless there is already a document title. +* Add desactivation date for social action and issue csv export +* Add Emoji and Fullscreen feature to ckeditor configuration +* ([#321](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/321)) Create editor which allow us to toggle between rich and simple text editor +* Do not remove workflow which are automatically canceled after staling for more than 30 days +### Fixed +* ([#376](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/376)) trying to prevent bug of typeerror in doc-history + improved display of document history +* ([#381](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/381)) Display previous participation in acc course work even if the person has left the acc course +* ([#372](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/372)) Fix display of text in calendar events +* Add missing translation for user_group.no_user_groups +* Fix admin entity edit actions for event admin entities and activity reason (category) entities +* ([#392](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/392)) Allow null and cast as string to setContent method for NewsItem + +* ([#393](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/393)) Doc Generation: the "dump only" method send the document as an email attachment. +### DX +* ([#352](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/352)) Remove dead code for wopi-link module +* Replace library node-sass by sass, and upgrade bootstrap to version 5.3 (yarn upgrade / install is required) +### UX +* ([#374](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/374)) Remove default filter in_progress for the page 'my tasks'; Allows for new tasks to be displayed upon opening of the page +* Improve labeling of fields in person resource creation form + +## v3.11.0 - 2025-04-17 +### Feature +* ([#365](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/365)) Add counters of actions and activities, with 2 boxes to (1) show the number of active actions on total actions and (2) show the number of activities in a accompanying period, and pills in menus for showing the number of active actions and the number of activities. +* ([#364](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/364)) Added a second phone number "telephone2" to the thirdParty entity. Adapted twig templates and vuejs apps to handle this phone number + + **Schema Change**: Add columns or tables +* Signature: add a button to go directly to the signature zone, even if there is only one +### Fixed +* Fixed wrong translations in the on-the-fly for creation of thirdParty +* Fixed update of phone number in on-the-fly edition of thirdParty +* Fixed closing of modal when editing thirdParty in accompanying course works +* Shorten the delay between two execution of AccompanyingPeriodStepChangeCronjob, to ensure at least one execution in a day +* ([#102](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/102)) Fix display of title in document list +* When cleaning the old stored object versions, do not throw an error if the stored object is not found on disk +* Add consistent log prefix and key to logs when stale workflows are automatically canceled +* ([#380](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/380)) Remove the "not null" validation constraint on recently added properties on HouseholdComposition + +### DX +* Add new chill-col style for displaying title and aside in a flex table + ## v3.10.3 - 2025-03-18 ### DX * Eslint fixes diff --git a/src/Bundle/ChillActivityBundle/Controller/ActivityReasonCategoryController.php b/src/Bundle/ChillActivityBundle/Controller/ActivityReasonCategoryController.php index 0d337416b..6ccddcc97 100644 --- a/src/Bundle/ChillActivityBundle/Controller/ActivityReasonCategoryController.php +++ b/src/Bundle/ChillActivityBundle/Controller/ActivityReasonCategoryController.php @@ -48,28 +48,6 @@ class ActivityReasonCategoryController extends AbstractController ]); } - /** - * Displays a form to edit an existing ActivityReasonCategory entity. - */ - #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/activityreasoncategory/{id}/edit', name: 'chill_activity_activityreasoncategory_edit')] - public function editAction(mixed $id) - { - $em = $this->managerRegistry->getManager(); - - $entity = $em->getRepository(ActivityReasonCategory::class)->find($id); - - if (!$entity) { - throw $this->createNotFoundException('Unable to find ActivityReasonCategory entity.'); - } - - $editForm = $this->createEditForm($entity); - - return $this->render('@ChillActivity/ActivityReasonCategory/edit.html.twig', [ - 'entity' => $entity, - 'edit_form' => $editForm->createView(), - ]); - } - /** * Lists all ActivityReasonCategory entities. */ @@ -100,29 +78,10 @@ class ActivityReasonCategoryController extends AbstractController ]); } - /** - * Finds and displays a ActivityReasonCategory entity. - */ - #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/activityreasoncategory/{id}/show', name: 'chill_activity_activityreasoncategory_show')] - public function showAction(mixed $id) - { - $em = $this->managerRegistry->getManager(); - - $entity = $em->getRepository(ActivityReasonCategory::class)->find($id); - - if (!$entity) { - throw $this->createNotFoundException('Unable to find ActivityReasonCategory entity.'); - } - - return $this->render('@ChillActivity/ActivityReasonCategory/show.html.twig', [ - 'entity' => $entity, - ]); - } - /** * Edits an existing ActivityReasonCategory entity. */ - #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/activityreasoncategory/{id}/update', name: 'chill_activity_activityreasoncategory_update', methods: ['POST', 'PUT'])] + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/activityreasoncategory/{id}/update', name: 'chill_activity_activityreasoncategory_update')] public function updateAction(Request $request, mixed $id) { $em = $this->managerRegistry->getManager(); @@ -139,7 +98,7 @@ class ActivityReasonCategoryController extends AbstractController if ($editForm->isSubmitted() && $editForm->isValid()) { $em->flush(); - return $this->redirectToRoute('chill_activity_activityreasoncategory_edit', ['id' => $id]); + return $this->redirectToRoute('chill_activity_activityreasoncategory', ['id' => $id]); } return $this->render('@ChillActivity/ActivityReasonCategory/edit.html.twig', [ @@ -178,7 +137,7 @@ class ActivityReasonCategoryController extends AbstractController { $form = $this->createForm(ActivityReasonCategoryType::class, $entity, [ 'action' => $this->generateUrl('chill_activity_activityreasoncategory_update', ['id' => $entity->getId()]), - 'method' => 'PUT', + 'method' => 'POST', ]); $form->add('submit', SubmitType::class, ['label' => 'Update']); diff --git a/src/Bundle/ChillActivityBundle/Controller/ActivityReasonController.php b/src/Bundle/ChillActivityBundle/Controller/ActivityReasonController.php index 37d04d367..7512b21ed 100644 --- a/src/Bundle/ChillActivityBundle/Controller/ActivityReasonController.php +++ b/src/Bundle/ChillActivityBundle/Controller/ActivityReasonController.php @@ -17,7 +17,6 @@ use Chill\ActivityBundle\Repository\ActivityReasonRepository; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** * ActivityReason controller. @@ -50,28 +49,6 @@ class ActivityReasonController extends AbstractController ]); } - /** - * Displays a form to edit an existing ActivityReason entity. - */ - #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/activityreason/{id}/edit', name: 'chill_activity_activityreason_edit')] - public function editAction(mixed $id) - { - $em = $this->managerRegistry->getManager(); - - $entity = $em->getRepository(ActivityReason::class)->find($id); - - if (null === $entity) { - throw new NotFoundHttpException('Unable to find ActivityReason entity.'); - } - - $editForm = $this->createEditForm($entity); - - return $this->render('@ChillActivity/ActivityReason/edit.html.twig', [ - 'entity' => $entity, - 'edit_form' => $editForm->createView(), - ]); - } - /** * Lists all ActivityReason entities. */ @@ -102,29 +79,10 @@ class ActivityReasonController extends AbstractController ]); } - /** - * Finds and displays a ActivityReason entity. - */ - #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/activityreason/{id}/show', name: 'chill_activity_activityreason_show')] - public function showAction(mixed $id) - { - $em = $this->managerRegistry->getManager(); - - $entity = $em->getRepository(ActivityReason::class)->find($id); - - if (!$entity) { - throw $this->createNotFoundException('Unable to find ActivityReason entity.'); - } - - return $this->render('@ChillActivity/ActivityReason/show.html.twig', [ - 'entity' => $entity, - ]); - } - /** * Edits an existing ActivityReason entity. */ - #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/activityreason/{id}/update', name: 'chill_activity_activityreason_update', methods: ['POST', 'PUT'])] + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/activityreason/{id}/update', name: 'chill_activity_activityreason_update')] public function updateAction(Request $request, mixed $id) { $em = $this->managerRegistry->getManager(); @@ -180,7 +138,7 @@ class ActivityReasonController extends AbstractController { $form = $this->createForm(ActivityReasonType::class, $entity, [ 'action' => $this->generateUrl('chill_activity_activityreason_update', ['id' => $entity->getId()]), - 'method' => 'PUT', + 'method' => 'POST', ]); $form->add('submit', SubmitType::class, ['label' => 'Update']); diff --git a/src/Bundle/ChillActivityBundle/Resources/views/ActivityReason/index.html.twig b/src/Bundle/ChillActivityBundle/Resources/views/ActivityReason/index.html.twig index 855c9386d..ee36958c3 100644 --- a/src/Bundle/ChillActivityBundle/Resources/views/ActivityReason/index.html.twig +++ b/src/Bundle/ChillActivityBundle/Resources/views/ActivityReason/index.html.twig @@ -3,7 +3,7 @@ {% block admin_content %}

{{ 'ActivityReason list'|trans }}

- +
@@ -29,10 +29,7 @@ diff --git a/src/Bundle/ChillActivityBundle/Resources/views/ActivityReasonCategory/index.html.twig b/src/Bundle/ChillActivityBundle/Resources/views/ActivityReasonCategory/index.html.twig index 5f48180b3..f64ce359d 100644 --- a/src/Bundle/ChillActivityBundle/Resources/views/ActivityReasonCategory/index.html.twig +++ b/src/Bundle/ChillActivityBundle/Resources/views/ActivityReasonCategory/index.html.twig @@ -3,7 +3,7 @@ {% block admin_content %}

{{ 'ActivityReasonCategory list'|trans }}

-
{{ 'Name'|trans }}
  • - -
  • -
  • - +
+
@@ -23,10 +23,7 @@ diff --git a/src/Bundle/ChillActivityBundle/Tests/Controller/ActivityControllerTest.php b/src/Bundle/ChillActivityBundle/Tests/Controller/ActivityControllerTest.php index 31012569a..62a885937 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Controller/ActivityControllerTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Controller/ActivityControllerTest.php @@ -22,6 +22,52 @@ use Symfony\Component\Security\Core\Role\Role; */ final class ActivityControllerTest extends WebTestCase { + /** + * @dataProvider getSecuredPagesUnauthenticated + */ + public function testAccessIsDeniedForUnauthenticated(mixed $url) + { + $client = $this->createClient(); + + $client->request('GET', $url); + + $this->assertEquals(302, $client->getResponse()->getStatusCode()); + $this->assertTrue( + $client->getResponse()->isRedirect('http://localhost/login'), + sprintf('the page "%s" does not redirect to http://localhost/login', $url) + ); + } + + /** + * Provide a client unauthenticated and. + */ + public function getSecuredPagesUnauthenticated() + { + self::bootKernel(); + $person = $this->getPersonFromFixtures(); + $activities = $this->getActivitiesForPerson($person); + + return [ + [sprintf('fr/person/%d/activity/', $person->getId())], + [sprintf('fr/person/%d/activity/new', $person->getId())], + [sprintf('fr/person/%d/activity/%d/show', $person->getId(), $activities[0]->getId())], + [sprintf('fr/person/%d/activity/%d/edit', $person->getId(), $activities[0]->getId())], + ]; + } + + /** + * @dataProvider getSecuredPagesAuthenticated + * + * @param type $client + * @param type $url + */ + public function testAccessIsDeniedForUnauthorized($client, $url) + { + $client->request('GET', $url); + + $this->assertEquals(403, $client->getResponse()->getStatusCode()); + } + public function getSecuredPagesAuthenticated() { self::bootKernel(); @@ -55,52 +101,6 @@ final class ActivityControllerTest extends WebTestCase ]; } - /** - * Provide a client unauthenticated and. - */ - public function getSecuredPagesUnauthenticated() - { - self::bootKernel(); - $person = $this->getPersonFromFixtures(); - $activities = $this->getActivitiesForPerson($person); - - return [ - [sprintf('fr/person/%d/activity/', $person->getId())], - [sprintf('fr/person/%d/activity/new', $person->getId())], - [sprintf('fr/person/%d/activity/%d/show', $person->getId(), $activities[0]->getId())], - [sprintf('fr/person/%d/activity/%d/edit', $person->getId(), $activities[0]->getId())], - ]; - } - - /** - * @dataProvider getSecuredPagesUnauthenticated - */ - public function testAccessIsDeniedForUnauthenticated(mixed $url) - { - $client = $this->createClient(); - - $client->request('GET', $url); - - $this->assertEquals(302, $client->getResponse()->getStatusCode()); - $this->assertTrue( - $client->getResponse()->isRedirect('http://localhost/login'), - sprintf('the page "%s" does not redirect to http://localhost/login', $url) - ); - } - - /** - * @dataProvider getSecuredPagesAuthenticated - * - * @param type $client - * @param type $url - */ - public function testAccessIsDeniedForUnauthorized($client, $url) - { - $client->request('GET', $url); - - $this->assertEquals(403, $client->getResponse()->getStatusCode()); - } - public function testCompleteScenario() { // Create a new client to browse the application diff --git a/src/Bundle/ChillActivityBundle/Tests/Repository/ActivityACLAwareRepositoryTest.php b/src/Bundle/ChillActivityBundle/Tests/Repository/ActivityACLAwareRepositoryTest.php index de4a3312d..a42ab6049 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Repository/ActivityACLAwareRepositoryTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Repository/ActivityACLAwareRepositoryTest.php @@ -137,6 +137,64 @@ class ActivityACLAwareRepositoryTest extends KernelTestCase self::assertIsArray($actual); } + public function provideDataFindByAccompanyingPeriod(): iterable + { + $this->setUp(); + + if (null === $period = $this->entityManager + ->createQueryBuilder() + ->select('a') + ->from(AccompanyingPeriod::class, 'a') + ->setMaxResults(1) + ->getQuery() + ->getSingleResult()) { + throw new \RuntimeException('no period found'); + } + + if ([] === $types = $this->entityManager + ->createQueryBuilder() + ->select('t') + ->from(ActivityType::class, 't') + ->setMaxResults(2) + ->getQuery() + ->getResult()) { + throw new \RuntimeException('no types'); + } + + if ([] === $jobs = $this->entityManager + ->createQueryBuilder() + ->select('j') + ->from(UserJob::class, 'j') + ->setMaxResults(2) + ->getQuery() + ->getResult() + ) { + $job = new UserJob(); + $job->setLabel(['fr' => 'test']); + $this->entityManager->persist($job); + $this->entityManager->flush(); + } + + if (null === $user = $this->entityManager + ->createQueryBuilder() + ->select('u') + ->from(User::class, 'u') + ->setMaxResults(1) + ->getQuery() + ->getSingleResult() + ) { + throw new \RuntimeException('no user found'); + } + + yield [$period, $user, ActivityVoter::SEE, 0, 10, ['date' => 'DESC'], []]; + yield [$period, $user, ActivityVoter::SEE, 0, 10, ['date' => 'DESC'], ['my_activities' => true]]; + yield [$period, $user, ActivityVoter::SEE, 0, 10, ['date' => 'DESC'], ['types' => $types]]; + yield [$period, $user, ActivityVoter::SEE, 0, 10, ['date' => 'DESC'], ['jobs' => $jobs]]; + yield [$period, $user, ActivityVoter::SEE, 0, 10, ['date' => 'DESC'], ['after' => new \DateTimeImmutable('1 year ago')]]; + yield [$period, $user, ActivityVoter::SEE, 0, 10, ['date' => 'DESC'], ['before' => new \DateTimeImmutable('1 year ago')]]; + yield [$period, $user, ActivityVoter::SEE, 0, 10, ['date' => 'DESC'], ['after' => new \DateTimeImmutable('1 year ago'), 'before' => new \DateTimeImmutable('1 month ago')]]; + } + /** * @dataProvider provideDataFindByPerson */ @@ -291,62 +349,4 @@ class ActivityACLAwareRepositoryTest extends KernelTestCase yield [$person, $user, $centers, $scopes, ActivityVoter::SEE, 0, 5, ['date' => 'DESC'], ['before' => new \DateTimeImmutable('1 year ago')]]; yield [$person, $user, $centers, $scopes, ActivityVoter::SEE, 0, 5, ['date' => 'DESC'], ['after' => new \DateTimeImmutable('1 year ago'), 'before' => new \DateTimeImmutable('1 month ago')]]; } - - public function provideDataFindByAccompanyingPeriod(): iterable - { - $this->setUp(); - - if (null === $period = $this->entityManager - ->createQueryBuilder() - ->select('a') - ->from(AccompanyingPeriod::class, 'a') - ->setMaxResults(1) - ->getQuery() - ->getSingleResult()) { - throw new \RuntimeException('no period found'); - } - - if ([] === $types = $this->entityManager - ->createQueryBuilder() - ->select('t') - ->from(ActivityType::class, 't') - ->setMaxResults(2) - ->getQuery() - ->getResult()) { - throw new \RuntimeException('no types'); - } - - if ([] === $jobs = $this->entityManager - ->createQueryBuilder() - ->select('j') - ->from(UserJob::class, 'j') - ->setMaxResults(2) - ->getQuery() - ->getResult() - ) { - $job = new UserJob(); - $job->setLabel(['fr' => 'test']); - $this->entityManager->persist($job); - $this->entityManager->flush(); - } - - if (null === $user = $this->entityManager - ->createQueryBuilder() - ->select('u') - ->from(User::class, 'u') - ->setMaxResults(1) - ->getQuery() - ->getSingleResult() - ) { - throw new \RuntimeException('no user found'); - } - - yield [$period, $user, ActivityVoter::SEE, 0, 10, ['date' => 'DESC'], []]; - yield [$period, $user, ActivityVoter::SEE, 0, 10, ['date' => 'DESC'], ['my_activities' => true]]; - yield [$period, $user, ActivityVoter::SEE, 0, 10, ['date' => 'DESC'], ['types' => $types]]; - yield [$period, $user, ActivityVoter::SEE, 0, 10, ['date' => 'DESC'], ['jobs' => $jobs]]; - yield [$period, $user, ActivityVoter::SEE, 0, 10, ['date' => 'DESC'], ['after' => new \DateTimeImmutable('1 year ago')]]; - yield [$period, $user, ActivityVoter::SEE, 0, 10, ['date' => 'DESC'], ['before' => new \DateTimeImmutable('1 year ago')]]; - yield [$period, $user, ActivityVoter::SEE, 0, 10, ['date' => 'DESC'], ['after' => new \DateTimeImmutable('1 year ago'), 'before' => new \DateTimeImmutable('1 month ago')]]; - } } diff --git a/src/Bundle/ChillActivityBundle/Tests/Security/Authorization/ActivityVoterTest.php b/src/Bundle/ChillActivityBundle/Tests/Security/Authorization/ActivityVoterTest.php index 0a9e7d8ba..e4cae588c 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Security/Authorization/ActivityVoterTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Security/Authorization/ActivityVoterTest.php @@ -57,6 +57,46 @@ final class ActivityVoterTest extends KernelTestCase $this->prophet = new \Prophecy\Prophet(); } + public function testNullUser() + { + $token = $this->prepareToken(); + $center = $this->prepareCenter(1, 'center'); + $person = $this->preparePerson($center); + $scope = $this->prepareScope(1, 'default'); + $activity = $this->prepareActivity($scope, $person); + + $this->assertEquals( + VoterInterface::ACCESS_DENIED, + $this->voter->vote($token, $activity, ['CHILL_ACTIVITY_SEE']), + 'assert that a null user is not allowed to see' + ); + } + + /** + * @dataProvider dataProvider_testVoteAction + * + * @param type $expectedResult + * @param string $attribute + * @param string $message + */ + public function testVoteAction( + $expectedResult, + User $user, + Scope $scope, + Center $center, + $attribute, + $message, + ) { + $token = $this->prepareToken($user); + $activity = $this->prepareActivity($scope, $this->preparePerson($center)); + + $this->assertEquals( + $expectedResult, + $this->voter->vote($token, $activity, [$attribute]), + $message + ); + } + public function dataProvider_testVoteAction() { $centerA = $this->prepareCenter(1, 'center A'); @@ -110,46 +150,6 @@ final class ActivityVoterTest extends KernelTestCase ]; } - public function testNullUser() - { - $token = $this->prepareToken(); - $center = $this->prepareCenter(1, 'center'); - $person = $this->preparePerson($center); - $scope = $this->prepareScope(1, 'default'); - $activity = $this->prepareActivity($scope, $person); - - $this->assertEquals( - VoterInterface::ACCESS_DENIED, - $this->voter->vote($token, $activity, ['CHILL_ACTIVITY_SEE']), - 'assert that a null user is not allowed to see' - ); - } - - /** - * @dataProvider dataProvider_testVoteAction - * - * @param type $expectedResult - * @param string $attribute - * @param string $message - */ - public function testVoteAction( - $expectedResult, - User $user, - Scope $scope, - Center $center, - $attribute, - $message, - ) { - $token = $this->prepareToken($user); - $activity = $this->prepareActivity($scope, $this->preparePerson($center)); - - $this->assertEquals( - $expectedResult, - $this->voter->vote($token, $activity, [$attribute]), - $message - ); - } - /** * prepare a token interface with correct rights. * diff --git a/src/Bundle/ChillAsideActivityBundle/src/Tests/Controller/AsideActivityControllerTest.php b/src/Bundle/ChillAsideActivityBundle/src/Tests/Controller/AsideActivityControllerTest.php index 21e78e6cf..a4c68a9b0 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Tests/Controller/AsideActivityControllerTest.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Tests/Controller/AsideActivityControllerTest.php @@ -30,6 +30,18 @@ final class AsideActivityControllerTest extends WebTestCase self::ensureKernelShutdown(); } + /** + * @dataProvider generateAsideActivityId + */ + public function testEditWithoutUsers(int $asideActivityId) + { + self::ensureKernelShutdown(); + $client = $this->getClientAuthenticated(); + $client->request('GET', "/fr/asideactivity/{$asideActivityId}/edit"); + + $this->assertEquals(200, $client->getResponse()->getStatusCode()); + } + public static function generateAsideActivityId(): iterable { self::bootKernel(); @@ -58,18 +70,6 @@ final class AsideActivityControllerTest extends WebTestCase self::ensureKernelShutdown(); } - /** - * @dataProvider generateAsideActivityId - */ - public function testEditWithoutUsers(int $asideActivityId) - { - self::ensureKernelShutdown(); - $client = $this->getClientAuthenticated(); - $client->request('GET', "/fr/asideactivity/{$asideActivityId}/edit"); - - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - } - public function testIndexWithoutUsers() { self::ensureKernelShutdown(); diff --git a/src/Bundle/ChillCalendarBundle/Tests/Controller/CalendarControllerTest.php b/src/Bundle/ChillCalendarBundle/Tests/Controller/CalendarControllerTest.php index ef2597367..31af5a921 100644 --- a/src/Bundle/ChillCalendarBundle/Tests/Controller/CalendarControllerTest.php +++ b/src/Bundle/ChillCalendarBundle/Tests/Controller/CalendarControllerTest.php @@ -42,6 +42,32 @@ final class CalendarControllerTest extends WebTestCase self::ensureKernelShutdown(); } + /** + * @dataProvider provideAccompanyingPeriod + */ + public function testList(int $accompanyingPeriodId) + { + $this->client->request( + Request::METHOD_GET, + sprintf('/fr/calendar/calendar/by-period/%d', $accompanyingPeriodId) + ); + + $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); + } + + /** + * @dataProvider provideAccompanyingPeriod + */ + public function testNew(int $accompanyingPeriodId) + { + $this->client->request( + Request::METHOD_GET, + sprintf('/fr/calendar/calendar/new?accompanying_period_id=%d', $accompanyingPeriodId) + ); + + $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); + } + public static function provideAccompanyingPeriod(): iterable { self::bootKernel(); @@ -82,30 +108,4 @@ final class CalendarControllerTest extends WebTestCase self::ensureKernelShutdown(); } - - /** - * @dataProvider provideAccompanyingPeriod - */ - public function testList(int $accompanyingPeriodId) - { - $this->client->request( - Request::METHOD_GET, - sprintf('/fr/calendar/calendar/by-period/%d', $accompanyingPeriodId) - ); - - $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); - } - - /** - * @dataProvider provideAccompanyingPeriod - */ - public function testNew(int $accompanyingPeriodId) - { - $this->client->request( - Request::METHOD_GET, - sprintf('/fr/calendar/calendar/new?accompanying_period_id=%d', $accompanyingPeriodId) - ); - - $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); - } } diff --git a/src/Bundle/ChillCalendarBundle/Tests/RemoteCalendar/Connector/MSGraph/MSUserAbsenceReaderTest.php b/src/Bundle/ChillCalendarBundle/Tests/RemoteCalendar/Connector/MSGraph/MSUserAbsenceReaderTest.php index 3d3a71854..3c9c0d2ff 100644 --- a/src/Bundle/ChillCalendarBundle/Tests/RemoteCalendar/Connector/MSGraph/MSUserAbsenceReaderTest.php +++ b/src/Bundle/ChillCalendarBundle/Tests/RemoteCalendar/Connector/MSGraph/MSUserAbsenceReaderTest.php @@ -45,20 +45,6 @@ class MSUserAbsenceReaderTest extends TestCase self::assertEquals($expected, $absenceReader->isUserAbsent($user), $message); } - public function testIsUserAbsentWithoutRemoteId(): void - { - $user = new User(); - $client = new MockHttpClient(); - - $mapUser = $this->prophesize(MapCalendarToUser::class); - $mapUser->getUserId($user)->willReturn(null); - $clock = new MockClock(new \DateTimeImmutable('2023-07-07T12:00:00')); - - $absenceReader = new MSUserAbsenceReader($client, $mapUser->reveal(), $clock); - - self::assertNull($absenceReader->isUserAbsent($user), 'when no user found, absence should be null'); - } - public static function provideDataTestUserAbsence(): iterable { // contains data that was retrieved from microsoft graph api on 2023-07-06 @@ -173,4 +159,18 @@ class MSUserAbsenceReaderTest extends TestCase 'User is absent: absence is always enabled', ]; } + + public function testIsUserAbsentWithoutRemoteId(): void + { + $user = new User(); + $client = new MockHttpClient(); + + $mapUser = $this->prophesize(MapCalendarToUser::class); + $mapUser->getUserId($user)->willReturn(null); + $clock = new MockClock(new \DateTimeImmutable('2023-07-07T12:00:00')); + + $absenceReader = new MSUserAbsenceReader($client, $mapUser->reveal(), $clock); + + self::assertNull($absenceReader->isUserAbsent($user), 'when no user found, absence should be null'); + } } diff --git a/src/Bundle/ChillCalendarBundle/Tests/Service/ShortMessageNotification/DefaultRangeGeneratorTest.php b/src/Bundle/ChillCalendarBundle/Tests/Service/ShortMessageNotification/DefaultRangeGeneratorTest.php index 1d28c43c0..4fb6e99d6 100644 --- a/src/Bundle/ChillCalendarBundle/Tests/Service/ShortMessageNotification/DefaultRangeGeneratorTest.php +++ b/src/Bundle/ChillCalendarBundle/Tests/Service/ShortMessageNotification/DefaultRangeGeneratorTest.php @@ -28,6 +28,24 @@ use PHPUnit\Framework\TestCase; */ final class DefaultRangeGeneratorTest extends TestCase { + /** + * @dataProvider generateData + */ + public function testGenerateRange(\DateTimeImmutable $date, ?\DateTimeImmutable $startDate, ?\DateTimeImmutable $endDate) + { + $generator = new DefaultRangeGenerator(); + + ['startDate' => $actualStartDate, 'endDate' => $actualEndDate] = $generator->generateRange($date); + + if (null === $startDate) { + $this->assertNull($actualStartDate); + $this->assertNull($actualEndDate); + } else { + $this->assertEquals($startDate->format(\DateTimeImmutable::ATOM), $actualStartDate->format(\DateTimeImmutable::ATOM)); + $this->assertEquals($endDate->format(\DateTimeImmutable::ATOM), $actualEndDate->format(\DateTimeImmutable::ATOM)); + } + } + /** * * Lundi => Envoi des rdv du mardi et mercredi. * * Mardi => Envoi des rdv du jeudi. @@ -79,22 +97,4 @@ final class DefaultRangeGeneratorTest extends TestCase null, ]; } - - /** - * @dataProvider generateData - */ - public function testGenerateRange(\DateTimeImmutable $date, ?\DateTimeImmutable $startDate, ?\DateTimeImmutable $endDate) - { - $generator = new DefaultRangeGenerator(); - - ['startDate' => $actualStartDate, 'endDate' => $actualEndDate] = $generator->generateRange($date); - - if (null === $startDate) { - $this->assertNull($actualStartDate); - $this->assertNull($actualEndDate); - } else { - $this->assertEquals($startDate->format(\DateTimeImmutable::ATOM), $actualStartDate->format(\DateTimeImmutable::ATOM)); - $this->assertEquals($endDate->format(\DateTimeImmutable::ATOM), $actualEndDate->format(\DateTimeImmutable::ATOM)); - } - } } diff --git a/src/Bundle/ChillCustomFieldsBundle/Tests/CustomFields/CustomFieldsChoiceTest.php b/src/Bundle/ChillCustomFieldsBundle/Tests/CustomFields/CustomFieldsChoiceTest.php index 6f6ba394e..453b8ee64 100644 --- a/src/Bundle/ChillCustomFieldsBundle/Tests/CustomFields/CustomFieldsChoiceTest.php +++ b/src/Bundle/ChillCustomFieldsBundle/Tests/CustomFields/CustomFieldsChoiceTest.php @@ -49,80 +49,6 @@ final class CustomFieldsChoiceTest extends KernelTestCase parent::tearDown(); } - /** - * provide empty data in different possible representations. - * Those data are supposed to be deserialized. - * - * @return array - */ - public static function emptyDataProvider() - { - return [ - // 0 - [ - // signle - '', - ], - // 1 - [ - // single - null, - ], - // 2 - [ - // signle with allow other - ['_other' => 'something', '_choices' => ''], - ], - // 3 - [ - // multiple - [], - ], - // 4 - [ - // multiple with allow other - ['_other' => 'something', '_choices' => []], - ], - // 5 - [ - // multiple with allow other - ['_other' => '', '_choices' => []], - ], - // 6 - [ - // empty - ['_other' => null, '_choices' => null], - ], - // 7 - [ - // empty - [null], - ], - ]; - } - - public static function serializedRepresentationDataProvider() - { - return [ - [ - // multiple => false, allow_other => false - 'my-value', - ], - [ - // multiple => true, allow_ther => false - ['my-value'], - ], - [ - // multiple => false, allow_other => true, current value not in other - ['_other' => '', '_choices' => 'my-value'], - ], - [ - // multiple => true, allow_other => true, current value not in other - ['_other' => '', '_choices' => ['my-value']], - ], - ]; - } - /** * Test if the representation of the data is deserialized to an array text * with an "allow_other" field. @@ -412,6 +338,58 @@ final class CustomFieldsChoiceTest extends KernelTestCase $this->assertTrue($isEmpty); } + /** + * provide empty data in different possible representations. + * Those data are supposed to be deserialized. + * + * @return array + */ + public static function emptyDataProvider() + { + return [ + // 0 + [ + // signle + '', + ], + // 1 + [ + // single + null, + ], + // 2 + [ + // signle with allow other + ['_other' => 'something', '_choices' => ''], + ], + // 3 + [ + // multiple + [], + ], + // 4 + [ + // multiple with allow other + ['_other' => 'something', '_choices' => []], + ], + // 5 + [ + // multiple with allow other + ['_other' => '', '_choices' => []], + ], + // 6 + [ + // empty + ['_other' => null, '_choices' => null], + ], + // 7 + [ + // empty + [null], + ], + ]; + } + // /////////////////////////////////////// // // test function isEmptyValue @@ -435,6 +413,28 @@ final class CustomFieldsChoiceTest extends KernelTestCase $this->assertFalse($isEmpty); } + public static function serializedRepresentationDataProvider() + { + return [ + [ + // multiple => false, allow_other => false + 'my-value', + ], + [ + // multiple => true, allow_ther => false + ['my-value'], + ], + [ + // multiple => false, allow_other => true, current value not in other + ['_other' => '', '_choices' => 'my-value'], + ], + [ + // multiple => true, allow_other => true, current value not in other + ['_other' => '', '_choices' => ['my-value']], + ], + ]; + } + /** * @param array $options * diff --git a/src/Bundle/ChillDocGeneratorBundle/Resources/public/vuejs/_components/PickTemplate.vue b/src/Bundle/ChillDocGeneratorBundle/Resources/public/vuejs/_components/PickTemplate.vue index 6639b0477..1bcc95fd0 100644 --- a/src/Bundle/ChillDocGeneratorBundle/Resources/public/vuejs/_components/PickTemplate.vue +++ b/src/Bundle/ChillDocGeneratorBundle/Resources/public/vuejs/_components/PickTemplate.vue @@ -58,6 +58,7 @@
{{ 'Name'|trans }}
  • - -
  • -
  • - +