3 namespace Drupal\Tests\views\Functional\Plugin;
5 use Drupal\dynamic_page_cache\EventSubscriber\DynamicPageCacheSubscriber;
6 use Drupal\Tests\views\Functional\ViewTestBase;
7 use Drupal\views\Entity\View;
10 * Tests the table style views plugin.
14 class StyleTableTest extends ViewTestBase {
17 * Views used by this test.
21 public static $testViews = ['test_table'];
26 protected function setUp($import_test_views = TRUE) {
27 parent::setUp($import_test_views);
29 $this->enableViewsTestModule();
33 * Test table caption/summary/description.
35 public function testAccessibilitySettings() {
36 $this->drupalGet('test-table');
38 $result = $this->xpath('//caption/child::text()');
39 $this->assertTrue(count($result), 'The caption appears on the table.');
40 $this->assertEqual(trim($result[0]->getText()), 'caption-text');
42 $result = $this->xpath('//summary/child::text()');
43 $this->assertTrue(count($result), 'The summary appears on the table.');
44 $this->assertEqual(trim($result[0]->getText()), 'summary-text');
46 $result = $this->xpath('//caption/details/child::text()');
47 $this->assertTrue(count($result), 'The table description appears on the table.');
48 $this->assertEqual(trim($result[0]->getText()), 'description-text');
50 // Remove the caption and ensure the caption is not displayed anymore.
51 $view = View::load('test_table');
52 $display = &$view->getDisplay('default');
53 $display['display_options']['style']['options']['caption'] = '';
56 $this->drupalGet('test-table');
57 $result = $this->xpath('//caption/child::text()');
58 $this->assertFalse(trim($result[0]->getText()), 'Ensure that the caption disappears.');
60 // Remove the table summary.
61 $display = &$view->getDisplay('default');
62 $display['display_options']['style']['options']['summary'] = '';
65 $this->drupalGet('test-table');
66 $result = $this->xpath('//summary/child::text()');
67 $this->assertFalse(count($result), 'Ensure that the summary disappears.');
69 // Remove the table description.
70 $display = &$view->getDisplay('default');
71 $display['display_options']['style']['options']['description'] = '';
74 $this->drupalGet('test-table');
75 $result = $this->xpath('//caption/details/child::text()');
76 $this->assertFalse(count($result), 'Ensure that the description disappears.');
80 * Test table fields in columns.
82 public function testFieldInColumns() {
83 $this->drupalGet('test-table');
85 // Ensure that both columns are in separate tds.
86 // Check for class " views-field-job ", because just "views-field-job" won't
87 // do: "views-field-job-1" would also contain "views-field-job".
88 // @see Drupal\system\Tests\Form\ElementTest::testButtonClasses().
89 $result = $this->xpath('//tbody/tr/td[contains(concat(" ", @class, " "), " views-field-job ")]');
90 $this->assertTrue(count($result), 'Ensure there is a td with the class views-field-job');
91 $result = $this->xpath('//tbody/tr/td[contains(concat(" ", @class, " "), " views-field-job-1 ")]');
92 $this->assertTrue(count($result), 'Ensure there is a td with the class views-field-job-1');
94 // Combine the second job-column with the first one, with ', ' as separator.
95 $view = View::load('test_table');
96 $display = &$view->getDisplay('default');
97 $display['display_options']['style']['options']['columns']['job_1'] = 'job';
98 $display['display_options']['style']['options']['info']['job']['separator'] = ', ';
101 // Ensure that both columns are properly combined.
102 $this->drupalGet('test-table');
104 $result = $this->xpath('//tbody/tr/td[contains(concat(" ", @class, " "), " views-field-job views-field-job-1 ")]');
105 $this->assertTrue(count($result), 'Ensure that the job column class names are joined into a single column');
107 $result = $this->xpath('//tbody/tr/td[contains(., "Drummer, Drummer")]');
108 $this->assertTrue(count($result), 'Ensure the job column values are joined into a single column');
112 * Test that a number with the value of "0" is displayed in the table.
114 public function testNumericFieldVisible() {
115 // Adds a new datapoint in the views_test_data table to have a person with
117 $data_set = $this->dataSet();
118 $query = db_insert('views_test_data')
119 ->fields(array_keys($data_set[0]));
121 'name' => 'James McCartney',
124 'created' => gmmktime(6, 30, 10, 1, 1, 2000),
129 $this->drupalGet('test-table');
131 $result = $this->xpath('//tbody/tr/td[contains(., "Baby")]');
132 $this->assertTrue(count($result), 'Ensure that the baby is found.');
134 $result = $this->xpath('//tbody/tr/td[text()=0]');
135 $this->assertTrue(count($result), 'Ensure that the baby\'s age is shown');
139 * Test that empty columns are hidden when empty_column is set.
141 public function testEmptyColumn() {
142 // Empty the 'job' data.
143 \Drupal::database()->update('views_test_data')
144 ->fields(['job' => ''])
147 $this->drupalGet('test-table');
149 // Test that only one of the job columns still shows.
150 $result = $this->xpath('//thead/tr/th/a[text()="Job"]');
151 $this->assertEqual(count($result), 1, 'Ensure that empty column header is hidden.');
153 $result = $this->xpath('//tbody/tr/td[contains(concat(" ", @class, " "), " views-field-job-1 ")]');
154 $this->assertEqual(count($result), 0, 'Ensure the empty table cells are hidden.');
158 * Tests grouping by a field.
160 public function testGrouping() {
161 /** @var \Drupal\views\ViewEntityInterface $view */
162 $view = \Drupal::entityTypeManager()->getStorage('view')->load('test_table');
163 // Get a reference to the display configuration so we can alter some
164 // specific style options.
165 $display = &$view->getDisplay('default');
166 // Set job as the grouping field.
167 $display['display_options']['style']['options']['grouping'][0] = [
170 'rendered_strip' => FALSE,
172 // Clear the caption text, the rendered job field will be used as a caption.
173 $display['display_options']['style']['options']['caption'] = '';
174 $display['display_options']['style']['options']['summary'] = '';
175 $display['display_options']['style']['options']['description'] = '';
178 // Add a record containing unsafe markup to be sure it's filtered out.
179 $unsafe_markup = '<script>alert("Rapper");</script>';
180 $unsafe_markup_data = [
181 'name' => 'Marshall',
183 'job' => $unsafe_markup,
184 'created' => gmmktime(0, 0, 0, 2, 15, 2001),
187 $database = $this->container->get('database');
188 $database->insert('views_test_data')
189 ->fields(array_keys($unsafe_markup_data))
190 ->values($unsafe_markup_data)
193 $this->drupalGet('test-table');
194 $expected_captions = [
199 'Job: ' . $unsafe_markup,
202 // Ensure that we don't find the caption containing unsafe markup.
203 $this->assertNoRaw($unsafe_markup, "Didn't find caption containing unsafe markup.");
205 // Ensure that all expected captions are found.
206 foreach ($expected_captions as $raw_caption) {
207 $this->assertEscaped($raw_caption);
210 $display = &$view->getDisplay('default');
211 // Remove the label from the grouping field.
212 $display['display_options']['fields']['job']['label'] = '';
215 $this->drupalGet('test-table');
216 $expected_captions = [
224 // Ensure that we don't find the caption containing unsafe markup.
225 $this->assertNoRaw($unsafe_markup, "Didn't find caption containing unsafe markup.");
227 // Ensure that all expected captions are found.
228 foreach ($expected_captions as $raw_caption) {
229 $this->assertEscaped($raw_caption);
234 * Tests the cacheability of the table display.
236 public function testTableCacheability() {
237 \Drupal::service('module_installer')->uninstall(['page_cache']);
240 $this->drupalGet($url);
241 $this->assertSession()->statusCodeEquals(200);
242 $this->assertEquals('MISS', $this->drupalGetHeader(DynamicPageCacheSubscriber::HEADER));
243 $this->drupalGet($url);
244 $this->assertEquals('HIT', $this->drupalGetHeader(DynamicPageCacheSubscriber::HEADER));