Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2.2.0 introduced BC breaks #180

Open
mxr576 opened this issue Jul 4, 2024 · 6 comments
Open

2.2.0 introduced BC breaks #180

mxr576 opened this issue Jul 4, 2024 · 6 comments

Comments

@mxr576
Copy link

mxr576 commented Jul 4, 2024

I am a strong advocate for type safety and the use of PHPStan in legacy projects. However, I encountered an issue stemming from the recent changes in the MinkBrowserKitDriver library, which introduced a breaking change in a minor version update.

The commit c1c3a2fd143e78ccfe8ec4363d42edcc46e3fdfa narrowed the type from no type to string for several parameters. This change was released in a minor version (2.2.0) instead of a major version, resulting in a backward compatibility (BC) break.

This change has caused test failures in downstream projects, such as Drupal core and contrib/custom modules, which previously worked with version 2.1.0 but now fail with version 2.2.0.

Example of Failure

In Drupal core, the following test fails:

1) Drupal\Tests\.......
Behat\Mink\Exception\DriverException: Only string values can be used for a radio input.

/mnt/files/local_mount/build/vendor/behat/mink-browserkit-driver/src/BrowserKitDriver.php:415
/mnt/files/local_mount/build/vendor/behat/mink/src/Element/NodeElement.php:118
/mnt/files/local_mount/build/web/core/tests/Drupal/Tests/UiHelperTrait.php:96
/mnt/files/local_mount/build/web/core/modules/user/tests/src/Functional/UserRegistrationTest.php:136
/mnt/files/local_mount/build/vendor/phpunit/phpunit/src/Framework/TestResult.php:729

Changes in Downstream Projects

To address this issue, Drupal core has updated its minimum requirement to >=2.2.0 and modified integer method parameters to strings to comply with the new type constraints. You can view the changes made in Drupal core here.

Backward Compatibility Check

Using Roave/BackwardCompatibilityCheck, the following breaking changes were identified:

$ git clone https://github.com/minkphp/MinkBrowserKitDriver.git
$ cd MinkBrowserKitDriver
$ docker run --rm -v `pwd`:/app nyholm/roave-bc-check --from=v2.1.0

[BC] CHANGED: The parameter $baseUrl of Behat\Mink\Driver\BrowserKitDriver#__construct() changed from no type to a non-contravariant string|null
...
[BC] CHANGED: The parameter $xpath of Behat\Mink\Driver\BrowserKitDriver#getFormField() changed from no type to string

(Full list of changes omitted for brevity)

Conclusion

Releasing such significant type changes in a minor version has caused unexpected failures in dependent projects. It would be prudent to release such changes in a major version update to adhere to semantic versioning principles and avoid breaking backward compatibility.

Recommendation In the 2.x branch, trigger user level deprecations for invalid input by using trigger_error() instead of throwing an exception.

@mxr576
Copy link
Author

mxr576 commented Jul 4, 2024

The Selenium driver and the behat/mink package may also introduced a similar problem.

@stof
Copy link
Member

stof commented Jul 5, 2024

Passing something else than a string value for a radio note was never supported across Mink drivers. In older versions, it was either silently failing or loudly failing or doing a bad thing or doing a "good" thing by luck, depending on the driver being used and the kind of values (passing an integer might have worked by luck thanks to an implicit casting to string happening somewhere).

Note that you don't need to bump the min driver version: version 2.1 of the driver was already accepting strings as valid values (and it was the only kind of values that was tested for radio buttons).

and for parameters like $baseUrl or $xpath, the phpdoc has always documented the supported argument type as being string|null or string respectively. If you were passing values not matching the documented contract, you were not covered by any backward compatibility behavior for those usages.

@stof
Copy link
Member

stof commented Jul 5, 2024

Note that Roave/BackwardCompatibilityCheck does not consider the phpdoc when checking for signature change. It look only at the native PHP signature, which means that any case of migrating from phpdoc argument types to native argument types is considered as a BC break by that tool, while it is a compatible change (when requiring PHP 7.2+ to support variance rules for non-final classes) for any project which considers the phpdoc contract as part of its public API for semver (which is approximately 100% of projects that use phpdoc)

@mxr576
Copy link
Author

mxr576 commented Jul 5, 2024

(passing an integer might have worked by luck thanks to an implicit casting to string happening somewhere).

Probably this hidden secret gem caused the problem and maybe the only problem, you can be right about the that... implicit casting in PHP is both a bug and a feature. I can also imagine that since at the end of the days ,everything is transferred as string on the wire, the browsers accepted an integer selector as long as it was valid, but now the client side (this PHP lib) does not accept it.

My question is, considering everything, could the 2.x branch restore the original, but unwanted behavior in a "lenient" mode and become fully strict in v3?

You are also right about the Roave/BackwardCompatibilityCheck limitations, I have used it to double check/prove my point, but I also know from experience that it could return false-positives (the length of the list was already surprising to me, but the method that I found problematic were there.)

@stof
Copy link
Member

stof commented Jul 10, 2024

I'd like to avoid reverting all parameter type additions (which would be a BC break because widening parameter types is not backward compatible, causing issues for requirements between Mink and driver packages). So it would be great to identify the exact changes causing issues as it might help avoiding a full revert.
And Roave/BackwardCompatibilityCheck won't help us here due to its limitation.

@mxr576
Copy link
Author

mxr576 commented Jul 30, 2024

The commit c1c3a2fd143e78ccfe8ec4363d42edcc46e3fdfa narrowed the type from no type to string

This was a problematic change for sure, the related Drupal core commit also confirms that (check all forced string typecasts).

pronovix-bot pushed a commit to Pronovix/drupal-qa that referenced this issue Aug 9, 2024
These conflicts can and has to be removed as the reason why they
were introduced ceased and these versions are not compatible with
D10.3 causing our PHPUnit tests to fail.
See https://project.pronovix.net/issues/26145 and
minkphp/MinkBrowserKitDriver#180.

Change-Id: I0bc561cc2805d78ff9070cc6305ae7d4452bc0ff
Issue-Link: https://project.pronovix.net/issues/28360
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants