If you call $this->clickLink() and the link is not on the page, you'll get a PHP notice:

ERROR: Undefined variable: url_target on line 1857 in /opt/www/apisite/sites/all/modules/simpletest/drupal_web_test_case.php (Notice)

This is because $url_target is only defined here:

    if (isset($urls[$index])) {
      $url_target = $this->getAbsoluteUrl($urls[$index]['href']);
    }

Simple fix is to say else { $url_target = '' } or something to that effect.

This is actually a pretty annoying bug because I have PHP notices printing and so if a clickLink fails, instead of the test finishing I get something like the attached screen shot.

I haven't checked to see if this is present in Drupal 7/8 core simpletest yet...

CommentFileSizeAuthor
#97 interdiff-d7-1452896_96.txt536 bytesjoshi.rohit100
#97 d7-1452896_96.patch1.79 KBjoshi.rohit100
#95 d7-1452896_95.patch1.79 KBjoshi.rohit100
#90 interdiff.txt2.15 KBMile23
#90 1452896_90.patch6.53 KBMile23
#88 interdiff.txt4.01 KBMile23
#88 1452896_88.patch6.63 KBMile23
#81 1452896.80.patch5.33 KBalexpott
#80 79-80-interdiff.txt2.94 KBalexpott
#79 interdiff.txt1.23 KBMile23
#79 1452896_79.patch4.95 KBMile23
#76 interdiff.txt1.22 KBMile23
#76 1452896_76.patch4.45 KBMile23
#72 interdiff.txt1.23 KBMile23
#72 1452896_72.patch4.47 KBMile23
#69 interdiff.txt2 KBMile23
#69 1452896_69.patch4.41 KBMile23
#69 clickLink100percentcoverage.jpg242.88 KBMile23
#66 fail_not_phail.jpg405.38 KBMile23
#65 1452896_60.patch4.53 KBMile23
#60 1452896_60_test_only.patch3.63 KBMile23
#60 1452896_60.patch4.53 KBMile23
#60 interdiff.txt2.35 KBMile23
#58 1452896_58.patch4.52 KBMile23
#51 fail_phail.jpg238.4 KBMile23
#45 1452896_45.patch4.02 KBMile23
#33 d8-clickLink_test-1452896-33.patch3.96 KBmarthinal
#25 d8-clickLink_test-1452896-25.patch4.2 KBmarthinal
#22 d8-clickLink-notice-1452896-22.patch2.07 KBmarthinal
#20 d8-clickLink-notice-1452896-20.patch2.19 KBmarthinal
#19 1452896-clickLink-notice-fix-d8.patch1.03 KBFreso
#19 1452896-clickLink-notice-test-d8.patch826 bytesFreso
#18 drupal-1452896-13-reroll.patch1.84 KBFreso
#17 445482-PDOException_reroll-reroll.patch4.3 KBFreso
#13 drupal-1452896-13.patch1.7 KBkid_icarus
#13 interdiff.txt1.23 KBkid_icarus
#9 drupal-1452896-9.patch1.49 KBkid_icarus
#9 interdiff.txt559 byteskid_icarus
#3 drupal-1452896-3.patch871 bytestim.plunkett
#1 simpletest-1452896-php-notice-d8.patch683 bytesjhodgdon
annoyingmessage.png48.78 KBjhodgdon
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

jhodgdon’s picture

Project: SimpleTest » Drupal core
Version: 6.x-2.x-dev » 8.x-dev
Component: Code » simpletest.module
Status: Active » Needs review
Issue tags: +Needs backport to D6, +Quick fix, +Needs backport to D7
FileSize
683 bytes

I have just verified that this is still present in the Drupal 7 core version of Simpletest, and it's still just as annoying... so I'm moving this issue to core.

The code is the exactly the same in Drupal 8/7 and the contrib Simpletest module for D6. Here's a patch for D8 to start with.

jhodgdon’s picture

Just as a note, this is primarily of interest to get fixed for contrib/core module developers who are writing and debugging tests, who have PHP notices turned on so they can make sure their code is clean. Or to people trying to port a well-tested contrib module from D6 to D7. :)

Instead of just having a one-line red test failure on the test results page, due to this link not being on the page where it's supposed to be (or you had a typo in your test and the link doesn't exist), you get a "TEST FAILED TO COMPLETE" failure.

tim.plunkett’s picture

FileSize
871 bytes

In a case like this, I think a ternary is actually MORE readable.

mikran’s picture

Wouldn't it be better to have something like 'not found' as url_target so the message doesn't look like "Clicked link %label () ..."?

jhodgdon’s picture

It will already show up as a failed test. At this point I don't care a whole lot about the message, but perhaps 'not found' would be more sensible. I'm fine with the patch in #3...

mikran’s picture

Status: Needs review » Reviewed & tested by the community

patch #3 it is then

catch’s picture

Status: Reviewed & tested by the community » Needs review
Issue tags: +Needs tests

Can we add a test for this to simpletest.test?

jhodgdon’s picture

Status: Needs review » Needs work
Issue tags: +Novice

Good idea to make a test for it. Seems like making the test might be a good Novice project? I might get to it if no one else takes it on, but not for a few days probably.

kid_icarus’s picture

FileSize
559 bytes
1.49 KB

So this is my first attempt at writing a test!

After writing the test though, I was curious:

@@ -362,6 +362,16 @@ class SimpleTestBrowserTestCase extends DrupalWebTestCase {
+    $this->assertEqual($this->url, $base_url . '/', 'Clicked a non-existant link');

It felt strange writing this assertion. The behavior implemented in patch #3 is such that if clickLink() is passed a label that doesn't exist, it winds up returning a drupalGet() on an empty string, which is essentially $base_url. I'm not sure if this is the desired behavior, but my concern lies in tests that might assume clickLink() either returns drupalGet() on a link if it exists, or false if it doesn't.

I ran the test before and after applying patch #3 by using git checkout on drupal_web_test_case.php. The test (by itself) fails before patch #3, and passes afterwards.

Review is greatly appreciated :)

kid_icarus’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, drupal-1452896-9.patch, failed testing.

jhodgdon’s picture

I don't think this test is quite right (and of course it is also failing).

In the current (and patched) clickLink function, the code does this:

    $this->assertTrue(isset($urls[$index]), t('Clicked link %label (@url_target) from @url_before', array('%label' => $label, '@url_target' => $url_target, '@url_before' => $url_before)), t('Browser'));

    if (isset($url_target)) {
      return $this->drupalGet($url_target);
    }
    return FALSE;

