<?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
 */


abstract class CmsControllerCalendarActionTestCase
  extends AbstractControllerTestCase {

  protected $_nanook2;

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

    $this->cfg_accueil =
      ['modules' =>
       [ '1' => [
                 'division' => '1',
                 'type_module' => 'CALENDAR',
                 'preferences' => [
                                   'titre' => 'Rendez-vous',
                                   'rss_avis' => false,
                                   'id_categorie' => '12-2',
                                   'display_cat_select' => true,
                                   'enabled_filters' => 'day;date;place;custom_field_2;custom_field_20;zork;tag',
                                   'display_event_info' => 'none']]],
       'options' =>   []];

    $this->fixture(Class_Profil::class,
                   ['id' => 3,
                    'browser' => 'opac',
                    'libelle' => 'Rendez-vous',
                    'cfg_accueil' => $this->cfg_accueil]);

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

    $this->_nanook2 = $this->fixture(Class_Article::class,
                                     ['id' => 4,
                                      'titre' => 'Nanook 2 en prod !',
                                      'contenu' => 'youpi !',
                                      'events_debut' => '2011-02-17',
                                      'events_fin' => '2011-02-22',
                                      'tags' => 'logiciel']);

    $this->onLoaderOfModel(Class_Article::class)
         ->whenCalled('getArticlesByPreferences')
         ->answers([$this->_nanook2]);
  }


  public function setupCustomFields() {
    $theme = $this->fixture(Class_CustomField::class,
                            ['id' => 2,
                             'priority' => 3,
                             'label' => 'Theme',
                             'field_type' => Class_CustomField_Meta::SELECT,
                             'options_list' => 'sigb;opac',
                             'model' => 'Article']);

    $multi_options = $this->fixture(Class_CustomField::class,
                                    ['id' => 20,
                                     'priority' => 3,
                                     'label' => 'Options "classieuses"',
                                     'field_type' => Class_CustomField_Meta::MULTI_CHECKBOX,
                                     'options_list' => 'wifi;restauration;projection',
                                     'model' => 'Article']);

    $this->fixture(Class_CustomField_Value::class,
                   ['id' => 59,
                    'custom_field_id' => $theme->getId(),
                    'model_id' => $this->_nanook2->getId(),
                    'value' => 'sigb']);

    $this->fixture(Class_CustomField_Value::class,
                   ['id' => 5,
                    'custom_field_id' => $multi_options->getId(),
                    'model_id' => $this->_nanook2->getId(),
                    'value' => 'wifi;restauration']);
  }


  public function tearDown() {
    Class_AdminVar::find('CACHE_ACTIF')->setValeur('0');
    parent::tearDown();
  }
}




class CmsControllerCalendarActionCacheTest
  extends CmsControllerCalendarActionTestCase {

  public function setUp() {
    parent::setUp();
    Storm_Cache::beVolatile();
    $module_cal = new ZendAfi_View_Helper_Accueil_Calendar(1, $this->cfg_accueil['modules']['1']);
    $module_cal->setView(new ZendAfi_Controller_Action_Helper_View());
  }


  /**
   * Test non-regression vu sur Bucarest (prenait le layout normal au lieu du layout iframe)
   * @test
   */
  function calendarShouldNotBeInAnIframeEventWithCacheActive() {
    $this->dispatch('/cms/calendar/id_profil/3/id_module/1/render/ajax');
    // ça plantait lors de la réutilisation du cache, donc 2 dispatchs
    $this->bootstrap();
    $this->dispatch('/cms/calendar/id_profil/3/id_module/1/render/ajax');
    $this->assertNotXPath('//div[@id="site_web_wrapper"]');
  }
}




class CmsControllerCalendarActionLanguageEnTest
  extends CmsControllerCalendarActionTestCase {

  /** @test */
  function ajaxCalendarWithLocaleEnMonthShouldBeFebruary() {
    $this->dispatch('/cms/calendar/id_profil/3/id_module/1/select_id_categorie/2/date/2011-02/language/en/render/ajax');
    $this->assertXPathContentContains('//td[@class="calendar_title_month"]/a', "february");
  }


  /** @test **/
  function ajaxCalendarShouldContains6AwithClassCalendarTitleMonthClickable() {
    $this->dispatch('/cms/calendar/id_profil/3/id_module/1/select_id_categorie/2/date/2011-02/language/en/render/ajax');
    $this->assertXPathCount('//a[@class="calendar_title_month_clickable"]', 6);
  }


  /** @test */
  function calendarWithLocaleEnMonthShouldBeFebruary() {
    $this->dispatch('/cms/calendar/id_profil/3/id_module/1/select_id_categorie/2/date/2011-02/language/en');
    $this->assertXPathContentContains('//div[@class="colContenu layout-division"]//td[@class="calendar_title_month"]/a', "february");
  }


  /** @test **/
  function calendarShouldContains6AwithClassCalendarTitleMonthClickable() {
    $this->dispatch('/cms/calendar/id_profil/3/id_module/1/select_id_categorie/2/date/2011-02/language/en');
    $this->assertXPathCount('//div[@class="colContenu layout-division"]//a[@class="calendar_title_month_clickable"]',
                            6);
  }
}




