Pull merge.
[yaffs-website] / web / core / modules / views_ui / tests / src / FunctionalJavascript / PreviewTest.php
1 <?php
2
3 namespace Drupal\Tests\views_ui\FunctionalJavascript;
4
5 use Behat\Mink\Element\NodeElement;
6 use Drupal\Core\Database\Database;
7 use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
8 use Drupal\views\Tests\ViewTestData;
9
10 /**
11  * Tests the UI preview functionality.
12  *
13  * @group views_ui
14  */
15 class PreviewTest extends WebDriverTestBase {
16
17   /**
18    * Views used by this test.
19    *
20    * @var array
21    */
22   public static $testViews = ['test_preview', 'test_pager_full_ajax', 'test_mini_pager_ajax', 'test_click_sort_ajax'];
23
24   /**
25    * {@inheritdoc}
26    */
27   public static $modules = [
28     'node',
29     'views',
30     'views_ui',
31     'views_test_config',
32   ];
33
34   /**
35    * {@inheritdoc}
36    */
37   public function setUp() {
38     parent::setUp();
39
40     ViewTestData::createTestViews(self::class, ['views_test_config']);
41
42     $this->enableViewsTestModule();
43
44     $admin_user = $this->drupalCreateUser([
45       'administer site configuration',
46       'administer views',
47       'administer nodes',
48       'access content overview',
49     ]);
50
51     // Disable automatic live preview to make the sequence of calls clearer.
52     \Drupal::configFactory()->getEditable('views.settings')->set('ui.always_live_preview', FALSE)->save();
53     $this->drupalLogin($admin_user);
54   }
55
56   /**
57    * Sets up the views_test_data.module.
58    *
59    * Because the schema of views_test_data.module is dependent on the test
60    * using it, it cannot be enabled normally.
61    */
62   protected function enableViewsTestModule() {
63     // Define the schema and views data variable before enabling the test module.
64     \Drupal::state()->set('views_test_data_schema', $this->schemaDefinition());
65     \Drupal::state()->set('views_test_data_views_data', $this->viewsData());
66
67     \Drupal::service('module_installer')->install(['views_test_data']);
68     $this->resetAll();
69     $this->rebuildContainer();
70     $this->container->get('module_handler')->reload();
71
72     // Load the test dataset.
73     $data_set = $this->dataSet();
74     $query = Database::getConnection()->insert('views_test_data')
75       ->fields(array_keys($data_set[0]));
76     foreach ($data_set as $record) {
77       $query->values($record);
78     }
79     $query->execute();
80   }
81
82   /**
83    * Returns the schema definition.
84    *
85    * @internal
86    */
87   protected function schemaDefinition() {
88     return ViewTestData::schemaDefinition();
89   }
90
91   /**
92    * Returns the views data definition.
93    */
94   protected function viewsData() {
95     return ViewTestData::viewsData();
96   }
97
98   /**
99    * Returns a very simple test dataset.
100    */
101   protected function dataSet() {
102     return ViewTestData::dataSet();
103   }
104
105   /**
106    * Tests the taxonomy term preview AJAX.
107    *
108    * This tests a specific regression in the taxonomy term view preview.
109    *
110    * @see https://www.drupal.org/node/2452659
111    */
112   public function testTaxonomyAJAX() {
113     \Drupal::service('module_installer')->install(['taxonomy']);
114     $this->getPreviewAJAX('taxonomy_term', 'page_1', 0);
115   }
116
117   /**
118    * Tests pagers in the preview form.
119    */
120   public function testPreviewWithPagersUI() {
121     // Create 11 nodes and make sure that everyone is returned.
122     $this->drupalCreateContentType(['type' => 'page']);
123     for ($i = 0; $i < 11; $i++) {
124       $this->drupalCreateNode();
125     }
126
127     // Test Full Pager.
128     $this->getPreviewAJAX('test_pager_full_ajax', 'default', 5);
129
130     // Test that the pager is present and rendered.
131     $elements = $this->xpath('//ul[contains(@class, :class)]/li', [':class' => 'pager__items']);
132     $this->assertTrue(!empty($elements), 'Full pager found.');
133
134     // Verify elements and links to pages.
135     // We expect to find 5 elements: current page == 1, links to pages 2 and
136     // and 3, links to 'next >' and 'last >>' pages.
137     $this->assertClass($elements[0], 'is-active', 'Element for current page has .is-active class.');
138     $this->assertTrue($elements[0]->find('css', 'a'), 'Element for current page has link.');
139
140     $this->assertClass($elements[1], 'pager__item', 'Element for page 2 has .pager__item class.');
141     $this->assertTrue($elements[1]->find('css', 'a'), 'Link to page 2 found.');
142
143     $this->assertClass($elements[2], 'pager__item', 'Element for page 3 has .pager__item class.');
144     $this->assertTrue($elements[2]->find('css', 'a'), 'Link to page 3 found.');
145
146     $this->assertClass($elements[3], 'pager__item--next', 'Element for next page has .pager__item--next class.');
147     $this->assertTrue($elements[3]->find('css', 'a'), 'Link to next page found.');
148
149     $this->assertClass($elements[4], 'pager__item--last', 'Element for last page has .pager__item--last class.');
150     $this->assertTrue($elements[4]->find('css', 'a'), 'Link to last page found.');
151
152     // Navigate to next page.
153     $elements = $this->xpath('//li[contains(@class, :class)]/a', [':class' => 'pager__item--next']);
154     $this->clickPreviewLinkAJAX($elements[0], 5);
155
156     // Test that the pager is present and rendered.
157     $elements = $this->xpath('//ul[contains(@class, :class)]/li', [':class' => 'pager__items']);
158     $this->assertTrue(!empty($elements), 'Full pager found.');
159
160     // Verify elements and links to pages.
161     // We expect to find 7 elements: links to '<< first' and '< previous'
162     // pages, link to page 1, current page == 2, link to page 3 and links
163     // to 'next >' and 'last >>' pages.
164     $this->assertClass($elements[0], 'pager__item--first', 'Element for first page has .pager__item--first class.');
165     $this->assertTrue($elements[0]->find('css', 'a'), 'Link to first page found.');
166
167     $this->assertClass($elements[1], 'pager__item--previous', 'Element for previous page has .pager__item--previous class.');
168     $this->assertTrue($elements[1]->find('css', 'a'), 'Link to previous page found.');
169
170     $this->assertClass($elements[2], 'pager__item', 'Element for page 1 has .pager__item class.');
171     $this->assertTrue($elements[2]->find('css', 'a'), 'Link to page 1 found.');
172
173     $this->assertClass($elements[3], 'is-active', 'Element for current page has .is-active class.');
174     $this->assertTrue($elements[3]->find('css', 'a'), 'Element for current page has link.');
175
176     $this->assertClass($elements[4], 'pager__item', 'Element for page 3 has .pager__item class.');
177     $this->assertTrue($elements[4]->find('css', 'a'), 'Link to page 3 found.');
178
179     $this->assertClass($elements[5], 'pager__item--next', 'Element for next page has .pager__item--next class.');
180     $this->assertTrue($elements[5]->find('css', 'a'), 'Link to next page found.');
181
182     $this->assertClass($elements[6], 'pager__item--last', 'Element for last page has .pager__item--last class.');
183     $this->assertTrue($elements[6]->find('css', 'a'), 'Link to last page found.');
184
185     // Test Mini Pager.
186     $this->getPreviewAJAX('test_mini_pager_ajax', 'default', 3);
187
188     // Test that the pager is present and rendered.
189     $elements = $this->xpath('//ul[contains(@class, :class)]/li', [':class' => 'pager__items']);
190     $this->assertTrue(!empty($elements), 'Mini pager found.');
191
192     // Verify elements and links to pages.
193     // We expect to find current pages element with no link, next page element
194     // with a link, and not to find previous page element.
195     $this->assertClass($elements[0], 'is-active', 'Element for current page has .is-active class.');
196
197     $this->assertClass($elements[1], 'pager__item--next', 'Element for next page has .pager__item--next class.');
198     $this->assertTrue($elements[1]->find('css', 'a'), 'Link to next page found.');
199
200     // Navigate to next page.
201     $elements = $this->xpath('//li[contains(@class, :class)]/a', [':class' => 'pager__item--next']);
202     $this->clickPreviewLinkAJAX($elements[0], 3);
203
204     // Test that the pager is present and rendered.
205     $elements = $this->xpath('//ul[contains(@class, :class)]/li', [':class' => 'pager__items']);
206     $this->assertTrue(!empty($elements), 'Mini pager found.');
207
208     // Verify elements and links to pages.
209     // We expect to find 3 elements: previous page with a link, current
210     // page with no link, and next page with a link.
211     $this->assertClass($elements[0], 'pager__item--previous', 'Element for previous page has .pager__item--previous class.');
212     $this->assertTrue($elements[0]->find('css', 'a'), 'Link to previous page found.');
213
214     $this->assertClass($elements[1], 'is-active', 'Element for current page has .is-active class.');
215     $this->assertEmpty($elements[1]->find('css', 'a'), 'Element for current page has no link.');
216
217     $this->assertClass($elements[2], 'pager__item--next', 'Element for next page has .pager__item--next class.');
218     $this->assertTrue($elements[2]->find('css', 'a'), 'Link to next page found.');
219   }
220
221   /**
222    * Tests the link to sort in the preview form.
223    */
224   public function testPreviewSortLink() {
225     // Get the preview.
226     $this->getPreviewAJAX('test_click_sort_ajax', 'page_1', 0);
227
228     // Test that the header label is present.
229     $elements = $this->xpath('//th[contains(@class, :class)]/a', [':class' => 'views-field views-field-name']);
230     $this->assertTrue(!empty($elements), 'The header label is present.');
231
232     // Verify link.
233     $this->assertLinkByHref('preview/page_1?_wrapper_format=drupal_ajax&order=name&sort=desc', 0, 'The output URL is as expected.');
234
235     // Click link to sort.
236     $elements[0]->click();
237     $sort_link = $this->assertSession()->waitForElement('xpath', '//th[contains(@class, \'views-field views-field-name is-active\')]/a');
238
239     $this->assertNotEmpty($sort_link);
240
241     // Verify link.
242     $this->assertLinkByHref('preview/page_1?_wrapper_format=drupal_ajax&order=name&sort=asc', 0, 'The output URL is as expected.');
243   }
244
245   /**
246    * Get the preview form and force an AJAX preview update.
247    *
248    * @param string $view_name
249    *   The view to test.
250    * @param string $panel_id
251    *   The view panel to test.
252    * @param int $row_count
253    *   The expected number of rows in the preview.
254    */
255   protected function getPreviewAJAX($view_name, $panel_id, $row_count) {
256     $this->drupalGet('admin/structure/views/view/' . $view_name . '/edit/' . $panel_id);
257     $this->getSession()->getPage()->pressButton('Update preview');
258     $this->assertSession()->assertWaitOnAjaxRequest();
259     $this->assertPreviewAJAX($row_count);
260   }
261
262   /**
263    * Click on a preview link.
264    *
265    * @param \Behat\Mink\Element\NodeElement $element
266    *   The element to click.
267    * @param int $row_count
268    *   The expected number of rows in the preview.
269    */
270   protected function clickPreviewLinkAJAX(NodeElement $element, $row_count) {
271     $element->click();
272     $this->assertSession()->assertWaitOnAjaxRequest();
273     $this->assertPreviewAJAX($row_count);
274   }
275
276   /**
277    * Assert that the preview contains expected data.
278    *
279    * @param int $row_count
280    *   The expected number of rows in the preview.
281    */
282   protected function assertPreviewAJAX($row_count) {
283     $elements = $this->getSession()->getPage()->findAll('css', '.view-content .views-row');
284     $this->assertCount($row_count, $elements, 'Expected items found on page.');
285   }
286
287   /**
288    * Asserts that an element has a given class.
289    *
290    * @param \Behat\Mink\Element\NodeElement $element
291    *   The element to test.
292    * @param string $class
293    *   The class to assert.
294    * @param string $message
295    *   (optional) A verbose message to output.
296    */
297   protected function assertClass(NodeElement $element, $class, $message = NULL) {
298     if (!isset($message)) {
299       $message = "Class .$class found.";
300     }
301     $this->assertTrue(strpos($element->getAttribute('class'), $class) !== FALSE, $message);
302   }
303
304 }