<?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::class, ['id' => 2, 'code' => '36', 'id_origine' => '36', 'libelle' => 'Annecy']); $this->fixture(Class_CodifAnnexe::class, ['id' => 3, 'code' => '37', 'id_origine' => '37', 'libelle' => 'Cran']); $this->fixture(Class_Notice::class, ['id' => 124, 'titre' => 'Aimer' ]); $this->fixture(Class_IntBib::class, ['id' => 12, 'sigb_comm' => Class_IntBib::COM_NANOOK, 'comm_params' => ['url_serveur' => 'http://valensol.net']]); $this->fixture(Class_Exemplaire::class, ['id' => 13425, 'id_origine' => 12, 'id_int_bib' => 12, 'notice_id' => 124, 'code_barres' => '1242', ]); $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©_id=13425',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, 'copy_id' => 13425, 'code_annexe' => '36']); $this->assertRedirectTo('/recherche/reservationajax/code_annexe/36'); } /** @test */ public function withoutAvailablePickupLocationPostResponseShouldAnswerError() { Class_CodifAnnexe::deleteBy([]); $this->postDispatch('recherche/reservation-pickup-ajax', ['id_bib' => 2, 'id_origine' => 12, 'copy_id' => 13425, 'code_annexe' => '36']); $json = json_decode($this->_response->getBody(), true); $this->assertContains('Aucun site de retrait disponible', $json['content']); } /** @test */ public function withoutAvailablePickupLocationGETResponseShouldAnswerError() { Class_CodifAnnexe::deleteBy([]); $this->dispatch('recherche/reservation-pickup-ajax/id_bib/2/id_origine/12/copy_id/13425'); $json = json_decode($this->_response->getBody(), true); $this->assertContains('Aucun site de retrait disponible', $json['content']); } /** @test */ public function withPopupAndInspectorGadgetResponseShouldStillSendJSON() { Zend_Registry::get('session')->inspectorCalls = [serialize(new Class_InspectorGadget_ServiceCall('I', 'love', 'milk', 'coffee', '418'))]; $this->postDispatch('recherche/reservation-pickup-ajax/render/popup/inspector_gadget/1', ['id_bib' => 2, 'id_origine' => 12, 'copy_id' => 13425, 'code_annexe' => '36']); $this->assertNotNull($json = json_decode($this->_response->getBody(), true)); $this->assertContains('<script>location.reload();</script>', $json['content']); } /** @test */ public function responseShouldContainsJsonRedirectToReservationajaxAction() { $this->postDispatch('recherche/reservation-pickup-ajax/render/popup', ['id_bib' => 2, 'id_origine' => 12, 'copy_id' => 13425, 'code_annexe' => '36']); $json = json_decode($this->_response->getBody(), true); $this->assertContains('<script>location.reload();</script>', $json['content']); } } class RechercheControllerReservationPickupAjaxActionTestWithChosenPickupDispatch extends RechercheControllerReservationWithPickupChoiceTestCase { protected $_sent_mails; public function setUp() { parent::setUp(); $bib = $this ->fixture(Class_IntBib::class, ['id' => 1, 'comm_sigb' => Class_IntBib::COM_NANOOK, 'comm_params' => ['url_serveur' => 'http://bib.valensol.net']]); $this->jajm = $this ->fixture(Class_Users::class, ['id' => 1, 'login' => 'jajm', 'password' => 'secret', 'idabon' => '0000007', 'int_bib' => $bib, ]); $this->nanook = (new Class_Testing_WebService_SIGB_Nanook_Service()) ->whenCalled('reserverExemplaire')->answers(['erreur' => '', 'statut' => true]) ->whenCalled('isConnected')->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]); $mock_transport = new MockMailTransport(); Zend_Mail::setDefaultTransport($mock_transport); $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); $this->_sent_mails = $mock_transport->getSentMails(); } /** @test */ public function parameterCodeAnnexeShouldBeUsedForReservation() { $this->assertEquals('23', $this->nanook->getAttributesForLastCallOn('reserverExemplaire')[2]); } /** @test */ public function noEmailShouldHaveBeenSentWithDefaultConf() { $this->assertEmpty($this->_sent_mails); } } 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 = (new Class_Testing_WebService_SIGB_Nanook_Service()) ->whenCalled('isConnected')->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, 'id_int_bib' => 12]); $this->dispatch('recherche/reservation-pickup-ajax?id_bib=2&id_origine=12&code_annexe=36©_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::class, ['id' => 1, 'comm_sigb' => Class_IntBib::COM_NANOOK, 'comm_params' => ['url_serveur' => 'http://bib.valensol.net']]); $this->jajm = $this->fixture(Class_Users::class, ['id' => 1, 'login' => 'jajm', 'password' => 'secret', 'idabon' => '0000007', 'int_bib' => $bib ]); $this->nanook = (new Class_Testing_WebService_SIGB_Nanook_Service()) ->whenCalled('isConnected')->answers(true) ->whenCalled('providesPickupLocations')->answers(false) ->whenCalled('reserverExemplaire')->answers(['statut' => true, 'erreur' => '']); 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::class, ['id' => 12, 'id_int_bib' => 1, 'annexe' => 36]); $this->dispatch('recherche/reservation-pickup-ajax?id_bib=2&id_origine=12&code_annexe=36©_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 = quoted_printable_decode($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 { protected $_storm_default_to_volatile = true; public function setUp() { parent::setUp(); $webservice = 'http://bib.valensol.net'; $bib = $this->fixture('Class_IntBib', ['id' => 1, 'comm_sigb' => Class_IntBib::COM_KOHA_LEGACY, '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 = new Class_Testing_WebService_SIGB_KohaLegacy_Service(); $this->koha->setServerRoot( $webservice); Class_WebService_SIGB_KohaLegacy::setService(['url_serveur' => $webservice, 'id_bib' => 1, 'type' => Class_IntBib::COM_KOHA_LEGACY], $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 reservationAjaxWithItemRequiringCalendarHoldShouldRedirectToReservationCalendarAjax() { $this->fixture(Class_CodifAnnexe::class, ['id' => 123, 'code' => 'VS', 'libelle' => 'ValStar', 'id_int_bib' => 1, 'id_origine' => 'VS']); $item = $this->fixture(Class_Exemplaire::class, ['id' => 456, 'code_barres' => 123, 'id_int_bib' => 1, 'annexe' => 'VS', 'notice' => $this->fixture(Class_Notice::class, ['id' => 8890, 'titre_principal' => 'Elementaire mon cher polar', 'auteur_principal' => 'Conan Doyle'])]); $item->setSigbExemplaire((Class_WebService_SIGB_Koha_Exemplaire::newInstance()) ->doRequiresCalendarHold() ->setId(2) ->beReservable())->save(); $this->jajm->setIdabon(395749); $this->koha ->whenCalledDo('reserverExemplaire', [], function() { return $this->_error('error'); }); $this->dispatch('/recherche/reservationajax/id_bib/1/copy_id/456/code_annexe/VS'); $this->assertRedirectTo('/recherche/reservation-calendar-ajax/id_bib/1/copy_id/456/code_annexe/VS'); } /** @test */ public function withMatchingHoldMessageShouldContainsPickupLocation() { $item = $this->fixture(Class_Exemplaire::class, ['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 withMatchingHoldAndRecordWithBRInTitleMessageShouldContainsPickupLocationAndRecordTitleAuthor() { $exemplaire = $this->fixture(Class_Exemplaire::class, ['id' => 456, 'code_barres' => 123, 'id_int_bib' => 1, 'notice' => $this->fixture(Class_Notice::class, ['id' => 8890, 'titre_principal' => 'Albator <br /> Arcadia', 'auteur_principal' => 'Matsumoto'])]); $this->_dispatchWithEmprunteurAndAssertContentEquals( $this->_prepareEmprunteurHolding($exemplaire, 'Valensole'), 'Votre réservation est enregistrée.<br>Nous vous informerons quand le document \'Albator Arcadia / Matsumoto\' sera disponible pour être retiré à : Valensole'); } /** @test */ public function withMatchingHoldAndRecordWithoutAuthorMessageShouldContainsPickupLocationAndRecordTitleOnly() { $exemplaire = $this->fixture('Class_Exemplaire', ['id' => 456, 'code_barres' => 123, 'id_int_bib' => 1, 'notice' => $this->fixture('Class_Notice', ['id' => 8890, 'titre_principal' => 'Arcadia'])]); $this->_dispatchWithEmprunteurAndAssertContentEquals( $this->_prepareEmprunteurHolding($exemplaire, 'Valensole'), 'Votre réservation est enregistrée.<br>Nous vous informerons quand le document \'Arcadia\' 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 ->whenCalledDefaultAnswers('reserverExemplaire', ['statut' => true, 'erreur' => '', 'popup' => false]) ->whenCalledDefaultAnswers('getEmprunteur',$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->_prepareEmprunteurHolding($this->fixture('Class_Exemplaire', ['id' => 456]), 'Valensole'); $this->jajm->setIdabon(null)->save(); $this->dispatchAndCheckContentEquals("Vous devez vous connecter sous votre numéro de carte pour effectuer une réservation."); } } class RechercheControllerReservationSerialWithWebServiceKohaTest extends AbstractControllerTestCase { protected $_storm_default_to_volatile = true; protected $_exemplaire; public function setUp() { parent::setUp(); $webservice = 'http://bib.valensol.net'; $bib = $this->fixture('Class_IntBib', ['id' => 1, 'comm_sigb' => Class_IntBib::COM_KOHA_LEGACY, 'comm_params' => ['url_serveur' => $webservice]]); $data_profile = $this->fixture('Class_IntProfilDonnees', ['id' => 433, 'id_article_periodique' => Class_IntProfilDonnees::SERIAL_FORMAT_KOHA] ); $this->_exemplaire = $this->fixture('Class_Exemplaire', ['id' => 203609, 'code_barres' => 1644067, 'id_int_bib' => 1, 'id_origine' => '259517-123', 'data_profile' => $data_profile, 'notice' => $this->fixture('Class_Notice', ['id' => 205227, 'titre_principal' => 'Animan 210', 'type_doc' => Class_TypeDoc::PERIODIQUE ])]); $this->jajm = $this->fixture('Class_Users', ['id' => 1, 'login' => 'jajm', 'password' => 'secret', 'int_bib' => $bib, ]); Class_AdminVar::set('KOHA_MULTI_SITES','1'); ZendAfi_Auth::getInstance()->logUser($this->jajm); $this->koha = new Class_Testing_WebService_SIGB_Koha_Service(); $this->koha ->whenCalledDefaultAnswers('getServerRoot', $webservice); Class_WebService_SIGB_KohaLegacy::setService(['url_serveur' => $webservice, 'id_bib' => 1, 'type' => Class_IntBib::COM_KOHA_LEGACY], $this->koha); } protected function dispatchAndCheckContentEquals($expected) { $this->dispatch('/recherche/reservationajax/id/205227-123/id_notice/205227-210/id_bib/1/copy_id/203609/code_annexe/VS', true); $this->json = json_decode($this->_response->getBody()); $this->assertEquals($expected, $this->json->content); } /** @test */ public function functionGetBibNumberFromIdOrigineShouldReturn259517() { $this->assertEquals('259517', $this->_exemplaire->getBibNumberFromIdOrigine()); } /** @test */ public function withMatchingHoldAndRecordSerialMessageShouldContainsPickupLocationAndRecordTitle() { $response = $this->_prepareEmprunteurHolding($this->_exemplaire, 'Valensole'); $expected_message = 'Votre réservation est enregistrée.<br>Nous vous informerons quand le document \'Animan 210\' sera disponible pour être retiré à : Valensole'; $this->_dispatchWithEmprunteurAndAssertContentEquals($response, $expected_message); } protected function _prepareEmprunteurHolding($item, $pickup_label) { $this->jajm->setIdabon(395749); $exemplaire = (new Class_WebService_SIGB_Exemplaire(203609)) ->setExemplaireOPAC($item); $hold = new Class_WebService_SIGB_Reservation(2, $exemplaire); $hold->setPickupLocationLabel($pickup_label) ->setCodeBarre(1644067); $emprunteur_jajm = Class_WebService_SIGB_Emprunteur::newInstance(2, 'jajm'); $emprunteur_jajm->reservationsAdd($hold); $emprunteur_jajm->save(); return $emprunteur_jajm; } protected function _dispatchWithEmprunteurAndAssertContentEquals($emprunteur, $content) { $this->koha ->whenCalledDefaultAnswers('reserverExemplaire',['statut' => true, 'erreur' => '', 'popup' => false]) ->whenCalledDefaultAnswers('getEmprunteur', $emprunteur); $this->dispatchAndCheckContentEquals($content); } } class RechercheControllerReservationCalendarAjaxTest extends AbstractControllerTestCase { protected $_storm_default_to_volatile = true, $_json, $_xpath; public function setUp() { parent::setUp(); $item = $this->fixture('Class_Exemplaire', ['id' => 456, 'id_origine' => 1, 'annexe' => 'VS']); $comm_sigb = (new Class_Testing_WebService_SIGB_Koha_Service()) ->whenCalledAnswers('holdsForItem', [$item], ['statut' => true, 'holds' => [(new Class_WebService_SIGB_Koha_Reservation(3,$item)) ->setReserveDate('2020-01-15') ->setExpirationDate('2020-06-16'), (new Class_WebService_SIGB_Koha_Reservation(2,$item)) ->setReserveDate('2019-07-26') ->setExpirationDate('2019-12-31')]]); Class_CommSigb::setInstance($comm_sigb); $this->dispatch('/recherche/reservation-calendar-ajax/id_bib/1/copy_id/456/code_annexe/VS',true); $this->_json = json_decode($this->_response->getBody()); $this->_xpath = new Storm_Test_XPath(); } /** @test */ public function popupHoldsListShouldContainsDu26JuilletAu31Decembre() { $this->_xpath->assertXPathContentContains($this->_json->content, '//ul/li[1]', utf8_encode('Du 26 juillet 2019 au 31 décembre 2019')); } /** @test */ public function popupHoldsListShouldContainsDu15JanvierAu16Juin() { $this->_xpath->assertXPathContentContains($this->_json->content, '//ul/li[2]', utf8_encode('Du 15 janvier 2020 au 16 juin 2020')); } /** @test */ public function formActionShouldBeRechercheReservationCalendarAjax() { $this->_xpath->assertXPath($this->_json->content, '//form[@action="/recherche/reservation-calendar-ajax/id_bib/1/copy_id/456/code_annexe/VS"]'); } /** @test */ public function formCancelButtonShouldCloseDialog() { $this->_xpath->assertXPath($this->_json->content, '//button[@value="Annuler"][contains(@onclick, "opacDialogClose()")]'); } /** @test */ public function formShouldContainsSubmit() { $this->_xpath->assertXPath($this->_json->content, '//input[@type="submit"][@value="Valider"]'); } /** @test */ public function responseShouldContainsInputDatePickerForResevationDate() { $this->_xpath->assertXPath($this->_json->content, '//input[@name="reservedate"]'); } /** @test */ public function responseShouldContainsInputDatePickerForExpirationDate() { $this->_xpath->assertXPath($this->_json->content, '//input[@name="expirationdate"]'); } } class RechercheControllerReservationCalendarPostTest extends AbstractControllerTestCase { protected $_storm_default_to_volatile = true, $_comm_sigb; public function setUp() { parent::setUp(); $int_bib = $this ->fixture('Class_IntBib', ['id' => 1, 'comm_sigb' => Class_IntBib::COM_KOHA_LEGACY, 'use_card_number' => 12345, 'comm_params' => ['bundled_holds_minimal_duration' => 29, 'url_serveur' => 'http://bib.valensol.net/cgi-bin/koha/ilsdi.pl']]); $item = $this->fixture('Class_Exemplaire', ['id' => 456, 'code_barres' => 123, 'id_int_bib' => 1, 'notice' => $this->fixture('Class_Notice', ['id' => 8890, 'titre_principal' => 'Elementaire mon cher polar', 'auteur_principal' => 'Conan Doyle'])]); $this->_comm_sigb = (new Class_Testing_CommSigb()) ->whenCalledAnswers('holdsForItem',[$item],['statut' => true, 'holds' => []]); Class_CommSigb::setInstance($this->_comm_sigb); } /** @test */ public function withReserveDateAndExpirationDateShouldNotifyHoldSuccess() { $this->_comm_sigb ->whenCalledAnswers('ficheAbonne', [Class_Users::getIdentity()],null) ->whenCalledDo('holdCalendar', [456,'VS','2020-01-19','2020-05-25'],fn() => []); $this->postDispatch('/recherche/reservation-calendar-ajax/id_bib/1/copy_id/456/code_annexe/VS', ['reservedate' => '19/01/2020' , 'expirationdate' => '25/05/2020']); $this->json = json_decode($this->_response->getBody()); $this->assertContains('Votre réservation est enregistrée', $this->json->content); } /** @test */ public function withInvalidReserveDateShouldDisplayErrorReserveDateInvalide() { Class_Users::getIdentity()->setIdIntBib(1)->save(); $this->postDispatch('/recherche/reservation-calendar-ajax/id_bib/1/copy_id/456/code_annexe/VS', ['reservedate' => 'pouet' , 'expirationdate' => '25/05/2020']); $this->json = json_decode($this->_response->getBody()); $xpath = new Storm_Test_XPath(); $xpath->assertXPathContentContains($this->json->content, '//ul[@class="errors"]/li', '\'pouet\' ne correspond pas au format de date attendu', $this->json->content); } /** @test */ public function withDurationInferiorToMinimunShouldDisplayErrorDurationTooSmall() { // $this->_comm_sigb->whenCalledDo('holdCalendar', // [456,'VS','2020-05-10','2020-05-25'], // fn()=> $this->addError('); Class_Users::getIdentity()->setIdIntBib(1)->save(); $this->postDispatch('/recherche/reservation-calendar-ajax/id_bib/1/copy_id/456/code_annexe/VS', ['reservedate' => '10/05/2020' , 'expirationdate' => '25/05/2020']); $this->json = json_decode($this->_response->getBody()); $xpath = new Storm_Test_XPath(); $xpath->assertXPathContentContains($this->json->content, '//ul[@class="errors"]', 'Durée minimale requise: 29 jours'); $xpath->assertXPath($this->json->content, '//input[@name="reservedate"][@value="10/05/2020"]', $this->json->content); } } 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']); $unimarc = (new Class_NoticeUnimarc_Fluent) ->zoneWithContent('001', '') ->zoneWithChildren('200', [ 'a' => 'Test record'], ' 0') ->zoneWithChildren('214', [ 'c' => 'Test editor'], ' 0') ->render(); $this->fixture(Class_Notice::class, ['id' => 550171, 'type_doc' => 1, 'auteur_principal' => 'Test author', 'unimarc' => $unimarc, ]); $_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); } } 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, quoted_printable_decode($mail->getBodyText(true))); } /** @test */ public function validFormShouldSendTwoMails() { $this->assertCount(2, $this->_mails); } /** @test */ public function mailsShouldHaveHoldQuerySubject() { foreach($this->_mails as $mail) $this->assertContains('Demande de réservation de document', quoted_printable_decode($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::class, ['id' => 12, 'comm_sigb' => Class_IntBib::COM_NANOOK, 'comm_params' => ['url_serveur' => 'http://bib.valensol.net']]); $this ->fixture(Class_CodifAnnexe::class, ['id' => 12, 'libelle' => 'Vanne', 'id_origine' => '12']); $this->jajm = $this->fixture(Class_Users::class, ['id' => 1, 'login' => 'jajm', 'password' => 'secret', 'idabon' => '0000007', 'int_bib' => $bib]); $this->nanook =(new Class_Testing_WebService_SIGB_Nanook_Service()) ->whenCalled('isConnected')->answers(true) ->whenCalled('providesPickupLocations')->answers(true) ->whenCalled('pickupLocationsFor') ->answers(['36' => 'Annecy', '37' => 'Cran', '45' => 'Istres', '99' => 'Lunel <strong>(Disponible)</strong>']); 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::class, ['id' => 12, 'id_int_bib' => 12, 'int_bib' => Class_IntBib::find(12), 'annexe' => 12]); } } class RechercheControllerReservationPickupAjaxNanookPickupLocationsItemLibraryHoldTest extends RechercheControllerReservationPickupAjaxWithNanookPickupLocationsTestCase { public function setUp() { parent::setUp(); $this->nanook->whenCalled('getUserAnnexe')->answers('45') ->whenCalled('reserverExemplaire')->answers(['status' => true, 'erreur' => '']); $this->dispatch('recherche/reservation-pickup-ajax?id_bib=2&id_origine=12&code_annexe=37©_id=12', true); $this->_json = json_decode($this->_response->getBody()); } /** @test */ public function jsonReturnedVotreReservationEstEnregistree() { $this->assertContains($this->_json->content, 'Votre réservation est enregistrée.<br>Nous vous informerons quand le document sera disponible à : Vanne'); } } class RechercheControllerReservationPickupAjaxNanookPickupLocationsPatronLibraryHoldTest extends RechercheControllerReservationPickupAjaxWithNanookPickupLocationsTestCase { public function setUp() { parent::setUp(); Class_CosmoVar::setValueOf('site_retrait_resa',2); $this->fixture(Class_Bib::class, ['id' => 12, 'libelle' => 'Rennes' ]); $this->nanook->whenCalled('getUserAnnexe')->answers('45') ->whenCalled('reserverExemplaire')->answers(['status' => true, 'erreur' => '']); $this->dispatch('recherche/reservation-pickup-ajax?id_bib=2&id_origine=12&code_annexe=37©_id=12', true); $this->_json = json_decode($this->_response->getBody()); } /** @test */ public function jsonReturnedVotreReservationEstEnregistree() { $this->assertContains($this->_json->content, 'Votre réservation est enregistrée.<br>Nous vous informerons quand le document sera disponible à : Rennes'); } } class RechercheControllerReservationPickupAjaxNanookPickupLocationsPrecheckRequestedTest extends RechercheControllerReservationPickupAjaxWithNanookPickupLocationsTestCase { public function setUp() { parent::setUp(); Class_CosmoVar::setValueOf('site_retrait_resa',1); $this->nanook->whenCalled('getUserAnnexe')->answers('66'); $this->dispatch('recherche/reservation-pickup-ajax?id_bib=2&id_origine=12&code_annexe=37©_id=12', true); $this->_json = json_decode($this->_response->getBody()); } 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 . '"]'); } /** @test */ public function cranShouldBeChecked() { $this->_xpath ->assertXPath($this->_json->content, '//input[@type="radio"][@value="37"][@checked]'); } } class RechercheControllerReservationPickupAjaxNanookPickupLocationsNoPrecheckTest extends RechercheControllerReservationPickupAjaxWithNanookPickupLocationsTestCase { public function setUp() { parent::setUp(); Class_CosmoVar::setValueOf('site_retrait_resa',1); $this->nanook->whenCalled('getUserAnnexe')->answers('66'); $this->dispatch('recherche/reservation-pickup-ajax?id_bib=2&id_origine=12&code_annexe=77©_id=12', true); $this->_json = json_decode($this->_response->getBody()); } /** * @test * @see https://forge.afi-sa.net/issues/128814 */ public function noSiteShouldBePreChecked() { $this->_xpath ->assertNotXPath($this->_json->content, '//input[@type="radio"][@checked]'); } } class RechercheControllerReservationPickupAjaxNanookPickupLocationsStrongInLabel 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=99©_id=12', true); $this->_json = json_decode($this->_response->getBody()); } /** @see https://forge.afi-sa.net/issues/94332 @test */ public function LunelShouldContainStrong() { $this->assertContains($this->_json->content, 'Votre réservation est enregistrée.<br>Nous vous informerons quand le document sera disponible à : Vanne'); } } class RechercheControllerReservationPickupAjaxAndNotifyByMailEnabledTest extends RechercheControllerReservationWithPickupChoiceTestCase { protected $_sent_mails = []; public function setUp() { parent::setUp(); Class_Profil::getCurrentProfil()->setMailSite('admin@example.com'); $int_bib = $this ->fixture('Class_IntBib', ['id' => 1, 'comm_sigb' => Class_IntBib::COM_KOHA_LEGACY, 'use_card_number' => 12345, 'comm_params' => ['url_serveur' => 'http://bib.valensol.net/cgi-bin/koha/ilsdi.pl']]); $bib = $this->fixture(Class_Bib::class, ['id' => 1, 'notify_on_new_resa' => 1, 'mail'=>'adminpukapuka@example.com', 'int_bib' => $int_bib]); $this->fixture(Class_CodifAnnexe::class, ['id' => 34, 'libelle'=>'BDM', 'id_origine' => 23]); $this->jajm = $this ->fixture(Class_Users::class, ['id' => 1, 'login' => 'jajm', 'password' => 'secret', 'nom' => 'Monsieur', 'prenom' => 'Julian', 'idabon' => '00004', 'int_bib' => $int_bib, 'id_sigb' =>'0000007', 'bib' => $bib ]); $this->mock = (new Class_Testing_WebService_SIGB_KohaLegacy_Service()) ->whenCalled('isConnected')->answers(true) ->whenCalled('open_url') ->with('http://bib.valensol.net/cgi-bin/koha/ilsdi.pl?service=HoldTitle&patron_id=0000007&bib_id=13&request_location=127.0.0.1&pickup_location=23') ->answers('<HoldTitle> <title>Mireille l\'abeille</title> <pickup_location>Bibliothèque Départementale de la Meuse</pickup_location> </HoldTitle>') ->whenCalled('reserverExemplaire')->answers(['statut'=>true,'erreur'=>'']); Class_WebService_SIGB_KohaLegacy::setService(['url_serveur' => 'http://bib.valensol.net/cgi-bin/koha/ilsdi.pl', 'id_bib' => 1, 'type' => Class_IntBib::COM_KOHA_LEGACY], $this->mock); ZendAfi_Auth::getInstance()->logUser($this->jajm); $this->fixture(Class_Exemplaire::class, ['id' => 12, 'id_origine' =>13, 'code_barres' =>12341, 'notice'=> $this ->fixture(Class_Notice::class, ['id'=>54, 'titre_principal' => "Mireille l'Abeille", 'type_doc' => Class_TypeDoc::LIVRE]) ]); $mock_transport = new MockMailTransport(); Zend_Mail::setDefaultTransport($mock_transport); $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); $this->_sent_mails = $mock_transport->getSentMails(); } /** @test */ public function parameterCodeAnnexeShouldBeUsedForReservation() { $this->assertEquals('23', $this->mock->getAttributesForLastCallOn('reserverExemplaire')[2]); } /** @test */ public function mailShouldHaveBeenSent() { $this->assertEquals(1, count($this->_sent_mails)); } /** @test */ public function mailSubjectShouldContainsJulianMonsieurSurExemplaire12341() { $this->assertContains("Julian Monsieur ? =?utf-8?Q?sur l'exemplaire 12341", quoted_printable_decode(current($this->_sent_mails)->getSubject())); } /** @test */ public function mailToShouldBeAdminPukaPukaAtExampleDotCom() { $this->assertContains("adminpukapuka@example.com",current($this->_sent_mails)->getRecipients()[0]); } /** @test */ public function mailFromShouldBeMailAdminAtExampleDotCom() { $this->assertContains("admin@example.com",current($this->_sent_mails)->getFrom()); } public function expectedData() { return [['Titre : Mireille l\'Abeille'], ['Annexe de retrait : BDM'], ['Julian Monsieur 00004'], ['Code Barre : 12341'], ['Type de Document : Livres'], ]; } /** * @test * @dataProvider expectedData */ public function mailBodyShouldContainsContent($content) { $this->assertContains($content,quoted_printable_decode(current($this->_sent_mails)->getBodyHtml(true))); } } require_once 'tests/fixtures/KohaFixtures.php'; class RechercheControllerReservationWithWebServiceKohaAndItypesTest extends AbstractControllerTestCase { protected $_xpath; public function setUp() { parent::setUp(); Class_WebService_SIGB_AbstractRESTService::shouldThrowError(true); $koha_service_params = ['url_serveur' => 'http://bib.valensol.net', 'grouped_holds_itypes' => " PRET_MALLE OUT PRET_GLACIERE PRET_VALISE", 'bundled_holds_minimal_duration' => 30, 'bundled_holds_maximal_duration' => 60, 'id_bib' => 1, 'type' => 5]; $bib = $this->fixture('Class_IntBib', ['id' => 1, 'comm_sigb' => Class_IntBib::COM_KOHA_LEGACY, 'comm_params' => $koha_service_params]); $http_client = $this ->mock() ->whenCalled('open_url') ->with('http://bib.valensol.net?service=GetRecords&id=678') ->answers(KohaFixtures::getRecordsWithGroupHoldsItypes()) ->beStrict(); Class_WebService_SIGB_KohaLegacy::getService($koha_service_params) ->setWebClient($http_client); $record = $this->fixture(Class_Notice::class, ['id' => 8890, 'titre_principal' => 'Elementaire mon cher polar', 'auteur_principal' => 'Conan Doyle']); $this->fixture(Class_Exemplaire::class, ['id' => 456, 'id_origine' => 678, 'code_barres' => 5360246264, 'id_int_bib' => 1, 'notice' => $record]); $this->fixture(Class_CodifAnnexe::class, ['id' => 3, 'code' => 'VS', 'id_origine' => 'VS', 'libelle' => 'Cran', 'no_pickup' => '0']); $this->fixture(Class_CodifAnnexe::class, ['id' => 4, 'code' => 'AN', 'id_origine' => 'AN', 'libelle' => 'Annecy', 'no_pickup' => '0']); Class_CosmoVar::setValueOf('site_retrait_resa', 1); $user = $this->fixture('Class_Users', ['id' => 1, 'login' => 'jajm', 'password' => 'secret', 'int_bib' => $bib, 'id_site' => 3, 'idabon' => '395749' ]); $this->_xpath = new Storm_Test_XPath(); ZendAfi_Auth::getInstance()->logUser($user); } /** @test */ public function reservationShouldSelectUserAnnexeByDefault() { $emprunteur = new Class_WebService_SIGB_Emprunteur('395749', 'jajm'); $emprunteur->setLibraryCode('VS'); Class_CommSigb::setInstance(( new Class_Testing_CommSigb) ->whenCalledAnswers('ficheAbonne',[] ,['fiche' => $emprunteur])); $this->dispatch('/recherche/reservation-pickup-ajax/id_bib/1/copy_id/456/code_annexe/AN'); $json = json_decode($this->_response->getBody()); $this->_xpath ->assertXPath($json->content, '//input[@type="radio"][@name="code_annexe"][ @value="VS"][ @checked="checked"]', $json->content); } /** @test */ public function reservationAjaxWithItemRequiringCalendarHoldShouldRedirectToReservationCalendarAjaxWithoutException() { $this->postDispatch('/recherche/reservation-pickup-ajax/id_bib/1/copy_id/456/code_annexe/VS', ['code_annexe' => 'VS']); $this->assertRedirectTo('/recherche/reservationajax/id_bib/1/copy_id/456/code_annexe/VS'); } /** @test */ public function dispatchReservationajaxShouldRenderCalendar() { $this->dispatch('/recherche/reservationajax/id_bib/1/copy_id/456/code_annexe/VS'); $this->assertRedirectTo('/recherche/reservation-calendar-ajax/id_bib/1/copy_id/456/code_annexe/VS'); } }