class CmsControllerCalendarActionWithMultipleFiltersTest
  extends CmsControllerCalendarActionTestCase {

  protected $_permaculture;

  public function setupCustomFields() {
    Class_CustomField_Meta::beVolatile();
    $theme = $this->fixture(Class_CustomField::class,
                            ['id' => 2,
                             'priority' => 3,
                             'label' => 'Theme',
                             'field_type' => Class_CustomField_Meta::MULTI_CHECKBOX,
                             'options_list' => 'culture;bd;logiciels libres',
                             'model' => 'Article']);

    $multi_options = $this->fixture(Class_CustomField::class,
                                    ['id' => 20,
                                     'priority' => 3,
                                     'label' => 'Options',
                                     'field_type' => Class_CustomField_Meta::MULTI_CHECKBOX,
                                     'options_list' => 'wifi;jardinage;projection',
                                     'model' => 'Article']);

    $this->fixture(Class_CustomField_Value::class,
                   ['id' => 59,
                    'custom_field_id' => $theme->getId(),
                    'model_id' => $this->_nanook2->getId(),
                    'value' => ';logiciels libres;']);

    $this->fixture(Class_CustomField_Value::class,
                   ['id' => 5,
                    'custom_field_id' => $multi_options->getId(),
                    'model_id' => $this->_permaculture->getId(),
                    'value' => ';jardinage;']);

    $this->fixture(Class_CustomField_Value::class,
                   ['id' => 2,
                    'custom_field_id' => $theme->getId(),
                    'model_id' => $this->_permaculture->getId(),
                    'value' => ';culture;bd;']);
  }


  public function setUp() {
    parent::setUp();
    $this->_permaculture = $this->fixture(Class_Article::class,
                                          ['id' => 5,
                                           'titre' => 'Liberons la permaculture !',
                                           'contenu' => 'Venez avec vos poireaux !',
                                           'events_debut' => '2011-02-17',
                                           'events_fin' => '2011-02-22',
                                           'tags' => '']);
    $this->setupCustomFields();

    $common_preferences = ['display_order' => 'EventDebut',
                           'id_categorie' => '12-2',
                           'events_only' => true,
                           'id_bib' => 0,
                           'id_lieu' => '',
                           'published' =>true,
    ];

    $time_source = new TimeSourceForTest('2014-06-06 14:14:14');
    ZendAfi_View_Helper_CalendarContent::setTimeSource($time_source);
    ZendAfi_View_Helper_Calendar_Months::setTimeSource($time_source);

    Class_Article::getLoader()
      ->whenCalled('getArticlesByPreferences')
      ->with(array_merge($common_preferences, [ 'custom_fields' => [2 => [0 => 'culture'],
                                                                    20 => [0 => 'jardinage']],
                                               'published' =>true,'event_date' => '2014-07']))
      ->answers([$this->_permaculture])

      ->whenCalled('getArticlesByPreferences')
      ->with(array_merge($common_preferences, ['event_date' => '2014-07',
                                               'custom_fields' => [2 => [0 => 'logiciels libres']]]))
      ->answers([$this->_permaculture])
      ->whenCalled('getArticlesByPreferences')
      ->with(array_merge($common_preferences, ['event_date' => '',
                                               'custom_fields' => [2 => [0 => 'culture'],
                                                                   20 => [0 => 'jardinage']],
                                               'event_start_after' => '2014-07',
                                               'event_end_after' => '',
                                               'limit' => 3]))

      ->answers([])
      ->whenCalled('getArticlesByPreferences')
      ->with(array_merge($common_preferences, ['event_date' => '',
                                               'custom_fields' => [2 => [0 => 'logiciels libres']],
                                               'event_start_after' => '2014-07',
                                               'event_end_after' => '',
                                               'limit' => 3]))
      ->answers([])
      ->beStrict();
  }


  /** @test */
  public function articlePermacultureShouldBeDisplayWithOptionSelected() {
    $this->dispatch('/cms/calendar/id_profil/3/id_module/1/date/2014-07/custom_field_2/culture/custom_field_20/jardinage/render/ajax');
    $this->assertXPathContentContains('//a[@class="calendar_event_title"]', 'Liberons la permaculture !');
  }


  /** @test */
  public function articleNanookShouldNotBeDisplayWithOptionSelected() {
    $this->dispatch('/cms/calendar/id_profil/3/id_module/1/date/2014-07/custom_field_2/culture/custom_field_20/jardinage/render/ajax');
    $this->assertNotXPathContentContains('//a[@class="calendar_event_title"]', 'Nanook 2 en prod !');
  }


  /** @test */
  public function articleNanookShouldBeDisplayWithLLSelected() {
    $this->dispatch('/cms/calendar/id_profil/3/id_module/1/date/2014-07/custom_field_2/logiciels libres/render/ajax');
    $this->assertNotXPathContentContains('//a[@class="calendar_event_title"]', 'Nanook 2 en prod !');
  }
}




abstract class CmsControllerCalendarActionWithFiltersTestCase
  extends CmsControllerCalendarActionTestCase  {

  protected
    $_opac4,
    $_date,
    $_common_preferences;

  public function setUp() {
    parent::setUp();
    $this->_opac4 = $this->fixture(Class_Article::class,
                                   ['id' => 5,
                                    'titre' => 'OPAC 4 en prod !',
                                    'contenu' => 'youpi !',
                                    'events_debut' => '2014-07-17',
                                    'events_fin' => '2014-07-18']);
    $this->setupCustomFields();

    $this->_common_preferences = ['display_order' => 'EventDebut',
                                  'id_categorie' => '12-2',
                                  'events_only' => true,
                                  'id_bib' => 0,
                                  'id_lieu' => '',
                                  'custom_fields' => [2 =>[0 => 'opac']],
                                  'published' => true];

    $time_source = new TimeSourceForTest('2014-06-06 14:14:14');
    ZendAfi_View_Helper_CalendarContent::setTimeSource($time_source);
    ZendAfi_View_Helper_Calendar_Months::setTimeSource($time_source);
  }
}




class CmsControllerCalendarActionWithFiltersDateTest
  extends CmsControllerCalendarActionWithFiltersTestCase {

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

    Class_Article::getLoader()
      ->whenCalled('getArticlesByPreferences')
      ->with(array_merge($this->_common_preferences, ['event_date' => '2014-07']))
      ->answers([$this->_opac4])

      ->whenCalled('getArticlesByPreferences')
      ->with(array_merge($this->_common_preferences, ['event_date' => '',
                                                      'event_start_after' => '2014-07',
                                                      'event_end_after' => '',
                                                      'limit' => 3]))
      ->answers([])
      ->beStrict();

    $this->dispatch('/cms/calendar/id_profil/3/id_module/1/date/2014-07/custom_field_2/opac/render/ajax');
  }


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

    $this->fixture(Class_CustomField_Value::class,
                   ['id' => 2,
                    'custom_field_id' => 2,
                    'model_id' => 5,
                    'value' => 'opac']);
  }


  /** @test */
  public function articleOpacShouldBeDisplayed() {
    $this->assertXPathContentContains('//a[@class="calendar_event_title"]', 'OPAC 4 en prod !');
  }


  /** @test */
  public function calendarFilterOnMonthShouldNotContainsLinkToResetDate() {
    $expected = '/custom_field_2/opac';
    $this->assertNotXPathContentContains('//li[@data-id="date"]//a["' . $expected. '"=substring(@href, string-length(@href)-' . (strlen($expected)-1) .')]',
                                         'Tous');
  }


  /** @test **/
  public function calendarWithCustomFieldFiltersShouldBuildPreferencesForGetArticlesByPreferences() {
    $this->assertXPathContentContains('//a[@class="calendar_event_title"]',
                                      'OPAC 4 en prod !');
  }


  /** @test */
  public function monthFilterShouldContainsCustomField2Music() {
    $this->assertXPathContentContains('//li[@class="date"]//li[not(@class="selected")]/a[contains(@href, "/cms/calendar/id_module/1/custom_field_2/opac/date/2014-11")]',
                                      'Novembre');
  }


  /** @test */
  public function selectedMonthFilterShouldHaveClassSelected() {
    $this->assertXPath('//li[@class="date"]//li[@class="selected"]/a[contains(@href, "/cms/calendar/id_module/1/custom_field_2/opac/date/2014-07")]');
  }


  /** @test */
  public function themeFilterShouldContainsDate() {
    $this->assertXPathContentContains('//li[@class="custom_field_2"]//li//a[contains(@href, "/cms/calendar/id_module/1/custom_field_2/sigb/date/2014-07")]', 'sigb');
  }


  /** @test */
  public function themeFilterHeaderShouldBeThemeOPAC() {
    $this->assertXPathContentContains('//li[@class="custom_field_2"]/h2[contains(text(), "Theme")]/span', ': opac');
  }


  /** @test */
  public function optionFilterHeaderShouldBeDisplayed() {
    $this->assertXPathContentContains('//li[@class="custom_field_20"]/h2', 'Options');
  }


  /** @test */
  public function optionFilterShouldContainsWifi() {
    $this->assertXPath('//li[@class="custom_field_20"]//li//input[@value="wifi"][contains(@data-url, "/cms/calendar/id_module/1/custom_field_2/opac/date/2014-07/custom_field_20/wifi")]');
  }


  /** @test */
  public function optionFilterShouldContainsRestauration() {
    $this->assertXPath('//li[@class="custom_field_20"]//li//input[@value="restauration"][contains(@data-url, "/cms/calendar/id_module/1/custom_field_2/opac/date/2014-07/custom_field_20/restauration")]');
  }


  /** @test */
  public function optionFilterShouldNotContainsProjection() {
    $this->assertNotXPathContentContains('//li[@class="custom_field_20"]//li//a[contains(@href, "/cms/calendar/id_module/1/custom_field_2/opac/date/2014-07/custom_field_20/projection")]',
                                         'projection');
  }


  /** @test */
  public function monthFilterShouldHaveTitleMoisJuillet() {
    $this->assertXPathContentContains('//ul[contains(@class, "filters")]/li[@class="date"]/h2[text()="Mois"]/span',
                                      ' : Juillet');
  }


  /** @test */
  public function linkNextMonthShouldContainsDayParameterAndDateParameter() {
    $this->assertXPath('//a[@class="calendar_title_month_clickable"][contains(@href,"/day/2014-08")][contains(@href, "/date/2014-08")]');
  }


  /** @test */
  public function linkPreviousMonthContainsDayAndDateParameters() {
    $this->assertXPath('//a[@class="calendar_title_month_clickable"][contains(@href,"/day/2014-06")][contains(@href, "/date/2014-06")]');
  }


  /** @test */
  public function linkCurrentMonthContainsDayParameter() {
    $this->assertXPath('//a[@class="calendar_title_month_clickable"][contains(@href,"/day/2014-07")][contains(@href,"/cms/calendar")]');
  }


  /** @test */
  public function linkInsideCalendarShouldContainsDayButNoDateParameters() {
    $this->assertXPath('//a[contains(@class,"day_clickable")][contains(@href,"/day/2014-07-17")][not(contains(@href, "/date/"))]');
  }
}




