<?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';

abstract class PortailWithOneLoginModuleTestCase extends AbstractControllerTestCase {
	public function setUp() {
		parent::setUp();

		Storm_Test_ObjectWrapper::onLoaderOfModel('Class_IntBib')
			->whenCalled('findAllBy')
			->answers([]);

		$cfg_accueil = ['modules' => [4 => ['division' => '4',
																				'id_module' => 4,
																				'type_module' => 'LOGIN',
																				'preferences' => [
																					'identifiant' => 'Numéro de carte',
																					'mot_de_passe'=> 'Année de naissance',
																					'identifiant_exemple' => 'jj-mm-aaaa',
																					'mot_de_passe_exemple' => '1983',
																					'titre_connecte' => 'Vous êtes connecté(e)',
																					'lien_connexion' => 'please, log me',
																					'lien_mot_de_passe_oublie' => 'me rappelle plus',
																					'profil_redirect' => 1,
																					'profil_logout_redirect' => 0]]],
										'options' => []];

		Class_Profil::getCurrentProfil()
			->setBrowser('opac')
			->setCfgAccueil(ZendAfi_Filters_Serialize::serialize($cfg_accueil));
	}
	
}



class AuthControllerInviteLoggedTest extends PortailWithOneLoginModuleTestCase {
	protected function _loginHook($account) {
		$account->ROLE = "invite";
		$account->ROLE_LEVEL = 1;
	}

	public function setUp() {
		parent::setUp();
		$this->dispatch('/opac/',true);
	}

	/** @test */
	public function noLinkPretsShouldBePresent() {
		$this->assertNotXPath('//div[@id="boite_login"]//a[contains(@href, "prets")]');
	}

	/** @test */
	public function linkSeDeconnecterShouldBePresent() {
		$this->assertXPath('//div[@id="boite_login"]//a[contains(@href, "auth/logout")]');
	}


	/** @test */
	public function actionIndexShouldRedirectToOpac() {
		$this->bootstrap();
		$this->dispatch('/auth', true);
		$this->assertRedirectTo('/opac');
	}
}




class AuthControllerAbonneSIGBLoggedTest extends PortailWithOneLoginModuleTestCase {
	public function setUp() {
		parent::setUp();

		$this->emprunteur_patrick = Class_WebService_SIGB_Emprunteur::newInstance(5, 'patrick')
			->empruntsAddAll(array(Class_WebService_SIGB_Emprunt::newInstanceWithEmptyExemplaire()
														 ->setDateRetour('23/12/2056'),

														 Class_WebService_SIGB_Emprunt::newInstanceWithEmptyExemplaire()
														 ->setDateRetour('3/2/2056'),

														 Class_WebService_SIGB_Emprunt::newInstanceWithEmptyExemplaire()
														 ->setDateRetour('23/1/1999')))
			
			->reservationsAddAll(array(Class_WebService_SIGB_Reservation::newInstanceWithEmptyExemplaire()));

		ZendAfi_Auth::getInstance()->logUser(
			Class_Users::newInstanceWithId(5, 
																		 ['login' => 'patrick',
																			'idabon' => 456,
																			'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB,
																			'id_site' => 1,
																			'fiche_sigb' => ['fiche' => $this->emprunteur_patrick]]));



		$this->dispatch('/opac/');
	}


	
	/** @test */
	public function redirectProfilShouldBeProfil1(){
		$this->assertXPath('//a[contains(@href,"abonne/fiche/id_profil/1")]',$this->_response->getBody());
	}


	/** @test */
	public function linkPretsShouldBePresent() {
		$this->assertXPathContentContains('//div[@id="boite_login"]//a[contains(@href, "prets")]', '3');
	}


	/** @test */
	public function linkReservationsShouldBePresent() {
		$this->assertXPath('//div[@id="boite_login"]//a[contains(@href, "reservations")]');
	}


	/** @test */
	public function linkSeDeconnecterShouldBePresent() {
		$this->assertXPath('//div[@id="boite_login"]//a[contains(@href, "auth/logout")]');
	}


	/** 
	 * @test 
	 * @group pagetitles
	 */
	public function pageAuthLoginBarreNavShouldBeConnexion() {
		$this->bootstrap();
		$this->dispatch('/opac/auth/login',true);
	  $this->assertXPathContentContains('//div[@class="barre_nav"]/span','Connexion',$this->_response->getBody());
	}

}



class AuthControllerAbonneSIGBLoggedLogoutTest 
extends PortailWithOneLoginModuleTestCase {
	public function setUp() {
		parent::setUp();
		$this->dispatch('/opac/auth/logout');
	}


	/** @test */
	public function shouldRedirectToRoot() {
		$this->assertRedirectTo('/');
	}
}



class AuthControllerWithProfilPageAbonneSIGBLoggedLogoutTest 
extends PortailWithOneLoginModuleTestCase {
	protected $_profile, $_parent_profile;

	public function setUp() {
		parent::setUp();
		$this->_parent_profile = Class_Profil::getCurrentProfil();
		$this->_profile = $this->fixture('Class_Profil', 
																		 ['id' => 22,
																			'browser' => 'opac',
																			'libelle' => 'Profil Adulte',
																			'hauteur_banniere' => 150,
																			'couleur_texte_bandeau' => '#F2C',
																			'couleur_lien_bandeau' => '#234',
																			'menu_haut_on' => true,
																			'cfg_menus' => [],
																			'commentaire' => 'Super bib',
																			'ref_tags' => 'bib,Adulte',
																			'parent_profil' => $this->_parent_profile]);
		Class_Profil::setCurrentProfil($this->_profile);
	}

	
	/** @test **/
	public function withoutLogoutProfileShouldRedirectToParentProfile() {
		$this->dispatch('/opac/auth/logout');
		$this->assertRedirectTo('/opac/index/index/id_profil/2');
	}


	/** @test **/
	public function withLogoutProfile6InParentShouldRedirectToIt() {
		$cfg_accueil = $this->_parent_profile->getCfgAccueilAsArray();
		$cfg_accueil['modules'][4]['preferences']['profil_logout_redirect'] = 6;
		$this->_parent_profile
			->setCfgAccueil(ZendAfi_Filters_Serialize::serialize($cfg_accueil));

		$this->dispatch('/opac/auth/logout');
		$this->assertRedirectTo('/opac/index/index/id_profil/6');
	}
}




abstract class AuthControllerNobodyLoggedTestCase extends PortailWithOneLoginModuleTestCase {
	public function setUp() {
		parent::setUp();
		ZendAfi_Auth::getInstance()->clearIdentity();
	}	
}


class AuthControllerNobodyLoggedActivateTest extends AuthControllerNobodyLoggedTestCase {
	const ERROR_MESSAGE = 'Un probleme est survenu lors de l\'activation';
	const OK_MESSAGE = 'Ok, compte cree';

	public function setUp() {
		parent::setUp();
		Class_UsersNonValid::beVolatile();
		Class_Users::beVolatile();
		$this->fixture('Class_AdminVar', ['id' => 'USER_NON_VALIDATED',
																			'valeur' => self::ERROR_MESSAGE]);
		$this->fixture('Class_AdminVar', ['id' => 'USER_VALIDATED',
																			'valeur' => self::OK_MESSAGE]);
	}

	/** @test */
	public function withoutKeyShouldRedirect() {
		$this->dispatch('/opac/auth/activeuser', true);
		$this->assertRedirect();
	}

	/** @test */
	public function withUnknownKeyShouldDisplayError() {
		$this->dispatch('/opac/auth/activeuser/c/666', true);
		$this->assertXPathContentContains('//div', self::ERROR_MESSAGE);
	}

	/** @test */
	public function withKnownKeyShouldCreateUserAndDeleteNonValid() {
		$this->fixture('Class_UsersNonValid', ['id' => 12,
																					 'cle' => '777',
																					 'login' => 'harlock',
																					 'mail' => 'harlock@afi-sa.fr',
																					 'password' => 'cosmos']);
		$this->dispatch('/opac/auth/activeuser/c/777', true);
		$this->assertXPathContentContains('//div', self::OK_MESSAGE);
		// non valid deleted
		$this->assertEquals(0, Class_UsersNonValid::countBy([]));
		// user created
		$created = Class_Users::findFirstBy(['order' => 'id desc']);
		$this->assertEquals('harlock@afi-sa.fr', $created->getMail());
	}
}


class AuthControllerNobodyLoggedAndRegistrationAllowedBoiteLoginTest 
extends AuthControllerNobodyLoggedTestCase {
	public function setUp() {
		parent::setUp();

		Class_AdminVar::getLoader()
			->newInstanceWithId('INTERDIRE_ENREG_UTIL')
			->setValeur(0);

		$this->dispatch('/opac/',true);
	}


	/** @test */
	public function loginSubmitShouldBePresent(){
		$this->assertXPath('//div[@id="boite_login"]//input[@type="submit"]',
											 $this->_response->getBody());
	}


	/** @test */
	public function titleShouldBeSeConnecter(){
		$this->assertXPathContentContains('//h1','Se connecter');
	}


	/** @test **/
	public function inputLoginShouldSubmitOnKey13Pressed() {
		$this->assertXPath('//div[@id="boite_login"]//input[contains(@onkeypress,"if (event.keyCode == 13) {this.form.submit();return false;}")]');
	}


	/** @test */
	public function loginLinkShouldBePresent() {
		$this->assertXPathContentContains('//div[@id="boite_login"]//a[contains(@onclick, "submit")]',
																			'please, log me');
	}


	/** @test */
	public function lostPassLinkShouldBePresent() {
		$this->assertXPathContentContains('//div[@id="boite_login"]//tr/td[@colspan="2"]/a[contains(@href, "auth/lostpass")]',
																			'me rappelle plus');
	}


	/** @test */
	public function registerLinkShouldBePresent() {
		$this->assertXPathContentContains('//div[@id="boite_login"]//a[contains(@href, "auth/register")]', "S'enregistrer");
	}


	/** @test */
	public function shouldAccessRegisterPage() {
		$this->bootstrap();
		$this->dispatch('auth/register', true);
		$this->assertAction('register');
		$this->assertController('auth');
		$this->assertNotRedirect('/');
	}


	/** @test */
	public function inputIdentifiantShouldHavePlaceHolderJJ_MM_AAAA() {
		$this->assertXPath('//input[@name="username"][@placeholder="jj-mm-aaaa"]');
	}


	/** @test */
	public function inputPasswordShouldHavePlaceHolder1983() {
		$this->assertXPath('//input[@name="password"][@placeholder="1983"]');
	}


	/** @test */
	function headShouldContainsAbonnesJS() {		
		$this->assertXPath('//head//script[contains(@src,"public/opac/js/abonne.js")]', $this->_response->getBody());
	}


	/** @test */
	function headShouldContainsAdminCommonJS() {
		$this->assertXPath('//head//script[contains(@src,"public/admin/js/common.js")]');
	}


	/** @test */
	function headShouldContainsJQuery() {
		$this->assertXPath('//head//script[contains(@src, "jquery")]');
	}


	/** @test */
	public function globalCssShouldBeLoadedAfterJQueryUiCss() {
		$pos_jquery = strpos($this->_response->getBody(), 'js/jquery_ui/css');
		$pos_global = strpos($this->_response->getBody(), 'css/global.css');
		$this->assertTrue(($pos_jquery < $pos_global) && ($pos_jquery > 0));
	}
}




class AuthControllerNobodyLoggedAndRegistrationAllowedAjaxLoginTest extends AuthControllerNobodyLoggedTestCase {
	protected 
		$_json, 
		$_xpath;

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

		Class_AdminVar::getLoader()
			->newInstanceWithId('INTERDIRE_ENREG_UTIL')
			->setValeur(0);

		$this->dispatch('/opac/auth/popup-login/render/popup', true);
		$this->_xpath = new Storm_Test_XPath();
		$this->_json = json_decode($this->_response->getBody());
	}


	public function testLinkLostPassword() {
		$this->_xpath->assertXPath($this->_json->content,
															 '//div//a[contains(@onclick, "getUsername")]');
	}

	
	public function testLinkSenregistrer() {
		$this->_xpath->assertXPath($this->_json->content,
															 '//div//a[contains(@href, "auth/register")]');

		$this->_xpath->assertXPathContentContains(
			$this->_json->content,
			'//div//a[contains(@href, "auth/register")]',
			"S'enregistrer");
	}


	/** @test */
	public function noLinkShouldHaveRenderPopup() {
		$this->_xpath->assertNotXPath($this->_json->content,
																	'//div//a[contains(@href, "render/popup")]');
	}
}




class AuthControllerNobodyLoggedAndNoRegistrationTest extends AuthControllerNobodyLoggedTestCase {

	public function setUp() {
		parent::setUp();
		$interdire_enregistrement = new Class_AdminVar();
		$interdire_enregistrement
			->setId('INTERDIRE_ENREG_UTIL')
			->setValeur(1);
		Class_AdminVar::getLoader()->cacheInstance($interdire_enregistrement);


		$this->dispatch('/opac/');
	}


	public function testLinkSenregistrerNotHere() {
		$this->assertNotXPath('//div[@id="boite_login"]//a[contains(@href, "auth/register")]');
	}


	public function testCannotAccessRegisterPage() {
		$this->dispatch('auth/register');
		$this->assertRedirect('/');
	}
}



class AuthControllerNobodyLoggedAndNoRegistrationOnLoginPageTest extends AuthControllerNobodyLoggedTestCase {

	public function setUp() {
		parent::setUp();
		$interdire_enregistrement = new Class_AdminVar();
		$interdire_enregistrement
			->setId('INTERDIRE_ENREG_UTIL')
			->setValeur(1);
		Class_AdminVar::getLoader()->cacheInstance($interdire_enregistrement);


		$this->dispatch('/opac/auth/login');
	}

	
	/** @test **/
	public function linkRegisterShouldNotBeDisplayInLoggingBox() {
		$this->assertNotXPath('//div[@id="boite_login"]//a[contains(@href, "auth/register")]');
	}


	/** @test **/
	public function linkRegisterShouldNotBeDisplayInPageAuthLogin() {
		$this->assertNotXPath('//div[@id="fieldset-login_form"]//a[contains(@href, "auth/register")]');
	}
}




class AuthControllerNobodyLoggedAndNoRegistrationAllowedAjaxLoginTest extends AuthControllerNobodyLoggedTestCase {
	protected 
		$_json, 
		$_xpath;

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

		Class_AdminVar::getLoader()
			->newInstanceWithId('INTERDIRE_ENREG_UTIL')
			->setValeur(1);

		$this->dispatch('/opac/auth/popup-login', true);

		$this->_xpath = new Storm_Test_XPath();
		$this->_json = json_decode($this->_response->getBody());
	}


	public function testLinkLostPassword() {
		$this->_xpath->assertXPath($this->_json->content,
															 '//div//a[contains(@onclick, "getUsername")]');
	}

	
	public function testNoLinkSenregistrer() {
		$this->_xpath->assertNotXPath($this->_json->content,
																	'//div//a[contains(@href, "auth/register")]');
	}
}




class AuthControllerNobodyLoggedTest extends PortailWithOneLoginModuleTestCase {
	public function setUp() {
		parent::setUp();
		ZendAfi_Auth::getInstance()->clearIdentity();
		$this->dispatch('/opac');
	}

	/** 
	 * @group integration
	 * @test 
	 */
	public function pageShouldBeHtml5Valid() {
		$this->assertHTML5($this->_response->getBody());
	}


	/** @test */
	public function pageShouldNotContainsRedirectInput() {
		$this->assertNotXPath('//input[@name="redirect"]');
	}

	/** @test */
	public function withRedirectParamPageShouldContainsRedirectInput() {
		$this->bootstrap();
		$this->dispatch('/opac/auth/login/redirect/'.urlencode('/opac/paniers'));
		$this->assertXPath('//input[@name="redirect"][@value="/opac/paniers"]');
	}

	/** @test */
	public function pageShouldNotContainsAjoutPanierInput() {
		$this->assertNotXPath('//input[@name="ajoutPanier"]');
	}
}


class AuthControllerNumilogConnectedUserDeconnexionTest extends PortailWithOneLoginModuleTestCase {
	public function setUp() {
		parent::setUp();
		
		$this->dispatch('/opac/auth/login?service=http://numilog?deconnexion=ok', true);
	}


	/** 
	 * @test 
	 */
	public function pageShouldBeRedirectedToHome() {
		$this->assertRedirectTo('/opac');

	}
}



class AuthControllerNoLoggedTest extends AuthControllerNobodyLoggedTestCase {
	public function setUp() {
		parent::setUp();

	}
	/** @test */
	public function pageAuthLoginWithServiceShouldIncludeHiddenService() {
		$this->dispatch('/opac/auth/login?service=http://monurlservice',true);
		$this->assertXPath('//input[@type="hidden"][@value="http://monurlservice"]',$this->_response->getBody());
	}
}


class AuthControllerAdminIsLoggedTest extends PortailWithOneLoginModuleTestCase {
	public function setUp() {
		parent::setUp();
		$this->sysadm = $this->fixture('Class_Users',
																	 ['id' => 1,
																		'pseudo' => 'sysadm',
																		'role_level' => ZendAfi_Acl_AdminControllerRoles::ADMIN_PORTAIL,
																		'role' => 'super_admin',
																		'login' => 'sysadm',
																		'password' => 'sysadmPassword',
																		'id_site' => 1]);
		ZendAfi_Auth::getInstance()->logUser($this->sysadm);
		$this->dispatch('/opac/auth/login',true);
	}


	public function testBoiteLoginDisplaysBienvenueSysadm() {
		$this->assertQueryContentContains('#boite_login .welcome', 'Bienvenue sysadm',$this->_response->getBody());
	}


	/** @test */
	public function shouldNotDisplayExpiredSubscription() {
		$this->assertNotXPath('//div[@class="boite login"]//p');
	}

	
	public function testLinkSeDeconnecter() {
		$this->assertXPath('//div[@id="boite_login"]//a[contains(@href, "auth/logout")]',
											 $this->_response->getBody());
		$this->assertXPathContentContains('//div[@id="boite_login"]//a[contains(@href, "auth/logout")]',
																			'Se déconnecter',$this->_response->getBody());
	}


	public function testLinkFonctionAdmin() {
		$this->assertXPath("//div[@class='configuration_module']//img[contains(@onclick,'admin/modules/auth?config=site&type_module=auth&id_profil=2&action1=login')]");
	}


	/** @test **/
	public function lienMonCompteShouldContainsClassAccount() {
		$this->assertXPath('//div[@class="form"]/a[@class="account-link"]');
	}


	/** @test **/
	public function lienSeDeconnecerShouldContainsClassAccountDisconnect() {
		$this->assertXPath('//div[@class="form"]/a[@class="account-disconnect"]',$this->_response->getBody());
	}

}




class AuthControllerPostTest extends AuthControllerNobodyLoggedTestCase {
	protected $_referer;
	
	public function setup() {
		parent::setup();
		$this->_referer= BASE_URL.'/cms/viewarticle/12';
	  $_SERVER['HTTP_REFERER'] = $this->_referer;
	}
	
	public function loggingWithOutFillingUsername() {
		$this->postDispatch('/opac/auth/boite-login?id_module=4',
												array('username' => 'My overkill username',
															'password' => ''),true);
	}


	public function loggingWithOutFillingPassword() {
		$this->postDispatch('/opac/auth/boite-login?id_module=4',
												array('username' => 'My overkill username',
															'password' => ''),true);
	}


	public function loggingWithWrongInformation() {
		$this->postDispatch('/opac/auth/boite-login?id_module=4',
												['username' => 'foo', 'password' => 'bar'],true);
	}


	public function loggingWithCorrectInformation() {
		$user = Class_Users::getLoader()->findFirstBy(array());
		$this->postDispatch('/opac/auth/boite-login?id_module=4',
												array('username' => $user->getLogin(),
															'password' => $user->getPassword()));
	}


	public function ajaxLoginWithWrongInformation() {
		$this->postDispatch('/opac/auth/ajax-login?id_module=4',
												['username' => 'foo', 
												 'password' => 'zoork',
												 'redirect' => '/auth/panier'],true);
	}


	public function loggedAsAdmin() {
		$admin = Class_Users::newInstanceWithId(34, ['login' => 'admin'])->beAdminPortail();
		ZendAfi_Auth::getInstance()->logUser($admin);
		$this->dispatch('/opac/auth/boite-login?id_module=4',true);
	}


	public function ajaxLoggingWithCorrectInformation() {
		$user = Class_Users::getLoader()->findFirstBy(array());

		$this->postDispatch('/opac/auth/ajax-login?id_module=4',
												array('username' => $user->getLogin(),
															'password' => $user->getPassword()));
	}

	
	/** @test */
	public function emptyUsernameShouldRedirectToReferer() {
	  $this->loggingWithOutFillingUsername();
		$this->assertRedirectTo($this->_referer);
	}

	/* @test */
	public function emptyUsernamePostActionShouldDisplayFlashMessengerWithMessageEntrezVotreIdentifiant() {
		$this->loggingWithOutFillingUsername();
		$this->assertFlashMessengerContentContains('Entrez votre identifiant');
	}

