Skip to content
Snippets Groups Projects
AbonneControllerMultimediaTest.php 35.2 KiB
Newer Older
llaffont's avatar
llaffont committed
<?php
/**
 * Copyright (c) 2012, Agence Française Informatique (AFI). All rights reserved.
 *
 * AFI-OPAC 2.0 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.
 *
 * There are special exceptions to the terms and conditions of the AGPL as it
 * is applied to this software (see README file).
 *
 * AFI-OPAC 2.0 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 AFI-OPAC 2.0; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA 
 */

require_once 'AbstractControllerTestCase.php';
require_once 'application/modules/opac/controllers/AbonneController.php';
trait TAbonneControllerMultimediaFixtureHoldSuccessOnSept12 {
	protected function _launch() {
		$this->onLoaderOfModel('Class_Multimedia_Location')
			->whenCalled('findByIdOrigine')
			->answers(Class_Multimedia_Location::newInstanceWithId(1));

				
		$this->onLoaderOfModel('Class_Multimedia_Device')
			->whenCalled('findByIdOrigineAndLocation')
			->answers(Class_Multimedia_Device::newInstanceWithId(1));
				
		$this->onLoaderOfModel('Class_Multimedia_DeviceHold')
			->whenCalled('getHoldOnDeviceAtTime')
			->answers(Class_Multimedia_DeviceHold::newInstanceWithId(333)
				->setIdUser($this->_user->getId())
				->setEnd(strtotime('2012-09-12 16:40:00')));
				
		parent::_launch();
	}
}




trait TAbonneControllerMultimediaFixtureWithUserLaurentInDevsAgiles {
	protected function _initUser() {
		$this->_user = AbonneControllerMultimediaUsersFixtures::getLaurent();
		$this->_group= 'Devs agiles';
	}
}




