web/lib/Zend/Test/PHPUnit/Constraint/DomQuery37.php
changeset 1230 68c69c656a2c
equal deleted inserted replaced
1229:5a6b6e770365 1230:68c69c656a2c
       
     1 <?php
       
     2 /**
       
     3  * Zend Framework
       
     4  *
       
     5  * LICENSE
       
     6  *
       
     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.
       
    14  *
       
    15  * @category   Zend
       
    16  * @package    Zend_Test
       
    17  * @subpackage PHPUnit
       
    18  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
       
    19  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    20  * @version    $Id$
       
    21  */
       
    22 
       
    23 /** @see Zend_Dom_Query */
       
    24 require_once 'Zend/Dom/Query.php';
       
    25 
       
    26 /**
       
    27  * Zend_Dom_Query-based PHPUnit Constraint
       
    28  *
       
    29  * @uses       PHPUnit_Framework_Constraint
       
    30  * @category   Zend
       
    31  * @package    Zend_Test
       
    32  * @subpackage PHPUnit
       
    33  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
       
    34  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    35  */
       
    36 class Zend_Test_PHPUnit_Constraint_DomQuery37 extends PHPUnit_Framework_Constraint
       
    37 {
       
    38     /**#@+
       
    39      * Assertion type constants
       
    40      */
       
    41     const ASSERT_QUERY            = 'assertQuery';
       
    42     const ASSERT_CONTENT_CONTAINS = 'assertQueryContentContains';
       
    43     const ASSERT_CONTENT_REGEX    = 'assertQueryContentRegex';
       
    44     const ASSERT_CONTENT_COUNT    = 'assertQueryCount';
       
    45     const ASSERT_CONTENT_COUNT_MIN= 'assertQueryCountMin';
       
    46     const ASSERT_CONTENT_COUNT_MAX= 'assertQueryCountMax';
       
    47     /**#@-*/
       
    48 
       
    49     /**
       
    50      * Current assertion type
       
    51      * @var string
       
    52      */
       
    53     protected $_assertType        = null;
       
    54 
       
    55     /**
       
    56      * Available assertion types
       
    57      * @var array
       
    58      */
       
    59     protected $_assertTypes       = array(
       
    60         self::ASSERT_QUERY,
       
    61         self::ASSERT_CONTENT_CONTAINS,
       
    62         self::ASSERT_CONTENT_REGEX,
       
    63         self::ASSERT_CONTENT_COUNT,
       
    64         self::ASSERT_CONTENT_COUNT_MIN,
       
    65         self::ASSERT_CONTENT_COUNT_MAX,
       
    66     );
       
    67 
       
    68     /**
       
    69      * Content being matched
       
    70      * @var string
       
    71      */
       
    72     protected $_content           = null;
       
    73 
       
    74     /**
       
    75      * Whether or not assertion is negated
       
    76      * @var bool
       
    77      */
       
    78     protected $_negate            = false;
       
    79 
       
    80     /**
       
    81      * CSS selector or XPath path to select against
       
    82      * @var string
       
    83      */
       
    84     protected $_path              = null;
       
    85 
       
    86     /**
       
    87      * Whether or not to use XPath when querying
       
    88      * @var bool
       
    89      */
       
    90     protected $_useXpath          = false;
       
    91 
       
    92     /**
       
    93      * XPath namespaces
       
    94      * @var array
       
    95      */
       
    96     protected $_xpathNamespaces = array();
       
    97 
       
    98     /**
       
    99      * Constructor; setup constraint state
       
   100      *
       
   101      * @param  string $path CSS selector path
       
   102      * @return void
       
   103      */
       
   104     public function __construct($path)
       
   105     {
       
   106         $this->_path = $path;
       
   107     }
       
   108 
       
   109     /**
       
   110      * Indicate negative match
       
   111      *
       
   112      * @param  bool $flag
       
   113      * @return void
       
   114      */
       
   115     public function setNegate($flag = true)
       
   116     {
       
   117         $this->_negate = $flag;
       
   118     }
       
   119 
       
   120     /**
       
   121      * Whether or not path is a straight XPath expression
       
   122      *
       
   123      * @param  bool $flag
       
   124      * @return Zend_Test_PHPUnit_Constraint_DomQuery
       
   125      */
       
   126     public function setUseXpath($flag = true)
       
   127     {
       
   128         $this->_useXpath = (bool) $flag;
       
   129         return $this;
       
   130     }
       
   131 
       
   132     /**
       
   133      * Evaluate an object to see if it fits the constraints
       
   134      *
       
   135      * @param  string       Response content to be matched against (haystack)
       
   136      * @param  null|string  Assertion type
       
   137      * @param  string       (optional) String to match (needle), may be required depending on assertion type
       
   138      * @return bool
       
   139      * 
       
   140      * NOTE:
       
   141      * Drastic changes up to PHPUnit 3.5.15 this was:
       
   142      *     public function evaluate($other, $assertType = null)
       
   143      * In PHPUnit 3.6.0 they changed the interface into this:
       
   144      *     public function evaluate($other, $description = '', $returnResult = FALSE)
       
   145      * We use the new interface for PHP-strict checking, but emulate the old one
       
   146      */
       
   147     public function evaluate($content, $assertType = '', $match = FALSE)
       
   148     {
       
   149         if (strstr($assertType, 'Not')) {
       
   150             $this->setNegate(true);
       
   151             $assertType = str_replace('Not', '', $assertType);
       
   152         }
       
   153 
       
   154         if (strstr($assertType, 'Xpath')) {
       
   155             $this->setUseXpath(true);
       
   156             $assertType = str_replace('Xpath', 'Query', $assertType);
       
   157         }
       
   158 
       
   159         if (!in_array($assertType, $this->_assertTypes)) {
       
   160             require_once 'Zend/Test/PHPUnit/Constraint/Exception.php';
       
   161             throw new Zend_Test_PHPUnit_Constraint_Exception(sprintf('Invalid assertion type "%s" provided to %s constraint', $assertType, __CLASS__));
       
   162         }
       
   163 
       
   164         $this->_assertType = $assertType;
       
   165 
       
   166         $method   = $this->_useXpath ? 'queryXpath' : 'query';
       
   167         $domQuery = new Zend_Dom_Query($content);
       
   168         $domQuery->registerXpathNamespaces($this->_xpathNamespaces);
       
   169         $result   = $domQuery->$method($this->_path);
       
   170 
       
   171         switch ($assertType) {
       
   172             case self::ASSERT_CONTENT_CONTAINS:
       
   173                 if (!$match) {
       
   174                     require_once 'Zend/Test/PHPUnit/Constraint/Exception.php';
       
   175                     throw new Zend_Test_PHPUnit_Constraint_Exception('No content provided against which to match');
       
   176                 }
       
   177                 $this->_content = $match;
       
   178                 return ($this->_negate)
       
   179                     ? $this->_notMatchContent($result, $match)
       
   180                     : $this->_matchContent($result, $match);
       
   181             case self::ASSERT_CONTENT_REGEX:
       
   182                 if (!$match) {
       
   183                     require_once 'Zend/Test/PHPUnit/Constraint/Exception.php';
       
   184                     throw new Zend_Test_PHPUnit_Constraint_Exception('No pattern provided against which to match');
       
   185                 }
       
   186                 $this->_content = $match;
       
   187                 return ($this->_negate)
       
   188                     ? $this->_notRegexContent($result, $match)
       
   189                     : $this->_regexContent($result, $match);
       
   190             case self::ASSERT_CONTENT_COUNT:
       
   191             case self::ASSERT_CONTENT_COUNT_MIN:
       
   192             case self::ASSERT_CONTENT_COUNT_MAX:
       
   193                 if ($match === false) {
       
   194                     require_once 'Zend/Test/PHPUnit/Constraint/Exception.php';
       
   195                     throw new Zend_Test_PHPUnit_Constraint_Exception('No count provided against which to compare');
       
   196                 }
       
   197                 $this->_content = $match;
       
   198                 return $this->_countContent($result, $match, $assertType);
       
   199             case self::ASSERT_QUERY:
       
   200             default:
       
   201                 if ($this->_negate) {
       
   202                     return (0 == count($result));
       
   203                 } else {
       
   204                     return (0 != count($result));
       
   205                 }
       
   206         }
       
   207     }
       
   208 
       
   209     /**
       
   210      * Report Failure
       
   211      *
       
   212      * @see    PHPUnit_Framework_Constraint for implementation details
       
   213      * @param  mixed    CSS selector path
       
   214      * @param  string   Failure description
       
   215      * @param  object   Cannot be used, null
       
   216      * @return void
       
   217      * @throws PHPUnit_Framework_ExpectationFailedException
       
   218      * NOTE:
       
   219      * Drastic changes up to PHPUnit 3.5.15 this was:
       
   220      *     public function fail($other, $description, $not = false)
       
   221      * In PHPUnit 3.6.0 they changed the interface into this:
       
   222      *     protected function fail($other, $description, PHPUnit_Framework_ComparisonFailure $comparisonFailure = NULL)
       
   223      * We use the new interface for PHP-strict checking
       
   224      */
       
   225     public function fail($other, $description, PHPUnit_Framework_ComparisonFailure $cannot_be_used = NULL)
       
   226     {
       
   227         require_once 'Zend/Test/PHPUnit/Constraint/Exception.php';
       
   228         switch ($this->_assertType) {
       
   229             case self::ASSERT_CONTENT_CONTAINS:
       
   230                 $failure = 'Failed asserting node denoted by %s CONTAINS content "%s"';
       
   231                 if ($this->_negate) {
       
   232                     $failure = 'Failed asserting node DENOTED BY %s DOES NOT CONTAIN content "%s"';
       
   233                 }
       
   234                 $failure = sprintf($failure, $other, $this->_content);
       
   235                 break;
       
   236             case self::ASSERT_CONTENT_REGEX:
       
   237                 $failure = 'Failed asserting node denoted by %s CONTAINS content MATCHING "%s"';
       
   238                 if ($this->_negate) {
       
   239                     $failure = 'Failed asserting node DENOTED BY %s DOES NOT CONTAIN content MATCHING "%s"';
       
   240                 }
       
   241                 $failure = sprintf($failure, $other, $this->_content);
       
   242                 break;
       
   243             case self::ASSERT_CONTENT_COUNT:
       
   244                 $failure = 'Failed asserting node DENOTED BY %s OCCURS EXACTLY %d times';
       
   245                 if ($this->_negate) {
       
   246                     $failure = 'Failed asserting node DENOTED BY %s DOES NOT OCCUR EXACTLY %d times';
       
   247                 }
       
   248                 $failure = sprintf($failure, $other, $this->_content);
       
   249                 break;
       
   250             case self::ASSERT_CONTENT_COUNT_MIN:
       
   251                 $failure = 'Failed asserting node DENOTED BY %s OCCURS AT LEAST %d times';
       
   252                 $failure = sprintf($failure, $other, $this->_content);
       
   253                 break;
       
   254             case self::ASSERT_CONTENT_COUNT_MAX:
       
   255                 $failure = 'Failed asserting node DENOTED BY %s OCCURS AT MOST %d times';
       
   256                 $failure = sprintf($failure, $other, $this->_content);
       
   257                 break;
       
   258             case self::ASSERT_QUERY:
       
   259             default:
       
   260                 $failure = 'Failed asserting node DENOTED BY %s EXISTS';
       
   261                 if ($this->_negate) {
       
   262                     $failure = 'Failed asserting node DENOTED BY %s DOES NOT EXIST';
       
   263                 }
       
   264                 $failure = sprintf($failure, $other);
       
   265                 break;
       
   266         }
       
   267 
       
   268         if (!empty($description)) {
       
   269             $failure = $description . "\n" . $failure;
       
   270         }
       
   271 
       
   272         throw new Zend_Test_PHPUnit_Constraint_Exception($failure);
       
   273     }
       
   274 
       
   275     /**
       
   276      * Complete implementation
       
   277      *
       
   278      * @return string
       
   279      */
       
   280     public function toString()
       
   281     {
       
   282         return '';
       
   283     }
       
   284 
       
   285     /**
       
   286      * Register XPath namespaces
       
   287      *
       
   288      * @param   array $xpathNamespaces
       
   289      * @return  void
       
   290      */
       
   291     public function registerXpathNamespaces($xpathNamespaces)
       
   292     {
       
   293         $this->_xpathNamespaces = $xpathNamespaces;
       
   294     }
       
   295 
       
   296     /**
       
   297      * Check to see if content is matched in selected nodes
       
   298      *
       
   299      * @param  Zend_Dom_Query_Result $result
       
   300      * @param  string $match Content to match
       
   301      * @return bool
       
   302      */
       
   303     protected function _matchContent($result, $match)
       
   304     {
       
   305         $match = (string) $match;
       
   306 
       
   307         if (0 == count($result)) {
       
   308             return false;
       
   309         }
       
   310 
       
   311         foreach ($result as $node) {
       
   312             $content = $this->_getNodeContent($node);
       
   313             if (strstr($content, $match)) {
       
   314                 return true;
       
   315             }
       
   316         }
       
   317 
       
   318         return false;
       
   319     }
       
   320 
       
   321     /**
       
   322      * Check to see if content is NOT matched in selected nodes
       
   323      *
       
   324      * @param  Zend_Dom_Query_Result $result
       
   325      * @param  string $match
       
   326      * @return bool
       
   327      */
       
   328     protected function _notMatchContent($result, $match)
       
   329     {
       
   330         if (0 == count($result)) {
       
   331             return true;
       
   332         }
       
   333 
       
   334         foreach ($result as $node) {
       
   335             $content = $this->_getNodeContent($node);
       
   336             if (strstr($content, $match)) {
       
   337                 return false;
       
   338             }
       
   339         }
       
   340 
       
   341         return true;
       
   342     }
       
   343 
       
   344     /**
       
   345      * Check to see if content is matched by regex in selected nodes
       
   346      *
       
   347      * @param  Zend_Dom_Query_Result $result
       
   348      * @param  string $pattern
       
   349      * @return bool
       
   350      */
       
   351     protected function _regexContent($result, $pattern)
       
   352     {
       
   353         if (0 == count($result)) {
       
   354             return false;
       
   355         }
       
   356 
       
   357         foreach ($result as $node) {
       
   358             $content = $this->_getNodeContent($node);
       
   359             if (preg_match($pattern, $content)) {
       
   360                 return true;
       
   361             }
       
   362         }
       
   363 
       
   364         return false;
       
   365     }
       
   366 
       
   367     /**
       
   368      * Check to see if content is NOT matched by regex in selected nodes
       
   369      *
       
   370      * @param  Zend_Dom_Query_Result $result
       
   371      * @param  string $pattern
       
   372      * @return bool
       
   373      */
       
   374     protected function _notRegexContent($result, $pattern)
       
   375     {
       
   376         if (0 == count($result)) {
       
   377             return true;
       
   378         }
       
   379 
       
   380         foreach ($result as $node) {
       
   381             $content = $this->_getNodeContent($node);
       
   382             if (preg_match($pattern, $content)) {
       
   383                 return false;
       
   384             }
       
   385         }
       
   386 
       
   387         return true;
       
   388     }
       
   389 
       
   390     /**
       
   391      * Determine if content count matches criteria
       
   392      *
       
   393      * @param  Zend_Dom_Query_Result $result
       
   394      * @param  int $test Value against which to test
       
   395      * @param  string $type assertion type
       
   396      * @return boolean
       
   397      */
       
   398     protected function _countContent($result, $test, $type)
       
   399     {
       
   400         $count = count($result);
       
   401 
       
   402         switch ($type) {
       
   403             case self::ASSERT_CONTENT_COUNT:
       
   404                 return ($this->_negate)
       
   405                     ? ($test != $count)
       
   406                     : ($test == $count);
       
   407             case self::ASSERT_CONTENT_COUNT_MIN:
       
   408                 return ($count >= $test);
       
   409             case self::ASSERT_CONTENT_COUNT_MAX:
       
   410                 return ($count <= $test);
       
   411             default:
       
   412                 return false;
       
   413         }
       
   414     }
       
   415 
       
   416     /**
       
   417      * Get node content, minus node markup tags
       
   418      *
       
   419      * @param  DOMNode $node
       
   420      * @return string
       
   421      */
       
   422     protected function _getNodeContent(DOMNode $node)
       
   423     {
       
   424         if ($node instanceof DOMAttr) {
       
   425             return $node->value;
       
   426         } else {
       
   427             $doc     = $node->ownerDocument;
       
   428             $content = $doc->saveXML($node);
       
   429             $tag     = $node->nodeName;
       
   430             $regex   = '|</?' . $tag . '[^>]*>|';
       
   431             return preg_replace($regex, '', $content);
       
   432         }
       
   433     }
       
   434 }