2626use Codeception \Test \Interfaces \ScenarioDriven ;
2727use Codeception \TestInterface ;
2828use Codeception \Util \ActionSequence ;
29- use Codeception \Util \Debug ;
3029use Codeception \Util \Locator ;
3130use Codeception \Util \Uri ;
3231use Facebook \WebDriver \Cookie ;
4746use Facebook \WebDriver \WebDriverExpectedCondition ;
4847use Facebook \WebDriver \WebDriverKeys ;
4948use Facebook \WebDriver \WebDriverSelect ;
50- use GuzzleHttp \Cookie \SetCookie ;
51- use Symfony \Component \DomCrawler \Crawler ;
5249
5350/**
5451 * New generation Selenium WebDriver module.
@@ -310,7 +307,7 @@ class WebDriver extends CodeceptionModule implements
310307 'http_proxy_port ' => null ,
311308 'ssl_proxy ' => null ,
312309 'ssl_proxy_port ' => null ,
313- 'debug_log_entries ' => 15 ,
310+ 'debug_log_entries ' => null ,
314311 'log_js_errors ' => false
315312 ];
316313
@@ -531,6 +528,11 @@ public function debugWebDriverLogs(TestInterface $test = null)
531528 $ this ->debug ('WebDriver::debugWebDriverLogs method has been called when webDriver is not set ' );
532529 return ;
533530 }
531+ // don't show logs if log entries not set
532+ if (!$ this ->config ['debug_log_entries ' ]) {
533+ return ;
534+ }
535+
534536 try {
535537 // Dump out latest Selenium logs
536538 $ logs = $ this ->webDriver ->manage ()->getAvailableLogTypes ();
@@ -1031,7 +1033,7 @@ public function _findClickable($page, $link)
10311033 return $ this ->matchFirstOrFail ($ page , $ link );
10321034 }
10331035
1034- $ locator = Crawler ::xpathLiteral (trim ($ link ));
1036+ $ locator = static ::xpathLiteral (trim ($ link ));
10351037
10361038 // narrow
10371039 $ xpath = Locator::combine (
@@ -1083,7 +1085,7 @@ protected function findFields($selector)
10831085 return $ fields ;
10841086 }
10851087
1086- $ locator = Crawler ::xpathLiteral (trim ($ selector ));
1088+ $ locator = static ::xpathLiteral (trim ($ selector ));
10871089 // by text or label
10881090 $ xpath = Locator::combine (
10891091 // @codingStandardsIgnoreStart
@@ -1583,14 +1585,14 @@ protected function findCheckable($context, $radioOrCheckbox, $byValue = false)
15831585 return $ this ->matchFirstOrFail ($ this ->getBaseElement (), $ radioOrCheckbox );
15841586 }
15851587
1586- $ locator = Crawler ::xpathLiteral ($ radioOrCheckbox );
1588+ $ locator = static ::xpathLiteral ($ radioOrCheckbox );
15871589 if ($ context instanceof WebDriverElement && $ context ->getTagName () === 'input ' ) {
15881590 $ contextType = $ context ->getAttribute ('type ' );
15891591 if (!in_array ($ contextType , ['checkbox ' , 'radio ' ], true )) {
15901592 return null ;
15911593 }
1592- $ nameLiteral = Crawler:: xPathLiteral ($ context ->getAttribute ('name ' ));
1593- $ typeLiteral = Crawler:: xPathLiteral ($ contextType );
1594+ $ nameLiteral = static :: xpathLiteral ($ context ->getAttribute ('name ' ));
1595+ $ typeLiteral = static :: xpathLiteral ($ contextType );
15941596 $ inputLocatorFragment = "input[@type = $ typeLiteral][@name = $ nameLiteral] " ;
15951597 $ xpath = Locator::combine (
15961598 // @codingStandardsIgnoreStart
@@ -3134,6 +3136,8 @@ public function deleteSessionSnapshot($name)
31343136 /**
31353137 * Check if the cookie domain matches the config URL.
31363138 *
3139+ * Taken from Guzzle\Cookie\SetCookie
3140+ *
31373141 * @param array|Cookie $cookie
31383142 * @return bool
31393143 */
@@ -3143,10 +3147,21 @@ private function cookieDomainMatchesConfigUrl($cookie)
31433147 return true ;
31443148 }
31453149
3146- $ setCookie = new SetCookie ();
3147- $ setCookie ->setDomain ($ cookie ['domain ' ]);
3150+ $ domain = parse_url ($ this ->config ['url ' ], PHP_URL_HOST );
31483151
3149- return $ setCookie ->matchesDomain (parse_url ($ this ->config ['url ' ], PHP_URL_HOST ));
3152+ // Remove the leading '.' as per spec in RFC 6265.
3153+ // http://tools.ietf.org/html/rfc6265#section-5.2.3
3154+ $ cookieDomain = ltrim ($ cookie ['domain ' ], '. ' );
3155+ // Domain not set or exact match.
3156+ if (!$ cookieDomain || !strcasecmp ($ domain , $ cookieDomain )) {
3157+ return true ;
3158+ }
3159+ // Matching the subdomain according to RFC 6265.
3160+ // http://tools.ietf.org/html/rfc6265#section-5.1.3
3161+ if (filter_var ($ domain , FILTER_VALIDATE_IP )) {
3162+ return false ;
3163+ }
3164+ return (bool ) preg_match ('/\. ' . preg_quote ($ cookieDomain , '/ ' ) . '$/ ' , $ domain );
31503165 }
31513166
31523167 /**
@@ -3360,4 +3375,48 @@ protected function disableImplicitWait()
33603375 }
33613376 $ this ->webDriver ->manage ()->timeouts ()->implicitlyWait (0 );
33623377 }
3378+
3379+ /**
3380+ * From symfony/dom-crawler
3381+ *
3382+ * Converts string for XPath expressions.
3383+ *
3384+ * Escaped characters are: quotes (") and apostrophe (').
3385+ *
3386+ * Examples:
3387+ *
3388+ * echo static::xpathLiteral('foo " bar');
3389+ * //prints 'foo " bar'
3390+ *
3391+ * echo static::xpathLiteral("foo ' bar");
3392+ * //prints "foo ' bar"
3393+ *
3394+ * echo static::xpathLiteral('a\'b"c');
3395+ * //prints concat('a', "'", 'b"c')
3396+ *
3397+ * @return string Converted string
3398+ */
3399+ private static function xpathLiteral (string $ s )
3400+ {
3401+ if (false === strpos ($ s , "' " )) {
3402+ return sprintf ("'%s' " , $ s );
3403+ }
3404+ if (false === strpos ($ s , '" ' )) {
3405+ return sprintf ('"%s" ' , $ s );
3406+ }
3407+ $ string = $ s ;
3408+ $ parts = [];
3409+ while (true ) {
3410+ if (false !== $ pos = strpos ($ string , "' " )) {
3411+ $ parts [] = sprintf ("'%s' " , substr ($ string , 0 , $ pos ));
3412+ $ parts [] = "\"' \"" ;
3413+ $ string = substr ($ string , $ pos + 1 );
3414+ } else {
3415+ $ parts [] = "' $ string' " ;
3416+ break ;
3417+ }
3418+ }
3419+ return sprintf ('concat(%s) ' , implode (', ' , $ parts ));
3420+ }
3421+
33633422}
0 commit comments