Problem/Motivation
From #3143870-10: Calls to AssertLegacyTrait::assertUrl() have wrong number of arguments: WebAssert::addressEquals is currently totally skipping the querystring of an URL. This means that tests that check on the address URL expecting or having an actual querystring are passing no matter what. Not good.
Proposed resolution
Fix WebAssert::addressEquals and WebAssert::addressNotEquals so that if the expected URL contains a querystring, the actual URL is is checked for the querystring to be equal.
Remaining tasks
review
User interface changes
no
API changes
no
Data model changes
no
Release notes snippet
no
Comment | File | Size | Author |
---|---|---|---|
#93 | 3164686-2-93.patch | 4.96 KB | alexpott |
#93 | 91-93-interdiff.txt | 2.84 KB | alexpott |
Issue fork drupal-3164686
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
mondrakeon this.
Comment #3
mondrakeA test only patch to prove the bug, and a patch with the fix - not changing yet the assertUrl calls with wrong parameters as identified in #3143870: Calls to AssertLegacyTrait::assertUrl() have wrong number of arguments.
Comment #6
mondrakeCopying hunks from #3143870: Calls to AssertLegacyTrait::assertUrl() have wrong number of arguments where the failures were fixed already.
Comment #8
mondrakeFix.
Comment #10
ridhimaabrol24 CreditAttribution: ridhimaabrol24 at Srijan | A Material+ Company for Drupal India Association commentedFixing failed test
Comment #11
longwaveFixing a one character nit in a comment, but otherwise the patch looks good so marking RTBC.
Does this need a change record? Contrib/custom tests might be unexpectedly relying on the existing broken behaviour.
Comment #12
catchLet's add a change record, but otherwise looks good.
Comment #13
mondrakeAdded CR https://www.drupal.org/node/3165286
Comment #14
larowlanThis feels like a bug in Mink too - so can we open an issue in their tracker for them as a courtesy?
This is failing cspell because of the word `scriptalertxsssubjectscript` so we need to add that to the exception list I think
Comment #15
longwaveAlready discussed at length upstream in https://github.com/minkphp/Mink/pull/566 which, if I read it correctly, was closed without fix due to backward compatibility concerns.
https://github.com/minkphp/Mink/issues/656 is also open with no response.
Comment #16
longwaveAdded cspell ignore comment.
Comment #17
mondrakethank you. it looks like Drupal has been stricter directionally, coming from Simpletest, and that was overseen when implementing WebAssert.
Comment #18
larowlanFixed on commit - cspell++, larowlan-- for not reading the output properly the first time
Committed 1e15ed9 and pushed to 9.1.x. Thanks!
Because there's a risk that this will disrupt contrib testing, I think this is not eligible for backporting. Happy to have the discussion if folks think there is a case for it - if so please re-open with reasoning.
Published change record
Comment #20
TR CreditAttribution: TR commentedIs there a way to ignore the query string? I have some tests that were broken by this - these tests were ignoring the query string because it is just a csrf token and I don't need or want to check that in every test. I have one test to ensure it's present, but in my functional tests I really want to be just testing the functionality, not the validity of the token every time.
Comment #21
larowlanI've used this in the past
Comment #22
mondrake... or use
$this->assertSession()->addressMatches()
that matches regexes, so you can have the URL path as a pattern and match against the full current URL.Comment #24
alexpottThis change is not quite correct and rather than fixing things making test writing more difficult.
I think this change when in the wrong direction - \Behat\Mink\WebAssert::cleanUrl() removes query strings for good reason. Query strings are highly dynamic and tricky to assert on.
Patch attached partially reverts #16 so contrib testing is not broken.
Revert this means we're still not checking query strings correctly - so that does need to be fixed. Then I think we need a better plan with how to test query strings if present and how to cope with destination. The only reason that
in the original patch is because \Drupal\form_test\ConfirmFormArrayPathTestForm::getCancelUrl() does not construct the destination correctly... it just hard codes
'destination' => 'admin/config',
- which is wrong.Comment #25
alexpottWhatever solution we come up with we need to massively improve the CR for the deprecation triggered when assertUrl() is called with more than one argument...
https://www.drupal.org/node/3129738 is not at all helpful.
Comment #26
longwaveLet's get the revert in and then figure out what to do to move this forward.
Could we only apply the strict rule if the expected URL contains a question mark?
Comment #27
alexpott@longwave that's a start - but the destination param with DrupalCI's sub-directory is PITA. See #2957953-99: Editing menus user-experience has regressed - it's too easy to have a test that passes locally and fails on CI - or vice versa. Other people have trod on this ground before... https://github.com/minkphp/Mink/pull/566
Comment #28
longwaveSo as discussed in Slack we likely need to special case the
destination
querystring to handle the base URL change, and perhaps also fix legacyassertUrl()
to accept a second argument containing the querystring, which Simpletest allowed but was never converted fully to WebTestBase.Comment #29
alexpottI've confirmed that PathAutoUiTest is fixed by the revert.
Comment #30
catchAgreed with reverting. Will commit once this comes back green.
Comment #33
catchCommitted/pushed to 9.2.x and cherry-picked to 9.1.x, thanks!
Moving back to needs work.
Comment #34
mondrakeOK, but bumping to critical since:
Also -
assertUrl
is dead in core 9.1, since #3139419: Replace usages of AssertLegacyTrait::assertUrl, that is deprecated. We need to understand what to do in that case.Comment #35
alexpottI've unpublished the CR. We've lived with the false positives here for years. Make something critical to get attention feels wrong. But I'm not going to play issue status games. I feel this should be left at major like the original bug because it is just the original bug.
Comment #36
mondrakeFine.
Comment #38
mondrakeHere's an idea: add a WebAssert method
urlQuerystringEquals
that checks only the querystring equality, by loading expected and actual querystring parameters into arrays so that they can be compared by PHPUnit'sassertEquals
. That would make the order of the parameters in the string irrelevant. See MR.Comment #39
mondrakeComment #40
mondrakeThe 7.3 test failure is connected to the composer.lock content hash, but that is not touched in the MR so it feels like an infra issue. For the 7.4 weirdness we have #3181910: Merge requests fail to run core PHPUnit tests on PHP 7.4.
Comment #41
mondrakeComment #42
mondrakeComment #44
anmolgoyal74 CreditAttribution: anmolgoyal74 at OpenSense Labs for DrupalFit commentedRe-rolled.
Comment #45
mondrakeComment #46
mondrakeComment #47
daffie CreditAttribution: daffie commentedComment #48
mondrakeThanks for review @daffie; replies in MR.
Comment #49
daffie CreditAttribution: daffie commentedI found 3 more files that need changes:
- modules/system/tests/src/Functional/Routing/RouterTest.php
- modules/search/tests/src/Functional/SearchLanguageTest.php
- modules/block/tests/src/Functional/BlockTest.php
@mondrake: The changes you made look good.
Comment #50
mondrakeDone #49
Comment #51
daffie CreditAttribution: daffie commentedOne nitpick.
Comment #52
mondrakeComment #53
daffie CreditAttribution: daffie commentedThe patch is for me RTBC.
Only the IS and the CR need an update.
Comment #54
longwaveAdded a few minor comments. Do we need to do anything special for the destination query string, as @alexpott alluded to earlier in this issue?
Comment #55
mondrakeThanks, replied in MR
Comment #56
mondrakeUpdated CR.
Comment #57
mondrakeUpdated IS
Comment #58
daffie CreditAttribution: daffie commentedComment #59
mondrakererolled
Comment #60
mondrakeRerolled.
Comment #61
daffie CreditAttribution: daffie commentedThe testbot is not happy.
Comment #62
SpokjeLooks like one of the TestBot's incarantions HDs is full, already encountered this in another issue and asked around in Slack (https://drupal.slack.com/archives/C51GNJG91/p1621922820016900), added this one also.
FWIW: On my incarnation simply ordering a retest made my issue go away (probably because I've got a different TestBot than before).
Ordered a re-test here as well.
Comment #63
mondrakeNo it's something more evil, like a contributor not testing before posting a patch. Horrible!
On this
Comment #64
mondrakeComment #65
SpokjeOh noes! That never ever happens! 😈
Comment #66
daffie CreditAttribution: daffie commentedAll the changes look good to me.
As far as I can see, we got all instances that need the new method.
There is a CR for the new method.
For me it is RTBC.
The only reason I am not setting the status to RTBC, is because the patch from the 9.2 MR does not apply to 9.3.
Comment #67
mondrakeRebased onto 9.3.x
Comment #68
mondrakeI messed up the MR branch, cleaning up
Comment #71
mondrakeComment #73
mondrakeOh my, I can't get MR working for me. Reverting to g'old patch.
Comment #74
daffie CreditAttribution: daffie commentedAnd who was the person who said that working with MR's was so much better then working with those patches? :grinning:
@mondrake I do not know what you did with the MR. I have tried compare the MR, that was for me RTBC, to the new patch. And I could not do it.
I had saved the MR as a patchfile on my local machine and all the changes are the same. Therefore this is RTBC for me.
Comment #75
mondrakeHaha, touchè.
I was trying to re-target the MR to 9.3.x. The problem was that in 9.2.x some stuff was removed to make it for the release, but not in 9.3.x. Having rebased the issue branch earlier onto 9.2.x, when changing the MR target to 9.3.x, stuff was not added back to the branch. IDK what is the right thing to do here.
Then, I had a couple of earlier branches for this issue in my local repo, and could not get a new clean branch to work on. At that point, I just cut short and made the patch :)
Thanks for review @daffie!
Comment #76
alexpottI wonder if we should push on the upstream project again. I think if we include a query string in addressEquals then it should check it. It's far too easy to write an assertion and think you've got it right - as shown by our code base.
I think if we want to implement a workaround in core we should do something like only asserting on query strings if the assertion contains a query string. So if you do
$this->assertSession()->addressEquals('admin/structure/block/list/classy?block-placement=' . Html::getClass($block['id']));
it will test the query string but if you do$this->assertSession()->addressEquals('admin/structure/block/list/classy');
it won't. That way you preserve BC but you break when the unexpected thing is happening.Do we need this given it is a new method?
Comment #77
longwaveNit: Querystring -> QueryString
Why does this pass? What is it testing?
Comment #78
mondrakeThat's a good idea. Do we want to keep the separate, new, method anyways, or are we merging that into
addressEquals
? Do we need a method to check a querystring independently from the URL address?Comment #79
alexpottI don't think we need more methods - I think once we've implemented it for us we should try again upstream - because if you include a query then I think it should either error or check it... and checking it seems better.
Comment #80
mondrakeSomething like this?
Comment #82
longwaveaddressEquals() only takes strings - not sure how this worked before, as you can't cast a Url to string?
Comment #83
longwaveAlso, should we be strict with the query strings here, or not? ie. if we expect
?a=1
should?a=1&b=2
be considered a pass, because that would be OK from most web applications' point of view?Comment #84
mondrake#83 good point, we should probably check only equality for the query parameter keys that are in the expectation, disregarding extra keys that occur in the actual.
Also, need to figure out what to do for addressNotEquals.
Comment #86
longwaveWhoops, didn't see our overridden
cleanUrl()
- I think we should just use that.Comment #87
alexpott$this->cleanUrl($page) is gonna remove the query from $page so the if will never evaluate to true... we need to write a test that is expected to fail :)
Comment #88
longwaveArgh yes. Let's try again, splitting cleanUrl() in two and adding some tests.
Comment #89
longwaveComment #90
longwaveComment #91
alexpottThis is tricky. This futzes with stuff.
I'd approach this a bit differently. I think we should maintain the same Behat\Mink exception and do something very similar as the parent but in the case that $page includes a query then it should be checked too. Something like the patch attached. Both could do with quite a bit of documentation. Another concern is that you can't assert that a page has no query parameters (like HEAD) but I'm not too sure that in practise that matters. Also this fix is pretty much what I think the upstream fix should look like.
Comment #93
alexpottFixing the test fails...
Comment #94
mondrakeIMHO these two URLs are equivalent (=equal); the order of the keys is not relevant.
Comment #95
alexpott@mondrake I think we should reduce the futzing with the comparison not add. However, if we do want to do that we could consider using \GuzzleHttp\Psr7\UriNormalizer as this has all the tools to do url comparison... however reading the docs there:
I think "IMHO these two URLs are equivalent (=equal); the order of the keys is not relevant." is an assumption that is 99% true but I'd bet there is a contrib / custom module out there where this is not correct.
I also think that evaluating 'test-page?a=b&c=d' to be equal to 'test-page?c=d&a=b' is not in the spirit of the principle of least surprise (also the current behaviour of addressEquals and addressNotEquals also goes against this)
Comment #96
mondrakeWith rationale in #95, this is RTBC. The CR is now irrelevant. Updated IS.
Comment #97
mondrakeComment #98
longwaveI had the same concern as #94 but #95 makes sense and we can always revisit this later to make it less strict if it turns out we need that for some reason.
This is what this assertion was meant to do in the test?
Anyway, RTBC +1
Comment #100
mondrakeRandom test fail.
Comment #102
catchLet's try this again :)
Committed/pushed to 9.3.x, thanks!