	/** @test */
	public function emptyPasswordPostActionShouldDisplayFlashMessengerWithMessageEntrezVotreMotDePasse() {
		$this->loggingWithOutFillingPassword();
		$this->assertFlashMessengerContentContains('Entrez votre mot de passe');
	}


	/** @test */
	public function withAuthenticationFailureFlashMessengerShouldDisplayMessageIdentifiantOuMotDePasseIncorrect(){
		$this->loggingWithWrongInformation();
		$this->assertFlashMessengerContentContains('Identifiant ou mot de passe incorrect');
	}

	/** @test */
	public function validAuthenticationShouldRedirectToRefererrer()	{
		$this->loggingWithCorrectInformation();
		$this->assertRedirectTo($this->_referer);
	}


	/** @test */
	public function validAjaxAuthenticationShouldRedirectToReferrer()	{
		$this->ajaxLoggingWithCorrectInformation();
		$this->assertRedirectTo($this->_referer);
	}


	/** @test */
	public function invalidAjaxAuthenticationShouldRedirectToActionReferrerWithPopupInFlash()	{
		$this->ajaxLoginWithWrongInformation();
		$this->assertRedirectTo($this->_referer);
		$this->assertFlashMessengerEquals(['Identifiant ou mot de passe incorrect.',
																			 [ZendAfi_Controller_Action_Helper_FlashMessenger::POPUP => ['url' => '/auth/popup-login?redirect='.urlencode('/auth/panier')]]]);
		
	}


	/** @test */
	public function validAuthenticationTitreBoiteShouldBeVousEtesConnecte () {
		$this->loggedAsAdmin();
		$this->assertXPathContentContains('//div[@class="boite login"]//h1','Vous êtes connecté(e)',$this->_response->getBody());
	}
}




abstract class AuthControllerPostSimpleTestCase extends AuthControllerNobodyLoggedTestCase {
	protected $_auth;

	public function setUp() {
		parent::setUp();
		$this->_auth = Storm_Test_ObjectWrapper::mock()
			->whenCalled('authenticateLoginPassword')
			->answers(false)
			->whenCalled('hasIdentity')
			->answers(false)
			->whenCalled('getIdentity')
			->answers(null);
		
		ZendAfi_Auth::setInstance($this->_auth);
	}


	public function tearDown() {
		ZendAfi_Auth::setInstance(null);
		parent::tearDown();
	}
}




abstract class AuthControllerPostSimpleSuccessfulTestCase extends AuthControllerPostSimpleTestCase {
	protected $_web_analytics_client;

	public function setUp() {
		parent::setUp();
		$this->group_musicme = $this->fixture('Class_UserGroup',
																					['id' => 20, 
																					 'libelle' => 'Multimedia'])
			->addRight(Class_UserGroup::RIGHT_ACCES_MUSICME);

		$marcel = Class_Users::newInstanceWithId(2, ['nom' => 'Marcel','login' =>'foo'])
			->beAbonneSIGB()
			->setUserGroups([$this->group_musicme]);

		$this->_auth
			->whenCalled('authenticateLoginPassword')
			->with('foo', 'bar')
			->willDo( 
				function() use($marcel)  {
					$this->_auth->whenCalled('getIdentity')->answers($marcel);
					return true;
				});


		$this->_web_analytics_client = Storm_Test_ObjectWrapper::mock()
			->whenCalled('trackEvent')
			->answers(true);
		ZendAfi_Controller_Action_Helper_TrackEvent::setDefaultWebAnalyticsClient($this->_web_analytics_client);
	}
}




class AuthControllerPostSimpleSuccessfulTest extends AuthControllerPostSimpleSuccessfulTestCase {
	public function setUp() {
		parent::setUp();

		$this->postDispatch('/opac/auth/login',
												['username' => 'foo', 'password' => 'bar'],true);
	}


	/** @test */
	public function responseShouldBeARedirectToOPAC() {
		$this->assertRedirectTo('/opac');
	}


	/** @test */
	public function trackEventShouldBeGenerated() {
		$this->assertTrue($this->_web_analytics_client->methodHasBeenCalledWithParams('trackEvent', 
																																									['authentification',
																																									 'connexion',
																																									 'utilisateur',
																																									 2]));
	}
}




class AuthControllerPostSimpleSuccessfulWithRedirectTest extends AuthControllerPostSimpleSuccessfulTestCase {
	public function setUp() {
		parent::setUp();

		$this->postDispatch('/opac/auth/login',
												['username' => 'foo', 
												 'password' => 'bar',
												 'redirect' => '/opac/paniers']);
	}


	/** @test */
	public function responseShouldRedirectToOpacPaniers() {
		$this->assertRedirectTo('/opac/paniers');
	}
}




class AuthControllerPostSuccessfulFromCASClientTest extends AuthControllerPostSimpleSuccessfulTestCase {
	public function setUp() {
		parent::setUp();

		$this->postDispatch('/opac/auth/login',
												['username' => 'foo', 
												 'password' => 'bar',
												 'service' => 'http://www.numilog.com/view?book=bilbo']);
	}	


	/** @test */
	public function responseShouldRedirectToCasClientWithTicket() {
		$this->assertRedirectTo('http://www.numilog.com/view?book=bilbo&ticket=ST-'.md5(Zend_Session::getId().'2'));
	}

	/** @test */
	public function userFooShouldBeLogged() {
		$this->assertEquals('foo', Class_Users::getIdentity()->getLogin());
	}
}



