crossword-8.x-1.x-dev/tests/src/FunctionalJavascript/CrosswordFormatterTestBase.php

tests/src/FunctionalJavascript/CrosswordFormatterTestBase.php
<?php

namespace Drupal\Tests\crossword\FunctionalJavascript;

use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
use Drupal\node\Entity\Node;

/**
 * Tests basic js functionality of crossword formatters.
 *
 * @group crossword
 */
abstract class CrosswordFormatterTestBase extends WebDriverTestBase {

  /**
   * {@inheritdoc}
   */
  protected $defaultTheme = 'stark';

  /**
   * The machine name of the formatter to test.
   *
   * @var string
   */
  protected $formatter;

  /**
   * Name of test puzzle.
   *
   * @var string
   */
  protected $testPuzzleFilename = 'test.txt';

  /**
   * Test the interactive crossword field formatter plugin.
   */
  public function testCrosswordFormatter() {

    $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();

    // Check for presence of various test.
    $assertSession->elementTextContains('css', '.crossword-title', "Test Puzzle");
    $assertSession->elementTextContains('css', '.crossword-author', "Test Author");

    // Columns classes.
    $assertSession->elementExists('css', '.crossword-grid.crossword-columns-3.crossword-rows-3');

    // No img in the black square.
    $assertSession->elementNotExists('css', '[data-col="1"][data-row="0"] img');

    // Check instructions toggle.
    $assertSession->pageTextNotContains('Move active square');
    $page->find('css', '.button-instructions')->click();
    $assertSession->pageTextContains('Move active square');
    $page->find('css', '.button-instructions')->click();
    $assertSession->pageTextNotContains('Move active square');

    // Initial settings.
    $assertSession->checkboxNotChecked('show-errors');
    $assertSession->checkboxChecked('show-references');
    $assertSession->elementExists('css', 'div.show-references, body.show-references');

    // 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->assertSame('TWO', $square->getAttribute('data-fill'));
    $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);

    // 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");
    // Click on bottom left square again. Check that direction toggles.
    $square->click();
    $this->assertTrue($square->hasClass('active'));
    $this->assertFalse($clue_across->hasClass('active'));
    $this->assertTrue($clue_down->hasClass('active'));
    $assertSession->elementTextNotContains('css', '#active-clues', "Five-A Has a reference to 3-Across and 1-Down");
    $assertSession->elementTextContains('css', '#active-clues', "One-D is AB2");
    // Check that errors work on squares and clues while testing rebus.
    $this->assertFalse($square->hasClass('error'));
    $this->assertFalse($clue_across->hasClass('error'));
    $square->click();
    $input->setValue('b');
    $this->assertTrue($square->hasClass('error'));
    $this->assertTrue($clue_across->hasClass('error'));
    // Go back.
    $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. Contains error.';
    $this->assertEquals($input->getAttribute('aria-label'), $expected_aria_label);
    $page->find('css', '#show-errors')->click();
    // Back to setting values.
    $input->setValue('T');
    $this->assertTrue($square->hasClass('error'));
    $this->assertTrue($clue_across->hasClass('error'));
    // Activate rebus entry.
    $square->click();
    $page->find('css', '#rebus-entry')->click();
    $input->setValue('W');
    $this->assertTrue($square->hasClass('error'));
    $this->assertTrue($clue_across->hasClass('error'));
    $input->setValue('O');
    $this->assertFalse($square->hasClass('error'));
    $this->assertFalse($clue_across->hasClass('error'));
    $page->find('css', '#rebus-entry')->click();

    // Check that some buttons work.
    // Previous across clue button.
    $page->find('css', '.crossword-clue-change.prev')->click();
    $new_active_square = $page->find('css', '[data-col="0"][data-row="1"]');
    $new_active_clue = $page->find('css', '.crossword-clue[data-clue-index-across="0"]');
    $this->assertTrue($new_active_square->hasClass('active'));
    $this->assertTrue($new_active_clue->hasClass('active'));
    $this->assertFalse($square->hasClass('active'));
    $this->assertFalse($clue_across->hasClass('active'));

    // Cheat button.
    $page->find('css', '.button-cheat')->click();
    $this->assertTrue($new_active_square->hasClass('cheat'));
    $this->assertTrue($new_active_clue->hasClass('cheat'));
    $assertSession->elementTextContains('css', '[data-col="0"][data-row="1"] .square-fill', 'B');

