<?php
class AJAXTestCase extends DrupalWebTestCase {
function setUp() {
$modules = func_get_args();
if (isset($modules[0]) && is_array($modules[0])) {
$modules = $modules[0];
}
parent::setUp(array_unique(array_merge(array(
'ajax_test',
'ajax_forms_test',
), $modules)));
}
protected function assertCommand($haystack, $needle, $message) {
$found = FALSE;
foreach ($haystack as $command) {
if (isset($command['settings']) && is_array($command['settings']) && isset($needle['settings']) && is_array($needle['settings'])) {
$command['settings'] = array_intersect_key($command['settings'], $needle['settings']);
}
if (array_intersect_key($command, $needle) == $needle) {
$found = TRUE;
break;
}
}
$this
->assertTrue($found, $message);
}
}
class AJAXFrameworkTestCase extends AJAXTestCase {
protected $profile = 'testing';
public static function getInfo() {
return array(
'name' => 'AJAX framework',
'description' => 'Performs tests on AJAX framework functions.',
'group' => 'AJAX',
);
}
function testAJAXRender() {
$commands = $this
->drupalGetAJAX('ajax-test/render');
$expected = array(
'command' => 'settings',
'settings' => array(
'basePath' => base_path(),
'ajax' => 'test',
),
);
$this
->assertCommand($commands, $expected, t('ajax_render() loads settings added with drupal_add_js().'));
$this
->drupalGet('ajax-test/link');
$settings = $this
->drupalGetSettings();
$this
->assertEqual($settings['ajax']['ajax-link']['url'], url('filter/tips'));
$this
->assertEqual($settings['ajax']['ajax-link']['wrapper'], 'block-system-main');
}
function testAJAXRenderError() {
$commands = $this
->drupalGetAJAX('ajax-test/render-error');
$expected = array(
'command' => 'alert',
'text' => t('An error occurred while handling the request: The server received invalid input.'),
);
$this
->assertCommand($commands, $expected, t('ajax_render_error() invokes alert command.'));
$edit = array(
'message' => 'Custom error message.',
);
$commands = $this
->drupalGetAJAX('ajax-test/render-error', array(
'query' => $edit,
));
$expected = array(
'command' => 'alert',
'text' => $edit['message'],
);
$this
->assertCommand($commands, $expected, t('Custom error message is output.'));
}
function testLazyLoad() {
$expected = array(
'setting_name' => 'ajax_forms_test_lazy_load_form_submit',
'setting_value' => 'executed',
'css' => drupal_get_path('module', 'system') . '/system.admin.css',
'js' => drupal_get_path('module', 'system') . '/system.js',
);
$expected_css_html = drupal_get_css(array(
$expected['css'] => array(
'type' => 'file',
'group' => CSS_DEFAULT,
'weight' => 0,
'every_page' => FALSE,
'media' => 'all',
'preprocess' => TRUE,
'data' => $expected['css'],
'browsers' => array(
'IE' => TRUE,
'!IE' => TRUE,
),
),
), TRUE);
$expected_js_html = drupal_get_js('header', array(
$expected['js'] => drupal_js_defaults($expected['js']),
), TRUE);
$this
->drupalGet('ajax_forms_test_lazy_load_form');
$original_settings = $this
->drupalGetSettings();
$original_css = $original_settings['ajaxPageState']['css'];
$original_js = $original_settings['ajaxPageState']['js'];
$this
->assertTrue(!isset($original_settings[$expected['setting_name']]), t('Page originally lacks the %setting, as expected.', array(
'%setting' => $expected['setting_name'],
)));
$this
->assertTrue(!isset($original_settings[$expected['css']]), t('Page originally lacks the %css file, as expected.', array(
'%css' => $expected['css'],
)));
$this
->assertTrue(!isset($original_settings[$expected['js']]), t('Page originally lacks the %js file, as expected.', array(
'%js' => $expected['js'],
)));
$commands = $this
->drupalPostAJAX(NULL, array(
'add_files' => FALSE,
), array(
'op' => t('Submit'),
));
$new_settings = $this
->drupalGetSettings();
$this
->assertTrue(!isset($new_settings['setting_name']), t('Page still lacks the %setting, as expected.', array(
'%setting' => $expected['setting_name'],
)));
$found_settings_command = FALSE;
$found_markup_command = FALSE;
foreach ($commands as $command) {
if ($command['command'] == 'settings' && (array_key_exists('css', $command['settings']['ajaxPageState']) || array_key_exists('js', $command['settings']['ajaxPageState']))) {
$found_settings_command = TRUE;
}
if (isset($command['data']) && ($command['data'] == $expected_js_html || $command['data'] == $expected_css_html)) {
$found_markup_command = TRUE;
}
}
$this
->assertFalse($found_settings_command, t('Page state still lacks the %css and %js files, as expected.', array(
'%css' => $expected['css'],
'%js' => $expected['js'],
)));
$this
->assertFalse($found_markup_command, t('Page still lacks the %css and %js files, as expected.', array(
'%css' => $expected['css'],
'%js' => $expected['js'],
)));
$commands = $this
->drupalPostAJAX(NULL, array(
'add_files' => TRUE,
), array(
'op' => t('Submit'),
));
$new_settings = $this
->drupalGetSettings();
$new_css = $new_settings['ajaxPageState']['css'];
$new_js = $new_settings['ajaxPageState']['js'];
$this
->assertIdentical($new_settings[$expected['setting_name']], $expected['setting_value'], t('Page now has the %setting.', array(
'%setting' => $expected['setting_name'],
)));
$this
->assertEqual($new_css, $original_css + array(
$expected['css'] => 1,
), t('Page state now has the %css file.', array(
'%css' => $expected['css'],
)));
$this
->assertCommand($commands, array(
'data' => $expected_css_html,
), t('Page now has the %css file.', array(
'%css' => $expected['css'],
)));
$this
->assertEqual($new_js, $original_js + array(
$expected['js'] => 1,
), t('Page state now has the %js file.', array(
'%js' => $expected['js'],
)));
$this
->assertCommand($commands, array(
'data' => $expected_js_html,
), t('Page now has the %js file.', array(
'%js' => $expected['js'],
)));
}
function testLazyLoadOverriddenCSS() {
theme_enable(array(
'test_theme',
));
variable_set('theme_default', 'test_theme');
$this
->drupalPostAJAX('ajax_forms_test_lazy_load_form', array(
'add_files' => TRUE,
), array(
'op' => t('Submit'),
));
$this
->assertNoText('system.base.css?', 'Ajax lazy loading does not add overridden CSS files.');
}
}
class AJAXCommandsTestCase extends AJAXTestCase {
public static function getInfo() {
return array(
'name' => 'AJAX commands',
'description' => 'Performs tests on AJAX framework commands.',
'group' => 'AJAX',
);
}
function testAJAXCommands() {
$form_path = 'ajax_forms_test_ajax_commands_form';
$web_user = $this
->drupalCreateUser(array(
'access content',
));
$this
->drupalLogin($web_user);
$edit = array();
$commands = $this
->drupalPostAJAX($form_path, $edit, array(
'op' => t("AJAX 'After': Click to put something after the div"),
));
$expected = array(
'command' => 'insert',
'method' => 'after',
'data' => 'This will be placed after',
);
$this
->assertCommand($commands, $expected, "'after' AJAX command issued with correct data");
$commands = $this
->drupalPostAJAX($form_path, $edit, array(
'op' => t("AJAX 'Alert': Click to alert"),
));
$expected = array(
'command' => 'alert',
'text' => 'Alert',
);
$this
->assertCommand($commands, $expected, "'alert' AJAX Command issued with correct text");
$commands = $this
->drupalPostAJAX($form_path, $edit, array(
'op' => t("AJAX 'Append': Click to append something"),
));
$expected = array(
'command' => 'insert',
'method' => 'append',
'data' => 'Appended text',
);
$this
->assertCommand($commands, $expected, "'append' AJAX command issued with correct data");
$commands = $this
->drupalPostAJAX($form_path, $edit, array(
'op' => t("AJAX 'before': Click to put something before the div"),
));
$expected = array(
'command' => 'insert',
'method' => 'before',
'data' => 'Before text',
);
$this
->assertCommand($commands, $expected, "'before' AJAX command issued with correct data");
$commands = $this
->drupalPostAJAX($form_path, $edit, array(
'op' => t("AJAX changed: Click to mark div changed."),
));
$expected = array(
'command' => 'changed',
'selector' => '#changed_div',
);
$this
->assertCommand($commands, $expected, "'changed' AJAX command issued with correct selector");
$commands = $this
->drupalPostAJAX($form_path, $edit, array(
'op' => t("AJAX changed: Click to mark div changed with asterisk."),
));
$expected = array(
'command' => 'changed',
'selector' => '#changed_div',
'asterisk' => '#changed_div_mark_this',
);
$this
->assertCommand($commands, $expected, "'changed' AJAX command (with asterisk) issued with correct selector");
$commands = $this
->drupalPostAJAX($form_path, $edit, array(
'op' => t("Set the '#box' div to be blue."),
));
$expected = array(
'command' => 'css',
'selector' => '#css_div',
'argument' => array(
'background-color' => 'blue',
),
);
$this
->assertCommand($commands, $expected, "'css' AJAX command issued with correct selector");
$commands = $this
->drupalPostAJAX($form_path, $edit, array(
'op' => t("AJAX data command: Issue command."),
));
$expected = array(
'command' => 'data',
'name' => 'testkey',
'value' => 'testvalue',
);
$this
->assertCommand($commands, $expected, "'data' AJAX command issued with correct key and value");
$commands = $this
->drupalPostAJAX($form_path, $edit, array(
'op' => t("AJAX invoke command: Invoke addClass() method."),
));
$expected = array(
'command' => 'invoke',
'method' => 'addClass',
'arguments' => array(
'error',
),
);
$this
->assertCommand($commands, $expected, "'invoke' AJAX command issued with correct method and argument");
$commands = $this
->drupalPostAJAX($form_path, $edit, array(
'op' => t("AJAX html: Replace the HTML in a selector."),
));
$expected = array(
'command' => 'insert',
'method' => 'html',
'data' => 'replacement text',
);
$this
->assertCommand($commands, $expected, "'html' AJAX command issued with correct data");
$commands = $this
->drupalPostAJAX($form_path, $edit, array(
'op' => t("AJAX insert: Let client insert based on #ajax['method']."),
));
$expected = array(
'command' => 'insert',
'data' => 'insert replacement text',
);
$this
->assertCommand($commands, $expected, "'insert' AJAX command issued with correct data");
$commands = $this
->drupalPostAJAX($form_path, $edit, array(
'op' => t("AJAX 'prepend': Click to prepend something"),
));
$expected = array(
'command' => 'insert',
'method' => 'prepend',
'data' => 'prepended text',
);
$this
->assertCommand($commands, $expected, "'prepend' AJAX command issued with correct data");
$commands = $this
->drupalPostAJAX($form_path, $edit, array(
'op' => t("AJAX 'remove': Click to remove text"),
));
$expected = array(
'command' => 'remove',
'selector' => '#remove_text',
);
$this
->assertCommand($commands, $expected, "'remove' AJAX command issued with correct command and selector");
$commands = $this
->drupalPostAJAX($form_path, $edit, array(
'op' => t("AJAX 'restripe' command"),
));
$expected = array(
'command' => 'restripe',
'selector' => '#restripe_table',
);
$this
->assertCommand($commands, $expected, "'restripe' AJAX command issued with correct selector");
$commands = $this
->drupalPostAJAX($form_path, $edit, array(
'op' => t("AJAX 'settings' command"),
));
$expected = array(
'command' => 'settings',
'settings' => array(
'ajax_forms_test' => array(
'foo' => 42,
),
),
);
$this
->assertCommand($commands, $expected, "'settings' AJAX command issued with correct data");
$commands = $this
->drupalPostAJAX($form_path, $edit, array(
'op' => t("AJAX 'add_css' command"),
));
$expected = array(
'command' => 'add_css',
'data' => 'my/file.css',
);
$this
->assertCommand($commands, $expected, "'add_css' AJAX command issued with correct data");
}
}
class AJAXFormValuesTestCase extends AJAXTestCase {
public static function getInfo() {
return array(
'name' => 'AJAX command form values',
'description' => 'Tests that form values are properly delivered to AJAX callbacks.',
'group' => 'AJAX',
);
}
function setUp() {
parent::setUp();
$this->web_user = $this
->drupalCreateUser(array(
'access content',
));
$this
->drupalLogin($this->web_user);
}
function testSimpleAJAXFormValue() {
foreach (array(
'red',
'green',
'blue',
) as $item) {
$edit = array(
'select' => $item,
);
$commands = $this
->drupalPostAJAX('ajax_forms_test_get_form', $edit, 'select');
$expected = array(
'command' => 'data',
'value' => $item,
);
$this
->assertCommand($commands, $expected, "verification of AJAX form values from a selectbox issued with a correct value");
}
foreach (array(
FALSE,
TRUE,
) as $item) {
$edit = array(
'checkbox' => $item,
);
$commands = $this
->drupalPostAJAX('ajax_forms_test_get_form', $edit, 'checkbox');
$expected = array(
'command' => 'data',
'value' => (int) $item,
);
$this
->assertCommand($commands, $expected, "verification of AJAX form values from a checkbox issued with a correct value");
}
}
}
class AJAXMultiFormTestCase extends AJAXTestCase {
public static function getInfo() {
return array(
'name' => 'AJAX multi form',
'description' => 'Tests that AJAX-enabled forms work when multiple instances of the same form are on a page.',
'group' => 'AJAX',
);
}
function setUp() {
parent::setUp(array(
'form_test',
));
$field_name = 'field_ajax_test';
$field = array(
'field_name' => $field_name,
'type' => 'text',
'cardinality' => FIELD_CARDINALITY_UNLIMITED,
);
field_create_field($field);
$instance = array(
'field_name' => $field_name,
'entity_type' => 'node',
'bundle' => 'page',
);
field_create_instance($instance);
$this->web_user = $this
->drupalCreateUser(array(
'create page content',
));
$this
->drupalLogin($this->web_user);
}
function testMultiForm() {
$field_name = 'field_ajax_test';
$field_xpaths = array(
'page-node-form' => '//form[@id="page-node-form"]//div[contains(@class, "field-name-field-ajax-test")]',
'page-node-form--2' => '//form[@id="page-node-form--2"]//div[contains(@class, "field-name-field-ajax-test")]',
);
$button_name = $field_name . '_add_more';
$button_value = t('Add another item');
$button_xpath_suffix = '//input[@name="' . $button_name . '"]';
$field_items_xpath_suffix = '//input[@type="text"]';
$this
->drupalGet('form-test/two-instances-of-same-form');
foreach ($field_xpaths as $form_html_id => $field_xpath) {
$this
->assert(count($this
->xpath($field_xpath . $field_items_xpath_suffix)) == 1, t('Found the correct number of field items on the initial page.'));
$this
->assertFieldByXPath($field_xpath . $button_xpath_suffix, NULL, t('Found the "add more" button on the initial page.'));
}
$this
->assertNoDuplicateIds(t('Initial page contains unique IDs'), 'Other');
foreach ($field_xpaths as $form_html_id => $field_xpath) {
for ($i = 0; $i < 2; $i++) {
$this
->drupalPostAJAX(NULL, array(), array(
$button_name => $button_value,
), 'system/ajax', array(), array(), $form_html_id);
$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.'));
$this
->assertFieldByXPath($field_xpath . $button_xpath_suffix, NULL, t('Found the "add more" button after an AJAX submission.'));
$this
->assertNoDuplicateIds(t('Updated page contains unique IDs'), 'Other');
}
}
}
}
class AJAXFormPageCacheTestCase extends AJAXTestCase {
protected $profile = 'testing';
public static function getInfo() {
return array(
'name' => 'AJAX forms on cached pages',
'description' => 'Tests that AJAX forms work properly for anonymous users on cached pages.',
'group' => 'AJAX',
);
}
public function setUp() {
parent::setUp();
variable_set('cache', TRUE);
}
protected function getFormBuildId() {
$build_id_fields = $this
->xpath('//input[@name="form_build_id"]');
$this
->assertEqual(count($build_id_fields), 1, 'One form build id field on the page');
return (string) $build_id_fields[0]['value'];
}
public function testSimpleAJAXFormValue() {
$this
->drupalGet('ajax_forms_test_get_form');
$this
->assertEqual($this
->drupalGetHeader('X-Drupal-Cache'), 'MISS', 'Page was not cached.');
$build_id_initial = $this
->getFormBuildId();
$edit = array(
'select' => 'green',
);
$commands = $this
->drupalPostAJAX(NULL, $edit, 'select');
$build_id_first_ajax = $this
->getFormBuildId();
$this
->assertNotEqual($build_id_initial, $build_id_first_ajax, 'Build id is changed in the simpletest-DOM on first AJAX submission');
$expected = array(
'command' => 'updateBuildId',
'old' => $build_id_initial,
'new' => $build_id_first_ajax,
);
$this
->assertCommand($commands, $expected, 'Build id change command issued on first AJAX submission');
$edit = array(
'select' => 'red',
);
$commands = $this
->drupalPostAJAX(NULL, $edit, 'select');
$build_id_second_ajax = $this
->getFormBuildId();
$this
->assertEqual($build_id_first_ajax, $build_id_second_ajax, 'Build id remains the same on subsequent AJAX submissions');
$this
->drupalGet('ajax_forms_test_get_form');
$this
->assertEqual($this
->drupalGetHeader('X-Drupal-Cache'), 'HIT', 'Page was cached.');
$build_id_from_cache_initial = $this
->getFormBuildId();
$this
->assertEqual($build_id_initial, $build_id_from_cache_initial, 'Build id is the same as on the first request');
$edit = array(
'select' => 'green',
);
$commands = $this
->drupalPostAJAX(NULL, $edit, 'select');
$build_id_from_cache_first_ajax = $this
->getFormBuildId();
$this
->assertNotEqual($build_id_from_cache_initial, $build_id_from_cache_first_ajax, 'Build id is changed in the simpletest-DOM on first AJAX submission');
$this
->assertNotEqual($build_id_first_ajax, $build_id_from_cache_first_ajax, 'Build id from first user is not reused');
$expected = array(
'command' => 'updateBuildId',
'old' => $build_id_from_cache_initial,
'new' => $build_id_from_cache_first_ajax,
);
$this
->assertCommand($commands, $expected, 'Build id change command issued on first AJAX submission');
$edit = array(
'select' => 'red',
);
$commands = $this
->drupalPostAJAX(NULL, $edit, 'select');
$build_id_from_cache_second_ajax = $this
->getFormBuildId();
$this
->assertEqual($build_id_from_cache_first_ajax, $build_id_from_cache_second_ajax, 'Build id remains the same on subsequent AJAX submissions');
}
}
class AJAXElementValidation extends AJAXTestCase {
public static function getInfo() {
return array(
'name' => 'Miscellaneous AJAX tests',
'description' => 'Various tests of AJAX behavior',
'group' => 'AJAX',
);
}
function testAJAXElementValidation() {
$web_user = $this
->drupalCreateUser();
$edit = array(
'drivertext' => t('some dumb text'),
);
$post_result = $this
->drupalPostAJAX('ajax_validation_test', $edit, 'drivertext');
$this
->assertNoText(t('Error message'), "No error message in resultant JSON");
$this
->assertText('ajax_forms_test_validation_form_callback invoked', 'The correct callback was invoked');
}
}