class CmsControllerCalendarActionWithFiltersDateAndNoCalendarTest
  extends CmsControllerCalendarActionWithFiltersTestCase {

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

    Class_Article::getLoader()
      ->whenCalled('getArticlesByPreferences')
      ->with(array_merge($this->_common_preferences, ['event_date' => '2014-07']))
      ->answers([$this->_opac4])

      ->whenCalled('getArticlesByPreferences')
      ->with(array_merge($this->_common_preferences, ['event_date' => '',
                                                      'event_start_after' => '2014-07',
                                                      'event_end_after' => '',
                                                      'limit' => 3]))
      ->answers([])
      ->beStrict();

    $profil = Class_Profil::find(3);
    $cfg_accueil = $profil->getCfgAccueilAsArray();
    $cfg_accueil['modules'][1]['preferences']['display_calendar'] = '0';
    $profil->setCfgAccueil($cfg_accueil)->assertSave();

    $this->dispatch('/cms/calendar/id_profil/3/id_module/1/date/2014-07/custom_field_2/opac/render/ajax');
  }


  /** @test */
  public function calendarFilterOnMonthShouldContainsLinkToResetDate() {
    $expected = '/custom_field_2/opac';
    $this->assertXPathContentContains('//li[@data-id="date"]//a["' . $expected. '"=substring(@href, string-length(@href)-' . (strlen($expected)-1) .')]',
                                      'Tous');
  }
}




class CmsControllerCalendarActionWithFiltersDayTest
  extends CmsControllerCalendarActionWithFiltersTestCase {

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

    Class_Article::getLoader()
      ->whenCalled('getArticlesByPreferences')
      ->with(array_merge($this->_common_preferences, ['event_date' => '2014-07']))
      ->answers([$this->_opac4])

      ->whenCalled('getArticlesByPreferences')
      ->with(array_merge($this->_common_preferences, ['event_date' => '2014-07-12']))
      ->answers([$this->_opac4])
      ->beStrict();

    $this->dispatch('/cms/calendar/id_profil/3/id_module/1/day/2014-07-12/custom_field_2/opac/render/ajax');
  }


  /** @test */
  public function articleOpacShouldBeDisplayed() {
    $this->assertXPathContentContains('//a[@class="calendar_event_title"]', 'OPAC 4 en prod !');
  }


  /** @test */
  public function selectedMonthFilterShouldNotHaveDayParam() {
    $this->assertXPath('//li[@class="date"]//li/a[contains(@href, "/date/2014-07")][not(contains(@href, "/day/"))]');
  }
}




class CmsControllerCalendarActionWithDayTest extends AbstractControllerTestCase {

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

    $cfg_accueil = ['modules' =>
                    [ '1' => [
                              'division' => '1',
                              'type_module' => 'CALENDAR',
                              'preferences' => ['mode-affichage' => 'article',
                                                'display_full_page' => 0]]],
                    'options' =>  []];

    $this->fixture(Class_Profil::class,
                   ['id' => 3,
                    'browser' => 'opac',
                    'libelle' => 'Plop',
                    'cfg_accueil' => $cfg_accueil]);

    $this->fixture(Class_Article::class,
                   ['id' => 5,
                    'titre' => 'News of the 15th September',
                    'contenu' => 'youpi !',
                    'events_debut' => '2014-09-15',
                    'events_fin' => '2014-09-15']);

    $this->fixture(Class_Article::class,
                   ['id' => 2,
                    'titre' => 'News of the 30th September',
                    'contenu' => 'youpi !',
                    'events_debut' => '2014-09-28',
                    'events_fin' => '2014-09-30']);

    $time_source = new TimeSourceForTest('2014-09-02 14:14:14');
    ZendAfi_View_Helper_CalendarContent::setTimeSource($time_source);
    ZendAfi_View_Helper_Calendar_Table::setTimeSource($time_source);

    $this->onLoaderOfModel(Class_Article::class)
         ->whenCalled('getArticlesByPreferences')
         ->with(['display_order' => 'EventDebut',
                 'id_categorie' => '',
                 'events_only' => true,
                 'event_date' => '2014-09',
                 'id_bib' => 0,
                 'id_lieu' => '',
                 'custom_fields' => [],
                 'published' => true])
         ->answers([Class_Article::find(2), Class_Article::find(5)])

         ->whenCalled('getArticlesByPreferences')
         ->with(['display_order' => 'EventDebut',
                 'id_categorie' => '',
                 'events_only' => true,
                 'event_date' => '2014-09',
                 'id_bib' => 0,
                 'id_lieu' => '',
                 'custom_fields' => [],
                 'published' => true,
                 'event_end_after' => '2014-09-02'])
         ->answers([Class_Article::find(2), Class_Article::find(5)])

         ->whenCalled('getArticlesByPreferences')
         ->with(['display_order' => 'EventDebut',
                 'id_categorie' => '',
                 'events_only' => true,
                 'event_date' => '',
                 'id_bib' => 0,
                 'id_lieu' => '',
                 'custom_fields' => [],
                 'published' => true,
                 'event_start_after' => '2014-09',
                 'event_end_after' => '',
                 'limit' => 3])
         ->answers([Class_Article::find(2), Class_Article::find(5)])

         ->whenCalled('getArticlesByPreferences')
         ->with(['display_order' => 'EventDebut',
                 'id_categorie' => '',
                 'events_only' => true,
                 'event_date' => '2014-09-30',
                 'id_bib' => 0,
                 'id_lieu' => '',
                 'custom_fields' => [],
                 'published' => true])
         ->answers([Class_Article::find(2)]);