    // Check out undo and redo. First cheat one more time.
    $page->find('css', '.button-cheat')->click();
    $assertSession->elementTextContains('css', '[data-col="1"][data-row="1"] .square-fill', 'C');
    $assertSession->elementTextContains('css', '[data-col="0"][data-row="1"] .square-fill', 'B');
    // Now undo.
    $page->find('css', '.button-undo')->click();
    $assertSession->elementTextNotContains('css', '[data-col="1"][data-row="1"] .square-fill', 'C');
    $assertSession->elementTextContains('css', '[data-col="0"][data-row="1"] .square-fill', 'B');
    // Now undo again.
    $page->find('css', '.button-undo')->click();
    $assertSession->elementTextNotContains('css', '[data-col="1"][data-row="1"] .square-fill', 'C');
    $assertSession->elementTextNotContains('css', '[data-col="0"][data-row="1"] .square-fill', 'B');
    // Now redo.
    $page->find('css', '.button-redo')->click();
    $assertSession->elementTextNotContains('css', '[data-col="1"][data-row="1"] .square-fill', 'C');
    $assertSession->elementTextContains('css', '[data-col="0"][data-row="1"] .square-fill', 'B');
    // Now redo again.
    $page->find('css', '.button-redo')->click();
    $assertSession->elementTextContains('css', '[data-col="1"][data-row="1"] .square-fill', 'C');
    $assertSession->elementTextContains('css', '[data-col="0"][data-row="1"] .square-fill', 'B');

    // Next clue express should advance to next across clue.
    $page->find('css', '.next-clue-express')->click();
    $new_active_square = $page->find('css', '[data-col="0"][data-row="2"]');
    $new_active_clue = $page->find('css', '.crossword-clue[data-clue-index-across="1"]');
    $this->assertTrue($new_active_square->hasClass('active'));
    $this->assertTrue($new_active_clue->hasClass('active'));
    // Now next clue express should get to the first down clue.
    $page->find('css', '.next-clue-express')->click();
    $new_active_square = $page->find('css', '[data-col="0"][data-row="0"]');
    $new_active_clue = $page->find('css', '.crossword-clue[data-clue-index-down="0"]');
    $this->assertTrue($new_active_square->hasClass('active'));
    $this->assertTrue($new_active_clue->hasClass('active'));

    // Test complete class on clues. Three-A is almost complete. Use it.
    $clue = $page->find('css', '.crossword-clue[data-clue-index-across="0"]');
    $clue->click();
    $this->assertFalse($clue->hasClass('complete'));
    $page->find('css', '[data-col="2"][data-row="1"]')->click();
    $page->find('css', '.button-cheat')->click();
    $this->assertTrue($clue->hasClass('complete'));
    $page->find('css', '.button-undo')->click();
    $this->assertFalse($clue->hasClass('complete'));
    // Aria text should not be on last square of clue.
    $this->assertEmpty($page->find('css', '[data-col="2"][data-row="1"] input')->getAttribute('aria-label'));

    // Check that local storage works.
    // Reload the page.
    $this->drupalGet("crossword-tests/1/{$this->formatter}");
    $assertSession = $this->assertSession();
    $session = $this->getSession();
    $page = $session->getPage();
    $assertSession->elementTextNotContains('css', '[data-col="0"][data-row="0"] .square-fill', 'A');
    $assertSession->elementTextNotContains('css', '[data-col="2"][data-row="0"] .square-fill', 'ONE');
    $assertSession->elementTextContains('css', '[data-col="0"][data-row="1"] .square-fill', 'B');
    $assertSession->elementTextContains('css', '[data-col="1"][data-row="1"] .square-fill', 'C');
    $assertSession->elementTextNotContains('css', '[data-col="2"][data-row="1"] .square-fill', 'D');
    $assertSession->elementTextContains('css', '[data-col="0"][data-row="2"] .square-fill', 'TWO');
    $assertSession->elementTextNotContains('css', '[data-col="1"][data-row="2"] .square-fill', 'E');
    $assertSession->elementTextNotContains('css', '[data-col="2"][data-row="2"] .square-fill', 'F');
    // Settings should persist: errors and references should both be off.
    $assertSession->checkboxNotChecked('show-errors');
    $assertSession->checkboxNotChecked('show-references');
    $assertSession->elementNotExists('css', 'div.show-references, body.show-references');

