Problem/Motivation
Sometimes we need to inspect hidden fields on forms but Mink fail to recognise those fields in \Behat\Mink\WebAssert::fieldExists(). It's just throwing an ElementNotFoundException. This happens because Mink observe fields like a human using the browser. His search is reaching only human visible fields and WebAssert::fieldExists() simply filters out hidden fields from the search. While manipulating hidden fields can be done in JavascriptTestBase with JavaScript, simply inspecting them should be made possible in BrowserTestBase.
Proposed resolution
While keeping the WebAssert::fieldExists() at his current behaviour, implement dedicated methods foe hidden fields inspeection.
Remaining tasks
None.
User interface changes
None.
API changes
New methods dedicated to hidden fields in WebAssert:
- ::hiddenFieldExists()
- ::hiddenFieldNotExists()
- ::hiddenFieldValueEquals()
- ::hiddenFieldValueNotEquals()
Data model changes
None.
| Comment | File | Size | Author |
|---|---|---|---|
| #48 | 2767655-hidden-fields.48.patch | 7.2 KB | larowlan |
| #45 | interdiff.txt | 1.01 KB | claudiu.cristea |
| #45 | 2767655-45.patch | 7.18 KB | claudiu.cristea |
| #5 | browsertestbase_hiddenfields-test-only.patch | 1.39 KB | claudiu.cristea |
Comments
Comment #2
claudiu.cristeaComment #3
claudiu.cristeaComment #5
claudiu.cristeaUps.
Comment #6
claudiu.cristeaComment #8
claudiu.cristeaPatch.
Comment #9
claudiu.cristeaI guess this is Major for testing framework as it blocks other test conversions.
Comment #10
claudiu.cristeaSmall naming fix.
Comment #13
claudiu.cristeaRefined our implementation of fieldExists() letting also 'named_exact' selector to run.
Comment #15
claudiu.cristeaHm. Interdiff is from #13.
Comment #16
claudiu.cristeaOptimize more fieldExists().
Comment #17
jibranCan we push this change upstream?
Comment #18
claudiu.cristea@jibran
Push where, In Mink repo? Their philosophy is to search for visible fields. I don't think such a selector will be accepted. But, by architecture. they are flexible. That's way we could add the new selector.
Comment #19
claudiu.cristeaHm. It's not enough to allow BrowserTestBase::drupalPostForm() to use hidden fields. Other assertions are suffering too. For example
$this->assertSession()->fieldValueEquals()& Co. They need to be able to search for hidden fields too.EDIT: Shouldn't we make WebAssert::fieldExists() and WebAssert::fieldNotExists() take into account hidden fields without any condition (w/o passing the flag as parameter)?
Comment #20
claudiu.cristeaI guess we need to expand the scope of this issue by extending
WebAssert::fieldExists()andWebAssert::fieldNotExists()to hidden fields. Lets' see if is workingComment #21
claudiu.cristeaComment #23
claudiu.cristeaSorry, bad patch. Interdiff correct in #20.
Comment #24
claudiu.cristea@jibran, I published also a PR upstream https://github.com/minkphp/Mink/pull/711. But this should not be a blocker for this issue.
Comment #25
larowlanI was kind of against this, given there is no valid use-case for editing a hidden field except in a JavaScript scenario.
But the code is low impact and helps us with writing tests for things like nefarious dom manipulation.
+1 RTBC from me.
Comment #26
claudiu.cristeaThe patch was expanded to field finders (
WebAssert::fieldExists()andWebAssert::fieldNotExists()). Changed the title to reflect that.Comment #27
dawehnerThank you for fixing this problem! I moved it to the phpunit component, as it kinda belongs more into that area.
Could we maybe document with a one liner, why we need it? "Per default hidden fields are not available".
Just in general, did someone checked out whether this is something mink would consider to have upstream, or maybe even be fixed as default behaviour upstream?
I'm wondering whether we should instead change out the existing selectors, by passing along
['named_partial' => new PartialNamedIncludingHiddenSelector()]above? This would allow us potentially to not add all this custom code below.Comment #28
claudiu.cristea@dawehner, thank you for review
#27.1: Done,
#27.2: I opened a PR upstream https://github.com/minkphp/Mink/pull/711. There's a discussion about the opportunity to have that in Mink. They seem reluctant.
#27.3: Yes, we can. The reason why I didn't went to that solution from the beginning (it would have been the straight way) is that I wanted to keep also the native Mink ability to filter out hidden fields. I don't know, maybe we need to create our own methods in WebAssert for searching also hidden fields and let those 2 methods untouched so we have both alternatives. Their way is based (I think) on the assumption that a field must be a human visible field.
Comment #29
dawehnerIdeally though I agree with the points that we should not expose a feature normal browser users don't have per default to our tests? Maybe just adding this capability to javascript tests seems to be a better approach. I also left a small comment on the github issue.
Comment #30
claudiu.cristea@dawehner, hm, but what about BrowserTestBase tests? They are coming from WebTestBase. The book pages ordering is such a case where we are using a non-JS browser but we are emulating a JS behaviour by manipulating (in behalf of JS) the hidden fields. Probably we'll have to move those tests as JS tests?
Comment #31
dawehner@claudiu.cristea
I mean in this example its kind of obvious. Reordering books is a clear JS feature, so they should be tested in JS, rather than faked using PHP.
Comment #32
klausiI'm not sure we should do this. If the use case is only faking Javascript by manipulating hidden fields, then we should not do this and convert the test to a proper javascript test instead.
Can you provide some other use cases in the issue summary where we would want to manipulate hidden fields? @larowlan mentioned nefarious DOM manipulation, but why would you do that in a functional test?
Comment #33
dawehner@klausi
Yeah I still believe having a WebAssert for JS, as we actually already have in
\Drupal\FunctionalJavascriptTests\JSWebAssertand put it on there is conceptually better.Comment #34
alexpottThere's another related issue - how about you want to assert on the value of a hidden input? $this->assertFieldById() does not work on hidden fields because of this.
Comment #35
alexpottSo
$this->assertSession()->fieldValueEquals()does not work eitherComment #36
claudiu.cristea@alexpott, Probably we want some dedicated assert methods only for hidden fields to cover such cases. ::assertHiddenFieldById(), $this->assertSession()->hiddenFieldValueEquals()? Then we can keep the actual behaviour for existing methods
EDIT: @alexpott, The patch from #23 can be a starting point.
Comment #37
claudiu.cristeaHere's a try that provides dedicated methods in WebAssert that work only for hidden fields inspection. Given to #34, I think this is reasonable to have in Drupal BrowserTestBase. Inspection not manipulation.
Comment #38
claudiu.cristeaTypo, nits, IS.
Comment #39
catchComment #40
dawehnerStrictly speaking this is no BC layer, should we try to add one or talk about that in another issue?
Comment #41
dawehnerI like this approach, less magic and more explicit code!
Comment #42
effulgentsia commentedDiscussed with @xjm and @catch, and we decided this is "rc eligible". The one hesitation we have about that is that it's not only changing tests, but also making an addition to a testing API: WebAssert could in theory be subclassed, and contrib/custom code might have such a subclass with these method names and collide. But, we think the risk of this actually being the case is sufficiently low, and the disruption for such a project/site wouldn't be breaking live code, but only a CI workflow, until fixed.
Comment #44
alexpottI'm pretty sure that this types of comments are no allowed in our coding standards - also 80 chars...
Needs a reroll - doesn't apply to 8.3.x - which is where the patch needs to be committed first.
Comment #45
claudiu.cristeaAs is only a tiny docs change and reroll, I set it back to RTBC as per #41.
Comment #47
catchFixed this on commit:
We should discuss whether to cherry-pick this to 8.2.x, so leaving at 'to be ported' there.
Comment #48
larowlan8.2.x backport
Comment #49
claudiu.cristeaHere I'm RTBCing only the port to 8.2.x, not the patch itself. The patch has been already reviewed.
Comment #54
berdirI have a feeling that this is not going to be backported to 8.2.x anymore :)
Struggled a bit to get this working with drupalPostForm(), what worked is using hiddenFieldExists() to get the hidden form elements and then setValue() on them, and then doing a drupalPostForm() only with the remaining visible form elements.
Comment #56
hermann77 commentedI have no luck with drupalPostForm() so my way to test forms with hidden fields is like this: