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

Use strpos instead of preg_match for responseContains/ResponseNotContains in WebAssert #743

Merged

Conversation

NickDickinsonWilde
Copy link
Contributor

As far as I can tell, especially with the existence of WebAssert::responseMatches, it doesn't make sense to create a regex/use preg_match in responseContains/NotContains.

Maybe there is a reason for the use of preg_match there, but I did a search for prior issues/history and couldn't find any discussion. If there was and I missed it, a link would be great.,

@NickDickinsonWilde
Copy link
Contributor Author

CI failing due to the tests. I had always assumed responseContains() was case sensitive. However, it clearly wasn't; so replacing strpos with stripos would allow the performance benefit without changing prior results.

$message = sprintf('The string "%s" was not found anywhere in the HTML response of the current page.', $text);

$this->assert((bool) preg_match($regex, $actual), $message);
$this->assert(strpos($actual, $text) !== false, $message);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The i modifier of preg_match was to match in case-insensitive manner, so to replicate that you need to use stripos instead of strpos.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, should've notice when I removed it.

$message = sprintf('The string "%s" appears in the HTML response of this page, but it should not.', $text);

$this->assert(!preg_match($regex, $actual), $message);
$this->assert(strpos($actual, $text) === false, $message);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The i modifier of preg_match was to match in case-insensitive manner, so to replicate that you need to use stripos instead of strpos.

@NickDickinsonWilde
Copy link
Contributor Author

Remainder of issues Travis brings up appear to be some broken environments and unrelated to this pr.

Copy link
Member

@aik099 aik099 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

Not sure if u modifier of preg_match (see http://php.net/manual/en/reference.pcre.pattern.modifiers.php) is even needed. As per docs it triggers a warning on malformed UTF-8 strings.

@stof stof force-pushed the NickWilde1990-strpos-instead-of-preg branch from 9ff7e8d to b733579 Compare January 7, 2018 12:09
@stof stof merged commit 04ab7af into minkphp:master Jan 7, 2018
@stof
Copy link
Member

stof commented Jan 7, 2018

thanks @NickWilde1990

@ghost
Copy link

ghost commented Feb 28, 2018

Previously, if the $text is object, it was cast to the string:
$regex = '/'.preg_quote($text, '/').'/ui';

Now it casting to the int by doc:
$this->assert(strpos($actual, $text) !== FALSE, $message);

The result is an implicit regression with error like:

Object of class MySuperString could not be converted to int

Yes, the use of non-string types is contrary to the annotation of these methods. But it's very convenient when they have a suitable __string.

@aik099
Copy link
Member

aik099 commented Feb 28, 2018

@vaplas , if the behavior isn't documented and it's just happens to work in unexpected way, to technically we're not breaking anything with this change.

Also you have 50%/50% chance of same Fatal Error, because not every object has __toString method.

@aik099
Copy link
Member

aik099 commented Feb 28, 2018

Now it casting to the int by doc:

Not true. 1st and 2nd parameter of stripos or strpos are strings as well.

@ghost
Copy link

ghost commented Feb 28, 2018

@aik099, thanks for the very quick feedback!

responseContains()/ResponseNotContains() have string $text type in annotations. So every objects must have the ability to string casting.

From strpos/stripos docs, 2nd parameter:

needle
If needle is not a string, it is converted to an integer and applied as the ordinal value of a character.

I fully agree with you that undocumented behavior should not be supported by strict backward compatibility policies.

I just wanted to explicitly point out this change, because in many cases, when working with methods responseContains()/ResponseNotContains(), string type on steroids can be used (for more convenient formatting, translations, etc.)

Although, of course, everyone can just wrap a WebAssert class. Or manually casting all the cases. But pure use (albeit undocumented) suffers.

@aik099
Copy link
Member

aik099 commented Feb 28, 2018

needle
If needle is not a string, it is converted to an integer and applied as the ordinal value of a character.

Ha-ha. That must be an easter egg in PHP.

I just wanted to explicitly point out this change, because in many cases, when working with methods responseContains()/ResponseNotContains(), string type on steroids can be used (for more convenient formatting, translations, etc.)

Then your comment would guide other library users in right direction in case if they'll have that fatal error. Thank you.

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

Successfully merging this pull request may close these issues.

3 participants