Skip to content
Snippets Groups Projects
RechercheControllerReservationTest.php 28.24 KiB
<?php
/**
 * Copyright (c) 2012-2014, 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
 */


abstract class RechercheControllerReservationTestCase
  extends AbstractControllerTestCase {

  protected $_json, $_xpath,
    $_storm_default_to_volatile = true;

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

    $this->fixture('Class_CodifAnnexe',
                   ['id' => 2,
                    'code' => '36',
                    'id_origine' => '36',
                    'libelle' => 'Annecy']);

    $this->fixture('Class_CodifAnnexe',
                   ['id' => 3,
                    'code' => '37',
                    'id_origine' => '37',
                    'libelle' => 'Cran']);

    $this->_xpath = new Storm_Test_XPath();
  }
}



abstract class RechercheControllerReservationWithPickupChoiceTestCase
  extends RechercheControllerReservationTestCase {

  public function setUp() {
    parent::setUp();
    Class_CosmoVar::setValueOf('site_retrait_resa',
                               Class_CosmoVar::PICKUP_LOCATION_CHOICE);
  }
}



class RechercheControllerReservationPickupAjaxActionWithChosenPickupTest
  extends RechercheControllerReservationWithPickupChoiceTestCase {

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

    $this->dispatch('recherche/reservation-pickup-ajax?id_bib=2&id_origine=12&code_annexe=36',true);

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


  /** @test */
  public function shouldRenderAnnecyCheckedRadio() {
    $this->_xpath->assertXPath($this->_json->content,
                               '//input[@name="code_annexe"][@value="36"][@checked="checked"]',$this->_json->content);
  }


  /** @test */
  public function shouldRenderCranRadio() {
    $this->_xpath->assertXPath($this->_json->content,
                               '//input[@name="code_annexe"][@value="37"]');
  }


  /** @test */
  public function layoutShouldBeEmpty() {
    $this->_xpath->assertNotXPath($this->_json->content, '//div[@id="banniere"]');
  }
}



class RechercheControllerReservationPickupAjaxActionPostTest
  extends RechercheControllerReservationWithPickupChoiceTestCase {


  /** @test */
  public function responseShouldRedirectToReservationajaxAction() {
    $this->postDispatch('recherche/reservation-pickup-ajax',
                        ['id_bib' => 2,
                         'id_origine' => 12,
                         'code_annexe' => '36']);

    $this->assertRedirectTo(Class_Url::absolute('/recherche/reservationajax/code_annexe/36'));
  }


  /** @test */
  public function responseShouldContainsJsonRedirectToReservationajaxAction() {
    $this->postDispatch('recherche/reservation-pickup-ajax/render/popup',
                        ['id_bib' => 2,
                         'id_origine' => 12,
                         'code_annexe' => '36']);

    $this->assertContains('<div class=\"saving-process\"><p>Veuillez patienter ...<\/p><img src=\"\/ghislo\/public\/admin\/images\/patience.gif\" class=\"loading-img\" alt=\"\"><\/div><script>location.reload();<\/script>', $this->_response->getBody());
  }
}




class RechercheControllerReservationPickupAjaxActionTestWithChosenPickupDispatch
  extends RechercheControllerReservationWithPickupChoiceTestCase {

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

    $bib = $this
      ->fixture('Class_IntBib',
                ['id' => 1,
                 'comm_sigb' => Class_IntBib::COM_NANOOK,
                 'comm_params' => ['url_serveur' => 'http://bib.valensol.net']]);

    $this->jajm = $this
      ->fixture('Class_Users',
                ['id' => 1,
                 'login' => 'jajm',
                 'password' => 'secret',
                 'idabon' => '0000007',
                 'int_bib' => $bib,
                ]);

    $this->nanook = Storm_Test_ObjectWrapper::mock()
      ->whenCalled('isConnected')->answers(true)
      ->whenCalled('reserverExemplaire')->answers(true);

    Class_WebService_SIGB_Nanook::setService(['url_serveur' => 'http://bib.valensol.net',
                                              'id_bib' => 1,
                                              'type' => Class_IntBib::COM_NANOOK,],
                                             $this->nanook);

    ZendAfi_Auth::getInstance()->logUser($this->jajm);

    $this->fixture('Class_Exemplaire', ['id' => 12]);

    $this->dispatch('recherche/reservationajax/id/11760/id_int_bib/23/id_bib/23/id_origine/594105/code_annexe/23/render/popup/copy_id/12', true);
  }


  /** @test */
  public function parameterCodeAnnexeShouldBeUsedForReservation() {
    $this->assertEquals('23',
                        $this->nanook->getAttributesForLastCallOn('reserverExemplaire')[2]);
  }
}



class RechercheControllerReservationPickupAjaxActionTestWithPatronLibraryPickup
  extends RechercheControllerReservationTestCase {

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

    $bib = $this
      ->fixture('Class_IntBib',
                ['id' => 12,
                 'comm_sigb' => Class_IntBib::COM_NANOOK,
                 'comm_params' => ['url_serveur' => 'http://bib.valensol.net']]);

    $this->jajm = $this->fixture('Class_Users',
                                 ['id' => 1,
                                  'login' => 'jajm',
                                  'password' => 'secret',
                                  'idabon' => '0000007',
                                  'int_bib' => $bib]);

    $this->nanook = Storm_Test_ObjectWrapper::mock()
      ->whenCalled('isConnected')->answers(true)
      ->whenCalled('reserverExemplaire')->answers(true)
      ->whenCalled('providesPickupLocations')->answers(false)
      ->whenCalled('getUserAnnexe')->answers('12');

    Class_WebService_SIGB_Nanook::setService(['url_serveur' => 'http://bib.valensol.net',
                                              'id_bib' => 12,
                                              'type' => Class_IntBib::COM_NANOOK,],
                                             $this->nanook);

    ZendAfi_Auth::getInstance()->logUser($this->jajm);

    Class_CosmoVar::setValueOf('site_retrait_resa',
                               Class_CosmoVar::PICKUP_LOCATION_PATRON);

    $this->fixture('Class_Exemplaire', ['id' => 12]);

    $this->dispatch('recherche/reservation-pickup-ajax?id_bib=2&id_origine=12&code_annexe=36&copy_id=12', true);
  }


  /** @test */
  public function getUserAnnexeResultShouldBeUsedForReservation() {
    $this->assertEquals('12',
                        $this->nanook->getAttributesForLastCallOn('reserverExemplaire')[2]);

  }
}



class RechercheControllerReservationPickupAjaxActionTestWithItemLibraryPickup
  extends RechercheControllerReservationTestCase {

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

    $bib = $this->fixture('Class_IntBib',
                          ['id' => 1,
                           'comm_sigb' => Class_IntBib::COM_NANOOK,
                           'comm_params' => ['url_serveur' => 'http://bib.valensol.net']]);

    $this->jajm = $this->fixture('Class_Users',
                                 ['id' => 1,
                                  'login' => 'jajm',
                                  'password' => 'secret',
                                  'idabon' => '0000007',
                                  'int_bib' => $bib
                                   ]);

    $this->nanook = Storm_Test_ObjectWrapper::mock()
      ->whenCalled('isConnected')->answers(true)
      ->whenCalled('providesPickupLocations')->answers(false)
      ->whenCalled('reserverExemplaire')->answers(true);

    Class_WebService_SIGB_Nanook::setService(['url_serveur' => 'http://bib.valensol.net',
                                              'id_bib' => 1,
                                              'type' => Class_IntBib::COM_NANOOK,],
                                             $this->nanook);

    ZendAfi_Auth::getInstance()->logUser($this->jajm);

    Class_CosmoVar::setValueOf('site_retrait_resa',
                               Class_CosmoVar::PICKUP_LOCATION_ITEM);

    $this->fixture('Class_Exemplaire', ['id' => 12]);

    $this->dispatch('recherche/reservation-pickup-ajax?id_bib=2&id_origine=12&code_annexe=36&copy_id=12', true);
  }


  /** @test */
  public function itemAnnexeShouldBeUsedForReservation() {
    $this->assertEquals('36',
                        $this->nanook->getAttributesForLastCallOn('reserverExemplaire')[2]);

  }
}