    $this->dispatch('cms/calendar/date/2014-09-30/id_profil/3/id_module/1/opac/render/ajax');
  }


  /** @test */
  public function currentMonthLinkShouldHaveReadyAjaxClass() {
    $this->assertXPath('//table[@class="calendar_main"]//td[@class="calendar_title_month"]//a[contains(@class, "calendar_ajax_ready")]');
  }


  /** @test */
  public function newsOfThe30thShouldBePresent() {
    $this->assertXPathContentContains('//div[@class="calendar"]//article//header//h2//a', 'News of the 30th September');
  }


  /** @test **/
  public function newsOfThe15ThSeptemberEventShouldNotBPresent() {
    $this->assertNotXPathContentContains('//div[@id="boite_1"][@class="calendar"]//article//header', 'News of the 15th September');
  }


  /** @test */
  public function newsOfThe15thSeptemberShouldBeClickableAtThe15Th() {
    $this->assertXPath('//div[@class="calendar"]//table//a[contains(@class, "day_clickable")][contains(@href, "date/2014-09-15")]');
  }
}




class CmsControllerCalendarActionHeaderTest extends AbstractControllerTestCase {

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

    $cfg_accueil = [
                    'modules' => [
                                  '1' => [
                                          'division' => '1',
                                          'type_module' => 'CALENDAR',
                                          'preferences' => [
                                                            'titre' => 'Rendez-vous',
                                                            'rss_avis' => false,
                                                            'id_categorie' => '12-2',
                                                            'display_cat_select' => true,
                                                            'enabled_filters' => 'date;place;custom_field_2;zork',
                                                            'display_event_info' => 'none',
                                          ]
                                  ]
                    ],
                    'options' => []
    ];

    $this->onLoaderOfModel(Class_Article::class)
         ->whenCalled('getArticlesByPreferences')
         ->answers([]);

    $this->fixture(Class_Profil::class,
                   ['id' => 4,
                    'browser' => 'opac',
                    'libelle' => 'Rendez-vous',
                    'cfg_accueil' => $cfg_accueil]);

    $this->dispatch('/index/index/id_profil/4');
  }


  /** @test */
  public function calendarHeaderShouldContainsThreeLinks() {
    $this->assertXPathCount('//td[@class="calendar_title_month"]/a', 3);
    $this->assertXPathContentContains('//td[@class="calendar_title_month"]/a[1]', '«');
    $this->assertXPathContentContains('//td[@class="calendar_title_month"]/a[3]', '»');
  }
}




class CmsControllerCalendarActionWithIdItemsTest extends AbstractControllerTestCase {

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

    $cfg_accueil = [
                    'modules' => [
                                  '1' => [
                                          'division' => '1',
                                          'type_module' => 'CALENDAR',
                                          'preferences' => [
                                                            'titre' => 'Rendez-vous',
                                                            'rss_avis' => false,
                                                            'id_categorie' => '12-2',
                                                            'id_items' => '100-102',
                                                            'display_cat_select' => true,
                                                            'enabled_filters' => 'date;place;custom_field_2;zork',
                                                            'display_event_info' => 'none',
                                          ]
                                  ]
                    ],
                    'options' => []
    ];

    $time_source = new TimeSourceForTest('2021-12-14 09:00:00');
    ZendAfi_View_Helper_Calendar_Table::setTimeSource($time_source);
    ZendAfi_View_Helper_CalendarContent::setTimeSource($time_source);
    Class_Calendar::setTimeSource($time_source);

    $this->fixture(Class_Article::class,
                   ['id' => 100,
                    'titre' => 'Les toiles de Nathalie Novi',
                    'events_debut' => '2021-12-01',
                    'events_fin' => '2021-12-31',
                    'categorie' => '',
                    'contenu' => 'L\'ensemble des oeuvres de Nathalie Novi'
                   ]);

    $this->fixture(Class_Article::class,
                   ['id' => 101,
                    'titre' => 'Sécurité',
                    'events_debut' => '2021-12-01',
                    'events_fin' => '2021-12-31',
                    'categorie' => '',
                    'contenu' => 'Se protéger contre les spywhare'
                   ]);

    $this->fixture(Class_Article::class,
                   ['id' => 102,
                    'titre' => 'Exposition Nathalie Novi',
                    'events_debut' => '2021-12-01',
                    'events_fin' => '2021-12-31',
                    'categorie' => '',
                    'contenu' => 'Toutes les expositions de l\'artiste'
                   ]);

    $this->fixture(Class_Profil::class,
                   ['id' => 4,
                    'browser' => 'opac',
                    'libelle' => 'Rendez-vous',
                    'cfg_accueil' => $cfg_accueil]);

    $callback = function ($preferences){
      if (isset($preferences['id_items'])
          && ($preferences['id_items'] === "100-102"))
        return [Class_Article::find(100),
                Class_Article::find(102)];
      return [Class_Article::find(100),
              Class_Article::find(101),
              Class_Article::find(102)];
    };

    $this->onLoaderOfModel(Class_Article::class)
         ->whenCalled('getArticlesByPreferences')
         ->willDo($callback);

    $this->dispatch('/index/index/id_profil/4');
  }


  /** @test */
  public function agendaShouldDisplayToilesNathalieNovi() {
    $this->assertXPathContentContains('//a[@class = "calendar_event_title"]', 'Les toiles de Nathalie Novi');
  }


  /** @test */
  public function agendaShouldDisplayExpositionNathalieNovi() {
    $this->assertXPathContentContains('//a[@class = "calendar_event_title"]', 'Exposition Nathalie Novi');
  }


  /** @test */
  public function agendaShouldNotContainsSecurite() {
    $this->assertNotXPathContentContains('//a[@class = "calendar_event_title"]', 'Sécurité');
  }
}




class CmsControllerCalendarActionAjaxLinkTest extends AbstractControllerTestCase {

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

    $cfg_accueil = [
                    'modules' => [
                                  '1' => [
                                          'division' => '1',
                                          'type_module' => 'CALENDAR',
                                          'preferences' => [
                                                            'titre' => 'Rendez-vous',
                                                            'rss_avis' => false,
                                                            'id_categorie' => '12-2',
                                                            'display_cat_select' => true,
                                                            'enabled_filters' => 'date;place;custom_field_2;zork',
                                                            'display_event_info' => 'none',
                                                            'display_full_page' => 1
                                          ]
                                  ]
                    ],
                    'options' => []
    ];

    $this->fixture(Class_Profil::class,
                   ['id' => 5,
                    'browser' => 'opac',
                    'libelle' => 'Rendez-vous',
                    'cfg_accueil' => $cfg_accueil]);

    $time_source = new TimeSourceForTest('2014-09-02 14:14:14');
    ZendAfi_View_Helper_CalendarContent::setTimeSource($time_source);
    ZendAfi_View_Helper_Calendar_Table::setTimeSource($time_source);
    Class_Calendar::setTimeSource($time_source);

    $this->onLoaderOfModel(Class_Article::class)
         ->whenCalled('getArticlesByPreferences')
         ->answers([$this->fixture(Class_Article::class,
                                   ['id' => 25,
                                    'titre' => 'News of the 30th September',
                                    'contenu' => 'youpi !',
                                    'events_debut' => '2014-09-28',
                                    'events_fin' => '2014-09-30'])]);

    $this->dispatch('/index/index/id_profil/5');
  }


  /** @test */
  public function calendarDayLinkShouldNotContainsRenderAjax() {
    $this->assertXPath('//td//a[@class="calendar_day_non_clickable day_clickable calendar_day_event_start "][not(contains(@href, "/render/ajax"))]');
  }
}




