26
26
use Codeception \Test \Interfaces \ScenarioDriven ;
27
27
use Codeception \TestInterface ;
28
28
use Codeception \Util \ActionSequence ;
29
- use Codeception \Util \Debug ;
30
29
use Codeception \Util \Locator ;
31
30
use Codeception \Util \Uri ;
32
31
use Facebook \WebDriver \Cookie ;
47
46
use Facebook \WebDriver \WebDriverExpectedCondition ;
48
47
use Facebook \WebDriver \WebDriverKeys ;
49
48
use Facebook \WebDriver \WebDriverSelect ;
50
- use GuzzleHttp \Cookie \SetCookie ;
51
- use Symfony \Component \DomCrawler \Crawler ;
52
49
53
50
/**
54
51
* New generation Selenium WebDriver module.
@@ -310,7 +307,7 @@ class WebDriver extends CodeceptionModule implements
310
307
'http_proxy_port ' => null ,
311
308
'ssl_proxy ' => null ,
312
309
'ssl_proxy_port ' => null ,
313
- 'debug_log_entries ' => 15 ,
310
+ 'debug_log_entries ' => null ,
314
311
'log_js_errors ' => false
315
312
];
316
313
@@ -531,6 +528,11 @@ public function debugWebDriverLogs(TestInterface $test = null)
531
528
$ this ->debug ('WebDriver::debugWebDriverLogs method has been called when webDriver is not set ' );
532
529
return ;
533
530
}
531
+ // don't show logs if log entries not set
532
+ if (!$ this ->config ['debug_log_entries ' ]) {
533
+ return ;
534
+ }
535
+
534
536
try {
535
537
// Dump out latest Selenium logs
536
538
$ logs = $ this ->webDriver ->manage ()->getAvailableLogTypes ();
@@ -1031,7 +1033,7 @@ public function _findClickable($page, $link)
1031
1033
return $ this ->matchFirstOrFail ($ page , $ link );
1032
1034
}
1033
1035
1034
- $ locator = Crawler ::xpathLiteral (trim ($ link ));
1036
+ $ locator = static ::xpathLiteral (trim ($ link ));
1035
1037
1036
1038
// narrow
1037
1039
$ xpath = Locator::combine (
@@ -1083,7 +1085,7 @@ protected function findFields($selector)
1083
1085
return $ fields ;
1084
1086
}
1085
1087
1086
- $ locator = Crawler ::xpathLiteral (trim ($ selector ));
1088
+ $ locator = static ::xpathLiteral (trim ($ selector ));
1087
1089
// by text or label
1088
1090
$ xpath = Locator::combine (
1089
1091
// @codingStandardsIgnoreStart
@@ -1583,14 +1585,14 @@ protected function findCheckable($context, $radioOrCheckbox, $byValue = false)
1583
1585
return $ this ->matchFirstOrFail ($ this ->getBaseElement (), $ radioOrCheckbox );
1584
1586
}
1585
1587
1586
- $ locator = Crawler ::xpathLiteral ($ radioOrCheckbox );
1588
+ $ locator = static ::xpathLiteral ($ radioOrCheckbox );
1587
1589
if ($ context instanceof WebDriverElement && $ context ->getTagName () === 'input ' ) {
1588
1590
$ contextType = $ context ->getAttribute ('type ' );
1589
1591
if (!in_array ($ contextType , ['checkbox ' , 'radio ' ], true )) {
1590
1592
return null ;
1591
1593
}
1592
- $ nameLiteral = Crawler:: xPathLiteral ($ context ->getAttribute ('name ' ));
1593
- $ typeLiteral = Crawler:: xPathLiteral ($ contextType );
1594
+ $ nameLiteral = static :: xpathLiteral ($ context ->getAttribute ('name ' ));
1595
+ $ typeLiteral = static :: xpathLiteral ($ contextType );
1594
1596
$ inputLocatorFragment = "input[@type = $ typeLiteral][@name = $ nameLiteral] " ;
1595
1597
$ xpath = Locator::combine (
1596
1598
// @codingStandardsIgnoreStart
@@ -3134,6 +3136,8 @@ public function deleteSessionSnapshot($name)
3134
3136
/**
3135
3137
* Check if the cookie domain matches the config URL.
3136
3138
*
3139
+ * Taken from Guzzle\Cookie\SetCookie
3140
+ *
3137
3141
* @param array|Cookie $cookie
3138
3142
* @return bool
3139
3143
*/
@@ -3143,10 +3147,21 @@ private function cookieDomainMatchesConfigUrl($cookie)
3143
3147
return true ;
3144
3148
}
3145
3149
3146
- $ setCookie = new SetCookie ();
3147
- $ setCookie ->setDomain ($ cookie ['domain ' ]);
3150
+ $ domain = parse_url ($ this ->config ['url ' ], PHP_URL_HOST );
3148
3151
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 );
3150
3165
}
3151
3166
3152
3167
/**
@@ -3360,4 +3375,48 @@ protected function disableImplicitWait()
3360
3375
}
3361
3376
$ this ->webDriver ->manage ()->timeouts ()->implicitlyWait (0 );
3362
3377
}
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
+
3363
3422
}
0 commit comments