Come from http://drupal.org/node/286668#comment-2137598

Page at admin/structure/trigger have multiple forms but there's no ability to assign an action to specific trigger - at always assigns to a first form.

DrupalPost() should be changed to make a specific form submit on page otherwise all trigger|action test are faik.

Tests from #20 with debug #286668: Trigger "User logging in" doesn't work with Action "Forward to URL" could be useful to explain

Comments

andypost’s picture

Issue tags: +actions, +triggers, +Simpletest, +API clean-up, +D7 API clean-up

Added tags

andypost’s picture

Status: Active » Needs review
StatusFileSize
new787 bytes

Simple fix is to add a hidden field values to filter values

andypost’s picture

StatusFileSize
new1.11 KB

This is a test to hit a bug

andypost’s picture

StatusFileSize
new1.36 KB

Previous patch was not unified

Status: Needs review » Needs work

The last submitted patch failed testing.

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new1.34 KB

Now without hidden field

Status: Needs review » Needs work

The last submitted patch failed testing.

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new2.19 KB

Now using a hidden field to assign action to specific hook

Status: Needs review » Needs work

The last submitted patch failed testing.

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new1.45 KB

Try bot this one

Status: Needs review » Needs work

The last submitted patch failed testing.

andypost’s picture

StatusFileSize
new2.19 KB

This one should fix, previous was without simpletest fix

andypost’s picture

Status: Needs work » Needs review

Let's test

andypost’s picture

StatusFileSize
new3.16 KB

Re-roll with code-style fixes

chx’s picture

Status: Needs review » Reviewed & tested by the community

That's a good one.

Status: Reviewed & tested by the community » Needs work

The last submitted patch failed testing.

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new3.08 KB
+++ modules/trigger/trigger.test	11 Oct 2009 14:57:16 -0000
@@ -228,7 +228,31 @@ class TriggerOtherTestCase extends Drupa
+    $hook = 'user_register';

merged from other patch, now hook is user_login

+++ modules/trigger/trigger.test	11 Oct 2009 14:57:16 -0000
@@ -228,7 +228,31 @@ class TriggerOtherTestCase extends Drupa
+    // Verify that the trigger's hook has assigned action.
+    $actions = trigger_get_assigned_actions($hook);
+    $this->assertEqual(1, count($actions), t('Action assigned'));
+    $this->assertEqual($actions[1]->label, $action_label, t('Action label equal'));

trigger_get_assigned_actions returns array of arrays

amc’s picture

Title: Simpletest does not allows to assings actions to triggers » Simpletest does not allow assigning actions to triggers
chx’s picture

Status: Needs review » Reviewed & tested by the community

I have RTBC'd above 'cos I knew that the bot can set to CNW should a test fail. I am still content with the patch and now the bot is too.

dries’s picture

Status: Reviewed & tested by the community » Needs work
+++ modules/trigger/trigger.test	11 Oct 2009 15:13:19 -0000
@@ -228,7 +228,31 @@ class TriggerOtherTestCase extends Drupa
+    // Verify that the trigger's hook has assigned action.

Looks like there is a word missing to make this sentence 'flow'.

Should be easy to fix!

andypost’s picture

Oh my... english
This should be like

Check that action assigned to the right hook of the trigger

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new3.08 KB

Another try with a google's help

robertdouglass’s picture

Change

+ // Verify that the action assigned to correct hook.
+ $actions = trigger_get_assigned_actions($hook);

to

+ // Verify that the action has been assigned to the correct hook.
+ $actions = trigger_get_assigned_actions($hook);

andypost’s picture

StatusFileSize
new3.09 KB

@robertDouglass many thanx!

Re-rolled and after commit ging to check all trigger's tests

chx’s picture

Status: Needs review » Reviewed & tested by the community

OK then back to the green queue.

webchick’s picture

Status: Reviewed & tested by the community » Needs review

Shouldn't we go one step further and ensure that the action actually fires when the user logs in?

damien tournoud’s picture

Status: Needs review » Needs work
+          case 'hidden':
+            if ($edit[$name] == $value) {
+              unset($edit[$name]);
+            }
+            break;

I have no idea what this is doing. Please explain and add comments.

andypost’s picture

Status: Needs work » Reviewed & tested by the community

@webchick this patch is a first step before
1) #286668: Trigger "User logging in" doesn't work with Action "Forward to URL" here is a actual test for action - redirect user to custom page, but it needs another fix in system_goto_action() so current patch is just a part of this URL redirect test - just ensure that we POST to pointed form in multiform page!
2) #43483: Add trigger/action for custom after-register, after-login and after-logout events same but needs this test to continue work

@Damien Tournoud this adds a check for hidden fields, if hidden field has been found in form body then next part of code is not trying to set field so form is not throwing an error on POST, this helps to filter forms for triggers page where all form have one form-builder, using a hidden field to filter give us ability to make POST into pointer form

damien tournoud’s picture

Status: Reviewed & tested by the community » Needs work

This still needs documentation, and I'm not really sure that the solution makes sense. I would expect that hidden fields need to be treated like text, textarea and password. We need to pass them to post anyway.

andypost’s picture

Status: Needs work » Needs review

@Damien Tournoud : Hidden fields are read-only so you cant set them - if you try you get an error. They are send to server by default.
A handleForm method :

/**
* Handle form input related to drupalPost(). Ensure that the specified fields
* exist
and attempt to create POST data in the correct manner for the particular
* field type.

This patch just adds support for hidden fields to default functionality (verification of existence corresponding fields by field-name) that I mark with strong in comment ^.

I see no reason to document already documented functionality...

sun’s picture

Just explain what you just explained in an inline comment for that case statement and be done with it.

andypost’s picture

StatusFileSize
new3.14 KB

Addes in-line comment for hidden field

sun’s picture

+++ modules/simpletest/drupal_web_test_case.php	12 Oct 2009 21:22:55 -0000
@@ -1621,6 +1621,12 @@ class DrupalWebTestCase extends DrupalTe
+          case 'hidden':
+            // Ensure that element exists.

uhm, replace that with maybe: "Normally, hidden fields are considered read-only. However, to allow to submit multiple forms on a single page that only differ in a hidden value, we allow their value to be overridden."

I'm on crack. Are you, too?

andypost’s picture

StatusFileSize
new3.35 KB

Not allow to override but specify in $edit to filter form by this value

Please check, is this comment correct in English

sun’s picture

StatusFileSize
new3.33 KB

uhm, I just wanted to fix the wrapping of that inline comment, but after looking at the actual code and how the processed values of handleForm() are used afterwards, that inline comment is utterly wrong.

Anyway, since I did it, you get it.

andypost’s picture

Status: Needs review » Reviewed & tested by the community

Thanx, now RTBC again

sun’s picture

Status: Reviewed & tested by the community » Needs review

that inline comment is utterly wrong.

andypost’s picture

StatusFileSize
new3.32 KB

paraphrased comment

damien tournoud’s picture

Status: Needs review » Needs work

Hidden fields are not read only. Like, not read only at all.

webchick’s picture

Poor andypost.

Could someone who is more confident in their English skills (this isn't a slag on andypost at all; he told me he doesn't feel English is his strong suit even though it seems fine to me :)) please rephrase the comment?

andypost’s picture

@Damien Tournoud in this context hidden fields are read-only because you can't set them (within this function).

I leave this issue because this small and useful fix eats a lot of attention and all about comment...

A write a lot to explain what it all about :( sorry...

sun’s picture

Issue tags: -D7 API clean-up

This is not critical for API freeze.

Status: Needs work » Needs review

deekayen requested that failed test be re-tested.

sun.core’s picture

Priority: Critical » Normal

Not critical. Please read and understand Priority levels of Issues, thanks.

rfay’s picture

Status: Needs review » Needs work

IMO, we should address this in a more generic fashion. The problem with the triggers page is that each form has the same Submit and the same values in the select. The problem is that the only way we have to choose among them is the value of the button, which is pretty weak. If we could just select with an xpath expression, I think that would do it.

I opened #709852: Impossible to write a test where duplicate buttons/forms exist as a more generic statement of the same problem (encountered in the same place). I'm marking it as a dup of this one.

I don't know if this causes us pain in other areas, but the assignment of actions to triggers is basically not being tested because of this limitation. You can only assign the first item on the page.

andypost’s picture

@rfay The only trouble with fix described in #40 - I cant write a good comment :(

rfay’s picture

Status: Needs work » Needs review
StatusFileSize
new9.54 KB

I spent quite a lot of time with this tonight, and andypost's approach will work. There were a couple of problems due to the passage of time, but this patch works.

I took such delight in the fact that we can now test triggers and actions that this fleshes out Andypost's original test, adds another one that triggers and advanced (email) action - which we couldn't do before.

I also took the liberty of adding two tiny email helper functions to drupal_web_test_case(). One allows assertion on a *pattern* in an email message, and the other allows verbose output of a mail message. Mail hasn't been supported as well as page views, but when it's better supported, we'll have better tests.

Finally, the trigger_test mock module for trigger had not been properly updated to D7, so was creating warnings about a missing label field. I took the liberty of fixing that, since it's in the line of trigger test and all.

The bot will find 2 exceptions (hopefully only two): The new test uncovered #714190: system_send_email_action uses $account without initializing it , which had already been reported.

Status: Needs review » Needs work

The last submitted patch, drupal.simpletest_triggers_601398_47.patch, failed testing.

rfay’s picture

Well, unfortunately these test failures demonstrate that this approach does *not* work.

The idea was a workaround to try to get simpletest to find the correct form based on a passed-in hidden field. If the hidden field matches what's there, it helps select the correct form on the page.

The problem is that forms like imagefield's forms submit hidden fields, which are *different* from what's already in the form. So I don't think we're going to be successful piggy-backing on the hidden field idea. This was my original reservation in #45.

IMO we have to change the interface to drupalPost() somehow to give it the ID or name of the form we want to submit.

I will roll a proposed alternate. I hope an interface change will fly, because we really need this testing capability.

rfay’s picture

Status: Needs work » Needs review
StatusFileSize
new9.43 KB

This patch changes the signature of drupalPost to add a $form_css_id argument: the CSS ID of the form we want to submit. That completely resolves the ambiguity we've been dealing with, and does not break existing usage of hidden fields. And I think the code is far clearer. Less WTF!

The same set of peripheral issues are dealt with as in #48: There are a couple of assertions, the triggertest module was updated, the trigger tests filled out, and a new one added.

Status: Needs review » Needs work

The last submitted patch, drupal.simpletest_triggers_601398_50.patch, failed testing.

rfay’s picture

Status: Needs work » Needs review
StatusFileSize
new7.56 KB

This patch removes the test that exercises system_send_email_action, so we can decouple this issue from #714190: system_send_email_action uses $account without initializing it. I will move the test over to the patch on that issue.

rfay’s picture

andypost’s picture

@rfay thanx to take it on, now I see that searching for form in page-html is not possible without $form_id so this change in API is requred.

Possible issue may rise when page hold more then one same form on page - do they get same ID? Walking through drupal_retrieve_form() I found nothing that could change final $form_css_id except theme layer.

So my +1 to RTBC this

dave reid’s picture

Status: Needs review » Needs work
+++ modules/simpletest/drupal_web_test_case.php
@@ -1533,8 +1533,12 @@ class DrupalWebTestCase extends DrupalTestCase {
+   * @param $form_css_id
+   *   The optional CSS id of the form to be submitted. On some pages there
+   *   are many identical forms, so just using the value of the submit button
+   *   is not enough.
    */