class AuthControllerPostSuccessfulFromMusicMeCASClientTest extends AuthControllerPostSimpleSuccessfulTestCase {
	public function setUp() {
		parent::setUp();
		RessourcesNumeriquesFixtures::activateMusicMe();
		$this->postDispatch('/opac/auth/login',
												['username' => 'foo', 
												 'password' => 'bar',
												 'service' => 'http://musicme.com']);
	}	


	/** @test */
	public function responseShouldRedirectToMusicMeCasClientWithTicketAndBibId() {
		$ticket='ST-'.md5(Zend_Session::getId(). '2');
		$this->assertRedirectTo('http://musicmeurl/?iduser=foo&ticket='.$ticket.'&MediaLibraryID=888&service=http%3A%2F%2Fmusicmeurl%2F%3Fiduser%3Dfoo%26ticket%3D'.$ticket.'%26MediaLibraryID%3D888');
	}

	/** @test */
	public function userFooMusicMeShouldBeLogged() {
		$this->assertEquals('foo', Class_Users::getIdentity()->getLogin());
	}
}




class AuthControllerFromCASClientUserConnectedTest extends AuthControllerNobodyLoggedTestCase {
	public function setUp() {
		parent::setUp();
		ZendAfi_Auth::getInstance()->logUser(Class_Users::newInstanceWithId('22',['login'=> 'john']));
		$this->dispatch('/auth/login?service=http://numilog.com/actionredirected');
	}	


	/** @test */
	public function responseShouldRedirectToCasClientServiceWithTicket() {
		$this->assertRedirectTo('http://numilog.com/actionredirected?ticket=ST-'.md5(Zend_Session::getId().'22'));
	}

	/** @test */
	public function userJohnShouldBeLogged() {
		$this->assertEquals('john', Class_Users::getIdentity()->getLogin());
	}
}






class AuthControllerPostSimpleFailureTest extends AuthControllerPostSimpleTestCase {
	
	public function setup() {
		parent::setup();
		$_SERVER['HTTP_REFERER'] = '/opac';
		
	}

	/** @test */
	public function withAuthenticationFailureResponseShouldBeRedirect() {
		$this->postDispatch('/opac/auth/login',
												['username' => 'foo', 'password' => 'bar']);
		$this->assertRedirectTo('/opac');
	}
	
  
}


class AuthControllerLoginActionRenderTest extends AuthControllerNobodyLoggedTestCase {
	public function setUp() {
		parent::setUp();
		$this->dispatch('/opac/auth/login',true);
	}

  /**	@test */
	public function authLoginShouldContainForm() {
		$this->assertXPath('//form//fieldset[contains(@id, "fieldset-login_form")]');
	}
}


class AuthControllerLoginActionWithDefaultPreferencesRenderTest extends AuthControllerNobodyLoggedTestCase {
	public function setUp() {
		parent::setUp();
		$cfg_accueil = array('modules' => array(4 => array('division' => '4',
																											 'id_module' => 4,
																											 'type_module' => 'LOGIN',
																											 'preferences' => array())));
		Class_Profil::getCurrentProfil()
			->setBrowser('opac')
			->setCfgAccueil(ZendAfi_Filters_Serialize::serialize($cfg_accueil));
		$this->dispatch('/opac/auth/login',true);
	}

  /**	@test */
	public function labelUserNameShouldContainIdentifiant() {
		$this->assertXPathContentContains('//label','Identifiant');
	}

	/** @test */
	public function inputPlaceholderUsernameShouldContainVotreIdentifiant() {
		$this->assertXPath('//input[contains(@placeholder, "")]');
	}

	/**	@test */
	public function labelPasswordShouldContainMotDePasse() {
		$this->assertXPathContentContains('//label','Mot de passe');
	}

	/** @test */
	public function inputPlaceholderPasswordShouldContainVotreMotDePasse() {
		$this->assertXPath('//input[contains(@placeholder, "")]');
	}

	/**	@test */
	public function linkConnectionShouldHaveOnclickAttributeWithSubmit() {
		$this->assertXPath('//a[contains(@onclick, "submit")]');
	}
}




class AuthControllerLostPasswordTest extends AuthControllerNobodyLoggedTestCase {
	public function setUp() {
		parent::setUp();
		$this->dispatch('/opac/auth/lostpass', true);
	}


	/** @test */
	public function formActionShouldBeLostPass() {
		$this->assertXPath('//form[@name="form_lostpass"][contains(@action, "/auth/lostpass")]');
	}


	/** @test */
	public function formShouldContainsInputForUsername() {
		$this->assertXPath('//form/input[@type="text"][@name="username"]');
	}


	/** @test */
	public function pageShouldBeHTML5Valid() {
		$this->assertHTML5();
	}
}




class AuthControllerNobodyLoggedAndRegistrationAllowedRegisterTest extends AuthControllerNobodyLoggedTestCase {
	public function setUp() {
		parent::setUp();
		Class_AdminVar::newInstanceWithId('INTERDIRE_ENREG_UTIL', ['valeur' => 0]);
		$this->dispatch('auth/register', true);
	}


	/** @test */
	public function H1ShouldContainsDemandDInscription() {
		$this->assertXPathContentContains('//h1', 'Demande d\'inscription');
	}


	/** @test */
	public function ParagraphRegisterHelpShouldContainsMailDeConfirmation() {
		$this->assertXPathContentContains('//p', 'mail de confirmation');
	}


	/** @test */
	public function inputMailShouldBePresent() {
		$this->assertXPath('//input[@name="mail"][@type="email"]');
	}

	
	/** @test */
	public function inputConfirmMailShouldBePresent() {
		$this->assertXPath('//input[@name="mail2"][@type="email"]');
	}