So if the link doesn't exist, it's not doing the drupalGet() at all. What I think you want to do is verify that the return value to clickLink is FALSE in the case of a nonexistent link, and perhaps also to verify that the URL of the page hasn't changed (i.e., use drupalGet to go to some page on the site, and then after clickLink verify the URL has not changed).

kid_icarus’s picture

FileSize
1.23 KB
1.7 KB

@jhodgdon, Thanks for the review.
Your assumption of how DrupalWebTestCase::clickLink works appears to me to be incorrect. I've used debug() to verify all values within the function when it is called with a bad link.

If DrupalWebTestCase::clickLink is passed a bad link, I've found the following sequence occurs:

  1.     $urls = $this->xpath('//a[normalize-space(text())=:label]', array(':label' => $label));
    

    DrupalWebTestCase::xpath() returns an empty array if the xpath query comes back with no results. Therefore $urls is assigned an empty array.

  2.     $url_target = isset($urls[$index]['href']) ? $this->getAbsoluteUrl($urls[$index]['href']) : '';
    

    The ternary operation assigns an empty string, '', to $url_target

  3.     $this->assertTrue(isset($urls[$index]), t('Clicked link %label (@url_target) from @url_before', array('%label' => $label, '@url_target' => $url_target, '@url_before' => $url_before)), t('Browser'));
    

    This assertion will always fail due to the fact that isset($urls[$index]) evaluates to FALSE because $urls is an empty array.

  4.     if (isset($url_target)) {
          return $this->drupalGet($url_target);
        }
    

    This condition will always evalutate to TRUE because according to php.net, isset($var):
    Returns TRUE if var exists and has value other than NULL, FALSE otherwise.

    An empty string is not NULL. Therefore DrupalWebTestCase::clickLink returns $this->drupalGet(''), which indeed is the HTML of the base URL. Using if (!empty($url_target)) solves this last problem.

There is a larger logic error which lies in the fact that DrupalWebTestCase::clickLink asserts that the link passed to it exists. One can test that DrupalWebTestCase::clickLink returns FALSE when given a bad link, however, in doing so the assetion within DrupalWebTestCase::clickLink itself will fail.

I'm assuming that one of the assertions must be removed. Attached is a new patch which addresses the issue of DrupalWebTestCase::clickLink not returning FALSE when passed a bad link. However, the aforementioned logic error still exists, and I'm not sure how to best handle it.

kid_icarus’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, drupal-1452896-13.patch, failed testing.

jhodgdon’s picture

Yeah, I guess due to (3) that probably a test to verify this will not ever pass, because if you pass a bad link in, the assertion will fail, thereby causing a failing test... But aren't there ways to test this? I mean, aren't there some tests for the simpletest module that test that assertions correctly fail?

One other note in your proposed patch: "existent" is misspelled. :)

Freso’s picture

This is a straight reroll (of #13) for the new directory/file structure - it doesn't work.

Freso’s picture

And the actual reroll of the patch in #13... >_>

Freso’s picture

Alright, so Cottser said this is likely no longer a "Novice" issue (I also removed "Quick fix" as it's turning out to be not so quick a fix anyway...). I'm not confident at all with the SimpleTest system to make any calls on this, so I'll just leave it here.

However, kid_icarus is right with regards to his point about the logic. If you run a test on clickLink'ing a bad link, you will get an error from clickLink(). However, removing that assertion in clickLink will also not reveal bad links in places where a bad link is not supposed to be.

Currently, I'm thinking to either have clickLink tage a paramenter, e.g., $badlink, which could swap assertTrue with assertFalse if = TRUE (defaulting to = FALSE, to not break current tests (and also because that's the most likely scenario...)), or have the assertTrue check on something else; like $url_target or the $urls array - or perhaps just populate $urls with $index if it's empty? But then again, we do not want to open up for actually broken links... This is making my head hurt. :p

The two attached files are the same as the reroll from just before, only split up in the "fix" and its test. (No, they still don't work. :))

marthinal’s picture

Status: Needs work » Needs review
FileSize
2.19 KB

With this patch we could know if the link was correctly clicked.

jhodgdon’s picture

Status: Needs review » Needs work

I'm assuming that the test in this patch is going to fail, because it's explicitly trying to click a link that doesn't exist, and clickLink() is now testing for that.

Also, there's a coding standard problem in this patch: test assertion messages should not be wrapped in t() (they shouldn't be translated). Use format_string() instead.

I also don't think this is very good code:

+    // We use assertTrue to verify if the link exists.
     if (isset($urls[$index])) {
       $url_target = $this->getAbsoluteUrl($urls[$index]['href']);
+      $this->assertTrue(isset($urls[$index]), t('Clicked link %label (@url_target) from @url_before', array('%label' => $label, '@url_target' => $url_target, '@url_before' => $url_before)), t('Browser'));
+    }
+    else {
+      $url_target = '';
+      $this->assertTrue(isset($urls[$index]), t('Clicked link %label (@url_target) from @url_before found', array('%label' => $label, '@url_target' => $url_target, '@url_before' => $url_before)), t('Browser'));
     }

The same assert is in both sides of this if() statement -- there's no reason for it to be within the if() at all, and it should be moved out.

marthinal’s picture

Status: Needs work » Needs review
FileSize
2.07 KB

@jhodgdon excuse about the if, I was trying different assertions and at the end I didn't verify very fine what I did. This is the same code but better.

I don't know if this test is the better option.Please let me know the best way to do this under your point of view.

upsss also this text is not correct in the patch 'Active URL persists after clicking non-existant link'

marthinal’s picture

Status: Needs review » Needs work

Like Freso says in #19 'This is making my head hurt. :p' trying to understand the best way to test when clickLink fail correctly... :))

jhodgdon’s picture

OK, I took a look at the tests that currently exist in the Simpletest module. In file core/modules/simpletest/lib/Drupal/simpletest/tests/SimpleTestTest.php, there *is* actually a way to test for a failing test. What it basically is doing in that test is that it runs a test called "Stub Test" in the testing UI, and then it verifies that the output is what it expects to see.

So I think we could:
- Add a line that would try a clickLink() on a non-existing link to the stubTest() method in that file.
- Add a line that verifies the correct assertion message in the confirmStubTestResults() method in that file.

Anyway... The patch in #22 looks like the right code fix to me. What I don't understand is how the added test passes, because it sure looks to me as though it's trying to click a non-existing link, and why is it passing? Maybe the added test isn't being run?

marthinal’s picture

Status: Needs work » Needs review
FileSize
4.2 KB