class RechercheControllerReservationWithMailPostAction
  extends AbstractControllerTestCase {
  protected
    $_sent_mails,
    $_storm_default_to_volatile = true;

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

    $_SESSION["captcha_code"] = '1234';

    $mock_transport = new MockMailTransport();
    Zend_Mail::setDefaultTransport($mock_transport);

    $this->fixture('Class_Bib', ['id' => 4,
                                 'libelle' => 'Astrolabe',
                                 'mail' => 'zork@gloub.fr',]);

    $this->fixture('Class_Notice', ['id' => 4,
                                    'unimarc' => "01570nam0 2200325   450 0010007000000100033000070200017000400210027000571000041000841010008001251020007001331050018001401060006001582000106001642100075002702150044003452250023003893000125004123000020005373000137005573300265006943450018009594100051009775120027010286060033010556060060010886760012011487000045011608010039012052218529  a2-86642-370-4bbr.d8,95 EUR  aFRb00347575  aFRbDLE-20031204-51138  a20031107d2003    m  h0frey0103    ba| afre  aFR  ay   z   000y|  ar1 aCinema d'animationbTexte impriméedessin animé, marionnettes, images de synthèsefBernard Genin  a[Paris]c\"Cahiers du cinéma\"cSCEREN-CNDPdcop. 2003gimpr. en Italie  a95 p.cill., couv. ill. en coul.d19 cm2 aLes petits cahiers  aLa couv. porte en plus : \"du crayon à l'ordinateur, pour ou contre Disney, Europe-Japon : le dessin animé aujourd'hui\"  aBibliogr. p. 93  aSCEREN = Services, cultures, éditions, ressources pour l'éducation nationale. CNDP = Centre national de documentation pédagogique  aPrésente un historique du cinéma d'animation, un survol des différentes productions nationales à travers le monde (Etats-Unis, Japon, France, Canada), les techniques du volume animé, l'image de synthèse, mais aussi l'oeuvre de Disney et le film d'auteur.  b9782866423704 032525826tLes Petits cahiers (Paris)x1633-90531 aLe cinéma d'animation| 31053394aAnimation (cinéma)| 31031625aDessins animés32195497xHistoire et critique  a791.431 |32547161aGeninbBernardf1946-....4070 0aFRbBNFc20031107gAFNOR2intermrc"]);

    $this->postDispatch('/recherche/reservation/id_notice/4/id_bib/4/cote/XYZ',
                        ['user_name' => 'nanuk',
                         'demande' => 'je veux le livre',
                         'user_mail' => 'nanuk@gloub.com',
                         'code_saisi' => '1234']);

    $this->_sent_mails = $mock_transport->getSentMails();
    $this->first_mail = array_first($this->_sent_mails);
    $this->first_content = $this->first_mail->getBodyText()->getContent();
    $this->last_mail = array_last($this->_sent_mails);
  }


  /** @test */
  public function twoMailsShouldHaveBeenSent() {
    $this->assertEquals(2, count($this->_sent_mails));
  }


  /** @test */
  public function firstMailFromShouldBeNanuk() {
    $this->assertEquals('nanuk@gloub.com',
                        $this->first_mail->getFrom());
  }


  /** @test */
  public function firstMailSubjectShouldBeDemandeDeReservation() {
    $this->assertContains('Demande de réservation de document',
                          quoted_printable_decode($this->first_mail->getSubject()));
  }


  /** @test */
  public function firstMailToShouldBeZork() {
    $this->assertContains('zork@gloub.fr',
                          $this->first_mail->getRecipients());
  }


  /** @test */
  public function titleShouldBePresent() {
    $this->assertTrue(false !== strpos($this->first_content, 'Titre : Cinema d\'animation'));
  }


  /** @test */
  public function authorShouldBePresent() {
    $this->assertTrue(false !== strpos($this->first_content, 'Auteur : Bernard Genin'),
                      $this->first_content);
  }


  /** @test */
  public function secondMailFromShouldBeNobody() {
    $this->assertEquals('nobody@noreply.fr',
                        $this->last_mail->getFrom());
  }


  /** @test */
  public function secondMailToShouldBeNanuk() {
    $this->assertContains('nanuk@gloub.com',
                          $this->last_mail->getRecipients());
  }
}



class RechercheControllerReservationWithWebServiceKohaTest
  extends AbstractControllerTestCase {

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

    $webservice = 'http://bib.valensol.net';
    $bib = $this->fixture('Class_IntBib',
                          ['id' => 1,
                           'comm_sigb' => Class_IntBib::COM_KOHA,
                           'comm_params' => ['url_serveur' => $webservice]]);

    $this->jajm = $this->fixture('Class_Users',
                                 ['id' => 1,
                                  'login' => 'jajm',
                                  'password' => 'secret',
                                  'int_bib' => $bib,
                                 ]);

    ZendAfi_Auth::getInstance()->logUser($this->jajm);
    $this->koha = Storm_Test_ObjectWrapper::mock();
    $this->koha
      ->whenCalled('getServerRoot')
      ->answers($webservice);

    Class_WebService_SIGB_Koha::setService(['url_serveur' => $webservice,
                                            'id_bib' => 1,
                                            'type' => Class_IntBib::COM_KOHA],
                                           $this->koha);
  }


  protected function dispatchAndCheckContentEquals($expected) {
    $this->dispatch('/recherche/reservationajax/id_bib/1/copy_id/456/code_annexe/VS',
                    true);
    $this->json = json_decode($this->_response->getBody());
    $this->assertEquals($expected, $this->json->content);
  }


  /** @test */
  public function withMatchingHoldMessageShouldContainsPickupLocation() {
    $item = $this->fixture('Class_Exemplaire',
                           ['id' => 456,
                            'code_barres' => 123,
                            'id_int_bib' => 1]);

    $response = $this->_prepareEmprunteurHolding($item, 'Valensole');
    $expected_message = 'Votre réservation est enregistrée.<br>Nous vous informerons quand le document sera disponible pour être retiré à : Valensole';
    $this->_dispatchWithEmprunteurAndAssertContentEquals($response,
                                                         $expected_message);
  }


  /** @test */
  public function withMatchingHoldAndRecordMessageShouldContainsPickupLocationAndRecordTitleAuthor() {
    $exemplaire = $this->fixture('Class_Exemplaire',
                                 ['id' => 456,
                                  'code_barres' => 123,
                                  'id_int_bib' => 1,
                                  'notice' => $this->fixture('Class_Notice',
                                                             ['id' => 8890,
                                                              'titre_principal' => 'Arcadia',
                                                              'auteur_principal' => 'Matsumoto'])]);
    $this->_dispatchWithEmprunteurAndAssertContentEquals(
      $this->_prepareEmprunteurHolding($exemplaire, 'Valensole'),
      'Votre réservation est enregistrée.<br>Nous vous informerons quand le document \'Arcadia / Matsumoto\' sera disponible pour être retiré à : Valensole');
  }


  /** @test */
  public function withoutMatchingHoldMessageShouldContainsDocumentNotFound() {
    $this->_dispatchWithEmprunteurAndAssertContentEquals(
      $this->_prepareEmprunteurHolding(null, 'Valensole'),
      'Document introuvable');
  }


  /** @test */
  public function withMatchingHoldAndNoPickupLocationShouldNotContainsPickupLocation() {
    $this->_dispatchWithEmprunteurAndAssertContentEquals(
      $this->_prepareEmprunteurHolding($this->fixture('Class_Exemplaire', ['id' => 456]),
                                       null),
      'Votre réservation est enregistrée.<br>Nous vous informerons quand le document sera disponible');
  }


  protected function _prepareEmprunteurHolding($item, $pickup_label) {
    $this->jajm->setIdabon(395749);

    $exemplaire = (new Class_WebService_SIGB_Exemplaire(2))
      ->setExemplaireOPAC($item);
    $hold = new Class_WebService_SIGB_Reservation(2, $exemplaire);
    $hold->setPickupLocationLabel($pickup_label)
         ->setCodeBarre(123);

    $emprunteur_jajm = Class_WebService_SIGB_Emprunteur::newInstance(2, 'jajm');
    $emprunteur_jajm->reservationsAdd($hold);
    return $emprunteur_jajm;
  }


  protected function _dispatchWithEmprunteurAndAssertContentEquals($emprunteur, $content) {
    $this->koha
      ->whenCalled('isConnected')->answers(true)
      ->whenCalled('reserverExemplaire')->answers(['statut' => true,
                                                   'erreur' => '',
                                                   'popup' => false])
      ->whenCalled('getEmprunteur')->answers($emprunteur);

    $this->dispatchAndCheckContentEquals($content);
  }


  /** @test */
  public function popupResultContentWithWebServiceErrorShouldContainsErreurDeCommunication() {
    $this->jajm->setIdabon(395749);

    $this->_prepareEmprunteurHolding($this->fixture('Class_Exemplaire', ['id' => 456]),
                                     'Valensole');

    $this->koha->whenCalled('isConnected')->answers(false);

    $this->dispatchAndCheckContentEquals("Une erreur de communication avec le serveur a fait échouer la requête. Merci de signaler ce problème à la bibliothèque.");
  }


  /** @test */
  public function withoutIdAbonpopupResultContentShouldContainsVousDevezVousConnecterSousVotreNumeroDeCarte() {
    $this->dispatchAndCheckContentEquals("Vous devez vous connecter sous votre numéro de carte pour effectuer une réservation.");
  }
}