abstract class CmsControllerCalendarActionFixturesTestCase
  extends CmsControllerCalendarActionTestCase {

  protected $_articles_by_pref = [];

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

    $this->annecy = $this->fixture('Class_Lieu',
                                   ['id' => '41',
                                    'libelle' => 'Annecy',
                                    'adresse' => 'Rue des tomates',
                                    'code_postal' => '74000',
                                    'latitude' => '47.0999715',
                                    'longitude' => '5.4883906']);

    $this->category_news = $this->fixture('Class_ArticleCategorie',
                                          ['id' => 24, 'libelle' => 'News']);

    $this->category_events = $this->fixture('Class_ArticleCategorie',
                                            ['id' => 12,
                                             'parent_categorie' => $this->category_news,
                                             'libelle' => 'Evenement']);

    $this->category_workshop = $this->fixture('Class_ArticleCategorie',
                                              ['id' => 13, 'libelle' => 'Atelier']);

    $this->_prepareFixtures();

    $this->setupCustomFields();

    $time_source = new TimeSourceForTest('2017-11-06 14:14:14');
    ZendAfi_View_Helper_CalendarContent::setTimeSource($time_source);
    ZendAfi_View_Helper_Calendar_Months::setTimeSource($time_source);

    Class_Article::getLoader()
      ->whenCalled('getArticlesByPreferences')
      ->answers($this->_articles_by_pref);

    $this->_dispatch();
  }


  protected function _prepareFixtures() {}


  protected function _dispatch() {
    $this->dispatch('/cms/ical');
  }
}




abstract class CmsControllerCalendarActionIcalExportTestCase
  extends CmsControllerCalendarActionFixturesTestCase {

  protected $_ical = '';

  public function setUp(){
    parent::setUp();
    $this->_ical = $this->_response->getBody();
  }


  /** @test */
  public function contentTypeHeaderShouldBeTextCalendarUtf8() {
    $this->assertHeaderContains('Content-Type', 'text/calendar;charset=utf-8');
  }


  /** @test */
  public function contentDispositionShouldBeAttachment() {
    $this->assertHeaderContains('Content-Disposition', 'attachment');
  }


  /** @test */
  public function vCalendarShouldBegin() {
    $this->assertContains('BEGIN:VCALENDAR', $this->_ical);
  }


  /** @test */
  public function vCalendarShouldEnd() {
    $this->assertContains('END:VCALENDAR', $this->_ical);
  }


  /** @test */
  public function prodidShouldBeBokehLibraryPortal() {
    $this->assertContains('PRODID:http://bokeh-library-portal.org', $this->_ical);
  }


  /** @test */
  public function versionShouldBe2Dot0() {
    $this->assertContains('VERSION:2.0', $this->_ical);
  }


  /** @test */
  public function vEventShouldBegin() {
    $this->assertContains('BEGIN:VEVENT', $this->_ical);
  }


  /** @test */
  public function vEventShouldEnd() {
    $this->assertContains('END:VEVENT', $this->_ical);
  }
}




class CmsControllerCalendarActionIcalExportSimpleTest
  extends CmsControllerCalendarActionIcalExportTestCase {

  protected function _prepareFixtures () {
    $capsule = $this->fixture(Class_Article::class,
                              ['id' => 42,
                               'titre' => 'CAPSULE TEMPORELLE 2017-2054',
                               'contenu' => 'Curieux envers l\'avenir ?',
                               'lieu' => $this->annecy,
                               'all_day' => 0,
                               'pick_day' => '',
                               'categorie' => $this->category_workshop,
                               'events_debut' => '2018-03-04 15:05',
                               'events_fin' => '2018-03-04 17:17',
                               'tags' => 'geek;science']);

    $this->_articles_by_pref = [ $capsule ];
  }


  /** @test */
  public function uidShouldBe42() {
    $this->assertContains('UID:42', $this->_ical);
  }


  /** @test */
  public function startDateShouldBe2018_03_04_15_05InEuropeParis() {
    $this->assertContains('DTSTART;TZID=Europe/Paris:20180304T150500',
                          $this->_ical);
  }


  /** @test */
  public function endDateShouldBe2018_03_04_17_17InEuropeParis() {
    $this->assertContains('DTEND;TZID=Europe/Paris:20180304T171700',
                          $this->_ical);
  }


  /** @test */
  public function categoriesShouldBeSlashAtelier() {
    $this->assertContains('CATEGORIES:/Atelier', $this->_ical);
  }


  /** @test */
  public function locationShouldBeAnnecy() {
    $this->assertContains('LOCATION:Annecy', $this->_ical);
  }


  /** @test */
  public function geoLocationShouldBeLat47Long5() {
    $this->assertContains('GEO:47.099972;5.488391', $this->_ical);
  }


  /** @test */
  public function descriptionShouldBeCurieuxEnversLAvenir() {
    $this->assertContains('DESCRIPTION:Curieux envers l\'avenir', $this->_ical);
  }


  /** @test */
  public function summaryShouldBeCapsuleTemporelle() {
    $this->assertContains('SUMMARY:CAPSULE TEMPORELLE 2017-2054', $this->_ical);
  }


  /** @test */
  public function shouldNotHaveRecurrence() {
    $this->assertNotContains('RRULE:', $this->_ical);
  }


  /** @test */
  public function shouldNotHaveCustomField() {
    $this->assertNotContains('X-BOKEH-CUSTOMFIELD', $this->_ical);
  }


  /** @test */
  public function tagsShouldBeGeekScience() {
    $this->assertContains('X-BOKEH-TAGS:geek;science', $this->_ical);
  }


  /** @test */
  public function shouldNotHaveAttach() {
    $this->assertNotContains('ATTACH:', $this->_ical);
  }


  /** @test */
  public function urlShouldContainsUrlToArticle42() {
    $this->assertContains('/cms/articleview/id_profil/1/id/42', $this->_ical);
  }
}




abstract class AbstractCmsControllerCalendarActionOpenagendaExportTestCase
  extends CmsControllerCalendarActionFixturesTestCase {

  protected $_json_content = [];

  public function setUp() {
    parent::setUp();
    $this->_json_content = json_decode($this->_response->getBody(), true);
  }


  protected function _dispatch(){
    $this->dispatch('cms/openagenda');
  }
}




class CmsControllerCalendarActionOpenagendaExportEmptyDataTest
  extends AbstractCmsControllerCalendarActionOpenagendaExportTestCase {

  /** @test */
  public function headerContentTypeShouldContainsApplicationJson() {
    $this->assertHeaderContains('Content-type', 'application/json');
  }


  /** @test */
  public function withEmptyPrefsJsonContentShouldBeEmpty() {
    $this->assertEmpty($this->_json_content);
  }
}




class CmsControllerCalendarActionOpenagendaExportSimpleTest
  extends AbstractCmsControllerCalendarActionOpenagendaExportTestCase {

  protected function _prepareFixtures() {
    $this->setupCustomFields();
    $this->_nanook2
      ->setCustomField('Theme', 'sigb')
      ->setCustomField('Options "classieuses"', ['wifi','restauration'])
      ->saveWithCustomFields();

    $this->_nanook2
      ->setLieu($this->annecy)
      ->setTags('Jeunesse;Interface')
      ->setDescription('Une super description <img src="/userfiles/images/descrimage.png">')
      ->setContenu('youpi ! <img src="/userfiles/images/youpimage.png" />')
      ->setDateMaj('2018-06-12 12:47:36')
      ->assertSave();

    $this->_articles_by_pref = [$this->_nanook2];
  }


  /** @test */
  public function headerContentTypeShouldContainsApplicationJson() {
    $this->assertHeaderContains('Content-type', 'application/json');
  }


  /** @test */
  public function uidShouldBe4() {
    $this->assertEquals(4, $this->_json_content[0]['uid']);
  }


  /** @test */
  public function titleShouldContainsNanook2EnProd() {
    $this->assertContains('Nanook 2 en prod', $this->_json_content[0]['title']);
  }


  /** @test */
  public function htmlShouldContainsYoupi() {
    $this->assertContains('youpi !', $this->_json_content[0]['html']);
  }


  /** @test */
  public function imgInHtmlShouldHaveAbsoluteUrl() {
    $this->assertContains('http://localhost/userfiles/images/youpimage.png', $this->_json_content[0]['html']);
  }

  /** @test */
  public function descriptionShouldContainsSuperDescription() {
    $this->assertContains('super description', $this->_json_content[0]['description']);
  }


  /** @test */
  public function imgInDescriptionShouldHaveAbsoluteUrl() {
    $this->assertContains('http://localhost/userfiles/images/descrimage.png', $this->_json_content[0]['description']);
  }


  /** @test */
  public function updatedAtShouldBeFoo2018_06_12() {
    $this->assertEquals('2018-06-12T12:47:36+02:00',
                        $this->_json_content[0]['updatedAt']);
  }


  /** @test */
  public function firstDateShouldContains20110217() {
    $this->assertEquals('2011-02-17', $this->_json_content[0]['firstDate']);
  }


  /** @test */
  public function firstTimeStartShouldBeMidnight() {
    $this->assertEquals('00:00', $this->_json_content[0]['firstTimeStart']);
  }


  /** @test */
  public function lastDateShouldContains20110222() {
    $this->assertEquals('2011-02-22', $this->_json_content[0]['lastDate']);
  }


  /** @test */
  public function lastTimeEndShouldBeMidnight() {
    $this->assertEquals('00:00', $this->_json_content[0]['lastTimeEnd']);
  }


  /** @test */
  public function timingsShouldContains20110222() {
    $this->assertEquals(['start' => '2011-02-17T00:00:00+01:00',
                         'end'   => '2011-02-22T00:00:00+01:00'],
                        $this->_json_content[0]['timings']);
  }


  /** @test */
  public function locationShouldBeAnnecy() {
    $annecy_place = ['uid' => '41',
                     'name' => 'Annecy',
                     'address' => 'Rue des tomates',
                     'postalCode' => '74000',
                     'latitude' => '47.0999715',
                     'longitude' => '5.4883906',
                     'country' => 'FRANCE'];

    $this->assertEquals($annecy_place,
                        $this->_json_content[0]['location']);
  }


  /** @test */
  public function tagGroupsTagsFromCustomFieldThemeShouldContainsSigb() {
    $this->assertEquals('sigb', $this->_json_content[0]['tagGroups'][0]['tags'][0]);
  }


  /** @test */
  public function tagGroupsNameFromCustomFieldThemeShouldContainsTheme() {
    $this->assertEquals('Theme', $this->_json_content[0]['tagGroups'][0]['name']);
  }


  /** @test */
  public function tagGroupsUidFromCustomFieldThemeShouldContainsTheme() {
    $this->assertEquals( 2 , $this->_json_content[0]['tagGroups'][0]['uid']);
  }


  /** @test */
  public function keywordsFromTagsShouldContainsJeunesse() {
    $this->assertContains('Jeunesse', $this->_json_content[0]['keywords']);
  }


  /** @test */
  public function keywordsFromCustomValuesWithExistingTagsShouldContainsSemiColonSigb() {
    $this->assertContains(';sigb', $this->_json_content[0]['keywords']);
  }
}




class CmsControllerCalendarActionIcalExportSimpleRecurrentTest
  extends CmsControllerCalendarActionIcalExportTestCase {

  protected function _prepareFixtures () {
    $capsule = $this->fixture(Class_Article::class,
                              ['id' => 42,
                               'titre' => 'CAPSULE TEMPORELLE 2017-2054',
                               'contenu' => 'Curieux envers l\'avenir ?',
                               'lieu' => $this->annecy,
                               'all_day' => 0,
                               'pick_day' => '1,3,0',
                               'categorie' => $this->category_workshop,
                               'events_debut' => '2018-03-04 15:05',
                               'events_fin' => '2018-05-15 17:30']);

    $this->_articles_by_pref = [ $capsule ];
  }


  /** @test */
  public function startDateShouldBe2018_03_04_15_05InEuropeParis() {
    $this->assertContains('DTSTART;TZID=Europe/Paris:20180304T150500',
                          $this->_ical);
  }


  /** @test */
  public function endDateShouldBeStartDateAtEndTimeInEuropeParis() {
    $this->assertContains('DTEND;TZID=Europe/Paris:20180304T173000',
                          $this->_ical);
  }


  /** @test */
  public function recurrenceShouldBeWeeklyUntil2018_05_15WithoutTime() {
    $this->assertContains('RRULE:FREQ=WEEKLY;INTERVAL=1;UNTIL=20180515T000000Z;BYDAY=MO,WE,SU',
                          $this->_ical);
  }
}




class CmsControllerCalendarActionIcalExportRecurrentAllDayTest
  extends CmsControllerCalendarActionIcalExportTestCase {

  protected function _prepareFixtures () {
    $opac4 = $this->fixture(Class_Article::class,
                            ['id' => 5,
                             'titre' => 'OPAC 4 en prod !',
                             'contenu' => '<h3>youpi &amp; oui c&#39;est beau !</h3><img src="/userfiles/images/youpi.png">',
                             'lieu' => $this->annecy,
                             'all_day' => 1,
                             'pick_day' => '1,3,0',
                             'categorie' => $this->category_events,
                             'events_debut' => '2018-02-17',
                             'events_fin' => '2018-02-22']);

    $this->_articles_by_pref = [ $opac4 ];
  }


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

    $this->fixture(Class_CustomField_Value::class,
                   ['id' => 2,
                    'custom_field_id' => 2,
                    'model_id' => 5,
                    'value' => 'opac']);
  }


  /** @test */
  public function uidShouldBe5() {
    $this->assertContains('UID:5', $this->_ical);
  }


  /** @test */
  public function startDateShouldBe2018_02_17() {
    $this->assertContains('DTSTART;VALUE=DATE:20180217', $this->_ical);
  }


  /** @test */
  public function endDateShouldNotBePresent() {
    $this->assertNotContains('DTEND', $this->_ical);
  }


  /** @test */
  public function categoriesShouldBeSlashNewsSlashEvenement() {
    $this->assertContains('CATEGORIES:/News/Evenement', $this->_ical);
  }


  /** @test */
  public function locationShouldBeAnnecy() {
    $this->assertContains('LOCATION:Annecy', $this->_ical);
  }


  /** @test */
  public function geoLocationShouldBeLat47Long5() {
    $this->assertContains('GEO:47.099972;5.488391', $this->_ical);
  }


  /** @test */
  public function descriptionShouldBeYoupiWithoutHtml() {
    $this->assertContains('DESCRIPTION:youpi & oui c\'est beau !', $this->_ical);
  }


  /** @test */
  public function xAltDescShouldBeYoupiWithHtml() {
    $this->assertContains('X-ALT-DESC;FMTTYPE=text/html:<h3>youpi &amp\;', $this->_ical);
  }


  /** @test */
  public function summaryShouldBeOpac4EnProd() {
    $this->assertContains('SUMMARY:OPAC 4 en prod !', $this->_ical);
  }


  /** @test */
  public function recurrenceShouldBeWeeklyMondayWenesdaySundayUntil2018_02_22() {
    $this->assertContains('RRULE:FREQ=WEEKLY;INTERVAL=1;UNTIL=20180222T000000Z;BYDAY=MO,WE,SU',
                          $this->_ical);
  }


  /** @test */
  public function themeCustomFieldShouldContainsOpac() {
    $this->assertContains("X-BOKEH-CUSTOMFIELD;NAME=Theme:opac", $this->_ical);
  }


  /** @test */
  public function attachShouldContainsYoupiImage() {
    $this->assertContains('ATTACH;X-BKH-=IMAGE:http://' . $_SERVER['HTTP_HOST'] . BASE_URL . '/userfiles/images/youpi.png', $this->_ical);
  }


  /** @test */
  public function urlShouldContainsUrlToArticle5() {
    $this->assertContains('/cms/articleview/id_profil/1/id/5', $this->_ical);
  }
}




class CmsControllerCalendarActionWithOutDateTest extends AbstractControllerTestCase {

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

    $time_source = new TimeSourceForTest('2014-09-02 14:14:14');
    ZendAfi_View_Helper_CalendarContent::setTimeSource($time_source);
    ZendAfi_View_Helper_Calendar_Table::setTimeSource($time_source);
    Class_Calendar::setTimeSource($time_source);

    $kitchen = $this->fixture(Class_Article::class,
                              ['id' => 1,
                               'titre' => 'Kitchen',
                               'contenu' => 'Cook',
                               'event_fin' => '2014-09-18',
                               'event_debut' => '2014-09-16']);

    $this->onLoaderOfModel(Class_Article::class)
         ->whenCalled('getArticlesByPreferences')
         ->with(['display_order' => 'EventDebut',
                 'id_categorie' => '',
                 'events_only' => true,
                 'event_date' => '2014-09',
                 'id_bib' => 0,
                 'id_lieu' => '',
                 'custom_fields' => [],
                 'published' => true,
                 'event_end_after' => '2014-09-02'])
         ->answers([$kitchen])

         ->whenCalled('getArticlesByPreferences')
         ->with(['display_order' => 'EventDebut',
                 'id_categorie' => '',
                 'events_only' => true,
                 'event_date' => '',
                 'id_bib' => 0,
                 'id_lieu' => '',
                 'custom_fields' => [],
                 'published' => true,
                 'event_start_after' => '2014-09',
                 'event_end_after' => ''])
         ->answers([])

         ->whenCalled('getArticlesByPreferences')
         ->with(['display_order' => 'EventDebut',
                 'id_categorie' => '',
                 'events_only' => true,
                 'event_date' => '2014-09',
                 'id_bib' => 0,
                 'id_lieu' => '',
                 'custom_fields' => [],
                 'published' => true])
         ->answers([$kitchen])

         ->beStrict();

    Class_AdminVar::set('CACHE_ACTIF', '1');
    Storm_Cache::beVolatile();

    $this->dispatch('/cms/calendar/render/ajax');
  }


  /** @test */
  public function getArticleByPreferencesShouldBeCallWithEventDateAfter() {
    $this->assertXPathContentContains('//div', 'Kitchen');
  }


  /** @test */
  public function ajaxCalendarContentShouldBeCached() {
    $this->bootstrap();
    Class_Article::getLoader()
      ->clearAllRedirections()
      ->whenCalled('getArticlesByPreferences')
      ->never();
    $this->dispatch('/cms/calendar/render/ajax');
    $this->assertXPathContentContains('//div', 'Kitchen');
  }
}




class CmsControllerCalendarActionIcalExportOneArticleByIdTest
  extends CmsControllerCalendarActionIcalExportTestCase {

  protected function _prepareFixtures () {
    $this->fixture(Class_Article::class,
                   ['id' => 5,
                    'titre' => 'OPAC 4 en prod !',
                    'contenu' => '<h3>youpi &amp; oui c&#39;est beau !</h3><img src="/userfiles/images/youpi.png">',
                    'lieu' => $this->annecy,
                    'all_day' => 1,
                    'pick_day' => '1,3,0',
                    'categorie' => $this->category_events,
                    'events_debut' => '2018-02-17',
                    'events_fin' => '2018-02-22']);
  }


  protected function _dispatch() {
    $this->dispatch('/cms/ical/id_article/5');
  }


  public function descriptionShouldBeYoupiWithoutHtml() {
    $this->assertContains('DESCRIPTION:youpi & oui c\'est beau !', $this->_ical);
  }


  /** @test */
  public function xAltDescShouldBeYoupiWithHtml() {
    $this->assertContains('X-ALT-DESC;FMTTYPE=text/html:<h3>youpi &amp\;', $this->_ical);
  }


  /** @test */
  public function summaryShouldBeOpac4EnProd() {
    $this->assertContains('SUMMARY:OPAC 4 en prod !', $this->_ical);
  }
}




class CmsControllerCalendarDuplicateDayDueToHourChangeTest
  extends CmsControllerCalendarActionTestCase {

  public function setUp() {
    parent::setUp();
    ZendAfi_View_Helper_CalendarContent::setTimeSource(new TimeSourceForTest('2018-09-03 00:00:00'));
    $this->dispatch('/cms/calendar/date/2018-10/render/ajax');
  }


  public function tearDown() {
    ZendAfi_View_Helper_CalendarContent::setTimeSource(null);
    parent::tearDown();
  }


  /** @test */
  function day28ShouldBeDisplayOnlyOnce() {
    $this->assertXPathCount('//td/span[contains(text(), "28")]', 1);
  }
}




class CmsControllerCalenderWithAllCatSelectedAndIdCategorieSetTest
  extends CmsControllerCalendarActionTestCase {

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

    $this->onLoaderOfModel(Class_Article::class)
         ->whenCalled('getArticlesByPreferences')
         ->with(['display_order' => 'EventDebut',
                 'id_categorie' => '12-2',
                 'events_only' => true,
                 'event_date' => '2018-09',
                 'id_bib' => 0,
                 'id_lieu' => '',
                 'custom_fields' => [],
                 'published' => true,
                 'event_end_after' => '2018-09-03'])
         ->answers([$this->_nanook2]);

    ZendAfi_View_Helper_CalendarContent::setTimeSource(new TimeSourceForTest('2018-09-03 00:00:00'));
    $this->dispatch('/cms/calendar/id_profil/3/id_module/1/select_id_categorie/all');
  }


  public function tearDown() {
    ZendAfi_View_Helper_CalendarContent::setTimeSource(null);
    parent::tearDown();
  }


  /** @test */
  function shouldDisplayArticleNanook2() {
    $this->assertXPathContentContains('//div', 'Nanook 2 en prod !');
  }
}




