resolving conflict

This commit is contained in:
Marc Ducobu 2015-02-06 11:26:09 +01:00
commit 090f91e19a
16 changed files with 841 additions and 31 deletions

View File

@ -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=

View File

@ -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());
}
}
}

View File

@ -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();

View File

@ -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.
*

View File

@ -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');
}
});

View File

@ -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(

View File

@ -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 <em>%name%</em> 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 <em>%name%</em> n''est pas fermé. Il ne peut donc être ouvert.'
'History %name% opened!': 'Bravo ! Le dossier de <em>%name</em> 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'

View File

@ -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'

View File

@ -25,7 +25,7 @@
{{ form_rest(form) }}
<div class="medium btn danger icon-right entypo icon-lock">
<button type="submit">{{ 'Close person accompanying period'|trans }}</button>
<button type="submit">{{ 'Submit'|trans }}</button>
</div>
{{ form_end(form) }}

View File

@ -0,0 +1,464 @@
<?php
/*
* Chill is a software for social workers
* Copyright (C) 2015 Julien Fastré <julien.fastre@champs-libres.coop>
*
* 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 <http://www.gnu.org/licenses/>.
*/
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é <julien.fastre@champs-libres.coop>
*/
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");
}
}

View File

@ -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]';

View File

@ -0,0 +1,235 @@
<?php
/*
* Chill is a suite of a modules, Chill is a software for social workers
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
*
* 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 <http://www.gnu.org/licenses/>.
*/
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é <julien.fastre@champs-libres.coop>
*/
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 <<<EOT
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse molestie at enim id auctor. Vivamus malesuada elit ipsum, ac mollis ex facilisis sit amet. Phasellus accumsan, quam ut aliquet accumsan, augue ligula consequat erat, condimentum iaculis orci magna egestas eros. In vel blandit sapien. Duis ut dui vitae tortor iaculis malesuada vitae vitae lorem. Morbi efficitur dolor orci, a rhoncus urna blandit quis. Aenean at placerat dui, ut tincidunt nulla. In ultricies tempus ligula ac rutrum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Fusce urna nibh, placerat vel auctor sed, maximus quis magna. Vivamus quam ante, consectetur vel feugiat quis, aliquet id ante. Integer gravida erat dignissim ante commodo mollis. Donec imperdiet mauris elit, nec blandit dolor feugiat ut. Proin iaculis enim ut tortor pretium commodo. Etiam aliquet hendrerit dolor sed fringilla. Vestibulum facilisis nibh tincidunt dui egestas, vitae congue mi imperdiet. Duis vulputate ultricies lectus id cursus. Fusce bibendum sem dignissim, bibendum purus quis, mollis ex. Cras ac est justo. Duis congue mattis ipsum, vitae sagittis justo dictum sit amet. Duis aliquam pharetra sem, non laoreet ante laoreet ac. Mauris ornare mi tempus rutrum consequat.
EOT;
}
}

View File

@ -16,7 +16,8 @@ class AppKernel extends Kernel
new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
new Chill\PersonBundle\ChillPersonBundle(),
new Chill\MainBundle\ChillMainBundle(),
new \Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle,
new \Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle(),
new Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle()
#add here all the required bundle (some bundle are not required)
);
}

View File

@ -0,0 +1,2 @@
*
!.gitignore

View File

@ -35,6 +35,9 @@ doctrine:
auto_generate_proxy_classes: "%kernel.debug%"
auto_mapping: true
chill_main:
available_languages: [ fr, nl, en ]
security:
providers:
users:

View File

@ -29,10 +29,24 @@
"doctrine/doctrine-bundle": "~1.2",
"chill-project/main": "*@dev",
"chill-project/custom-fields": "*@dev",
"doctrine/doctrine-fixtures-bundle": "~2.2"
"doctrine/doctrine-fixtures-bundle": "~2.2",
"champs-libres/composer-bundle-migration": "~1.0",
"doctrine/doctrine-migrations-bundle": "dev-master@dev",
"doctrine/migrations": "~1.0@dev"
},
"require-dev": {
"symfony/dom-crawler": "2.5",
"symfony/security": "~2.5"
},
"scripts": {
"post-install-cmd": [
"ComposerBundleMigration\\Composer\\Migrations::synchronizeMigrations"
],
"post-update-cmd": [
"ComposerBundleMigration\\Composer\\Migrations::synchronizeMigrations"
]
},
"extra": {
"app-migrations-dir": "Tests/Fixtures/App/app/DoctrineMigrations"
}
}