class RechercheControllerReservationWithMailFormTest
  extends AbstractControllerTestCase {

  protected $_storm_default_to_volatile = true;

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

    $this->fixture('Class_Bib', ['id' => 88,
                                 'libelle' => 'My Library',
                                 'mail' => 'my@library.com']);

    $this->fixture('Class_Notice',
                   ['id' => 550171,
                    'type_doc' => 1,
                    'titre_principal' => 'Test record',
                    'auteur_principal' => 'Test author',
                    'editeur' => 'Test editor',
                   ]);

    $this->dispatch('/recherche/reservation/id/550171/id_int_bib/88/id_bib/88/id_notice/550171/cote/P+TRA', true);
  }


  /** @test */
  public function bibNameShouldBePresentInForm() {
    $this->assertXPath('//input[@type="text"][@disabled][@name="bib_name"][@value="My Library"]');
  }


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


  /** @test */
  public function shouldContainsMessage() {
    $this->assertXPath('//textarea[@name="demande"]');
  }


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


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




abstract class RechercheControllerReservationWithMailFormPostTestCase
  extends AbstractControllerTestCase {
  protected
    $_storm_default_to_volatile = true,
    $_mail_transport;

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

    $this->fixture('Class_Bib', ['id' => 88,
                                 'libelle' => 'My Library',
                                 'mail' => 'my@library.com']);

    $this->fixture('Class_Notice',
                   ['id' => 550171,
                    'type_doc' => 1,
                    'titre_principal' => 'Test record',
                    'auteur_principal' => 'Test author',
                    'editeur' => 'Test editor',
                   ]);

    $_SESSION['captcha_code'] = 'e2df0';

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


  protected function postDatas($datas) {
    $this->postDispatch('/recherche/reservation/id/550171/id_int_bib/88/id_bib/88/id_notice/550171/cote/P+TRA',
                        $datas);
  }


  protected function assertElementError($path, $message) {
    $this->assertXPathContentContains($path . '/following-sibling::ul[@class="errors"]/li', $message,
                                  $this->_response->getBody());
  }
}



