Modules

abstract Unittest_TestCase
extends Kohana_Unittest_TestCase
extends PHPUnit_Framework_TestCase
extends Kodoc_Missing
extends Kohana_Kodoc_Missing

A version of the stock PHPUnit testcase that includes some extra helpers and default settings[!!] This class, or a class parent, could not be found or loaded. This could be caused by a missing module or other dependancy. The documentation for class may not be complete!

Class declared in MODPATH/unittest/classes/Unittest/TestCase.php on line 3.

Properties

protected Kohana_Unittest_Helpers $_helpers

A set of unittest helpers that are shared between normal / database testcases

Default value:
NULL

protected boolean $backupGlobals

Make sure PHPUnit backs up globals

Default value:
bool FALSE

protected array $environmentDefault

A default set of environment to be applied before each test

Default value:
array(0) 

Methods

public static assertNotTag( array $matcher , string $actual [, string $message = string(0) "" , bool $isHtml = bool TRUE ] ) (defined in Kohana_Unittest_TestCase)

This assertion is the exact opposite of assertTag

Rather than asserting that $matcher results in a match, it asserts that $matcher does not match

TODO: this should be removed when phpunit-dom-assertions gets released https://github.com/phpunit/phpunit-dom-assertions

Parameters

  • array $matcher required - $matcher
  • string $actual required - $actual
  • string $message = string(0) "" - $message
  • bool $isHtml = bool TRUE - $isHtml

Tags

Source Code

public static function assertNotTag($matcher, $actual, $message = '', $isHtml = true)
{
    $dom = PHPUnit_Util_XML::load($actual, $isHtml);
    $tags = static::findNodes($dom, $matcher, $isHtml);
    $matched = count($tags) > 0 && $tags[0] instanceof DOMNode;

    self::assertFalse($matched, $message);
}

public static assertTag( array $matcher , string $actual [, string $message = string(0) "" , bool $isHtml = bool TRUE ] ) (defined in Kohana_Unittest_TestCase)

Evaluate an HTML or XML string and assert its structure and/or contents.

TODO: this should be removed when phpunit-dom-assertions gets released https://github.com/phpunit/phpunit-dom-assertions

Parameters

  • array $matcher required - $matcher
  • string $actual required - $actual
  • string $message = string(0) "" - $message
  • bool $isHtml = bool TRUE - $isHtml

Tags

Source Code

public static function assertTag($matcher, $actual, $message = '', $isHtml = true)
{
    $dom = PHPUnit_Util_XML::load($actual, $isHtml);
    $tags = self::findNodes($dom, $matcher, $isHtml);
    $matched = count($tags) > 0 && $tags[0] instanceof DOMNode;

    self::assertTrue($matched, $message);
}

public static assertValidKeys( array $hash , array $validKeys ) (defined in Kohana_Unittest_TestCase)

Validate list of keys in the associative array.

TODO: This should be removed when phpunit-dom-assertions gets released.

Parameters

  • array $hash required - $hash
  • array $validKeys required - $validKeys

Tags

Return Values

  • array

Source Code

public static function assertValidKeys(array $hash, array $validKeys)
{
    $valids = [];

    // Normalize validation keys so that we can use both indexed and
    // associative arrays.
    foreach ($validKeys as $key => $val) {
        is_int($key) ? $valids[$val] = null : $valids[$key] = $val;
    }

    $validKeys = array_keys($valids);

    // Check for invalid keys.
    foreach ($hash as $key => $value) {
        if (!in_array($key, $validKeys)) {
            $unknown[] = $key;
        }
    }

    if (!empty($unknown)) {
        throw new PHPUnit_Framework_Exception(
        'Unknown key(s): ' . implode(', ', $unknown)
        );
    }

    // Add default values for any valid keys that are empty.
    foreach ($valids as $key => $value) {
        if (!isset($hash[$key])) {
            $hash[$key] = $value;
        }
    }

    return $hash;
}

public cleanCacheDir( ) (defined in Kohana_Unittest_TestCase)

Removes all kohana related cache files in the cache directory

Source Code

public function cleanCacheDir()
{
    return Unittest_Helpers::clean_cache_dir();
}

public dirSeparator( string $path ) (defined in Kohana_Unittest_TestCase)

Helper function that replaces all occurences of '/' with the OS-specific directory separator

Parameters

  • string $path required - The path to act on

Return Values

  • string

Source Code

public function dirSeparator($path)
{
    return Unittest_Helpers::dir_separator($path);
}

public static findNodes( DOMDocument $dom , array $options [, bool $isHtml = bool TRUE ] ) (defined in Kohana_Unittest_TestCase)

Parse out the options from the tag using DOM object tree.

TODO: This should be removed when phpunit-dom-assertions gets released.

