crossword-8.x-1.x-dev/tests/src/FunctionalJavascript/CrosswordPseudofieldsTest.php
tests/src/FunctionalJavascript/CrosswordPseudofieldsTest.php
<?php
namespace Drupal\Tests\crossword\FunctionalJavascript;
/**
* Tests the real pseudofields, not just the formatter.
*
* @group crossword
*/
class CrosswordPseudofieldsTest extends CrosswordFormatterTestBase {
/**
* {@inheritdoc}
*/
protected $formatter = 'crossword_pseudofields';
/**
* {@inheritdoc}
*/
protected static $modules = ['crossword_pseudofields_tests'];
/**
* Tests pseudofields when redacted.
*
* Mostly we are testing that errors are not shown and that the cheat and
* solution button don't do anything.
*/
public function testCrosswordFormatterRedacted() {
$node = $this->createTestNode();
$this->assertEquals(1, $node->id());
// View the crossword node.
$this->drupalGet("crossword-tests/1/{$this->formatter}/redacted");
$assertSession = $this->assertSession();
$session = $this->getSession();
$page = $session->getPage();
// Check for presence of various test.
$assertSession->elementTextContains('css', '.crossword-title', "Test Puzzle");
$assertSession->elementTextContains('css', '.crossword-author', "Test Author");
// Check initial active clue.
$assertSession->elementTextContains('css', '#active-clues', "Three-A Second square has a circle");
// Click on bottom left square. Check that active clues update.
$square = $page->find('css', '[data-col="0"][data-row="2"]');
$input = $page->find('css', '[data-col="0"][data-row="2"] input');
$clue_across = $page->find('css', '.crossword-clue[data-clue-index-across="1"]');
$clue_down = $page->find('css', '.crossword-clue[data-clue-index-down="0"]');
$square->click();
$this->assertTrue($square->hasClass('active'));
$this->assertTrue($clue_across->hasClass('active'));
$this->assertFalse($clue_down->hasClass('active'));
$assertSession->elementTextContains('css', '#active-clues', "Five-A Has a reference to 3-Across and 1-Down");
$assertSession->elementTextContains('css', '#active-clues', "Three-A Second square has a circle");
$assertSession->elementTextContains('css', '#active-clues', "One-D is AB2");
// Check the aria text.
$expected_aria_label = '5 across. Five-A Has a reference to 3-Across and 1-Down. 3 letters.';
$this->assertEquals($input->getAttribute('aria-label'), $expected_aria_label);
// Check that errors are not marked with class or in aria text.
// The real fill value is TWO.
$this->assertFalse($square->hasClass('error'));
$this->assertFalse($clue_across->hasClass('error'));
$square->click();
$input->setValue('b');
$assertSession->elementTextContains('css', '[data-col="0"][data-row="2"] .square-fill', 'B');
$this->assertFalse($square->hasClass('error'));
$this->assertFalse($clue_across->hasClass('error'));
// Click twice to trigger aria update.
$square->click();
$square->click();
// Check the aria text.
$expected_aria_label = '5 across. Five-A Has a reference to 3-Across and 1-Down. Answer: 3 letters. B. blank. blank.';
$this->assertEquals($input->getAttribute('aria-label'), $expected_aria_label);
// Show errors and check again.
$page->find('css', '#show-errors')->click();
$square->click();
$square->click();
$expected_aria_label = '5 across. Five-A Has a reference to 3-Across and 1-Down. Answer: 3 letters. B. blank. blank.';
$this->assertEquals($input->getAttribute('aria-label'), $expected_aria_label);
$page->find('css', '#show-errors')->click();
// Click on left middle square. Correct fill is B.
$square = $page->find('css', '[data-col="0"][data-row="1"]');
$input = $page->find('css', '[data-col="0"][data-row="1"] input');
// Cheat button shouldn't do anything.
$page->find('css', '.button-cheat')->click();
$this->assertFalse($square->hasClass('cheat'));
$this->assertFalse($input->hasClass('cheat'));
$assertSession->elementTextNotContains('css', '[data-col="0"][data-row="1"] .square-fill', 'B');
// Test that solution button doesn't do anything.
$assertSession->elementNotExists('css', '.crossword.crossword-solved, body.crossword-solved');
$assertSession->elementNotExists('css', '.crossword.crossword-revealed, body.crossword-revealed');
$assertSession->pageTextNotContains('Well done!');
$page->find('css', '.button-solution')->click();
$session->getDriver()->getWebDriverSession()->accept_alert();
$assertSession->elementNotExists('css', '.crossword.crossword-solved, body.crossword-solved');
$assertSession->elementNotExists('css', '.crossword.crossword-revealed, body.crossword-revealed');
$assertSession->pageTextNotContains('Well done!');
$assertSession->elementTextNotContains('css', '[data-col="0"][data-row="1"] .square-fill', 'B');
}
/**
* Test with no clue list.
*
* When there are no clue dom nodes, the active clues works differently.
* We just need to do a quick check.
*/
public function testWithNoClueList() {
$config = \Drupal::service('config.factory')->getEditable('core.entity_view_display.node.crossword.default');
$content = $config->get('content');
unset($content['crossword_across']);
unset($content['crossword_down']);
$config->set('content', $content);
$config->save();
$node = $this->createTestNode();
$this->assertEquals(1, $node->id());
// View the crossword node.
$this->drupalGet("crossword-tests/1/{$this->formatter}");
$assertSession = $this->assertSession();
$session = $this->getSession();
$page = $session->getPage();
// Confirm clues are not listed.
$assertSession->pageTextNotContains('Across');
$assertSession->pageTextNotContains('Down');
// Check initial active clue.
$assertSession->elementTextContains('css', '#active-clues', "Three-A Second square has a circle");
// Click on bottom left square. Check that active clues update.
$square = $page->find('css', '[data-col="0"][data-row="2"]');
$input = $page->find('css', '[data-col="0"][data-row="2"] input');
$square->click();
$this->assertTrue($square->hasClass('active'));
$assertSession->elementTextContains('css', '#active-clues', "Five-A Has a reference to 3-Across and 1-Down");
$assertSession->elementTextContains('css', '#active-clues', "Three-A Second square has a circle");
$assertSession->elementTextContains('css', '#active-clues', "One-D is AB2");
// Uncheck references. Make sure active clues update.
$page->find('css', '#show-references')->click();
$assertSession->elementTextContains('css', '#active-clues', "Five-A Has a reference to 3-Across and 1-Down");
$assertSession->elementTextNotContains('css', '#active-clues', "Three-A Second square has a circle");
$assertSession->elementTextNotContains('css', '#active-clues', "One-D is AB2");
}
/**
* Check that special behavior with no clue list is safe.
*/
public function testWithNoClueListXss() {
$this->testPuzzleFilename = 'xss.txt';
$config = \Drupal::service('config.factory')->getEditable('core.entity_view_display.node.crossword.default');
$content = $config->get('content');
unset($content['crossword_across']);
unset($content['crossword_down']);
$config->set('content', $content);
$config->save();
$node = $this->createTestNode();
$this->assertEquals(1, $node->id());
// Rest is copied from CrosswordFormatterXssTest::testCrosswordFormatter().
// View the crossword node.
$this->drupalGet("crossword-tests/1/{$this->formatter}");
$assertSession = $this->assertSession();
$session = $this->getSession();
$page = $session->getPage();
// Confirm clues are not listed.
$assertSession->pageTextNotContains('Across');
$assertSession->pageTextNotContains('Down');
// These is attempted XSS all over this puzzle. If it causes an alert
// to appear at any time, there would end up being an UnexpectedAlertOpen
// and the test would err out. If we get to the end and everything passes
// then we know no alert ever appeared. Let's start!
// Make sure the attempted Xss text is on the page.
$assertSession->pageTextContains("alert('Xss Title');");
$assertSession->pageTextContains("alert('Xss Author');");
$assertSession->pageTextContains("alert('Xss Notepad');");
// Click on top right square and cheat.
// This square is un-crossed so direction changes to down.
$square = $page->find('css', '[data-col="2"][data-row="0"]');
$square->click();
$page->find('css', '.button-cheat')->click();
$assertSession->pageTextContains("alert('Xss Letter');");
// Click (twice) on 3-Across and see clue.
$square = $page->find('css', '[data-col="0"][data-row="1"]');
$square->click();
$square->click();
$assertSession->elementTextContains('css', '#active-clues', "alert('Xss Clue');");
// Click on 5-Across and see reference.
$square = $page->find('css', '[data-col="0"][data-row="2"]');
$square->click();
$assertSession->elementTextContains('css', '#active-clues', "alert('Xss Reference');");
// Just for fun, do an active test of alert presence.
try {
$session->getDriver()->getWebDriverSession()->getAlert_text();
$exception = NULL;
}
catch (\Exception $e) {
$exception = $e;
}
$this->assertEquals('WebDriver\Exception\NoAlertOpenError', get_class($exception));
// Reload to examine local storage.
$this->drupalGet("crossword-tests/1/{$this->formatter}");
$assertSession = $this->assertSession();
$session = $this->getSession();
$assertSession->pageTextContains("alert('Xss Letter');");
try {
$session->getDriver()->getWebDriverSession()->getAlert_text();
$exception = NULL;
}
catch (\Exception $e) {
$exception = $e;
}
$this->assertEquals('WebDriver\Exception\NoAlertOpenError', get_class($exception));
}
/**
* Test clue toggle.
*/
public function testCluesToggle() {
$node = $this->createTestNode();
$this->assertEquals(1, $node->id());
// View the crossword node at its normal path.
// Allows us to test non-default config.
$this->drupalGet('node/1');
$assertSession = $this->assertSession();
$session = $this->getSession();
$page = $session->getPage();
// By default, there is no clue toggling and clues are visible.
$assertSession->elementNotExists('css', '#show-clues');
$assertSession->elementExists('css', '.crossword-clues.across');
$assertSession->elementExists('css', '.crossword-clues.down');
// Add the toggle button, initially unchecked.
$config = \Drupal::service('config.factory')->getEditable('crossword_pseudofields.settings');
$config->set('clues.show', TRUE);
$config->save();
drupal_flush_all_caches();
$this->drupalGet('node/1');
$assertSession->elementExists('css', '#show-clues');
$assertSession->elementNotExists('css', '#show-clues:checked');
$this->assertFalse($page->find('css', '.crossword-clues.across')->isVisible());
$this->assertFalse($page->find('css', '.crossword-clues.down')->isVisible());
// Click the toggle button to show clues.
$page->find('css', '#show-clues')->click();
$this->assertTrue($page->find('css', '.crossword-clues.across')->isVisible());
$this->assertTrue($page->find('css', '.crossword-clues.down')->isVisible());
// Add the toggle button, initially checked.
$config = \Drupal::service('config.factory')->getEditable('crossword_pseudofields.settings');
$config->set('clues.checked', TRUE);
$config->save();
drupal_flush_all_caches();
$this->drupalGet('node/1');
$assertSession->elementExists('css', '#show-clues');
$assertSession->elementExists('css', '#show-clues:checked');
$this->assertTrue($page->find('css', '.crossword-clues.across')->isVisible());
$this->assertTrue($page->find('css', '.crossword-clues.down')->isVisible());
// Click the toggle button to show clues.
$page->find('css', '#show-clues')->click();
$this->assertFalse($page->find('css', '.crossword-clues.across')->isVisible());
$this->assertFalse($page->find('css', '.crossword-clues.down')->isVisible());
}
}