abstract class AbonneControllerMultimediaAuthenticateTestCase extends AbstractControllerTestCase {
llaffont's avatar
llaffont committed
	public function setUp() {
		parent::setUp();
			->whenCalled('authenticateLoginPassword')->answers(false)
			->whenCalled('hasIdentity')->answers(false)
			->whenCalled('getIdentity')->answers(null)
			->whenCalled('newAuthSIGB')->answers('auth_sigb')
			->whenCalled('newAuthDb')->answers('auth_db');
	public function tearDown() {
		ZendAfi_Auth::setInstance(null);
		parent::tearDown();
	}

	/**
	 * @param $url string
	 * @return stdClass
	 */
	protected function getJson($url) {
		$this->dispatch($url, true);
		return json_decode($this->_response->getBody());
	}


	/**
	 * @param $user Class_Users
	 */
	protected function _expectUserToLoad($user) {
		$this->_auth
			->whenCalled('authenticateLoginPassword')
			->with($user->getLogin(), $user->getPassword(), ['auth_sigb', 'auth_db'])
			->willDo(
				function() use ($user) {
					$this->_auth
						->whenCalled('getIdentity')
						->answers($user);
					return true;
				});
llaffont's avatar
llaffont committed
		Storm_Test_ObjectWrapper::onLoaderOfModel('Class_Users')
			->whenCalled('findFirstBy')
			->with(array('login'=> $user->getLogin()))
			->answers($user)
				
			->whenCalled('findFirstBy')
			->answers(null);
	}

	/**
	 * @param $user Class_Users
	 * @param $group_label string
	 */
	protected function _expectGroupForUser($user, $group_label) {
		Storm_Test_ObjectWrapper::onLoaderOfModel('Class_UserGroupMembership')
				->whenCalled('findAllBy')
llaffont's avatar
llaffont committed
				->with(['role' => 'user', 'model' => $user])
				->answers(array(Class_UserGroupMembership::getLoader()
						->newInstance()
						->setUserGroup(Class_UserGroup::getLoader()
							->newInstanceWithId(1)
llaffont's avatar
llaffont committed

		Storm_Test_ObjectWrapper::onLoaderOfModel('Class_UserGroup')
			->whenCalled('findAllBy')
			->with(['role_level' => $user->getRoleLevel(), 
							'group_type' => Class_UserGroup::TYPE_DYNAMIC])
			->answers([]);
class AbonneControllerMultimediaAuthenticateValidationTest extends AbonneControllerMultimediaAuthenticateTestCase {
	public function setUp() {
		parent::setUp();
		$this->_expectUserToLoad(AbonneControllerMultimediaUsersFixtures::getLaurent());
llaffont's avatar
llaffont committed

	/** @test */
	public function responseShouldNotBeARedirect() {
		$json = $this->getJson('/abonne/authenticate/login/any/password/any');
llaffont's avatar
llaffont committed
		$this->assertNotRedirect();
	}
	/** @test */
	public function controllerActionShouldBeAbonneAuthenticate() {
		$this->getJson('/abonne/authenticate/login/any/password/any');
		$this->assertController('abonne');
		$this->assertAction('authenticate');
	}


	/** @test */
	public function withoutPosteShouldReturnErrorMissingParameter() {
		$json = $this->getJson('/abonne/authenticate/login/any');
		$this->assertEquals('MissingParameter', $json->error);
	}


	/** @test */
	public function withoutSiteShouldReturnErrorMissingParameter() {
		$json = $this->getJson('/abonne/authenticate/login/any/password/any/poste/1');
		$this->assertEquals('MissingParameter', $json->error);
	}


llaffont's avatar
llaffont committed
	/** @test */
	public function getAbonneZorkShouldReturnErrorUserNotFound() {
		$json = $this->getJson('/abonne/authenticate/login/any/password/toto/poste/1/site/1');
llaffont's avatar
llaffont committed
		$this->assertEquals("UserNotFound", $json->error);
	}
llaffont's avatar
llaffont committed

	/** @test */
	public function authenticateAbonneLaurentPasswordXXXShouldReturnWrongPassword() {
		$json = $this->getJson('/abonne/authenticate/login/laurent/password/xxx/poste/1/site/1');
		$this->assertEquals("PasswordIsWrong", $json->error);	
class AbonneControllerMultimediaAuthenticateMireilleTest extends AbonneControllerMultimediaAuthenticateTestCase {
	public function setUp() {
		parent::setUp();
		$user = AbonneControllerMultimediaUsersFixtures::getMireille();
		$this->_expectUserToLoad($user);

		$this->_json = $this->getJson('/abonne/authenticate/login/mireille/password/afi/poste/1/site/1');
	}

llaffont's avatar
llaffont committed

	/** @test */
	public function shouldReturnSubscriptionExpired() {
		$this->assertEquals('SubscriptionExpired', $this->_json->error);	
	}
}


abstract class AbonneControllerMultimediaAuthenticateValidTestCase extends AbonneControllerMultimediaAuthenticateTestCase {
	protected $_user;
	protected $_group;

	public function setUp() {
		parent::setUp();

		$this->_initUser();
		$this->_expectUserToLoad($this->_user);
		$this->_expectGroupForUser($this->_user, $this->_group);
		$this->_launch();
	}


	protected function _launch() {
		$this->_json = $this->getJson(sprintf('/abonne/authenticate/login/%s/password/%s/poste/1/site/1',
				                                  $this->_user->getLogin(),
				                                  $this->_user->getPassword()));
	}


	protected function _initUser() {}
}


class AbonneControllerMultimediaAuthenticateLaurentTest extends AbonneControllerMultimediaAuthenticateValidTestCase {
	use 
		TAbonneControllerMultimediaFixtureHoldSuccessOnSept12,
		TAbonneControllerMultimediaFixtureWithUserLaurentInDevsAgiles;
	/** @test */
	public function shouldNotReturnError() {
		$this->assertFalse(property_exists($this->_json, 'error'));
	/** @test */
	public function idShoudBe8() {
		$this->assertEquals('8', $this->_json->id);
	/** @test */
	public function loginShoudBelaurent() {
		$this->assertEquals('laurent', $this->_json->login);
	/** @test */
	public function passwordShoudBeAfi() {
		$this->assertEquals('afi', $this->_json->password);
	}


	/** @test */
	public function nomShoudBelaffont() {
		$this->assertEquals('laffont', $this->_json->nom);
	/** @test */
	public function prenomShoudBelaurent() {
		$this->assertEquals('laurent', $this->_json->prenom);
	/** @test */
	public function dateNaissanceShoudBe1978_02_17() {
		$this->assertEquals('1978/02/17', $this->_json->date_naissance);
	/** @test */
	public function groupShoudBeAdulteAbonneAdminAndAgile() {
llaffont's avatar
llaffont committed
		$this->assertEquals(array('adulte','abonne', 'abonne_sigb', 'Devs agiles'),
	/** @test */
	public function shouldHaveHold() {
		$this->assertEquals(1, $this->_json->auth);
	/** @test */
	public function holdShouldLastUntil16h40() {
		$this->assertEquals('2012-09-12T16:40:00+02:00', $this->_json->until);
class AbonneControllerMultimediaAuthenticateLaurentDeviceNotHeldByUserTest extends AbonneControllerMultimediaAuthenticateValidTestCase {
	use TAbonneControllerMultimediaFixtureWithUserLaurentInDevsAgiles;

	protected function _launch() {
		$this->onLoaderOfModel('Class_Multimedia_Location')
			->whenCalled('findByIdOrigine')
			->answers($location = Class_Multimedia_Location::newInstanceWithId(1)								
								->setAuthDelay(1)
								->setAutohold(1));

		$this->onLoaderOfModel('Class_Multimedia_Device')
			->whenCalled('findByIdOrigineAndLocation')
			->answers(Class_Multimedia_Device::newInstanceWithId(1)
								->setGroup(Class_Multimedia_DeviceGroup::newInstanceWithId(34)->setLocation($location)));
		$this->onLoaderOfModel('Class_Multimedia_DeviceHold')
			->whenCalled('getHoldOnDeviceAtTime')
			->answers(Class_Multimedia_DeviceHold::newInstanceWithId(333)
								->setIdUser(9878)
								->setStart(strtotime('2012-09-12 08:30:00'))
								->setEnd(strtotime('2012-09-12 16:40:00')));
		parent::_launch();
	}


	/** @test */
	public function jsonShouldContainsErrorDeviceNotHeldByUser() {
		$this->assertEquals('DeviceNotHeldByUser', $this->_json->error);
	}


	/** @test */
	public function loginShoudBelaurent() {
		$this->assertEquals('laurent', $this->_json->login);
	}


	/** @test */
	public function authShouldBeZero() {
		$this->assertEquals('0', $this->_json->auth);
	}

}



class AbonneControllerMultimediaAuthenticateLaurentDeviceNotFoundTest extends AbonneControllerMultimediaAuthenticateValidTestCase {
	use TAbonneControllerMultimediaFixtureWithUserLaurentInDevsAgiles;
	protected function _launch() {
		$this->onLoaderOfModel('Class_Multimedia_Location')
			->whenCalled('findByIdOrigine')
			->answers(Class_Multimedia_Location::newInstanceWithId(1));

		$this->onLoaderOfModel('Class_Multimedia_Device')
			->whenCalled('findByIdOrigineAndLocation')
			->answers(null);
				
		parent::_launch();
	}


	/** @test */
	public function jsonShouldContainsErrorDeviceNotFound() {
		$this->assertEquals('DeviceNotFound', $this->_json->error);
	}


	/** @test */
	public function loginShoudBelaurent() {
		$this->assertEquals('laurent', $this->_json->login);
	}
}

class AbonneControllerMultimediaAuthenticateArnaudTest extends AbonneControllerMultimediaAuthenticateValidTestCase {
	use TAbonneControllerMultimediaFixtureHoldSuccessOnSept12;

	protected function _initUser() {
		$this->_user = AbonneControllerMultimediaUsersFixtures::getArnaud();
		$this->_group= 'Patrons';
	/** @test */
llaffont's avatar
llaffont committed
	public function groupsShouldBeAbonneAndPatrons() {
		$this->assertEquals(array('abonne_sigb', 'Patrons'), $this->_json->groupes);	


	/** @test */
	public function shouldNotReturnError() {
		$this->assertFalse(property_exists($this->_json, 'error'));
	}
class AbonneControllerMultimediaAuthenticateBaptisteTest extends AbonneControllerMultimediaAuthenticateValidTestCase {
	use TAbonneControllerMultimediaFixtureHoldSuccessOnSept12;

	protected function _initUser() {
		$this->_user = AbonneControllerMultimediaUsersFixtures::getBaptiste();
		$this->_group= 'Devs Oldschool';
	}

		
	/** @test */
	public function groupsShouldBeMineurAbonneAndOldSchool() {
		$this->assertEquals(array('mineur','abonne_sigb', 'Devs Oldschool'), $this->_json->groupes);	
/* Début test du workflow de réservation */
abstract class AbonneControllerMultimediaHoldTestCase extends AbstractControllerTestCase {
	protected $_session;
	public function setUp() {
		parent::setUp();
		$this->_session = new Zend_Session_Namespace('abonneController');
		$this->_session->holdBean = $this->_bean = new Class_Multimedia_ReservationBean();
		Class_Users::getIdentity()
			->setUserGroups([Class_UserGroup::newInstanceWithId(12)
											 ->setMaxDay(120)
											 ->setMaxWeek(240)
											 ->setMaxMonth(360)]);
		$this
			->onLoaderOfModel('Class_Multimedia_DeviceHold')
			->whenCalled('getDurationForUserBetweenTimes')
			->answers(0);
	}


	protected function _prepareLocationInSession() {
		Class_Multimedia_Location::newInstanceWithId(123)
			->setIdSite(3)
			->setLibelle('Antibes')
			->setSlotSize(30)
			->setMaxSlots(4)
			->setHoldDelayMin(0)
			->setHoldDelayMax(60)
			->setOuvertures([Class_Ouverture::chaqueLundi('08:30', '12:00', '12:00', '17:45')->setId(1)->cache(),
											 Class_Ouverture::chaqueMercredi('08:30', '12:00', '12:00', '17:45')->setId(3)->cache(),
											 Class_Ouverture::chaqueJeudi('08:30', '12:00', '12:00', '17:45')->setId(4)->cache()])
			->setGroups([Class_Multimedia_DeviceGroup::newInstanceWithId(3)
									 ->setLibelle('Musique')
									 ->setDevices([Class_Multimedia_Device::getLoader()
																 ->newInstanceWithId(1)
																 ->setLibelle('Poste 1')
																 ->setOs('Ubuntu Lucid')
																 ->setDisabled(0),

																 Class_Multimedia_Device::getLoader()
																 ->newInstanceWithId(3)
																 ->setLibelle('Poste 3')
																 ->setOs('OSX')
																 ->setDisabled(0)]),

									 Class_Multimedia_DeviceGroup::newInstanceWithId(5)
									 ->setLibelle('Jeunesse')
									 ->setDevices([
																 Class_Multimedia_Device::getLoader()
																 ->newInstanceWithId(2)
																 ->setLibelle('Poste 2')
																 ->setOs('Windows XP')
																 ->setDisabled(0),

																 Class_Multimedia_Device::getLoader()
																 ->newInstanceWithId(4)
																 ->setLibelle('Poste 4')
																 ->setOs('Amiga OS')
																 ->setDisabled(0)])
									 ]);
	}


	protected function _prepareTimeAndDurationInSession() {
		$this->_bean->time = '9:45';
		$this->_bean->duration = 45;
	}


	protected function _prepareGroupInSession() {
		$this->_bean->group = 5;
	}

	protected function _assertCurrentTimelineStep($step) {
		$this->_assertTimeLineStepWithClass($step, 'selected');
	}


	protected function _assertPassedTimelineStep($step) {
		$this->_assertTimeLineStepWithClass($step, 'passed');
	}


	protected function _assertTimeLineStepWithClass($step, $class) {
		$this->assertXPathContentContains('//div[@class="timeline"]//li[@class="' . $class . '"]',
			                                $step);
	}
abstract class AbonneControllerMultimediaHoldLocationTest extends AbonneControllerMultimediaHoldTestCase {
	public function setUp() {
		parent::setUp();
		Storm_Test_ObjectWrapper::onLoaderOfModel('Class_Multimedia_Location')
				->whenCalled('findAllBy')
				->answers([
									 Class_Multimedia_Location::newInstanceWithId(1)
									 ->setLibelle('Salle 1')
									 ->setBib(Class_Bib::newInstanceWithId(1)->setLibelle('Médiathèque Antibes'))
									 ->setOuvertures([Class_Ouverture::chaqueLundi('8:00', '12:00', '13:00', '18:00')->cache()]),

									 Class_Multimedia_Location::newInstanceWithId(2)
									 ->setLibelle('Salle 2')
									 ->setBib(Class_Bib::newInstanceWithId(2)->setLibelle('Médiathèque Roquefort'))
									 ->setOuvertures([Class_Ouverture::chaqueMercredi('8:00', '12:00', '13:00', '18:00')->cache()]),

									 Class_Multimedia_Location::newInstanceWithId(3)
									 ->setLibelle('Salle 3')
									 ->setBib(Class_Bib::newInstanceWithId(3)->setLibelle('Médiathèque Valbonne'))
									 ->setOuvertures([]),

									 Class_Multimedia_Location::newInstanceWithId(5)
									 ->setLibelle('Erreur')
									 ->setBib(null)
		$this->dispatch('/abonne/multimedia-hold-location', true);
	}


	/** @test */
	public function bodyShouldContainsClass_abonne_multimedia_hold_location() {
		$this->assertXPath('//body[contains(@class, "abonne_multimedia-hold-location")]');
	}


	/** @test */
	public function currentTimelineStepShouldBeLieu() {
		$this->_assertCurrentTimelineStep('Lieu');
	}
		

	/** @test */
	public function locationSalle1ShouldBePresent() {
		$this->assertXPathContentContains('//a[contains(@href, "/multimedia-hold-location/location/1")]', 'Médiathèque Antibes');
	}


	/** @test */
	public function locationSalle2ShouldBePresent() {
		$this->assertXPathContentContains('//a[contains(@href, "/multimedia-hold-location/location/2")]', 'Médiathèque Roquefort');


	/** @test */
	public function locationSalle3WithoutAnyOuvertureShouldNotBePresent() {
		$this->assertNotXPath('//a[contains(@href, "/multimedia-hold-location/location/3")]');
	}


/* Validation du lieu, on est redirigé sur l'écran choix du jour */
class AbonneControllerMultimediaHoldLocationChoiceTest extends AbonneControllerMultimediaHoldTestCase {
	public function setUp() {
		parent::setUp();
		$this->dispatch('/abonne/multimedia-hold-location/location/1', true);
	}


	/** @test */
	public function shouldRedirectToNextStep() {
		$this->assertRedirectTo('/abonne/multimedia-hold-day');
	}


	/** @test */
	public function beanShouldHaveLocationSet() {
		$this->assertEquals(1, $this->_session->holdBean->location);
class AbonneControllerMultimediaHoldDayTest extends AbonneControllerMultimediaHoldTestCase {
	public function setUp() {
		parent::setUp();
		$this->_prepareLocationInSession();
		$this->dispatch('/abonne/multimedia-hold-day', true);
	/** @test */
	public function bodyShouldContainsClass_abonne_multimedia_hold_location() {
		$this->assertXPath('//body[contains(@class, "abonne_multimedia-hold-day")]');
	}


	/** @test */
	public function currentTimelineStepShouldBeJour() {
		$this->_assertCurrentTimelineStep('Jour');
	}


	/** @test */
	public function timelineStepShouldBePassed() {
		$this->_assertPassedTimelineStep('Lieu');
	}


	/** @test */
	public function calendarShouldBePresent() {
		$this->assertXPath('//div[@class="calendar"]');
	}
}




/* Validation du second écran choix du jour, redirection vers le choix de l'heure */
class AbonneControllerMultimediaHoldDayChoiceTest extends AbonneControllerMultimediaHoldTestCase {
	public function setUp() {
		parent::setUp();
		$this->_prepareLocationInSession();
		$this->dispatch('/abonne/multimedia-hold-day/day/2012-09-12', true);
	}


	/** @test */
	public function shouldRedirectToNextStep() {
		$this->assertRedirectTo('/abonne/multimedia-hold-hours');
	}


	/** @test */
	public function beanShouldHaveDaySet() {
		$this->assertEquals('2012-09-12', $this->_session->holdBean->day);


/* Validation du second écran mais l'utilisateur a dépassé son quota de réservation */
class AbonneControllerMultimediaHoldDayChoiceWithOverQuotaTest extends AbonneControllerMultimediaHoldTestCase {
	public function setUp() {
		parent::setUp();
		$this->_prepareLocationInSession();

		Storm_Test_ObjectWrapper::onLoaderOfModel('Class_Multimedia_DeviceHold')
			->whenCalled('getDurationForUserBetweenTimes')
			->answers(8000);
				
		$this->dispatch('/abonne/multimedia-hold-day/day/2012-09-12', true);
	}


	/** @test */
	public function shouldNotRedirect() {
		$this->assertNotRedirect();
	}


	/** @test */
	public function quotaErrorShouldBePresent() {
		$this->assertXPathContentContains('//div', 'Quota déjà atteint ce jour');
	}
}





/* Troisième écran choix de l'heure de début de réservation */
class AbonneControllerMultimediaHoldHoursTest extends AbonneControllerMultimediaHoldTestCase {
	public function setUp() {
		parent::setUp();
		$this->_prepareLocationInSession();
		Class_Multimedia_Location::setTimeSource(new TimeSourceForTest('2012-09-12 09:00:00'));
		$this->dispatch('/abonne/multimedia-hold-hours', true);
	/** @test */
	public function currentTimelineStepShouldBeHoraires() {
		$this->_assertCurrentTimelineStep('Horaires');
	}
		

	/** @test */
	public function listOfStartTimesShouldBePresent() {
		$this->assertXPathCount('//select[@id="time"]/option', 17, $this->_response->getBody());
	}


	/** @test */
	public function startingAt10ShouldBePossible() {
		$this->assertXPathContentContains('//option[@value="10:00"]', '10h00');
	}


	/** @test */
	public function startingAt8AndHalfShouldNotBePossible() {
		$this->assertNotXpath('//option[@value="08:30"]');
	}


	public function oneHourDurationOptionShouldBePresent() {
		$this->assertXPathContentContains('//option[@value="60"]', '1h');
	}


	/** @test */
	public function oneHourAndAHalfDurationLinkShouldBePresent() {
		$this->assertXPathContentContains('//option[@value="90"]', '1h30mn');
	}
}




/* Troisième écran choix de l'heure, redirection sur le choix du poste */
class AbonneControllerMultimediaHoldHoursChoiceTest extends AbonneControllerMultimediaHoldTestCase {
	public function setUp() {
		parent::setUp();
		$this->_prepareLocationInSession();
		$this->_prepareDayInSession();
		$this->dispatch('/abonne/multimedia-hold-hours/time/' . urlencode('9:45') . '/duration/45', true);
	}


	/** @test */
	public function shouldRedirectToNextStep() {
		$this->assertRedirectTo('/abonne/multimedia-hold-group');
	}


	/** @test */
	public function beanShouldHaveTimeAndDurationSet() {
		$this->assertEquals('9:45', $this->_session->holdBean->time);
		$this->assertEquals('45', $this->_session->holdBean->duration);


/* Troisième écran choix d'une heure déjà allouée */
class AbonneControllerMultimediaHoldHoursChooseAlreadyHeldTest extends AbonneControllerMultimediaHoldTestCase {
	public function setUp() {
		parent::setUp();
		$this->_prepareLocationInSession();
		$this->_prepareDayInSession();
		Storm_Test_ObjectWrapper::onLoaderOfModel('Class_Multimedia_DeviceHold')
				->whenCalled('countBetweenTimesForUser')
				->answers(1);
		$this->dispatch('/abonne/multimedia-hold-hours/time/' . urlencode('9:45') . '/duration/45', true);
	}


	/** @test */
	public function errorMessageShouldBePresent() {
		$this->assertXPathContentContains('//div[@class="error"]', 'Vous avez déjà une réservation dans ce créneau horaire');
	}
}


/* Quatrième écran choix du groupe de postes */
class AbonneControllerMultimediaHoldGroupTest extends AbonneControllerMultimediaHoldTestCase {
	public function setUp() {
		parent::setUp();
		$this->_prepareLocationInSession();
		$this->_prepareDayInSession();
		$this->_prepareTimeAndDurationInSession();
		$this->dispatch('/abonne/multimedia-hold-group', true);
	}


	/** @test */
	public function pageShouldContainsLinkToGroupMusique() {
		$this->assertXPathContentContains('//a[contains(@href, "/multimedia-hold-group/group/3")]', 'Musique');
	}


	/** @test */
	public function pageShouldContainsLinkToGroupJeunesse() {
		$this->assertXPathContentContains('//a[contains(@href, "/multimedia-hold-group/group/5")]', 'Jeunesse');
	}


	/** @test */
	public function currentTimelineShouldBeSecteur() {
		$this->_assertCurrentTimelineStep('Secteur');


	/** @test */
	public function timelinePreviousActionsShouldHaveLink() {
		$this->assertXPathContentContains('//div[@class="timeline"]//li//a[contains(@href, abonne/multimedia-hold-location)]', 'Lieu');
		$this->assertXPathContentContains('//div[@class="timeline"]//li//a[contains(@href, abonne/multimedia-hold-day)]', 'Jour');
		$this->assertXPathContentContains('//div[@class="timeline"]//li//a[contains(@href, abonne/multimedia-hold-hours)]', 'Horaires');
		$this->assertNotXPathContentContains('//div[@class="timeline"]//li//a', 'Secteur');
		$this->assertNotXPathContentContains('//div[@class="timeline"]//li//a', 'Poste');
		$this->assertNotXPathContentContains('//div[@class="timeline"]//li//a', 'Confirmation');
	}
}




/* Quatrième écran validation du choix du groupe de postes, redirection vers le choix du poste */
class AbonneControllerMultimediaHoldGroupChoiceTest extends AbonneControllerMultimediaHoldTestCase {
	public function setUp() {
		parent::setUp();
		$this->_prepareLocationInSession();
		$this->_prepareDayInSession();
		$this->_prepareTimeAndDurationInSession();
		$this->dispatch('/abonne/multimedia-hold-group/group/5', true);
	}


	/** @test */
	public function shouldRedirectToStepHoldDevice() {
		$this->assertRedirectTo('/abonne/multimedia-hold-device');
	}


	/** @test */
	public function beanShouldHaveGroupSetToFive() {
		$this->assertEquals(5, $this->_session->holdBean->group);
	}
}




/* Quatrième écran validation du choix du groupe de postes, redirection vers le choix du poste */
class AbonneControllerMultimediaHoldGroupChoiceErrorTest extends AbonneControllerMultimediaHoldTestCase {
	/** @test */
	public function withoutHoursShouldRedirectToHoldHours() {
		$this->_prepareLocationInSession();
		$this->_prepareDayInSession();
		$this->dispatch('/abonne/multimedia-hold-group/group/5', true);
		$this->assertRedirectTo('/abonne/multimedia-hold-hours');
	}


	/** @test */
	public function withoutDayShouldRedirectToHoldDay() {
		$this->_prepareLocationInSession();
		$this->_prepareTimeAndDurationInSession();
		$this->dispatch('/abonne/multimedia-hold-group/group/5', true);
		$this->assertRedirectTo('/abonne/multimedia-hold-day');
	}


	/** @test */
	public function withoutLocationShouldRedirectToHoldLocation() {
		$this->_prepareDayInSession();
		$this->_prepareTimeAndDurationInSession();
		$this->dispatch('/abonne/multimedia-hold-group/group/5', true);
		$this->assertRedirectTo('/abonne/multimedia-hold-location');
	}
}




/* Cinquième écran choix du poste */
class AbonneControllerMultimediaHoldDeviceTest extends AbonneControllerMultimediaHoldTestCase {
	public function setUp() {
		parent::setUp();
		$this->_prepareLocationInSession();
		$this->_prepareDayInSession();
		$this->_prepareTimeAndDurationInSession();
		$this->_prepareGroupInSession();

		Storm_Test_ObjectWrapper::onLoaderOfModel('Class_Multimedia_DeviceHold')
				->whenCalled('countBy')
				->answers(0);
				
		$this->dispatch('/abonne/multimedia-hold-device', true);
	/** @test */
	public function currentTimelineStepShouldBePoste() {
		$this->_assertCurrentTimelineStep('Poste');
	}

	public function posteUnShouldNotBeHoldable() {
		$this->assertNotXPathContentContains('//a','Poste 1');
	}


	/** @test */
	public function posteDeuxShouldBeHoldable() {
		$this->assertXPathContentContains('//a[contains(@href, "multimedia-hold-device/device/2")]','Poste 2');
/* Cinquième écran validation du choix du poste, redirection vers la confirmation */
class AbonneControllerMultimediaHoldDeviceChoiceTest extends AbonneControllerMultimediaHoldTestCase {
	public function setUp() {
		parent::setUp();
		$this->_prepareLocationInSession();
		$this->_prepareDayInSession();
		$this->_prepareTimeAndDurationInSession();
		$this->_prepareGroupInSession();
		$this->dispatch('/abonne/multimedia-hold-device/device/1', true);
	}


	/** @test */
	public function shouldRedirectToNextStep() {
		$this->assertRedirectTo('/abonne/multimedia-hold-confirm');
	}


	/** @test */
	public function beanShouldHaveDeviceSet() {
		$this->assertEquals(1, $this->_session->holdBean->device);
	}
}


class AbonneControllerMultimediaHoldDeviceChoiceErrorTest extends AbonneControllerMultimediaHoldTestCase {
	/** @test */
	public function withoutGroupShouldRedirectToHoldGroup() {
		parent::setUp();
		$this->_prepareLocationInSession();
		$this->_prepareDayInSession();
		$this->_prepareTimeAndDurationInSession();
		$this->dispatch('/abonne/multimedia-hold-device/device/1', true);
		$this->assertRedirectTo('/abonne/multimedia-hold-group');
	}
}




/* Sixième écran confirmation de la réservation */
class AbonneControllerMultimediaHoldConfirmTest extends AbonneControllerMultimediaHoldTestCase {
	public function setUp() {
		parent::setUp();
		$this->_prepareLocationInSession();
		$this->_prepareDayInSession();
		$this->_prepareTimeAndDurationInSession();
		$this->_prepareGroupInSession();