Problem/Motivation
The AssertContentTrait::assertOptionSelected() method is useless at the moment.
There is a @todo in the comments that suggests switching from id to name.
An example from Paragraphs:
$this->assertOptionSelected('edit-fields-field-paragraphs-settings-edit-form-settings-add-mode', 'button', 'Updated value is correct!.');
This line tries to assert that the button option on the current form has been selected with the previous drupalPostAjaxForm() call. It currently fails because an xpath query with //select[@id='edit-fields-field-paragraphs-settings-edit-form-settings-add-mode']//option[@value='button'] doesn't return any elements. It is missing some random string at the end:
'edit-fields-field-paragraphs-settings-edit-form-settings-add-mode--XYZXYZXYZX'
A couple of screenshots - the element id:

The query drupal tries to use:

The query that is necessary (with two dashes and the random string):

Proposed resolution
Switch from using the ID to find a field in a form to using the name of the field. This would be an API change. One possible alternative would be to change the xpath query to a partial match.
Remaining tasks
Discuss, provide patch, review and commit.
Provide patch: There is one in the comments, it only changes the assertOption methods, no tests yet.
User interface changes
None
API changes
assertOptionSelected(), assertNoOption(), assertNoOptionSelected() use the name of the field instead of the id.
OR
None / behaviour of assertOption...() changes.
Data model changes
None
| Comment | File | Size | Author |
|---|---|---|---|
| #36 | assertoptionselected-2530092-36.patch | 2.29 KB | johnchque |
| #33 | interdiff_30-33.txt | 1.12 KB | LKS90 |
| #33 | assertoptionselected-2530092-33.patch | 16.56 KB | LKS90 |
| #30 | interdiff_23-30.txt | 3.53 KB | LKS90 |
| #30 | assertoptionselected-2530092-30.patch | 16.55 KB | LKS90 |
Comments
Comment #1
LKS90 commentedHere is a patch that implements the @todo from the comment.
It switches from using the id of the form field to the name. No random characters in the field name like in the ID.
I made the paragraphs test pass easily by implementing this and then switching the id with the name in the tests.
Edit: I also provided a patch for the paragraphs module which depends on this issue. You can find it here.
Comment #2
LKS90 commentedComment #4
LKS90 commentedForgot one @id in the SafeMarkup::format call.
Comment #6
LKS90 commentedComment #7
LKS90 commentedComment #8
LKS90 commentedNew version, this one replaces the
select[@id=:id]withselect[contains(@id, :id)], so a partial match is also returned (and the random characters are not necessary.). Paragraphs tests pass with this one, should also pass the core tests.Comment #9
LKS90 commentedA non-empty patch this time.
Comment #10
berdirStarts with might be a better option, to avoid false positives?
Maybe even an option to explicitly make it starts-with, not sure...
Comment #11
dawehnerInstead of using IDs we should promote assertion methods which deal which use the
data-drupal-selectorbits.Comment #12
LKS90 commentedSwitched to starts-with, also removed an additional @todo that was in the drupal-selector method and basically just wrong.
Comment #13
berdirCan we try what happens if we just switch to data-drupal-selector?
Comment #14
LKS90 commentedThis patch is made from scratch, no interdiff.
For the no versions, I copied the function itself and replaced assertTrue with assertFalse, otherwise I just call the data-drupal-selector variant. Works in Paragraphs.
Comment #16
LKS90 commentedHere is a patch that also updates one test (FilterFormTest) which fails with the changes from above.
The changes are of the same nature as the initial patch, switching from using $id/@id/:id to the data-drupal-selector.
Comment #17
LKS90 commentedHere is an updated version, I forgot to update some of the documentation and one of the replacement variable names.
No functional changes, so the testbot run of the previous patch still applies.
Comment #18
sasanikolic commentedHere we don't need to check if it contains 'required'?
We should change the $id also here to $drupal_selector, i guess?
Empty line.
Comment #19
LKS90 commentedReadded the check for the required attribute, switched $ids which were data-drupal-selectors to $drupal_selectors, removed useless empty line. The interdiff is a bit different, it's a diff of patch 17 and 19 instead of using git diff.
Now I'm starting to wonder why we have those functions twice, except to keep contrib modules from failing. I'd rather switch to $name instead of $id, and update all core tests to only use the
...WithDrupalSelector()variant to lead as a good example. Or we replace the current assertOption() method with the...WithDrupalSelector()variant and force contrib modules to update as well?Comment #20
LKS90 commentedSpotted another change that modifies the behaviour of a function instead of replacing the function as I meant to do.
Comment #22
LKS90 commentedAccidentally reverted the wrong function, fixed now.
Comment #23
LKS90 commentedOnly pulled, forgot to actually rebase the branch... :D
Comment #24
juanse254 commentedLooks good to me :).
Comment #25
giancarlosotelo commentedComment #27
xjmNice find!
Why is it necessary/correct to switch to the string cast here instead of the isset check? We didn't do that elsewhere in the patch. An inline comment would be good if there is a reason it's different.
This is changing the logic of the assertion in a pretty confusing way... why? I think the result is also changing for the condition where the element is not set. Before, that would trigger a fail; now, it will trigger a pass. I think; I could have gotten confused though while drawing the truth table in my head because of the compound negatives. An inline comment would be good and I feel like we also need more test coverage for this assertion's behavior itself for all four possible combinations. (Well, all three that is; the
'selected'obviously must be empty if the parent element is not set.)I think this would need a small change record for those using this assertion, also.
Comment #28
xjmBTW, for reviewers, I highly recommending doing a word diff on this one.
Comment #29
xjmForgot the tag.
Comment #30
LKS90 commentedHey there!
Thanks for the review, here is an updated patch.
I reverted both changes as they are unnecessary. The first change (with the string cast) is pointless, the xpath query already looks for the value of the form element, so if the element doesn't exist, the options array/SimpleXMLElement would be empty. I checked for the value, which would be (an) empty (string) in case the element doesn't exist, a bit too much probably. The second change is simply switching the logic around, I reverted that one as well.
I also found some text which I updated incorrectly, corrected that as well.
The patch should be easier to review now :).
I also made a change record, it's not published yet and probably needs some feedback as well (my first change record).
Comment #33
LKS90 commentedI broke the xpath query in the last patch. Here is the fix for that. This patch should pass the tests, should be easy to review and the scope is minimized to only modify things that are necessary.
Comment #34
juanse254 commentedComment #36
johnchqueIt seems we had a @todo there. I tried using the function in a contrib module but it does not work with dynamic html ids. Added the assertOptionSelectedWithName function. Should we also add something like assertOptionSelectedWithId? Also not sure if this should go to 8.2.x.
Comment #44
quietone commentedTriaging issues in simpletest.module as part of the Bug Smash Initiative to determine if they should be in the Simpletest Project or core.
This looks like it a Phpunit issue, changing component.
Comment #48
smustgrave commentedThis looks like it was already deprecated in https://www.drupal.org/project/drupal/issues/3114617 in favor of
Should this be closed as a duplicate?
Comment #49
berdirI'd say outdated it is, we didn't fix the problem, we just removed the problematic method.