Here we test if the link is correctly clicked (in this case we want that) and verify that the user login form isn't correctly validated so we are in the same url.

Also added the patch created in the previous comments.

Added a test to verify that a link that doesn't exist, is correctly no clicked.

Changed at assertTrue the t() with format_string.

Status: Needs review » Needs work

The last submitted patch, d8-clickLink_test-1452896-25.patch, failed testing.

jhodgdon’s picture

Status: Needs work » Needs review

Most of this patch looks great!

One thing I don't understand though. Can you explain this added test? It looks like the comments in the test are saying it's not a valid link, but you're expecting the test to pass... I just don't understand it. I think if you want to verify that clickLink works, you should test on some URL that would actually work?

/**
+   * Tests DrupalWebTestCase::clickLink().
+   */
+  function testClickLink() {
+    global $base_url;
+
+    $this->drupalGet('user');
+    $this->clickLink(t('Log in'));
+    // Verify we are in same url because the login form validation fail in this case.
+    $this->assertEqual($this->url, $base_url . '/user', 'Active URL persists.');
+  }
+
+  /**
marthinal’s picture

At localhost the test pass correctly....

@jhodgdon about the test snippet ... What I want to do is to click correctly a link and check if the actual url is correct.

I really don't know the best possibility and also if we need it.

What do you think about it?

jhodgdon’s picture

I'm inclined to say that we don't need a test to verify that clickLink() works correctly on an existing link, since there are thousands of correct uses of clickLink() in the body of tests. But testing that it fails correctly (without an exception), which is the subject of this issue, does seem like a good thing to test. :)

Speaking of which... The addition that you made should *not* add exceptions or debug output to the test output, should it? It seems like it ought to add exactly 1 test failure, because there is 1 bad clickLink() added to the tests... right?

-    $this->assertEqual('6 passes, 5 fails, 2 exceptions, and 1 debug message', $this->childTestResults['summary'], 'Stub test summary is correct');
+    $this->assertEqual('9 passes, 7 fails, 7 exceptions, and 3 debug messages', $this->childTestResults['summary'], 'Stub test summary is correct');
marthinal’s picture

Ok so i'll create another patch without clickLink() test ... let me time to check the fails and exceptions correctly I need to debug what's going on here :) It seems that clickLink is adding another fail more ...

jhodgdon’s picture

Status: Needs review » Needs work

I apparently changed the status incorrectly above... marthinal: thanks for working on this!

marthinal’s picture

Assigned: Unassigned » marthinal
marthinal’s picture

@jhodgdon:

We have more fails actually because when we try for example a drupalGet() from stubTest appear these fails:

Undefined index: backtrace
Notice errors.inc 188 _drupal_log_error() Exception
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'd8.simpletest211209semaphore' doesn't exist: SELECT expire, value FROM {semaphore} WHERE name = :name; Array ( [:name] => variable_init )

Debugging with debug() I can see why it appears and this is why:

'Tables_in_d8' => 'simpletest907255simpletest211209semaphore',

In the setup we add the first prefix and then another new (second prefix) + table name.

So the tables are created but when trying to use them it's not possible.

I fixed the problem in the this patch.The problem is .... I really don't know when exactly we could need to use the first prefix and then the second... like actually is in the code.

Actually seems with no side effects with this patch.

Also we have two debug messages more added when we go to 'node' and another when clicking a link.

marthinal’s picture

Status: Needs work » Needs review
jhodgdon’s picture

Status: Needs review » Needs work

Hm. I don't think it's OK to change TestBase like this:

-        'default' => $value['prefix']['default'] . $this->databasePrefix,
+        'default' => $this->databasePrefix,

Maybe you were debugging and forgot to put this line back to its original? Hopefully...

Then in the added test code, this comment needs to be slightly reformatted:

+    //Check that we make click in a link that doesn't exist.

Needs a space after // and I think I would say "Check that the clickLink failure was recorded" as the comment.

Other than that, looks great!

marthinal’s picture

Perfect. I will add the space in the comment.

About the first point :

-        'default' => $value['prefix']['default'] . $this->databasePrefix,
+        'default' => $this->databasePrefix,

Actually with $value['prefix']['default'] . $this->databasePrefix we have 2 fails at stubTest when trying to click a link or ... log a user or something. Exactly this error:

Undefined index: backtrace
Notice errors.inc 188 _drupal_log_error() Exception
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'd8.simpletest211209semaphore' doesn't exist: SELECT expire, value FROM {semaphore} WHERE name = :name; Array ( [:name] => variable_init )

Ok, so I can verify debugging that the semaphore table name is 'simpletest907255simpletest211209semaphore', while testing we ask for 'simpletest211209semaphore'. The method name is changeDatabasePrefix(). I see that it ' Changes the database connection to the prefixed one. '.

What I don't understand is why we need to have a table with this name 'simpletest907255simpletest211209semaphore' and when exactly we need to have it.

If I don't remove the first prefix '$value['prefix']['default'] . $this->databasePrefix' then I will always have the 2 unexpected fails. Also I am trying to do the same but without modifying TestBase ...

1) So I would like understand why and when we need two prefixes because at the moment I don't understand why...
2) Do you think that there's another way to do this ???
3) Maybe this is a bug because we are asking for a table that doesn't exist.
4) Modifying TestBase the test passes correctly.

Thanks for your help.

jhodgdon’s picture

I don't know what's going on -- maybe one of the simpletest module maintainers can help us out?

marthinal’s picture

Yes , I'll try in #drupal-contribute .

boombatower’s picture

1) So I would like understand why and when we need two prefixes because at the moment I don't understand why...

SimpleTest tests itself using a browser test which means that it runs a test using the web runner and does so from a test. We must go deeper...etc etc, but yes it does.

2) Do you think that there's another way to do this ???

The assertions for the inner test require a database even if the test itself does not, something clever perhaps, but I doubt that will be any cleaner then the way it works now. Although I do not see why we need to explicitly prepend both prefixes as it should just be recursive.

I have not read the issue in length or looked at patches, just responded to #36 as linked to from IRC. Let me know if this is helpful or need more details.

jhodgdon’s picture

The objective we really need help with here is how to add a test that verifies that clickLink() will fail (but without an exception as it is doing now) if a nonexistent link is clicked. The patch in #33 attempts to do this, but it made a change that I don't understand to how that test was running, and I'm not sure it's OK to change the test in that way (see #35). Apparently (see #36) the test doesn't pass without that change... so I'm still confused about why the test won't pass without that change, what the change really does, and whether it's OK to make that change.

webchick’s picture

Just hit this myself while porting Pants module from D7 to D8. Marked #1089792: Undefined variable: url_target in clickLink as a duplicate of this bug.

star-szr’s picture

Assigned: marthinal » Unassigned
Issue summary: View changes

Just unassigning to free up (and bump) this issue. @marthinal, if you still want to work on this feel free to reassign. Thanks!

martin107’s picture

I am amazed by this discussion.

Can I convince people here that they have gone off track into a cul-de-sac?

I take a much simpler approach... if WebTestBase.php clickLink() is fed an invalid label it should abort with an exception to tell the test developer he/she is doing something wrong. Exceptions should be limited to when the routine cannot sensibly continue this is such a case.

That is what burn myself today and webchick a month ago and i guess jhodgdon ( OVER TWO YEARS AGO ) and nothing has been done!!!!!

Fundamentally this should be a ONE line fix...

I say again If clickLink() is given invalid input it should bark at the webtest creator appropriately.

  protected function clickLink($label, $index = 0) {
    $url_before = $this->getUrl();
    $urls = $this->xpath('//a[normalize-space()=:label]', array(':label' => $label));

    if (isset($urls[$index])) {
      $url_target = $this->getAbsoluteUrl($urls[$index]['href']);
+    } else {
+      throw new \UnexpectedValueException('Clicked link is invalid.');
+   }

    $this->assertTrue(isset($urls[$index]), String::format('Clicked link %label (@url_target) from @url_before', array('%label' => $label, '@url_target' => $url_target, '@url_before' => $url_before)), 'Browser');

    if (isset($url_target)) {
      return $this->drupalGet($url_target);
    }
    return FALSE;
  }

Behind the scenes it is more than an one line fix if you include the @throw comment and a web test that feeds invalid input into clickLink() and check for the exception.

I will work on this further if I can get consensus... but given the history this is unlikely

sorry for the rant.

https://drupal.org/comment/8538789#comment-8538789

Mile23’s picture

Assigned: Unassigned » Mile23

I say again If clickLink() is given invalid input it should bark at the webtest creator appropriately.

Well, no. clickLink() should report a failed test if the link label doesn't exist. It should also report a fail if the URL under that link is unreachable.

Patch this evening.

Mile23’s picture

FileSize
4.02 KB

Basically, this is the only change to clickLink():

    $this->assertTrue(isset($urls[$index]), String::format(
      'Clicked link %label (@url_target) from @url_before',
      array(
        '%label' => $label,
        '@url_target' => isset($url_target) ? $url_target : '<none>',
        '@url_before' => $url_before,
      )
    ), 'Browser');

This just says 'none' for the path if xpath can't find anything.

Also added a unit test so we can check the behavior when the link exists and when it doesn't.

We can't unit test (or simpletest) the output of the assertion, because assertions are not injectable, and you can't assert that a failing assertion is a pass. :-)

Mile23’s picture

Status: Needs work » Needs review
sun’s picture

I agree with @martin107 in #43:

Throwing an exception makes sense, because if a link cannot be clicked, then the entire rest of the test method will not succeed either way.

In almost all cases, failing to click a link is an unmet precondition, so proceeding with the test method only makes you wait unnecessarily long(er) for test results, whereas the results will only consist of failures after the failing clickLink().

I consider those needless wait times to be even more annoying than the faulty fail/error handling of clickLink() itself. — In 99% of all cases I experienced myself, clickLink() failures are "D'oh!" situations. Instead of waiting minutes for the test to complete with tons of failures, I would have highly appreciated an early exception that halts the test (method), so that the broken clickLink() can be fixed first (and fast).

Mile23’s picture

Throwing an exception makes sense, because if a link cannot be clicked, then the entire rest of the test method will not succeed either way.

Yes exactly. So FAIL and move on, but there is exactly zero need for an exception. Subsequent tests will fail also, but that's good, because this is, after all, a TEST. :-)

Here, let's get remedial:

Because clickLink() has an assertion in it, it is a test. It should really be called assertClickLink().

We're not trying to follow the link, we are trying to FIND OUT if we CAN follow that link, and then we do it if we can.

If the label doesn't exist, then clearly the test fails.

And in that circumstance, we're completely done. There is nothing else to say.

We are not in the midst of an error condition. We simply failed to find the link, click it, or follow it.

Again: Failing to find the label is not an error condition. Failing to follow the link is not an error condition. They are both FAIL conditions, which is different.

SimpleTest should hide errors related to discovering whether the test has passed or failed.

Because that's how testing works.

Mile23’s picture

Also: My interest in this issue comes about from writing tests which are supposed to fail at this point, because that's what programmers do these days. You write tests which fail, and then make them pass.

Here's the failing test for a skeleton module I wrote: https://qa.drupal.org/pifr/test/764843

Note that it throws a bunch of errors which deliver zero value to the test author (me), or anyone else. These errors are fixed by the patch in #45, but the test still fails, because that's how testing works. :-)

Mile23’s picture

Assigned: Mile23 » Unassigned
Mile23’s picture

FileSize
238.4 KB

Here's what you see if you get a failing test in Drupal due to clickLink().

It's completely unacceptable.

I want to suggest that there be a checkbox in the UI that says 'Report stack trace for failures,' which is turned off by default, but I doubt that if I do the work, anyone will want it.

If you want this, please ping on this issue.

jhodgdon’s picture

I'm with Mile23 as well. If a test fails, it should fail, not throw an exception. If it throws an exception, the rest of the test you are trying to develop doesn't finish, and the rest of the tests you were trying to run don't run, and you lose the list of what you were even trying to run. It is definitely not what I want to happen -- it's totally annoying, which is why I filed this issue in the first place.

Normally when you are developing a test, you get a bunch of failures, and iterate on the code and test until everything is green, but when you get an exception you are just hit in the face and it derails the whole process.

So... As several of us had said, clickLink should just fail if the link doesn't exist, not completely derail your development process.

Mile23’s picture

@jhodgdon: There's a patch in #45 that could use a review, which fixes this error. It unit-tests clickLink().

jhodgdon’s picture

I don't see an actual code change in the patch in #45 -- it just looks like the formatting of the code was changed there, and you added a test? If there is a code change, can you make a patch that just changes the code and leaves the formatting the same, so it is more obvious what you are changing? Code formatting seems to me to be out of scope here.

The early patches on this issue that I made and others modified actually did fix the problem...

Mile23’s picture

Formatting according to coding standards. :-)

Basically it checks for $url_target and if it's not set, then subtitutes 'none'. This way we get the message even if the target isn't found, and we also get no crash.

+++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
@@ -2391,7 +2391,14 @@ protected function clickLink($label, $index = 0) {
+        '@url_target' => isset($url_target) ? $url_target : '<none>',

We have a number of things going on in this issue.

We have a problem where SimpleTest has an actual bug. (It tries to use an uninitialized variable.)

We have a problem where people have confused this bug for useful debugging information. (Other fails present a stacktrace and error codes, so it seems like this one should, too.)

We have two solutions to the problem: 1) Martin107 wants to throw an exception so that we can get the debugging information, and 2) others and myself want to just see whether the link exists and then just report a fail.

My solution is very simple, fails on fail rather than throwing an exception, and has a unit test for clickLink().

If we can get an RTBC, then a maintainer can decide, and we can move forward with something other than that screenshot in #51.

This is an almost-blocker for #2277599: [meta] Port tests from D7 to D8 Examples, Add Skeleton Module Structure because of the extreme tedium it creates.

jhodgdon’s picture

I do not see a place in the coding standards that says function calls should ever be split up into multiple lines:
https://drupal.org/coding-standards#functcall
This was proposed several years ago, but people disagree so it was never adopted. You may like this format; I don't...

Anyway, that aside, as I said it makes it really hard to see what was changed in the patch when you mix unrelated changes like this with actual changes. Would you be willing to make a new patch that keeps the formatting as it was? It's not just me -- someone has to review this, then someone has to commit it, and if it's a pain to double-check that the changes are as intended, then it's a pain for several people.

But in any case, regarding reviewing... I took a look at the test code and it's about as clear as mud. :( providerTestClickLink makes a couple of cryptic arrays with no documentation on what is in them, and then ... well I don't know too much about unit testing, so ... it's not obvious to me what's going on or whether it's really testing that clickLink fails gracefully if it doesn't find the requested URL in the current page (which is the bug being reported here).

Maybe some code comments could be added to explain at least what the array values in providerTestClickLink are (it's not even an associative array where the array keys would provide a clue)? Or maybe you can get someone else to review it? Or maybe a WebTest that used an actual Drupal admin web page with a link that doesn't exist on the page would be more illuminating (since it would then be clear that it was testing the actual bug)?

Oh, and: 'an_url' ?!? What is this? I would personally always say "a URL", not "an URL'. :)

I am tempted to set this to Needs Work but maybe it is just my own deficiency of understanding that makes the code cryptic and hard to read?

Mile23’s picture

Your suggestions are good. :-) I'll re-do the formatting and pad out the test docs.

Mile23’s picture

FileSize
4.52 KB

Needed a re-roll anyway, so here it is.

Reverted the formatting, which is still just as unreadable in the patch. :-) Also added more docblock and inline commenting to the test, and added another piece of test data.

What this patch does: It introduces a check to make sure that $url_target exists, and if it does not, it substitutes '<none>' for the path in the report line. It also adds a heavily-mocked unit test with data provider, which verifies that if $url_target doesn't exist, clickLink() returns a fail. Were clickLink to throw the error for this issue, PHPUnit would fail this test.

Here's a reformatted version of the original function for readability's sake, and then the changed version.

Before:

protected function clickLink($label, $index = 0) {
    $url_before = $this->getUrl();
    $urls = $this->xpath('//a[normalize-space()=:label]', array(':label' => $label));

    if (isset($urls[$index])) {
      $url_target = $this->getAbsoluteUrl($urls[$index]['href']);
    }

    $this->assertTrue(isset($urls[$index]), String::format(
      'Clicked link %label (@url_target) from @url_before',
      array(
        '%label' => $label,
        '@url_target' => $url_target,
        '@url_before' => $url_before,
      )),
      'Browser'
    );

    if (isset($url_target)) {
      return $this->drupalGet($url_target);
    }
    return FALSE;
  }

After:

  protected function clickLink($label, $index = 0) {
    $url_before = $this->getUrl();
    $urls = $this->xpath('//a[normalize-space()=:label]', array(':label' => $label));

    if (isset($urls[$index])) {
      $url_target = $this->getAbsoluteUrl($urls[$index]['href']);
    }

    $this->assertTrue(isset($urls[$index]), String::format(
      'Clicked link %label (@url_target) from @url_before',
      array(
        '%label' => $label,
        // This is the changed line...
        '@url_target' => isset($url_target) ? $url_target : '<none>',
        '@url_before' => $url_before,
      )),
      'Browser'
    );

    if (isset($url_target)) {
      return $this->drupalGet($url_target);
    }
    return FALSE;
  }

And here we see the test failing against the current code:

$ ./vendor/bin/phpunit --group simpletest
[..]
There was 1 error:

1) Drupal\simpletest\Tests\WebTestBaseTest::testClickLink with data set #0 (false, 'does_not_exist', 0, array())
Undefined variable: url_target

/Users/paulmitchum/projects/drupal8/core/modules/simpletest/src/WebTestBase.php:2526
/Users/paulmitchum/projects/drupal8/core/modules/simpletest/tests/src/WebTestBaseTest.php:189

FAILURES!
Tests: 18, Assertions: 27, Errors: 1.
jhodgdon’s picture

Status: Needs review » Needs work

Much better, thanks!

We normally upload test-only patches to verify that the test fails as expected without the code patch. :)

A few minor details on the docs:

+   * @return array
+   *   Array of arrays of test data. Test data is structured as follows:
+   *   - Expected value, as per return value of clickLink().
+   *   - Label as per clickLink().
+   *   - Index as per clickLink().
+   *   - Test data which will be returned by mocked xpath(). Return an empty
+   *   array here to test the condition of no link found. 'href' key will be
+   *   inserted into this array.
+   */
+  public function providerTestClickLink() {

a) List formatting -- in the last bullet item, indent the additional lines of text 2 spaces.

