<?php
/**
 * Copyright (c) 2012, Agence Française Informatique (AFI). All rights reserved.
 *
 * BOKEH 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).
 *
 * BOKEH 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 BOKEH; 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")]');
  }


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

}



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


  /** @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")]');
  }


  /** @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")]');
  }


  /** @test */
  public function formActionShouldBeLogin() {
    $this->assertXPath('//form[@action="/auth/login"]');
  }
}




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 formActionShouldBeBoiteLogin() {
    $this->assertXPath('//div[@id="boite_login"]//form[@action="/auth/boite-login/id_module/4"]');
  }

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



class AuthControllerUserIsLoggedTest extends PortailWithOneLoginModuleTestCase {
  public function setUp() {
    parent::setUp();
    $marcus = $this->fixture('Class_Users', [
                                             'id' => 1,
                                             'pseudo' => '',
                                             'login' => 'sysadm',
                                             'password' => 'sysadmPassword',
                                             'nom' => 'Miller',
                                             'prenom' => 'Marcus']);
    ZendAfi_Auth::getInstance()->logUser($marcus);
    $this->dispatch('/opac/auth/login',true);
  }


  /** @test */
  public function bienvenueMarcusMillerShouldBePresent() {
    $this->assertXPath('//div//div[@class="welcome"][contains(text(),"Bienvenue Marcus")]//span[@data-name="last-name"][contains(text(), "Miller")]');
  }
}

class AuthControllerUserNameIsEscaped extends PortailWithOneLoginModuleTestCase {
  public function setUp() {
    parent::setUp();
    $marcus = $this->fixture('Class_Users',
                             ['id' => 1,
                              'pseudo' => '',
                              'login' => 'sysadm',
                              'password' => 'sysadmPassword',
                              'nom' => '<script>Miller',
                              'prenom' => '<script>Marcus']);
    ZendAfi_Auth::getInstance()->logUser($marcus);
    $this->dispatch('/opac/auth/login',true);
  }

  /** @test */
  public function userNameShouldBeEscaped() {
    $this->assertXPathContentContains("//div[@class='welcome']", "Bienvenue &lt;script&gt;Marcus");
  }

  /** @test */
  public function userSurNameShouldBeEscaped() {
    $this->assertXPathContentContains("//span[@data-name='last-name']", "&lt;script&gt;Miller");
  }


}

class AuthControllerPseudoIsEscaped extends PortailWithOneLoginModuleTestCase {
  public function setUp() {
    parent::setUp();
    $marcus = $this->fixture('Class_Users',
                             ['id' => 1,
                              'pseudo' => '<script>pseudo',
                              'login' => 'sysadm',
                              'password' => 'sysadmPassword',
                              'nom' => 'Miller',
                              'prenom' => 'Marcus']);
    ZendAfi_Auth::getInstance()->logUser($marcus);
    $this->dispatch('/opac/auth/login',true);
  }

  /** @test */
  public function userPseudoShouldBeEscaped() {
    $this->assertXPathContentContains("//div[@class='welcome']", "Bienvenue &lt;script&gt;pseudo");
  }
}

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


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


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


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

}




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


  /** @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 invalidAjaxAuthenticationShouldRedirectToActionReferrerWithPopupInFlash() {
    $this->ajaxLoginWithWrongInformation();
    $this->assertRedirectTo($this->_referer);
    $this->assertFlashMessengerEquals([[ZendAfi_Controller_Action_Helper_FlashMessenger::NOTIFICATION => ['message' => '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)');
  }
}




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,
    $_marcel;

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

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

    Class_Users::cacheInstance($this->_marcel);

    $this->_marcel
      ->whenCalled('registerNotificationsOn')
      ->willDo(function($notifiable) {
        $notifiable->notify('Message de notification');
      });


    $this->_auth
      ->whenCalled('authenticateLoginPassword')
      ->with('foo', 'bar')
      ->willDo(
               function() {
                 $user = new stdClass();
                 $user->ID_USER = $this->_marcel->getId();
                 $this->_auth->whenCalled('getIdentity')->answers($user);
                 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]));
  }

  /** @test */
  public function flasMessengerShouldContainMessageDeNotification() {
    $this->assertFlashMessengerContains([ZendAfi_Controller_Action_Helper_FlashMessenger::NOTIFICATION => ['message' => 'Message de notification',
                                                                                                           'display' => 'popup']]);
  }
}



