BrowserTestBaseTest.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. <?php
  2. namespace Drupal\FunctionalTests;
  3. use Behat\Mink\Exception\ExpectationException;
  4. use Drupal\Component\Utility\Html;
  5. use Drupal\Core\Url;
  6. use Drupal\Tests\BrowserTestBase;
  7. use Drupal\Tests\Traits\Core\CronRunTrait;
  8. /**
  9. * Tests BrowserTestBase functionality.
  10. *
  11. * @group browsertestbase
  12. */
  13. class BrowserTestBaseTest extends BrowserTestBase {
  14. use CronRunTrait;
  15. /**
  16. * Modules to enable.
  17. *
  18. * @var array
  19. */
  20. public static $modules = ['test_page_test', 'form_test', 'system_test'];
  21. /**
  22. * Tests basic page test.
  23. */
  24. public function testGoTo() {
  25. $account = $this->drupalCreateUser();
  26. $this->drupalLogin($account);
  27. // Visit a Drupal page that requires login.
  28. $this->drupalGet('test-page');
  29. $this->assertSession()->statusCodeEquals(200);
  30. // Test page contains some text.
  31. $this->assertSession()->pageTextContains('Test page text.');
  32. // Check that returned plain text is correct.
  33. $text = $this->getTextContent();
  34. $this->assertContains('Test page text.', $text);
  35. $this->assertNotContains('</html>', $text);
  36. // Response includes cache tags that we can assert.
  37. $this->assertSession()->responseHeaderEquals('X-Drupal-Cache-Tags', 'http_response rendered');
  38. // Test that we can read the JS settings.
  39. $js_settings = $this->getDrupalSettings();
  40. $this->assertSame('azAZ09();.,\\\/-_{}', $js_settings['test-setting']);
  41. // Test drupalGet with a url object.
  42. $url = Url::fromRoute('test_page_test.render_title');
  43. $this->drupalGet($url);
  44. $this->assertSession()->statusCodeEquals(200);
  45. // Test page contains some text.
  46. $this->assertSession()->pageTextContains('Hello Drupal');
  47. // Test that setting headers with drupalGet() works.
  48. $this->drupalGet('system-test/header', [], [
  49. 'Test-Header' => 'header value',
  50. ]);
  51. $returned_header = $this->getSession()->getResponseHeader('Test-Header');
  52. $this->assertSame('header value', $returned_header);
  53. }
  54. /**
  55. * Tests basic form functionality.
  56. */
  57. public function testForm() {
  58. // Ensure the proper response code for a _form route.
  59. $this->drupalGet('form-test/object-builder');
  60. $this->assertSession()->statusCodeEquals(200);
  61. // Ensure the form and text field exist.
  62. $this->assertSession()->elementExists('css', 'form#form-test-form-test-object');
  63. $this->assertSession()->fieldExists('bananas');
  64. // Check that the hidden field exists and has a specific value.
  65. $this->assertSession()->hiddenFieldExists('strawberry');
  66. $this->assertSession()->hiddenFieldExists('red');
  67. $this->assertSession()->hiddenFieldExists('redstrawberryhiddenfield');
  68. $this->assertSession()->hiddenFieldValueNotEquals('strawberry', 'brown');
  69. $this->assertSession()->hiddenFieldValueEquals('strawberry', 'red');
  70. // Check that a hidden field does not exist.
  71. $this->assertSession()->hiddenFieldNotExists('bananas');
  72. $this->assertSession()->hiddenFieldNotExists('pineapple');
  73. $edit = ['bananas' => 'green'];
  74. $this->submitForm($edit, 'Save', 'form-test-form-test-object');
  75. $config_factory = $this->container->get('config.factory');
  76. $value = $config_factory->get('form_test.object')->get('bananas');
  77. $this->assertSame('green', $value);
  78. // Test drupalPostForm().
  79. $edit = ['bananas' => 'red'];
  80. $this->drupalPostForm('form-test/object-builder', $edit, 'Save');
  81. $value = $config_factory->get('form_test.object')->get('bananas');
  82. $this->assertSame('red', $value);
  83. $this->drupalPostForm('form-test/object-builder', NULL, 'Save');
  84. $value = $config_factory->get('form_test.object')->get('bananas');
  85. $this->assertSame('', $value);
  86. }
  87. /**
  88. * Tests clickLink() functionality.
  89. */
  90. public function testClickLink() {
  91. $this->drupalGet('test-page');
  92. $this->clickLink('Visually identical test links');
  93. $this->assertContains('user/login', $this->getSession()->getCurrentUrl());
  94. $this->drupalGet('test-page');
  95. $this->clickLink('Visually identical test links', 0);
  96. $this->assertContains('user/login', $this->getSession()->getCurrentUrl());
  97. $this->drupalGet('test-page');
  98. $this->clickLink('Visually identical test links', 1);
  99. $this->assertContains('user/register', $this->getSession()->getCurrentUrl());
  100. }
  101. public function testError() {
  102. $this->setExpectedException('\Exception', 'User notice: foo');
  103. $this->drupalGet('test-error');
  104. }
  105. /**
  106. * Tests linkExists() with pipe character (|) in locator.
  107. *
  108. * @see \Drupal\Tests\WebAssert::linkExists()
  109. */
  110. public function testPipeCharInLocator() {
  111. $this->drupalGet('test-pipe-char');
  112. $this->assertSession()->linkExists('foo|bar|baz');
  113. }
  114. /**
  115. * Tests legacy text asserts.
  116. */
  117. public function testLegacyTextAsserts() {
  118. $this->drupalGet('test-encoded');
  119. $dangerous = 'Bad html <script>alert(123);</script>';
  120. $sanitized = Html::escape($dangerous);
  121. $this->assertNoText($dangerous);
  122. $this->assertText($sanitized);
  123. // Test getRawContent().
  124. $this->assertSame($this->getSession()->getPage()->getContent(), $this->getRawContent());
  125. }
  126. /**
  127. * Tests legacy field asserts which use xpath directly.
  128. */
  129. public function testLegacyXpathAsserts() {
  130. $this->drupalGet('test-field-xpath');
  131. $this->assertFieldsByValue($this->xpath("//h1[@class = 'page-title']"), NULL);
  132. $this->assertFieldsByValue($this->xpath('//table/tbody/tr[2]/td[1]'), 'one');
  133. $this->assertFieldByXPath('//table/tbody/tr[2]/td[1]', 'one');
  134. $this->assertFieldsByValue($this->xpath("//input[@id = 'edit-name']"), 'Test name');
  135. $this->assertFieldByXPath("//input[@id = 'edit-name']", 'Test name');
  136. $this->assertFieldsByValue($this->xpath("//select[@id = 'edit-options']"), '2');
  137. $this->assertFieldByXPath("//select[@id = 'edit-options']", '2');
  138. $this->assertNoFieldByXPath('//notexisting');
  139. $this->assertNoFieldByXPath("//input[@id = 'edit-name']", 'wrong value');
  140. // Test that the assertion fails correctly.
  141. try {
  142. $this->assertFieldByXPath("//input[@id = 'notexisting']");
  143. $this->fail('The "notexisting" field was found.');
  144. }
  145. catch (\PHPUnit_Framework_ExpectationFailedException $e) {
  146. $this->pass('assertFieldByXPath correctly failed. The "notexisting" field was not found.');
  147. }
  148. try {
  149. $this->assertNoFieldByXPath("//input[@id = 'edit-name']");
  150. $this->fail('The "edit-name" field was not found.');
  151. }
  152. catch (\PHPUnit_Framework_ExpectationFailedException $e) {
  153. $this->pass('assertNoFieldByXPath correctly failed. The "edit-name" field was found.');
  154. }
  155. try {
  156. $this->assertFieldsByValue($this->xpath("//input[@id = 'edit-name']"), 'not the value');
  157. $this->fail('The "edit-name" field is found with the value "not the value".');
  158. }
  159. catch (\PHPUnit_Framework_ExpectationFailedException $e) {
  160. $this->pass('The "edit-name" field is not found with the value "not the value".');
  161. }
  162. }
  163. /**
  164. * Tests legacy field asserts using textfields.
  165. */
  166. public function testLegacyFieldAssertsWithTextfields() {
  167. $this->drupalGet('test-field-xpath');
  168. // *** 1. assertNoField().
  169. $this->assertNoField('invalid_name_and_id');
  170. // Test that the assertion fails correctly when searching by name.
  171. try {
  172. $this->assertNoField('name');
  173. $this->fail('The "name" field was not found based on name.');
  174. }
  175. catch (ExpectationException $e) {
  176. $this->pass('assertNoField correctly failed. The "name" field was found by name.');
  177. }
  178. // Test that the assertion fails correctly when searching by id.
  179. try {
  180. $this->assertNoField('edit-name');
  181. $this->fail('The "name" field was not found based on id.');
  182. }
  183. catch (ExpectationException $e) {
  184. $this->pass('assertNoField correctly failed. The "name" field was found by id.');
  185. }
  186. // *** 2. assertField().
  187. $this->assertField('name');
  188. $this->assertField('edit-name');
  189. // Test that the assertion fails correctly if the field does not exist.
  190. try {
  191. $this->assertField('invalid_name_and_id');
  192. $this->fail('The "invalid_name_and_id" field was found.');
  193. }
  194. catch (ExpectationException $e) {
  195. $this->pass('assertField correctly failed. The "invalid_name_and_id" field was not found.');
  196. }
  197. // *** 3. assertNoFieldById().
  198. $this->assertNoFieldById('name');
  199. $this->assertNoFieldById('name', 'not the value');
  200. $this->assertNoFieldById('notexisting');
  201. $this->assertNoFieldById('notexisting', NULL);
  202. // Test that the assertion fails correctly if no value is passed in.
  203. try {
  204. $this->assertNoFieldById('edit-description');
  205. $this->fail('The "description" field, with no value was not found.');
  206. }
  207. catch (ExpectationException $e) {
  208. $this->pass('The "description" field, with no value was found.');
  209. }
  210. // Test that the assertion fails correctly if a NULL value is passed in.
  211. try {
  212. $this->assertNoFieldById('edit-name', NULL);
  213. $this->fail('The "name" field was not found.');
  214. }
  215. catch (ExpectationException $e) {
  216. $this->pass('The "name" field was found.');
  217. }
  218. // *** 4. assertFieldById().
  219. $this->assertFieldById('edit-name', NULL);
  220. $this->assertFieldById('edit-name', 'Test name');
  221. $this->assertFieldById('edit-description', NULL);
  222. $this->assertFieldById('edit-description');
  223. // Test that the assertion fails correctly if no value is passed in.
  224. try {
  225. $this->assertFieldById('edit-name');
  226. $this->fail('The "edit-name" field with no value was found.');
  227. }
  228. catch (\PHPUnit_Framework_ExpectationFailedException $e) {
  229. $this->pass('The "edit-name" field with no value was not found.');
  230. }
  231. // Test that the assertion fails correctly if the wrong value is passed in.
  232. try {
  233. $this->assertFieldById('edit-name', 'not the value');
  234. $this->fail('The "name" field was found, using the wrong value.');
  235. }
  236. catch (\PHPUnit_Framework_ExpectationFailedException $e) {
  237. $this->pass('The "name" field was not found, using the wrong value.');
  238. }
  239. // *** 5. assertNoFieldByName().
  240. $this->assertNoFieldByName('name');
  241. $this->assertNoFieldByName('name', 'not the value');
  242. $this->assertNoFieldByName('notexisting');
  243. $this->assertNoFieldByName('notexisting', NULL);
  244. // Test that the assertion fails correctly if no value is passed in.
  245. try {
  246. $this->assertNoFieldByName('description');
  247. $this->fail('The "description" field, with no value was not found.');
  248. }
  249. catch (ExpectationException $e) {
  250. $this->pass('The "description" field, with no value was found.');
  251. }
  252. // Test that the assertion fails correctly if a NULL value is passed in.
  253. try {
  254. $this->assertNoFieldByName('name', NULL);
  255. $this->fail('The "name" field was not found.');
  256. }
  257. catch (ExpectationException $e) {
  258. $this->pass('The "name" field was found.');
  259. }
  260. // *** 6. assertFieldByName().
  261. $this->assertFieldByName('name');
  262. $this->assertFieldByName('name', NULL);
  263. $this->assertFieldByName('name', 'Test name');
  264. $this->assertFieldByName('description');
  265. $this->assertFieldByName('description', '');
  266. $this->assertFieldByName('description', NULL);
  267. // Test that the assertion fails correctly if given the wrong name.
  268. try {
  269. $this->assertFieldByName('non-existing-name');
  270. $this->fail('The "non-existing-name" field was found.');
  271. }
  272. catch (ExpectationException $e) {
  273. $this->pass('The "non-existing-name" field was not found');
  274. }
  275. // Test that the assertion fails correctly if given the wrong value.
  276. try {
  277. $this->assertFieldByName('name', 'not the value');
  278. $this->fail('The "name" field with incorrect value was found.');
  279. }
  280. catch (ExpectationException $e) {
  281. $this->pass('assertFieldByName correctly failed. The "name" field with incorrect value was not found.');
  282. }
  283. }
  284. /**
  285. * Tests legacy field asserts on other types of field.
  286. */
  287. public function testLegacyFieldAssertsWithNonTextfields() {
  288. $this->drupalGet('test-field-xpath');
  289. // Option field type.
  290. $this->assertOptionByText('options', 'one');
  291. try {
  292. $this->assertOptionByText('options', 'four');
  293. $this->fail('The select option "four" was found.');
  294. }
  295. catch (ExpectationException $e) {
  296. $this->pass($e->getMessage());
  297. }
  298. $this->assertOption('options', 1);
  299. try {
  300. $this->assertOption('options', 4);
  301. $this->fail('The select option "4" was found.');
  302. }
  303. catch (ExpectationException $e) {
  304. $this->pass($e->getMessage());
  305. }
  306. $this->assertNoOption('options', 'non-existing');
  307. try {
  308. $this->assertNoOption('options', 'one');
  309. $this->fail('The select option "one" was not found.');
  310. }
  311. catch (ExpectationException $e) {
  312. $this->pass($e->getMessage());
  313. }
  314. $this->assertOptionSelected('options', 2);
  315. try {
  316. $this->assertOptionSelected('options', 4);
  317. $this->fail('The select option "4" was selected.');
  318. }
  319. catch (ExpectationException $e) {
  320. $this->pass($e->getMessage());
  321. }
  322. try {
  323. $this->assertOptionSelected('options', 1);
  324. $this->fail('The select option "1" was selected.');
  325. }
  326. catch (\PHPUnit_Framework_ExpectationFailedException $e) {
  327. $this->pass($e->getMessage());
  328. }
  329. // Button field type.
  330. $this->assertFieldById('edit-save', NULL);
  331. // Test that the assertion fails correctly if the field value is passed in
  332. // rather than the id.
  333. try {
  334. $this->assertFieldById('Save', NULL);
  335. $this->fail('The field with id of "Save" was found.');
  336. }
  337. catch (ExpectationException $e) {
  338. $this->pass($e->getMessage());
  339. }
  340. $this->assertNoFieldById('Save', NULL);
  341. // Test that the assertion fails correctly if the id of an actual field is
  342. // passed in.
  343. try {
  344. $this->assertNoFieldById('edit-save', NULL);
  345. $this->fail('The field with id of "edit-save" was not found.');
  346. }
  347. catch (ExpectationException $e) {
  348. $this->pass($e->getMessage());
  349. }
  350. // Checkbox field type.
  351. // Test that checkboxes are found/not found correctly by name, when using
  352. // TRUE or FALSE to match their 'checked' state.
  353. $this->assertFieldByName('checkbox_enabled', TRUE);
  354. $this->assertFieldByName('checkbox_disabled', FALSE);
  355. $this->assertNoFieldByName('checkbox_enabled', FALSE);
  356. $this->assertNoFieldByName('checkbox_disabled', TRUE);
  357. // Test that checkboxes are found by name when using NULL to ignore the
  358. // 'checked' state.
  359. $this->assertFieldByName('checkbox_enabled', NULL);
  360. $this->assertFieldByName('checkbox_disabled', NULL);
  361. // Test that checkboxes are found/not found correctly by ID, when using
  362. // TRUE or FALSE to match their 'checked' state.
  363. $this->assertFieldById('edit-checkbox-enabled', TRUE);
  364. $this->assertFieldById('edit-checkbox-disabled', FALSE);
  365. $this->assertNoFieldById('edit-checkbox-enabled', FALSE);
  366. $this->assertNoFieldById('edit-checkbox-disabled', TRUE);
  367. // Test that checkboxes are found by by ID, when using NULL to ignore the
  368. // 'checked' state.
  369. $this->assertFieldById('edit-checkbox-enabled', NULL);
  370. $this->assertFieldById('edit-checkbox-disabled', NULL);
  371. // Test that the assertion fails correctly when using NULL to ignore state.
  372. try {
  373. $this->assertNoFieldByName('checkbox_enabled', NULL);
  374. $this->fail('The "checkbox_enabled" field was not found by name, using NULL value.');
  375. }
  376. catch (ExpectationException $e) {
  377. $this->pass('assertNoFieldByName failed correctly. The "checkbox_enabled" field was found using NULL value.');
  378. }
  379. // Test that the assertion fails correctly when using NULL to ignore state.
  380. try {
  381. $this->assertNoFieldById('edit-checkbox-disabled', NULL);
  382. $this->fail('The "edit-checkbox-disabled" field was not found by ID, using NULL value.');
  383. }
  384. catch (ExpectationException $e) {
  385. $this->pass('assertNoFieldById failed correctly. The "edit-checkbox-disabled" field was found by ID using NULL value.');
  386. }
  387. // Test the specific 'checked' assertions.
  388. $this->assertFieldChecked('edit-checkbox-enabled');
  389. $this->assertNoFieldChecked('edit-checkbox-disabled');
  390. // Test that the assertion fails correctly with non-existant field id.
  391. try {
  392. $this->assertNoFieldChecked('incorrect_checkbox_id');
  393. $this->fail('The "incorrect_checkbox_id" field was found');
  394. }
  395. catch (ExpectationException $e) {
  396. $this->pass('assertNoFieldChecked correctly failed. The "incorrect_checkbox_id" field was not found.');
  397. }
  398. // Test that the assertion fails correctly for a checkbox that is checked.
  399. try {
  400. $this->assertNoFieldChecked('edit-checkbox-enabled');
  401. $this->fail('The "edit-checkbox-enabled" field was not found in a checked state.');
  402. }
  403. catch (ExpectationException $e) {
  404. $this->pass('assertNoFieldChecked correctly failed. The "edit-checkbox-enabled" field was found in a checked state.');
  405. }
  406. // Test that the assertion fails correctly for a checkbox that is not
  407. // checked.
  408. try {
  409. $this->assertFieldChecked('edit-checkbox-disabled');
  410. $this->fail('The "edit-checkbox-disabled" field was found and checked.');
  411. }
  412. catch (ExpectationException $e) {
  413. $this->pass('assertFieldChecked correctly failed. The "edit-checkbox-disabled" field was not found in a checked state.');
  414. }
  415. }
  416. /**
  417. * Tests the ::cronRun() method.
  418. */
  419. public function testCronRun() {
  420. $last_cron_time = \Drupal::state()->get('system.cron_last');
  421. $this->cronRun();
  422. $this->assertSession()->statusCodeEquals(204);
  423. $next_cron_time = \Drupal::state()->get('system.cron_last');
  424. $this->assertGreaterThan($last_cron_time, $next_cron_time);
  425. }
  426. /**
  427. * Tests the Drupal install done in \Drupal\Tests\BrowserTestBase::setUp().
  428. */
  429. public function testInstall() {
  430. $htaccess_filename = $this->tempFilesDirectory . '/.htaccess';
  431. $this->assertTrue(file_exists($htaccess_filename), "$htaccess_filename exists");
  432. }
  433. /**
  434. * Tests the assumption that local time is in 'Australia/Sydney'.
  435. */
  436. public function testLocalTimeZone() {
  437. // The 'Australia/Sydney' time zone is set in core/tests/bootstrap.php
  438. $this->assertEquals('Australia/Sydney', date_default_timezone_get());
  439. // The 'Australia/Sydney' time zone is also set in
  440. // FunctionalTestSetupTrait::initConfig().
  441. $config_factory = $this->container->get('config.factory');
  442. $value = $config_factory->get('system.date')->get('timezone.default');
  443. $this->assertEquals('Australia/Sydney', $value);
  444. }
  445. }