From ef1fd4887aedfd7c33477300977fadd053478b1e Mon Sep 17 00:00:00 2001 From: Dries Buytaert Date: Tue, 29 Jun 2010 18:24:10 +0000 Subject: - Patch #721086 by rfay, aspilicious, andypost: create tests for system actions, clean up token replacement, clean up triggers. --- modules/trigger/tests/trigger_test.module | 1 - modules/trigger/trigger.module | 17 +- modules/trigger/trigger.test | 325 ++++++++++++++++++++++++++++-- 3 files changed, 315 insertions(+), 28 deletions(-) (limited to 'modules/trigger') diff --git a/modules/trigger/tests/trigger_test.module b/modules/trigger/tests/trigger_test.module index 9f0eeadd3..064287251 100644 --- a/modules/trigger/tests/trigger_test.module +++ b/modules/trigger/tests/trigger_test.module @@ -35,7 +35,6 @@ function trigger_test_action_info() { 'comment_insert', 'comment_update', 'comment_delete', - 'user_presave', 'user_insert', 'user_update', 'user_delete', diff --git a/modules/trigger/trigger.module b/modules/trigger/trigger.module index 93ed2485c..91c36c65d 100644 --- a/modules/trigger/trigger.module +++ b/modules/trigger/trigger.module @@ -145,9 +145,6 @@ function trigger_trigger_info() { ), ), 'user' => array( - 'user_presave' => array( - 'label' => t('When either creating a new user account or updating an existing'), - ), 'user_insert' => array( 'label' => t('After creating a new user account'), ), @@ -488,17 +485,10 @@ function trigger_user_login(&$edit, $account, $category) { * Implements hook_user_logout(). */ function trigger_user_logout($account) { - $edit = NULL; + $edit = array(); _trigger_user('user_logout', $edit, $account); } -/** - * Implements hook_user_presave(). - */ -function trigger_user_presave(&$edit, $account, $category) { - _trigger_user('user_presave', $edit, $account, $category); -} - /** * Implements hook_user_insert(). */ @@ -528,7 +518,8 @@ function trigger_user_cancel($edit, $account, $method) { * Implements hook_user_delete(). */ function trigger_user_delete($account) { - _trigger_user('user_delete', $edit, $account, $method); + $edit = array(); + _trigger_user('user_delete', $edit, $account, NULL); } /** @@ -557,7 +548,7 @@ function _trigger_user($hook, &$edit, $account, $category = NULL) { if (!isset($objects[$type])) { $objects[$type] = _trigger_normalize_user_context($type, $account); } - $context['account'] = $account; + $context['user'] = $account; actions_do($aid, $objects[$type], $context); } else { diff --git a/modules/trigger/trigger.test b/modules/trigger/trigger.test index fd4e2be42..461686993 100644 --- a/modules/trigger/trigger.test +++ b/modules/trigger/trigger.test @@ -2,7 +2,7 @@ // $Id$ /** - * Class with common helper methods. + * Provides common helper methods. */ class TriggerWebTestCase extends DrupalWebTestCase { @@ -14,6 +14,7 @@ class TriggerWebTestCase extends DrupalWebTestCase { * @param $edit * The $edit array for the form to be used to configure. * Example members would be 'actions_label' (always), 'message', etc. + * * @return * the aid (action id) of the configured action, or FALSE if none. */ @@ -30,7 +31,7 @@ class TriggerWebTestCase extends DrupalWebTestCase { } /** - * Test node triggers. + * Provides tests for node triggers. */ class TriggerContentTestCase extends TriggerWebTestCase { var $_cleanup_roles = array(); @@ -49,7 +50,9 @@ class TriggerContentTestCase extends TriggerWebTestCase { } /** - * Various tests, all in one function to assure they happen in the right order. + * Tests several content-oriented trigger issues. + * + * These are in one function to assure they happen in the right order. */ function testActionsContent() { global $user; @@ -98,8 +101,10 @@ class TriggerContentTestCase extends TriggerWebTestCase { } /** - * Test that node actions are fired for each node individually if acting on - * multiple nodes. + * Tests multiple node actions. + * + * Verifies that node actions are fired for each node individually, if acting + * on multiple nodes. */ function testActionContentMultiple() { // Assign an action to the node save/update trigger. @@ -127,10 +132,13 @@ class TriggerContentTestCase extends TriggerWebTestCase { } /** - * Helper function for testActionsContent(): returns some info about each of the content actions. + * Returns some info about each of the content actions. + * + * This is helper function for testActionsContent(). * * @param $action * The name of the action to return info about. + * * @return * An associative array of info about the action. */ @@ -172,7 +180,7 @@ class TriggerContentTestCase extends TriggerWebTestCase { } /** - * Test cron trigger. + * Tests cron trigger. */ class TriggerCronTestCase extends TriggerWebTestCase { public static function getInfo() { @@ -188,7 +196,7 @@ class TriggerCronTestCase extends TriggerWebTestCase { } /** - * Test assigning multiple actions to the cron trigger. + * Tests assigning multiple actions to the cron trigger. * * This test ensures that both simple and multiple complex actions * succeed properly. This is done in the cron trigger test because @@ -239,7 +247,296 @@ class TriggerCronTestCase extends TriggerWebTestCase { } /** - * Test other triggers. + * Provides a base class with trigger assignments and test comparisons. + */ +class TriggerActionTestCase extends TriggerWebTestCase { + + function setUp() { + parent::setUp('trigger'); + } + + /** + * Creates a message with tokens. + * + * @param $trigger + * + * @return + * A message with embedded tokens. + */ + function generateMessageWithTokens($trigger) { + // Note that subject is limited to 254 characters in action configuration. + $message = t('Action was triggered by trigger @trigger user:name=[user:name] user:uid=[user:uid] user:mail=[user:mail] user:url=[user:url] user:edit-url=[user:edit-url] user:created=[user:created]', + array('@trigger' => $trigger)); + return trim($message); + } + + /** + * Generates a comparison message to match the pre-token-replaced message. + * + * @param $trigger + * Trigger, like 'user_login'. + * @param $account + * Associated user account. + * + * @return + * The token-replaced equivalent message. This does not use token + * functionality. + * + * @see generateMessageWithTokens() + */ + function generateTokenExpandedComparison($trigger, $account) { + // Note that user:last-login was omitted because it changes and can't + // be properly verified. + $message = t('Action was triggered by trigger @trigger user:name=@username user:uid=@uid user:mail=@mail user:url=@user_url user:edit-url=@user_edit_url user:created=@user_created', + array( + '@trigger' => $trigger, + '@username' => $account->name, + '@uid' => !empty($account->uid) ? $account->uid : t('not yet assigned'), + '@mail' => $account->mail, + '@user_url' => !empty($account->uid) ? url("user/$account->uid", array('absolute' => TRUE)) : t('not yet assigned'), + '@user_edit_url' => !empty($account->uid) ? url("user/$account->uid/edit", array('absolute' => TRUE)) : t('not yet assigned'), + '@user_created' => isset($account->created) ? format_date($account->created, 'medium') : t('not yet created'), + ) + ); + return trim($message); + } + + + /** + * Assigns a simple (non-configurable) action to a trigger. + * + * @param $trigger + * The trigger to assign to, like 'user_login'. + * @param $action + * The simple action to be assigned, like 'comment_insert'. + */ + function assignSimpleAction($trigger, $action) { + $form_name = "trigger_{$trigger}_assign_form"; + $form_html_id = strtr($form_name, '_', '-'); + $edit = array('aid' => drupal_hash_base64($action)); + $trigger_type = preg_replace('/_.*/', '', $trigger); + $this->drupalPost("admin/structure/trigger/$trigger_type", $edit, t('Assign'), array(), array(), $form_html_id); + $actions = trigger_get_assigned_actions($trigger); + $this->assertTrue(!empty($actions[$action]), t('Simple action @action assigned to trigger @trigger', array('@action' => $action, '@trigger' => $trigger))); + } + + /** + * Assigns a system message action to the passed-in trigger. + * + * @param $trigger + * For example, 'user_login' + */ + function assignSystemMessageAction($trigger) { + $form_name = "trigger_{$trigger}_assign_form"; + $form_html_id = strtr($form_name, '_', '-'); + // Assign a configurable action 'System message' to the passed trigger. + $action_edit = array( + 'actions_label' => $trigger . "_system_message_action_" . $this->randomName(16), + 'message' => $this->generateMessageWithTokens($trigger), + ); + + // Configure an advanced action that we can assign. + $aid = $this->configureAdvancedAction('system_message_action', $action_edit); + + $edit = array('aid' => drupal_hash_base64($aid)); + $this->drupalPost('admin/structure/trigger/user', $edit, t('Assign'), array(), array(), $form_html_id); + } + + + /** + * Assigns a system_send_email_action to the passed-in trigger. + * + * @param $trigger + * For example, 'user_login' + */ + function assignSystemEmailAction($trigger) { + $form_name = "trigger_{$trigger}_assign_form"; + $form_html_id = strtr($form_name, '_', '-'); + + $message = $this->generateMessageWithTokens($trigger); + // Assign a configurable action 'System message' to the passed trigger. + $action_edit = array( + // 'actions_label' => $trigger . "_system_send_message_action_" . $this->randomName(16), + 'actions_label' => $trigger . "_system_send_email_action", + 'recipient' => '[user:mail]', + 'subject' => $message, + 'message' => $message, + ); + + // Configure an advanced action that we can assign. + $aid = $this->configureAdvancedAction('system_send_email_action', $action_edit); + + $edit = array('aid' => drupal_hash_base64($aid)); + $this->drupalPost('admin/structure/trigger/user', $edit, t('Assign'), array(), array(), $form_html_id); + } + + /** + * Asserts correct token replacement in both system message and email. + * + * @param $trigger + * A trigger like 'user_login'. + * @param $account + * The user account which triggered the action. + * @param $email_depth + * Number of emails to scan, starting with most recent. + */ + function assertSystemMessageAndEmailTokenReplacement($trigger, $account, $email_depth = 1) { + $this->assertSystemMessageTokenReplacement($trigger, $account); + $this->assertSystemEmailTokenReplacement($trigger, $account, $email_depth); + } + + /** + * Asserts correct token replacement for the given trigger and account. + * + * @param $trigger + * A trigger like 'user_login'. + * @param $account + * The user account which triggered the action. + */ + function assertSystemMessageTokenReplacement($trigger, $account) { + $expected = $this->generateTokenExpandedComparison($trigger, $account); + $this->assertText($expected, + t('Expected system message to contain token-replaced text "@expected" found in configured system message action', array('@expected' => $expected )) ); + } + + + /** + * Asserts correct token replacement for the given trigger and account. + * + * @param $trigger + * A trigger like 'user_login'. + * @param $account + * The user account which triggered the action. + * @param $email_depth + * Number of emails to scan, starting with most recent. + */ + function assertSystemEmailTokenReplacement($trigger, $account, $email_depth = 1) { + $this->verboseEmail($email_depth); + $expected = $this->generateTokenExpandedComparison($trigger, $account); + $this->assertMailString('subject', $expected, $email_depth); + $this->assertMailString('body', $expected, $email_depth); + $this->assertMail('to', $account->mail, t('Mail sent to correct destination')); + } +} + +/** + * Tests token substitution in trigger actions. + * + * This tests nearly every permutation of user triggers with system actions + * and checks the token replacement. + */ +class TriggerUserTokenTestCase extends TriggerActionTestCase { + public static function getInfo() { + return array( + 'name' => 'Test user triggers', + 'description' => 'Test user triggers and system actions with token replacement.', + 'group' => 'Trigger', + ); + } + + + /** + * Tests a variety of token replacements in actions. + */ + function testUserTriggerTokenReplacement() { + $test_user = $this->drupalCreateUser(array('administer actions', 'administer users', 'change own username', 'access user profiles')); + $this->drupalLogin($test_user); + + $triggers = array('user_login', 'user_insert', 'user_update', 'user_delete', 'user_logout', 'user_view'); + foreach ($triggers as $trigger) { + $this->assignSystemMessageAction($trigger); + $this->assignSystemEmailAction($trigger); + } + + $this->drupalLogout(); + $this->assertSystemEmailTokenReplacement('user_logout', $test_user); + + $this->drupalLogin($test_user); + $this->assertSystemMessageAndEmailTokenReplacement('user_login', $test_user, 2); + $this->assertSystemMessageAndEmailTokenReplacement('user_view', $test_user, 2); + + $this->drupalPost("user/{$test_user->uid}/edit", array('name' => $test_user->name . '_changed'), t('Save')); + $test_user->name .= '_changed'; // Since we just changed it. + $this->assertSystemMessageAndEmailTokenReplacement('user_update', $test_user, 2); + + $this->drupalGet('user'); + $this->assertSystemMessageAndEmailTokenReplacement('user_view', $test_user); + + $new_user = $this->drupalCreateUser(array('administer actions', 'administer users', 'cancel account', 'access administration pages')); + $this->assertSystemEmailTokenReplacement('user_insert', $new_user); + + $this->drupalLogin($new_user); + $user_to_delete = $this->drupalCreateUser(array('access content')); + variable_set('user_cancel_method', 'user_cancel_delete'); + + $this->drupalPost("user/{$user_to_delete->uid}/cancel", array(), t('Cancel account')); + $this->assertSystemMessageAndEmailTokenReplacement('user_delete', $user_to_delete); + } + + +} + +/** + * Tests token substitution in trigger actions. + * + * This tests nearly every permutation of user triggers with system actions + * and checks the token replacement. + */ +class TriggerUserActionTestCase extends TriggerActionTestCase { + public static function getInfo() { + return array( + 'name' => 'Test user actions', + 'description' => 'Test user actions.', + 'group' => 'Trigger', + ); + } + + /** + * Tests user action assignment and execution. + */ + function testUserActionAssignmentExecution() { + $test_user = $this->drupalCreateUser(array('administer actions', 'create article content', 'access comments', 'administer comments', 'post comments without approval', 'edit own comments')); + $this->drupalLogin($test_user); + + $triggers = array('comment_presave', 'comment_insert', 'comment_update'); + // system_block_ip_action is difficult to test without ruining the test. + $actions = array('user_block_user_action'); + foreach ($triggers as $trigger) { + foreach ($actions as $action) { + $this->assignSimpleAction($trigger, $action); + } + } + + $node = $this->drupalCreateNode(array('type' => 'article')); + $this->drupalPost("node/{$node->nid}", array('comment_body[und][0][value]' => t("my comment"), 'subject' => t("my comment subject")), t('Save')); + // Posting a comment should have blocked this user. + $account = user_load($test_user->uid, TRUE); + $this->assertTrue($account->status == 0, t('Account is blocked')); + $comment_author_uid = $account->uid; + // Now rehabilitate the comment author so it can be be blocked again when + // the comment is updated. + user_save($account, array('status' => TRUE)); + + $test_user = $this->drupalCreateUser(array('administer actions', 'create article content', 'access comments', 'administer comments', 'post comments without approval', 'edit own comments')); + $this->drupalLogin($test_user); + + // Our original comment will have been comment 1. + $this->drupalPost("comment/1/edit", array('comment_body[und][0][value]' => t("my comment, updated"), 'subject' => t("my comment subject")), t('Save')); + $comment_author_account = user_load($comment_author_uid, TRUE); + $this->assertTrue($comment_author_account->status == 0, t('Comment author account (uid=@uid) is blocked after update to comment', array('@uid' => $comment_author_uid))); + + // Verify that the comment was updated. + $test_user = $this->drupalCreateUser(array('administer actions', 'create article content', 'access comments', 'administer comments', 'post comments without approval', 'edit own comments')); + $this->drupalLogin($test_user); + + $this->drupalGet("node/$node->nid"); + $this->assertText(t("my comment, updated")); + $this->verboseEmail(); + } +} + +/** + * Tests other triggers. */ class TriggerOtherTestCase extends TriggerWebTestCase { var $_cleanup_roles = array(); @@ -258,7 +555,7 @@ class TriggerOtherTestCase extends TriggerWebTestCase { } /** - * Test triggering on user create and user login. + * Tests triggering on user create and user login. */ function testActionsUser() { // Assign an action to the create user trigger. @@ -315,7 +612,7 @@ class TriggerOtherTestCase extends TriggerWebTestCase { } /** - * Test triggering on comment save. + * Tests triggering on comment save. */ function testActionsComment() { // Assign an action to the comment save trigger. @@ -344,7 +641,7 @@ class TriggerOtherTestCase extends TriggerWebTestCase { } /** - * Test triggering on taxonomy new term. + * Tests triggering on taxonomy new term. */ function testActionsTaxonomy() { // Assign an action to the taxonomy term save trigger. @@ -382,7 +679,7 @@ class TriggerOtherTestCase extends TriggerWebTestCase { } /** - * Test that orphaned actions are properly handled. + * Tests that orphaned actions are properly handled. */ class TriggerOrphanedActionsTestCase extends DrupalWebTestCase { @@ -399,7 +696,7 @@ class TriggerOrphanedActionsTestCase extends DrupalWebTestCase { } /** - * Test logic around orphaned actions. + * Tests logic around orphaned actions. */ function testActionsOrphaned() { $action = 'trigger_test_generic_any_action'; -- cgit v1.2.3