Needs work
Project:
Drupal core
Version:
main
Component:
phpunit
Priority:
Normal
Category:
Feature request
Assigned:
Unassigned
Reporter:
Created:
13 Oct 2016 at 09:19 UTC
Updated:
13 Sep 2025 at 14:44 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #2
sam152 commentedPatch attached. Once #2757007: Convert all book web tests to BrowserTestBase lands, we'll update the assertion in that test to use WebAssert, so some part of core flexes this method.
Comment #3
dawehnerThis looks like a nice addition. Sadly we are currently a bit stuck in the discussion what we want to add in our testing framework.
Note: We should have tests for our tests.
Is there a reason you haven't used
$this->assert()?Comment #4
sam152 commentedThis method was wholesale taken from the other issue. I'll look into the feedback.
Do we already have some tests for our test assertions? Can you point me to them? Couldn't find any.
Comment #5
dawehnerWell we have
\Drupal\Tests\Core\Assert\AssertLegacyTraitTestand\Drupal\FunctionalTests\BrowserTestBaseTestComment #6
claudiu.cristeaThis code is copied from #2757007: Convert all book web tests to BrowserTestBase and, yes, I agree that this should go as
$this->assertNotSame().On the other hand, I'm asking if we should not have 2 methods like this: one searching in page HTML, the other in page Text.
EDIT: That would be: orderInPageText() and orderInPageContent()
Comment #7
claudiu.cristeaAlso here, I would collect all "not found" items and throw the exception after
foreach() {...}, if case. This would be more helpful for the debugging.Comment #8
dawehnerWell, web asserts cannot access the usual assertions, just use
$this->assert()though is fine. We are writing a new assertion here, so using "just"$this->assertis kinda fine.Comment #10
claudiu.cristea@dawehner, how about this?
EDIT: Ignore the interdiff, it's a wrong patch.
Comment #11
claudiu.cristea.
Comment #12
dawehnerI'd have expected this method to be named
orderInPageHtml, so its clear what this is about. Content is quite a vague term to be honest.Comment #13
claudiu.cristeaOK, renamed. But I see often in the new phpunit framework the usage of Text for what a user sees in the browser and Content for page markup.
Comment #14
dawehnerOh do you have some examples? In that case it totally makes sense to keep content around.
Comment #15
claudiu.cristea@dawehner,
This?
But, anyway, "HTML" sounds more explicit for me, too.
Comment #16
dawehnerOh you are right, given that it feels a bit better to use content? Please decide what you think is better.
Comment #17
claudiu.cristeaI don't have a strong opinion. I like more "html", because it tells better the story. On the other hand seems that "content" is more consistent, right?
Here's a version with "content". Committers are able to chose between #13 and #17 -- we always drop the big decisions on core committers :)))
Comment #18
dawehnerHa, good idea!
Comment #19
lendudeNice addition to the test framework!
Not sure about the logic in
orderInPageHelper()thought. Currently, if you search for the same string twice this will fail.example:
$this->assertSession()->orderInPageContent(['item3', 'item3', 'item2']);will fail, where I would expect it to pass.
Why not just loop through the strings and use the $pos of the previous string as an offset in strpos and just check === FALSE? Seems more straight forward to me.
Some other things:
This should probably use a try-catch/fail-pass pattern like in testLegacyFieldAsserts(), that will make it easier to add more cases to this test.
Why not make this public and rename to assertOrderInString or something? I can see a use case for testing the order of strings in something else then the full page.
Comment #25
andyf commentedAdded new task: search for @todos.
Comment #26
claudiu.cristeaMoved to 8.8.x as is about test framework.
Comment #27
claudiu.cristeaComment #29
claudiu.cristeaThe book titles are placed inside
<input .../>tags, so we need to use the method that is searching markup, not in text.Comment #30
andyf commentedDoes it also make sense to test the correct strings in the wrong order?
Now that it's using an offset, if the actual content is
'AB'and you expect['B', 'A']I think it will throw anElementNotFoundExceptionrather than failing on the order.I guess this is not using
assertSame()to have a neat customised assertion message?There was some talk from #12 about whether to call this
orderInPageContentororderInPageHtmlbut currently the assertion hasContentin its name while it callsgetHtml()(which returns the inner HTML apparently) rather thangetContent(). It's an edge case, but I guess it makes more sense to usegetContent()on the off-chance someone wants to assert on the attributes of the html element itself?!Thanks for teaching me more about Drupal test exceptions (:
Thanks!
Comment #31
claudiu.cristea@AndyF, thank you for review.
#30.1: Added a test case.
#30.2: True. Fixed.
#30.3: I tried with assertSame() but because of offset the message is misleading. For instance it's possible to receive such an output:
and this might confuse the user as the actual order contains also item1 & item2. I went with a simple message.
#30.4: So, "content" or "html"?
#30.5: 👍
Comment #32
claudiu.cristea#2769825: Cannot swap tabledrag rows by dragging the lower over the upper row in tests is merged, we can now remove the @todo. However, I would wait to see it that goes also in 8.8.x because this also qualifies a as 8.8.x (because is an addition to the test framework).
Comment #33
andyf commentedOh yeah, that's a very confusing message, +1.
I don't see a big difference, my vote goes for content just in case there's ever a need to assert order on the root html element itself, which seems a bit edge-case, but you know what they say about assumptions (:
Does it make sense to use
@covers?I don't think this is actually asserting the exception happens, just asserting the message if it does. I think
\PHPUnit\Framework\TestCase::expectException()is the right tool here (and again below).Thanks
Comment #34
claudiu.cristeaMoving back to 8.9.x as #2769825: Cannot swap tabledrag rows by dragging the lower over the upper row in tests was not committed to 8.8.x.
#33.1: Yes, let's use
@covers.#33.2:
I agree, it was an incomplete implementation. Now it asserts also that the exception is thrown and fails if not but still checks for the correct exception message.
In this particular test we cannot use
::expectException()as you cannot have multipleexpectException()in a single test. See https://thephp.cc/news/2016/02/questioning-phpunit-best-practices and https://stackoverflow.com/questions/1593834/how-do-i-test-for-multiple-e.... Please, also read comment #19.1.As #2769825: Cannot swap tabledrag rows by dragging the lower over the upper row in tests has been committed I removed the custom implementation from the table drag test.
Comment #35
andyf commented👍
I don't know how much we care, but there's still a mismatch between the name used in the WebAssert method and the call made to the page object. (Just in case I wasn't clear before,
\Behat\Mink\Element\DocumentElementhas bothgetContent()andgetHtml()).Apart from that one question about html/content it looks great to me, thanks.
Comment #36
chi commentedThere is a CS issue in orderInString method.Edit: Never mind. I modified that file myself accidentally.
Comment #37
claudiu.cristea#35.1:
@AndyF, Wow, finally I got the problem. I wasn't aware about the two methods. Inspecting both, I see they are different but are leading to the same results. So, I went with
::getContent().#36: @Chi, I cannot find this CS warning, neither the error in
::orderInString().Comment #38
andyf commented👌 Looks good to me, thanks.
I'm also a bit lost as to where that might come from, I don't see any CS messages.
Seeing as this a) only adds new testing capabilities (which it tests) and b) there are two pre-existing tests that now use it and c) everything's green, I'm tentatively setting it to RTBC despite being just one, hope that's ok...
Comment #39
alexpottorderInPageContent and orderInPageText is too close. This methods should be named like the ones in \Behat\Mink\WebAssert... so something like
responseHasOrder()andpageTextHasOrder().Also sometimes I guess I'm wondering why we don't use responseMatches and pageTextMatches and supply a regex.
Comment #40
ravi.shankar commentedHere I have made changes as suggested in comment #39.
Comment #41
fenstratThe changes in #40 look good, thanks.
Comment #43
xjmComment #44
xjmThanks for working on this. These seem like they could be helpful API additions, although the fact that we've only found two tests to change makes me wonder if they're useful enough to be worth maintaining, given that we also have ongoing work to deprecate a lot of our various custom assertions in favor of PHPUnit-native stuff. Without spending too much time on it, could we identify other tests in core for which these assertions might be useful?
Is there a particular reason these are using
responseHasOrder()rather thanpageTextHasOrder()? The previous test was doinggetHtml()rather thangetText()but it still seems like it should work, no? Since (reading the text) these are the book titles, rather than anything internal to the markup? Edit: If I'm wrong about that, feel free to say so. Thanks!This is out of scope, but: Worst fixture name ever.
renderOrderInPage()is a weird name for this; that sounds like it's rendering the order of things in the page, rather than rendering a page with things in a particular order. MayberenderPageWithOrderedContent()?This should probably say "in the response content".
responseHasOrder()is a little weird for the method name; makes me think it's about the order response headers were returned in, or something. MayberesponseContentHasOrder()would be a more clear name that would also still allude to the difference betweenpageTextContains()andresponseContains()?Nit: "Several" in this one-line summary seems overly specific. It could be "two" or "dozens", neither of which are "several". (Or even one or zero, although neither of those would be particularly useful to make assertions about.) Let's say "multiple" instead of "several"?
Also, maybe we should add tests that document the expected behavior with zero or one entries in the array?
OK, but why? (The comment should explain why.)
Thanks!
Comment #45
alexpottIt'd be useful for #2932016: Entity names in the 'add view' form are unsorted for example.
This should be $this->assertSame($expected_order, $actual_order, 'Strings found but incorrectly ordered') because then PHPUnit will then show you the incorrect order - which is helpful.
Comment #46
deepak goyal commentedHi @alexpott
Made changes as you suggested please review.
Comment #49
claudiu.cristea@xjm here's another use-case #3207047: Value & format scrambled when text_format element is in a subform . I've updated the IS with the occurrences I've found on a bird-eye check.
Comment #50
spokjeLet's start with a reroll against
9.2.xComment #51
spokjeThis should make TestBot happy
Comment #52
spokjeThis addresses #49
Comment #53
spokjeKeeping this on
Needs worksince all the points made by @xjm in #44 were not addressed yet.Comment #54
spokjeNote: Expecting Failures from #3207086: [HEAD BROKEN] Consistent failure in MonthDatePluginTest
Comment #55
spokje#3207086: [HEAD BROKEN] Consistent failure in MonthDatePluginTest was committed. Ordered retest.
Comment #56
spokjeAddressed:
#44.1: The text the test is looking for is actually in an
<input type="text">-tag and isn't found when just searching for text. (Been there, tried that, no T-shirt)#44.2: Agreed. (Both on worst name and out of scope)
#44.3: Renamed.
#44.4: Changed.
#44.5: Renamed.
#44.6.1: Comment changed.
#44.6.2: Added both requested tests.
#44.7: Not a clue TBH, changed it back to throwing a
ExpectationExceptionComment #57
spokjeComment #58
spokjeComment #59
andyf commentedRe #44.7, I had thought it was using
ResponseTextExceptionjust because it's a specialization ofExpectationExceptionthat seems to fitpageTextHasOrder()(and notresponseContentHasOrder()): Exception thrown when an expectation on the response text fails.It seems consistent with
\Drupal\Tests\WebAssert::pageTextContains()throwing aResponseTextExceptionwhile\Drupal\Tests\WebAssert::responseContains()just throws anExpectationException.Comment #60
spokje@AndyF in #59:
Ah, that makes sense now.
Since I just love consistency, changed it back to
ResponseTextExceptionThanks for the explanation.
Comment #61
spokjeComment #62
spokjeGrmbl...
Comment #64
spokjeComment #65
renatog commentedOn this line, the array passed the 80 chars
$this->assertSession()->orderInString(['item1', 'item2', 'item1', 'item1', 'item2'], 'item1.item2.item1.item1.item2');On this please could you split the array in a second line? E.g:
It's easier to read code with long arrays
Comment #66
spokjeThanks @RenatoG, well spotted.
Addressed in attached patch.
Comment #68
spokjeUsed
2817657-66.patchas base for the MR against9.3.xComment #70
spokje- Rebased MR on
9.4.x-dev- Merged latest commits from
9.4.x-devComment #73
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #75
hmdnawaz commentedRe-rolled the patch in #66 for Drupal 9.5 version
Comment #76
hmdnawaz commentedRe-rolled for 10.1.x
Comment #77
hmdnawaz commentedFor 10.4
Comment #78
catchI think the signature should be more like ::assertStringOrder($items, $markup) - we can then get $markup from the page, but also from direct rendering or other sources. I needed something like this for #3546376: Use the 'yield' option instead of output buffering for twig rendering to support async rendering and found this issue.