class AuthControllerAjaxLoginPostTest extends AuthControllerPostSimpleSuccessfulTestCase {
  public function setUp() {
    parent::setUp();
    $_SERVER['HTTP_REFERER'] = '/recherche/viewnotice';
    $this->postDispatch('/opac/auth/ajax-login',
                        ['username' => 'foo', 'password' => 'bar'], true);
  }


  /** @test */
  public function flashMessengerShouldContainMessageDeNotification() {
    $this->assertFlashMessengerContains(
          [ZendAfi_Controller_Action_Helper_FlashMessenger::NOTIFICATION => ['message' => 'Message de notification']]);
  }


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



class AuthControllerBoiteLoginPostTest extends AuthControllerPostSimpleSuccessfulTestCase {
  public function setUp() {
    parent::setUp();
    $_SERVER['HTTP_REFERER'] = '/recherche/viewnotice';
    $this->postDispatch('/opac/auth/boite-login',
                        ['username' => 'foo', 'password' => 'bar'],true);
  }


  /** @test */
  public function flashMessengerShouldContainMessageDeNotification() {
    $this->assertFlashMessengerContains(
                                        [ZendAfi_Controller_Action_Helper_FlashMessenger::NOTIFICATION => ['message' => 'Message de notification',
                                                                                                           'display' => ZendAfi_Controller_Action_Helper_FlashMessenger::POPUP]]);
  }

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



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

abstract class AuthControllerLecturaTestCase extends AuthControllerPostSimpleTestCase {
  protected $server_host;
  public function setUp() {
    parent::setUp();
    $this->server_host = $_SERVER['HTTP_HOST'];
    $_SERVER['HTTPS']='on';
    $_SERVER['HTTP_HOST'] = 'test.webuser.lectura.fr';

    $this->fixture('Class_AdminVar', ['id' => 'LECTURA_DOMAIN',
                                      'valeur' => 'test.webuser.lectura.fr']);
    Class_Users::beVolatile();

  }


  public function tearDown() {
    unset($_SERVER['HTTPS']);
    $_SERVER['HTTP_HOST'] = $this->server_host;
    parent::tearDown();
  }


}


class AuthControllerPostWrongUserFromLecturaClientTest extends AuthControllerLecturaTestCase {
  public function setUp() {
    parent::setUp();
    $this->postDispatch('/',
                        ['CAB' => '0007',
                         'PWD' => 'toto' ]);

  }
  /** @test */
  public function responseShouldContainsError() {
    $this->assertContains('error', $this->_response->getBody());
  }

}


class AuthControllerPostSuccessfulFromLecturaClientTest extends AuthControllerLecturaTestCase {
  public function setUp() {
    parent::setUp();

    $this->fixture('Class_Users', ['id' => 5 ,
                                   'login' => '0007',
                                   'idabon' => '0007',
                                   'password' => 'toto']);

    $this->_auth->whenCalled('authenticateLoginPassword')
                ->with('0007', 'toto')
                ->answers(true);
    $this->postDispatch('/',
                        ['CAB' => '0007',
                         'PWD' => 'toto' ]);

  }

  /** @test */
  public function controllerShouldBeAuth() {
    $this->assertEquals('auth',$this->_request->getControllerName());
  }

  /** @test */
  public function actionShouldBeLogin() {
    $this->assertEquals('login',$this->_request->getActionName());
  }

  /** @test */
  public function responseShouldContainsSuccess() {
    $this->assertContains('success', $this->_response->getBody());
  }

}



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


  /** @test */
  public function authLoginTableShouldContainCaption() {
    $this->assertXPath('//form//table/caption/details/summary');
  }
}


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 AuthControllerLostPasswordUnknownPostTest extends AbstractControllerTestCase{

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

  }