-  protected function drupalPost($path, $edit, $submit, array $options = array(), array $headers = array()) {
+  protected function drupalPost($path, $edit, $submit, array $options = array(), array $headers = array(), $form_css_id = NULL) {

If anything this should be just $form_id. It doesn't have anything to do with CSS.

+++ modules/simpletest/drupal_web_test_case.php
@@ -2711,6 +2719,31 @@ class DrupalWebTestCase extends DrupalTestCase {
   /**
+   * Look for a regex in the body of the email.
+   * @param string $name
+   *   Name of the portion of the body to search. Most common: 'body'
+   * @param string $regex
+   *   Text to search for.
+   * @param string $message
+   *   Message for simpletest.
+   */

Fails coding standards.
- Needs newline between function summary and @params
- We aren't documenting types in @param or @returns yet.

+++ modules/trigger/trigger.test
@@ -298,4 +322,36 @@ class TriggerOtherTestCase extends DrupalWebTestCase {
+  /**
+   * Configure an advanced action.
+   * @param string $hook
+   *   The name of the hook. For example: 'user_presave', 'user_login'
+   * @param array $action_configure_edit
+   *   The $edit array for the form to be used to configure.
+   *   Example members would be 'actions_label' (always), 'message', etc.
+   * @return integer
+   *   the aid (action id) of the configured action, or -1 if none.
+   */

Fails multiple coding standards.
- See above points, same apply here.
- Why not just use $edit instead of $action_configure_edit?

+++ modules/trigger/trigger.test
@@ -298,4 +322,36 @@ class TriggerOtherTestCase extends DrupalWebTestCase {
+    // Now we have to find out the action ID of what we created.
+    $cell_to_find = "//div/table/tbody/tr/td[2][. = '{$action_configure_edit['actions_label']}']/../td[3]/a[@href]";
+    $this->assertFieldByXPath($cell_to_find, t('configure'), t('Found the configure link'));
+    $atag = $this->xpath($cell_to_find);
+    $this->assertTrue(is_object($atag[0]), t("Found the cell with 'configure' in it"));
+    if (is_object($atag[0])) {
+      $href = (string)$atag[0]->attributes()->href;
+      $aid = preg_replace('/^.*\//', '', (string)$href);
+      $this->verbose(t('The action ID for configured action hook=@hook is aid=@aid.', array('@hook' => $hook, '@aid' => $aid)));
+      return $aid;
+    }

Wow. Just wow. This is going to be a fun chunk to maintain. Is there any better way to accomplish this? Can we just load the action from the database and use that data to find the specific link instead of this voodoo? :)

Powered by Dreditor.

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new9.85 KB

@Dave thanx for review

New patch:
- fixed all phpdocs,
- $form_id uses drupal_html_id() for xpath
- made common function to assign configurable actions (moved to TriggerWebTestCase baseclass)

rfay’s picture

Status: Needs review » Reviewed & tested by the community

I think it's fantastic. Much improved. I really like what you did with the form id. That really helps bridge the gap between the Drupal and the HTML world.

webchick’s picture

Status: Reviewed & tested by the community » Needs work

This no longer applies after today's spring cleaning.

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new9 KB

Quick re-roll: there was a hunk from modules/trigger/tests/trigger_test.module which already fixed

Also about code-style - docs said that @param could have type and it is recommended for complex types of parameters

andypost’s picture

StatusFileSize
new8.05 KB

Seems like assertMailPattern() verboseEmail() are from different issue so skipped

rfay’s picture

Status: Needs review » Reviewed & tested by the community

Edit: #60 is the same patch as #56, rerolled. The two pieces removed belonged with #721086: Create tests for system actions, clean up token replacement, clean up triggers so I moved them over there.

This should go in.

webchick’s picture

Status: Reviewed & tested by the community » Fixed

Ok, great! Took a look through here and all looks good. I imagine that extra $form_id parameter would also come in handy for testing something like the Fivestar module. Nice to have expanded test coverage for this stuff, too.

Committed to HEAD!

Also, wow, Trigger module is weird, with that md5() stuff everywhere. I questioned rfay about this and he said this was probably to disambiguate the forms from one another, which makes sense, although also seems totally unnecessarily fancy. Maybe we can add a general sanity clean-up to trigger module to the todo list for D8. ;)

andypost’s picture

md5() staff used to separate actionIDs that are code-defined and user-defined.
Suppose rules would grow older for D8 and will replace triggers

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

andypost’s picture

Status: Closed (fixed) » Needs review
StatusFileSize
new7.01 KB

Working on #403446: Increase default weight of trigger module
I found that drupal_html_id() uses drupal_static() and there's no ability to post the same form.

Here's a patch to fix this:

1) Logic to clean $form_id copied from drupal_html_id() with comment (please check my grammar)
2) Tests for triggers extended with real form names (pointing actual trigger to assign action to)
3) TriggerContentTestCase a bit optimized - there's no need to create new users in loop

sun’s picture

Status: Needs review » Needs work

We rather want to remove that call to drupal_html_id() entirely here.

andypost’s picture

Status: Needs work » Needs review

@sun do you propose to change tests to pass a clean $form_id?

sun’s picture

Status: Needs review » Needs work

yes, tests should pass a valid form_id already. After all, test authors will look up the form_id on the actual page and copy+paste that into their test. drupal_html_id() is totally wrong here.

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new7.19 KB

Added comment and tests are changed to actial form IDs

sun’s picture

Status: Needs review » Reviewed & tested by the community

Please wait for the bot to come back green.

andypost’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new7.8 KB

user-login formID missed

andypost’s picture

Status: Needs review » Reviewed & tested by the community

changing status back

rfay’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new8.25 KB

Since we're going back to the HTML ID, I'd like to make the signature really clear about that. This reroll addresses that.

andypost’s picture

Status: Needs review » Reviewed & tested by the community

@rfay thanx for extended comment

webchick’s picture

Status: Reviewed & tested by the community » Needs review

Dang. I loved $form_id in that function. :(

Also this?

-      $this->drupalPost('admin/structure/trigger/node', $edit, t('Assign'));
+      $this->drupalPost('admin/structure/trigger/node', $edit, t('Assign'), array(), array(), 'trigger-node-presave-assign-form');

Ugh. So very, very ugly. And an API change to boot.

Since the reason for changing this according to #65 is "I found that drupal_html_id() uses drupal_static() and there's no ability to post the same form," can we not fix this with #684568: drupal_html_id() should use $drupal_static_fast pattern instead?

rfay’s picture

Status: Needs review » Needs work

@webchick, the API change, with its ugliness, was the only way we could figure out to solve this problem. It was thoroughly reviewed (and accepted and committed already, by you, in #62). The ugliness was introduced there, but only for callers that need to use the HTML ID to find the proper form. So the many instances of that you see here are not required of all callers of drupalPost(), just the callers that need to use the ID to find their way in the test.

@sun: I liked using $form_id as a parameter (instead of the HTML ID of the form) as well. It looks like this was done at your request?

webchick’s picture

Sorry. I meant the fact that test writers who used to be able to do:

      $this->drupalPost('admin/structure/trigger/node', $edit, t('Assign'));

now have to do:

      $this->drupalPost('admin/structure/trigger/node', $edit, t('Assign'), array(), array(), 'trigger-node-presave-assign-form');

This was not the case in the original patch that was committed.

andypost’s picture

Status: Needs work » Needs review

@webchick Test writers should point actual form (trigger) in their tests! This all it's issue about!

As I pointed in #65 to make crystal clear: Tests are always broken when

1) If any module changes an order of forms on trigger-assign page
2) weight of trigger module changed #403446: Increase default weight of trigger module original source of this bug
3) Test writer should point exactly a trigger-name which he wants to test - current approach is mistakenly supposes then 'trigger-node-presave-assign-form' is always a first hook on page!

Also it's much clear to code reviewers to see actual hook that tested.

About HTML ID - the main proposal to help test writers because construction of trigger forms are wtf http://api.drupal.org/api/function/trigger_assign/7

sun’s picture

Status: Needs review » Reviewed & tested by the community

Sorry, quite some confusion here.

  1. The optional form id was already introduced in a (committed) patch earlier in this issue. It is entirely optional, and only required in cases you have the same form more than once on the page.
  2. The earlier patch introduced $form_id as parameter, specifying the internal form_id. This is wrong for two reasons:
    1. When using the internal $form_id, we need to invoke drupal_html_id() to translate the $form_id into a HTML id, and, assume that we get the translated form_id we want. Since the sole purpose of drupal_html_id() is to ensure that ids in Drupal's HTML output are unique, it's easily possible that drupal_html_id() will not return what you expected, due to other tests/assertions running before yours.
    2. The entire SimpleTest functionality and helper functions work with values from the HTML output. We do not specify an multi-dimensional array of form values to post, but instead input names like foo[bar], as visible in the output. We also specify form button names using t('Save'), as visible in the output. Therefore, it is wrong to specify an internal $form_id, because this is not what we see in the output.
sun’s picture

+++ modules/simpletest/drupal_web_test_case.php
@@ -1608,8 +1611,8 @@ class DrupalWebTestCase extends DrupalTestCase {
       // Let's iterate over all the forms.
       $xpath = "//form";
...
+      if (!empty($form_html_id)) {
+        $xpath .= "[@id='" . $form_html_id . "']";
       }
       $forms = $this->xpath($xpath);

Note, however, that we could use the internal form id, if someone comes up with a xpath expression that filters //form via //form/input[@name='form_id',@value='$form_id'], but still makes it return the matched forms, and not that input element. (i.e. like $('form:has(input[name=form_id][value=$form_id])))

138 critical left. Go review some!

rfay’s picture

Actually, I just got bit by the fact that drupal_html_id() is clearly the wrong tool for this job, as it generated an incorrect HTML ID for me (with a -2 on it). I think we probably have to use the HTML ID to make this work right.

Another +1 from me for this as is.

webchick’s picture

Status: Reviewed & tested by the community » Fixed

Ah, got it. Thanks, folks.

Committed to HEAD.

Status: Fixed » Closed (fixed)
Issue tags: -actions, -triggers, -Simpletest, -API clean-up

Automatically closed -- issue fixed for 2 weeks with no activity.