b) What is all the "as per" here? Maybe should just be "Expected return value of clickLink", "Parameter $label to clickLink", etc.? Same comments apply to the @param docs for the test method.

c) in "Test data which will be returned" ... which -> that [also in test method param]

d)

+      // Test for an extant label.

What does this mean? I shouldn't have to get out a dictionary to figure out what a code comment means. :)

Mile23’s picture

Status: Needs work » Needs review
FileSize
2.35 KB
4.53 KB
3.63 KB

You have to know what 'extant' means. :-)

Nevertheless... This is #58 with all the changes above, separate test patch to illustrate fail.

Check comment #58 to see a readable version of the changes.

Status: Needs review » Needs work

The last submitted patch, 60: 1452896_60_test_only.patch, failed testing.

Mile23’s picture

I'd set this back to 'needs review' but then it would just test again and fail and be set at 'needs work.'

jhodgdon’s picture

Issue tags: +Needs manual testing

No, setting to "needs review" does not cause a retest. :) Setting it to RTBC would... I guess we should probably upload just the actual patch on its own comment and set that to RTBC so that the test bot will not keep testing the "test-only-fail" patch.

Anyway... This looks good to me! Someone should probably manually test this in the Simpletest UI with a test trying to click on a nonexistent link.

jhodgdon’s picture

