diff --git a/.travis.yml b/.travis.yml
index 73ae082a7..06751b78a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,30 +3,27 @@ php:
- 5.5
- 5.6
- hhvm-nightly
-
matrix:
allow_failures:
- - php: hhvm-nightly
-
+ - php: hhvm-nightly
sudo: false
-
addons:
- postgresql: "9.3"
-
-install:
- - composer install --dev
- - cp Tests/Fixtures/App/app/config/parameters.travis.yml Tests/Fixtures/App/app/config/parameters.yml
-
+ postgresql: '9.3'
+install:
+ - composer config -g github-oauth.github.com $GITHUB_COMPOSER_AUTH
+ - composer install --dev --no-interaction
+ - cp Tests/Fixtures/App/app/config/parameters.travis.yml Tests/Fixtures/App/app/config/parameters.yml
before_script:
- psql -c 'create database test0;' -U postgres
- psql -d test0 -c 'CREATE EXTENSION unaccent;' -U postgres
- php Tests/Fixtures/App/app/console.php --env=test cache:warmup
- php Tests/Fixtures/App/app/console.php assets:install Tests/Fixtures/App/web
- - php Tests/Fixtures/App/app/console.php doctrine:schema:create --env=test --no-interaction
+ - php Tests/Fixtures/App/app/console.php doctrine:migrations:migrate --no-interaction
- php Tests/Fixtures/App/app/console.php doctrine:fixtures:load --env=test --no-interaction
-
script: phpunit --coverage-text
-
notifications:
email:
- - info@champs-libres.coop
+ - info@champs-libres.coop
+env:
+ global:
+ secure: cTLFyo5WBqz9r+cfvYB9JozISdiXWBQ/feLmQQjOEjj+CiQteKYGh7oQkePyJJRdi95JO9jyXG8yiKGcEcVNLgwShLkwKno3iyiWOIDVl0mPmFUKbQPd9P3UVWpCiL3oH1JVTFd7uz6Mq+eUMrETeLa/3sxoxlnmre8ESqDIIEo=
diff --git a/Controller/AccompanyingPeriodController.php b/Controller/AccompanyingPeriodController.php
index f4e96de2a..75b3f9a15 100644
--- a/Controller/AccompanyingPeriodController.php
+++ b/Controller/AccompanyingPeriodController.php
@@ -221,8 +221,15 @@ class AccompanyingPeriodController extends Controller
}
} else { //if form is not valid
$this->get('session')->getFlashBag()
- ->add('danger', $this->get('translator')
- ->trans('Pediod closing form is not valide'));
+ ->add('danger',
+ $this->get('translator')
+ ->trans('Pediod closing form is not valide')
+ );
+
+ foreach ($form->getErrors() as $error) {
+ $this->get('session')->getFlashBag()
+ ->add('info', $error->getMessage());
+ }
}
}
diff --git a/Controller/PersonController.php b/Controller/PersonController.php
index cffab8fe7..d7bfdbbd4 100644
--- a/Controller/PersonController.php
+++ b/Controller/PersonController.php
@@ -91,13 +91,11 @@ class PersonController extends Controller
if ($request->getMethod() === 'POST') {
$form->handleRequest($request);
-
- if ( ! $form->isValid() ) {
-
- $errors = $form->getErrorsAsString();
-
+
+ if ( ! $form->isValid() ) {
$this->get('session')
- ->getFlashBag()->add('danger', 'error' . $errors);
+ ->getFlashBag()->add('danger', 'Thp person data provided'
+ . ' are not valid');
return $this->render('ChillPersonBundle:Person:edit.html.twig',
array('person' => $person,
@@ -107,7 +105,7 @@ class PersonController extends Controller
$this->get('session')->getFlashBag()
->add('success',
$this->get('translator')
- ->trans('The person has been created')
+ ->trans('The person data has been updated')
);
$em = $this->getDoctrine()->getManager();
diff --git a/Entity/Person.php b/Entity/Person.php
index b2a5822ff..5dae44c33 100644
--- a/Entity/Person.php
+++ b/Entity/Person.php
@@ -134,6 +134,10 @@ class Person {
$this->history->add($period);
}
+ public function removeHistoryFile(PersonHistoryFile $history) {
+ $this->history->remove($history);
+ }
+
/**
* set the Person file as open at the given date.
*
diff --git a/Form/AccompanyingPeriodType.php b/Form/AccompanyingPeriodType.php
index 98a4b2a81..f27820651 100644
--- a/Form/AccompanyingPeriodType.php
+++ b/Form/AccompanyingPeriodType.php
@@ -19,8 +19,11 @@ class AccompanyingPeriodType extends AbstractType
//if the period_action is close, date opening should not be seen
if ($options['period_action'] !== 'close') {
$builder
- ->add('date_opening', 'date', array("required" => true,
- 'widget' => 'single_text'));
+ ->add('date_opening', 'date', array(
+ "required" => true,
+ 'widget' => 'single_text',
+ 'format' => 'dd-MM-yyyy'
+ ));
}
// the closingDate should be seen only if period_action = close
@@ -38,7 +41,7 @@ class AccompanyingPeriodType extends AbstractType
($options['period_action'] === 'update' AND !$accompanyingPeriod->isOpen())
) {
$form->add('date_closing', 'date', array('required' => true,
- 'widget' => 'single_text'));
+ 'widget' => 'single_text', 'format' => 'dd-MM-yyyy'));
$form->add('closingMotive', 'closing_motive');
}
});
diff --git a/Form/PersonType.php b/Form/PersonType.php
index 84b82cd23..6d90623ef 100644
--- a/Form/PersonType.php
+++ b/Form/PersonType.php
@@ -74,7 +74,8 @@ class PersonType extends AbstractType
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
- 'data_class' => 'Chill\PersonBundle\Entity\Person'
+ 'data_class' => 'Chill\PersonBundle\Entity\Person',
+ 'validation_groups' => array('general', 'creation')
));
$resolver->setRequired(array(
diff --git a/Resources/translations/messages.en.yml b/Resources/translations/messages.en.yml
new file mode 100644
index 000000000..2a13e4c4e
--- /dev/null
+++ b/Resources/translations/messages.en.yml
@@ -0,0 +1,80 @@
+Edit: Edit
+'First name': First name
+'Last name': Last name
+Name: Name
+'Date of birth': Date of birth
+'Unknown date of birth': 'Date de naissance inconnue'
+Nationality: Nationality
+'Without nationality': 'Sans nationalité'
+Gender: Gender
+'Creation date': 'Date d''ouverture'
+'Not given': 'Non renseigné'
+'Place of birth': 'Place of birth'
+'Country of birth': 'Country of birth'
+'Unknown country of birth': 'Pays inconnu'
+'Marital status': 'État civil'
+'Number of children': 'Nombre d''enfants'
+'{0} No child|{1} One child | ]1,Inf] %nb% children': '{0} Aucun enfant|{1} Un enfant | ]1,Inf] %nb% enfants'
+'National number': 'Numéro national'
+Email: 'Email addresses'
+Address: Adresse
+Memo: Memo
+Phonenumber: 'Phonenumber7'
+'{0} Born the %date% | {1} Born the %date%': '{0} Né le %date% | {1} Née le %date%'
+'Spoken languages': 'Langues parlées'
+'Unknown spoken languages': 'Langues parlées inconnues'
+Male: Homme
+Female: Femme
+man: Homme
+woman: Femme
+Divorced: Divorcé(e)
+Separated: Séparé(e)
+Widow: Veuf(ve)
+'Unknow marital status': Indéterminé
+'Legal cohabitant': 'Cohabitant légal'
+Single: Célibataire
+Married: Marié(e)
+'General information': Généralités
+'Birth information': Naissance
+'Family information': Famille
+'Contact information': 'Informations de contact'
+'Administrative information': Administratif
+'Alreay existing person': 'Dossiers déjà encodés'
+'Add the person': 'Ajouter la personne'
+'Confirm the creation': 'Confirmer la création'
+'You will create this person': 'Vous allez créer le dossier suivant'
+Return: Retour
+Submit: Submit
+Reset: 'Remise à zéro'
+'The person data has been updated': 'Bravo ! Les données ont été mises à jour.'
+'{1} The person field %field% is incorrect. Please check. | ]1, Inf] Several person fields are incorrect. Please check.': '{1} Le champs %field% est incorrect. Veuillez le corriger. | ]1, Inf] Plusieurs champs sont incorrects. Veuillez les vérifier.'
+'Add a person': 'Ajout d''une personne'
+'Person Menu': 'Menu personne'
+'The person data are not valid': 'Les données de votre formulaire sont invalides.'
+'%nb% person with similar name. Please verify that this is a new person': '%nb% personnes ont un nom similaire. Vérifiez qu''il ne s''agit pas de l''une d''elles.'
+'The person has been created': 'Le dossier a été créé'
+'Person search results': 'Recherche de personnes'
+'Search within persons': 'Recherche parmi les personnes'
+'%total% persons matching the search %pattern%': '{0} Aucune personne ne correspond aux termes de recherche "%pattern%" | {1} Une personne a été trouvée par la recherche "%pattern%" | ]1,Inf] %total% personnes correspondent aux termes de recherche "%pattern%".'
+'Last opening since %last_opening%': 'Dernière ouverture le %last_opening%.'
+'Close person history': Clotûrer
+'Person history - %name%': 'Historique du dossier - %name%'
+'Opening date': 'Date d''ouverture'
+'Closing date': 'Date de fermeture'
+'Still open': 'Toujours en cours'
+'Close history': 'Clôre le dossier'
+'Open history': 'Ouvrir le dossier'
+'Create history': 'Nouvel ouverture-fermeture à une autre date'
+'Closing motive': 'Motif de clôture'
+'History created!': 'Bravo ! Le dossier est maintenant ouvert.'
+'Error! History not created!': 'Erreur ! Le dossier n''a pas pu être ouvert.'
+'Updating history done': 'Bravo ! La mise à jour de l''historique a réussi !'
+'Error when updating history': 'Les données introduites ne sont pas valides. Veuillez vérifier les informations ci-dessous.'
+'Beware history is closed': 'Attention le dossier est déjà fermé'
+'History closed!': 'Bravo ! Le dossier de %name% a été clotûré.'
+'Error! History not closed!': 'Les informations introduites ne sont pas valides. Le dossier n''a pu être clos.'
+'History closing form is not valide': 'Le formulaire n''est pas valide.'
+'Error! History %name% is not closed ; it can be open': 'Le dossier de %name% n''est pas fermé. Il ne peut donc être ouvert.'
+'History %name% opened!': 'Bravo ! Le dossier de %name a été ouvert'
+'History not opened': 'Les informations introduites ne sont pas valides. Le dossier n''a pu être ouvert.'
+'Person details': 'Détails de la personne'
diff --git a/Resources/translations/messages.fr.yml b/Resources/translations/messages.fr.yml
index e14fb5b5f..b08fc84fd 100644
--- a/Resources/translations/messages.fr.yml
+++ b/Resources/translations/messages.fr.yml
@@ -47,6 +47,7 @@ Return: Retour
Submit: Envoi
Reset: 'Remise à zéro'
'The person data has been updated': 'Bravo ! Les données ont été mises à jour.'
+'The person data provided are not valid': 'Les données introduites ne sont pas valides'
'{1} The person field %field% is incorrect. Please check. | ]1, Inf] Several person fields are incorrect. Please check.': '{1} Le champs %field% est incorrect. Veuillez le corriger. | ]1, Inf] Plusieurs champs sont incorrects. Veuillez les vérifier.'
'Add a person': 'Ajout d''une personne'
'Person Menu': 'Menu personne'
diff --git a/Resources/views/AccompanyingPeriod/form.html.twig b/Resources/views/AccompanyingPeriod/form.html.twig
index 2e23c9832..94006b2f6 100644
--- a/Resources/views/AccompanyingPeriod/form.html.twig
+++ b/Resources/views/AccompanyingPeriod/form.html.twig
@@ -25,7 +25,7 @@
{{ form_rest(form) }}
-
+
{{ form_end(form) }}
diff --git a/Tests/Controller/AccompanyingPeriodControllerTest.php b/Tests/Controller/AccompanyingPeriodControllerTest.php
new file mode 100644
index 000000000..1d2abd882
--- /dev/null
+++ b/Tests/Controller/AccompanyingPeriodControllerTest.php
@@ -0,0 +1,464 @@
+
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+namespace Chill\PersonBundle\Tests\Controller;
+
+use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
+use Chill\PersonBundle\Entity\PersonHistoryFile as AccompanyingPeriod;
+use Chill\PersonBundle\Entity\Person;
+use Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive;
+
+/**
+ * Test the creation or deletion of accompanying periods
+ *
+ * @author Julien Fastré
+ */
+class AccompanyingPeriodControllerTest extends WebTestCase
+{
+ /**
+ *
+ * @var \Symfony\Component\BrowserKit\Client
+ */
+ private $client;
+
+ /**
+ *
+ * @var Person
+ */
+ private $person;
+
+ /**
+ *
+ * @var \Doctrine\ORM\EntityManagerInterface
+ */
+ private static $em;
+
+ const OPENING_INPUT = 'cl_chill_personbundle_personhistoryfile[date_opening]';
+ const CLOSING_INPUT = 'cl_chill_personbundle_personhistoryfile[date_closing]';
+ const CLOSING_MOTIVE_INPUT = 'cl_chill_personbundle_personhistoryfile[closingMotive]';
+
+ public static function setUpBeforeClass()
+ {
+ static::bootKernel();
+
+ static::$em = static::$kernel->getContainer()
+ ->get('doctrine.orm.entity_manager');
+ }
+
+ public function setUp()
+ {
+ $this->client = static::createClient(array(), array(
+ 'PHP_AUTH_USER' => 'center a_social',
+ 'PHP_AUTH_PW' => 'password',
+ ));
+
+ $this->person = (new Person(new \DateTime('2015-01-05')))
+ ->setFirstName('Roland')
+ ->setLastName('Gallorime')
+ ->setGenre(Person::GENRE_MAN)
+ ;
+
+ static::$em->persist($this->person);
+ static::$em->flush();
+ }
+
+ public function tearDown()
+ {
+ static::$em->refresh($this->person);
+ static::$em->remove($this->person);
+
+ static::$em->flush();
+ }
+
+ private function generatePeriods(array $periods)
+ {
+ foreach ($periods as $periodDef) {
+ $period = new AccompanyingPeriod(new \DateTime($periodDef['openingDate']));
+
+ if (array_key_exists('closingDate', $periodDef)) {
+ if (!array_key_exists('closingMotive', $periodDef)) {
+ throw new \LogicalException('you must define a closing '
+ . 'motive into your periods fixtures');
+ }
+
+ $period->setDateClosing(new \DateTime($periodDef['closingDate']))
+ ->setClosingMotive($periodDef['closingMotive']);
+ }
+
+ $this->person->addHistoryFile($period);
+
+ static::$em->persist($period);
+
+ }
+
+ static::$em->flush();
+ }
+
+ private function getLastValueOnClosingMotive(\Symfony\Component\DomCrawler\Form $form)
+ {
+ $values = $form->get(self::CLOSING_MOTIVE_INPUT)
+ ->availableOptionValues();
+ return end($values);
+ }
+
+ private function getRandomClosingMotive()
+ {
+ $motives = static::$em
+ ->getRepository('ChillPersonBundle:AccompanyingPeriod\ClosingMotive')
+ ->findAll();
+ return end($motives);
+ }
+
+ /**
+ * Test the closing of a periods
+ *
+ * Given that a person as an accompanying period opened since 2015-01-05
+ * and we fill the close form (at /en/person/[id]/history/close
+ * with : dateClosing: 2015-02-01
+ * with : the last closing motive in list
+ * Then the response should redirect to history view
+ * And the next page should have a `.error` element present in page
+ *
+ * @todo
+ */
+ public function testClosingCurrentPeriod()
+ {
+
+ $crawler = $this->client->request('GET', '/en/person/'
+ .$this->person->getId().'/history/close');
+
+ $form = $crawler->selectButton('Submit')->form();
+
+ $form->get(self::CLOSING_MOTIVE_INPUT)
+ ->setValue($this->getLastValueOnClosingMotive($form));
+ $form->get(self::CLOSING_INPUT)
+ ->setValue((new \DateTime('2015-02-01'))->format('d-m-Y'));
+
+ $cr = $this->client->submit($form);
+
+ $this->assertTrue($this->client->getResponse()->isRedirect(
+ '/en/person/'.$this->person->getId().'/history'),
+ 'the server redirects to /history page');
+ $this->assertGreaterThan(0, $this->client->followRedirect()
+ ->filter('.success')->count(),
+ "a 'success' element is shown");
+ }
+
+ /**
+ * Test the closing of a periods
+ *
+ * Given that a person as an accompanying period opened since 2015-01-05
+ * and we fill the close form (at /en/person/[id]/history/close
+ * with : dateClosing: 2014-01-01
+ * with : the last closing motive in list
+ * Then the response should redirect to history view
+ * And the next page should have a `.error` element present in page
+ *
+ * @todo
+ */
+ public function testClosingCurrentPeriodWithDateClosingBeforeOpeningFails()
+ {
+
+ $crawler = $this->client->request('GET', '/en/person/'
+ .$this->person->getId().'/history/close');
+
+ $form = $crawler->selectButton('Submit')->form();
+
+ $form->get(self::CLOSING_MOTIVE_INPUT)
+ ->setValue($this->getLastValueOnClosingMotive($form));
+ $form->get(self::CLOSING_INPUT)
+ ->setValue((new \DateTime('2014-01-01'))->format('d-m-Y'));
+
+ $crawlerResponse = $this->client->submit($form);
+
+ $this->assertFalse($this->client->getResponse()->isRedirect(),
+ 'the server stays on the /close page');
+ $this->assertGreaterThan(0, $crawlerResponse
+ ->filter('.error')->count(),
+ "an '.error' element is shown");
+ }
+
+ /**
+ * Test the creation of a new period
+ *
+ * Given that a person as an accompanying period opened since 2015-01-05
+ * and we create a new period
+ * with : dateClosing: 2014-12-31
+ * with : dateOpening: 2014-01-01
+ * with : the last closing motive in list
+ * Then the response should redirect to history view
+ */
+ public function testAddNewPeriodBeforeActual()
+ {
+
+ $crawler = $this->client->request('GET', '/en/person/'
+ .$this->person->getId().'/history/create');
+
+ $form = $crawler->selectButton('Submit')->form();;
+ $form->get(self::CLOSING_MOTIVE_INPUT)
+ ->setValue($this->getLastValueOnClosingMotive($form));
+ $form->get(self::CLOSING_INPUT)
+ ->setValue('31-12-2014');
+ $form->get(self::OPENING_INPUT)
+ ->setValue('01-01-2014');
+
+ $this->client->submit($form);
+
+ $this->assertTrue($this->client->getResponse()->isRedirect(
+ '/en/person/'.$this->person->getId().'/history'),
+ 'the server redirects to /history page');
+ $this->assertGreaterThan(0, $this->client->followRedirect()
+ ->filter('.success')->count(),
+ "a 'success' element is shown");
+ }
+
+ /**
+ * Create a period with closing after current fails
+ *
+ * Given that a person as an accompanying period opened since 2015-01-05
+ * and we create a new period
+ * with : dateClosing: 2015-02-01 (after 2015-01-05)
+ * with : dateOpening: 2014-12-31
+ * with : the last closing motive in list
+ * Then the response should not redirect to any page
+ * and an error element is shown
+ *
+ * @todo
+ */
+ public function testCreatePeriodWithClosingAfterCurrentFails()
+ {
+
+ $this->markTestSkipped('this feature is not yet implemented');
+
+ $crawler = $this->client->request('GET', '/en/person/'
+ .$this->person->getId().'/history/create');
+
+ $form = $crawler->selectButton('Submit')->form();;
+ $form->get(self::CLOSING_MOTIVE_INPUT)
+ ->setValue($this->getLastValueOnClosingMotive($form));
+ $form->get(self::CLOSING_INPUT)
+ ->setValue('01-02-2015');
+ $form->get(self::OPENING_INPUT)
+ ->setValue('31-12-2014');
+
+ $crawler = $this->client->submit($form);
+
+ $this->assertFalse($this->client->getResponse()->isRedirect(),
+ 'the server stay on form page');
+ $this->assertGreaterThan(0, $crawler->filter('.error')->count(),
+ "an 'error' element is shown");
+ }
+
+ /**
+ * Create a period after a current opened period fails
+ *
+ * Given that a person as an accompanying period opened since 2015-01-05
+ * and we create a new period
+ * with : dateClosing: 2015-03-01
+ * with : dateOpening: 2015-02-01
+ * with : the last closing motive in list
+ * Then the response should not redirect to any page
+ * and an error element is shown
+ *
+ * @todo
+ */
+ public function testCreatePeriodWithOpeningAndClosingAfterCurrentFails()
+ {
+
+ $this->markTestSkipped('this feature is not yet implemented');
+
+ $crawler = $this->client->request('GET', '/en/person/'
+ .$this->person->getId().'/history/create');
+
+ $form = $crawler->selectButton('Submit')->form();;
+ $form->get(self::CLOSING_MOTIVE_INPUT)
+ ->setValue($this->getLastValueOnClosingMotive($form));
+ $form->get(self::CLOSING_INPUT)
+ ->setValue('01-03-2015');
+ $form->get(self::OPENING_INPUT)
+ ->setValue('01-02-2015');
+
+ $crawler = $this->client->submit($form);
+
+ $this->assertFalse($this->client->getResponse()->isRedirect(),
+ 'the server stay on form page');
+ $this->assertGreaterThan(0, $crawler->filter('.error')->count(),
+ "an 'error' element is shown");
+ }
+
+ /**
+ * create a period with date end between another period must fails
+ *
+ * Given that a person as an accompanying period opened since 2015-01-05
+ * and that this person has another accompanying period between 2014-01-01 and 2014-12-31
+ * and we create a new period
+ * with : dateClosing: 2014-16-01
+ * with : dateOpening: 2013-01-01
+ * with : the last closing motive in list
+ * Then the response should not redirect
+ * and a error element is shown on the response page
+ */
+ public function testCreatePeriodWithDateEndBetweenAnotherPeriodFails()
+ {
+
+ $this->generatePeriods(array(
+ [
+ 'openingDate' => '2014-01-01',
+ 'closingDate' => '2014-12-31',
+ 'closingMotive' => $this->getRandomClosingMotive()
+ ]
+ ));
+
+ $crawler = $this->client->request('GET', '/en/person/'
+ .$this->person->getId().'/history/create');
+
+ $form = $crawler->selectButton('Submit')->form();;
+ $form->get(self::CLOSING_MOTIVE_INPUT)
+ ->setValue($this->getLastValueOnClosingMotive($form));
+ $form->get(self::CLOSING_INPUT)
+ ->setValue('31-12-2014');
+ $form->get(self::OPENING_INPUT)
+ ->setValue('01-02-2015');
+
+ $crawlerResponse = $this->client->submit($form);
+
+ $this->assertFalse($this->client->getResponse()->isRedirect(),
+ 'the server stay on form page');
+ $this->assertGreaterThan(0, $crawlerResponse->filter('.error')->count(),
+ "an 'error' element is shown");
+ }
+
+ /**
+ * create a period with date closing after opening fails
+ *
+ * Given that a person as an accompanying period opened since 2015-01-05
+ * and we create a new period
+ * with : dateClosing: 2014-01-01 (before opening)
+ * with : dateOpening: 2015-01-01
+ * with : the last closing motive in list
+ * Then the response should redirect to history view
+ */
+ public function testCreatePeriodWithClosingBeforeOpeningFails()
+ {
+ $crawler = $this->client->request('GET', '/en/person/'
+ .$this->person->getId().'/history/create');
+
+ $form = $crawler->selectButton('Submit')->form();;
+ $form->get(self::CLOSING_MOTIVE_INPUT)
+ ->setValue($this->getLastValueOnClosingMotive($form));
+ $form->get(self::CLOSING_INPUT)
+ ->setValue('01-01-2014');
+ $form->get(self::OPENING_INPUT)
+ ->setValue('01-01-2015');
+
+ $crawler = $this->client->submit($form);
+
+ $this->assertFalse($this->client->getResponse()->isRedirect(),
+ 'the server stay on form page');
+ $this->assertGreaterThan(0, $crawler->filter('.error')->count(),
+ "an 'error' element is shown");
+ }
+
+ /**
+ * create a period with date closing and date opening inside another period
+ * fails
+ *
+ * Given that a person as an accompanying period opened since 2015-01-05
+ * and that this person has another accompanying period between 2014-01-01 and 2014-12-31
+ * and we create a new period
+ * with : dateClosing: 2014-02-01
+ * with : dateOpening: 2014-03-01
+ * with : the last closing motive in list
+ * Then the response should not redirect
+ * and a error element is shown on the response page
+ */
+ public function testCreatePeriodAfterOpeningFails()
+ {
+ $this->generatePeriods(array(
+ [
+ 'openingDate' => '2014-01-01',
+ 'closingDate' => '2014-12-31',
+ 'closingMotive' => $this->getRandomClosingMotive()
+ ]
+ ));
+
+ $crawler = $this->client->request('GET', '/en/person/'
+ .$this->person->getId().'/history/create');
+
+ $form = $crawler->selectButton('Submit')->form();;
+ $form->get(self::CLOSING_MOTIVE_INPUT)
+ ->setValue($this->getLastValueOnClosingMotive($form));
+ $form->get(self::CLOSING_INPUT)
+ ->setValue('2014-02-01');
+ $form->get(self::OPENING_INPUT)
+ ->setValue('01-03-2014');
+
+ $crawlerResponse = $this->client->submit($form);
+
+ $this->assertFalse($this->client->getResponse()->isRedirect(),
+ 'the server stay on form page');
+ $this->assertGreaterThan(0, $crawlerResponse->filter('.error')->count(),
+ "an 'error' element is shown");
+ }
+
+ /**
+ * Create a period with dateOpening between another period must fails
+ *
+ * Given that a person as an accompanying period opened since 2015-01-05
+ * and that this person has another accompanying period between 2014-01-01 and 2014-12-31
+ * and we create a new period
+ * with : dateClosing: 2015-01-01
+ * with : dateOpening: 2014-06-01
+ * with : the last closing motive in list
+ * Then the response should not redirect
+ * and a error element is shown on the response page
+ */
+ public function testCreatePeriodWithDateOpeningBetweenAnotherPeriodFails()
+ {
+
+ $this->generatePeriods(array(
+ [
+ 'openingDate' => '2014-01-01',
+ 'closingDate' => '2014-12-31',
+ 'closingMotive' => $this->getRandomClosingMotive()
+ ]
+ ));
+
+ $crawler = $this->client->request('GET', '/en/person/'
+ .$this->person->getId().'/history/create');
+
+ $form = $crawler->selectButton('Submit')->form();;
+ $form->get(self::CLOSING_MOTIVE_INPUT)
+ ->setValue($this->getLastValueOnClosingMotive($form));
+ $form->get(self::CLOSING_INPUT)
+ ->setValue('2015-01-01');
+ $form->get(self::OPENING_INPUT)
+ ->setValue('01-06-2014');
+
+ $crawlerResponse = $this->client->submit($form);
+
+ $this->assertFalse($this->client->getResponse()->isRedirect(),
+ 'the server stay on form page');
+ $this->assertGreaterThan(0, $crawlerResponse->filter('.error')->count(),
+ "an 'error' element is shown");
+ }
+
+
+}
diff --git a/Tests/Controller/PersonControllerTest.php b/Tests/Controller/PersonControllerCreateTest.php
similarity index 99%
rename from Tests/Controller/PersonControllerTest.php
rename to Tests/Controller/PersonControllerCreateTest.php
index 8c0f91072..cbc6444e6 100644
--- a/Tests/Controller/PersonControllerTest.php
+++ b/Tests/Controller/PersonControllerCreateTest.php
@@ -9,7 +9,7 @@ use Symfony\Component\HttpFoundation\RedirectResponse;
/**
* Test creation and deletion for persons
*/
-class PersonControllerTest extends WebTestCase
+class PersonControllerCreateTest extends WebTestCase
{
const FIRSTNAME_INPUT = 'chill_personbundle_person_creation[firstName]';
diff --git a/Tests/Controller/PersonControllerUpdateTest.php b/Tests/Controller/PersonControllerUpdateTest.php
new file mode 100644
index 000000000..6196bb166
--- /dev/null
+++ b/Tests/Controller/PersonControllerUpdateTest.php
@@ -0,0 +1,235 @@
+
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+namespace Chill\PersonBundle\Tests\Controller;
+
+use Chill\PersonBundle\Entity\Person;
+use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
+
+/**
+ * Test the edition of persons
+ *
+ * As I am logged in as "center a_social"
+ *
+ * @author Julien Fastré
+ */
+class PersonControllerUpdateTest extends WebTestCase
+{
+ /**
+ *
+ * @var \Doctrine\ORM\EntityManagerInterface
+ */
+ private $em;
+
+ /**
+ *
+ * @var Person
+ */
+ private $person;
+
+ /**
+ *
+ * @var string
+ */
+ private $editUrl;
+
+ /**
+ * prepare client and select a random person
+ */
+ public function setUp()
+ {
+ static::bootKernel();
+
+ $this->person = (new Person())
+ ->setLastName("My Beloved")
+ ->setFirstName("Jesus")
+ ->setGenre(Person::GENRE_MAN);
+
+ $this->em = static::$kernel->getContainer()->get('doctrine.orm.entity_manager');
+
+ $this->em->persist($this->person);
+ $this->em->flush();
+
+ $this->editUrl = '/en/person/'.$this->person->getId().'/general/edit';
+ $this->seeUrl = '/en/person/'.$this->person->getId().'/general';
+
+ $this->client = static::createClient(array(), array(
+ 'PHP_AUTH_USER' => 'center a_social',
+ 'PHP_AUTH_PW' => 'password',
+ ));
+ }
+
+ /**
+ * Test the edit page exist and rendering is successful
+ */
+ public function testEditPageIsSuccessful()
+ {
+ $this->client->request('GET', $this->editUrl);
+
+ $this->assertTrue($this->client->getResponse()->isSuccessful(),
+ "The person edit form is accessible");
+ }
+
+ /**
+ * test the edition of a field
+ *
+ * Given I fill the field with $value
+ * And I submit the form
+ * Then I am redirected to the 'general' page
+ * And the person is updated in the db
+ *
+ * @dataProvider validTextFieldsProvider
+ * @param string $field
+ * @param string $value
+ * @param \Closure $callback
+ */
+ public function testEditTextField($field, $value, \Closure $callback)
+ {
+ $crawler = $this->client->request('GET', $this->editUrl);
+
+ $form = $crawler->selectButton('Submit')
+ ->form();
+ //transform countries into value if needed
+ switch ($field) {
+ case 'nationality':
+ case 'countryOfBirth':
+ if ($value !== NULL) {
+ $country = $this->em->getRepository('ChillMainBundle:Country')
+ ->findOneByCountryCode($value);
+ $transformedValue = $country->getId();
+ } else {
+ $transformedValue = NULL;
+ }
+ break;
+ default:
+ $transformedValue = $value;
+ }
+
+ $form->get('chill_personbundle_person['.$field. ']')
+ ->setValue($transformedValue);
+
+ $this->client->submit($form);
+ $this->em->refresh($this->person);
+
+ $this->assertTrue($this->client->getResponse()->isRedirect($this->seeUrl),
+ 'the page is redirected to general view');
+ $this->assertEquals($value, $callback($this->person),
+ 'the value '.$field.' is updated in db');
+ }
+
+ public function testEditLanguages()
+ {
+ $crawler = $this->client->request('GET', $this->editUrl);
+ $selectedLanguages = array('en', 'an', 'bbj');
+
+ $form = $crawler->selectButton('Submit')
+ ->form();
+ $form->get('chill_personbundle_person[spokenLanguages]')
+ ->setValue($selectedLanguages);
+
+ $this->client->submit($form);
+ $this->em->refresh($this->person);
+
+ $this->assertTrue($this->client->getResponse()->isRedirect($this->seeUrl),
+ 'the page is redirected to /general view');
+ //retrieve languages codes present in person
+ foreach($this->person->getSpokenLanguages() as $lang){
+ $languagesCodesPresents[] = $lang->getId();
+ }
+ $this->assertEquals(asort($selectedLanguages), asort($languagesCodesPresents),
+ 'the person speaks the expected languages');
+
+ }
+
+
+ /**
+ *
+ * @dataProvider providesInvalidFieldsValues
+ * @param string $field
+ * @param string $value
+ */
+ public function testInvalidFields($field, $value)
+ {
+ $crawler = $this->client->request('GET', $this->editUrl);
+
+ $form = $crawler->selectButton('Submit')
+ ->form();
+ $form->get('chill_personbundle_person['.$field.']')
+ ->setValue($value);
+
+ $crawler = $this->client->submit($form);
+
+ $this->assertFalse($this->client->getResponse()->isRedirect(),
+ 'the page is not redirected to /general');
+ $this->assertGreaterThan(0, $crawler->filter('.error')->count(),
+ 'a element .error is shown');
+ }
+
+ /**
+ * provide valid values to test, with field name and
+ * a function to find the value back from person entity
+ *
+ * @return mixed[]
+ */
+ public function validTextFieldsProvider()
+ {
+ return array(
+ ['firstName', 'random Value', function(Person $person) { return $person->getFirstName(); } ],
+ ['lastName' , 'random Value', function(Person $person) { return $person->getLastName(); } ],
+ ['placeOfBirth', 'none place', function(Person $person) { return $person->getPlaceOfBirth(); }],
+ ['dateOfBirth', '15-12-1980', function(Person $person) { return $person->getDateOfBirth()->format('d-m-Y'); }],
+ ['phonenumber', '0123456789', function(Person $person) { return $person->getPhonenumber(); }],
+ ['memo', 'jfkdlmq jkfldmsq jkmfdsq', function(Person $person) { return $person->getMemo(); }],
+ ['countryOfBirth', 'BE', function(Person $person) { return $person->getCountryOfBirth()->getCountryCode(); }],
+ ['nationality', 'FR', function(Person $person) { return $person->getNationality()->getCountryCode(); }],
+ ['placeOfBirth', '', function(Person $person) { return $person->getPlaceOfBirth(); }],
+ ['dateOfBirth', '', function(Person $person) { return $person->getDateOfBirth(); }],
+ ['phonenumber', '', function(Person $person) { return $person->getPhonenumber(); }],
+ ['memo', '', function(Person $person) { return $person->getMemo(); }],
+ ['countryOfBirth', NULL, function(Person $person) { return $person->getCountryOfBirth(); }],
+ ['nationality', NULL, function(Person $person) { return $person->getNationality(); }],
+ ['genre', Person::GENRE_WOMAN, function(Person $person) { return $person->getGenre(); }]
+ );
+ }
+
+ public function providesInvalidFieldsValues()
+ {
+ return array(
+ ['firstName', $this->getVeryLongText()],
+ ['lastName', $this->getVeryLongText()],
+ ['firstName', ''],
+ ['lastName', ''],
+ ['dateOfBirth', 'false date']
+ );
+ }
+
+ public function tearDown()
+ {
+ $this->em->remove($this->person);
+ $this->em->flush();
+ }
+
+ private function getVeryLongText()
+ {
+ return <<