	/** @test */
	public function inputLoginShouldBePresent() {
		$this->assertXPath('//input[@name="login"]');
	}


	/** @test */
	public function inputMdpShouldBePresent() {
		$this->assertXPath('//input[@name="mdp"]');
	}


	/** @test */
	public function inputMdp2ShouldBePresent() {
		$this->assertXPath('//input[@name="mdp2"]');
	}


	/** @test */
	public function inputCaptchaShouldBePresent() {
		$this->assertXPath('//input[@name="captcha[input]"]');
	}
}




class AuthControllerNobodyLoggedRegisterPostRightDatasTest extends AuthControllerNobodyLoggedTestCase {
	public function setUp() {
		parent::setUp();
		Class_Users::beVolatile();
		Class_UsersNonValid::beVolatile();
		ZendAfi_Form_Element_Captcha::beValid();

		$this->mock_transport = new MockMailTransport();
		Zend_Mail::setDefaultTransport($this->mock_transport);

		Class_Profil::getCurrentProfil()
			->setMailSite('chef@afi.fr')
			->setModulePreference('auth',
														'register',
														'register_confirm',
														'Coucou, merci pour ton inscription');

		Class_AdminVar::newInstanceWithId('REGISTER_OK', ['valeur' => '']);


		Class_AdminVar::newInstanceWithId('INTERDIRE_ENREG_UTIL', ['valeur' => 0]);

		$this->postDispatch('auth/register', 
												['login' => 'mario',
												 'mail' => 'mario@afi-sa.fr',
												 'mail2' => 'mario@afi-sa.fr',
												 'mdp' => 'secret',
												 'mdp2' => 'secret',
												 'captcha[id]' => '1234',
												 'captcha[input]' => '1234']);
	}


	protected function getSentMail() {
		return $this->mock_transport->sent_mail;
	}


	protected function getSentMailRecipients() {
		return $this->getSentMail()->getRecipients();
	}


	protected function getSentMailFrom() {
		return $this->getSentMail()->getFrom();
	}


	protected function getSentMailContent() {
		return quoted_printable_decode($this->getSentMail()->getBodyText()->getContent());
	}


	/** @test */
	public function recipientShouldBeMario() {
		$this->assertContains('mario@afi-sa.fr', $this->getSentMailRecipients());
	}

	/** @test */
	public function recipientsShouldContainsChefAtAfiDotFr() {
		$this->assertContains('chef@afi.fr', $this->getSentMailRecipients());
	}


	/** @test */
	public function contentShouldBeAsExpected() {
		$this->assertContains('Vous avez fait une demande d\'inscription', $this->getSentMailContent());
	}


	/** @test */
	public function confirmationShouldBeAsExpected() {
		$this->assertXPathContentContains('//div',
																			'Coucou, merci pour ton inscription');
	}


	/** @test */
	public function withoutProfilMailSenderShouldBeAdmin() {
		$this->assertContains('chef@afi.fr', $this->getSentMailFrom());
	}


	/** @test */
	public function newUsersNonValidShouldBeCreated() {
		$user = Class_UsersNonValid::findFirstBy(['login' => 'mario']);
		$this->assertEquals(['id' => 1,
												 'id_user' => 1,
												 'login' => 'mario',
												 'password' => 'secret',
												 'mail' => 'mario@afi-sa.fr',
												 'cle' => md5('mario@afi-sa.fr')],
												$user->getRawAttributes());
	}
}




class AuthControllerNobodyLoggedRegisterPostWrongDataTest extends AuthControllerNobodyLoggedTestCase {
	public function setUp() {
		parent::setUp();
		$this->fixture('Class_Users',
									 ['id' => 2,
										'login' => 'alexa',
										'password' => 'secret',
										'mail' => 'alex.arnaud@biblibre.com']);
		$this->fixture('Class_UsersNonValid',
									 ['id' => 3,
										'login' => 'laurent',
										'password' => 'secret_aussi',
										'mail' => 'lolo@biblibre.com']);

		Class_AdminVar::newInstanceWithId('INTERDIRE_ENREG_UTIL', ['valeur' => 0]);
	}

	public function fields() {
		return [
			['login',],
			['mail'],
			['mail2'],
			['mdp'],
			['mdp2'],
			];
	}
	

	/** 
	 * @dataProvider fields
	 * @test 
	 */
	public function errorForEmptyFieldShouldBeVisible($field) {
		$this->postDispatch('auth/register', 
												['login' => '',
												 'mail' => '',
												 'mail2' => '',
												 'mdp' => '',
												 'mdp2' => '',
												 'captcha[id]' => '93248',
												 'captcha[input]' => '']);

		$this->assertXPathContentContains('//ul[@class="errors"][preceding-sibling::input[@name="'.$field.'"]]//li', 
																			'Une valeur est requise',
																			$this->_response->getBody());
	}


	/** @test */
	public function withMailsNotWellFormedShouldDisplayErrorInvalidMail() {
		$this->postDispatch('auth/register', 
												['mail' => 'blib',
												 'mail2' => 'blib']);
		$this->assertXPathContentContains('//ul[@class="errors"][preceding-sibling::input[@name="mail"]]//li', 
																			"'blib' n'est pas un email valide de la forme 'compte@hote.ext'");
												 
	}