Parameters

  • DOMDocument $dom required - $dom
  • array $options required - $options
  • bool $isHtml = bool TRUE - $isHtml

Return Values

  • array

Source Code

public static function findNodes(DOMDocument $dom, array $options, $isHtml = true)
{
    $valid = [
        'id', 'class', 'tag', 'content', 'attributes', 'parent',
        'child', 'ancestor', 'descendant', 'children', 'adjacent-sibling'
    ];

    $filtered = [];
    $options = self::assertValidKeys($options, $valid);

    // find the element by id
    if ($options['id']) {
        $options['attributes']['id'] = $options['id'];
    }

    if ($options['class']) {
        $options['attributes']['class'] = $options['class'];
    }

    $nodes = [];

    // find the element by a tag type
    if ($options['tag']) {
        if ($isHtml) {
            $elements = self::getElementsByCaseInsensitiveTagName(
                    $dom, $options['tag']
            );
        } else {
            $elements = $dom->getElementsByTagName($options['tag']);
        }

        foreach ($elements as $element) {
            $nodes[] = $element;
        }

        if (empty($nodes)) {
            return false;
        }
    } // no tag selected, get them all
    else {
        $tags = [
            'a', 'abbr', 'acronym', 'address', 'area', 'b', 'base', 'bdo',
            'big', 'blockquote', 'body', 'br', 'button', 'caption', 'cite',
            'code', 'col', 'colgroup', 'dd', 'del', 'div', 'dfn', 'dl',
            'dt', 'em', 'fieldset', 'form', 'frame', 'frameset', 'h1', 'h2',
            'h3', 'h4', 'h5', 'h6', 'head', 'hr', 'html', 'i', 'iframe',
            'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'link',
            'map', 'meta', 'noframes', 'noscript', 'object', 'ol', 'optgroup',
            'option', 'p', 'param', 'pre', 'q', 'samp', 'script', 'select',
            'small', 'span', 'strong', 'style', 'sub', 'sup', 'table',
            'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'title',
            'tr', 'tt', 'ul', 'var',
            // HTML5
            'article', 'aside', 'audio', 'bdi', 'canvas', 'command',
            'datalist', 'details', 'dialog', 'embed', 'figure', 'figcaption',
            'footer', 'header', 'hgroup', 'keygen', 'mark', 'meter', 'nav',
            'output', 'progress', 'ruby', 'rt', 'rp', 'track', 'section',
            'source', 'summary', 'time', 'video', 'wbr'
        ];

        foreach ($tags as $tag) {
            if ($isHtml) {
                $elements = self::getElementsByCaseInsensitiveTagName(
                        $dom, $tag
                );
            } else {
                $elements = $dom->getElementsByTagName($tag);
            }

            foreach ($elements as $element) {
                $nodes[] = $element;
            }
        }

        if (empty($nodes)) {
            return false;
        }
    }

    // filter by attributes
    if ($options['attributes']) {
        foreach ($nodes as $node) {
            $invalid = false;

            foreach ($options['attributes'] as $name => $value) {
                // match by regexp if like "regexp:/foo/i"
                if (preg_match('/^regexp\s*:\s*(.*)/i', $value, $matches)) {
                    if (!preg_match($matches[1], $node->getAttribute($name))) {
                        $invalid = true;
                    }
                } // class can match only a part
                elseif ($name == 'class') {
                    // split to individual classes
                    $findClasses = explode(
                        ' ', preg_replace("/\s+/", ' ', $value)
                    );

                    $allClasses = explode(
                        ' ', preg_replace("/\s+/", ' ', $node->getAttribute($name))
                    );

                    // make sure each class given is in the actual node
                    foreach ($findClasses as $findClass) {
                        if (!in_array($findClass, $allClasses)) {
                            $invalid = true;
                        }
                    }
                } // match by exact string
                else {
                    if ($node->getAttribute($name) != $value) {
                        $invalid = true;
                    }
                }
            }

            // if every attribute given matched
            if (!$invalid) {
                $filtered[] = $node;
            }
        }

        $nodes = $filtered;
        $filtered = [];

        if (empty($nodes)) {
            return false;
        }
    }

    // filter by content
    if ($options['content'] !== null) {
        foreach ($nodes as $node) {
            $invalid = false;

            // match by regexp if like "regexp:/foo/i"
            if (preg_match('/^regexp\s*:\s*(.*)/i', $options['content'], $matches)) {
                if (!preg_match($matches[1], self::getNodeText($node))) {
                    $invalid = true;
                }
            } // match empty string
            elseif ($options['content'] === '') {
                if (self::getNodeText($node) !== '') {
                    $invalid = true;
                }
            } // match by exact string
            elseif (strstr(self::getNodeText($node), $options['content']) === false) {
                $invalid = true;
            }

            if (!$invalid) {
                $filtered[] = $node;
            }
        }

        $nodes = $filtered;
        $filtered = [];

        if (empty($nodes)) {
            return false;
        }
    }

    // filter by parent node
    if ($options['parent']) {
        $parentNodes = self::findNodes($dom, $options['parent'], $isHtml);
        $parentNode = isset($parentNodes[0]) ? $parentNodes[0] : null;

        foreach ($nodes as $node) {
            if ($parentNode !== $node->parentNode) {
                continue;
            }

            $filtered[] = $node;
        }

        $nodes = $filtered;
        $filtered = [];

        if (empty($nodes)) {
            return false;
        }
    }

    // filter by child node
    if ($options['child']) {
        $childNodes = self::findNodes($dom, $options['child'], $isHtml);
        $childNodes = !empty($childNodes) ? $childNodes : [];

        foreach ($nodes as $node) {
            foreach ($node->childNodes as $child) {
                foreach ($childNodes as $childNode) {
                    if ($childNode === $child) {
                        $filtered[] = $node;
                    }
                }
            }
        }

        $nodes = $filtered;
        $filtered = [];

        if (empty($nodes)) {
            return false;
        }
    }

    // filter by adjacent-sibling
    if ($options['adjacent-sibling']) {
        $adjacentSiblingNodes = self::findNodes($dom, $options['adjacent-sibling'], $isHtml);
        $adjacentSiblingNodes = !empty($adjacentSiblingNodes) ? $adjacentSiblingNodes : [];

        foreach ($nodes as $node) {
            $sibling = $node;

            while ($sibling = $sibling->nextSibling) {
                if ($sibling->nodeType !== XML_ELEMENT_NODE) {
                    continue;
                }

                foreach ($adjacentSiblingNodes as $adjacentSiblingNode) {
                    if ($sibling === $adjacentSiblingNode) {
                        $filtered[] = $node;
                        break;
                    }
                }

                break;
            }
        }

        $nodes = $filtered;
        $filtered = [];

        if (empty($nodes)) {
            return false;
        }
    }

    // filter by ancestor
    if ($options['ancestor']) {
        $ancestorNodes = self::findNodes($dom, $options['ancestor'], $isHtml);
        $ancestorNode = isset($ancestorNodes[0]) ? $ancestorNodes[0] : null;

        foreach ($nodes as $node) {
            $parent = $node->parentNode;

            while ($parent && $parent->nodeType != XML_HTML_DOCUMENT_NODE) {
                if ($parent === $ancestorNode) {
                    $filtered[] = $node;
                }

                $parent = $parent->parentNode;
            }
        }

        $nodes = $filtered;
        $filtered = [];

        if (empty($nodes)) {
            return false;
        }
    }

    // filter by descendant
    if ($options['descendant']) {
        $descendantNodes = self::findNodes($dom, $options['descendant'], $isHtml);
        $descendantNodes = !empty($descendantNodes) ? $descendantNodes : [];

        foreach ($nodes as $node) {
            foreach (self::getDescendants($node) as $descendant) {
                foreach ($descendantNodes as $descendantNode) {
                    if ($descendantNode === $descendant) {
                        $filtered[] = $node;
                    }
                }
            }
        }

        $nodes = $filtered;
        $filtered = [];

        if (empty($nodes)) {
            return false;
        }
    }

    // filter by children
    if ($options['children']) {
        $validChild = ['count', 'greater_than', 'less_than', 'only'];
        $childOptions = self::assertValidKeys(
                $options['children'], $validChild
        );

        foreach ($nodes as $node) {
            $childNodes = $node->childNodes;

            foreach ($childNodes as $childNode) {
                if ($childNode->nodeType !== XML_CDATA_SECTION_NODE &&
                    $childNode->nodeType !== XML_TEXT_NODE) {
                    $children[] = $childNode;
                }
            }

            // we must have children to pass this filter
            if (!empty($children)) {
                // exact count of children
                if ($childOptions['count'] !== null) {
                    if (count($children) !== $childOptions['count']) {
                        break;
                    }
                } // range count of children
                elseif ($childOptions['less_than'] !== null &&
                    $childOptions['greater_than'] !== null) {
                    if (count($children) >= $childOptions['less_than'] ||
                        count($children) <= $childOptions['greater_than']) {
                        break;
                    }
                } // less than a given count
                elseif ($childOptions['less_than'] !== null) {
                    if (count($children) >= $childOptions['less_than']) {
                        break;
                    }
                } // more than a given count
                elseif ($childOptions['greater_than'] !== null) {
                    if (count($children) <= $childOptions['greater_than']) {
                        break;
                    }
                }

                // match each child against a specific tag
                if ($childOptions['only']) {
                    $onlyNodes = self::findNodes(
                            $dom, $childOptions['only'], $isHtml
                    );

                    // try to match each child to one of the 'only' nodes
                    foreach ($children as $child) {
                        $matched = false;

                        foreach ($onlyNodes as $onlyNode) {
                            if ($onlyNode === $child) {
                                $matched = true;
                            }
                        }

                        if (!$matched) {
                            break 2;
                        }
                    }
                }

                $filtered[] = $node;
            }
        }

        $nodes = $filtered;

        if (empty($nodes)) {
            return;
        }
    }

    // return the first node that matches all criteria
    return !empty($nodes) ? $nodes : [];
}

