It is currently hard to do work with objects implementing SafeStringInterface in tests as we have to do string casting in the calling tests themselves as opposed to already allowing for this in the TestBase helper methods.
We use these objects more and more, and people shouldn't have to cast when doing simple equality checks with another string.
In working on #2557113: Make t() return a TranslationWrapper object to remove reliance on a static, unpredictable safe list most of he work went into fixing test fails rather than actual code that broke - without a patch like the work would be quite a bit more involved, so this will definitely be a help to contrib as well in having less refactoring to do in dealing with the BC break.
| Comment | File | Size | Author |
|---|---|---|---|
| #26 | interdiff-25-26.txt | 1.16 KB | stefan.r |
| #26 | 2560729-26.patch | 12.77 KB | stefan.r |
| #25 | 2560729-25.patch | 13.73 KB | stefan.r |
| #25 | interdiff-18-25.txt | 7.06 KB | stefan.r |
| #23 | interdiff-20-23.txt | 565 bytes | stefan.r |
Comments
Comment #2
stefan.r commentedComment #3
stefan.r commentedcomments from @dawehner in the parent issue:
+++ b/core/modules/simpletest/src/AssertContentTrait.php
@@ -178,6 +179,10 @@ protected function getUrl() {
+ // @todo fix this
+ if ($value instanceof SafeStringInterface) {
+ $value = (string) $value;
+ }
IMHO for xpath we can always cast to string, right? anything else would not pack anyway, given how xpath works
+++ b/core/modules/simpletest/src/TestBase.php
@@ -654,6 +655,18 @@ protected function assertNotNull($value, $message = '', $group = 'Other') {
+ if (is_array($first)) {
+ array_walk_recursive($first, [$this, 'translationWrapperToString']);
+ }
+ if (is_array($second)) {
+ array_walk_recursive($second, [$this, 'translationWrapperToString']);
+ }
@@ -683,6 +696,15 @@ protected function assertNotEqual($first, $second, $message = '', $group = 'Othe
+ * @todo remove this
+ */
+ public function translationWrapperToString(&$value) {
+ if ($value instanceof SafeStringInterface) {
+ $value = (string) $value;
+ }
+ }
+
What about using strval for iteration?
Comment #4
stefan.r commentedComment #5
stefan.r commentedUpgrading to major as these were split out of a Major issue
Comment #6
stefan.r commentedComment #7
stefan.r commentedSeems we already do something similar in AssertContentTrait::assertThemeOutput() as well:
Comment #8
stefan.r commentedSadly this can't really be tested, so a few manual reviews would be good.
As to #3, I had rather it keep failing on anything other than SafeStringInterface... And strval the same concern -- I'd rather not blindly cast everything to string.
Comment #9
alexpott#2560715: Prefer toString to __toString in renderVar for ToStringInterface is very related to this... perhaps we want to push on that one first.
Comment #10
stefan.r commentedAgreed...
Comment #11
joelpittetThat is now closed won't fix, so opening this up again.
Comment #12
stefan.r commentedJut gave this another look and not much to add here.
We already use
SafeStringInterfacein various places interchangeably with strings and in the renderer we do quite a bit of string casting as well so it only makes sense for us to cater to this in tests.SafeMarkup::format()may soon only output safe strings anymore for instance.This is all a bit magical and it will make the equality checks and assertions more lenient but I don't really see where this could currently pose any serious problem. Maybe in the future we (or contrib) will have some wonky objects implementing
SafeStringInterface, but it should only be used for value objects anyway, andTranslationWrappersseem like the only possible place where casting is a bit more involved than printing the value. And that is where we actuallly /want/ the string casting as when we make t() return a TranslationWrapper, the string casting in tests will make the BC break less severe as it will make t() behave the way it used to historically.In #2557113: Make t() return a TranslationWrapper object to remove reliance on a static, unpredictable safe list most of the work went into fixing test fails rather than actual code that broke - without a patch like tere the work would be quite a bit more involved, so this will definitely be a help to contrib as well in having less refactoring to do in dealing with the BC break.
Comment #13
stefan.r commentedComment #14
lauriiiDo we need casting on assertEqual? Anyway for me the patch looks sane. Lets just add some documentation at least for the assertIdentical that its parameters will be automatically casted from SafeStringInterface to string because it might be unexpected.
Comment #15
stefan.r commentedAdded comments to clarify - I think we want to keep the string cast in assertEquals() just to be sure, rather than relying on PHP silently casting compared TranslationWrappers to string.
Comment #16
lauriii80 chars
Maybe remove the reference on that issue or at least make it something that works also after the issue has landed and if the issue doesn't ever get commited.
Comment #17
stefan.r commentedComment #18
lauriiiFixed the 80 chars problem. Otherwise RTBC for me.
Comment #19
alexpottLet's make this an anonymous function that way we don't have wonder why we're not using it elsewhere. In fact you could make a helper method for an array because there are other array_walk_recursive().
string and single |
I think that just the string cast is fine... is the interface checking everywhere really necessary? How about something like this...
Comment #20
stefan.r commentedI'd rather err on the side of being more specific in these cases rather than blindly casting - we don't want false positives/negatives or hide any errors when passing in NULL/FALSE or such.
Anyway let's see if this passes tests anyway, these seem like they should be fine.
Comment #21
stefan.r commentedComment #23
stefan.r commentedComment #25
stefan.r commentedConverted the ones that were possible -- turned one into an isset (as it could also be NULL) and two into a more lenient "is_object" as they could also be NULL or an array.
Comment #26
stefan.r commentedRemoving the cast from the identical check, we'll have to run $this->castSafeStrings() in the individual tests themselves before identical checks that include output from t()
Comment #27
alexpott@stefan.r or just change to
assertEquals()Comment #28
lauriiis/list/mixed but can be fixed on commit. Otherwise everything looks good.
Comment #29
alexpottThis is a bit ugly but it is test code so I'm not too bothered. Committed 1bd7a29 and pushed to 8.0.x. Thanks!