7 * This source file is subject to the new BSD license that is bundled
8 * with this package in the file LICENSE.txt.
9 * It is also available through the world-wide-web at this URL:
10 * http://framework.zend.com/license/new-bsd
11 * If you did not receive a copy of the license and are unable to
12 * obtain it through the world-wide-web, please send an email
13 * to license@zend.com so we can send you a copy immediately.
17 * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
18 * @license http://framework.zend.com/license/new-bsd New BSD License
19 * @version $Id: DomQuery.php 16874 2009-07-20 12:46:00Z mikaelkael $
22 /** PHPUnit_Framework_Constraint */
23 require_once 'PHPUnit/Framework/Constraint.php';
26 require_once 'Zend/Dom/Query.php';
29 * Zend_Dom_Query-based PHPUnit Constraint
31 * @uses PHPUnit_Framework_Constraint
34 * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
35 * @license http://framework.zend.com/license/new-bsd New BSD License
37 class Zend_Test_PHPUnit_Constraint_DomQuery
extends PHPUnit_Framework_Constraint
40 * @const string Assertion type constants
42 const ASSERT_QUERY
= 'assertQuery';
43 const ASSERT_CONTENT_CONTAINS
= 'assertQueryContentContains';
44 const ASSERT_CONTENT_REGEX
= 'assertQueryContentRegex';
45 const ASSERT_CONTENT_COUNT
= 'assertQueryCount';
46 const ASSERT_CONTENT_COUNT_MIN
= 'assertQueryCountMin';
47 const ASSERT_CONTENT_COUNT_MAX
= 'assertQueryCountMax';
51 * Current assertion type
54 protected $_assertType = null;
57 * Available assertion types
60 protected $_assertTypes = array(
62 self
::ASSERT_CONTENT_CONTAINS
,
63 self
::ASSERT_CONTENT_REGEX
,
64 self
::ASSERT_CONTENT_COUNT
,
65 self
::ASSERT_CONTENT_COUNT_MIN
,
66 self
::ASSERT_CONTENT_COUNT_MAX
,
70 * Content being matched
73 protected $_content = null;
76 * Whether or not assertion is negated
79 protected $_negate = false;
82 * CSS selector or XPath path to select against
85 protected $_path = null;
88 * Whether or not to use XPath when querying
91 protected $_useXpath = false;
94 * Constructor; setup constraint state
96 * @param string $path CSS selector path
99 public function __construct($path)
101 $this->_path
= $path;
105 * Indicate negative match
110 public function setNegate($flag = true)
112 $this->_negate
= $flag;
116 * Whether or not path is a straight XPath expression
119 * @return Zend_Test_PHPUnit_Constraint_DomQuery
121 public function setUseXpath($flag = true)
123 $this->_useXpath
= (bool) $flag;
128 * Evaluate an object to see if it fits the constraints
130 * @param string $other String to examine
131 * @param null|string Assertion type
134 public function evaluate($other, $assertType = null)
136 if (strstr($assertType, 'Not')) {
137 $this->setNegate(true);
138 $assertType = str_replace('Not', '', $assertType);
141 if (strstr($assertType, 'Xpath')) {
142 $this->setUseXpath(true);
143 $assertType = str_replace('Xpath', 'Query', $assertType);
146 if (!in_array($assertType, $this->_assertTypes
)) {
147 require_once 'Zend/Test/PHPUnit/Constraint/Exception.php';
148 throw new Zend_Test_PHPUnit_Constraint_Exception(sprintf('Invalid assertion type "%s" provided to %s constraint', $assertType, __CLASS__
));
151 $this->_assertType
= $assertType;
153 $method = $this->_useXpath ?
'queryXpath' : 'query';
154 $domQuery = new Zend_Dom_Query($other);
155 $result = $domQuery->$method($this->_path
);
156 $argv = func_get_args();
157 $argc = func_num_args();
159 switch ($assertType) {
160 case self
::ASSERT_CONTENT_CONTAINS
:
162 require_once 'Zend/Test/PHPUnit/Constraint/Exception.php';
163 throw new Zend_Test_PHPUnit_Constraint_Exception('No content provided against which to match');
165 $this->_content
= $content = $argv[2];
166 return ($this->_negate
)
167 ?
$this->_notMatchContent($result, $content)
168 : $this->_matchContent($result, $content);
169 case self
::ASSERT_CONTENT_REGEX
:
171 require_once 'Zend/Test/PHPUnit/Constraint/Exception.php';
172 throw new Zend_Test_PHPUnit_Constraint_Exception('No pattern provided against which to match');
174 $this->_content
= $content = $argv[2];
175 return ($this->_negate
)
176 ?
$this->_notRegexContent($result, $content)
177 : $this->_regexContent($result, $content);
178 case self
::ASSERT_CONTENT_COUNT
:
179 case self
::ASSERT_CONTENT_COUNT_MIN
:
180 case self
::ASSERT_CONTENT_COUNT_MAX
:
182 require_once 'Zend/Test/PHPUnit/Constraint/Exception.php';
183 throw new Zend_Test_PHPUnit_Constraint_Exception('No count provided against which to compare');
185 $this->_content
= $content = $argv[2];
186 return $this->_countContent($result, $content, $assertType);
187 case self
::ASSERT_QUERY
:
189 if ($this->_negate
) {
190 return (0 == count($result));
192 return (0 != count($result));
200 * @see PHPUnit_Framework_Constraint for implementation details
201 * @param mixed $other CSS selector path
202 * @param string $description
205 * @throws PHPUnit_Framework_ExpectationFailedException
207 public function fail($other, $description, $not = false)
209 require_once 'Zend/Test/PHPUnit/Constraint/Exception.php';
210 switch ($this->_assertType
) {
211 case self
::ASSERT_CONTENT_CONTAINS
:
212 $failure = 'Failed asserting node denoted by %s CONTAINS content "%s"';
213 if ($this->_negate
) {
214 $failure = 'Failed asserting node DENOTED BY %s DOES NOT CONTAIN content "%s"';
216 $failure = sprintf($failure, $other, $this->_content
);
218 case self
::ASSERT_CONTENT_REGEX
:
219 $failure = 'Failed asserting node denoted by %s CONTAINS content MATCHING "%s"';
220 if ($this->_negate
) {
221 $failure = 'Failed asserting node DENOTED BY %s DOES NOT CONTAIN content MATCHING "%s"';
223 $failure = sprintf($failure, $other, $this->_content
);
225 case self
::ASSERT_CONTENT_COUNT
:
226 $failure = 'Failed asserting node DENOTED BY %s OCCURS EXACTLY %d times';
227 if ($this->_negate
) {
228 $failure = 'Failed asserting node DENOTED BY %s DOES NOT OCCUR EXACTLY %d times';
230 $failure = sprintf($failure, $other, $this->_content
);
232 case self
::ASSERT_CONTENT_COUNT_MIN
:
233 $failure = 'Failed asserting node DENOTED BY %s OCCURS AT LEAST %d times';
234 $failure = sprintf($failure, $other, $this->_content
);
236 case self
::ASSERT_CONTENT_COUNT_MAX
:
237 $failure = 'Failed asserting node DENOTED BY %s OCCURS AT MOST %d times';
238 $failure = sprintf($failure, $other, $this->_content
);
240 case self
::ASSERT_QUERY
:
242 $failure = 'Failed asserting node DENOTED BY %s EXISTS';
243 if ($this->_negate
) {
244 $failure = 'Failed asserting node DENOTED BY %s DOES NOT EXIST';
246 $failure = sprintf($failure, $other);
250 if (!empty($description)) {
251 $failure = $description . "\n" . $failure;
254 throw new Zend_Test_PHPUnit_Constraint_Exception($failure);
258 * Complete implementation
262 public function toString()
268 * Check to see if content is matched in selected nodes
270 * @param Zend_Dom_Query_Result $result
271 * @param string $match Content to match
274 protected function _matchContent($result, $match)
276 if (0 == count($result)) {
280 foreach ($result as $node) {
281 $content = $this->_getNodeContent($node);
282 if (strstr($content, $match)) {
291 * Check to see if content is NOT matched in selected nodes
293 * @param Zend_Dom_Query_Result $result
294 * @param string $match
297 protected function _notMatchContent($result, $match)
299 if (0 == count($result)) {
303 foreach ($result as $node) {
304 $content = $this->_getNodeContent($node);
305 if (strstr($content, $match)) {
314 * Check to see if content is matched by regex in selected nodes
316 * @param Zend_Dom_Query_Result $result
317 * @param string $pattern
320 protected function _regexContent($result, $pattern)
322 if (0 == count($result)) {
326 foreach ($result as $node) {
327 $content = $this->_getNodeContent($node);
328 if (preg_match($pattern, $content)) {
337 * Check to see if content is NOT matched by regex in selected nodes
339 * @param Zend_Dom_Query_Result $result
340 * @param string $pattern
343 protected function _notRegexContent($result, $pattern)
345 if (0 == count($result)) {
349 foreach ($result as $node) {
350 $content = $this->_getNodeContent($node);
351 if (preg_match($pattern, $content)) {
360 * Determine if content count matches criteria
362 * @param Zend_Dom_Query_Result $result
363 * @param int $test Value against which to test
364 * @param string $type assertion type
367 protected function _countContent($result, $test, $type)
369 $count = count($result);
372 case self
::ASSERT_CONTENT_COUNT
:
373 return ($this->_negate
)
376 case self
::ASSERT_CONTENT_COUNT_MIN
:
377 return ($count >= $test);
378 case self
::ASSERT_CONTENT_COUNT_MAX
:
379 return ($count <= $test);
386 * Get node content, minus node markup tags
388 * @param DOMNode $node
391 protected function _getNodeContent(DOMNode
$node)
393 $doc = $node->ownerDocument
;
394 $content = $doc->saveXML($node);
395 $tag = $node->nodeName
;
396 $regex = '|</?' . $tag . '[^>]*>|';
397 return preg_replace($regex, '', $content);