public hasInternet( ) (defined in Kohana_Unittest_TestCase)

Check for internet connectivity

Return Values

  • boolean - Whether an internet connection is available

Source Code

public function hasInternet()
{
    return Unittest_Helpers::has_internet();
}

public setEnvironment( array $environment ) (defined in Kohana_Unittest_TestCase)

Allows easy setting & backing up of enviroment config

Option types are checked in the following order:

  • Server Var
  • Static Variable
  • Config option

Parameters

  • array $environment required - List of environment to set

Source Code

public function setEnvironment(array $environment)
{
    return $this->_helpers->set_environment($environment);
}

public setUp( ) (defined in Kohana_Unittest_TestCase)

Creates a predefined environment using the default environment

Extending classes that have their own setUp() should call parent::setUp()

Source Code

public function setUp()
{
    $this->_helpers = new Unittest_Helpers;

    $this->setEnvironment($this->environmentDefault);
}

public tearDown( ) (defined in Kohana_Unittest_TestCase)

Restores the original environment overriden with setEnvironment()

Extending classes that have their own tearDown() should call parent::tearDown()

Source Code

public function tearDown()
{
    $this->_helpers->restore_environment();
}

public static create_class( string $class ) (defined in Kohana_Kodoc_Missing)

Creates classes when they are otherwise not found.

Kodoc::create_class('ThisClassDoesNotExist');

All classes created will extend Kodoc_Missing.

Parameters

  • string $class required - Class name

Tags

  • Since - 3.0.7

Return Values

  • boolean

Source Code

public static function create_class($class)
{
    if (!class_exists($class)) {
        // Create a new missing class
        eval("class {$class} extends Kodoc_Missing {}");
    }

    return true;
}

protected static getDescendants( DOMNode $node ) (defined in Kohana_Unittest_TestCase)

Recursively get flat array of all descendants of this node.

TODO: This should be removed when phpunit-dom-assertions gets released.

Parameters

  • DOMNode $node required - $node

Return Values

  • array

Source Code

protected static function getDescendants(DOMNode $node)
{
    $allChildren = [];
    $childNodes = $node->childNodes ? $node->childNodes : [];

    foreach ($childNodes as $child) {
        if ($child->nodeType === XML_CDATA_SECTION_NODE ||
            $child->nodeType === XML_TEXT_NODE) {
            continue;
        }

        $children = self::getDescendants($child);
        $allChildren = array_merge($allChildren, $children, [$child]);
    }

    return isset($allChildren) ? $allChildren : [];
}

protected static getElementsByCaseInsensitiveTagName( DOMDocument $dom , string $tag ) (defined in Kohana_Unittest_TestCase)

Gets elements by case insensitive tagname.

TODO: This should be removed when phpunit-dom-assertions gets released.

Parameters

  • DOMDocument $dom required - $dom
  • string $tag required - $tag

Return Values

  • DOMNodeList

Source Code

protected static function getElementsByCaseInsensitiveTagName(DOMDocument $dom, $tag)
{
    $elements = $dom->getElementsByTagName(strtolower($tag));

    if ($elements->length == 0) {
        $elements = $dom->getElementsByTagName(strtoupper($tag));
    }

    return $elements;
}

protected static getNodeText( DOMNode $node ) (defined in Kohana_Unittest_TestCase)

Get the text value of this node's child text node.

TODO: This should be removed when phpunit-dom-assertions gets released.

Parameters

  • DOMNode $node required - $node

Return Values

  • string

Source Code

protected static function getNodeText(DOMNode $node)
{
    if (!$node->childNodes instanceof DOMNodeList) {
        return '';
    }

    $result = '';

    foreach ($node->childNodes as $childNode) {
        if ($childNode->nodeType === XML_TEXT_NODE ||
            $childNode->nodeType === XML_CDATA_SECTION_NODE) {
            $result .= trim($childNode->data) . ' ';
        } else {
            $result .= self::getNodeText($childNode);
        }
    }

    return str_replace('  ', ' ', $result);
}