We will work on Apr 26th (Saturday) and will be off from Apr 30th (Wednesday) until May 2nd (Friday) for public holiday in our country

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()) { ...@@ -10,6 +10,10 @@ if (!Mage::isInstalled()) {
exit('Magento Unit Tests can be runned only on installed version'); 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::app('admin');
Mage::getConfig()->init(); 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 ...@@ -32,11 +32,29 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
// Admin store code // Admin store code
const ADMIN_STORE_CODE = 'admin'; const ADMIN_STORE_CODE = 'admin';
const AREA_ADMINHTML = 'adminhtml'; const AREA_ADMINHTML = EcomDev_PHPUnit_Model_App_Area::AREA_ADMINHTML;
const AREA_FRONTEND = 'frontend'; 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_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_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 * Old configuration model to be returned back
...@@ -84,11 +102,14 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App ...@@ -84,11 +102,14 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
protected static $_eventCollectionClass = 'Varien_Event_Collection'; 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 * Enabled events flag
...@@ -97,6 +118,13 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App ...@@ -97,6 +118,13 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
*/ */
protected $_eventsEnabled = true; protected $_eventsEnabled = true;
/**
* Dispatched events array
*
* @var array
*/
protected $_dispatchedEvents = array();
/** /**
* List of module names stored by class name * List of module names stored by class name
* *
...@@ -165,22 +193,196 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App ...@@ -165,22 +193,196 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
// Init modules runs install proccess for table structures, // Init modules runs install proccess for table structures,
// It is required for setting up proper setup script // It is required for setting up proper setup script
$this->_initModules(); $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()) { if ($this->_config->isLocalConfigLoaded()) {
$this->_initCurrentStore(self::ADMIN_STORE_CODE, self::RUN_TYPE_STORE); $this->_initCurrentStore(self::ADMIN_STORE_CODE, self::RUN_TYPE_STORE);
$this->_initRequest(); $this->_initRequest();
Mage_Core_Model_Resource_Setup::applyAllDataUpdates(); Mage_Core_Model_Resource_Setup::applyAllDataUpdates();
} }
$layoutModel = Mage::getModel( $layoutModel = $this->_getModelFromConfig(
$this->getConfig()->getNode(self::XML_PATH_LAYOUT_MODEL_FOR_TEST) 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'
); );
Mage::register(self::REGISTRY_PATH_LAYOUT_SINGLETON, $layoutModel, true); $this->replaceRegistry(self::REGISTRY_PATH_DESIGN_PACKAGE_SINGLETON,
$designPackageModel);
$this->loadAreaPart(self::AREA_TEST, self::AREA_PART_EVENTS);
return $this; 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;
}
/**
* 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 * Overriden to fix issue with stores loading
* (non-PHPdoc) * (non-PHPdoc)
...@@ -254,6 +456,30 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App ...@@ -254,6 +456,30 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
return $this; 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 * Disables events fire
* *
...@@ -287,8 +513,42 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App ...@@ -287,8 +513,42 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
{ {
if ($this->_eventsEnabled) { if ($this->_eventsEnabled) {
parent::dispatchEvent($eventName, $args); 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; 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 @@ ...@@ -23,6 +23,10 @@
*/ */
class EcomDev_PHPUnit_Model_Config extends Mage_Core_Model_Config 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, * Scope snapshot without applied configurations,
* It is used for proper store/website/default loading on per store basis * 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 ...@@ -212,6 +216,7 @@ class EcomDev_PHPUnit_Model_Config extends Mage_Core_Model_Config
$merge = clone $this->_prototype; $merge = clone $this->_prototype;
if ($merge->loadFile($this->_getLocalXmlForTest())) { if ($merge->loadFile($this->_getLocalXmlForTest())) {
$this->_checkDbCredentialForDuplicate($this, $merge); $this->_checkDbCredentialForDuplicate($this, $merge);
$this->_checkBaseUrl($this, $merge);
$this->extend($merge); $this->extend($merge);
} else { } else {
throw new Exception('Unable to load local.xml.phpunit'); throw new Exception('Unable to load local.xml.phpunit');
...@@ -254,6 +259,30 @@ class EcomDev_PHPUnit_Model_Config extends Mage_Core_Model_Config ...@@ -254,6 +259,30 @@ class EcomDev_PHPUnit_Model_Config extends Mage_Core_Model_Config
return $this; 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, * Retrieves local.xml file path for tests,
* If it is not found, method will rise an exception * If it is not found, method will rise an exception
......
...@@ -2,7 +2,9 @@ ...@@ -2,7 +2,9 @@
class EcomDev_PHPUnit_Model_Design_Package class EcomDev_PHPUnit_Model_Design_Package
extends Mage_Core_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, * Asserts layout file existance in design packages,
......
...@@ -22,7 +22,10 @@ ...@@ -22,7 +22,10 @@
* for testing the layout itself * 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 * List of replaced blocks creation
...@@ -31,6 +34,30 @@ class EcomDev_PHPUnit_Model_Layout extends Mage_Core_Model_Layout ...@@ -31,6 +34,30 @@ class EcomDev_PHPUnit_Model_Layout extends Mage_Core_Model_Layout
*/ */
protected $_replaceBlockCreation = array(); 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 * Replaces creation of some block by mock object
* *
...@@ -82,6 +109,7 @@ class EcomDev_PHPUnit_Model_Layout extends Mage_Core_Model_Layout ...@@ -82,6 +109,7 @@ class EcomDev_PHPUnit_Model_Layout extends Mage_Core_Model_Layout
$this->_helpers = array(); $this->_helpers = array();
$this->_directOutput = false; $this->_directOutput = false;
$this->_output = array(); $this->_output = array();
$this->_records = array();
foreach ($this->_blocks as $block) { foreach ($this->_blocks as $block) {
// Remove references between blocks // Remove references between blocks
...@@ -91,8 +119,376 @@ class EcomDev_PHPUnit_Model_Layout extends Mage_Core_Model_Layout ...@@ -91,8 +119,376 @@ class EcomDev_PHPUnit_Model_Layout extends Mage_Core_Model_Layout
} }
$this->_blocks = array(); $this->_blocks = array();
return $this;
}
/**
* Returns all the recorded actions
*
* @return array
*/
public function getRecords()
{
return $this->_records;
}
/**
* 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());
}
}
$this->flushReplaceBlockCreation();
return $this; 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 ...@@ -55,6 +55,182 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
*/ */
protected $_originalStore = null; 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 * Retrieves the module name for current test case
...@@ -64,7 +240,7 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase ...@@ -64,7 +240,7 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
*/ */
public function getModuleName() 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 ...@@ -155,10 +331,10 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
} }
if (in_array($type, array('model', 'resource_model'))) { 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); $type = str_replace('model', 'singleton', $type);
} elseif ($type == 'block') { } elseif ($type == 'block') {
Mage::app()->getLayout()->replaceBlockCreation($classAlias, $mock); $this->app()->getLayout()->replaceBlockCreation($classAlias, $mock);
} }
if (in_array($type, array('singleton', 'resource_singleton', 'helper'))) { if (in_array($type, array('singleton', 'resource_singleton', 'helper'))) {
...@@ -178,7 +354,8 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase ...@@ -178,7 +354,8 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
protected function replaceRegistry($key, $value) protected function replaceRegistry($key, $value)
{ {
$oldValue = Mage::registry($key); $oldValue = Mage::registry($key);
Mage::register($key, $value, true);
$this->app()->replaceRegistry($key, $value);
$this->_replacedRegistry[$key] = $oldValue; $this->_replacedRegistry[$key] = $oldValue;
return $this; return $this;
...@@ -291,7 +468,7 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase ...@@ -291,7 +468,7 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
$mockClassAlias = '', $callOriginalConstructor = true, $mockClassAlias = '', $callOriginalConstructor = true,
$callOriginalClone = true, $callAutoload = true) $callOriginalClone = true, $callAutoload = true)
{ {
return $this->getGroupedClassMock('model', $methods, $isAbstract, return $this->getGroupedClassMock('model', $classAlias, $methods, $isAbstract,
$constructorArguments, $mockClassAlias, $constructorArguments, $mockClassAlias,
$callOriginalConstructor, $callOriginalClone, $callOriginalConstructor, $callOriginalClone,
$callAutoload); $callAutoload);
...@@ -315,7 +492,7 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase ...@@ -315,7 +492,7 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
$mockClassAlias = '', $callOriginalConstructor = true, $mockClassAlias = '', $callOriginalConstructor = true,
$callOriginalClone = true, $callAutoload = true) $callOriginalClone = true, $callAutoload = true)
{ {
return $this->getGroupedClassMock('resource_model', $methods, $isAbstract, return $this->getGroupedClassMock('resource_model', $classAlias, $methods, $isAbstract,
$constructorArguments, $mockClassAlias, $constructorArguments, $mockClassAlias,
$callOriginalConstructor, $callOriginalClone, $callOriginalConstructor, $callOriginalClone,
$callAutoload); $callAutoload);
...@@ -339,7 +516,7 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase ...@@ -339,7 +516,7 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
$mockClassAlias = '', $callOriginalConstructor = true, $mockClassAlias = '', $callOriginalConstructor = true,
$callOriginalClone = true, $callAutoload = true) $callOriginalClone = true, $callAutoload = true)
{ {
return $this->getGroupedClassMock('helper', $methods, $isAbstract, return $this->getGroupedClassMock('helper', $classAlias, $methods, $isAbstract,
$constructorArguments, $mockClassAlias, $constructorArguments, $mockClassAlias,
$callOriginalConstructor, $callOriginalClone, $callOriginalConstructor, $callOriginalClone,
$callAutoload); $callAutoload);
...@@ -363,7 +540,7 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase ...@@ -363,7 +540,7 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
$mockClassAlias = '', $callOriginalConstructor = true, $mockClassAlias = '', $callOriginalConstructor = true,
$callOriginalClone = true, $callAutoload = true) $callOriginalClone = true, $callAutoload = true)
{ {
return $this->getGroupedClassMock('block', $methods, $isAbstract, return $this->getGroupedClassMock('block', $classAlias, $methods, $isAbstract,
$constructorArguments, $mockClassAlias, $constructorArguments, $mockClassAlias,
$callOriginalConstructor, $callOriginalClone, $callOriginalConstructor, $callOriginalClone,
$callAutoload); $callAutoload);
...@@ -378,10 +555,10 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase ...@@ -378,10 +555,10 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
protected function getGroupedClassName($type, $classAlias) protected function getGroupedClassName($type, $classAlias)
{ {
if ($type === 'resource_model') { 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 ...@@ -398,7 +575,7 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
* @param boolean $callAutoload * @param boolean $callAutoload
* @return PHPUnit_Framework_MockObject_MockObject * @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(), array $constructorArguments = array(),
$mockClassAlias = '', $callOriginalConstructor = true, $mockClassAlias = '', $callOriginalConstructor = true,
$callOriginalClone = true, $callAutoload = true) $callOriginalClone = true, $callAutoload = true)
...@@ -486,7 +663,7 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase ...@@ -486,7 +663,7 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
if (current($annotationValue)) { if (current($annotationValue)) {
$classAlias = current($annotationValue); $classAlias = current($annotationValue);
} else { } else {
$classAlias = Mage::getConfig()->getNode($configPath); $classAlias = $this->app()->getConfig()->getNode($configPath);
} }
return $classAlias; return $classAlias;
...@@ -554,6 +731,7 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase ...@@ -554,6 +731,7 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
$annotations = $this->getAnnotations(); $annotations = $this->getAnnotations();
$this->getFixture()->setOptions($annotations['method']); $this->getFixture()->setOptions($annotations['method']);
$this->getFixture()->apply(); $this->getFixture()->apply();
$this->app()->resetDispatchedEvents();
parent::setUp(); parent::setUp();
} }
...@@ -586,11 +764,11 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase ...@@ -586,11 +764,11 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
public function setCurrentStore($store) public function setCurrentStore($store)
{ {
if (!$this->_originalStore) { if (!$this->_originalStore) {
$this->_originalStore = Mage::app()->getStore(); $this->_originalStore = $this->app()->getStore();
} }
Mage::app()->setCurrentStore( $this->app()->setCurrentStore(
Mage::app()->getStore($store) $this->app()->getStore($store)
); );
return $this; return $this;
} }
...@@ -603,7 +781,7 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase ...@@ -603,7 +781,7 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
protected function tearDown() protected function tearDown()
{ {
if ($this->_originalStore) { // Remove store scope, that was set in test if ($this->_originalStore) { // Remove store scope, that was set in test
Mage::app()->setCurrentStore($this->_originalStore); $this->app()->setCurrentStore($this->_originalStore);
$this->_originalStore = null; $this->_originalStore = null;
} }
...@@ -611,12 +789,11 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase ...@@ -611,12 +789,11 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
$this->getExpectation()->discard(); $this->getExpectation()->discard();
} }
Mage::getConfig()->flushReplaceInstanceCreation(); $this->app()->getConfig()->flushReplaceInstanceCreation();
$this->app()->getLayout()->flushReplaceBlockCreation();
Mage::app()->getLayout()->reset();
foreach ($this->_replacedRegistry as $registryPath => $originalValue) { foreach ($this->_replacedRegistry as $registryPath => $originalValue) {
Mage::register($registryPath, $originalValue, true); $this->app()->replaceRegistry($registryPath, $originalValue);
} }
$this->getFixture()->discard(); // Clear applied fixture $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 ...@@ -29,7 +29,7 @@ class EcomDev_PHPUnit_Test_Suite extends PHPUnit_Framework_TestSuite
// Configuration path constants // Configuration path constants
const XML_PATH_UNIT_TEST_GROUPS = 'phpunit/suite/groups'; const XML_PATH_UNIT_TEST_GROUPS = 'phpunit/suite/groups';
const XML_PATH_UNIT_TEST_MODULES = 'phpunit/suite/modules'; 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 XML_PATH_UNIT_TEST_SUITE = 'phpunit/suite/test_suite';
const CACHE_TAG = 'ECOMDEV_PHPUNIT'; const CACHE_TAG = 'ECOMDEV_PHPUNIT';
const CACHE_TYPE = 'ecomdev_phpunit'; const CACHE_TYPE = 'ecomdev_phpunit';
......
...@@ -51,12 +51,18 @@ ...@@ -51,12 +51,18 @@
<helpers>Helper</helpers> <helpers>Helper</helpers>
<blocks>Block</blocks> <blocks>Block</blocks>
<config>Config</config> <config>Config</config>
<controllers>Controller</controllers>
</groups> </groups>
<!-- Test suite that will be used for creation of each of the tests --> <!-- Test suite that will be used for creation of each of the tests -->
<test_suite>EcomDev_PHPUnit_Test_Suite_Group</test_suite> <test_suite>EcomDev_PHPUnit_Test_Suite_Group</test_suite>
<layout> <layout>
<model>ecomdev_phpunit/layout</model> <model>ecomdev_phpunit/layout</model>
</layout> </layout>
<design>
<package>
<model>ecomdev_phpunit/design_package</model>
</package>
</design>
<expectation> <expectation>
<!-- Default model for loading of expectations --> <!-- Default model for loading of expectations -->
<model>ecomdev_phpunit/expectation</model> <model>ecomdev_phpunit/expectation</model>
...@@ -73,8 +79,27 @@ ...@@ -73,8 +79,27 @@
<catalog_category>ecomdev_phpunit/fixture_eav_catalog_category</catalog_category> <catalog_category>ecomdev_phpunit/fixture_eav_catalog_category</catalog_category>
</eav> </eav>
</fixture> </fixture>
<!-- Application model class name for running tests --> <app>
<app>EcomDev_PHPUnit_Model_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> <modules>
<!-- Place your module name in your module config.xml <!-- Place your module name in your module config.xml
For adding it to test suite --> For adding it to test suite -->
...@@ -84,4 +109,17 @@ ...@@ -84,4 +109,17 @@
</modules> </modules>
</suite> </suite>
</phpunit> </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> </config>
...@@ -9,4 +9,17 @@ ...@@ -9,4 +9,17 @@
</default_setup> </default_setup>
</resources> </resources>
</global> </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> </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 ...@@ -44,17 +44,14 @@ class EcomDev_PHPUnit_Constraint_Config extends PHPUnit_Framework_Constraint
*/ */
public function __construct($constraint) public function __construct($constraint)
{ {
$this->config = $config;
if (!$constraint instanceof EcomDev_PHPUnit_Constraint_Config_Interface) { if (!$constraint instanceof EcomDev_PHPUnit_Constraint_Config_Interface) {
throw PHPUnit_Util_InvalidArgumentHelper::factory( throw PHPUnit_Util_InvalidArgumentHelper::factory(
1, 'EcomDev_PHPUnit_Constraint_Config_Interface' 1, 'EcomDev_PHPUnit_Constraint_Config_Interface'
); );
} }
$this->constraint = $constraint; $this->constraint = $constraint;
} }
/** /**
* *
* @param mixed $other * @param mixed $other
......
...@@ -21,31 +21,9 @@ ...@@ -21,31 +21,9 @@
* *
*/ */
abstract class EcomDev_PHPUnit_Constraint_Config_Abstract abstract class EcomDev_PHPUnit_Constraint_Config_Abstract
extends PHPUnit_Framework_Constraint extends EcomDev_PHPUnit_Constraint_Abstract
implements EcomDev_PHPUnit_Constraint_Config_Interface 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 * Config node path defined in the constructor
* *
...@@ -53,34 +31,6 @@ abstract class EcomDev_PHPUnit_Constraint_Config_Abstract ...@@ -53,34 +31,6 @@ abstract class EcomDev_PHPUnit_Constraint_Config_Abstract
*/ */
protected $_nodePath = null; 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 * Constraint constructor
* *
...@@ -94,56 +44,8 @@ abstract class EcomDev_PHPUnit_Constraint_Config_Abstract ...@@ -94,56 +44,8 @@ abstract class EcomDev_PHPUnit_Constraint_Config_Abstract
throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string', $type); 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->_nodePath = $nodePath;
$this->_type = $type; parent::__construct($type, $expectedValue);
$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;
} }
/** /**
...@@ -158,22 +60,10 @@ abstract class EcomDev_PHPUnit_Constraint_Config_Abstract ...@@ -158,22 +60,10 @@ abstract class EcomDev_PHPUnit_Constraint_Config_Abstract
} }
/** /**
* Calls internal protected method by defined constraint type * Automatically evaluate to false if the node was not found
* Also can be passed a single argument
* *
* @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) * (non-PHPdoc)
* @see PHPUnit_Framework_Constraint::evaluate() * @see EcomDev_PHPUnit_Constraint_Abstract::evaluate()
*/ */
public function evaluate($other) public function evaluate($other)
{ {
...@@ -182,59 +72,39 @@ abstract class EcomDev_PHPUnit_Constraint_Config_Abstract ...@@ -182,59 +72,39 @@ abstract class EcomDev_PHPUnit_Constraint_Config_Abstract
return false; 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) * @param Varien_Simplexml_Element $other
* @see PHPUnit_Framework_Constraint::fail() * @return scalar
*/ */
public function fail($other, $description, $not = FALSE) protected function getActualValue($other = null)
{ {
$failureDescription = $this->failureDescription($other, $description, $not); if (!$this->_useActualValue && $other->hasChildren()) {
return $other->asNiceXml();
if (in_array($this->_type, $this->_typesWithDiff)) { } elseif (!$this->_useActualValue) {
if ($this->_useActualValue) { return (string) $other;
$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;
}
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 * Returns a scalar representation of expected value
* (non-PHPdoc) *
* @see PHPUnit_Framework_SelfDescribing::toString() * @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 ...@@ -99,9 +99,9 @@ class EcomDev_PHPUnit_Constraint_Config_Layout
/** /**
* Sets design package model for assertions * 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; self::$_designPackageModel = $model;
} }
...@@ -109,7 +109,7 @@ class EcomDev_PHPUnit_Constraint_Config_Layout ...@@ -109,7 +109,7 @@ class EcomDev_PHPUnit_Constraint_Config_Layout
/** /**
* Retrieves design package model that was set before * 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() public static function getDesignPackageModel()
{ {
...@@ -162,7 +162,7 @@ class EcomDev_PHPUnit_Constraint_Config_Layout ...@@ -162,7 +162,7 @@ class EcomDev_PHPUnit_Constraint_Config_Layout
->getLayoutFileAssertion($this->_expectedValue, $this->_area, $this->_designPackage, $this->_theme); ->getLayoutFileAssertion($this->_expectedValue, $this->_area, $this->_designPackage, $this->_theme);
$this->setActualValue($assertion['actual']); $this->setActualValue($assertion['actual']);
$this->_expectedValue = $assertin['expected']; $this->_expectedValue = $assertion['expected'];
return $this->_actualValue !== $this->_expectedValue; 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 ...@@ -27,6 +27,10 @@ class EcomDev_PHPUnit_Constraint_Exception extends PHPUnit_Framework_Expectation
public function __construct($description, $diff = '', $message = '') public function __construct($description, $diff = '', $message = '')
{ {
if (!is_scalar($diff)) {
$diff = print_r($diff, true);
}
$this->diff = $diff; $this->diff = $diff;
parent::__construct($description, null, $message); 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 @@ ...@@ -20,7 +20,7 @@
* Interface for assertions in layout configuration * 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, * 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