	/** @test */
	public function withDifferentMailsShouldDisplayErrorMailAreNotTheSame() {
		$this->postDispatch('auth/register', 
												['mail' => 'grand-schtroumpf@champi.gnon',
												 'mail2' => 'schtroumpfette@champi.gnon']);
		$this->assertXPathContentContains('//ul[@class="errors"][preceding-sibling::input[@name="mail2"]]//li', 
																			"Les champs 'E-mail' sont différents");
	}


	/** @test */
	public function withDifferentPasswordsShouldDisplayErrorPasswordsAreNotTheSame() {
		$this->postDispatch('auth/register', 
												['mdp' => 'secret',
												 'mdp2' => 'sicrette']);
		$this->assertXPathContentContains('//ul[@class="errors"][preceding-sibling::input[@name="mdp2"]]//li', 
																			"Les champs 'Mot de passe' sont différents");
	}


	/** @test */
	public function existingMailsShouldDisplayErrorMailAlreadyExists() {
		$this->postDispatch('auth/register', 
												['mail' => 'alex.arnaud@biblibre.com',
												 'mail2' => 'alex.arnaud@biblibre.com']);
		$this->assertXPathContentContains('//ul[@class="errors"][preceding-sibling::input[@name="mail"]]//li', 
																			"L'e-mail 'alex.arnaud@biblibre.com' existe déjà.");
	}


	/** @test */
	public function existingMailInUsersNonValidShouldDisplayErrorMailAlreadyExists() {
		$this->postDispatch('auth/register', 
												['mail' => 'lolo@biblibre.com',
												 'mail2' => 'lolo@biblibre.com']);
		$this->assertXPathContentContains('//ul[@class="errors"][preceding-sibling::input[@name="mail"]]//li', 
																			"L'e-mail 'lolo@biblibre.com' existe déjà.");
	}


	/** @test */
	public function existingLoginShouldDisplayErrorLoginAlreadyExists() {
		$this->postDispatch('auth/register', 
												['login' => 'alexa']);
		$this->assertXPathContentContains('//ul[@class="errors"][preceding-sibling::input[@name="login"]]//li', 
																			"L'identifiant 'alexa' existe déjà.");
	}


	/** @test */
	public function existingLoginInUsersNonValidShouldDisplayErrorLoginAlreadyExists() {
		$this->postDispatch('auth/register', 
												['login' => 'laurent']);
		$this->assertXPathContentContains('//ul[@class="errors"][preceding-sibling::input[@name="login"]]//li', 
																			"L'identifiant 'laurent' existe déjà.");
	}
}




class PortailWithOneLoginModuleTestAndLoggedUserCase extends AbstractControllerTestCase {
	public function setUp() {
		parent::setUp();

		Class_IntBib::beVolatile();

		$cfg_accueil = ['modules' => [4 => ['division' => '4',
																				'id_module' => 4,
																				'type_module' => 'LOGIN',
																				'preferences' => [
																					'identifiant' => 'Numéro de carte',
																					'mot_de_passe'=> 'Année de naissance',
																					'identifiant_exemple' => 'jj-mm-aaaa',
																					'mot_de_passe_exemple' => '1983',
																					'titre_connecte' => 'Vous êtes connecté(e)',
																					'lien_connexion' => 'please, log me',
																					'lien_mot_de_passe_oublie' => 'me rappelle plus',
																					'profil_redirect' => 0]]],
										'options' => []];

		Class_Profil::getCurrentProfil()
			->setBrowser('opac')
			->setCfgAccueil(ZendAfi_Filters_Serialize::serialize($cfg_accueil));


		ZendAfi_Auth::getInstance()->logUser(
			$this->fixture('Class_Users',
										 ['id' => 5,
											'login' => 'Pioup',
											'idabon' => 48,
											'password' => 'one ok password',
											'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB,
											'id_site' => 1,
											'fiche_sigb' => []]));

		$this->dispatch('/opac/');
	}

	
	/** @test */
	public function redirectProfilForLoginShouldBeProfil2(){
		$this->assertXPath('//a[contains(@href,"abonne/fiche/id_profil/2")]',$this->_response->getBody());
	}


	/** @test */
	public function redirectProfilForLoginShouldNotBeProfil0(){
		$this->assertNotXPath('//a[contains(@href,"abonne/fiche/id_profil/0")]',$this->_response->getBody());
	}


	/** @test */
	public function redirectProfilForLogoutShouldBeProfilParent(){
		$this->bootstrap();
		$this->dispatch('opac/auth/logout');
		$this->assertRedirectTo('/');
	}


	/** @test */
	public function redirectProfilForLogoutShouldNotBeProfil0(){
		$this->assertNotXPath('//a[contains(@href,"auth/logout/id_profil/")]',$this->_response->getBody());
	}

}



	class AuthControllerAbonneSIGBNotValidLoggedTest extends PortailWithOneLoginModuleTestCase {
		public function setUp() {
			parent::setUp();

			ZendAfi_Auth::getInstance()->logUser(
				Class_Users::newInstanceWithId(5,
																			 ['login' => 'tomato',
																				'idabon' => 48,
																				'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB,
																				'id_site' => 1,
																				'date_fin' => '2014-01-01',
																				'fiche_sigb' => []]));

			$this->dispatch('/opac/');
		}


		/** @test */
		public function shouldDisplayExpiredSubscription() {
			$this->assertXPathContentContains('//div[@class="boite login"]//p[@class="expired"]', 'Abonnement expiré - Merci de contacter la médiathèque');
		}
	}

?>