File indexing completed on 2024-12-29 05:28:06
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_DomQuery34 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 $other String to examine 0136 * @param null|string Assertion type 0137 * @return bool 0138 */ 0139 public function evaluate($other, $assertType = null) 0140 { 0141 if (strstr($assertType, 'Not')) { 0142 $this->setNegate(true); 0143 $assertType = str_replace('Not', '', $assertType); 0144 } 0145 0146 if (strstr($assertType, 'Xpath')) { 0147 $this->setUseXpath(true); 0148 $assertType = str_replace('Xpath', 'Query', $assertType); 0149 } 0150 0151 if (!in_array($assertType, $this->_assertTypes)) { 0152 // require_once 'Zend/Test/PHPUnit/Constraint/Exception.php'; 0153 throw new Zend_Test_PHPUnit_Constraint_Exception(sprintf('Invalid assertion type "%s" provided to %s constraint', $assertType, __CLASS__)); 0154 } 0155 0156 $this->_assertType = $assertType; 0157 0158 $method = $this->_useXpath ? 'queryXpath' : 'query'; 0159 $domQuery = new Zend_Dom_Query($other); 0160 $domQuery->registerXpathNamespaces($this->_xpathNamespaces); 0161 $result = $domQuery->$method($this->_path); 0162 $argv = func_get_args(); 0163 $argc = func_num_args(); 0164 0165 switch ($assertType) { 0166 case self::ASSERT_CONTENT_CONTAINS: 0167 if (3 > $argc) { 0168 // require_once 'Zend/Test/PHPUnit/Constraint/Exception.php'; 0169 throw new Zend_Test_PHPUnit_Constraint_Exception('No content provided against which to match'); 0170 } 0171 $this->_content = $content = $argv[2]; 0172 return ($this->_negate) 0173 ? $this->_notMatchContent($result, $content) 0174 : $this->_matchContent($result, $content); 0175 case self::ASSERT_CONTENT_REGEX: 0176 if (3 > $argc) { 0177 // require_once 'Zend/Test/PHPUnit/Constraint/Exception.php'; 0178 throw new Zend_Test_PHPUnit_Constraint_Exception('No pattern provided against which to match'); 0179 } 0180 $this->_content = $content = $argv[2]; 0181 return ($this->_negate) 0182 ? $this->_notRegexContent($result, $content) 0183 : $this->_regexContent($result, $content); 0184 case self::ASSERT_CONTENT_COUNT: 0185 case self::ASSERT_CONTENT_COUNT_MIN: 0186 case self::ASSERT_CONTENT_COUNT_MAX: 0187 if (3 > $argc) { 0188 // require_once 'Zend/Test/PHPUnit/Constraint/Exception.php'; 0189 throw new Zend_Test_PHPUnit_Constraint_Exception('No count provided against which to compare'); 0190 } 0191 $this->_content = $content = $argv[2]; 0192 return $this->_countContent($result, $content, $assertType); 0193 case self::ASSERT_QUERY: 0194 default: 0195 if ($this->_negate) { 0196 return (0 == count($result)); 0197 } else { 0198 return (0 != count($result)); 0199 } 0200 } 0201 } 0202 0203 /** 0204 * Report Failure 0205 * 0206 * @see PHPUnit_Framework_Constraint for implementation details 0207 * @param mixed $other CSS selector path 0208 * @param string $description 0209 * @param bool $not 0210 * @return void 0211 * @throws PHPUnit_Framework_ExpectationFailedException 0212 */ 0213 public function fail($other, $description, $not = false) 0214 { 0215 // require_once 'Zend/Test/PHPUnit/Constraint/Exception.php'; 0216 switch ($this->_assertType) { 0217 case self::ASSERT_CONTENT_CONTAINS: 0218 $failure = 'Failed asserting node denoted by %s CONTAINS content "%s"'; 0219 if ($this->_negate) { 0220 $failure = 'Failed asserting node DENOTED BY %s DOES NOT CONTAIN content "%s"'; 0221 } 0222 $failure = sprintf($failure, $other, $this->_content); 0223 break; 0224 case self::ASSERT_CONTENT_REGEX: 0225 $failure = 'Failed asserting node denoted by %s CONTAINS content MATCHING "%s"'; 0226 if ($this->_negate) { 0227 $failure = 'Failed asserting node DENOTED BY %s DOES NOT CONTAIN content MATCHING "%s"'; 0228 } 0229 $failure = sprintf($failure, $other, $this->_content); 0230 break; 0231 case self::ASSERT_CONTENT_COUNT: 0232 $failure = 'Failed asserting node DENOTED BY %s OCCURS EXACTLY %d times'; 0233 if ($this->_negate) { 0234 $failure = 'Failed asserting node DENOTED BY %s DOES NOT OCCUR EXACTLY %d times'; 0235 } 0236 $failure = sprintf($failure, $other, $this->_content); 0237 break; 0238 case self::ASSERT_CONTENT_COUNT_MIN: 0239 $failure = 'Failed asserting node DENOTED BY %s OCCURS AT LEAST %d times'; 0240 $failure = sprintf($failure, $other, $this->_content); 0241 break; 0242 case self::ASSERT_CONTENT_COUNT_MAX: 0243 $failure = 'Failed asserting node DENOTED BY %s OCCURS AT MOST %d times'; 0244 $failure = sprintf($failure, $other, $this->_content); 0245 break; 0246 case self::ASSERT_QUERY: 0247 default: 0248 $failure = 'Failed asserting node DENOTED BY %s EXISTS'; 0249 if ($this->_negate) { 0250 $failure = 'Failed asserting node DENOTED BY %s DOES NOT EXIST'; 0251 } 0252 $failure = sprintf($failure, $other); 0253 break; 0254 } 0255 0256 if (!empty($description)) { 0257 $failure = $description . "\n" . $failure; 0258 } 0259 0260 throw new Zend_Test_PHPUnit_Constraint_Exception($failure); 0261 } 0262 0263 /** 0264 * Complete implementation 0265 * 0266 * @return string 0267 */ 0268 public function toString() 0269 { 0270 return ''; 0271 } 0272 0273 /** 0274 * Register XPath namespaces 0275 * 0276 * @param array $xpathNamespaces 0277 * @return void 0278 */ 0279 public function registerXpathNamespaces($xpathNamespaces) 0280 { 0281 $this->_xpathNamespaces = $xpathNamespaces; 0282 } 0283 0284 /** 0285 * Check to see if content is matched in selected nodes 0286 * 0287 * @param Zend_Dom_Query_Result $result 0288 * @param string $match Content to match 0289 * @return bool 0290 */ 0291 protected function _matchContent($result, $match) 0292 { 0293 $match = (string) $match; 0294 0295 if (0 == count($result)) { 0296 return false; 0297 } 0298 0299 foreach ($result as $node) { 0300 $content = $this->_getNodeContent($node); 0301 if (strstr($content, $match)) { 0302 return true; 0303 } 0304 } 0305 0306 return false; 0307 } 0308 0309 /** 0310 * Check to see if content is NOT matched in selected nodes 0311 * 0312 * @param Zend_Dom_Query_Result $result 0313 * @param string $match 0314 * @return bool 0315 */ 0316 protected function _notMatchContent($result, $match) 0317 { 0318 if (0 == count($result)) { 0319 return true; 0320 } 0321 0322 foreach ($result as $node) { 0323 $content = $this->_getNodeContent($node); 0324 if (strstr($content, $match)) { 0325 return false; 0326 } 0327 } 0328 0329 return true; 0330 } 0331 0332 /** 0333 * Check to see if content is matched by regex in selected nodes 0334 * 0335 * @param Zend_Dom_Query_Result $result 0336 * @param string $pattern 0337 * @return bool 0338 */ 0339 protected function _regexContent($result, $pattern) 0340 { 0341 if (0 == count($result)) { 0342 return false; 0343 } 0344 0345 foreach ($result as $node) { 0346 $content = $this->_getNodeContent($node); 0347 if (preg_match($pattern, $content)) { 0348 return true; 0349 } 0350 } 0351 0352 return false; 0353 } 0354 0355 /** 0356 * Check to see if content is NOT matched by regex in selected nodes 0357 * 0358 * @param Zend_Dom_Query_Result $result 0359 * @param string $pattern 0360 * @return bool 0361 */ 0362 protected function _notRegexContent($result, $pattern) 0363 { 0364 if (0 == count($result)) { 0365 return true; 0366 } 0367 0368 foreach ($result as $node) { 0369 $content = $this->_getNodeContent($node); 0370 if (preg_match($pattern, $content)) { 0371 return false; 0372 } 0373 } 0374 0375 return true; 0376 } 0377 0378 /** 0379 * Determine if content count matches criteria 0380 * 0381 * @param Zend_Dom_Query_Result $result 0382 * @param int $test Value against which to test 0383 * @param string $type assertion type 0384 * @return boolean 0385 */ 0386 protected function _countContent($result, $test, $type) 0387 { 0388 $count = count($result); 0389 0390 switch ($type) { 0391 case self::ASSERT_CONTENT_COUNT: 0392 return ($this->_negate) 0393 ? ($test != $count) 0394 : ($test == $count); 0395 case self::ASSERT_CONTENT_COUNT_MIN: 0396 return ($count >= $test); 0397 case self::ASSERT_CONTENT_COUNT_MAX: 0398 return ($count <= $test); 0399 default: 0400 return false; 0401 } 0402 } 0403 0404 /** 0405 * Get node content, minus node markup tags 0406 * 0407 * @param DOMNode $node 0408 * @return string 0409 */ 0410 protected function _getNodeContent(DOMNode $node) 0411 { 0412 if ($node instanceof DOMAttr) { 0413 return $node->value; 0414 } else { 0415 $doc = $node->ownerDocument; 0416 $content = $doc->saveXML($node); 0417 $tag = $node->nodeName; 0418 $regex = '|</?' . $tag . '[^>]*>|'; 0419 return preg_replace($regex, '', $content); 0420 } 0421 } 0422 }