    // Test crossword-revealed and crossword-solved classes and congrats.
    // This also covers solution and clear buttons.
    $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->elementExists('css', '.crossword.crossword-revealed, body.crossword-revealed');
    $assertSession->pageTextNotContains('Well done!');
    // Check aria-text of top left square.
    $page->find('css', '[data-col="0"][data-row="0"]')->click();
    $expected_aria_label = 'The puzzle has been revealed. 1 down. One-D is AB2. Answer: 3 letters. A. B. TWO.';
    $this->assertEquals($page->find('css', '[data-col="0"][data-row="0"] input')->getAttribute('aria-label'), $expected_aria_label);
    // Check express button on solved puzzle. Should go to next down clue.
    $page->find('css', '.next-clue-express')->click();
    $new_active_square = $page->find('css', '[data-col="2"][data-row="0"]');
    $new_active_clue = $page->find('css', '.crossword-clue[data-clue-index-down="1"]');
    $this->assertTrue($new_active_square->hasClass('active'));
    $this->assertTrue($new_active_clue->hasClass('active'));
    // "Revealed" status should persist on page load.
    $this->drupalGet("crossword-tests/1/{$this->formatter}");
    $assertSession->elementNotExists('css', '.crossword.crossword-solved, body.crossword-solved');
    $assertSession->elementExists('css', '.crossword.crossword-revealed, body.crossword-revealed');
    $assertSession->pageTextNotContains('Well done!');
    $page->find('css', '[data-col="0"][data-row="0"]')->click();
    $expected_aria_label = 'The puzzle has been revealed. 1 down. One-D is AB2. Answer: 3 letters. A. B. TWO.';
    $this->assertEquals($page->find('css', '[data-col="0"][data-row="0"] input')->getAttribute('aria-label'), $expected_aria_label);
    // Clear button should clear classes.
    $page->find('css', '.button-clear')->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!');
    $page->find('css', '[data-col="0"][data-row="0"]')->click();
    $expected_aria_label = '1 down. One-D is AB2. 3 letters.';
    $this->assertEquals($page->find('css', '[data-col="0"][data-row="0"] input')->getAttribute('aria-label'), $expected_aria_label);
    // Enter all correct answers (by cheating).
    $page->find('css', '[data-col="0"][data-row="0"]')->click();
    $page->find('css', '.button-cheat')->click();
    $page->find('css', '.button-cheat')->click();
    $page->find('css', '.button-cheat')->click();
    $page->find('css', '.button-cheat')->click();
    $page->find('css', '.button-cheat')->click();
    $page->find('css', '.button-cheat')->click();
    $page->find('css', '.button-cheat')->click();
    $page->find('css', '.button-cheat')->click();
    $this->drupalGet("crossword-tests/1/{$this->formatter}");
    $assertSession->elementExists('css', '.crossword.crossword-solved, body.crossword-solved');
    $assertSession->elementNotExists('css', '.crossword.crossword-revealed, body.crossword-revealed');
    $assertSession->pageTextContains('Well done!');
    $page->find('css', '[data-col="0"][data-row="0"]')->click();
    $expected_aria_label = 'The puzzle has been solved. Well done! 1 down. One-D is AB2. Answer: 3 letters. A. B. TWO.';
    $this->assertEquals($page->find('css', '[data-col="0"][data-row="0"] input')->getAttribute('aria-label'), $expected_aria_label);
    $page->find('css', '#show-errors')->click();
    $page->find('css', '[data-col="0"][data-row="0"]')->click();
    $expected_aria_label = 'The puzzle has been solved. Well done! 1 down. One-D is AB2. Answer: 3 letters. A. B. TWO.';
    $this->assertEquals($page->find('css', '[data-col="0"][data-row="0"] input')->getAttribute('aria-label'), $expected_aria_label);
    $page->find('css', '#show-errors')->click();
    $page->find('css', '.button-clear')->click();
    $this->assertEquals('Do you really want to clear? This action cannot be undone.', $session->getDriver()->getWebDriverSession()->getAlert_text());
    $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!');
  }

  /**
   * Helper function to create node that can be viewed and used for testing.
   *
   * @return Drupal\node\Entity\Node
   *   A crossword node that can be used in tests.
   */
  protected function createTestNode() {
    // First we move a test file to the file system.
    $contents = file_get_contents(\Drupal::service('extension.list.module')->getPath('crossword') . "/tests/files/{$this->testPuzzleFilename}");
    $file = \Drupal::service('file.repository')->writeData($contents, "public://{$this->testPuzzleFilename}");
    // Now use that file in a new crossword node.
    $node = Node::create(['type' => 'crossword']);
    $node->set('title', 'Test Crossword Node');
    $node->set('field_crossword', $file->id());
    $node->set('status', 1);
    $node->save();
    return $node;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc