File indexing completed on 2024-12-29 05:28:07
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Test 0017 * @subpackage PHPUnit 0018 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @license http://framework.zend.com/license/new-bsd New BSD License 0020 * @version $Id$ 0021 */ 0022 0023 /** @see Zend_Dom_Query */ 0024 // require_once 'Zend/Dom/Query.php'; 0025 0026 /** 0027 * Zend_Dom_Query-based PHPUnit Constraint 0028 * 0029 * @uses PHPUnit_Framework_Constraint 0030 * @category Zend 0031 * @package Zend_Test 0032 * @subpackage PHPUnit 0033 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0034 * @license http://framework.zend.com/license/new-bsd New BSD License 0035 */ 0036 class Zend_Test_PHPUnit_Constraint_DomQuery41 extends PHPUnit_Framework_Constraint 0037 { 0038 /**#@+ 0039 * Assertion type constants 0040 */ 0041 const ASSERT_QUERY = 'assertQuery'; 0042 const ASSERT_CONTENT_CONTAINS = 'assertQueryContentContains'; 0043 const ASSERT_CONTENT_REGEX = 'assertQueryContentRegex'; 0044 const ASSERT_CONTENT_COUNT = 'assertQueryCount'; 0045 const ASSERT_CONTENT_COUNT_MIN= 'assertQueryCountMin'; 0046 const ASSERT_CONTENT_COUNT_MAX= 'assertQueryCountMax'; 0047 /**#@-*/ 0048 0049 /** 0050 * Current assertion type 0051 * @var string 0052 */ 0053 protected $_assertType = null; 0054 0055 /** 0056 * Available assertion types 0057 * @var array 0058 */ 0059 protected $_assertTypes = array( 0060 self::ASSERT_QUERY, 0061 self::ASSERT_CONTENT_CONTAINS, 0062 self::ASSERT_CONTENT_REGEX, 0063 self::ASSERT_CONTENT_COUNT, 0064 self::ASSERT_CONTENT_COUNT_MIN, 0065 self::ASSERT_CONTENT_COUNT_MAX, 0066 ); 0067 0068 /** 0069 * Content being matched 0070 * @var string 0071 */ 0072 protected $_content = null; 0073 0074 /** 0075 * Whether or not assertion is negated 0076 * @var bool 0077 */ 0078 protected $_negate = false; 0079 0080 /** 0081 * CSS selector or XPath path to select against 0082 * @var string 0083 */ 0084 protected $_path = null; 0085 0086 /** 0087 * Whether or not to use XPath when querying 0088 * @var bool 0089 */ 0090 protected $_useXpath = false; 0091 0092 /** 0093 * XPath namespaces 0094 * @var array 0095 */ 0096 protected $_xpathNamespaces = array(); 0097 0098 /** 0099 * Constructor; setup constraint state 0100 * 0101 * @param string $path CSS selector path 0102 * @return void 0103 */ 0104 public function __construct($path) 0105 { 0106 $this->_path = $path; 0107 } 0108 0109 /** 0110 * Indicate negative match 0111 * 0112 * @param bool $flag 0113 * @return void 0114 */ 0115 public function setNegate($flag = true) 0116 { 0117 $this->_negate = $flag; 0118 } 0119 0120 /** 0121 * Whether or not path is a straight XPath expression 0122 * 0123 * @param bool $flag 0124 * @return Zend_Test_PHPUnit_Constraint_DomQuery 0125 */ 0126 public function setUseXpath($flag = true) 0127 { 0128 $this->_useXpath = (bool) $flag; 0129 return $this; 0130 } 0131 0132 /** 0133 * Evaluate an object to see if it fits the constraints 0134 * 0135 * @param string Response content to be matched against (haystack) 0136 * @param null|string Assertion type 0137 * @param string (optional) String to match (needle), may be required depending on assertion type 0138 * @return bool 0139 * 0140 * NOTE: 0141 * Drastic changes up to PHPUnit 3.5.15 this was: 0142 * public function evaluate($other, $assertType = null) 0143 * In PHPUnit 3.6.0 they changed the interface into this: 0144 * public function evaluate($other, $description = '', $returnResult = FALSE) 0145 * We use the new interface for PHP-strict checking, but emulate the old one 0146 */ 0147 public function evaluate($content, $assertType = '', $match = FALSE) 0148 { 0149 if (strstr($assertType, 'Not')) { 0150 $this->setNegate(true); 0151 $assertType = str_replace('Not', '', $assertType); 0152 } 0153 0154 if (strstr($assertType, 'Xpath')) { 0155 $this->setUseXpath(true); 0156 $assertType = str_replace('Xpath', 'Query', $assertType); 0157 } 0158 0159 if (!in_array($assertType, $this->_assertTypes)) { 0160 // require_once 'Zend/Test/PHPUnit/Constraint/Exception.php'; 0161 throw new Zend_Test_PHPUnit_Constraint_Exception(sprintf('Invalid assertion type "%s" provided to %s constraint', $assertType, __CLASS__)); 0162 } 0163 0164 $this->_assertType = $assertType; 0165 0166 $method = $this->_useXpath ? 'queryXpath' : 'query'; 0167 $domQuery = new Zend_Dom_Query($content); 0168 $domQuery->registerXpathNamespaces($this->_xpathNamespaces); 0169 $result = $domQuery->$method($this->_path); 0170 0171 switch ($assertType) { 0172 case self::ASSERT_CONTENT_CONTAINS: 0173 if (!$match) { 0174 // require_once 'Zend/Test/PHPUnit/Constraint/Exception.php'; 0175 throw new Zend_Test_PHPUnit_Constraint_Exception('No content provided against which to match'); 0176 } 0177 $this->_content = $match; 0178 return ($this->_negate) 0179 ? $this->_notMatchContent($result, $match) 0180 : $this->_matchContent($result, $match); 0181 case self::ASSERT_CONTENT_REGEX: 0182 if (!$match) { 0183 // require_once 'Zend/Test/PHPUnit/Constraint/Exception.php'; 0184 throw new Zend_Test_PHPUnit_Constraint_Exception('No pattern provided against which to match'); 0185 } 0186 $this->_content = $match; 0187 return ($this->_negate) 0188 ? $this->_notRegexContent($result, $match) 0189 : $this->_regexContent($result, $match); 0190 case self::ASSERT_CONTENT_COUNT: 0191 case self::ASSERT_CONTENT_COUNT_MIN: 0192 case self::ASSERT_CONTENT_COUNT_MAX: 0193 if ($match === false) { 0194 // require_once 'Zend/Test/PHPUnit/Constraint/Exception.php'; 0195 throw new Zend_Test_PHPUnit_Constraint_Exception('No count provided against which to compare'); 0196 } 0197 $this->_content = $match; 0198 return $this->_countContent($result, $match, $assertType); 0199 case self::ASSERT_QUERY: 0200 default: 0201 if ($this->_negate) { 0202 return (0 == count($result)); 0203 } else { 0204 return (0 != count($result)); 0205 } 0206 } 0207 } 0208 0209 /** 0210 * Report Failure 0211 * 0212 * @see PHPUnit_Framework_Constraint for implementation details 0213 * @param mixed CSS selector path 0214 * @param string Failure description 0215 * @param object Cannot be used, null 0216 * @return void 0217 * @throws PHPUnit_Framework_ExpectationFailedException 0218 * NOTE: 0219 * Drastic changes up to PHPUnit 3.5.15 this was: 0220 * public function fail($other, $description, $not = false) 0221 * In PHPUnit 3.6.0 they changed the interface into this: 0222 * protected function fail($other, $description, PHPUnit_Framework_ComparisonFailure $comparisonFailure = NULL) 0223 * We use the new interface for PHP-strict checking 0224 * NOTE 2: 0225 * Interface changed again in PHPUnit 4.1.0 because of refactoring to SebastianBergmann\Comparator 0226 */ 0227 public function fail($other, $description, \SebastianBergmann\Comparator\ComparisonFailure $cannot_be_used = NULL) 0228 { 0229 // require_once 'Zend/Test/PHPUnit/Constraint/Exception.php'; 0230 switch ($this->_assertType) { 0231 case self::ASSERT_CONTENT_CONTAINS: 0232 $failure = 'Failed asserting node denoted by %s CONTAINS content "%s"'; 0233 if ($this->_negate) { 0234 $failure = 'Failed asserting node DENOTED BY %s DOES NOT CONTAIN content "%s"'; 0235 } 0236 $failure = sprintf($failure, $other, $this->_content); 0237 break; 0238 case self::ASSERT_CONTENT_REGEX: 0239 $failure = 'Failed asserting node denoted by %s CONTAINS content MATCHING "%s"'; 0240 if ($this->_negate) { 0241 $failure = 'Failed asserting node DENOTED BY %s DOES NOT CONTAIN content MATCHING "%s"'; 0242 } 0243 $failure = sprintf($failure, $other, $this->_content); 0244 break; 0245 case self::ASSERT_CONTENT_COUNT: 0246 $failure = 'Failed asserting node DENOTED BY %s OCCURS EXACTLY %d times'; 0247 if ($this->_negate) { 0248 $failure = 'Failed asserting node DENOTED BY %s DOES NOT OCCUR EXACTLY %d times'; 0249 } 0250 $failure = sprintf($failure, $other, $this->_content); 0251 break; 0252 case self::ASSERT_CONTENT_COUNT_MIN: 0253 $failure = 'Failed asserting node DENOTED BY %s OCCURS AT LEAST %d times'; 0254 $failure = sprintf($failure, $other, $this->_content); 0255 break; 0256 case self::ASSERT_CONTENT_COUNT_MAX: 0257 $failure = 'Failed asserting node DENOTED BY %s OCCURS AT MOST %d times'; 0258 $failure = sprintf($failure, $other, $this->_content); 0259 break; 0260 case self::ASSERT_QUERY: 0261 default: 0262 $failure = 'Failed asserting node DENOTED BY %s EXISTS'; 0263 if ($this->_negate) { 0264 $failure = 'Failed asserting node DENOTED BY %s DOES NOT EXIST'; 0265 } 0266 $failure = sprintf($failure, $other); 0267 break; 0268 } 0269 0270 if (!empty($description)) { 0271 $failure = $description . "\n" . $failure; 0272 } 0273 0274 throw new Zend_Test_PHPUnit_Constraint_Exception($failure); 0275 } 0276 0277 /** 0278 * Complete implementation 0279 * 0280 * @return string 0281 */ 0282 public function toString() 0283 { 0284 return ''; 0285 } 0286 0287 /** 0288 * Register XPath namespaces 0289 * 0290 * @param array $xpathNamespaces 0291 * @return void 0292 */ 0293 public function registerXpathNamespaces($xpathNamespaces) 0294 { 0295 $this->_xpathNamespaces = $xpathNamespaces; 0296 } 0297 0298 /** 0299 * Check to see if content is matched in selected nodes 0300 * 0301 * @param Zend_Dom_Query_Result $result 0302 * @param string $match Content to match 0303 * @return bool 0304 */ 0305 protected function _matchContent($result, $match) 0306 { 0307 $match = (string) $match; 0308 0309 if (0 == count($result)) { 0310 return false; 0311 } 0312 0313 foreach ($result as $node) { 0314 $content = $this->_getNodeContent($node); 0315 if (strstr($content, $match)) { 0316 return true; 0317 } 0318 } 0319 0320 return false; 0321 } 0322 0323 /** 0324 * Check to see if content is NOT matched in selected nodes 0325 * 0326 * @param Zend_Dom_Query_Result $result 0327 * @param string $match 0328 * @return bool 0329 */ 0330 protected function _notMatchContent($result, $match) 0331 { 0332 if (0 == count($result)) { 0333 return true; 0334 } 0335 0336 foreach ($result as $node) { 0337 $content = $this->_getNodeContent($node); 0338 if (strstr($content, $match)) { 0339 return false; 0340 } 0341 } 0342 0343 return true; 0344 } 0345 0346 /** 0347 * Check to see if content is matched by regex in selected nodes 0348 * 0349 * @param Zend_Dom_Query_Result $result 0350 * @param string $pattern 0351 * @return bool 0352 */ 0353 protected function _regexContent($result, $pattern) 0354 { 0355 if (0 == count($result)) { 0356 return false; 0357 } 0358 0359 foreach ($result as $node) { 0360 $content = $this->_getNodeContent($node); 0361 if (preg_match($pattern, $content)) { 0362 return true; 0363 } 0364 } 0365 0366 return false; 0367 } 0368 0369 /** 0370 * Check to see if content is NOT matched by regex in selected nodes 0371 * 0372 * @param Zend_Dom_Query_Result $result 0373 * @param string $pattern 0374 * @return bool 0375 */ 0376 protected function _notRegexContent($result, $pattern) 0377 { 0378 if (0 == count($result)) { 0379 return true; 0380 } 0381 0382 foreach ($result as $node) { 0383 $content = $this->_getNodeContent($node); 0384 if (preg_match($pattern, $content)) { 0385 return false; 0386 } 0387 } 0388 0389 return true; 0390 } 0391 0392 /** 0393 * Determine if content count matches criteria 0394 * 0395 * @param Zend_Dom_Query_Result $result 0396 * @param int $test Value against which to test 0397 * @param string $type assertion type 0398 * @return boolean 0399 */ 0400 protected function _countContent($result, $test, $type) 0401 { 0402 $count = count($result); 0403 0404 switch ($type) { 0405 case self::ASSERT_CONTENT_COUNT: 0406 return ($this->_negate) 0407 ? ($test != $count) 0408 : ($test == $count); 0409 case self::ASSERT_CONTENT_COUNT_MIN: 0410 return ($count >= $test); 0411 case self::ASSERT_CONTENT_COUNT_MAX: 0412 return ($count <= $test); 0413 default: 0414 return false; 0415 } 0416 } 0417 0418 /** 0419 * Get node content, minus node markup tags 0420 * 0421 * @param DOMNode $node 0422 * @return string 0423 */ 0424 protected function _getNodeContent(DOMNode $node) 0425 { 0426 if ($node instanceof DOMAttr) { 0427 return $node->value; 0428 } else { 0429 $doc = $node->ownerDocument; 0430 $content = $doc->saveXML($node); 0431 $tag = $node->nodeName; 0432 $regex = '|</?' . $tag . '[^>]*>|'; 0433 return preg_replace($regex, '', $content); 0434 } 0435 } 0436 }