Skip navigation
Help

ajax.test

  1. drupal
    1. 7 drupal/modules/simpletest/tests/ajax.test

Classes

NameDescription
AJAXCommandsTestCaseTests Ajax framework commands.
AJAXElementValidationMiscellaneous Ajax tests using ajax_test module.
AJAXFormValuesTestCaseTest that $form_state['values'] is properly delivered to $ajax['callback'].
AJAXFrameworkTestCaseTests primary Ajax framework functions.
AJAXMultiFormTestCaseTests that Ajax-enabled forms work when multiple instances of the same form are on a page.
AJAXTestCase

File

drupal/modules/simpletest/tests/ajax.test
View source
  1. <?php
  2. class AJAXTestCase extends DrupalWebTestCase {
  3. function setUp() {
  4. $modules = func_get_args();
  5. if (isset($modules[0]) && is_array($modules[0])) {
  6. $modules = $modules[0];
  7. }
  8. parent::setUp(array_unique(array_merge(array('ajax_test', 'ajax_forms_test'), $modules)));
  9. }
  10. /**
  11. * Assert that a command with the required properties exists within the array of Ajax commands returned by the server.
  12. *
  13. * The Ajax framework, via the ajax_deliver() and ajax_render() functions,
  14. * returns an array of commands. This array sometimes includes commands
  15. * automatically provided by the framework in addition to commands returned by
  16. * a particular page callback. During testing, we're usually interested that a
  17. * particular command is present, and don't care whether other commands
  18. * precede or follow the one we're interested in. Additionally, the command
  19. * we're interested in may include additional data that we're not interested
  20. * in. Therefore, this function simply asserts that one of the commands in
  21. * $haystack contains all of the keys and values in $needle. Furthermore, if
  22. * $needle contains a 'settings' key with an array value, we simply assert
  23. * that all keys and values within that array are present in the command we're
  24. * checking, and do not consider it a failure if the actual command contains
  25. * additional settings that aren't part of $needle.
  26. *
  27. * @param $haystack
  28. * An array of Ajax commands returned by the server.
  29. * @param $needle
  30. * Array of info we're expecting in one of those commands.
  31. * @param $message
  32. * An assertion message.
  33. */
  34. protected function assertCommand($haystack, $needle, $message) {
  35. $found = FALSE;
  36. foreach ($haystack as $command) {
  37. // If the command has additional settings that we're not testing for, do
  38. // not consider that a failure.
  39. if (isset($command['settings']) && is_array($command['settings']) && isset($needle['settings']) && is_array($needle['settings'])) {
  40. $command['settings'] = array_intersect_key($command['settings'], $needle['settings']);
  41. }
  42. // If the command has additional data that we're not testing for, do not
  43. // consider that a failure. Also, == instead of ===, because we don't
  44. // require the key/value pairs to be in any particular order
  45. // (http://www.php.net/manual/en/language.operators.array.php).
  46. if (array_intersect_key($command, $needle) == $needle) {
  47. $found = TRUE;
  48. break;
  49. }
  50. }
  51. $this->assertTrue($found, $message);
  52. }
  53. }
  54. /**
  55. * Tests primary Ajax framework functions.
  56. */
  57. class AJAXFrameworkTestCase extends AJAXTestCase {
  58. protected $profile = 'testing';
  59. public static function getInfo() {
  60. return array(
  61. 'name' => 'AJAX framework',
  62. 'description' => 'Performs tests on AJAX framework functions.',
  63. 'group' => 'AJAX',
  64. );
  65. }
  66. /**
  67. * Test that ajax_render() returns JavaScript settings generated during the page request.
  68. *
  69. * @todo Add tests to ensure that ajax_render() returns commands for new CSS
  70. * and JavaScript files to be loaded by the page. See
  71. * http://drupal.org/node/561858.
  72. */
  73. function testAJAXRender() {
  74. $commands = $this->drupalGetAJAX('ajax-test/render');
  75. // Verify that there is a command to load settings added with
  76. // drupal_add_js().
  77. $expected = array(
  78. 'command' => 'settings',
  79. 'settings' => array('basePath' => base_path(), 'ajax' => 'test'),
  80. );
  81. $this->assertCommand($commands, $expected, t('ajax_render() loads settings added with drupal_add_js().'));
  82. // Verify that Ajax settings are loaded for #type 'link'.
  83. $this->drupalGet('ajax-test/link');
  84. $settings = $this->drupalGetSettings();
  85. $this->assertEqual($settings['ajax']['ajax-link']['url'], url('filter/tips'));
  86. $this->assertEqual($settings['ajax']['ajax-link']['wrapper'], 'block-system-main');
  87. }
  88. /**
  89. * Test behavior of ajax_render_error().
  90. */
  91. function testAJAXRenderError() {
  92. // Verify default error message.
  93. $commands = $this->drupalGetAJAX('ajax-test/render-error');
  94. $expected = array(
  95. 'command' => 'alert',
  96. 'text' => t('An error occurred while handling the request: The server received invalid input.'),
  97. );
  98. $this->assertCommand($commands, $expected, t('ajax_render_error() invokes alert command.'));
  99. // Verify custom error message.
  100. $edit = array(
  101. 'message' => 'Custom error message.',
  102. );
  103. $commands = $this->drupalGetAJAX('ajax-test/render-error', array('query' => $edit));
  104. $expected = array(
  105. 'command' => 'alert',
  106. 'text' => $edit['message'],
  107. );
  108. $this->assertCommand($commands, $expected, t('Custom error message is output.'));
  109. }
  110. }
  111. /**
  112. * Tests Ajax framework commands.
  113. */
  114. class AJAXCommandsTestCase extends AJAXTestCase {
  115. public static function getInfo() {
  116. return array(
  117. 'name' => 'AJAX commands',
  118. 'description' => 'Performs tests on AJAX framework commands.',
  119. 'group' => 'AJAX',
  120. );
  121. }
  122. /**
  123. * Test the various Ajax Commands.
  124. */
  125. function testAJAXCommands() {
  126. $form_path = 'ajax_forms_test_ajax_commands_form';
  127. $web_user = $this->drupalCreateUser(array('access content'));
  128. $this->drupalLogin($web_user);
  129. $edit = array();
  130. // Tests the 'after' command.
  131. $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'After': Click to put something after the div")));
  132. $expected = array(
  133. 'command' => 'insert',
  134. 'method' => 'after',
  135. 'data' => 'This will be placed after',
  136. );
  137. $this->assertCommand($commands, $expected, "'after' AJAX command issued with correct data");
  138. // Tests the 'alert' command.
  139. $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'Alert': Click to alert")));
  140. $expected = array(
  141. 'command' => 'alert',
  142. 'text' => 'Alert',
  143. );
  144. $this->assertCommand($commands, $expected, "'alert' AJAX Command issued with correct text");
  145. // Tests the 'append' command.
  146. $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'Append': Click to append something")));
  147. $expected = array(
  148. 'command' => 'insert',
  149. 'method' => 'append',
  150. 'data' => 'Appended text',
  151. );
  152. $this->assertCommand($commands, $expected, "'append' AJAX command issued with correct data");
  153. // Tests the 'before' command.
  154. $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'before': Click to put something before the div")));
  155. $expected = array(
  156. 'command' => 'insert',
  157. 'method' => 'before',
  158. 'data' => 'Before text',
  159. );
  160. $this->assertCommand($commands, $expected, "'before' AJAX command issued with correct data");
  161. // Tests the 'changed' command.
  162. $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX changed: Click to mark div changed.")));
  163. $expected = array(
  164. 'command' => 'changed',
  165. 'selector' => '#changed_div',
  166. );
  167. $this->assertCommand($commands, $expected, "'changed' AJAX command issued with correct selector");
  168. // Tests the 'changed' command using the second argument.
  169. $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX changed: Click to mark div changed with asterisk.")));
  170. $expected = array(
  171. 'command' => 'changed',
  172. 'selector' => '#changed_div',
  173. 'asterisk' => '#changed_div_mark_this',
  174. );
  175. $this->assertCommand($commands, $expected, "'changed' AJAX command (with asterisk) issued with correct selector");
  176. // Tests the 'css' command.
  177. $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("Set the the '#box' div to be blue.")));
  178. $expected = array(
  179. 'command' => 'css',
  180. 'selector' => '#css_div',
  181. 'argument' => array('background-color' => 'blue'),
  182. );
  183. $this->assertCommand($commands, $expected, "'css' AJAX command issued with correct selector");
  184. // Tests the 'data' command.
  185. $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX data command: Issue command.")));
  186. $expected = array(
  187. 'command' => 'data',
  188. 'name' => 'testkey',
  189. 'value' => 'testvalue',
  190. );
  191. $this->assertCommand($commands, $expected, "'data' AJAX command issued with correct key and value");
  192. // Tests the 'invoke' command.
  193. $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX invoke command: Invoke addClass() method.")));
  194. $expected = array(
  195. 'command' => 'invoke',
  196. 'method' => 'addClass',
  197. 'arguments' => array('error'),
  198. );
  199. $this->assertCommand($commands, $expected, "'invoke' AJAX command issued with correct method and argument");
  200. // Tests the 'html' command.
  201. $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX html: Replace the HTML in a selector.")));
  202. $expected = array(
  203. 'command' => 'insert',
  204. 'method' => 'html',
  205. 'data' => 'replacement text',
  206. );
  207. $this->assertCommand($commands, $expected, "'html' AJAX command issued with correct data");
  208. // Tests the 'insert' command.
  209. $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX insert: Let client insert based on #ajax['method'].")));
  210. $expected = array(
  211. 'command' => 'insert',
  212. 'data' => 'insert replacement text',
  213. );
  214. $this->assertCommand($commands, $expected, "'insert' AJAX command issued with correct data");
  215. // Tests the 'prepend' command.
  216. $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'prepend': Click to prepend something")));
  217. $expected = array(
  218. 'command' => 'insert',
  219. 'method' => 'prepend',
  220. 'data' => 'prepended text',
  221. );
  222. $this->assertCommand($commands, $expected, "'prepend' AJAX command issued with correct data");
  223. // Tests the 'remove' command.
  224. $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'remove': Click to remove text")));
  225. $expected = array(
  226. 'command' => 'remove',
  227. 'selector' => '#remove_text',
  228. );
  229. $this->assertCommand($commands, $expected, "'remove' AJAX command issued with correct command and selector");
  230. // Tests the 'restripe' command.
  231. $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'restripe' command")));
  232. $expected = array(
  233. 'command' => 'restripe',
  234. 'selector' => '#restripe_table',
  235. );
  236. $this->assertCommand($commands, $expected, "'restripe' AJAX command issued with correct selector");
  237. // Tests the 'settings' command.
  238. $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'settings' command")));
  239. $expected = array(
  240. 'command' => 'settings',
  241. 'settings' => array('ajax_forms_test' => array('foo' => 42)),
  242. );
  243. $this->assertCommand($commands, $expected, "'settings' AJAX command issued with correct data");
  244. }
  245. }
  246. /**
  247. * Test that $form_state['values'] is properly delivered to $ajax['callback'].
  248. */
  249. class AJAXFormValuesTestCase extends AJAXTestCase {
  250. public static function getInfo() {
  251. return array(
  252. 'name' => 'AJAX command form values',
  253. 'description' => 'Tests that form values are properly delivered to AJAX callbacks.',
  254. 'group' => 'AJAX',
  255. );
  256. }
  257. function setUp() {
  258. parent::setUp();
  259. $this->web_user = $this->drupalCreateUser(array('access content'));
  260. $this->drupalLogin($this->web_user);
  261. }
  262. /**
  263. * Create a simple form, then POST to system/ajax to change to it.
  264. */
  265. function testSimpleAJAXFormValue() {
  266. // Verify form values of a select element.
  267. foreach (array('red', 'green', 'blue') as $item) {
  268. $edit = array(
  269. 'select' => $item,
  270. );
  271. $commands = $this->drupalPostAJAX('ajax_forms_test_get_form', $edit, 'select');
  272. $expected = array(
  273. 'command' => 'data',
  274. 'value' => $item,
  275. );
  276. $this->assertCommand($commands, $expected, "verification of AJAX form values from a selectbox issued with a correct value");
  277. }
  278. // Verify form values of a checkbox element.
  279. foreach (array(FALSE, TRUE) as $item) {
  280. $edit = array(
  281. 'checkbox' => $item,
  282. );
  283. $commands = $this->drupalPostAJAX('ajax_forms_test_get_form', $edit, 'checkbox');
  284. $expected = array(
  285. 'command' => 'data',
  286. 'value' => (int) $item,
  287. );
  288. $this->assertCommand($commands, $expected, "verification of AJAX form values from a checkbox issued with a correct value");
  289. }
  290. }
  291. }
  292. /**
  293. * Tests that Ajax-enabled forms work when multiple instances of the same form are on a page.
  294. */
  295. class AJAXMultiFormTestCase extends AJAXTestCase {
  296. public static function getInfo() {
  297. return array(
  298. 'name' => 'AJAX multi form',
  299. 'description' => 'Tests that AJAX-enabled forms work when multiple instances of the same form are on a page.',
  300. 'group' => 'AJAX',
  301. );
  302. }
  303. function setUp() {
  304. parent::setUp(array('form_test'));
  305. // Create a multi-valued field for 'page' nodes to use for Ajax testing.
  306. $field_name = 'field_ajax_test';
  307. $field = array(
  308. 'field_name' => $field_name,
  309. 'type' => 'text',
  310. 'cardinality' => FIELD_CARDINALITY_UNLIMITED,
  311. );
  312. field_create_field($field);
  313. $instance = array(
  314. 'field_name' => $field_name,
  315. 'entity_type' => 'node',
  316. 'bundle' => 'page',
  317. );
  318. field_create_instance($instance);
  319. // Login a user who can create 'page' nodes.
  320. $this->web_user = $this->drupalCreateUser(array('create page content'));
  321. $this->drupalLogin($this->web_user);
  322. }
  323. /**
  324. * Test that a page with the 'page_node_form' included twice works correctly.
  325. */
  326. function testMultiForm() {
  327. // HTML IDs for elements within the field are potentially modified with
  328. // each Ajax submission, but these variables are stable and help target the
  329. // desired elements.
  330. $field_name = 'field_ajax_test';
  331. $field_xpaths = array(
  332. 'page-node-form' => '//form[@id="page-node-form"]//div[contains(@class, "field-name-field-ajax-test")]',
  333. 'page-node-form--2' => '//form[@id="page-node-form--2"]//div[contains(@class, "field-name-field-ajax-test")]',
  334. );
  335. $button_name = $field_name . '_add_more';
  336. $button_value = t('Add another item');
  337. $button_xpath_suffix = '//input[@name="' . $button_name . '"]';
  338. $field_items_xpath_suffix = '//input[@type="text"]';
  339. // Ensure the initial page contains both node forms and the correct number
  340. // of field items and "add more" button for the multi-valued field within
  341. // each form.
  342. $this->drupalGet('form-test/two-instances-of-same-form');
  343. foreach ($field_xpaths as $form_html_id => $field_xpath) {
  344. $this->assert(count($this->xpath($field_xpath . $field_items_xpath_suffix)) == 1, t('Found the correct number of field items on the initial page.'));
  345. $this->assertFieldByXPath($field_xpath . $button_xpath_suffix, NULL, t('Found the "add more" button on the initial page.'));
  346. }
  347. $this->assertNoDuplicateIds(t('Initial page contains unique IDs'), 'Other');
  348. // Submit the "add more" button of each form twice. After each corresponding
  349. // page update, ensure the same as above.
  350. foreach ($field_xpaths as $form_html_id => $field_xpath) {
  351. for ($i = 0; $i < 2; $i++) {
  352. $this->drupalPostAJAX(NULL, array(), array($button_name => $button_value), 'system/ajax', array(), array(), $form_html_id);
  353. $this->assert(count($this->xpath($field_xpath . $field_items_xpath_suffix)) == $i+2, t('Found the correct number of field items after an AJAX submission.'));
  354. $this->assertFieldByXPath($field_xpath . $button_xpath_suffix, NULL, t('Found the "add more" button after an AJAX submission.'));
  355. $this->assertNoDuplicateIds(t('Updated page contains unique IDs'), 'Other');
  356. }
  357. }
  358. }
  359. }
  360. /**
  361. * Miscellaneous Ajax tests using ajax_test module.
  362. */
  363. class AJAXElementValidation extends AJAXTestCase {
  364. public static function getInfo() {
  365. return array(
  366. 'name' => 'Miscellaneous AJAX tests',
  367. 'description' => 'Various tests of AJAX behavior',
  368. 'group' => 'AJAX',
  369. );
  370. }
  371. /**
  372. * Try to post an Ajax change to a form that has a validated element.
  373. *
  374. * The drivertext field is Ajax-enabled. An additional field is not, but
  375. * is set to be a required field. In this test the required field is not
  376. * filled in, and we want to see if the activation of the "drivertext"
  377. * Ajax-enabled field fails due to the required field being empty.
  378. */
  379. function testAJAXElementValidation() {
  380. $web_user = $this->drupalCreateUser();
  381. $edit = array('drivertext' => t('some dumb text'));
  382. // Post with 'drivertext' as the triggering element.
  383. $post_result = $this->drupalPostAJAX('ajax_validation_test', $edit, 'drivertext');
  384. // Look for a validation failure in the resultant JSON.
  385. $this->assertNoText(t('Error message'), t("No error message in resultant JSON"));
  386. $this->assertText('ajax_forms_test_validation_form_callback invoked', t('The correct callback was invoked'));
  387. }
  388. }