  /** @test */
  public function withUnknowUserShouldDisplayError() {
    $this->postDispatch('/opac/auth/lostpass',['username' => 'unknown']);
    $this->assertXPathContentContains('//div', 'Identifiant inconnu',$this->_response->getBody());
  }


/** @test */
  public function withEmptyUserShouldDisplayError() {
    $this->postDispatch('/opac/auth/lostpass',['username' => '']);
    $this->assertXPathContentContains('//div', 'Veuillez saisir votre identifiant.',$this->_response->getBody());
  }

}

class AuthControllerLostPasswordNoMailPostTest extends AbstractControllerTestCase{

  public function setUp() {
    parent::setUp();
    $user = $this->fixture('Class_Users',
                             ['id' => 1,
                              'pseudo' => 'luddite',
                              'login' => 'luddite',
                              'password' => 'notech',
                              'nom' => 'Lu',
                              'prenom' => 'Dites']);

    $this->postDispatch('/opac/auth/lostpass' , ['username' => 'luddite']);
  }

/** @test */
  public function withoutEmailShouldReturnErrorMessage() {
    $this->assertXPathContentContains('//div', "Votre mail n'est pas renseigné dans votre compte lecteur. Merci de vous adresser à la bibliothèque pour récupérer votre mot de passe ou bien le remplacer par un nouveau.");
  }

}


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


  /** @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")]');
  }


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


  /** @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/")]');
  }

}



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="user_notifications"]', 'Abonnement expiré - Merci de contacter la médiathèque');
  }
}



class AuthControllerNobodyLoggedAndRegisterNewsletterWithNoNewsletterTest extends AuthControllerNobodyLoggedTestCase {

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

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


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



class AuthControllerNobodyLoggedAndRegisterNewsletterWithWrongNewsletterTest extends AuthControllerNobodyLoggedTestCase {

  public function setUp() {
    parent::setUp();
    Class_Newsletter::beVolatile();
    $this->dispatch('/opac/auth/newsletter-register/id/1', true);
  }


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




class AuthControllerNewsletterRegisterKickSpamBotsTest extends AuthControllerNobodyLoggedTestCase {

  public function setUp() {
    parent::setUp();
    $this->fixture('Class_Newsletter',
                   ['id' => 5,
                    'titre' => 'Daily News']);

    $this->postDispatch('/opac/auth/newsletter-register/id/5', [
                                                                'email' => 'imnotabot@factory.bot',
                                                                'emailCheck' => 'imnotabot@factory.bot']);
  }


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




class AuthControllerNobodyLoggedAndRegisterNewsletterTest extends AuthControllerNobodyLoggedTestCase {

  public function setUp() {
    parent::setUp();
    $this->fixture('Class_Newsletter',
                   ['id' => 5,
                    'titre' => 'Daily News']);

    $this->dispatch('/opac/auth/newsletter-register/id/5', true);
  }


  /** @test */
  public function titleShouldBeAsExpected() {
    $this->assertXPathContentContains('//div[@class="titre"]//h1', 'Inscription à la lettre d\'information: Daily News');
  }


  /** @test */
  public function registerFormShouldBePresent() {
    $this->assertXPath('//form[@id="newsletter_register"]');
  }


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


  /** @test */
  public function negativeCaptchaShouldBePresent() {
    $this->assertXPath('//form//input[@name="emailCheck"][@data-spambots="negative-captcha"]');
  }


  /** @test */
  public function submitButtonShouldBePresent() {
    $this->assertXPath('//form//input[@type="submit"][@value="Valider"]');
  }
}




class AuthControllerPostRegisterNewsletterDailyNewsTest extends AuthControllerNobodyLoggedTestCase {

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

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

    Class_Profil::getCurrentProfil()
      ->setMailSite('tom@afi.fr');

    Class_Users::beVolatile();
    Class_UsersNonValid::beVolatile();

    $this->fixture('Class_Newsletter', ['id' => 5, 'titre' => 'Daily News']);