class CmsControllerCalenderWithAllCatSelectedAndIdCategorieEmptyTest
  extends CmsControllerCalendarActionTestCase {

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

    $this->cfg_accueil =
      ['modules' =>
       [ '1' => [
                 'division' => '1',
                 'type_module' => 'CALENDAR',
                 'preferences' => [
                                   'titre' => 'Rendez-vous',
                                   'rss_avis' => false,
                                   'id_categorie' => '',
                                   'display_cat_select' => true,
                                   'enabled_filters' => 'day;date;place;custom_field_2;custom_field_20;zork',
                                   'display_event_info' => 'none']]],
       'options' =>   []];

    $this->fixture(Class_Profil::class,
                   ['id' => 3,
                    'browser' => 'opac',
                    'libelle' => 'Rendez-vous',
                    'cfg_accueil' => $this->cfg_accueil]);

    $this->onLoaderOfModel(Class_Article::class)
         ->whenCalled('getArticlesByPreferences')
         ->with(['display_order' => 'EventDebut',
                 'id_categorie' => '',
                 'events_only' => true,
                 'event_date' => '2018-09',
                 'id_bib' => 0,
                 'id_lieu' => '',
                 'custom_fields' => [],
                 'published' => true,
                 'event_end_after' => '2018-09-03'])
         ->answers([$this->_nanook2]);

    ZendAfi_View_Helper_CalendarContent::setTimeSource(new TimeSourceForTest('2018-09-03 00:00:00'));
    $this->dispatch('/cms/calendar/id_profil/3/id_module/1/select_id_categorie/all');
  }


  public function tearDown() {
    ZendAfi_View_Helper_CalendarContent::setTimeSource(null);
    parent::tearDown();
  }


  /** @test */
  function shouldDisplayArticleNanook2() {
    $this->assertXPathContentContains('//div', 'Nanook 2 en prod !');
  }
}




class CmsControllerCalendarActionWithFiltersTagTest
  extends CmsControllerCalendarActionTestCase {

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

    Class_Article::getLoader()
      ->whenCalled('getArticlesByPreferences')
      ->with(['tag' => 'logiciel',
              'display_order' => 'EventDebut',
              'id_categorie' => '12-2',
              'events_only' => true,
              'event_date' => '2011-02',
              'id_bib' => 0,
              'id_lieu' => '',
              'custom_fields' => [],
              'published' => false])
      ->answers([$this->_nanook2])

      ->whenCalled('getArticlesByPreferences')
      ->with(['tag' => 'logiciel',
              'display_order' => 'EventDebut',
              'id_categorie' => '12-2',
              'events_only' => true,
              'event_date' => '',
              'id_bib' => 0,
              'id_lieu' => '',
              'custom_fields' => [],
              'published' => false,
              'event_start_after' => '2011-02',
              'event_end_after' => '',
              'limit' => 3])
      ->answers([$this->_nanook2])

      ->beStrict();

    $this->dispatch('/cms/calendar/id_profil/3/id_module/1/tag/logiciel/date/2011-02/render/ajax');
  }


  /** @test */
  public function responseShouldContainsArticleNanook() {
    $this->assertXPathContentContains('//a[@class="calendar_event_title"]', 'Nanook 2 en prod !');
  }
}




class CmsControllerCalendarActionFullTest extends AbstractControllerTestCase {

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

    $cfg_accueil =
      ['modules' =>
       [ '1' => [
                 'division' => '1',
                 'type_module' => 'CALENDAR',
                 'preferences' => [
                                   'titre' => 'Calendrier',
                                   'id_categorie' => 30,
                                   'display_cat_select' => false,
                                   'display_event_info' => 'bib',
                                   'rss_avis' => false,
                                   'ical_feed' => true,
                                   'display_next_event' => true,
                                   'display_order' => 'EventDebut',
                                   'display_mode' => 'FullArticle',
                                   'display_full_page' => true,
                                   'nb_events' => 0,
                                   'display_calendar' => true,
                                   'mode-affichage' => 'simple',
                                   'layout' => 'grid',
                                   'event_filter' => 'none',
                                   'id_module' => 1,
                                   'profile_id' => 3,
                                   'styles_reload' => true]]],
       'options' =>   []];

    $this->fixture(Class_Profil::class,
                   ['id' => 3,
                    'browser' => 'opac',
                    'libelle' => 'Rendez-vous',
                    'cfg_accueil' => $cfg_accueil]);

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

    $nanook2 = $this->fixture(Class_Article::class,
                              ['id' => 4,
                               'titre' => 'Nanook 2 en prod !',
                               'contenu' => 'youpi !',
                               'events_debut' => '2011-02-17',
                               'events_fin' => '2011-02-22',
                               'tags' => 'logiciel']);

    $this->onLoaderOfModel(Class_Article::class)
         ->whenCalled('getArticlesByPreferences')
         ->answers([$nanook2]);

    $this->dispatch('/cms/calendar/id_profil/3/id_module/1/select_id_categorie/all/date/2011-02/render/ajax');
  }


  public function tearDown() {
    Class_AdminVar::find('CACHE_ACTIF')->setValeur('0');
    parent::tearDown();
  }


  /** @test */
  public function onChangeMonthCalendarShouldDisplayUrlDayWithoutContext() {
    $this->assertXPath('//a[@href="/cms/articleviewbydate/d/2011-02-17/id_module/1/id_profil/3/select_id_categorie/all"]');
  }
}




class CmsControllerCalendarActionWallTest extends AbstractControllerTestCase {

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

    $cfg_accueil =
      ['modules' =>
       [ '1' => [
                 'division' => '1',
                 'type_module' => 'CALENDAR',
                 'preferences' => [
                                   'titre' => 'Calendrier',
                                   'id_categorie' => 30,
                                   'display_cat_select' => false,
                                   'display_event_info' => 'bib',
                                   'rss_avis' => false,
                                   'ical_feed' => true,
                                   'display_next_event' => true,
                                   'display_order' => 'EventDebut',
                                   'display_mode' => 'FullArticle',
                                   'display_full_page' => true,
                                   'nb_events' => 15,
                                   'display_calendar' => true,
                                   'mode-affichage' => 'wall',
                                   'layout' => 'grid',
                                   'event_filter' => 'none',
                                   'id_module' => 1,
                                   'profile_id' => 3,
                                   'styles_reload' => true]]],
       'options' =>   []];

    $this->fixture(Class_Profil::class,
                   ['id' => 3,
                    'browser' => 'opac',
                    'libelle' => 'Rendez-vous',
                    'cfg_accueil' => $cfg_accueil]);

    $nanook2 = $this->fixture(Class_Article::class,
                              ['id' => 4,
                               'titre' => 'Nanook 2 en prod !',
                               'contenu' => 'youpi !',
                               'description' => 'youpi !',
                               'contenu' => 'youpi !',
                               'events_debut' => '2011-02-17',
                               'events_fin' => '2011-02-22',
                               'tags' => 'logiciel']);

    $this->onLoaderOfModel(Class_Article::class)
         ->whenCalled('getArticlesByPreferences')
         ->answers([$nanook2]);

    $this->dispatch('/cms/calendar/id_profil/3/id_module/1/date/2011-02/render/ajax');
  }


  /** @test */
  public function articleTitleLinkShouldDisplayUrlWithoutContext() {
    $this->assertXPath('//span[@class="title"]/a[@href="/cms/articleview/id/4"]');
  }


  /** @test */
  public function lirelArticleLinkShouldBeDirectAccessToArticle() {
    $this->assertXPath('//a[@href="/cms/articleview/id/4"][@class="article_read_full"]');
  }
}