Status: Needs work » Needs review

forgot status. And by the way I looked at the test result for the failing test and it is failing where the test was designed to fail to test this issue.

Mile23’s picture

FileSize
4.53 KB

Ok, here's a re-upload of the patch, without the test-only patch.

Note that the failing test-only patch appears in #60 and the run-down of what this patch does appears in #58.

Mile23’s picture

FileSize
405.38 KB

And here's what it looks like in the UI:

Compare with: https://drupal.org/comment/8843605

jhodgdon’s picture

Status: Needs review » Reviewed & tested by the community

Looks good, thanks!

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

I agree with @sun that a test method should be halted the moment you get an error - how every other test method in the same class should run - however that is not how simpletest currently works so the change here is in line. Changing this behaviour is a separate issue (and one that I would support).

The major issue I have with this patch is the complexity of understanding the test and the fact that the test is not really covering much of the clickLink functionality. Yes PHPUnit is great and fast and everything but when we're mocking 5 methods and using reflection to change whether or not something is protected alarm bells should be ringing. This test will be expensive to maintain because it is tightly coupled to the internals of the clickLink() method.

+++ b/core/modules/simpletest/tests/src/WebTestBaseTest.php
@@ -86,4 +86,108 @@ public function testAssertFieldByName($filename, $name, $value, $expected) {
+        array(),
...
+        array(0 => 'this_is_a_url'),
...
+        array(0 => 'this_is_a_url', 1 => 'this_is_another_url'),
...
+    $xpath_array = array();
+    foreach ($xpath_data as $key => $xpath) {
+      $xpath_array[$key]['href'] = $xpath;
+    }

That said if we are going to go down the PHPUnit route, why are we not just passing in a correctly structure return value for xpath? Or even better not actually mock xpath but mock drupalGetContent() since providing content would make the test much easier to understand.

To improve the coverage of what is being tested we should be asserting if drupalGet() is called and what with.

Mile23’s picture

@alexpott #68:

I agree with @sun that a test method should be halted the moment you get an error

There's no error. It's a test. It fails. Not an error. The desired behavior is to report a fail, not crash in your face. The current behavior is a bug.

The major issue I have with this patch is the complexity of understanding the test and the fact that the test is not really covering much of the clickLink functionality.

It exercises *every line* of clickLink() towards a number of desired results. Don't believe me? Here's a picture:

Note that a report like this is impossible using SimpleTest.

Yes PHPUnit is great and fast and everything but when we're mocking 5 methods and using reflection to change whether or not something is protected alarm bells should be ringing.

I'm using PHPunit because there is a veritable army of patches in this issue which failed to use SimpleTest to test this functionality. The unit test proves that clickLink() now does not do the thing it shouldn't do. Which is error out.

That said if we are going to go down the PHPUnit route, why are we not just passing in a correctly structure return value for xpath?

Either way works. Will change it.

Or even better not actually mock xpath but mock drupalGetContent() since providing content would make the test much easier to understand.

drupalGetContent() is not a dependency of clickLink(), so it doesn't need to be mocked.

To improve the coverage of what is being tested we should be asserting if drupalGet() is called and what with.

That's happening in the patch in #65 already.

Edit: Actually, yah, it's not, strictly speaking. :-) However, we are asserting that drupalGet() is called and returns a value. We don't care what it returns. We know what value is being sent to it, because we mocked getAbsoluteUrl().

Attached patch puts the 'href' in the xpath data, rather than adding it in the test.

Mile23’s picture

Status: Needs work » Needs review
alexpott’s picture

@mile23 phpunit stops running a test method the moment an assertion fails :) It does not run any more assertions in the same method - I think simpletest (or any testing framework) should work the same way since after one assertion fails (especially one in click link) all bets are off as to what will happen next.

