BrowserWithJavascriptTest.php 5.49 KB
Newer Older
1
2
<?php

3
namespace Drupal\FunctionalJavascriptTests;
4

5
use PHPUnit\Framework\AssertionFailedError;
6

7
8
9
10
11
/**
 * Tests if we can execute JavaScript in the browser.
 *
 * @group javascript
 */
12
class BrowserWithJavascriptTest extends WebDriverTestBase {
13

14
15
16
17
18
  /**
   * Modules to enable.
   *
   * @var array
   */
19
  protected static $modules = ['test_page_test'];
20

21
22
23
24
25
  /**
   * {@inheritdoc}
   */
  protected $defaultTheme = 'stark';

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
  public function testJavascript() {
    $this->drupalGet('<front>');
    $session = $this->getSession();

    $session->resizeWindow(400, 300);
    $javascript = <<<JS
    (function(){
        var w = window,
        d = document,
        e = d.documentElement,
        g = d.getElementsByTagName('body')[0],
        x = w.innerWidth || e.clientWidth || g.clientWidth,
        y = w.innerHeight || e.clientHeight|| g.clientHeight;
        return x == 400 && y == 300;
    }());
JS;
    $this->assertJsCondition($javascript);
43
44
45
46

    // Ensure that \Drupal\Tests\UiHelperTrait::isTestUsingGuzzleClient() works
    // as expected.
    $this->assertFalse($this->isTestUsingGuzzleClient());
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
  }

  public function testAssertJsCondition() {
    $this->drupalGet('<front>');
    $session = $this->getSession();

    $session->resizeWindow(500, 300);
    $javascript = <<<JS
    (function(){
        var w = window,
        d = document,
        e = d.documentElement,
        g = d.getElementsByTagName('body')[0],
        x = w.innerWidth || e.clientWidth || g.clientWidth,
        y = w.innerHeight || e.clientHeight|| g.clientHeight;
        return x == 400 && y == 300;
    }());
JS;

    // We expected the following assertion to fail because the window has been
    // re-sized to have a width of 500 not 400.
68
    $this->expectException(AssertionFailedError::class);
69
70
71
    $this->assertJsCondition($javascript, 100);
  }

72
73
74
75
76
77
78
79
80
  /**
   * Tests creating screenshots.
   */
  public function testCreateScreenshot() {
    $this->drupalGet('<front>');
    $this->createScreenshot('public://screenshot.jpg');
    $this->assertFileExists('public://screenshot.jpg');
  }

81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
  /**
   * Tests assertEscaped() and assertUnescaped().
   *
   * @see \Drupal\Tests\WebAssert::assertNoEscaped()
   * @see \Drupal\Tests\WebAssert::assertEscaped()
   */
  public function testEscapingAssertions() {
    $assert = $this->assertSession();

    $this->drupalGet('test-escaped-characters');
    $assert->assertNoEscaped('<div class="escaped">');
    $assert->responseContains('<div class="escaped">');
    $assert->assertEscaped('Escaped: <"\'&>');

    $this->drupalGet('test-escaped-script');
    $assert->assertNoEscaped('<div class="escaped">');
    $assert->responseContains('<div class="escaped">');
    $assert->assertEscaped("<script>alert('XSS');alert(\"XSS\");</script>");

    $this->drupalGetWithAlert('test-unescaped-script');
    $assert->assertNoEscaped('<div class="unescaped">');
    $assert->responseContains('<div class="unescaped">');
    $assert->responseContains("<script>alert('Marked safe');alert(\"Marked safe\");</script>");
    $assert->assertNoEscaped("<script>alert('Marked safe');alert(\"Marked safe\");</script>");
  }

  /**
   * Retrieves a Drupal path or an absolute path.
   *
   * @param string|\Drupal\Core\Url $path
   *   Drupal path or URL to load into Mink controlled browser.
   * @param array $options
   *   (optional) Options to be forwarded to the url generator.
   * @param string[] $headers
   *   An array containing additional HTTP request headers, the array keys are
   *   the header names and the array values the header values. This is useful
   *   to set for example the "Accept-Language" header for requesting the page
   *   in a different language. Note that not all headers are supported, for
   *   example the "Accept" header is always overridden by the browser. For
   *   testing REST APIs it is recommended to obtain a separate HTTP client
   *   using getHttpClient() and performing requests that way.
   *
   * @return string
   *   The retrieved HTML string, also available as $this->getRawContent()
   *
   * @see \Drupal\Tests\BrowserTestBase::getHttpClient()
   */
  protected function drupalGetWithAlert($path, array $options = [], array $headers = []) {
    $options['absolute'] = TRUE;
    $url = $this->buildUrl($path, $options);

    $session = $this->getSession();

    $this->prepareRequest();
    foreach ($headers as $header_name => $header_value) {
      $session->setRequestHeader($header_name, $header_value);
    }

    $session->visit($url);

    // There are 2 alerts to accept before we can get the content of the page.
    $session->getDriver()->getWebdriverSession()->accept_alert();
    $session->getDriver()->getWebdriverSession()->accept_alert();

    $out = $session->getPage()->getContent();

    // Ensure that any changes to variables in the other thread are picked up.
    $this->refreshVariables();

    // Replace original page output with new output from redirected page(s).
    if ($new = $this->checkForMetaRefresh()) {
      $out = $new;
      // We are finished with all meta refresh redirects, so reset the counter.
      $this->metaRefreshCount = 0;
    }

157
158
159
    // Log only for WebDriverTestBase tests because for DrupalTestBrowser we log
    // with ::getResponseLogHandler.
    if ($this->htmlOutputEnabled && !$this->isTestUsingGuzzleClient()) {
160
161
162
163
164
165
166
167
168
169
      $html_output = 'GET request to: ' . $url .
        '<hr />Ending URL: ' . $this->getSession()->getCurrentUrl();
      $html_output .= '<hr />' . $out;
      $html_output .= $this->getHtmlOutputHeaders();
      $this->htmlOutput($html_output);
    }

    return $out;
  }

170
}