    $this->postDispatch('/opac/auth/newsletter-register/id/5', ['email' => 'iwanttobespamed@abo.com',
                                                                'emailCheck' => '']);
  }


  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 nonValidUserShouldBeCreatedWithExpectedEmail() {
    $this->assertEquals('iwanttobespamed@abo.com', Class_UsersNonValid::find(1)->getMail());
  }


  /** @test */
  public function recipientShouldBeIwanttobespamed() {
    $this->assertContains('iwanttobespamed@abo.com', $this->getSentMailRecipients());
  }


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


  /** @test */
  public function validationUrlShouldBeAsExpected() {
    $this->assertContains('/auth/newsletter-active-user/c/d7660b4a8df1ccb01fd50ddc6e7d3426/id/5', $this->getSentMailContent(), $this->getSentMailContent());
  }


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


  /** @test */
  public function confirmationShouldBeAsExpected() {
    $this->assertXPathContentContains('//p',"Une demande de confirmation d'inscription vous a été envoyée à l'adresse mail renseignée.");
  }


  /** @test */
  public function mailShouldContainsAccountMessage() {
    $this->assertContains("Un compte vous a été créé automatiquement.", $this->getSentMailContent());
  }


  /** @test */
  public function mailShouldContainsAccountLogin() {
    $this->assertContains('Votre identifiant: iwanttobespamed@abo.com', $this->getSentMailContent());
  }


  /** @test */
  public function mailShouldContainsAccountPassword() {
    $this->assertContains('Votre mot de passe: ', $this->getSentMailContent());
  }


  /** @test */
  public function unssubscribUrlShouldBeAsExpected() {
    $this->assertContains('/auth/newsletter-unsubscribe/id/5', $this->getSentMailContent());
  }
}




class AuthControllerPostRegisterNewsletterDailyNewsWithNonUniqueMailTest extends AuthControllerNobodyLoggedTestCase {

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

    $this->fixture('Class_Users',
                   ['id' => 1,
                    'login' => 'Tom',
                    'password' => 'pwd',
                    'mail' => 'imalreadyused@mail.com']);

    Class_UsersNonValid::beVolatile();

    $this->fixture('Class_Newsletter',
                   ['id' => 5,
                    'titre' => 'Daily News']);

    $this->postDispatch('/opac/auth/newsletter-register/id/5', [
                                                                'email' => 'imalreadyused@mail.com',
                                                                'emailCheck' => '']);
  }


  /** @test */
  public function shouldReturnNonUniqueMailMessage() {
    $this->assertXPathContentContains('//span[@class="error"]',
                                      "Un utilisateur a déjà renseigné cet email. Merci de vous identifier avec le compte qui utilise cet email.");
  }


  /** @test */
  public function linkToLoginShouldBePresent() {
    $this->assertXPathContentContains('//a[contains(@href, "auth/ajax-login")]', 'J\'ai déjà un compte');
  }
}




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

    Class_Users::beVolatile();
    Class_UsersNonValid::beVolatile();
    $this->fixture('Class_Newsletter', ['id' => 5, 'titre' => 'Daily News']);

    $this->postDispatch('/opac/auth/newsletter-register/id/5', ['email' => 'bad_mail!',
                                                                'emailCheck' => '']);
  }

  /** @test */
  public function shouldDisplayValidationError() {
    $this->assertXPathContentContains('//ul[@class="errors"]/li', 'n\'est pas un email valide');
  }
}




class AuthControllerNewsletterActiveUserWithWrongParamsTest extends AuthControllerNoBodyLoggedTestCase {
  public function setUp() {
    parent::setUp();
  }


  /** @test */
  public function noParamsShouldRedirectToIndex() {
    $this->dispatch('opac/auth/newsletter-active-user', true);
    $this->assertRedirectTo('/');
  }


  /** @test */
  public function noKeySshouldRedirectToIndex() {
    $this->dispatch('opac/auth/newsletter-active-user/id/5', true);
    $this->assertRedirectTo('/');
  }


  /** @test */
  public function noNewsletterShouldRedirectToIndex() {
    $this->dispatch('opac/auth/newsletter-active-user/c/4897sd8fsdf', true);
    $this->assertRedirectTo('/');
  }


  /** @test */
  public function wrongNewsletterShouldRedirectedToIndex() {
    Class_Newsletter::beVolatile();
    $this->dispatch('opac/auth/newsletter-active-user/c/4897sd8fsdf/id/1', true);
    $this->assertRedirectTo('/');
  }


  /** @test */
  public function wrongKeyShouldDisplayExpectedMessage() {
    $this->fixture('Class_Newsletter',
                   ['id' => 1,
                    'titre' => 'News of the month']);

    $this->dispatch('opac/auth/newsletter-active-user/c/4897sd8fsdf/id/1', true);
    $this->assertXPathContentContains('//p', 'Inscription à la newsletter invalide.');
  }
}



class AuthControllerNewsletterActiveUserTest extends AuthControllerNoBodyLoggedTestCase {
  public function setUp() {
    parent::setUp();

    Class_NewsletterSubscription::beVolatile();

    Class_Users::beVolatile();

    $this->fixture('Class_Newsletter',[
                                       'id' => 1,
                                       'titre' => 'News of the month']);

    $this->fixture('Class_UsersNonValid', [
                                           'id' => 1,
                                           'login' => 'future@i.am',
                                           'mail' => 'future@i.am',
                                           'password' => 'random',
                                           'cle' => '12345678']);

    $this->fixture('Class_UsersNonValid', [
                                           'id' => 2,
                                           'login' => 'future@i.am',
                                           'mail' => 'future@i.am',
                                           'password' => 'random',
                                           'cle' => '12345678']);

    $this->dispatch('opac/auth/newsletter-active-user/c/12345678/id/1', true);
  }


  /** @test */
  public function userFutureShouldExist() {
    $this->assertEquals('future@i.am', Class_Users::findFirstBy(['login' => 'future@i.am'])->getMail());
  }


  /** @test */
  public function newsletterShouldHaveFutureAsSubscriber() {
    $this->assertEquals('future@i.am', Class_NewsletterSubscription::find(1)->getUser()->getMail());
  }


  /** @test */
  public function successMessageShouldBeAsExpected() {
    $this->assertXPathContentContains('//p', "Vous avez bien été abonné à la newsletter: News of the month avec l'adresse suivante: future@i.am");
  }


  /** @test */
  public function allNonValidUsersShouldBeDeleted() {
    $this->assertEmpty(Class_UsersNonValid::findAll());
  }
}



class AuthControllerTomLoggedRegisterNewsletterTestCase extends AbstractControllerTestCase {
  public function setUp() {
    parent::setUp();
    Class_NewsletterSubscription::beVolatile();
    $this->fixture('Class_Newsletter',
                   ['id' => 5,
                    'titre' => 'Daily News']);

    ZendAfi_Auth::getInstance()
      ->logUser($this->fixture('Class_Users',
                               ['id' => 156,
                                'login' => 'tomato',
                                'password' => 'pwd']));
    $this->dispatch('auth/newsletter-register/id/5', true);
  }


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


  /** @test */
  public function flashMessengerShouldBeReadyWithExpectedMessage() {
    $this->assertFlashMessengerContentContains('Vous êtes inscrit à la liste de diffusion: Daily News');
  }


  /** @test */
  public function tomatoShouldBeInDailyNewsSubscribers() {
    $this->assertEquals('tomato' , Class_NewsletterSubscription::find(1)->getUser()->getLogin());
  }
}



class AuthControllerNewsletterUnsubscribeNoBodyTest extends AuthControllerNobodyLoggedTestCase {

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

    $this->fixture('Class_Newsletter',
                   ['id' => 1,
                    'titre' => 'Daily News']);


    $this->dispatch('auth/newsletter-unsubscribe/id/1', true);
  }


  /** @test */
  public function authMessageShouldBeDisplay() {
    $this->assertXPathContentContains('//p', 'Vous devez vous identifier pour vous désinscrire de la newsletter: Daily News');
  }


  /** @test */
  public function linkToLoginShouldBePresent() {
    $this->assertXPath('//a[contains(@href,"auth/ajax-login")]');
  }
}




class AuthControllerNewsletterUnsubscribeWrongIdTest extends AuthControllerNobodyLoggedTestCase {

  public function setUp() {
    parent::setUp();
    Class_Newsletter::beVolatile();
    $this->dispatch('auth/newsletter-unsubscribe/id/1', true);
  }


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


  /** @test */
  public function flashMessageShouldBeAsExpected() {
    $this->assertFlashMessengerContentContains('Vous n\'êtes plus inscrit à la lettre d\'information, celle-ci n\'existe plus.');
  }
}




class AuthControllerNewsletterUnsubscribeTest extends AbstractControllerTestCase {

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

    $tomato = $this->fixture('Class_Users',
                             ['id' => 156,
                              'login' => 'tomato',
                              'password' => 'pwd']);

    ZendAfi_Auth::getInstance()
      ->logUser($tomato);

    $daily_news = $this->fixture('Class_Newsletter',
                                 ['id' => 1,
                                  'titre' => 'Daily News']);

    $subscription = $this->fixture('Class_NewsletterSubscription',
                                   ['id' => 1]);

    $subscription->setUser($tomato);
    $subscription->setNewsletter($daily_news);
    $subscription->save();

    $this->dispatch('auth/newsletter-unsubscribe/id/1', true);
  }


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


  /** @test */
  public function flashMessageShouldBeAsExpected() {
    $this->assertFlashMessengerContentContains('Vous êtes désinscrit de la liste de diffusion: Daily News');
  }
}



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

    ZendAfi_Auth::getInstance()->clearIdentity();

    $this->mock_transport = new MockMailTransport();
    Zend_Mail::setDefaultTransport($this->mock_transport);
    $this->mock_transport->onSendDo(function() { throw new Exception();
                                                });

    Class_Profil::getCurrentProfil()
      ->setMailSite('tom@afi.fr');

    Class_Users::beVolatile();
    Class_UsersNonValid::beVolatile();

    $this->fixture('Class_Newsletter', ['id' => 5, 'titre' => 'Daily News']);

    $this->postDispatch('/opac/auth/newsletter-register/id/5', ['email' => 'iwanttobespamed@abo.it',
                                                                'emailCheck' => '']);
  }


  /** @test */
  public function sendMailErrorShouldBePresent() {
    $this->assertXPathContentContains('//span[@class="error"]', 'Une erreur est survenue à l\'envoi du mail de confirmation. Veuillez réessayer. Si le problème persiste, veuillez contacter votre médiathèque.');
  }
}



class AuthControllerNewsletterRegisterWithAutoSubscribeNewsletterTest extends AbstractControllerTestCase {
  public function setUp() {
    parent::setUp();
    Class_NewsletterSubscription::beVolatile();
    Class_Users::beVolatile();
    $this->fixture('Class_UsersNonValid', [
                                           'id' => 1,
                                           'login' => 'future@i.am',
                                           'mail' => 'future@i.am',
                                           'password' => 'random',
                                           'cle' => '12345678']);

    $daily_news = $this->fixture('Class_Newsletter',
                                 ['id' => 1,
                                  'titre' => 'Daily News']);

    $daily_news->setAutoSubscribe(true)->save();

    $weekly_news = $this->fixture('Class_Newsletter',
                                  ['id' => 2,
                                   'titre' => 'Weekly News']);

    $this->dispatch('opac/auth/newsletter-active-user/c/12345678/id/1', true);
  }


  /** @test */
  public function onlyOneSubscriptionsShouldBeSaved() {
    $this->assertEquals(1, count(Class_NewsletterSubscription::findAll()));

  }


  /** @test */
  public function newsletterSubscriptionShouldContainsDailyNewsNews() {
    $this->assertEquals('Daily News', Class_NewsletterSubscription::find(1)->getNewsletter()->getTitre());
  }


  /** @test */
  public function messageShouldBeAsExpected() {
    $this->assertXPathContentContains('//p', "Vous avez bien été abonné à la newsletter");
  }
}
?>