Exercising lines does not mean that all the logic in the method is tested - for example:

+++ b/core/modules/simpletest/tests/src/WebTestBaseTest.php
@@ -86,4 +86,106 @@ public function testAssertFieldByName($filename, $name, $value, $expected) {
+    $web_test->expects($this->any())
+      ->method('drupalGet')
+      ->will($this->returnValue('A Web Page.'));

We should assert this is called once and with the correct url and if there is no target url we should assert that it is not called.

And people have got code coverage reports out of simpletest https://www.drupal.org/project/code_coverage

Mile23’s picture

FileSize
4.47 KB
1.23 KB

@alexpott #71

@mile23 phpunit stops running a test method the moment an assertion fails :) It does not run any more assertions in the same method - I think simpletest (or any testing framework) should work the same way since after one assertion fails (especially one in click link) all bets are off as to what will happen next.

In an ideal world, yes, we'd short-circuit the whole method as failed on the first assertion fail. That's outside the scope of this issue though. I can't find an issue for such a change, but fire it up and let's go.

In this issue, we're going from buggy crash to consistent output.

RE: drupalGet(): We should assert this is called once and with the correct url and if there is no target url we should assert that it is not called.

That's exactly what we're testing with the unit test. In fact, it's the *only* thing we're testing with the unit test, because it's the only thing we can test. :-)

Our mocked drupalGet() can never return FALSE. We mock it because we're not testing the behavior of drupalGet(), and if we return a known value we know that it was called.

With all the mock scaffolding in place, clickLink() can only ever return 'A Web Page.' or FALSE. If we get 'A Web Page.' then we know drupalGet() was called. Thus, mission accomplished.

But... Here's a patch to make it more clear, substituting 'This Text Returned By drupalGet()' for 'A Web Page.'

jhodgdon’s picture

Status: Needs review » Needs work

Really? You want to make it so that Simpletest stops at the first failed test, or not fix this issue?

This would totally break my ability to develop tests and code in a timely manner. When I've made significant changes to the code in the API module, for instance, I usually need to run the entire suite of tests, which takes about an hour on my machine (there are a LOT of tests). So, I generally start the tests running, and go do something else, like eat lunch or get some exercise. When I get back to my machine, if all goes as planned, all the tests have run and I have a list of all the things I need to fix. I would then change code/tests and rerun either the failed tests or all tests, depending on what I had to change.

If the testing stopped at the first problem each time, or if the bug that this issue is trying to fix came up so that one of the tests aborted due to a PHP error that was really just a simple test failure, I would instead need to fix one error at a time and start the tests up again. This really would not work.

So... PLEASE can we just get this fixed? Simpletest does not work the way you're describing, and I hope it never does. It would really make things difficult for people without a really fast machine running long suites of tests to get anything done.

Meanwhile... Reviewing the current patch:

+   *   Array of arrays of test data. Test data is structured as follows:
+   *   - Expected return value of clickLink().
+   *   - Parameter $label to clickLink().
+   *   - Parameter $index to clickLink().
+   *   - Test data which that be returned by mocked xpath(). Return an empty
+   *     array here to test the condition of no link found.
+   */
+  public function providerTestClickLink() {
+   *   - Test data which that be returned by mocked xpath(). Return an empty
+   *     array here to test the condition of no link found.
+   */
+  public function providerTestClickLink() {

Two problems here:
a) I don't think this description was updated when the patch was updated? I think the first item in the array is the return value from drupalGet() mock, for instance?
b) The last bullet point is garbled... not sure what it is supposed to say really?

Until these two problems are fixed in the documentation, I'm unable to review the test properly, since I'm not sure what it is meant to be doing.

Mile23’s picture

@jhodgson:

Agreed that halting on fail is out of scope for this issue. Everyone can argue about that in some other issue. :-)

The code snippet you quote above is kind of garbled... Here's what I see in the patch.

+++ b/core/modules/simpletest/tests/src/WebTestBaseTest.php
@@ -86,4 +86,106 @@ public function testAssertFieldByName($filename, $name, $value, $expected) {
+  /**
+   * Data provider for testClickLink().
+   *
+   * @return array
+   *   Array of arrays of test data. Test data is structured as follows:
+   *   - Expected return value of clickLink().
+   *   - Parameter $label to clickLink().
+   *   - Parameter $index to clickLink().
+   *   - Test data which that be returned by mocked xpath(). Return an empty
+   *     array here to test the condition of no link found.
+   */
+++ b/core/modules/simpletest/tests/src/WebTestBaseTest.php
@@ -86,4 +86,106 @@ public function testAssertFieldByName($filename, $name, $value, $expected) {
+  /**
+   * Test WebTestBase::clickLink().
+   *
+   * @dataProvider providerTestClickLink
+   *
+   * @param mixed $expected
+   *   Expected return value of clickLink().
+   * @param string $label
+   *   Parameter $label to clickLink().
+   * @param int $index
+   *   Parameter $index to clickLink().
+   * @param array $xpath_data
+   *   Test data that will be returned by mocked xpath().
+   */

We're mocking xpath() so it returns known results for trying to find $label on the page. If we tell xpath() to return an empty array, then we're testing for the situation where no link was found.

Doing this, we can force clickLink() down different code paths based on the result of xpath(). The one we care about most is if there was no link found, because we want to be sure that our code catches any errors related to it.

The modification to clickLink() only catches an error condition. The test only proves that the error condition doesn't happen any more.

If someone feels a need for more testing of clickLink() beyond the scope of this issue, then open another one please.

jhodgdon’s picture

Oh, sorry about the garbled comment. Here is what I see in the latest patch:

+   * @return array
+   *   Array of arrays of test data. Test data is structured as follows:
+   *   - Expected return value of clickLink().
+   *   - Parameter $label to clickLink().
+   *   - Parameter $index to clickLink().
+   *   - Test data which that be returned by mocked xpath(). Return an empty
+   *     array here to test the condition of no link found.
+   */
+  public function providerTestClickLink() {
...
+      array(
+        'This Text Returned By drupalGet()',
+        'exists',
+        0,
+        array(0 => array('href' => 'this_is_a_url')),
+      ),

So the first item in the array appears to be text returned by drupalGet(), but it is documented to be "Expected return value of clickLInk". That is not right?

And the part that I do not understand says;

+   *   - Test data which that be returned by mocked xpath(). Return an empty
+   *     array here to test the condition of no link found.

"Test data which that be returned" ?!?!?!? What does that mean?

Mile23’s picture

Status: Needs work » Needs review
FileSize
4.45 KB
1.22 KB

Ahh, structure error sentence in the latter. Will fix that. :-)

As for the former:

So the first item in the array appears to be text returned by drupalGet(), but it is documented to be "Expected return value of clickLInk". That is not right?

drupalGet() is mocked to return a known value. It's 'This text from drupalGet()' because alexpott seemed to be unclear on whether we were checking if drupalGet() was returning a value.

If you do a little analysis of clickLink(), you see that it returns either FALSE or the value of drupalGet().

Therefore, we know that if clickLink() returns 'This text returned from drupalGet()', from our mocked version of drupalGet(), then clickLink() found the link.

So it's both the return value of the mocked drupalGet() *and* the expected output of clickLink(). :-)

jhodgdon’s picture

OK, so you just spent several paragraphs explaining this to me. How about documenting that the first value is used for, as you said "... both the return value of the mocked drupalGet() *and* the expected output of clickLink()" so that the test will be clear when the next maintainer comes around? :)

Status: Needs review » Needs work

The last submitted patch, 76: 1452896_76.patch, failed testing.

Mile23’s picture

Status: Needs work » Needs review
FileSize
4.95 KB
1.23 KB

Added some more explanation.

I hope the seemingly unrelated test fail from the last patch goes away... I couldn't get Drupal to install to make a test work and see.

alexpott’s picture

FileSize
2.94 KB

@jhodgdon whilst not wanting to derail this issue any further - my point is that once there is a failure in one test method that method should no longer continue to run - and this is especially important for clickLink since if the assertion fails the simpletest browser is not even on the expected page anymore. The other methods contained in that class should still run. But if you've read my comments you'll see I'm not blocking this patch and agree that it should be fixed. All I'm trying to do is point out that the test we're adding is not actually covering all the logic in the clickLink method and the test is extremely expensive to maintain. Personally I would have preferred if this test had gone down the same path as the testAssertFieldByName() contained in the same test class - because understanding html is far far simpler than understanding xpath output and the actual input to the method is output from the simpletest browser - but y'all seem hellbent on this approach so whatever.

So here is what I'm on about - I've changed the test to now actually test all the logic contained within the clickLink() method. If we're testing that method it is important to assert that we don't ever try to use drupalGet() on a non existent link :) As we're adding a completely new test for clickLink() and using code coverage reports to say hey look we've covered everything it is important that we actually do cover everything.

alexpott’s picture

FileSize
5.33 KB

Now for the patch

Mile23’s picture

Status: Needs review » Reviewed & tested by the community

Personally I would have preferred if this test had gone down the same path as the testAssertFieldByName() contained in the same test class - because understanding html is far far simpler than understanding xpath output and the actual input to the method is output from the simpletest browser - but y'all seem hellbent on this approach so whatever.

If someone doesn't understand what xpath() is doing, why are they writing unit tests for this class? :-)

Your version is much better. I see what you were trying to goad me into doing.

In the past I've gotten into trouble for writing tests beyond the scope of the thing I changed. If the issue was 'fix the php error and expand test coverage,' then yah.

Anyway: I give it the Mile23 Seal Of Approval. Let's see if jhodgdon has further criticism.

jhodgdon’s picture

I like the new patch too. The docs are clear on what it's doing. Thanks!

jhodgdon’s picture

Should we open another issue to discuss the other "when to stop" questions that have come up here, or is there already one?

Dries’s picture

Status: Reviewed & tested by the community » Active

Committed this patch to 8.x. I think the message could actually be made more clear when $target_url is not set but this is a lot better than what we have.

jhodgdon’s picture

Status: Active » Reviewed & tested by the community

I do not think the patch above was actually committed.

jhodgdon’s picture

So I was going to make a new patch with a better message... but since the above patch wasn't committed, that's a bit of a problem.

Here's the suggested code though:

  protected function clickLink($label, $index = 0) {
    $url_before = $this->getUrl();
    $urls = $this->xpath('//a[normalize-space()=:label]', array(':label' => $label));

    if (isset($urls[$index])) {
      $url_target = $this->getAbsoluteUrl($urls[$index]['href']);
      $this->pass(String::format('Clicked link %label (@url_target) from @url_before', array('%label' => $label, '@url_target' => $url_target, '@url_before' => $url_before)), 'Browser');
      return $this->drupalGet($url_target);
    }

    $this->fail(String::format('Link $label does not exist on @url_before', array('%label' => $label, '@url_before' => $url_before)), 'Browser');
    return FALSE;
  }
Mile23’s picture

Status: Reviewed & tested by the community » Needs review
FileSize
6.63 KB
4.01 KB

Incorporated @jhodgdon's change, which is way better. :-)

Small tweak to method docblock.

Added pass()/fail() requirement to unit test, which is kind of the whole point, right?

If #81 was really added but not pushed or something, it might need reroll.

jhodgdon’s picture

Status: Needs review » Needs work

I'm not thrilled about this documentation line:

+   * We assert a pass for discovering and clicking the link, a fail otherwise.

We normally don't put "We" in function header docs. :) And to me "assert a pass" (or fail) doesn't make sense. You don't "assert" a pass, you assert values and conditions. Maybe something like "The test passes if the link is discovered, and fails if it doesn't exist."?

The rest of the patch, I am of course happy with. ... A bit confused in the test though as to why 3 of the places in the interdiff have this line added and one doesn't:

        ->will($this->returnValue(NULL));

I guess I don't understand what that does, but ... why add it mostly?

Mile23’s picture

Status: Needs work » Needs review
FileSize
6.53 KB
2.15 KB

Yah, I think an extra returnValue(NULL) crept its way in there in a copypasta frenzy.

As far as 'assert'... If you look at pass() and fail(), they just map to asssert()... Also, I think clickLink() should really be called assertClickLink(), but that's another issue for another day.

So: Removed extra returnValue(NULL), changed docblock wording for clickLink(), removed some docblock stuff from the test method that no longer applies.

jhodgdon’s picture

Status: Needs review » Reviewed & tested by the community

OK, assuming the test bot agrees, I think this is back to RTBC. Thanks!

catch’s picture

Version: 8.x-dev » 7.x-dev
Status: Reviewed & tested by the community » Patch (to be ported)

Committed/pushed to 8.x, thanks!

Moving to 7.x for backport.

  • catch committed 97ee3b9 on 8.x
    Issue #1452896 by Mile23, marthinal, Freso, kid_icarus, alexpott, tim....
jhodgdon’s picture

Since we do not have the capability for the same kind of tests in D7/D6 as we have in D8, I think that the ported patch only needs to port the part in the clickLink() method, not the test. Should be a simple backport... any takers?

joshi.rohit100’s picture

Status: Patch (to be ported) » Needs review
FileSize
1.79 KB

Patch for Drupal-7

jhodgdon’s picture

Status: Needs review » Needs work

There is an extra space at the end of the middle line in:

+   * The label is translated label.
+   * 
+   * If the link is discovered and clicked, the test passes. Fail otherwise.

You've been contributing a lot of patches (thanks!) -- please check your code editor settings. If you have a decent code editor, you should be able to set it to either remove or highlight end-of-line spaces, so that this doesn't happen.

Otherwise, the patch looks good.

joshi.rohit100’s picture

Status: Needs work » Needs review
FileSize
1.79 KB
536 bytes

Removed the extra space.

Status: Needs review » Needs work

The last submitted patch, 97: d7-1452896_96.patch, failed testing.

joshi.rohit100’s picture

Status: Needs work » Needs review

some testbot glitch

jhodgdon’s picture

Status: Needs review » Reviewed & tested by the community

That looks good, thanks!

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 97: d7-1452896_96.patch, failed testing.

joshi.rohit100’s picture

Status: Needs work » Needs review
jhodgdon’s picture

Status: Needs review » Reviewed & tested by the community

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 97: d7-1452896_96.patch, failed testing.

dcam queued 97: d7-1452896_96.patch for re-testing.

dcam’s picture

Status: Needs work » Reviewed & tested by the community

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 97: d7-1452896_96.patch, failed testing.

jhodgdon queued 97: d7-1452896_96.patch for re-testing.

jhodgdon’s picture

Status: Needs work » Reviewed & tested by the community

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 97: d7-1452896_96.patch, failed testing.

jhodgdon’s picture

Status: Needs work » Reviewed & tested by the community

Errors are unrelated to this patch...

David_Rothstein’s picture

Status: Reviewed & tested by the community » Fixed

Committed to 7.x - thanks!

Pretty sure this could be tested for Drupal 7 (the test would just look different than Drupal 8) but testing bugs in the test framework internals doesn't seem like it's super high-priority, so someone can do that as a followup if they want to.

  • David_Rothstein committed 49a51c7 on 7.x
    Issue #1452896 by Mile23, marthinal, Freso, kid_icarus, joshi.rohit100,...

Status: Fixed » Closed (fixed)

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