class RechercheControllerReservationWithMailFormInvalidPostTest
  extends RechercheControllerReservationWithMailFormPostTestCase{

  /** @test */
  public function withEmptyPostAllFieldsShouldBeRequired() {
    $this->postDatas([]);

    foreach([
             ['//input[@name="user_name"]', 'Une valeur est requise'],
             ['//textarea[@name="demande"]', 'Une valeur est requise'],
             ['//input[@name="user_mail"]', 'Une valeur est requise'],
             ['//input[@name="code_saisi"]', 'Une valeur est requise'],
             ] as $case) {
      list($path, $message) = $case;
      $this->assertElementError($path, $message);
    }
  }


  /** @test */
  public function withBadMailShouldDisplayInvalidMail() {
    $this->postDatas(['user_mail' => 'bad mail address']);
    $this->assertElementError('//input[@name="user_mail"]', 'n\'est pas un email valide');
  }


  /** @test */
  public function withBadCaptchaShouldDisplayInvalidCaptchaHaveEmptyValue() {
    $this->postDatas(['code_saisi' => 'bad captcha code']);
    $this->assertElementError('//input[@name="code_saisi"][@value=""]',
                              'Le code anti-spam est incorrect');
  }
}



class RechercheControllerReservationWithMailFormValidPostTest
  extends RechercheControllerReservationWithMailFormPostTestCase{

  protected $_mails;

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

    Class_AdminVar::set('TEXTE_MAIL_RESA', 'Thanks for your hold');

    $this->postDatas(['user_name' => 'Testing user',
                      'demande' => 'testing demande',
                      'user_mail' => 'test@server.com',
                      'code_saisi' => 'e2df0']);

    $this->_mails = $this->_mail_transport->getSentMails();
  }


  protected function assertMailBodyContains($needle, $mail) {
    $this->assertContains($needle, $mail->getBodyText(true));
  }


  /** @test */
  public function validFormShouldSendTwoMails() {
    $this->assertCount(2, $this->_mails);
  }


  /** @test */
  public function mailsShouldHaveHoldQuerySubject() {
    foreach($this->_mails as $mail)
      $this->assertEquals('Demande de réservation de document', $mail->getSubject());
  }


  /** @test */
  public function firstMailRecipientShouldBeLibrary() {
    $this->assertContains('my@library.com', $this->_mails[0]->getRecipients());
  }


  /** @test */
  public function firstMailFromShouldBeUser() {
    $this->assertEquals('test@server.com', $this->_mails[0]->getFrom());
  }


  /** @test */
  public function firstMailBodyShouldContainsUserName() {
    $this->assertMailBodyContains('Testing user', $this->_mails[0]);
  }


  /** @test */
  public function firstMailBodyShouldContainsRecordInfo() {
    foreach(['Test record', 'P TRA', 'Test author', 'Test editor'] as $info)
      $this->assertMailBodyContains($info, $this->_mails[0]);
  }


  /** @test */
  public function firstMailBodyShouldUserMessage() {
    $this->assertMailBodyContains('testing demande', $this->_mails[0]);
  }

  /** @test */
  public function secondMailRecipientShouldBeUser() {
    $this->assertContains('test@server.com', $this->_mails[1]->getRecipients());
  }


  /** @test */
  public function secondMailFromShouldBeNobody() {
    $this->assertEquals('nobody@noreply.fr', $this->_mails[1]->getFrom());
  }


  /** @test */
  public function secondMailBodyShouldContainsTexteMailResa() {
    $this->assertMailBodyContains('Thanks for your hold', $this->_mails[1]);
  }


  /** @test */
  public function shouldRedirectToRecordView() {
    $this->assertRedirectTo('/opac/recherche/viewnotice/id/550171?type_doc=1');
  }
}



abstract class RechercheControllerReservationPickupAjaxWithNanookPickupLocationsTestCase
  extends RechercheControllerReservationTestCase{

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

    $bib = $this
      ->fixture('Class_IntBib',
                ['id' => 12,
                 'comm_sigb' => Class_IntBib::COM_NANOOK,
                 'comm_params' => ['url_serveur' => 'http://bib.valensol.net']]);

    $this->jajm = $this->fixture('Class_Users',
                                 ['id' => 1,
                                  'login' => 'jajm',
                                  'password' => 'secret',
                                  'idabon' => '0000007',
                                  'int_bib' => $bib]);

    $this->nanook = $this->mock()
      ->whenCalled('isConnected')->answers(true)
      ->whenCalled('providesPickupLocations')->answers(true)

      ->whenCalled('pickupLocationsFor')
      ->answers(['36' => 'Annecy',
                 '37' => 'Cran',
                 '45' => 'Istres']);

    Class_WebService_SIGB_Nanook::setService(['url_serveur' => 'http://bib.valensol.net',
                                              'id_bib' => 12,
                                              'type' => Class_IntBib::COM_NANOOK,],
                                             $this->nanook);

    ZendAfi_Auth::getInstance()->logUser($this->jajm);

    $this->fixture('Class_Exemplaire', ['id' => 12]);
  }


  public function choices() {
    return [[36], [37], [45]];
  }

  /**
   * @test
   * @dataProvider choices
   */
  public function choiceShouldBePresent($location_id) {
    $this->_xpath
      ->assertXPath($this->_json->content,
                    '//input[@type="radio"][@value="' . $location_id . '"]');
  }
}



class RechercheControllerReservationPickupAjaxNanookPickupLocationsPrecheckPatronTest
  extends RechercheControllerReservationPickupAjaxWithNanookPickupLocationsTestCase {

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

    $this->nanook->whenCalled('getUserAnnexe')->answers('45');

    $this->dispatch('recherche/reservation-pickup-ajax?id_bib=2&id_origine=12&code_annexe=37&copy_id=12', true);

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


  /** @test */
  public function istresShouldBeChecked() {
    $this->_xpath
      ->assertXPath($this->_json->content, '//input[@type="radio"][@value="45"][@checked]');
  }
}



class RechercheControllerReservationPickupAjaxNanookPickupLocationsPrecheckRequestedTest
  extends RechercheControllerReservationPickupAjaxWithNanookPickupLocationsTestCase {

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

    $this->nanook->whenCalled('getUserAnnexe')->answers('66');

    $this->dispatch('recherche/reservation-pickup-ajax?id_bib=2&id_origine=12&code_annexe=37&copy_id=12', true);

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


  /** @test */
  public function cranShouldBeChecked() {
    $this->_xpath
      ->assertXPath($this->_json->content, '//input[@type="radio"][@value="37"][@checked]');
  }
}



class RechercheControllerReservationPickupAjaxNanookPickupLocationsPrecheckFirstTest
  extends RechercheControllerReservationPickupAjaxWithNanookPickupLocationsTestCase {

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

    $this->nanook->whenCalled('getUserAnnexe')->answers('66');

    $this->dispatch('recherche/reservation-pickup-ajax?id_bib=2&id_origine=12&code_annexe=77&copy_id=12', true);
    $this->_json = json_decode($this->_response->getBody());
  }


  /** @test */
  public function annecyShouldBeChecked() {
    $this->_xpath
      ->assertXPath($this->_json->content, '//input[@type="radio"][@value="36"][@checked]');
  }
}