Commit a1c4ad24 authored by Ivan Chepurnyi's avatar Ivan Chepurnyi

+ Controller Test Case (Request, Response, Layout, Session Support)

! Some changes in configuration constraints
+ Added JSON constraint + assert method in base test case
! Changes in configuration
! Fix issues with mock object creation
! Changes in app/etc/local.phpunit for supporting controller test cases
! Refactored module, almost all the interfaces moved to lib. 
! NOTICE: Constraints are implmented without knowing about Magento system at all, so everyone can use them, just by creating own module that will implement required interface from lib.
parent 68f9fe81
......@@ -10,6 +10,10 @@ if (!Mage::isInstalled()) {
exit('Magento Unit Tests can be runned only on installed version');
}
/* Replace server variables for proper file naming */
$_SERVER['SCRIPT_NAME'] = dirname(__FILE__) . DS . 'index.php';
$_SERVER['SCRIPT_FILENAME'] = dirname(__FILE__) . DS . 'index.php';
Mage::app('admin');
Mage::getConfig()->init();
......
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Front controller for test suite
*
*/
class EcomDev_PHPUnit_Controller_Front extends Mage_Core_Controller_Varien_Front
{
/**
* Overriden for getting rid of unusual behavior in the test case,
* because test should be isolated
*
* (non-PHPdoc)
* @see Mage_Core_Controller_Varien_Front::_checkBaseUrl()
*/
protected function _checkBaseUrl()
{
// Does nothing
}
/**
* Overriden for getting rid
* of initialization of routers for each test case
*
* (non-PHPdoc)
* @see Mage_Core_Controller_Varien_Front::init()
*/
public function init()
{
if (!$this->_routers) {
parent::init();
}
return $this;
}
}
\ No newline at end of file
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Request class for usage in the controller test cases
*
* By default set for test app instance,
* you can change to your class,
* but you should extend it from this one
*
*/
class EcomDev_PHPUnit_Controller_Request_Http
extends Mage_Core_Controller_Request_Http
implements EcomDev_PHPUnit_Isolation_Interface,
EcomDev_PHPUnit_Controller_Request_Interface
{
/**
* List of $_SERVER variable changes
* that were done by test case
*
* @var array
*/
protected $_originalServerValues = array();
/**
* List of headers that were set for test case
*
* @return array
*/
protected $_headers = array();
/**
* Initializes forward data
*
* (non-PHPdoc)
* @see Mage_Core_Controller_Request_Http::initForward()
*/
public function initForward()
{
if (empty($this->_beforeForwardInfo)) {
parent::initForward();
$this->_beforeForwardInfo['route_name'] = $this->getRouteName();
return $this;
}
return parent::initForward();
}
/**
* Returns only request uri that was set before
* (non-PHPdoc)
* @see Zend_Controller_Request_Http::getRequestUri()
*/
public function getRequestUri()
{
return $this->_requestUri;
}
/**
* Sets cookie value for test,
*
* @param string|array $name
* @param string|null $value
* @return EcomDev_PHPUnit_Controller_Request_Http_Test
*/
public function setCookie($name, $value)
{
$_COOKIE[$name] = $value;
return $this;
}
/**
* Sets more than one cookie
*
* @param array $cookies
* @return EcomDev_PHPUnit_Controller_Request_Http_Test
*/
public function setCookies(array $cookies)
{
$_COOKIE += $cookies;
return $this;
}
/**
* Resets all cookies for the test request
*
* @return EcomDev_PHPUnit_Controller_Request_Http_Test
*/
public function resetCookies()
{
$_COOKIE = array();
return $this;
}
/**
* Resets query for the current request
*
* @return EcomDev_PHPUnit_Controller_Request_Http_Test
*/
public function resetQuery()
{
$_GET = array();
return $this;
}
/**
* Resets $_POST superglobal for test request
*
* @return EcomDev_PHPUnit_Controller_Request_Http_Test
*/
public function resetPost()
{
$_POST = array();
return $this;
}
/**
* Resets user defined request params for test request
*
* @return EcomDev_PHPUnit_Controller_Request_Http_Test
*/
public function resetParams()
{
$this->_params = array();
return $this;
}
/**
* Resets internal properties to its default values
*
* @return EcomDev_PHPUnit_Controller_Request_Http_Test
*/
public function resetInternalProperties()
{
// From abstract request
$this->_dispatched = false;
$this->_module = null;
$this->_moduleKey = 'module';
$this->_controller = null;
$this->_controllerKey = 'controller';
$this->_action = null;
$this->_actionKey = 'action';
// From Http request
$this->_paramSources = array('_GET', '_POST');
$this->_requestUri = null;
$this->_baseUrl = null;
$this->_basePath = null;
$this->_pathInfo = '';
$this->_rawBody = null;
$this->_aliases = array();
// From Magento Http request
$this->_originalPathInfo = '';
$this->_storeCode = null;
$this->_requestString = '';
$this->_rewritedPathInfo = null;
$this->_requestedRouteName = null;
$this->_routingInfo = array();
$this->_route = null;
$this->_directFrontNames = null;
$this->_controllerModule = null;
return $this;
}
/**
* Set custom http header
*
* @param string $name
* @param string $value
* @return EcomDev_PHPUnit_Controller_Request_Http_Test
*/
public function setHeader($name, $value)
{
$name = $this->headerName($name);
$this->_headers[$name] = $value;
// Additionally set $_SERVER http header value
$this->setServer('HTTP_' . $name, $value);
return $this;
}
/**
* Sets more than one header,
* headers list is an associative array
*
* @param array $headers
* @return EcomDev_PHPUnit_Controller_Request_Http_Test
*/
public function setHeaders(array $headers)
{
foreach ($headers as $name => $value) {
$this->setHeader($name, $value);
}
return $this;
}
/**
* Returns header from test request parameters
*
* (non-PHPdoc)
* @see Zend_Controller_Request_Http::getHeader()
*/
public function getHeader($header)
{
$name = $this->headerName($header);
if (isset($this->_headers[$name])) {
return $this->_headers[$name];
}
return false;
}
/**
* Resets headers in test request
*
* @return EcomDev_PHPUnit_Controller_Request_Http_Test
*/
public function resetHeaders()
{
$this->_headers = array();
return $this;
}
/**
* Returns unified header name for internal storage
*
* @param string $name
* @return string
*/
protected function headerName($name)
{
return strtr(strtoupper($name), '-', '_');
}
/**
* Sets value for a particular $_SERVER superglobal array key for test request
*
* Saves original value for returning it back
*
* @param string $name
* @param string $value
* @return EcomDev_PHPUnit_Controller_Request_Http_Test
*/
public function setServer($name, $value)
{
if (!isset($this->_originalServerValues[$name])) {
$originalValue = (isset($_SERVER[$name]) ? $_SERVER[$name] : null);
$this->_originalServerValues[$name] = $originalValue;
}
$_SERVER[$name] = $value;
return $this;
}
/**
* Sets multiple values for $_SERVER superglobal in test request
*
* @param array $values
* @return EcomDev_PHPUnit_Controller_Request_Http_Test
*/
public function setServers(array $values)
{
foreach ($values as $name => $value) {
$this->setServer($name, $value);
}
return $this;
}
/**
* Resets $_SERVER superglobal to previous state
*
* @return EcomDev_PHPUnit_Controller_Request_Http_Test
*/
public function resetServer()
{
foreach ($this->_originalServerValues as $name => $value) {
if ($value !== null) {
$_SERVER[$name] = $value;
} elseif (isset($_SERVER[$name])) {
// If original value was not set,
// then unsetting the changed value
unset($_SERVER[$name]);
}
}
$this->_originalServerValues = array();
return $this;
}
/**
* Sets request method for test request
*
* @param string $requestMethod
* @return EcomDev_PHPUnit_Controller_Request_Http_Test
*/
public function setMethod($requestMethod)
{
$this->setServer('REQUEST_METHOD', $requestMethod);
return $this;
}
/**
* Sets current request scheme for test request,
* accepts boolean flag for HTTPS
*
* @param boolean $flag
* @return EcomDev_PHPUnit_Controller_Request_Http_Test
*/
public function setIsSecure($flag = true)
{
$this->setServer('HTTPS', $flag ? 'on' : null);
return $this;
}
/**
* Returns HTTP host from base url that were set in the controller
*
* (non-PHPdoc)
* @see Mage_Core_Controller_Request_Http::getHttpHost()
*/
public function getHttpHost($trimPort = false)
{
$baseUrl = $this->getBaseUrl();
$parts = parse_url($baseUrl);
$httpHost = $parts['host'];
if (!$trimPort && isset($parts['port'])) {
$httpHost .= ':' . $parts['port'];
}
return $httpHost;
}
/**
* Returns only base url that was set before
*
* (non-PHPdoc)
* @see Mage_Core_Controller_Request_Http::getBaseUrl()
*/
public function getBaseUrl()
{
return $this->_baseUrl;
}
/**
* Resets all request data for test
*
* @return EcomDev_PHPUnit_Controller_Request_Http_Test
*/
public function reset()
{
$this->resetInternalProperties()
->resetHeaders()
->resetParams()
->resetPost()
->resetQuery()
->resetCookies()
->resetServer();
return $this;
}
}
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Response class for usage in the controller test cases
*
* By default set for test app instance,
* you can change to your class,
* but you should extend it from this one
*
*/
class EcomDev_PHPUnit_Controller_Response_Http
extends Mage_Core_Controller_Response_Http
implements EcomDev_PHPUnit_Isolation_Interface,
EcomDev_PHPUnit_Controller_Response_Interface
{
const LINE_ENDING = "\r\n";
/**
* Headers that was sent via sendHeaders() method
*
* @var array
*/
protected $_sentHeaders = null;
/**
* Response that was sent via sendRespose()
* or sendHeaders() or outputBody() methods
*
* @var string
*/
protected $_sentResponse = null;
/**
* Response body that was sent via outputBody()
* method
*
* @var string
*/
protected $_outputBody = null;
/**
* Resets response object
*
* @return EcomDev_PHPUnit_Controller_Response_Http_Test
*/
public function reset()
{
$this->_sentHeaders = null;
$this->_sentResponse = null;
$this->_outputBody = null;
$this->_body = array();
$this->_exceptions = array();
$this->_headers = array();
$this->_headersRaw = array();
$this->_httpResponseCode = 200;
$this->_isRedirect = false;
$this->_renderExceptions = false;
$this->headersSentThrowsException = Mage::$headersSentThrowsException;
$this->setHeader('Content-Type', 'text/html; charset=UTF-8');
return $this;
}
/**
* Implementation of sending the headers to output
*
* (non-PHPdoc)
* @see Mage_Core_Controller_Response_Http::sendHeaders()
*/
public function sendHeaders()
{
$this->canSendHeaders(true);
$this->_sentHeaders= array();
$this->_sentHeaders[null] = 'HTTP/1.1 ' . $this->_httpResponseCode;
foreach ($this->_headersRaw as $headerRaw) {
list($headerName, $headerValue) = explode(':', $headerRaw, 2);
$headerName = $this->_normalizeHeader($headerName);
if (isset($this->_sentHeaders[$headerName])) {
// Merge headers, if already any was sent with the same name
// Set-Cookie header is usually not sent via response
// so it should be ok.
$this->_sentHeaders[$headerName] .= '; ' . $headerValue;
} else {
$this->_sentHeaders[$headerName] = $headerValue;
}
}
foreach ($this->_headers as $header) {
if (isset($this->_sentHeaders[$header['name']])) {
$this->_sentHeaders[$header['name']] .= '; ' . $header['value'];
} else {
$this->_sentHeaders[$header['name']] = $header['value'];
}
}
$this->_sentResponse = '';
foreach ($this->_sentHeaders as $headerName => $headerValue) {
$headerString = '';
if ($headerName === null) {
$headerString .= $headerName . ': ';
}
$headerString .= $headerValue . self::LINE_ENDING;
$this->_sentResponse .= $headerString;
}
$this->_sentResponse .= self::LINE_ENDING;
}
/**
* Returns rendered headers array that was sent,
* if headers was not sent, then returns null
*
* @return array|null
*/
public function getSentHeaders()
{
return $this->_sentHeaders;
}
/**
* Returns a particular header that was sent
*
* @param string $headerName
* @return string|false
*/
public function getSentHeader($headerName)
{
$headerName = $this->_normalizeHeader($headerName);
if (isset($this->_sentHeaders[$headerName])) {
return $this->_sentHeaders[$headerName];
}
return false;
}
/**
* Implementation of sending response for test case
* (non-PHPdoc)
* @see Mage_Core_Controller_Response_Http::sendResponse()
*/
public function sendResponse()
{
//Mage::dispatchEvent('http_response_send_before', array('response'=>$this));
$this->sendHeaders();
if ($this->isException() && $this->renderExceptions()) {
$exceptions = '';
foreach ($this->getException() as $e) {
$exceptions .= (string)$e . "\n";
}
$this->_sentResponse .= $exceptions;
return;
}
$this->outputBody();
}
/**
* Returns rendered response, if response was not sent,
* then it returns null
*
* @return string|null
*/
public function getSentResponse()
{
return $this->_sentResponse;
}
/**
* Implementation of outputting the body of response
*
* (non-PHPdoc)
* @see Zend_Controller_Response_Abstract::outputBody()
*/
public function outputBody()
{
$this->_outputBody = implode('', $this->_body);
$this->_sentResponse .= $this->_outputBody;
}
/**
* Returns rendered body output
*
* @return string
*/
public function getOutputBody()
{
return $this->_outputBody;
}
/**
* Can send headers implementation for test case
*
* (non-PHPdoc)
* @see Zend_Controller_Response_Abstract::canSendHeaders()
*/
public function canSendHeaders($throw = false)
{
if ($this->_sentHeaders !== null && $throw && $this->headersSentThrowsException) {
#require_once 'Zend/Controller/Response/Exception.php';
throw new Zend_Controller_Response_Exception('Cannot send headers; headers already sent');
}
return $this->_sentHeaders === null;
}
}
\ No newline at end of file
......@@ -32,11 +32,29 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
// Admin store code
const ADMIN_STORE_CODE = 'admin';
const AREA_ADMINHTML = 'adminhtml';
const AREA_FRONTEND = 'frontend';
const AREA_ADMINHTML = EcomDev_PHPUnit_Model_App_Area::AREA_ADMINHTML;
const AREA_ADMIN = EcomDev_PHPUnit_Model_App_Area::AREA_ADMIN;
const AREA_FRONTEND = EcomDev_PHPUnit_Model_App_Area::AREA_FRONTEND;
const AREA_GLOBAL = EcomDev_PHPUnit_Model_App_Area::AREA_GLOBAL;
const AREA_TEST = EcomDev_PHPUnit_Model_App_Area::AREA_TEST;
const AREA_PART_EVENTS = EcomDev_PHPUnit_Model_App_Area::PART_EVENTS;
const AREA_PART_DESIGN = EcomDev_PHPUnit_Model_App_Area::PART_DESIGN;
const AREA_PART_TRANSLATE = EcomDev_PHPUnit_Model_App_Area::PART_TRANSLATE;
const AREA_PART_CONFIG = EcomDev_PHPUnit_Model_App_Area::PART_CONFIG;
const INTERFACE_ISOLATION = 'EcomDev_PHPUnit_Isolation_Interface';
const REGISTRY_PATH_LAYOUT_SINGLETON = '_singleton/core/layout';
const REGISTRY_PATH_DESIGN_PACKAGE_SINGLETON = '_singleton/core/design_package';
const XML_PATH_LAYOUT_MODEL_FOR_TEST = 'phpunit/suite/layout/model';
const XML_PATH_DESIGN_PACKAGE_MODEL_FOR_TEST = 'phpunit/suite/design/package/model';
const XML_PATH_APP_AREA = 'phpunit/suite/app/area/class';
const XML_PATH_CONTROLLER_FRONT = 'phpunit/suite/controller/front/class';
const XML_PATH_CONTROLLER_REQUEST = 'phpunit/suite/controller/request/class';
const XML_PATH_CONTROLLER_RESPONSE = 'phpunit/suite/controller/response/class';
/**
* Old configuration model to be returned back
......@@ -84,11 +102,14 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
protected static $_eventCollectionClass = 'Varien_Event_Collection';
/**
* Configuration model class name for unit tests
* List of areas that will be ignored in resetAreas() method
*
* @var string
* @var array
*/
protected static $_cacheClass = 'EcomDev_PHPUnit_Model_Cache';
protected $_resetIgnoreAreas = array(
self::AREA_GLOBAL,
self::AREA_TEST
);
/**
* Enabled events flag
......@@ -97,6 +118,13 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
*/
protected $_eventsEnabled = true;
/**
* Dispatched events array
*
* @var array
*/
protected $_dispatchedEvents = array();
/**
* List of module names stored by class name
*
......@@ -165,22 +193,196 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
// Init modules runs install proccess for table structures,
// It is required for setting up proper setup script
$this->_initModules();
$this->loadAreaPart(Mage_Core_Model_App_Area::AREA_GLOBAL, Mage_Core_Model_App_Area::PART_EVENTS);
$this->loadAreaPart(self::AREA_GLOBAL, self::AREA_PART_EVENTS);
if ($this->_config->isLocalConfigLoaded()) {
$this->_initCurrentStore(self::ADMIN_STORE_CODE, self::RUN_TYPE_STORE);
$this->_initRequest();
Mage_Core_Model_Resource_Setup::applyAllDataUpdates();
}
$layoutModel = Mage::getModel(
$this->getConfig()->getNode(self::XML_PATH_LAYOUT_MODEL_FOR_TEST)
$layoutModel = $this->_getModelFromConfig(
self::XML_PATH_LAYOUT_MODEL_FOR_TEST,
self::INTERFACE_ISOLATION,
'Layout model'
);
$this->replaceRegistry(self::REGISTRY_PATH_LAYOUT_SINGLETON,
$layoutModel);
$designPackageModel = $this->_getModelFromConfig(
self::XML_PATH_DESIGN_PACKAGE_MODEL_FOR_TEST,
self::INTERFACE_ISOLATION,
'Design package model'
);
$this->replaceRegistry(self::REGISTRY_PATH_DESIGN_PACKAGE_SINGLETON,
$designPackageModel);
$this->loadAreaPart(self::AREA_TEST, self::AREA_PART_EVENTS);
return $this;
}
/**
* Retrieves a model from config and checks it on interface implementation
*
* @param string $configPath
* @param string $interface
* @param string $modelName
* @return Mage_Core_Model_Abstract
*/
protected function _getModelFromConfig($configPath, $interface, $modelName = 'Model')
{
$model = Mage::getModel(
(string)$this->getConfig()->getNode($configPath)
);
if (!$model instanceof $interface) {
throw new RuntimeException(
sprintf('%s should implement %s to make possible running tests in isolation',
$modelName, $interface)
);
}
return $model;
}
/**
* Initialize front controller for test suite
*
* @return EcomDev_PHPUnit_Model_App
*/
protected function _initFrontController()
{
$frontControllerClass = $this->_getClassNameFromConfig(self::XML_PATH_CONTROLLER_FRONT);
$this->_frontController = new $frontControllerClass();
Mage::register('controller', $this->_frontController);
$this->_frontController->init();
return $this;
}
/**
* Retrieve application area
*
* @param string $code
* @return EcomDev_PHPUnit_Model_App_Area
*/
public function getArea($code)
{
if (!isset($this->_areas[$code])) {
$appAreaClass = $this->_getClassNameFromConfig(
self::XML_PATH_APP_AREA, self::INTERFACE_ISOLATION
);
$this->_areas[$code] = new $appAreaClass($code, $this);
}
return $this->_areas[$code];
}
/**
* Resets areas parts, like events, translations, design
*
* @return EcomDev_PHPUnit_Model_App
*/
public function resetAreas()
{
/* @var $area EcomDev_PHPUnit_Model_App_Area */
foreach ($this->_areas as $code => $area) {
if (!in_array($code, $this->_resetIgnoreAreas)) {
$area->reset();
}
}
return $this;
}
Mage::register(self::REGISTRY_PATH_LAYOUT_SINGLETON, $layoutModel, true);
/**
* Replace registry item value
*
* @param string $key
* @param string $value
*/
public function replaceRegistry($key, $value)
{
$registry = EcomDev_Utils_Reflection::getRestrictedPropertyValue('Mage', '_registry');
$registry[$key] = $value;
EcomDev_Utils_Reflection::setRestrictedPropertyValue('Mage', '_registry', $registry);
return $this;
}
/**
* Removes event area
*
* @param string $code area code
* @return EcomDev_PHPUnit_Model_App
*/
public function removeEventArea($code)
{
if (isset($this->_events[$code])) {
unset($this->_events[$code]);
}
return $this;
}
/**
* Returns request for test suite
* (non-PHPdoc)
* @see Mage_Core_Model_App::getRequest()
* @return EcomDev_PHPUnit_Controller_Request_Http
*/
public function getRequest()
{
if ($this->_request === null) {
$requestClass = $this->_getClassNameFromConfig(
self::XML_PATH_CONTROLLER_REQUEST, self::INTERFACE_ISOLATION
);
$this->_request = new $requestClass;
}
return $this->_request;
}
/**
* Returns response for test suite
* (non-PHPdoc)
* @see Mage_Core_Model_App::getResponse()
* @return EcomDev_PHPUnit_Controller_Response_Http
*/
public function getResponse()
{
if ($this->_response === null) {
$responseClass = $this->_getClassNameFromConfig(
self::XML_PATH_CONTROLLER_RESPONSE, self::INTERFACE_ISOLATION
);
$this->_response = new $responseClass;
}
return $this->_response;
}
/**
* Returns class name from configuration path,
* If $interface is specified, then it additionaly checks it for implementation
*
*
* @param string $configPath
* @param string $interface
* @return string
*/
protected function _getClassNameFromConfig($configPath, $interface = null)
{
$className = (string)$this->getConfig()->getNode($configPath);
$reflection = EcomDev_Utils_Reflection::getRelflection($className);
if ($interface !== null && !$reflection->implementsInterface($interface)) {
throw new RuntimeException(
sprintf('Invalid class name defined in configuration path %s, because %s does not implement %s interface',
$configPath, $interface)
);
}
return $className;
}
/**
* Overriden to fix issue with stores loading
* (non-PHPdoc)
......@@ -254,6 +456,30 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
return $this;
}
/**
* Overriden for typehinting
*
* @return EcomDev_PHPUnit_Model_Config
* (non-PHPdoc)
* @see Mage_Core_Model_App::getConfig()
*/
public function getConfig()
{
return parent::getConfig();
}
/**
* Overriden for typehinting
*
* @return EcomDev_PHPUnit_Model_Layout
* (non-PHPdoc)
* @see Mage_Core_Model_App::getLayout()
*/
public function getLayout()
{
return parent::getLayout();
}
/**
* Disables events fire
*
......@@ -287,8 +513,42 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
{
if ($this->_eventsEnabled) {
parent::dispatchEvent($eventName, $args);
if (!isset($this->_dispatchedEvents[$eventName])) {
$this->_dispatchedEvents[$eventName] = 0;
}
$this->_dispatchedEvents[$eventName]++;
}
return $this;
}
/**
* Returns number of times when the event was dispatched
*
* @param string $eventName
* @return int
*/
public function getDispatchedEventCount($eventName)
{
if (isset($this->_dispatchedEvents[$eventName])) {
return $this->_dispatchedEvents[$eventName];
}
return 0;
}
/**
* Resets dispatched events information
*
* @return EcomDev_PHPUnit_Model_App
*/
public function resetDispatchedEvents()
{
$this->_dispatchedEvents = array();
return $this;
}
}
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Implementation of app area for a test
*
*
*/
class EcomDev_PHPUnit_Model_App_Area
extends Mage_Core_Model_App_Area
implements EcomDev_PHPUnit_Isolation_Interface
{
const AREA_TEST = 'test';
/**
* Reset all the data,
* related to a particular area
*
* @return EcomDev_PHPUnit_Model_App_Area
*/
public function reset()
{
$this->resetEvents();
$this->resetDesign();
$this->resetTranslate();
return $this;
}
/**
* Resets events area data
*
* @return EcomDev_PHPUnit_Model_App_Area
*/
public function resetEvents()
{
$this->_application->removeEventArea($this->_code);
return $this;
}
/**
* Resets design related area data
*
*
* @return EcomDev_PHPUnit_Model_App_Area
*/
public function resetDesign()
{
Mage::getSingleton('core/design')->unsetData();
Mage::getSingleton('core/design_package')->reset();
return $this;
}
/**
* Resets translator data
*
* @return EcomDev_PHPUnit_Model_App_Area
*/
public function resetTranslate()
{
$translator = $this->_application->getTranslator();
EcomDev_Utils_Reflection::setRestrictedPropertyValue($translator, '_config', null);
EcomDev_Utils_Reflection::setRestrictedPropertyValue($translator, '_locale', null);
EcomDev_Utils_Reflection::setRestrictedPropertyValue($translator, '_cacheId', null);
EcomDev_Utils_Reflection::setRestrictedPropertyValue($translator, '_translateInline', null);
EcomDev_Utils_Reflection::setRestrictedPropertyValue($translator, '_dataScope', null);
EcomDev_Utils_Reflection::setRestrictedPropertyValue($translator, '_data', array());
return $this;
}
}
\ No newline at end of file
......@@ -23,6 +23,10 @@
*/
class EcomDev_PHPUnit_Model_Config extends Mage_Core_Model_Config
{
const XML_PATH_SECURE_BASE_URL = 'default/web/secure/base_url';
const XML_PATH_UNSECURE_BASE_URL = 'default/web/unsecure/base_url';
const CHANGE_ME = '[change me]';
/**
* Scope snapshot without applied configurations,
* It is used for proper store/website/default loading on per store basis
......@@ -212,6 +216,7 @@ class EcomDev_PHPUnit_Model_Config extends Mage_Core_Model_Config
$merge = clone $this->_prototype;
if ($merge->loadFile($this->_getLocalXmlForTest())) {
$this->_checkDbCredentialForDuplicate($this, $merge);
$this->_checkBaseUrl($this, $merge);
$this->extend($merge);
} else {
throw new Exception('Unable to load local.xml.phpunit');
......@@ -254,6 +259,30 @@ class EcomDev_PHPUnit_Model_Config extends Mage_Core_Model_Config
return $this;
}
/**
* Check base url settings, if not set it rises an exception
*
* @param Mage_Core_Model_Config_Base $original
* @param Mage_Core_Model_Config_Base $test
* @return EcomDev_PHPUnit_Model_Config
* @throws RuntimeException
*/
protected function _checkBaseUrl($original, $test)
{
$baseUrlSecure = (string)$test->getNode(self::XML_PATH_SECURE_BASE_URL);
$baseUrlUnsecure = (string)$test->getNode(self::XML_PATH_UNSECURE_BASE_URL);
if (empty($baseUrlSecure) || empty($baseUrlUnsecure)
|| $baseUrlSecure == self::CHANGE_ME || $baseUrlUnsecure == self::CHANGE_ME) {
echo sprintf(
'Please change values in %s file for nodes %s and %s. '
. 'It will help in setting up proper controller test cases',
'app/etc/local.phpunit', self::XML_PATH_SECURE_BASE_URL, self::XML_PATH_UNSECURE_BASE_URL
);
exit();
}
}
/**
* Retrieves local.xml file path for tests,
* If it is not found, method will rise an exception
......
......@@ -2,7 +2,9 @@
class EcomDev_PHPUnit_Model_Design_Package
extends Mage_Core_Model_Design_Package
implements EcomDev_PHPUnit_Constraint_Config_Layout_Design_Package_Interface
implements EcomDev_PHPUnit_Design_Package_Interface,
EcomDev_PHPUnit_Isolation_Interface
{
/**
* Asserts layout file existance in design packages,
......
......@@ -22,7 +22,10 @@
* for testing the layout itself
*
*/
class EcomDev_PHPUnit_Model_Layout extends Mage_Core_Model_Layout
class EcomDev_PHPUnit_Model_Layout
extends Mage_Core_Model_Layout
implements EcomDev_PHPUnit_Constraint_Layout_Logger_Interface,
EcomDev_PHPUnit_Isolation_Interface
{
/**
* List of replaced blocks creation
......@@ -31,6 +34,30 @@ class EcomDev_PHPUnit_Model_Layout extends Mage_Core_Model_Layout
*/
protected $_replaceBlockCreation = array();
/**
* Records for gethering information about all,
* the actions that was performed
*
*
* @var array
*/
protected $_records = array();
/**
* List of collected args for action call
*
* @var array
*/
protected $_collectedArgs = null;
/**
* Collected block during block creation
*
* @var Mage_Core_Block_Abstract
*/
protected $_collectedBlock = null;
/**
* Replaces creation of some block by mock object
*
......@@ -82,6 +109,7 @@ class EcomDev_PHPUnit_Model_Layout extends Mage_Core_Model_Layout
$this->_helpers = array();
$this->_directOutput = false;
$this->_output = array();
$this->_records = array();
foreach ($this->_blocks as $block) {
// Remove references between blocks
......@@ -91,8 +119,376 @@ class EcomDev_PHPUnit_Model_Layout extends Mage_Core_Model_Layout
}
$this->_blocks = array();
return $this;
}
/**
* Returns all the recorded actions
*
* @return array
*/
public function getRecords()
{
return $this->_records;
}
$this->flushReplaceBlockCreation();
/**
* Returns all actions performed on the target
* or if target is null returns actions for all targets
*
* @param string $action
* @param string|null $target
* @return array
*/
public function findAll($action, $target = null)
{
if ($target !== null && isset($this->_records[$action][$target])) {
return $this->_records[$action][$target];
} elseif ($target !== null) {
return array();
} elseif (!isset($this->_records[$action])) {
return array();
}
$result = array();
foreach ($this->_records[$action] as $target => $records) {
$record['target'] = $target;
$result = array_merge($result, $records);
}
return $result;
}
/**
* Returns all actions targets
*
* @param string $action
* @return array
*/
public function findAllTargets($action)
{
if (isset($this->_records[$action])) {
return array_keys($this->_records[$action]);
}
return array();
}
/**
* Returns a single target action record by specified parameters
*
* @param string $action
* @param string $target
* @param array $parameters
* @return boolean
*/
public function findByParameters($action, $target, array $parameters, $searchType = self::SEARCH_TYPE_AND)
{
if (!isset($this->_records[$action][$target])) {
return array();
}
$records = array();
$arrayValues = false;
// If it is a numeric array, then actual parameters should transformed as well
if (count(array_filter(array_keys($parameters), 'is_int')) === count($parameters)) {
$arrayValues = true;
}
foreach ($this->_records[$action][$target] as $actualParameters) {
if ($arrayValues) {
$actualParameters = array_values($actualParameters);
}
$intersection = array_intersect_assoc($actualParameters, $parameters);
switch ($searchType) {
case self::SEARCH_TYPE_OR:
$match = !empty($intersection);
break;
case self::SEARCH_TYPE_EXACT:
$match = count($intersection) === count($actualParameters);
break;
case self::SEARCH_TYPE_AND:
default:
$match = count($intersection) === count($parameters);
break;
}
if ($match) {
$records[] = $actualParameters;
}
}
return $records;
}
/**
* Returns first action that was recorded for target
*
* @param string $action
* @param string $target
* @return array
*/
public function findFirst($action, $target)
{
if (!isset($this->_records[$action][$target])) {
return false;
}
reset($this->_records[$action][$target]);
return current($this->_records[$action][$target]);
}
/**
* Records a particular target action
*
* @param string $action
* @param string|null $target
* @param array $parameters
* @return EcomDev_PHPUnit_Model_Layout
*/
public function record($action, $target = null, array $parameters = array())
{
$this->_records[$action][$target][] = $parameters;
return $this;
}
/**
* Observes a system event that is triggered on block render process start
*
* @param Varien_Event_Observer $observer
* @return EcomDev_PHPUnit_Model_Layout
*/
public function recordBlockRender(Varien_Event_Observer $observer)
{
/* @var $block Mage_Core_Block_Abstract */
$block = $observer->getEvent()->getBlock();
$transport = $observer->getEvent()->getTransport();
$this->record(
self::ACTION_BLOCK_RENDERED,
$block->getNameInLayout(),
array('content' => $transport->getHtml())
);
}
/**
* Records action call
* (non-PHPdoc)
* @see Mage_Core_Model_Layout::_generateAction()
*/
protected function _generateAction($node, $parent)
{
$this->_collectedArgs = null;
parent::_generateAction($node, $parent);
if ($this->_collectedArgs !== null) {
$method = (string)$node['method'];
if (!empty($node['block'])) {
$parentName = (string)$node['block'];
} else {
$parentName = $parent->getBlockName();
}
$target = $parentName . '::' . $method;
$this->record(self::ACTION_BLOCK_ACTION, $target, $this->_collectedArgs);
}
return $this;
}
/**
* Collects arguments if was not collected before
* (non-PHPdoc)
* @see Mage_Core_Model_Layout::_translateLayoutNode()
*/
protected function _translateLayoutNode($node, $args)
{
parent::_translateLayoutNode($node, $args);
if ($this->_collectedArgs === null) {
$this->_collectedArgs = $args;
}
}
/**
* Records information about new block creation
* (non-PHPdoc)
* @see Mage_Core_Model_Layout::_generateBlock()
*/
protected function _generateBlock($node, $parent)
{
$this->_collectedBlock = null;
parent::_generateBlock($node, $parent);
if ($this->_collectedBlock !== null) {
$target = $this->_collectedBlock->getNameInLayout();
$params = array();
if (isset($node['as'])) {
$params['alias'] = (string)$node['as'];
} else {
$params['alias'] = $target;
}
if (isset($node['class'])) {
$params['type'] = (string)$node['class'];
} elseif (isset($node['type'])) {
$params['type'] = (string)$node['type'];
}
$params['class'] = get_class($this->_collectedBlock);
$params['is_root'] = isset($node['output']);
$this->record(self::ACTION_BLOCK_CREATED, $target, $params);
if (isset($node['template'])) {
$this->record(self::ACTION_BLOCK_ACTION, $target . '::setTemplate',
array('template' => (string)$node['template']));
}
}
return $this;
}
/**
* Collects block creation
* (non-PHPdoc)
* @see Mage_Core_Model_Layout::addBlock()
*/
public function addBlock($block, $blockName)
{
$block = parent::addBlock($block, $blockName);
if ($this->_collectedBlock === null) {
$this->_collectedBlock = $block;
}
return $block;
}
/**
* Records information about blocks removal and loaded layout handles
* (non-PHPdoc)
* @see Mage_Core_Model_Layout::generateXml()
*/
public function generateXml()
{
$loadedHandles = $this->getUpdate()->getHandles();
foreach ($loadedHandles as $key => $handle) {
$params = array();
if ($key > 0) {
$params['after'] = array_slice($loadedHandles, 0, $key);
} else {
$params['after'] = array();
}
if ($key < count($loadedHandles)) {
$params['before'] = array_slice($loadedHandles, $key + 1);
} else {
$params['before'] = array();
}
$this->record(self::ACTION_HANDLE_LOADED, $handle, $params);
}
parent::generateXml();
$removedBlocks = $this->_xml->xpath('//block[@ignore]');
if (is_array($removedBlocks)) {
foreach ($removedBlocks as $block) {
$this->record(self::ACTION_BLOCK_REMOVED, $block->getBlockName());
}
}
return $this;
}
/**
* Returns block position information in the parent subling.
* Returned array contains two keys "before" and "after"
* which are list of block names in this positions
*
* @param string $block
* @return array
*/
public function getBlockPosition($block)
{
$result = array(
'before' => array(),
'after' => array()
);
$block = $this->getBlock($block);
if (!$block || !$block->getParentBlock()) {
return $result;
}
$sortedBlockNames = $block->getParentBlock()->getSortedChildren();
$key = 'before';
foreach ($sortedBlockNames as $blockName) {
if ($blockName == $block->getNameInLayout()) {
$key = 'after';
continue;
}
$result[$key][] = $blockName;
}
return $result;
}
/**
* Returns block parent
*
* @param string $block
* @return srting|boolean
*/
public function getBlockParent($block)
{
$block = $this->getBlock($block);
if (!$block || !$block->getParentBlock()) {
return false;
}
return $block->getParentBlock()->getNameInLayout();
}
/**
* Returns block property by getter
*
* @param string $block
* @return mixed
*/
public function getBlockProperty($block, $property)
{
$block = $this->getBlock($block);
if (!$block) {
throw new RuntimeException('Received a call to block, that does not exist');
}
return $block->getDataUsingMethod($property);
}
/**
* Retuns a boolean flag for layout load status
*
* @return boolean
*/
public function isLoaded()
{
return $this->_xml->hasChildren();
}
/**
* Records that layout was rendered
* (non-PHPdoc)
* @see Mage_Core_Model_Layout::getOutput()
*/
public function getOutput()
{
$this->record(self::ACTION_RENDER, 'layout');
return parent::getOutput();
}
}
......@@ -55,6 +55,182 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
*/
protected $_originalStore = null;
/**
* Returns app for test case, created for type hinting
* in the test case code
*
* @return EcomDev_PHPUnit_Model_App
*/
public static function app()
{
return Mage::app();
}
/**
* Asserts that event was dispatched at least once
*
* @param string|array $event
* @param string $message
*/
public static function assertEventDispatched($eventName)
{
if (is_array($eventName)) {
foreach ($eventNames as $eventName) {
self::assertEventDispatched($eventName);
}
return;
}
$actual = self::app()->getDispatchedEventCount($eventName);
$message = sprintf('%s event was not dispatched', $eventName);
self::assertGreaterThanOrEqual(1, $actual, $message);
}
/**
* Asserts that event was not dispatched
*
* @param string|array $event
* @param string $message
*/
public static function assertEventNotDispatched($eventName)
{
if (is_array($eventName)) {
foreach ($eventNames as $eventName) {
self::assertEventNotDispatched($eventName);
}
return;
}
$actual = self::app()->getDispatchedEventCount($eventName);
$message = sprintf('%s event was dispatched', $eventName);
self::assertEquals(0, $actual, $message);
}
/**
* Assert that event was dispatched exactly $times
*
* @param string $eventName
* @param int
*/
public static function assertEventDispatchedExactly($eventName, $times)
{
$actual = self::app()->getDispatchedEventCount($eventName);
$message = sprintf(
'%s event was dispatched only %d times, but expected to be dispatched %d times',
$eventName, $actual, $times
);
self::assertEquals($times, $actual, $message);
}
/**
* Assert that event was dispatched at least $times
*
* @param string $eventName
* @param int
*/
public static function assertEventDispatchedAtLeast($eventName, $times)
{
$actual = self::app()->getDispatchedEventCount($eventName);
$message = sprintf(
'%s event was dispatched only %d times, but expected to be dispatched at least %d times',
$eventName, $actual, $times
);
self::assertGreaterThanOrEqual($times, $actual, $message);
}
/**
* Creates a constraint for checking that string is valid JSON
*
* @return EcomDev_PHPUnit_Constraint_Json
*/
public static function isJson()
{
return new EcomDev_PHPUnit_Constraint_Json(
EcomDev_PHPUnit_Constraint_Json::TYPE_VALID
);
}
/**
* Creates a constraint for checking that string
* is matched expected JSON structure
*
* @param array $expectedValue
* @param strign $matchType
* @return EcomDev_PHPUnit_Constraint_Json
*/
public static function matchesJson(array $expectedValue, $matchType = EcomDev_PHPUnit_Constraint_Json::MATCH_AND)
{
return new EcomDev_PHPUnit_Constraint_Json(
EcomDev_PHPUnit_Constraint_Json::TYPE_MATCH,
$expectedValue,
$matchType
);
}
/**
* Assert that string is a valid JSON
*
* @param string $string
* @param string $message
*/
public static function assertJson($string, $message = '')
{
self::assertThat($string, self::isJson(), $message);
}
/**
* Assert that string is not a valid JSON
*
* @param string $string
* @param string $message
*/
public static function assertNotJson($string, $message = '')
{
self::assertThat($string, self::logicalNot(self::isJson()), $message);
}
/**
* Assert that JSON string matches expected value,
* Can accept different match type for matching logic.
*
* @param string $string
* @param array $expectedValue
* @param string $message
* @param strign $matchType
*/
public static function assertJsonMatch($string, array $expectedValue, $message = '',
$matchType = EcomDev_PHPUnit_Constraint_Json::MATCH_AND)
{
self::assertThat(
$string,
self::matchesJson($expectedValue, $matchType),
$message
);
}
/**
* Assert that JSON string doesn't matches expected value,
* Can accept different match type for matching logic.
*
* @param string $string
* @param array $expectedValue
* @param string $message
* @param strign $matchType
*/
public static function assertJsonNotMatch($string, array $expectedValue, $message = '',
$matchType = EcomDev_PHPUnit_Constraint_Json::MATCH_AND)
{
self::assertThat(
$string,
self::logicalNot(
self::matchesJson($expectedValue, $matchType)
),
$message
);
}
/**
* Retrieves the module name for current test case
......@@ -64,7 +240,7 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
*/
public function getModuleName()
{
return Mage::app()->getModuleNameByClassName($this);
return $this->app()->getModuleNameByClassName($this);
}
/**
......@@ -155,10 +331,10 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
}
if (in_array($type, array('model', 'resource_model'))) {
Mage::getConfig()->replaceInstanceCreation($type, $classAlias, $mock);
$this->app()->getConfig()->replaceInstanceCreation($type, $classAlias, $mock);
$type = str_replace('model', 'singleton', $type);
} elseif ($type == 'block') {
Mage::app()->getLayout()->replaceBlockCreation($classAlias, $mock);
$this->app()->getLayout()->replaceBlockCreation($classAlias, $mock);
}
if (in_array($type, array('singleton', 'resource_singleton', 'helper'))) {
......@@ -178,7 +354,8 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
protected function replaceRegistry($key, $value)
{
$oldValue = Mage::registry($key);
Mage::register($key, $value, true);
$this->app()->replaceRegistry($key, $value);
$this->_replacedRegistry[$key] = $oldValue;
return $this;
......@@ -291,7 +468,7 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
$mockClassAlias = '', $callOriginalConstructor = true,
$callOriginalClone = true, $callAutoload = true)
{
return $this->getGroupedClassMock('model', $methods, $isAbstract,
return $this->getGroupedClassMock('model', $classAlias, $methods, $isAbstract,
$constructorArguments, $mockClassAlias,
$callOriginalConstructor, $callOriginalClone,
$callAutoload);
......@@ -315,7 +492,7 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
$mockClassAlias = '', $callOriginalConstructor = true,
$callOriginalClone = true, $callAutoload = true)
{
return $this->getGroupedClassMock('resource_model', $methods, $isAbstract,
return $this->getGroupedClassMock('resource_model', $classAlias, $methods, $isAbstract,
$constructorArguments, $mockClassAlias,
$callOriginalConstructor, $callOriginalClone,
$callAutoload);
......@@ -339,7 +516,7 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
$mockClassAlias = '', $callOriginalConstructor = true,
$callOriginalClone = true, $callAutoload = true)
{
return $this->getGroupedClassMock('helper', $methods, $isAbstract,
return $this->getGroupedClassMock('helper', $classAlias, $methods, $isAbstract,
$constructorArguments, $mockClassAlias,
$callOriginalConstructor, $callOriginalClone,
$callAutoload);
......@@ -363,7 +540,7 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
$mockClassAlias = '', $callOriginalConstructor = true,
$callOriginalClone = true, $callAutoload = true)
{
return $this->getGroupedClassMock('block', $methods, $isAbstract,
return $this->getGroupedClassMock('block', $classAlias, $methods, $isAbstract,
$constructorArguments, $mockClassAlias,
$callOriginalConstructor, $callOriginalClone,
$callAutoload);
......@@ -378,10 +555,10 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
protected function getGroupedClassName($type, $classAlias)
{
if ($type === 'resource_model') {
return Mage::getConfig()->getResourceModelClassName($classAlias);
return $this->app()->getConfig()->getResourceModelClassName($classAlias);
}
return Mage::getConfig()->getGroupedClassName($type, $classAlias);
return $this->app()->getConfig()->getGroupedClassName($type, $classAlias);
}
/**
......@@ -398,7 +575,7 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
* @param boolean $callAutoload
* @return PHPUnit_Framework_MockObject_MockObject
*/
public function getGroupedClassMock($type, $classAlias, $methods = array(), $isAbstract = false,
public function getGroupedClassMock($type, $classAlias, array $methods = array(), $isAbstract = false,
array $constructorArguments = array(),
$mockClassAlias = '', $callOriginalConstructor = true,
$callOriginalClone = true, $callAutoload = true)
......@@ -486,7 +663,7 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
if (current($annotationValue)) {
$classAlias = current($annotationValue);
} else {
$classAlias = Mage::getConfig()->getNode($configPath);
$classAlias = $this->app()->getConfig()->getNode($configPath);
}
return $classAlias;
......@@ -554,6 +731,7 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
$annotations = $this->getAnnotations();
$this->getFixture()->setOptions($annotations['method']);
$this->getFixture()->apply();
$this->app()->resetDispatchedEvents();
parent::setUp();
}
......@@ -586,11 +764,11 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
public function setCurrentStore($store)
{
if (!$this->_originalStore) {
$this->_originalStore = Mage::app()->getStore();
$this->_originalStore = $this->app()->getStore();
}
Mage::app()->setCurrentStore(
Mage::app()->getStore($store)
$this->app()->setCurrentStore(
$this->app()->getStore($store)
);
return $this;
}
......@@ -603,7 +781,7 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
protected function tearDown()
{
if ($this->_originalStore) { // Remove store scope, that was set in test
Mage::app()->setCurrentStore($this->_originalStore);
$this->app()->setCurrentStore($this->_originalStore);
$this->_originalStore = null;
}
......@@ -611,12 +789,11 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
$this->getExpectation()->discard();
}
Mage::getConfig()->flushReplaceInstanceCreation();
Mage::app()->getLayout()->reset();
$this->app()->getConfig()->flushReplaceInstanceCreation();
$this->app()->getLayout()->flushReplaceBlockCreation();
foreach ($this->_replacedRegistry as $registryPath => $originalValue) {
Mage::register($registryPath, $originalValue, true);
$this->app()->replaceRegistry($registryPath, $originalValue);
}
$this->getFixture()->discard(); // Clear applied fixture
......
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Base for controller test case
*
*/
abstract class EcomDev_PHPUnit_Test_Case_Controller extends EcomDev_PHPUnit_Test_Case
{
/**
* Cookies container
*
* @var Zend_Http_CookieJar
*/
protected static $_cookies = null;
/**
* Returns cookies container,
* that processes them
*
* @return Zend_Http_CookieJar
*/
protected static function getCookies()
{
if (self::$_cookies === null) {
self::$_cookies = new Zend_Http_CookieJar();
}
return self::$_cookies;
}
/**
* Returns request object
*
* @return EcomDev_PHPUnit_Controller_Request_Http
*/
protected static function getRequest()
{
return self::app()->getRequest();
}
/**
* Returns response object
*
* @return EcomDev_PHPUnit_Controller_Response_Http
*/
protected static function getResponse()
{
return self::app()->getResponse();
}
/**
* Returns layout model
*
* @return EcomDev_PHPUnit_Model_Layout
*/
protected static function getLayout()
{
return self::app()->getLayout();
}
/**
* Layout main functions constraint
*
* @param string $type
* @return EcomDev_PHPUnit_Constraint_Layout
*/
public static function layout($type)
{
return new EcomDev_PHPUnit_Constraint_Layout($type);
}
/**
* Layout handle functionality constaint
*
* @param string $handle handle name
* @param string $type
* @param string|null $position another handle for position check
* @return EcomDev_PHPUnit_Constraint_Layout_Handle
*/
public static function layoutHandle($handle, $type, $position = null)
{
return new EcomDev_PHPUnit_Constraint_Layout_Handle($handle, $type, $position);
}
/**
* Layout block functionality constraint
*
* @param string $blockName
* @param string $type
* @param string|null $expectedValue
* @return EcomDev_PHPUnit_Constraint_Layout_Block
*/
public static function layoutBlock($blockName, $type, $expectedValue = null)
{
return new EcomDev_PHPUnit_Constraint_Layout_Block($blockName, $type, $expectedValue);
}
/**
* Layout block action calls functionality constaint
*
* @param string $blockName
* @param string $method
* @param string $type
* @param int|null $invocationCount
* @param array|null $arguments
* @param string $searchType
* @return EcomDev_PHPUnit_Constraint_Layout_Block_Action
*/
public static function layoutBlockAction($blockName, $method, $type, $invocationCount = null,
array $arguments = null, $searchType = EcomDev_PHPUnit_Constraint_Layout_Block_Action::SEARCH_TYPE_AND)
{
return new EcomDev_PHPUnit_Constraint_Layout_Block_Action(
$blockName, $method, $type, $invocationCount, $arguments, $searchType
);
}
/**
* Layout block property constraint creation
*
* @param string $blockName
* @param string $propertyName
* @param PHPUnit_Framework_Constraint $constraint
* @return EcomDev_PHPUnit_Constraint_Layout_Block_Property
*/
public static function layoutBlockProperty($blockName, $propertyName, PHPUnit_Framework_Constraint $constraint)
{
return new EcomDev_PHPUnit_Constraint_Layout_Block_Property($blockName, $propertyName, $constraint);
}
/**
* Controller request constraint creation
*
*
* @param string $type
* @param string|null $expectedValue
* @return string
*/
public static function request($type, $expectedValue = null)
{
return new EcomDev_PHPUnit_Constraint_Controller_Request($type, $expectedValue);
}
/**
* Controller response header constraint creation
*
* @param string $type
* @param string $headerName
* @param PHPUnit_Framework_Constraint|null $constraint
* @return string
*/
public static function responseHeader($headerName, $type, PHPUnit_Framework_Constraint $constraint = null)
{
return new EcomDev_PHPUnit_Constraint_Controller_Response_Header($headerName, $type, $constraint);
}
/**
* Controller response body constraint creation
*
* @param PHPUnit_Framework_Constraint $constraint
* @return string
*/
public static function responseBody(PHPUnit_Framework_Constraint $constraint)
{
return new EcomDev_PHPUnit_Constraint_Controller_Response_Body($constraint);
}
/**
* Assert that controller request matches assertion type
*
* @param string $type type of assertion
* @param string|null $expectedValue
* @param string $message
*/
public static function assertRequest($type, $expectedValue = null, $message = '')
{
self::assertThat(
self::getRequest(),
self::request($type, $expectedValue),
$message
);
}
/**
* Assert that controller request doesn't matches assertion type
*
* @param string $type type of assertion
* @param string|null $expectedValue
* @param string $message
*/
public static function assertRequestNot($type, $expectedValue = null, $message = '')
{
self::assertThat(
self::getRequest(),
self::logicalNot(
self::request($type, $expectedValue)
),
$message
);
}
/**
* Assert that controller request is dispatched
*
* @param string $message
*/
public static function assertRequestDispatched($message = '')
{
self::assertRequest(
EcomDev_PHPUnit_Constraint_Controller_Request::TYPE_DISPATCHED,
null, $message
);
}
/**
* Assert that controller request is not dispatched
*
* @param string $message
*/
public static function assertRequestNotDispatched($message = '')
{
self::assertRequestNot(
EcomDev_PHPUnit_Constraint_Controller_Request::TYPE_DISPATCHED,
null, $message
);
}
/**
* Assert that controller request is forwarded
*
* @param string $message
*/
public static function assertRequestForwarded($message = '')
{
self::assertRequest(
EcomDev_PHPUnit_Constraint_Controller_Request::TYPE_FORWARDED,
null, $message
);
}
/**
* Assert that controller request is not forwarded
*
* @param string $message
*/
public static function assertRequestNotForwarded($message = '')
{
self::assertRequestNot(
EcomDev_PHPUnit_Constraint_Controller_Request::TYPE_FORWARDED,
null, $message
);
}
/**
* Asserts that current request route is matched expected one
*
* @param string $expectedRoute
* @param string $message
*/
public static function assertRequestRoute($expectedRoute, $message = '')
{
self::assertRequest(
EcomDev_PHPUnit_Constraint_Controller_Request::TYPE_ROUTE,
$expectedRoute, $message
);
}
/**
* Asserts that current request route is not matched expected one
*
* @param string $expectedRoute
* @param string $message
*/
public static function assertRequestRouteNot($expectedRoute, $message = '')
{
self::assertRequestNot(
EcomDev_PHPUnit_Constraint_Controller_Request::TYPE_ROUTE,
$expectedRoute, $message
);
}
/**
* Asserts that current request route name is the same as expected
*
* @param string $expectedRouteName
* @param string $message
*/
public static function assertRequestRouteName($expectedRouteName, $message = '')
{
self::assertRequest(
EcomDev_PHPUnit_Constraint_Controller_Request::TYPE_ROUTE_NAME,
$expectedRouteName, $message
);
}
/**
* Asserts that current request route name is not the same as expected
*
* @param string $expectedRouteName
* @param string $message
*/
public static function assertRequestRouteNameNot($expectedRouteName, $message = '')
{
self::assertRequestNot(
EcomDev_PHPUnit_Constraint_Controller_Request::TYPE_ROUTE_NAME,
$expectedRouteName, $message
);
}
/**
* Asserts that current request controller name is the same as expected
*
* @param string $expectedControllerName
* @param string $message
*/
public static function assertRequestControllerName($expectedControllerName, $message = '')
{
self::assertRequest(
EcomDev_PHPUnit_Constraint_Controller_Request::TYPE_CONTROLLER_NAME,
$expectedControllerName, $message
);
}
/**
* Asserts that current request controller name is not the same as expected
*
* @param string $expectedControllerName
* @param string $message
*/
public static function assertRequestControllerNameNot($expectedControllerName, $message = '')
{
self::assertRequestNot(
EcomDev_PHPUnit_Constraint_Controller_Request::TYPE_CONTROLLER_NAME,
$expectedControllerName, $message
);
}
/**
* Asserts that current request controller module is the same as expected
*
* @param string $expectedControllerModule
* @param string $message
*/
public static function assertRequestControllerModule($expectedControllerModule, $message = '')
{
self::assertRequest(
EcomDev_PHPUnit_Constraint_Controller_Request::TYPE_CONTROLLER_MODULE,
$expectedControllerModule, $message
);
}
/**
* Asserts that current request controller name is not the same as expected
*
* @param string $expectedControllerModule
* @param string $message
*/
public static function assertRequestControllerModuleNot($expectedControllerModule, $message = '')
{
self::assertRequestNot(
EcomDev_PHPUnit_Constraint_Controller_Request::TYPE_CONTROLLER_MODULE,
$expectedControllerModule, $message
);
}
/**
* Asserts that current request action name is the same as expected
*
* @param string $expectedActionName
* @param string $message
*/
public static function assertRequestActionName($expectedActionName, $message = '')
{
self::assertRequest(
EcomDev_PHPUnit_Constraint_Controller_Request::TYPE_ACTION_NAME,
$expectedActionName, $message
);
}
/**
* Asserts that current request action name is not the same as expected
*
* @param string $expectedActionName
* @param string $message
*/
public static function assertRequestActionNameNot($expectedActionName, $message = '')
{
self::assertRequestNot(
EcomDev_PHPUnit_Constraint_Controller_Request::TYPE_ACTION_NAME,
$expectedActionName, $message
);
}
/**
* Asserts that current request before forwarded route is matched expected
*
* @param string $expectedBeforeForwardedRoute
* @param string $message
*/
public static function assertRequestBeforeForwardedRoute($expectedBeforeForwardedRoute, $message = '')
{
self::assertRequest(
EcomDev_PHPUnit_Constraint_Controller_Request::TYPE_BEFORE_FORWARD_ROUTE,
$expectedBeforeForwardedRoute, $message
);
}
/**
* Asserts that current request before forwarded route is not matched expected
*
* @param string $expectedBeforeForwardedRoute
* @param string $message
*/
public static function assertRequestBeforeForwardedRouteNot($expectedBeforeForwardedRoute, $message = '')
{
self::assertRequestNot(
EcomDev_PHPUnit_Constraint_Controller_Request::TYPE_BEFORE_FORWARD_ROUTE,
$expectedActionName, $message
);
}
/**
* Assert shortcut for response assertions
*
* @param EcomDev_PHPUnit_Constraint_Controller_Response_Header $constraint
* @param string $message
*/
public static function assertThatResponse(EcomDev_PHPUnit_Constraint_Controller_Response_Header $constraint, $message)
{
self::assertThat(self::getResponse(), $constraint, $message);
}
/**
* Assert that response header is sent
*
* @param string $headerName
* @param string $message
*/
public static function assertResponseHeaderSent($headerName, $message = '')
{
self::assertThatResponse(
self::responseHeader(
$headerName,
EcomDev_PHPUnit_Constraint_Controller_Response_Header::TYPE_SENT
),
$message
);
}
/**
* Assert that response header is not sent
*
* @param string $headerName
* @param string $message
*/
public static function assertResponseHeaderNotSent($headerName, $message = '')
{
self::assertThatResponse(
self::logicalNot(
self::responseHeader(
$headerName,
EcomDev_PHPUnit_Constraint_Controller_Response_Header::TYPE_SENT
)
),
$message
);
}
/**
* Assert that response header is evaluated by a specified constraint
*
* @param string $headerName
* @param PHPUnit_Framework_Constraint $constraint
* @param string $message
*/
public static function assertResponseHeader($headerName, PHPUnit_Framework_Constraint $constraint, $message = '')
{
self::assertThatResponse(
self::responseHeader(
$headerName,
EcomDev_PHPUnit_Constraint_Controller_Response_Header::TYPE_CONSTRAINT,
$constraint
),
$message
);
}
/**
* Assert that response header is not evaluated by a specified constraint
*
* @param string $headerName
* @param PHPUnit_Framework_Constraint $constraint
* @param string $message
*/
public static function assertResponseHeaderNot($headerName, PHPUnit_Framework_Constraint $constraint, $message = '')
{
self::assertThatResponse(
self::responseHeader(
$headerName,
EcomDev_PHPUnit_Constraint_Controller_Response_Header::TYPE_CONSTRAINT,
self::logicalNot($constraint)
),
$message
);
}
/**
* Assert that response header is equal to expected value
*
* @param string $headerName
* @param mixed $expectedValue
* @param string $message
* @param float $delta
* @param integer $maxDepth
* @param boolean $canonicalize
* @param boolean $ignoreCase
*/
public static function assertResponseHeaderEquals($headerName, $expectedValue, $message = '',
$delta = 0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false)
{
self::assertResponseHeader(
$headerName,
self::equalTo($expectedValue, $delta, $maxDepth, $canonicalize, $ignoreCase),
$message
);
}
/**
* Assert that response header is not equal to expected value
*
* @param string $headerName
* @param mixed $expectedValue
* @param string $message
* @param float $delta
* @param integer $maxDepth
* @param boolean $canonicalize
* @param boolean $ignoreCase
*/
public static function assertResponseHeaderNotEquals($headerName, $expectedValue, $message = '',
$delta = 0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false)
{
self::assertResponseHeaderNot(
$headerName,
self::equalTo($expectedValue, $delta, $maxDepth, $canonicalize, $ignoreCase),
$message
);
}
/**
* Assert that response header is the same as expected value
*
* @param string $headerName
* @param mixed $expectedValue
* @param string $message
*/
public static function assertResponseHeaderSame($headerName, $expectedValue, $message = '')
{
self::assertResponseHeader(
$headerName,
self::identicalTo($expectedValue),
$message
);
}
/**
* Assert that response header is not the same as expected value
*
* @param string $headerName
* @param mixed $expectedValue
* @param string $message
*/
public static function assertResponseHeaderNotSame($headerName, $expectedValue, $message = '')
{
self::assertResponseHeaderNot(
$headerName,
self::identicalTo($expectedValue),
$message
);
}
/**
* Assert that response header contains expected string value
*
* @param string $headerName
* @param string $expectedValue
* @param string $message
* @param boolean $ignoreCase
*/
public static function assertResponseHeaderContains($headerName, $expectedValue, $message = '', $ignoreCase = true)
{
self::assertResponseHeader(
$headerName,
self::stringContains($expectedValue, $ignoreCase),
$message
);
}
/**
* Assert that response header doesn't contain expected string value
*
* @param string $headerName
* @param string $expectedValue
* @param string $message
* @param boolean $ignoreCase
*/
public static function assertResponseHeaderNotContains($headerName, $expectedValue, $message = '', $ignoreCase = true)
{
self::assertResponseHeaderNot(
$headerName,
self::stringContains($expectedValue, $ignoreCase),
$message
);
}
/**
* Assert that response header matches specified PCRE pattern
*
* @param string $headerName
* @param string $pcrePattern
* @param string $message
* @param boolean $ignoreCase
*/
public static function assertResponseHeaderRegExp($headerName, $pcrePattern, $message = '')
{
self::assertResponseHeader(
$headerName,
self::matchesRegularExpression($pcrePattern),
$message
);
}
/**
* Assert that response header doesn't match specified PCRE pattern
*
* @param string $headerName
* @param string $pcrePattern
* @param string $message
* @param boolean $ignoreCase
*/
public static function assertResponseHeaderNotRegExp($headerName, $pcrePattern, $message = '')
{
self::assertResponseHeaderNot(
$headerName,
self::matchesRegularExpression($pcrePattern),
$message
);
}
/**
* Assert that response body is evaluated by the constraint
*
* @param PHPUnit_Framework_Constraint $constraint
* @param string $message
*/
public static function assertResponseBody(PHPUnit_Framework_Constraint $constraint, $message = '')
{
self::assertThatResponse(
self::responseBody($constraint),
$message
);
}
/**
* Assert that response body is not evaluated by the constraint
*
* @param PHPUnit_Framework_Constraint $constraint
* @param string $message
*/
public static function assertResponseBodyNot(PHPUnit_Framework_Constraint $constraint, $message = '')
{
self::assertThatResponse(
self::logicalNot(
self::responseBody($constraint)
),
$message
);
}
/**
* Assert that response body contains expected string
*
* @param string $expectedValue
* @param string $message
* @param boolean $ignoreCase
*/
public static function assertResponseBodyContains($expectedValue, $message = '', $ignoreCase = true)
{
self::assertResponseBody(
self::stringContains($expectedValue, $ignoreCase),
$message
);
}
/**
* Assert that response body doen't contain expected string
*
* @param string $expectedValue
* @param string $message
* @param boolean $ignoreCase
*/
public static function assertResponseBodyNotContains($expectedValue, $message = '', $ignoreCase = true)
{
self::assertResponseBodyNot(
self::stringContains($expectedValue, $ignoreCase),
$message
);
}
/**
* Assert that response body is matched by PCRE pattern
*
* @param string $pcrePattern
* @param string $message
*/
public static function assertResponseBodyRegExp($pcrePattern, $message = '')
{
self::assertResponseBody(
self::matchesRegularExpression($pcrePattern),
$message
);
}
/**
* Assert that response body is not matched by PCRE pattern
*
* @param string $pcrePattern
* @param string $message
*/
public static function assertResponseBodyNotRegExp($pcrePattern, $message = '')
{
self::assertResponseBodyNot(
self::matchesRegularExpression($pcrePattern),
$message
);
}
/**
* Assert that response body is valid JSON string
*
* @param string $message
*/
public static function assertResponseBodyJson($message = '')
{
self::assertResponseBody(
self::isJson(),
$message
);
}
/**
* Assert that response body is not valid JSON string
*
* @param string $message
*/
public static function assertResponseBodyNotJson($message = '')
{
self::assertResponseBody(
self::logicalNot(self::isJson()),
$message
);
}
/**
* Assert that response body is JSON and matches expected value,
* Can accept different match type for matching logic.
*
* @param array $expectedValue
* @param string $message
* @param strign $matchType
*/
public static function assertResponseBodyJsonMatch(array $expectedValue, $message = '',
$matchType = EcomDev_PHPUnit_Constraint_Json::MATCH_AND)
{
self::assertResponseBodyJson($message);
self::assertResponseBody(
self::matchesJson($expectedValue, $matchType),
$message
);
}
/**
* Assert that response body is JSON and not matches expected value,
* Can accept different match type for matching logic.
*
* @param array $expectedValue
* @param string $message
* @param strign $matchType
*/
public static function assertResponseBodyJsonNotMatch(array $expectedValue, $message = '',
$matchType = EcomDev_PHPUnit_Constraint_Json::MATCH_AND)
{
self::assertResponseBodyJson($message);
self::assertResponseBodyNot(
self::matchesJson($expectedValue, $matchType),
$message
);
}
/**
* Assert HTTP response code value
*
* @param int $code
*/
public static function assertResponseHttpCode($code, $message = '')
{
self::assertEquals(
$code,
self::getResponse()->getHttpResponseCode(),
$message
. sprintf("\nFailed asserting that response code is equal to %d", $code)
);
}
/**
* Assert that controller response is redirect
*
* @param string $message
* @param int|null $code
*/
public static function assertRedirect($message = '', $responseCode = null)
{
self::assertTrue(
self::getResponse()->isRedirect(),
$message . "\nFailed asserting that response is redirect"
);
if ($responseCode !== null) {
self::assertResponseHttpCode($responseCode, $message);
}
}
/**
* Assert that controller response is not redirect
*
* @param string $message
*/
public static function assertNotRedirect($message = '')
{
self::assertFalse(
self::getResponse()->isRedirect(),
$message . "\nFailed asserting that response is not redirect"
);
}
/**
* Assert that constroller response is a redirect
* to a specific url
*
* @param string $route route path
* @param string $params route params
* @param string $message
*/
public static function assertRedirectTo($route, array $params = array(), $message = '')
{
if (!isset($params['_store']) && strpos($route, EcomDev_PHPUnit_Model_App::AREA_ADMINHTML) !== false) {
$params['_store'] = EcomDev_PHPUnit_Model_App::ADMIN_STORE_CODE;
}
if ($params['_store'] === EcomDev_PHPUnit_Model_App::ADMIN_STORE_CODE) {
$urlModel = Mage::getModel('adminhtml/url');
} else {
$urlModel = Mage::getModel('core/url');
}
$url = $urlModel->getUrl($route, $params);
self::assertRedirectToUrl($url, $message);
}
/**
* Assert that constroller response redirect is equal
* to a specific url
*
* @param string $url
* @param string $message
*/
public static function assertRedirectToUrl($url, $message = '')
{
self::assertRedirect($message);
self::assertResponseHeaderEquals('Location', $url, $message);
}
/**
* Assert that constroller response redirect url
* starts with expected url part
*
* @param string $urlPart
* @param string $message
*/
public static function assertRedirectToUrlStartsWith($urlPart, $message = '')
{
self::assertRedirect($message);
self::assertResponseHeader('Location',
self::stringStartsWith($urlPart),
$message
);
}
/**
* Assert that constroller response redirect url
* contains expected url part
*
* @param string $urlPart
* @param string $message
*/
public static function assertRedirectToUrlContains($urlPart, $message = '')
{
self::assertRedirect($message);
self::assertResponseHeaderContains('Location', $urlPart, $message);
}
/**
* Assert that constroller response redirect url matches PRCE pattern
*
* @param string $pcrePattern route path
* @param string $message
*/
public static function assertRedirectToUrlRegExp($pcrePattern, $message = '')
{
self::assertRedirect($message);
self::assertResponseHeaderRegExp('Location', $pcrePattern, $message);
}
/**
* Assert shortcut for layout constaints
*
* @param EcomDev_PHPUnit_Constraint_Layout_Abstract|PHPUnit_Framework_Constraint $constaint
* @param string $message
*/
public static function assertThatLayout(PHPUnit_Framework_Constraint $constraint, $message)
{
self::assertThat(self::getLayout(), $constraint, $message);
}
/**
* Assert that layout is loaded
*
* @param string $message
*/
public static function assertLayoutLoaded($message = '')
{
self::assertThatLayout(
self::layout(EcomDev_PHPUnit_Constraint_Layout::TYPE_LOADED),
$message
);
}
/**
* Assert that layout is not loaded
*
* @param string $message
*/
public static function assertLayoutNotLoaded($message = '')
{
self::assertThatLayout(
self::logicalNot(
self::layout(EcomDev_PHPUnit_Constraint_Layout::TYPE_LOADED)
),
$message
);
}
/**
* Assert that layout is rendered
*
* @param string $message
*/
public static function assertLayoutRendered($message = '')
{
self::assertThatLayout(
self::layout(EcomDev_PHPUnit_Constraint_Layout::TYPE_RENDERED),
$message
);
}
/**
* Assert that layout is not rendered
*
* @param string $message
*/
public static function assertLayoutNotRendered($message = '')
{
self::assertThatLayout(
self::logicalNot(
self::layout(EcomDev_PHPUnit_Constraint_Layout::TYPE_RENDERED)
),
$message
);
}
/**
* Assert that layout handle is loaded into layout updates
*
*
* @param string $handle
* @param string $message
*/
public static function assertLayoutHandleLoaded($handle, $message = '')
{
self::assertThatLayout(
self::layoutHandle(
$handle, EcomDev_PHPUnit_Constraint_Layout_Handle::TYPE_LOADED
),
$message
);
}
/**
* Assert that layout handle is not loaded into layout updates
*
*
* @param string $handle
* @param string $message
*/
public static function assertLayoutHandleNotLoaded($handle, $message = '')
{
self::assertThatLayout(
self::logicalNot(
self::layoutHandle(
$handle, EcomDev_PHPUnit_Constraint_Layout_Handle::TYPE_LOADED
)
),
$message
);
}
/**
* Assert that layout handle is loaded into layout updates after expected one
*
*
* @param string $handle
* @param string $message
*/
public static function assertLayoutHandleLoadedAfter($handle, $after, $message = '')
{
self::assertLayoutHandleLoaded($handle);
self::assertThatLayout(
self::layoutHandle(
$handle, EcomDev_PHPUnit_Constraint_Layout_Handle::TYPE_LOADED_AFTER,
$after
),
$message
);
}
/**
* Assert that layout handle is loaded into layout updates after expected one
*
*
* @param string $handle
* @param string $message
*/
public static function assertLayoutHandleLoadedBefore($handle, $before, $message = '')
{
self::assertLayoutHandleLoaded($handle);
self::assertThatLayout(
self::layoutHandle(
$handle, EcomDev_PHPUnit_Constraint_Layout_Handle::TYPE_LOADED_BEFORE,
$before
),
$message
);
}
/**
* Assert that layout block is created via layout file
*
*
* @param string $blockName
* @param string $message
*/
public static function assertLayoutBlockCreated($blockName, $message = '')
{
self::assertThatLayout(
self::layoutBlock(
$blockName, EcomDev_PHPUnit_Constraint_Layout_Block::TYPE_CREATED
),
$message
);
}
/**
* Assert that layout block is removed via layout file
*
* @param string $blockName
* @param string $message
*/
public static function assertLayoutBlockRemoved($blockName, $message = '')
{
self::assertThatLayout(
self::layoutBlock(
$blockName, EcomDev_PHPUnit_Constraint_Layout_Block::TYPE_REMOVED
),
$message
);
}
/**
* Assert that layout block is rendered
*
* @param string $blockName
* @param string $message
*/
public static function assertLayoutBlockRendered($blockName, $message = '')
{
self::assertThatLayout(
self::layoutBlock(
$blockName, EcomDev_PHPUnit_Constraint_Layout_Block::TYPE_RENDERED
),
$message
);
}
/**
* Assert that layout block is not rendered
*
* @param string $blockName
* @param string $message
*/
public static function assertLayoutBlockNotRendered($blockName, $message = '')
{
self::assertThatLayout(
self::logicalNot(
self::layoutBlock(
$blockName, EcomDev_PHPUnit_Constraint_Layout_Block::TYPE_RENDERED
)
),
$message
);
}
/**
* Assert that layout block rendered content is evaluated by constraint
*
* @param string $blockName
* @param PHPUnit_Framework_Constraint $constraint
* @param string $message
*/
public static function assertLayoutBlockRenderedContent($blockName,
PHPUnit_Framework_Constraint $constraint, $message = '')
{
self::assertThatLayout(
self::layoutBlock(
$blockName,
EcomDev_PHPUnit_Constraint_Layout_Block::TYPE_RENDERED,
$constraint
),
$message
);
}
/**
* Assert that layout block rendered content is not evaluated by constraint
*
* @param string $blockName
* @param PHPUnit_Framework_Constraint $constraint
* @param string $message
*/
public static function assertLayoutBlockRenderedContentNot($blockName,
PHPUnit_Framework_Constraint $constraint, $message = '')
{
self::assertThatLayout(
self::layoutBlock(
$blockName,
EcomDev_PHPUnit_Constraint_Layout_Block::TYPE_RENDERED,
self::logicalNot($constraint)
),
$message
);
}
/**
* Assert that layout block type is a type of expected class alias
*
* @param string $blockName
* @param string $classAlias
* @param string $message
*/
public static function assertLayoutBlockTypeOf($blockName, $classAlias, $message = '')
{
self::assertThatLayout(
self::layoutBlock(
$blockName,
EcomDev_PHPUnit_Constraint_Layout_Block::TYPE_TYPE,
$classAlias
),
$message
);
}
/**
* Assert that layout block type is not a type of expected class alias
*
* @param string $blockName
* @param string $classAlias
* @param string $message
*/
public static function assertLayoutBlockNotTypeOf($blockName, $classAlias, $message = '')
{
self::assertThatLayout(
self::logicalNot(
self::layoutBlock(
$blockName,
EcomDev_PHPUnit_Constraint_Layout_Block::TYPE_TYPE,
$classAlias
)
),
$message
);
}
/**
* Assert that layout block type is an instance of expected class
*
* @param string $blockName
* @param string $className
* @param string $message
*/
public static function assertLayoutBlockInstanceOf($blockName, $className, $message = '')
{
self::assertThatLayout(
self::layoutBlock(
$blockName,
EcomDev_PHPUnit_Constraint_Layout_Block::TYPE_INSTANCE_OF,
$className
),
$message
);
}
/**
* Assert that layout block type is an instance of expected class
*
* @param string $blockName
* @param string $className
* @param string $message
*/
public static function assertLayoutBlockNotInstanceOf($blockName, $className, $message = '')
{
self::assertThatLayout(
self::logicalNot(
self::layoutBlock(
$blockName,
EcomDev_PHPUnit_Constraint_Layout_Block::TYPE_INSTANCE_OF,
$className
)
),
$message
);
}
/**
* Assert that layout block parent is equal to expected
*
* @param string $blockName
* @param string $parentBlockName
* @param string $message
*/
public static function assertLayoutBlockParentEquals($blockName, $parentBlockName, $message = '')
{
self::assertThatLayout(
self::layoutBlock(
$blockName,
EcomDev_PHPUnit_Constraint_Layout_Block::TYPE_PARENT_NAME,
$parentBlockName
),
$message
);
}
/**
* Assert that layout block parent is not equal to expected
*
* @param string $blockName
* @param string $parentBlockName
* @param string $message
*/
public static function assertLayoutBlockParentNotEquals($blockName, $parentBlockName, $message = '')
{
self::assertThatLayout(
self::logicalNot(
self::layoutBlock(
$blockName,
EcomDev_PHPUnit_Constraint_Layout_Block::TYPE_PARENT_NAME,
$parentBlockName
)
),
$message
);
}
/**
* Assert that layout block is placed after expected
*
* @param string $blockName
* @param string $after
* @param string $message
*/
public static function assertLayoutBlockAfter($blockName, $after, $message = '')
{
self::assertThatLayout(
self::layoutBlock(
$blockName,
EcomDev_PHPUnit_Constraint_Layout_Block::TYPE_AFTER,
$after
),
$message
);
}
/**
* Assert that layout block is placed before expected
*
* @param string $blockName
* @param string $before
* @param string $message
*/
public static function assertLayoutBlockBefore($blockName, $before, $message = '')
{
self::assertThatLayout(
self::layoutBlock(
$blockName,
EcomDev_PHPUnit_Constraint_Layout_Block::TYPE_BEFORE,
$before
),
$message
);
}
/**
* Assert that layout block is placed after all expected ones
*
* @param string $blockName
* @param array $after
* @param string $message
*/
public static function assertLayoutBlockAfterAll($blockName, array $after, $message = '')
{
$constaints = array();
foreach ($after as $value) {
$constaints[] = self::layoutBlock(
$blockName, EcomDev_PHPUnit_Constraint_Layout_Block::TYPE_AFTER, $value
);
}
$logicalAnd = new PHPUnit_Framework_Constraint_And();
$logicalAnd->setConstraints($constaints);
self::assertThatLayout($logicalAnd, $message);
}
/**
* Assert that layout block is placed after all expected ones
*
* @param string $blockName
* @param array $after
* @param string $message
*/
public static function assertLayoutBlockBeforeAll($blockName, array $before, $message = '')
{
$constaints = array();
foreach ($before as $value) {
$constaints[] = self::layoutBlock(
$blockName, EcomDev_PHPUnit_Constraint_Layout_Block::TYPE_BEFORE, $value
);
}
$logicalAnd = new PHPUnit_Framework_Constraint_And();
$logicalAnd->setConstraints($constaints);
self::assertThatLayout($logicalAnd, $message);
}
/**
* Assert that layout block type is on the root rendering level
*
* @param string $blockName
* @param string $message
*/
public static function assertLayoutBlockRootLevel($blockName, $message = '')
{
self::assertThatLayout(
self::layoutBlock(
$blockName,
EcomDev_PHPUnit_Constraint_Layout_Block::TYPE_ROOT_LEVEL
),
$message
);
}
/**
* Assert that layout block type is not on the root rendering level
*
* @param string $blockName
* @param string $message
*/
public static function assertLayoutBlockNotRootLevel($blockName, $message = '')
{
self::assertThatLayout(
self::logicalNot(
self::layoutBlock(
$blockName,
EcomDev_PHPUnit_Constraint_Layout_Block::TYPE_ROOT_LEVEL
)
),
$message
);
}
/**
* Assert that layout block action was invoked
*
*
* @param string $blockName
* @param string $method
* @param string $message
* @param array|null $params
* @param string $searchType
*/
public static function assertLayoutBlockActionInvoked($blockName, $method, $message = '',
array $arguments = null, $searchType = EcomDev_PHPUnit_Constraint_Layout_Block_Action::SEARCH_TYPE_AND)
{
self::assertThatLayout(
self::layoutBlockAction(
$blockName, $method,
EcomDev_PHPUnit_Constraint_Layout_Block_Action::TYPE_INVOKED, null,
$arguments, $searchType
),
$message
);
}
/**
* Assert that layout block action was not invoked
*
*
* @param string $blockName
* @param string $method
* @param string $message
* @param array|null $params
* @param string $searchType
*/
public static function assertLayoutBlockActionNotInvoked($blockName, $method, $message = '',
array $arguments = null, $searchType = EcomDev_PHPUnit_Constraint_Layout_Block_Action::SEARCH_TYPE_AND)
{
self::assertThatLayout(
self::logicalNot(
self::layoutBlockAction(
$blockName, $method,
EcomDev_PHPUnit_Constraint_Layout_Block_Action::TYPE_INVOKED, null,
$arguments, $searchType
)
),
$message
);
}
/**
* Assert that layout block action was invoked at least expected number of times
*
*
* @param string $blockName
* @param string $method
* @param string $message
* @param array|null $params
* @param string $searchType
*/
public static function assertLayoutBlockActionInvokedAtLeast($blockName, $method, $invokationCount,
$message = '', array $arguments = null,
$searchType = EcomDev_PHPUnit_Constraint_Layout_Block_Action::SEARCH_TYPE_AND)
{
self::assertThatLayout(
self::layoutBlockAction(
$blockName, $method,
EcomDev_PHPUnit_Constraint_Layout_Block_Action::TYPE_INVOKED_AT_LEAST, $invokationCount,
$arguments, $searchType
),
$message
);
}
/**
* Assert that layout block action was invoked exactly expected number of times
*
*
* @param string $blockName
* @param string $method
* @param string $message
* @param array|null $params
* @param string $searchType
*/
public static function assertLayoutBlockActionInvokedExactly($blockName, $method, $invokationCount,
$message = '', array $arguments = null,
$searchType = EcomDev_PHPUnit_Constraint_Layout_Block_Action::SEARCH_TYPE_AND)
{
self::assertThatLayout(
self::layoutBlockAction(
$blockName, $method,
EcomDev_PHPUnit_Constraint_Layout_Block_Action::TYPE_INVOKED_EXACTLY, $invokationCount,
$arguments, $searchType
),
$message
);
}
/**
* Assert that layout block property is matched constraint conditions
*
* @param string $blockName
* @param string $propertyName
* @param PHPUnit_Framework_Constraint $constraint
* @param string $message
*/
public static function assertLayoutBlockProperty($blockName, $propertyName,
PHPUnit_Framework_Constraint $constraint, $message = '')
{
self::assertThatLayout(
self::layoutBlockProperty($blockName, $propertyName, $constraint),
$message
);
}
/**
* Assert that layout block property is not matched constraint conditions
*
* @param string $blockName
* @param string $propertyName
* @param PHPUnit_Framework_Constraint $constraint
* @param string $message
*/
public static function assertLayoutBlockPropertyNot($blockName, $propertyName,
PHPUnit_Framework_Constraint $constraint, $message = '')
{
self::assertThatLayout(
self::logicalNot(
self::layoutBlockProperty($blockName, $propertyName, $constraint)
),
$message
);
}
/**
* Assert that layout block property is equal to expected value
*
* @param string $blockName
* @param string $propertyName
* @param mixed $expectedValue
* @param string $message
* @param float $delta
* @param integer $maxDepth
* @param boolean $canonicalize
* @param boolean $ignoreCase
*/
public static function assertLayoutBlockPropertyEquals($blockName, $propertyName,
$expectedValue, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = false,
$ignoreCase = false)
{
self::assertLayoutBlockProperty(
$blockName, $propertyName,
self::equalTo($expectedValue, $delta, $maxDepth, $canonicalize, $ignoreCase),
$message
);
}
/**
* Assert that layout block property is not equal to expected value
*
* @param string $blockName
* @param string $propertyName
* @param mixed $expectedValue
* @param string $message
* @param float $delta
* @param integer $maxDepth
* @param boolean $canonicalize
* @param boolean $ignoreCase
*/
public static function assertLayoutBlockPropertyNotEquals($blockName, $propertyName,
$expectedValue, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = false,
$ignoreCase = false)
{
self::assertLayoutBlockPropertyNot(
$blockName, $propertyName,
self::equalTo($expectedValue, $delta, $maxDepth, $canonicalize, $ignoreCase),
$message
);
}
/**
* Assert that layout block property is the same as expected value
*
* @param string $blockName
* @param string $propertyName
* @param mixed $expectedValue
* @param string $message
*/
public static function assertLayoutBlockPropertySame($blockName, $propertyName,
$expectedValue, $message = '')
{
self::assertLayoutBlockProperty(
$blockName, $propertyName,
self::identicalTo($expectedValue),
$message
);
}
/**
* Assert that layout block property is not the same as expected value
*
* @param string $blockName
* @param string $propertyName
* @param mixed $expectedValue
* @param string $message
*/
public static function assertLayoutBlockPropertyNotSame($blockName, $propertyName,
$expectedValue, $message = '')
{
self::assertLayoutBlockPropertyNot(
$blockName, $propertyName,
self::identicalTo($expectedValue),
$message
);
}
/**
* Assert that layout block property is equal to expected php internal type
*
* @param string $blockName
* @param string $propertyName
* @param string $type
* @param string $message
*/
public static function assertLayoutBlockPropertyType($blockName, $propertyName,
$type, $message = '')
{
self::assertLayoutBlockProperty(
$blockName, $propertyName,
self::isType($type),
$message
);
}
/**
* Assert that layout block property is not equal to expected php internal type
*
* @param string $blockName
* @param string $propertyName
* @param string $type
* @param string $message
*/
public static function assertLayoutBlockPropertyNotType($blockName, $propertyName,
$type, $message = '')
{
self::assertLayoutBlockPropertyNot(
$blockName, $propertyName,
self::isType($type),
$message
);
}
/**
* Assert that layout block property is an instance of expected class name
*
* @param string $blockName
* @param string $propertyName
* @param string $expectedClassName
* @param string $message
*/
public static function assertLayoutBlockPropertyInstanceOf($blockName, $propertyName,
$expectedClassName, $message = '')
{
self::assertLayoutBlockProperty(
$blockName, $propertyName,
self::isInstanceOf($expectedClassName),
$message
);
}
/**
* Assert that layout block property is not an instance of expected class name
*
* @param string $blockName
* @param string $propertyName
* @param string $expectedClassName
* @param string $message
*/
public static function assertLayoutBlockPropertyNotInstanceOf($blockName, $propertyName,
$expectedClassName, $message = '')
{
self::assertLayoutBlockPropertyNot(
$blockName, $propertyName,
self::isInstanceOf($expectedClassName),
$message
);
}
/**
* Assert that layout block property is empty
*
* @param string $blockName
* @param string $propertyName
* @param string $message
*/
public static function assertLayoutBlockPropertyEmpty($blockName, $propertyName, $message = '')
{
self::assertLayoutBlockProperty(
$blockName, $propertyName,
self::isEmpty(),
$message
);
}
/**
* Assert that layout block property is not empty
*
* @param string $blockName
* @param string $propertyName
* @param string $message
*/
public static function assertLayoutBlockPropertyNotEmpty($blockName, $propertyName, $message = '')
{
self::assertLayoutBlockPropertyNot(
$blockName, $propertyName,
self::isEmpty(),
$message
);
}
/**
* Assert that layout block property is null
*
* @param string $blockName
* @param string $propertyName
* @param string $message
*/
public static function assertLayoutBlockPropertyNull($blockName, $propertyName, $message = '')
{
self::assertLayoutBlockProperty(
$blockName, $propertyName,
self::isNull(),
$message
);
}
/**
* Assert that layout block property is not null
*
* @param string $blockName
* @param string $propertyName
* @param string $message
*/
public static function assertLayoutBlockPropertyNotNull($blockName, $propertyName, $message = '')
{
self::assertLayoutBlockPropertyNot(
$blockName, $propertyName,
self::isEmpty(),
$message
);
}
/**
* Set up controller params
* (non-PHPdoc)
* @see EcomDev_PHPUnit_Test_Case::setUp()
*/
protected function setUp()
{
parent::setUp();
$this->reset();
$this->registerCookieStub();
$this->getCookies()->reset();
$this->app()->getFrontController()->init();
}
/**
* Registers cookie stub
*
* @return EcomDev_PHPUnit_Test_Case_Controller
*/
protected function registerCookieStub()
{
$cookie = $this->getModelMock('core/cookie', array('set', 'delete'));
$cookie->expects($this->any())
->method('set')
->will($this->returnCallback(
array($this, 'setCookieCallback')
));
$cookie->expects($this->any())
->method('delete')
->will($this->returnCallback(
array($this, 'deleteCookieCallback')
));
$this->replaceByMock('singleton', 'core/cookie', $cookie);
return $this;
}
/**
* A callback that is invoked when a cookie is set
* Emulates cookies processing by browser
* Uses Zend_Http_CookieJar component
*
* @param string $name
* @param string $value
* @param int|boolean|null $period
* @param string|null $path
* @param string|null $domain
* @param boolean|null $secure
* @param boolean|null $httponly
* @return EcomDev_PHPUnit_Test_Case_Controller
*/
public function setCookieCallback($name, $value, $period = null, $path = null, $domain = null, $secure = null, $httponly = null)
{
/* @var $coookieStub Mage_Core_Model_Cookie */
$cookieStub = Mage::getSingleton('core/cookie');
$cookie = urlencode($name) . '=' . urlencode($value);
if ($period === true) {
$period = 3600;
} elseif ($period === null) {
$period = $cookieStub->getLifetime();
}
if ($path === null) {
$path = $cookieStub->getPath();
}
if ($domain !== null) {
$domain = $cookieStub->getDomain();
}
if ($period === false) {
$expire = 0;
} elseif ($period === 0) {
$expire = null;
} else {
$expire = time() + $period;
}
if ($domain !== null) {
$cookie .= '; Domain=.' . $domain;
}
if ($path !== null) {
$cookie .= '; Path=' . urlencode($path);
}
if ($expire !== null) {
$cookie .= '; Expires='. date('r', $expire);
}
if ($secure || $cookieStub->isSecure()) {
$cookie .= '; Secure';
}
if ($httponly || $cookieStub->getHttponly()) {
$cookie .= '; HttpOnly';
}
self::getCookies()->addCookie($cookie);
return $this;
}
/**
* A callback that is invoked when a cookie is deleted
*
* @return EcomDev_PHPUnit_Test_Case_Controller
*/
public function deleteCookieCallback($name, $path = null, $domain = null, $secure = null, $httponly = null)
{
$this->setCookieCallback($name, null, false, $path, $domain, $secure, $httponly);
return $this;
}
/**
* Resets controller test case
*
* @return EcomDev_PHPUnit_Test_Case_Controller
*/
protected function reset()
{
$_SESSION = array();
$this->getRequest()->reset();
$this->getResponse()->reset();
$this->getLayout()->reset();
return $this;
}
/**
* Dispatches controller action
*
*
* @param string $route
* @param $store
*/
public function dispatch($route = null, array $params = array())
{
if (!isset($params['_store'])) {
if (strpos($route, EcomDev_PHPUnit_Model_App::AREA_ADMINHTML) !== false) {
$params['_store'] = EcomDev_PHPUnit_Model_App::ADMIN_STORE_CODE;
} else {
$params['_store'] = $this->app()->getAnyStoreView()->getCode();
}
}
if ($params['_store'] !== EcomDev_PHPUnit_Model_App::ADMIN_STORE_CODE) {
$this->setCurrentStore($params['_store']);
$urlModel = Mage::getModel('core/url');
} else {
$urlModel = Mage::getModel('adminhtml/url');
}
$this->app()->resetAreas();
$requestUri = $urlModel->getUrl($route, $params);
$baseUrl = $urlModel->getBaseUrl($params);
$this->getRequest()->resetInternalProperties();
$this->getRequest()->setBaseUrl($baseUrl)
->setRequestUri($requestUri)
->setPathInfo();
$customCookies = $this->getRequest()->getCookie();
$autoCookies = $this->getCookies()->getMatchingCookies($requestUri);
/* @var $cookie Zend_Http_Cookie */
foreach ($autoCookies as $cookie) {
$this->getRequest()->setCookie(
$cookie->getName(),
$cookie->getValue()
);
}
if ($urlModel instanceof Mage_Adminhtml_Model_Url) {
// Workaround for secret key in admin
$this->getRequest()->setParam(
Mage_Adminhtml_Model_Url::SECRET_KEY_PARAM_NAME,
$urlModel->getSecretKey()
);
}
// Workaround for form key
if ($this->getRequest()->isPost()) {
$this->getRequest()->setPost('form_key', Mage::getSingleton('core/session')->getFromKey());
}
$this->getLayout()->reset();
$this->getResponse()->reset();
$this->app()->getFrontController()->dispatch();
// Unset changed cookies
$this->getRequest()->resetCookies();
$this->getRequest()->setCookies($customCookies);
return $this;
}
}
......@@ -29,7 +29,7 @@ class EcomDev_PHPUnit_Test_Suite extends PHPUnit_Framework_TestSuite
// Configuration path constants
const XML_PATH_UNIT_TEST_GROUPS = 'phpunit/suite/groups';
const XML_PATH_UNIT_TEST_MODULES = 'phpunit/suite/modules';
const XML_PATH_UNIT_TEST_APP = 'phpunit/suite/app';
const XML_PATH_UNIT_TEST_APP = 'phpunit/suite/app/class';
const XML_PATH_UNIT_TEST_SUITE = 'phpunit/suite/test_suite';
const CACHE_TAG = 'ECOMDEV_PHPUNIT';
const CACHE_TYPE = 'ecomdev_phpunit';
......
......@@ -51,12 +51,18 @@
<helpers>Helper</helpers>
<blocks>Block</blocks>
<config>Config</config>
<controllers>Controller</controllers>
</groups>
<!-- Test suite that will be used for creation of each of the tests -->
<test_suite>EcomDev_PHPUnit_Test_Suite_Group</test_suite>
<layout>
<model>ecomdev_phpunit/layout</model>
</layout>
<design>
<package>
<model>ecomdev_phpunit/design_package</model>
</package>
</design>
<expectation>
<!-- Default model for loading of expectations -->
<model>ecomdev_phpunit/expectation</model>
......@@ -73,8 +79,27 @@
<catalog_category>ecomdev_phpunit/fixture_eav_catalog_category</catalog_category>
</eav>
</fixture>
<!-- Application model class name for running tests -->
<app>EcomDev_PHPUnit_Model_App</app>
<app>
<!-- Application class name for running tests -->
<class>EcomDev_PHPUnit_Model_App</class>
<area>
<!-- Application area class name for tests -->
<class>EcomDev_PHPUnit_Model_App_Area</class>
</area>
</app>
<!-- Configuration of controller for test cases -->
<controller>
<front>
<class>EcomDev_PHPUnit_Controller_Front</class>
</front>
<request>
<class>EcomDev_PHPUnit_Controller_Request_Http</class>
</request>
<response>
<class>EcomDev_PHPUnit_Controller_Response_Http</class>
</response>
</controller>
<modules>
<!-- Place your module name in your module config.xml
For adding it to test suite -->
......@@ -84,4 +109,17 @@
</modules>
</suite>
</phpunit>
<test>
<!-- Definition of event observers that will be used only for test environment -->
<events>
<core_block_abstract_to_html_after>
<observers>
<ecomdev_phpunit>
<class>core/layout</class>
<method>recordBlockRender</method>
</ecomdev_phpunit>
</observers>
</core_block_abstract_to_html_after>
</events>
</test>
</config>
......@@ -9,4 +9,17 @@
</default_setup>
</resources>
</global>
<default>
<web>
<seo>
<use_rewrites>1</use_rewrites>
</seo>
<secure>
<base_url>[change me]</base_url>
</secure>
<unsecure>
<base_url>[change me]</base_url>
</unsecure>
</web>
</default>
</config>
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Abstract constraint for EcomDev_PHPUnit constraints
* Contains flexible constaint types implementation
*
*/
abstract class EcomDev_PHPUnit_Constraint_Abstract
extends PHPUnit_Framework_Constraint
{
/**
* List of valiadation rules for expected value
* It is an associative array with key as type and value
* as an array of rules.
*
* First item of the rule array is mandatory indicator,
* second is function name for checking the type,
* third one is the type that will be displayed in invalid argument expception
* each of them can be ommited or if it between other ones just by specifying null value
*
* @var array
*/
protected $_expectedValueValidation = array();
/**
* List of types that will use diff for displaying fail result
*
* @var array
*/
protected $_typesWithDiff = array();
/**
* Comparisment type defined in the constructor
*
* @var string
*/
protected $_type = null;
/**
* Expected value defined in the constructor
*
* @var mixed
*/
protected $_expectedValue = null;
/**
* Custom actual value
*
* @var mixed
*/
protected $_actualValue = null;
/**
* Flag for using of actual value in failure description
*
* @var boolean
*/
protected $_useActualValue = false;
/**
* Abstract cnstraint constructor,
* provides unified interface for working with multiple types of evalation
*
* @param string $type
* @param mixed $expectedValue
*/
public function __construct($type, $expectedValue = null)
{
$reflection = EcomDev_Utils_Reflection::getRelflection(get_class($this));
$types = array();
foreach ($reflection->getConstants() as $name => $constant) {
if (strpos($name, 'TYPE_') === 0) {
$types[] = $constant;
}
}
if (empty($type) || !is_string($type) || !in_array($type, $types)) {
throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string', $type);
}
if (isset($this->_expectedValueValidation[$type])) {
$expectedValueType = (isset($this->_expectedValueValidation[$type][2]) ?
isset($this->_expectedValueValidation[$type][2]) :
'');
// Mandatory check
if (isset($this->_expectedValueValidation[$type][0])
&& $this->_expectedValueValidation[$type][0]
&& $expectedValue === null) {
throw PHPUnit_Util_InvalidArgumentHelper::factory(2, $expectedValueType, $expectedValue);
}
// Type check
if (isset($this->_expectedValueValidation[$type][1])
&& !$this->_expectedValueValidation[$type][1]($expectedValue)) {
throw PHPUnit_Util_InvalidArgumentHelper::factory(2, $expectedValueType, $expectedValue);
}
}
$this->_type = $type;
$this->_expectedValue = $expectedValue;
}
/**
* Set actual value that will be used in the fail message
*
* @param mixed $actual
* @return EcomDev_PHPUnit_Constraint_Abstract
*/
protected function setActualValue($actual)
{
$this->_useActualValue = true;
$this->_actualValue = $actual;
return $this;
}
/**
* Calls internal protected method by defined constraint type
* Also can be passed a single argument
*
* @param string $prefix
* @return mixed
*/
protected function callProtectedByType($prefix, $argument = null)
{
$camelizedType = uc_words($this->_type, '');
$methodName = $prefix . $camelizedType;
return $this->$methodName($argument);
}
/**
* Evaluates value by type.
* (non-PHPdoc)
* @see PHPUnit_Framework_Constraint::evaluate()
*/
public function evaluate($other)
{
return $this->callProtectedByType('evaluate', $other);
}
/**
* Generates a failure exception based on exception type
*
* (non-PHPdoc)
* @see PHPUnit_Framework_Constraint::fail()
*/
public function fail($other, $description, $not = FALSE)
{
$failureDescription = $this->failureDescription($other, $description, $not);
if (in_array($this->_type, $this->_typesWithDiff)) {
throw new EcomDev_PHPUnit_Constraint_Exception(
$failureDescription,
PHPUnit_Util_Diff::diff($this->getExpectedValue(), $this->getActualValue($other)),
$description
);
} else {
throw new EcomDev_PHPUnit_Constraint_Exception(
$failureDescription, $this->getActualValue($other), $description
);
}
}
/**
* Returns a scalar representation of actual value,
* Returns $other if internal acutal value is not set
*
* @param Varien_Simplexml_Element $other
* @return scalar
*/
protected function getActualValue($other = null)
{
if ($this->_useActualValue) {
return $this->_actualValue;
}
return $other;
}
/**
* Returns a scalar representation of expected value
*
* @return string
*/
protected function getExpectedValue()
{
return $this->_expectedValue;
}
/**
* Text reperesentation of constraint
* (non-PHPdoc)
* @see PHPUnit_Framework_SelfDescribing::toString()
*/
public function toString()
{
return $this->callProtectedByType('text');
}
}
\ No newline at end of file
......@@ -44,17 +44,14 @@ class EcomDev_PHPUnit_Constraint_Config extends PHPUnit_Framework_Constraint
*/
public function __construct($constraint)
{
$this->config = $config;
if (!$constraint instanceof EcomDev_PHPUnit_Constraint_Config_Interface) {
throw PHPUnit_Util_InvalidArgumentHelper::factory(
1, 'EcomDev_PHPUnit_Constraint_Config_Interface'
);
}
$this->constraint = $constraint;
}
/**
*
* @param mixed $other
......
......@@ -21,31 +21,9 @@
*
*/
abstract class EcomDev_PHPUnit_Constraint_Config_Abstract
extends PHPUnit_Framework_Constraint
extends EcomDev_PHPUnit_Constraint_Abstract
implements EcomDev_PHPUnit_Constraint_Config_Interface
{
/**
* List of valiadation rules for expected value
* It is an associative array with key as type and value
* as an array of rules.
*
* First item of the rule array is mandatory indicator,
* second is function name for checking the type,
* third one is the type that will be displayed in invalid argument expception
* each of them can be ommited or if it between other ones just by specifying null value
*
* @var array
*/
protected $_expectedValueValidation = array();
/**
* List of types that will use diff for displaying fail result
*
* @var array
*/
protected $_typesWithDiff = array();
/**
* Config node path defined in the constructor
*
......@@ -53,34 +31,6 @@ abstract class EcomDev_PHPUnit_Constraint_Config_Abstract
*/
protected $_nodePath = null;
/**
* Comparisment type defined in the constructor
*
* @var string
*/
protected $_type = null;
/**
* Expected value defined in the constructor
*
* @var mixed
*/
protected $_expectedValue = null;
/**
* Custom actual value
*
* @var mixed
*/
protected $_actualValue = null;
/**
* Flag for using of actual valu in failure description
*
* @var boolean
*/
protected $_useActualValue = false;
/**
* Constraint constructor
*
......@@ -94,56 +44,8 @@ abstract class EcomDev_PHPUnit_Constraint_Config_Abstract
throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string', $type);
}
$reflection = EcomDev_Utils_Reflection::getRelflection(get_class($this));
$types = array();
foreach ($reflection->getConstants() as $name => $constant) {
if (strpos($name, 'TYPE_') === 0) {
$types[] = $constant;
}
}
if (empty($type) || !is_string($type) || !in_array($type, $types)) {
throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string', $type);
}
if (isset($this->_expectedValueValidation[$type])) {
$expectedValueType = (isset($this->_expectedValueValidation[$type][2]) ?
isset($this->_expectedValueValidation[$type][2]) :
'');
// Mandatory check
if (isset($this->_expectedValueValidation[$type][0])
&& $this->_expectedValueValidation[$type][0]
&& $expectedValue === null) {
throw PHPUnit_Util_InvalidArgumentHelper::factory(3, $expectedValueType, $expectedValue);
}
// Type check
if (isset($this->_expectedValueValidation[$type][1])
&& !$this->_expectedValueValidation[$type][1]($expectedValue)) {
throw PHPUnit_Util_InvalidArgumentHelper::factory(3, $expectedValueType, $expectedValue);
}
}
$this->_nodePath = $nodePath;
$this->_type = $type;
$this->_expectedValue = $expectedValue;
}
/**
* Set actual value that will be used in the fail message
*
* @param mixed $actual
* @return EcomDev_PHPUnit_Constraint_Config_Abstract
*/
protected function setActualValue($actual)
{
$this->_useActualValue = true;
$this->_actualValue = $actual;
return $this;
parent::__construct($type, $expectedValue);
}
/**
......@@ -158,22 +60,10 @@ abstract class EcomDev_PHPUnit_Constraint_Config_Abstract
}
/**
* Calls internal protected method by defined constraint type
* Also can be passed a single argument
* Automatically evaluate to false if the node was not found
*
* @param string $prefix
*/
protected function callProtectedByType($prefix, $argument = null)
{
$camelizedType = uc_words($this->_type, '');
$methodName = $prefix . $camelizedType;
return $this->$methodName($argument);
}
/**
* Evaluates value by type.
* (non-PHPdoc)
* @see PHPUnit_Framework_Constraint::evaluate()
* @see EcomDev_PHPUnit_Constraint_Abstract::evaluate()
*/
public function evaluate($other)
{
......@@ -182,59 +72,39 @@ abstract class EcomDev_PHPUnit_Constraint_Config_Abstract
return false;
}
return $this->callProtectedByType('evaluate', $other);
return parent::evaluate($other);
}
/**
* Generates a failure exception based on exception type
* Returns a scalar representation of actual value,
* Returns $other if internal acutal value is not set
*
* (non-PHPdoc)
* @see PHPUnit_Framework_Constraint::fail()
* @param Varien_Simplexml_Element $other
* @return scalar
*/
public function fail($other, $description, $not = FALSE)
protected function getActualValue($other = null)
{
$failureDescription = $this->failureDescription($other, $description, $not);
if (in_array($this->_type, $this->_typesWithDiff)) {
if ($this->_useActualValue) {
$other = $this->_actualValue;
} elseif ($other->hasChildren()) {
$other = $other->asNiceXml();
} else {
$other = (string) $other;
}
if ($this->_expectedValue instanceof Varien_Simplexml_Element) {
$expected = $this->_expectedValue->asNiceXml();
} else {
$expected = $this->_expectedValue;
if (!$this->_useActualValue && $other->hasChildren()) {
return $other->asNiceXml();
} elseif (!$this->_useActualValue) {
return (string) $other;
}
throw new EcomDev_PHPUnit_Constraint_Exception(
$failureDescription,
PHPUnit_Util_Diff::diff($expected, $other),
$description
);
} else {
if (!$this->_useActualValue) {
$actualValue = $other->asNiceXml();
} else {
$actualValue = $this->_actualValue;
}
throw new EcomDev_PHPUnit_Constraint_Exception(
$failureDescription, $actualValue, $description
);
}
return parent::getActualValue($other);
}
/**
* Text reperesentation of constraint
* (non-PHPdoc)
* @see PHPUnit_Framework_SelfDescribing::toString()
* Returns a scalar representation of expected value
*
* @return string
*/
public function toString()
protected function getExpectedValue()
{
return $this->callProtectedByType('text');
if ($this->_expectedValue instanceof Varien_Simplexml_Element) {
return $this->_expectedValue->asNiceXml();
}
return parent::getExpectedValue();
}
}
\ No newline at end of file
......@@ -99,9 +99,9 @@ class EcomDev_PHPUnit_Constraint_Config_Layout
/**
* Sets design package model for assertions
*
* @param EcomDev_PHPUnit_Constraint_Config_Design_Package_Interface $model
* @param EcomDev_PHPUnit_Design_Package_Interface $model
*/
public static function setDesignPackageModel(EcomDev_PHPUnit_Constraint_Config_Design_Package_Interface $model)
public static function setDesignPackageModel(EcomDev_PHPUnit_Design_Package_Interface $model)
{
self::$_designPackageModel = $model;
}
......@@ -109,7 +109,7 @@ class EcomDev_PHPUnit_Constraint_Config_Layout
/**
* Retrieves design package model that was set before
*
* @return EcomDev_PHPUnit_Constraint_Config_Design_Package_Interface
* @return EcomDev_PHPUnit_Design_Package_Interface
*/
public static function getDesignPackageModel()
{
......@@ -162,7 +162,7 @@ class EcomDev_PHPUnit_Constraint_Config_Layout
->getLayoutFileAssertion($this->_expectedValue, $this->_area, $this->_designPackage, $this->_theme);
$this->setActualValue($assertion['actual']);
$this->_expectedValue = $assertin['expected'];
$this->_expectedValue = $assertion['expected'];
return $this->_actualValue !== $this->_expectedValue;
}
......
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Constraint for controller request assetions
*
*/
class EcomDev_PHPUnit_Constraint_Controller_Request extends EcomDev_PHPUnit_Constraint_Abstract
{
const TYPE_ROUTE = 'route';
const TYPE_ROUTE_NAME = 'route_name';
const TYPE_CONTROLLER_NAME = 'controller_name';
const TYPE_CONTROLLER_MODULE = 'controller_module';
const TYPE_ACTION_NAME = 'action_name';
const TYPE_DISPATCHED = 'dispatched';
const TYPE_FORWARDED = 'forwarded';
const TYPE_BEFORE_FORWARD_ROUTE = 'before_forward_route';
/**
* Constraint for controller request assetions
*
*
* @param string $type
* @param string|null $expectedValue
*/
public function __construct($type, $expectedValue = null)
{
$this->_expectedValueValidation += array(
self::TYPE_ROUTE => array(true, 'is_string', 'string'),
self::TYPE_ROUTE_NAME => array(true, 'is_string', 'string'),
self::TYPE_CONTROLLER_NAME => array(true, 'is_string', 'string'),
self::TYPE_CONTROLLER_MODULE => array(true, 'is_string', 'string'),
self::TYPE_ACTION_NAME => array(true, 'is_string', 'string'),
self::TYPE_BEFORE_FORWARD_ROUTE => array(true, 'is_string', 'string')
);
$this->_typesWithDiff[] = self::TYPE_ROUTE;
$this->_typesWithDiff[] = self::TYPE_ROUTE_NAME;
$this->_typesWithDiff[] = self::TYPE_CONTROLLER_NAME;
$this->_typesWithDiff[] = self::TYPE_CONTROLLER_MODULE;
$this->_typesWithDiff[] = self::TYPE_ACTION_NAME;
$this->_typesWithDiff[] = self::TYPE_BEFORE_FORWARD_ROUTE;
parent::__construct($type, $expectedValue);
}
/**
* Parses route to params
*
* @param string $route
* @return array
*/
protected function parseRoute($route)
{
$routeParts = explode('/', $route, 3);
$routePartsCount = count($routeParts);
if ($routePartsCount < 3) {
array_pad($routeParts, 3-$routePartsCount, null);
}
$params = array();
if ($routeParts[0] !== '*') {
$params['route_name'] = !empty($routeParts[0]) ? $routeParts[0] : 'index';
}
if ($routeParts[1] !== '*') {
$params['controller_name'] = !empty($routeParts[1]) ? $routeParts[1] : 'index';
}
if ($routeParts[2] !== '*') {
$params['action_name'] = !empty($routeParts[2]) ? $routeParts[2] : 'index';
}
return $params;
}
/**
* Evaluates that current controller route is equal to expected
*
* @param EcomDev_PHPUnit_Controller_Request_Interface $other
* @return boolean
*/
protected function evaluateRoute($other)
{
$params = $this->parseRoute($this->_expectedValue);
$this->setActualValue(
$other->getRouteName() . '/' . $other->getControllerName()
. '/' . $other->getActionName()
);
foreach ($params as $propertyName => $expectedValue) {
$methodName = 'get'.str_replace(' ', '',
ucwords(strtr($propertyName, '_', ' '))
);
if ($other->$methodName() !== $expectedValue) {
return false;
}
}
return true;
}
/**
* Text reperesentation of route path assertion
*
* @return string
*/
protected function textRoute()
{
return 'route matches expected one';
}
/**
* Evaluates that before forwarding controller route is equal to expected
*
* @param EcomDev_PHPUnit_Controller_Request_Interface $other
* @return boolean
*/
protected function evaluateBeforeForwardRoute($other)
{
if (!$other->getBeforeForwardInfo()) {
$this->setActualValue(false);
return false;
}
$params = $this->parseRoute($this->_expectedValue);
$this->setActualValue(
$other->getBeforeForwardInfo('route_name') . '/'
. $other->getBeforeForwardInfo('controller_name') . '/'
. $other->getBeforeForwardInfo('action_name')
);
foreach ($params as $propertyName => $expectedValue) {
if ($other->getBeforeForwardInfo($propertyName) !== $expectedValue) {
return false;
}
}
return true;
}
/**
* Text reperesentation of route path assertion
*
* @return string
*/
protected function textBeforeForwardRoute()
{
return 'route before forwarding matches expected one';
}
/**
* Evaluates that request was forwarded
*
* @param EcomDev_PHPUnit_Controller_Request_Interface $other
* @return boolean
*/
protected function evaluateForwarded($other)
{
return (bool)$other->getBeforeForwardInfo();
}
/**
* Text reperesentation of was forwaded request assertion
*
* @return string
*/
protected function textForwarded()
{
return 'is forwarded';
}
/**
* Evaluates that request was forwarded
*
* @param EcomDev_PHPUnit_Controller_Request_Interface $other
* @return boolean
*/
protected function evaluateDispatched($other)
{
return $other->isDispatched();
}
/**
* Text reperesentation of was forwaded request assertion
*
* @return string
*/
protected function textDispatched()
{
return 'is dispatched';
}
/**
* Evaluates that request route name is equal to expected
*
* @param EcomDev_PHPUnit_Controller_Request_Interface $other
* @return boolean
*/
protected function evaluateRouteName($other)
{
$this->setActualValue($other->getRouteName());
return $this->_actualValue === $this->_expectedValue;
}
/**
* Text reperesentation of route name assertion
*
* @return string
*/
protected function textRouteName()
{
return 'route name is equal to expected';
}
/**
* Evaluates that request controller name is equal to expected
*
* @param EcomDev_PHPUnit_Controller_Request_Interface $other
* @return boolean
*/
protected function evaluateControllerName($other)
{
$this->setActualValue($other->getControllerName());
return $this->_actualValue === $this->_expectedValue;
}
/**
* Text reperesentation of controller name assertion
*
* @return string
*/
protected function textControllerName()
{
return 'controller name is equal to expected';
}
/**
* Evaluates that request controller module is equal to expected
*
* @param EcomDev_PHPUnit_Controller_Request_Interface $other
* @return boolean
*/
protected function evaluateControllerModule($other)
{
$this->setActualValue($other->getControllerModule());
return $this->_actualValue === $this->_expectedValue;
}
/**
* Text reperesentation of controller module assertion
*
* @return string
*/
protected function textControllerModule()
{
return 'controller module is equal to expected';
}
/**
* Evaluates that request action name is equal to expected
*
* @param EcomDev_PHPUnit_Controller_Request_Interface $other
* @return boolean
*/
protected function evaluateActionName($other)
{
$this->setActualValue($other->getActionName());
return $this->_actualValue === $this->_expectedValue;
}
/**
* Text reperesentation of action name assertion
*
* @return string
*/
protected function textActionName()
{
return 'action name is equal to expected';
}
/**
* Custom failure description for showing request related errors
* (non-PHPdoc)
* @see PHPUnit_Framework_Constraint::customFailureDescription()
*/
protected function customFailureDescription($other, $description, $not)
{
return sprintf(
'Failed asserting that request %s.',
$this->toString()
);
}
}
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Abstract constraint for controller response assetions
*
*/
abstract class EcomDev_PHPUnit_Constraint_Controller_Response_Abstract
extends EcomDev_PHPUnit_Constraint_Abstract
{
/**
* Custom failure description for showing response related errors
* (non-PHPdoc)
* @see PHPUnit_Framework_Constraint::customFailureDescription()
*/
protected function customFailureDescription($other, $description, $not)
{
return sprintf(
'Failed asserting that request %s.',
$this->toString()
);
}
}
\ No newline at end of file
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Constraint for controller response body assertions
*
*/
class EcomDev_PHPUnit_Constraint_Controller_Response_Body
extends EcomDev_PHPUnit_Constraint_Controller_Response_Abstract
{
const TYPE_CONSTRAINT = 'constraint';
/**
* Constraint for controller response body assertions
*
* @param PHPUnit_Framework_Constraint $constraint
* @param string $type
*/
public function __construct(PHPUnit_Framework_Constraint $constraint = null, $type = self::TYPE_CONSTRAINT)
{
$this->_expectedValueValidation += array(
self::TYPE_CONSTRAINT => array(true, null, 'PHPUnit_Framework_Constraint')
);
parent::__construct($type, $constraint);
}
/**
* Evaluates controller response body is evaluated by constraint
*
*
* @param EcomDev_PHPUnit_Controller_Response_Interface $other
*/
protected function evaluateConstraint($other)
{
$this->setActualValue($other->getOutputBody());
return $this->_expectedValue->evaluate($this->_actualValue);
}
/**
* Text representation of response body is evaluated by constraint assertion
*
* @return string
*/
protected function textConstraint()
{
return sprintf('body %s', $this->_expectedValue->toString());
}
}
\ No newline at end of file
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Constraint for controller response header assertions
*
*/
class EcomDev_PHPUnit_Constraint_Controller_Response_Header
extends EcomDev_PHPUnit_Constraint_Controller_Response_Abstract
{
const TYPE_CONSTRAINT = 'constraint';
const TYPE_SENT = 'sent';
/**
* The name of the header that will be asserted
*
* @var string
*/
protected $_headerName = null;
/**
* Response header assertion
*
* @param string $headerName
* @param string $type
* @param PHPUnit_Framework_Constraint $constraint
*/
public function __construct($headerName, $type, PHPUnit_Framework_Constraint $constraint = null)
{
if (empty($headerName) || !is_string($headerName)) {
throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string', $headerName);
}
$this->_expectedValueValidation += array(
self::TYPE_CONSTRAINT => array(true, null, 'PHPUnit_Framework_Constraint')
);
parent::__construct($type, $constraint);
$this->_headerName = $headerName;
}
/**
* Evaluates controller response header is sent
*
*
* @param EcomDev_PHPUnit_Controller_Response_Interface $other
*/
protected function evaluateSent($other)
{
$this->setActualValue($other->getSentHeaders());
return $other->getSentHeader($this->_headerName) !== false;
}
/**
* Text representation of header is sent assertion
*
* @return string
*/
protected function textSent()
{
return sprintf('header "%s" is sent', $this->_headerName);
}
/**
* Evaluates controller response header is evaluated by constraint
*
*
* @param EcomDev_PHPUnit_Controller_Response_Interface $other
*/
protected function evaluateConstraint($other)
{
$this->setActualValue($other->getSentHeader($this->_headerName));
return $this->_expectedValue->evaluate($this->_actualValue);
}
/**
* Text representation of header is evaluated by constraint assertion
*
* @return string
*/
protected function textConstraint()
{
return sprintf('header "%s" value %s', $this->_headerName, $this->_expectedValue->toString());
}
}
......@@ -27,6 +27,10 @@ class EcomDev_PHPUnit_Constraint_Exception extends PHPUnit_Framework_Expectation
public function __construct($description, $diff = '', $message = '')
{
if (!is_scalar($diff)) {
$diff = print_r($diff, true);
}
$this->diff = $diff;
parent::__construct($description, null, $message);
}
......
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Constraint for checking JSON values
*
*/
class EcomDev_PHPUnit_Constraint_Json extends EcomDev_PHPUnit_Constraint_Abstract
{
const TYPE_VALID = 'valid';
const TYPE_MATCH = 'match';
const MATCH_AND = 'and';
const MATCH_OR = 'or';
const MATCH_EXACT = 'exact';
/**
* Match type for evaluation
*
* @var string
*/
protected $_matchType = self::MATCH_AND;
/**
* Constraint for checking JSON values
*
*
* @param string $type
* @param array $expectedValue expected json in array format
* @param string $matchType
*/
public function __construct($type, $expectedValue = null, $matchType = self::MATCH_AND)
{
if ($expectedValue !== null && (empty($matchType) || !is_string($matchType))) {
PHPUnit_Util_InvalidArgumentHelper::factory(3, 'string', $matchType);
}
$this->_expectedValueValidation += array(
self::TYPE_MATCH => array(true, 'is_array', 'array')
);
$this->_typesWithDiff[] = self::TYPE_MATCH;
parent::__construct($type, $expectedValue);
$this->_matchType = $matchType;
}
/**
* Evaluate that string is valid JSON
*
* @param string $other
* @return boolean
*/
protected function evaluateValid($other)
{
try {
$decodedJson = Zend_Json::decode($other);
$this->setActualValue($decodedJson);
} catch (Zend_Json_Exception $e) {
$this->setActualValue(
PHPUnit_Util_Type::shortenedString($other)
. "\n" . $e->__toString()
);
return false;
}
return true;
}
/**
* Text representation of JSON string is valid assertion
*
* @return string
*/
protected function textValid()
{
return 'is valid JSON';
}
/**
* Evaluate that string is valid JSON
*
* @param string $other
* @return boolean
*/
protected function evaluateMatch($other)
{
$decodedJson = Zend_Json::decode($other);
$this->setActualValue($decodedJson);
$intersection = array_intersect_assoc(
$this->_actualValue,
$this->_expectedValue
);
switch ($this->_matchType) {
case self::MATCH_OR:
$matched = !empty($intersection);
break;
case self::MATCH_EXACT:
$matched = count($intersection) === count($decodedJson);
break;
case self::MATCH_AND:
default:
$matched = count($intersection) === count($this->_expectedValue);
break;
}
return $matched;
}
/**
* Text representation of matching evaluation
*
* @return string
*/
protected function textMatch()
{
$string = 'matches expected JSON structure ';
switch ($this->_matchType) {
case self::MATCH_OR:
$string .= 'at least in one element';
break;
case self::MATCH_EXACT:
$string .= 'exactly';
break;
case self::MATCH_AND:
default:
$string .= 'in all expected elements';
break;
}
return $string;
}
/**
* Text representation of JSON string is valid assertion
*
* @return string
*/
protected function textValid()
{
return 'is valid JSON';
}
/**
* Custom failure description for showing json related errors
* (non-PHPdoc)
* @see PHPUnit_Framework_Constraint::customFailureDescription()
*/
protected function customFailureDescription($other, $description, $not)
{
return sprintf(
'Failed asserting that string value %s.',
$this->toString()
);
}
}
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Constraint for main layout functionality
*
*/
class EcomDev_PHPUnit_Constraint_Layout extends EcomDev_PHPUnit_Constraint_Layout_Abstract
{
const TYPE_LOADED = 'loaded';
const TYPE_RENDERED = 'rendered';
const ACTION_RENDER = EcomDev_PHPUnit_Constraint_Layout_Logger_Interface::ACTION_RENDER;
/**
* Constraint for main layout functions
*
*
* @param string $type
*/
public function __construct($type = self::TYPE_LOADED)
{
parent::__construct($type);
}
/**
* Evaluates that layout was loaded
*
*
* @param EcomDev_PHPUnit_Constraint_Layout_Logger_Interface $other
* @return boolean
*/
protected function evaluateLoaded($other)
{
return $other->isLoaded();
}
/**
* Text representation of layout is loaded assertion
*
* @return string
*/
protected function textLoaded()
{
return 'is loaded';
}
/**
* Evaluates that layout was rendered
*
*
* @param EcomDev_PHPUnit_Constraint_Layout_Logger_Interface $other
* @return boolean
*/
protected function evaluateRendered($other)
{
return $other->findFirst(self::ACTION_RENDER, 'layout') !== false;
}
/**
* Text representation of layout is rendered assertion
*
* @return string
*/
protected function textRendered()
{
return 'is rendered';
}
}
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Base for all layout constraints
*
*/
abstract class EcomDev_PHPUnit_Constraint_Layout_Abstract extends EcomDev_PHPUnit_Constraint_Abstract
{
/**
* Custom failure description for showing layout related errors
* (non-PHPdoc)
* @see PHPUnit_Framework_Constraint::customFailureDescription()
*/
protected function customFailureDescription($other, $description, $not)
{
return sprintf(
'Failed asserting that layout %s.',
$this->toString()
);
}
/**
* For layout, actual value should be always set
* (non-PHPdoc)
* @see EcomDev_PHPUnit_Constraint_Abstract::getActualValue()
*/
protected function getActualValue($other)
{
if ($this->_useActualValue) {
if (is_array($this->_actualValue)) {
return PHPUnit_Util_Type::toString($this->_actualValue);
}
return parent::getActualValue($other);
}
return '';
}
}
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Constaint related to main layout block functionality
*
*/
class EcomDev_PHPUnit_Constraint_Layout_Block extends EcomDev_PHPUnit_Constraint_Layout_Abstract
{
const TYPE_CREATED = 'created';
const TYPE_REMOVED = 'removed';
const TYPE_RENDERED = 'rendered';
const TYPE_RENDERED_CONTENT = 'rendered_content';
const TYPE_TYPE = 'type';
const TYPE_INSTANCE_OF = 'instance_of';
const TYPE_AFTER = 'after';
const TYPE_BEFORE = 'before';
const TYPE_PARENT_NAME = 'parent_name';
const TYPE_ROOT_LEVEL = 'root_level';
const ACTION_BLOCK_CREATED = EcomDev_PHPUnit_Constraint_Layout_Logger_Interface::ACTION_BLOCK_CREATED;
const ACTION_BLOCK_RENDERED = EcomDev_PHPUnit_Constraint_Layout_Logger_Interface::ACTION_BLOCK_RENDERED;
const ACTION_BLOCK_REMOVED = EcomDev_PHPUnit_Constraint_Layout_Logger_Interface::ACTION_BLOCK_REMOVED;
/**
* Block name for constraint
*
* @var string
*/
protected $_blockName = null;
/**
* Constaint related to main layout block functionality
*
* @param string $blockName
* @param string $type
* @param string|null $expectedValue
*/
public function __construct($blockName, $type, $expectedValue = null)
{
if (empty($blockName) || !is_string($blockName)) {
throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string', $blockName);
}
$this->_blockName = $blockName;
$this->_expectedValueValidation += array(
self::TYPE_TYPE => array(true, 'is_string', 'string'),
self::TYPE_INSTANCE_OF => array(true, 'is_string', 'string'),
self::TYPE_AFTER => array(true, 'is_string', 'string'),
self::TYPE_BEFORE => array(true, 'is_string', 'string'),
self::TYPE_PARENT_NAME => array(true, 'is_string', 'string'),
self::TYPE_RENDERED_CONTENT => array(true)
);
$this->_typesWithDiff[] = self::TYPE_TYPE;
$this->_typesWithDiff[] = self::TYPE_AFTER;
$this->_typesWithDiff[] = self::TYPE_BEFORE;
$this->_typesWithDiff[] = self::TYPE_PARENT_NAME;
parent::__construct($type, $expectedValue);
}
/**
* Evaluates that layout block was created
*
* @param EcomDev_PHPUnit_Constraint_Layout_Logger_Interface $other
* @return boolean
*/
protected function evaluateCreated($other)
{
return $other->findFirst(self::ACTION_BLOCK_CREATED, $this->_blockName);
}
/**
* Text representation of block is created assertion
*
* @return string
*/
protected function textCreated()
{
return sprintf('block "%s" is created', $this->_blockName);
}
/**
* Evaluates that layout block was rendered
*
* @param EcomDev_PHPUnit_Constraint_Layout_Logger_Interface $other
* @return boolean
*/
protected function evaluateRendered($other)
{
return $other->findFirst(self::ACTION_BLOCK_RENDERED, $this->_blockName) !== false;
}
/**
* Text representation of block is rendered assertion
*
* @return string
*/
protected function textRendered()
{
return sprintf('block "%s" is rendered', $this->_blockName);
}
/**
* Evaluates that layout block rendered is evaluated by expected constraint
*
* @param EcomDev_PHPUnit_Constraint_Layout_Logger_Interface $other
* @return boolean
*/
protected function evaluateRenderedContent($other)
{
$renderInfo = $other->findFirst(self::ACTION_BLOCK_RENDERED, $this->_blockName);
if (!$renderInfo) {
$this->setActualValue(false);
return false;
}
$this->setActualValue($renderInfo['content']);
return $this->_expectedValue->evaluate($renderInfo['content']);
}
/**
* Text representation of block rendered is evaluated by expected constraint assertion
*
* @return string
*/
protected function textRenderedContent()
{
return sprintf('block "%s" rendered content %s',
$this->_blockName, $this->_expectedValue->toString());
}
/**
* Evaluates that layout block was removed
*
* @param EcomDev_PHPUnit_Constraint_Layout_Logger_Interface $other
* @return boolean
*/
protected function evaluateRemoved($other)
{
// Set possible block creation record for failure
$this->setActualValue(
$other->findFirst(self::ACTION_BLOCK_CREATED, $this->_blockName)
);
return $this->_actualValue === false
&& $other->findFirst(self::ACTION_BLOCK_REMOVED, $this->_blockName) !== false;
}
/**
* Text representation of block is removed assertion
*
* @return string
*/
protected function textRemoved()
{
return sprintf('block "%s" is removed', $this->_blockName);
}
/**
* Evaluates that layout block was placed after expected one
*
* @param EcomDev_PHPUnit_Constraint_Layout_Logger_Interface $other
* @return boolean
*/
protected function evaluateAfter($other)
{
$positionInfo = $other->getBlockPosition($this->_blockName);
$this->setActualValue($positionInfo['after']);
return in_array($this->_expectedValue, $this->_actualValue);
}
/**
* Text representation of layout block is placed after another
*
* @return string
*/
protected function textAfter()
{
return sprintf('block "%s" is placed after "%s"', $this->_blockName, $this->_expectedValue);
}
/**
* Evaluates that layout block was placed before expected one
*
* @param EcomDev_PHPUnit_Constraint_Layout_Logger_Interface $other
* @return boolean
*/
protected function evaluateBefore($other)
{
$positionInfo = $other->getBlockPosition($this->_blockName);
$this->setActualValue($positionInfo['before']);
return in_array($this->_expectedValue, $this->_actualValue);
}
/**
* Text representation of layout block is placed before another
*
* @return string
*/
protected function textBefore()
{
return sprintf('block "%s" is placed before "%s"', $this->_blockName, $this->_expectedValue);
}
/**
* Evaluates that layout block is a type of expected
*
* @param EcomDev_PHPUnit_Constraint_Layout_Logger_Interface $other
* @return boolean
*/
protected function evaluateType($other)
{
$blockInfo = $other->findFirst(self::ACTION_BLOCK_CREATED, $this->_blockName);
if ($blockInfo === false) {
$this->setActualValue(false);
return false;
}
$this->setActualValue($blockInfo['type']);
return $blockInfo['type'] === $this->_expectedValue;
}
/**
* Text represetation of block type constraint
*
* @return string
*/
protected function textType()
{
return sprintf('block "%s" is a type of "%s"', $this->_blockName, $this->_expectedValue);
}
/**
* Evaluates that layout block is an instance of expected class/interface
*
* @param EcomDev_PHPUnit_Constraint_Layout_Logger_Interface $other
* @return boolean
*/
protected function evaluateInstanceOf($other)
{
$blockInfo = $other->findFirst(self::ACTION_BLOCK_CREATED, $this->_blockName);
if ($blockInfo === false) {
$this->setActualValue(false);
return false;
}
$this->setActualValue($blockInfo['class']);
$actualReflection = EcomDev_Utils_Reflection::getRelflection($this->_actualValue);
return $this->_actualValue === $this->_expectedValue
|| $actualReflection->isSubclassOf($this->_expectedValue);
}
/**
* Text represetation of block instance of constraint
*
* @return string
*/
protected function textInstanceOf()
{
return sprintf('block "%s" is an instance of %s', $this->_blockName, $this->_expectedValue);
}
/**
* Evaluates that layout block is a root level block
*
* @param EcomDev_PHPUnit_Constraint_Layout_Logger_Interface $other
* @return boolean
*/
protected function evaluateRootLevel($other)
{
$blockInfo = $other->findFirst(self::ACTION_BLOCK_CREATED, $this->_blockName);
if ($blockInfo === false) {
return false;
}
return $blockInfo['root'] === true;
}
/**
* Text representation of a root level block assertion
*
* @return string
*/
protected function textRootLevel()
{
return sprintf('block "%s" is a root level one', $this->_blockName);
}
}
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Constaint related to main layout block action calls functionality
*
*/
class EcomDev_PHPUnit_Constraint_Layout_Block_Action extends EcomDev_PHPUnit_Constraint_Layout_Abstract
{
const TYPE_INVOKED = 'invoked';
const TYPE_INVOKED_AT_LEAST = 'invoked_at_least';
const TYPE_INVOKED_EXACTLY = 'invoked_exactly';
const ACTION_BLOCK_ACTION = EcomDev_PHPUnit_Constraint_Layout_Logger_Interface::ACTION_BLOCK_ACTION;
const SEARCH_TYPE_OR = EcomDev_PHPUnit_Constraint_Layout_Logger_Interface::SEARCH_TYPE_OR;
const SEARCH_TYPE_EXACT = EcomDev_PHPUnit_Constraint_Layout_Logger_Interface::SEARCH_TYPE_EXACT;
const SEARCH_TYPE_AND = EcomDev_PHPUnit_Constraint_Layout_Logger_Interface::SEARCH_TYPE_AND;
/**
* Block name for the action
*
* @var string
*/
protected $_blockName = null;
/**
* Block method name for the action
*
* @var string
*/
protected $_method = null;
/**
* Target for searching in layout records
*
* @var string
*/
protected $_target = null;
/**
* Block method arguments for search
*
* @var array
*/
protected $_arguments = null;
/**
* Block method arguments search type
*
* @var unknown_type
*/
protected $_searchType = self::SEARCH_TYPE_AND;
/**
* Constaint related to main layout block action calls functionality
*
* @param string $blockName
* @param string $method
* @param string $type
* @param int|null $invocationCount
* @param array|null $parameters
* @param string $searchType
*/
public function __construct($blockName, $method, $type, $invocationCount = null,
array $arguments = null, $searchType = self::SEARCH_TYPE_AND)
{
if (empty($blockName) || !is_string($blockName)) {
PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string', $blockName);
}
if (empty($method) || !is_string($method)) {
throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string', $method);
}
if (!is_string($searchType)) {
throw PHPUnit_Util_InvalidArgumentHelper::factory(6, 'string', $searchType);
}
$this->_expectedValueValidation += array(
self::TYPE_INVOKED_AT_LEAST => array(true, 'is_int', 'integer'),
self::TYPE_INVOKED_EXACTLY => array(true, 'is_int', 'integer')
);
parent::__construct($type, $invocationCount);
$this->_blockName = $blockName;
$this->_method = $method;
$this->_target = sprintf('%s::%s', $this->_blockName, $this->_method);
$this->_arguments = $arguments;
}
/**
* Finds records in layout logger history
*
* @param EcomDev_PHPUnit_Constraint_Layout_Logger_Interface $other
* @return array
*/
protected function findRecords($other)
{
if ($this->_arguments !== null) {
$this->setActualValue($other->findAll(self::ACTION_BLOCK_ACTION, $this->_target));
return $other->findByParameters(
self::ACTION_BLOCK_ACTION, $this->_target,
$this->_arguments, $this->_searchType
);
}
$records = $other->findAll(self::ACTION_BLOCK_ACTION, $this->_target);
$this->setActualValue($records);
return $records;
}
/**
* Evaluates that method was invoked at least once
*
* @param EcomDev_PHPUnit_Constraint_Layout_Logger_Interface $other
* @return boolean
*/
protected function evaluateInvoked($other)
{
$records = $this->findRecords($other);
return !empty($records);
}
/**
* Text representation of at least once invokation
*
* @return string
*/
protected function textInvoked()
{
$withArguments = '';
if ($this->_arguments !== null) {
$withArguments = ' with expected arguments';
}
return sprintf('block "%s" action for method "%s" was invoked%s',
$this->_blockName, $this->_method, $withArguments);
}
/**
* Evaluates that method was invoked
* at least expected number of times
*
* @param EcomDev_PHPUnit_Constraint_Layout_Logger_Interface $other
* @return boolean
*/
protected function evaluateInvokedAtLeast($other)
{
$records = $this->findRecords($other);
return count($records) >= $this->_expectedValue;
}
/**
* Text representation of at least expected times invokation
*
* @return string
*/
protected function textInvokedAtLeast()
{
return $this->textInvoked() . sprintf(' at least %d times', $this->_expectedValue);
}
/**
* Evaluates that method was invoked
* exactly expected number of times
*
* @param EcomDev_PHPUnit_Constraint_Layout_Logger_Interface $other
* @return boolean
*/
protected function evaluateInvokedExactly($other)
{
$records = $this->findRecords($other);
return count($records) === $this->_expectedValue;
}
/**
* Text representation of exactly times invokation
*
* @return string
*/
protected function textInvokedExactly()
{
return $this->textInvoked() . sprintf(' exactly %d times', $this->_expectedValue);
}
}
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Block property constraint
*
*/
class EcomDev_PHPUnit_Constraint_Layout_Block_Property
extends EcomDev_PHPUnit_Constraint_Layout_Abstract
{
const TYPE_CONSTRAINT = 'constraint';
/**
* Block name for constraint
*
* @var string
*/
protected $_blockName = null;
/**
* Block property for constraint
*
* @var string
*/
protected $_propertyName = null;
/**
* Block property constraint
*
* @return boolean
*/
public function __construct($blockName, $propertyName, PHPUnit_Framework_Constraint $constraint,
$type = self::TYPE_CONSTRAINT)
{
if (empty($blockName) || !is_string($blockName)) {
throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string', $blockName);
}
if (empty($propertyName) || !is_string($propertyName)) {
throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string', $propertyName);
}
parent::__construct($type, $constraint);
$this->_blockName = $blockName;
$this->_propertyName = $propertyName;
}
/**
* Retuns number of constraint assertions
*
* (non-PHPdoc)
* @see PHPUnit_Framework_Constraint::count()
*/
public function count()
{
return $this->_expectedValue->count();
}
/**
* Returning user friendly actual value
* (non-PHPdoc)
* @see EcomDev_PHPUnit_Constraint_Abstract::getActualValue()
*/
protected function getActualValue($other)
{
if ($this->_useActualValue) {
if ($this->_actualValue instanceof Varien_Object) {
$value = $this->_actualValue->debug();
} else {
$value = $this->_actualValue;
}
return PHPUnit_Util_Type::toString($value);
}
return '';
}
/**
* Evaluates a property constraint
*
* @param EcomDev_PHPUnit_Constraint_Layout_Logger_Interface $other
* @return boolean
*/
protected function evaluateConstraint($other)
{
$this->setActualValue(
$other->getBlockProperty($this->_blockName, $this->_propertyName)
);
return $this->_expectedValue->evaluate($this->_actualValue);
}
/**
* Text representation of block property constraint
*
* @return string
*/
protected function textConstraint()
{
return sprintf('block "%s" property "%s" %s',
$this->_blockName, $this->_propertyName,
$this->_expectedValue->toString());
}
}
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Constraint for testing layout handles load priority
*
*/
class EcomDev_PHPUnit_Constraint_Layout_Handle extends EcomDev_PHPUnit_Constraint_Layout_Abstract
{
const TYPE_LOADED = 'loaded';
const TYPE_LOADED_AFTER = 'loaded_after';
const TYPE_LOADED_BEFORE = 'loaded_before';
const ACTION_HANDLE_LOADED = EcomDev_PHPUnit_Constraint_Layout_Logger_Interface::ACTION_HANDLE_LOADED;
/**
* Position element of layout handle,
* for instance another handle
*
* @var string|null
*/
protected $_position = null;
/**
* Handle name
*
* @var string
*/
protected $_handle = null;
/**
* Layout handle constraint
*
*
* @param string $handle layout handle name
* @param string $type
* @param string|null $position layout handle position
*/
public function __construct($handle, $type, $position = null)
{
if ($position !== null && !is_string($position)) {
throw PHPUnit_Util_InvalidArgumentHelper::factory(3, 'string', $position);
}
$this->_position = $position;
$this->_handle = $handle;
$this->_expectedValueValidation += array(
self::TYPE_LOADED => array(true, 'is_string', 'string'),
self::TYPE_LOADED_AFTER => array(true, 'is_string', 'string'),
self::TYPE_LOADED_BEFORE => array(true, 'is_string', 'string')
);
$this->_typesWithDiff[] = self::TYPE_LOADED;
$this->_typesWithDiff[] = self::TYPE_LOADED_AFTER;
$this->_typesWithDiff[] = self::TYPE_LOADED_BEFORE;
parent::__construct($type, $this->_handle);
}
/**
* Evaluates that layout handle was loaded
*
*
* @param EcomDev_PHPUnit_Constraint_Layout_Logger_Interface $other
* @return boolean
*/
protected function evaluateLoaded($other)
{
$this->setActualValue(
$other->findAllTargets(self::ACTION_HANDLE_LOADED)
);
$this->_expectedValue = $this->_actualValue;
$match = $other->findFirst(self::ACTION_HANDLE_LOADED, $this->_handle) !== false;
if (!$match) {
$this->_expectedValue[] = $this->_handle;
}
return $match;
}
/**
* Text representation of layout handle loaded assertion
*
* @return string
*/
protected function textLoaded()
{
return sprintf('handle "%s" is loaded', $this->_handle);
}
/**
* Evaluates that layout handle was loaded after another
*
* @param EcomDev_PHPUnit_Constraint_Layout_Logger_Interface $other
* @return boolean
*/
protected function evaluateLoadedAfter($other)
{
$handleInfo = $other->findFirst(self::ACTION_HANDLE_LOADED, $this->_handle);
if ($handleInfo === false) {
return false;
}
$match = in_array($this->_position, $handleInfo['after']);
$this->setActualValue(
$handleInfo['before']
);
$this->_actualValue[] = $this->_handle;
$this->_expectedValue = $this->_actualValue;
if (!$match) {
array_splice(
$this->_expectedValue,
array_search($this->_handle, $this->_expectedValue),
0,
$this->_position
);
}
return $match;
}
/**
* Text representation of loaded after assertion
*
* @return string
*/
protected function textLoadedAfter()
{
return sprintf('handle "%s" is loaded after "%s"', $this->_handle, $this->_position);
}
/**
* Evaluates that layout handle was loaded after another
*
* @param EcomDev_PHPUnit_Constraint_Layout_Logger_Interface $other
* @return boolean
*/
protected function evaluateLoadedBefore($other)
{
$handleInfo = $other->findFirst(self::ACTION_HANDLE_LOADED, $this->_handle);
if ($handleInfo === false) {
return false;
}
$match = in_array($this->_position, $handleInfo['before']);
$this->setActualValue(
$handleInfo['before']
);
array_unshift($this->_actualValue, $this->_handle);
$this->_expectedValue = $this->_actualValue;
if (!$match) {
array_splice(
$this->_expectedValue,
array_search($this->_handle, $this->_expectedValue) + 1,
0,
$this->_position
);
}
return $match;
}
/**
* Text representation of loaded after assertion
*
* @return string
*/
protected function textLoadedBefore()
{
return sprintf('handle "%s" is loaded before "%s"', $this->_handle, $this->_position);
}
}
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Interface that should be implemented in layout model for
* making possible asserting layout actions
*
*/
interface EcomDev_PHPUnit_Constraint_Layout_Logger_Interface
{
const ACTION_HANDLE_LOADED = 'handle_loaded';
const ACTION_BLOCK_CREATED = 'block_created';
const ACTION_BLOCK_RENDERED = 'block_rendered';
const ACTION_BLOCK_REMOVED = 'block_removed';
const ACTION_BLOCK_ACTION = 'block_action';
const ACTION_RENDER = 'rendered';
const SEARCH_TYPE_OR = 'or';
const SEARCH_TYPE_AND = 'and';
const SEARCH_TYPE_EXACT = 'exact';
/**
* Records a particular target action
*
* @param string $action
* @param string $target
* @param array $parameters
* @return EcomDev_PHPUnit_Constraint_Layout_Logger_Interface
*/
public function record($action, $target, array $parameters = array());
/**
* Returns all actions performed on the target
* or if target is null returns actions for all targets
*
* @param string $action
* @param string|null $target
* @return array
*/
public function findAll($action, $target = null);
/**
* Returns all actions targets
*
* @param string $action
* @return array
*/
public function findAllTargets($action);
/**
* Returns first action that was recorded for target
*
* @param string $action
* @param string $target
* @return array|false
*/
public function findFirst($action, $target);
/**
* Returns target action records by specified parameters
*
*
* @param string $action
* @param string $target
* @param array $parameters
* @param string $searchType (or, and, exact)
* @return array|false
*/
public function findByParameters($action, $target, array $parameters, $searchType = self::SEARCH_TYPE_AND);
/**
* Returns block position information in the parent subling.
* Returned array contains two keys "before" and "after"
* which are list of block names in this positions
*
* @param string $block
* @return array
*/
public function getBlockPosition($block);
/**
* Returns block parent name
*
* @param string $block
* @return string|boolean
*/
public function getBlockParent($block);
/**
* Returns block property, even by getter
*
* @param string $block
* @return mixed
*/
public function getBlockProperty($block, $property);
/**
* Retuns a boolean flag for layout load status
*
* @return boolean
*/
public function isLoaded();
}
\ No newline at end of file
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Interface for request object, that will be asserted
*
*/
interface EcomDev_PHPUnit_Controller_Request_Interface
{
/**
* Returns current route name
*
* @return string
*/
public function getRouteName();
/**
* Returns current controller name
*
* @return string
*/
public function getControllerName();
/**
* Returns current controller module
*
* @return string
*/
public function getControllerModule();
/**
* Returns current controller action name
*
* @return string
*/
public function getActionName();
/**
* Retrieve property's value which was before forward call.
*
* @param string $name
* @return array|string|null
*/
public function getBeforeForwardInfo($name = null);
/**
* Check whether request was dispatched
*
*/
public function isDispatched();
}
\ No newline at end of file
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Interface for response object, that will be asserted
*
*/
interface EcomDev_PHPUnit_Controller_Response_Interface
{
/**
* Returns rendered headers array that was sent,
* if headers was not sent, then returns null
*
* @return array|null
*/
public function getSentHeaders();
/**
* Returns a particular header that was sent
*
* @param string $headerName
* @return string|false
*/
public function getSentHeader($headerName);
/**
* Returns rendered response, if response was not sent,
* then it returns null
*
* @return string|null
*/
public function getSentResponse();
/**
* Returns rendered body output
*
* @return string
*/
public function getOutputBody();
}
......@@ -20,7 +20,7 @@
* Interface for assertions in layout configuration
*
*/
interface EcomDev_PHPUnit_Constraint_Config_Layout_Design_Package_Interface
interface EcomDev_PHPUnit_Design_Package_Interface
{
/**
* Asserts layout file existance in design packages,
......
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Isolation interface,
* should be implemented on resetable Magento entities,
* that should be isolated during the test
*
*/
interface EcomDev_PHPUnit_Isolation_Interface
{
/**
* Unified method for reseting data
* in currently isolated object
*
*/
public function reset();
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment