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 e9104eec authored by Ivan Chepurnyi's avatar Ivan Chepurnyi

Merge branch 'release/0.3.5'

parents 1cd444fe 460f4a42
......@@ -372,7 +372,7 @@ class EcomDev_PHPUnit_Controller_Request_Http
*
* @see Mage_Core_Controller_Request_Http::getBaseUrl()
*/
public function getBaseUrl()
public function getBaseUrl($raw = false)
{
return $this->_baseUrl;
}
......
......@@ -124,11 +124,11 @@ class EcomDev_PHPUnit_Model_Config extends Mage_Core_Model_Config
*/
public function getModelInstance($modelClass='', $constructArguments=array())
{
if (!isset($this->_replaceInstanceCreation['model'][$modelClass])) {
return parent::getModelInstance($modelClass, $constructArguments);
if (!isset($this->_replaceInstanceCreation['model'][(string)$modelClass])) {
return parent::getModelInstance((string)$modelClass, $constructArguments);
}
return $this->_replaceInstanceCreation['model'][$modelClass];
return $this->_replaceInstanceCreation['model'][(string)$modelClass];
}
/**
......
......@@ -301,7 +301,7 @@ class EcomDev_PHPUnit_Model_Fixture
public function loadByTestCase(PHPUnit_Framework_TestCase $testCase)
{
$fixtures = EcomDev_PHPUnit_Test_Case_Util::getAnnotationByNameFromClass(
get_class($testCase), 'loadFixture', array('class', 'method'), $testCase->getName(false)
get_class($testCase), 'loadFixture', array('method', 'class'), $testCase->getName(false)
);
$this->_loadFixtureFiles($fixtures, $testCase);
......@@ -412,7 +412,7 @@ class EcomDev_PHPUnit_Model_Fixture
if (empty($this->_fixture)) {
$this->_fixture = $data;
} else {
$this->_fixture = array_merge_recursive($this->_fixture, $data);
$this->_fixture = array_replace_recursive($this->_fixture, $data);
}
return $this;
......
......@@ -139,6 +139,19 @@ class EcomDev_PHPUnit_Model_Fixture_Processor_Config
{
Mage::getConfig()->loadScopeSnapshot();
Mage::getConfig()->loadDb();
// Flush website and store configuration caches
foreach (Mage::app()->getWebsites(true) as $website) {
EcomDev_Utils_Reflection::setRestrictedPropertyValue(
$website, '_configCache', array()
);
}
foreach (Mage::app()->getStores(true) as $store) {
EcomDev_Utils_Reflection::setRestrictedPropertyValue(
$store, '_configCache', array()
);
}
return $this;
}
......@@ -160,9 +173,19 @@ class EcomDev_PHPUnit_Model_Fixture_Processor_Config
$value = $backend->getValue();
}
if (is_array($value)) {
Mage::throwException(
sprintf(
'There is a collision in configuration value %s. Got: %s',
$path,
print_r($value, true)
)
);
}
Mage::getConfig()->setNode($path, $value);
return $this;
}
}
\ No newline at end of file
}
......@@ -89,10 +89,15 @@ class EcomDev_PHPUnit_Model_Fixture_Processor_Eav
$this->getResource()->beginTransaction();
foreach ($data as $entityType => $values) {
$eavLoaders[] = $this->_getEavLoader($entityType)
$eavLoaders[$entityType] = $this->_getEavLoader($entityType)
->setFixture($fixture)
->setOptions($fixture->getOptions())
->loadEntity($entityType, $values);
->setOptions($fixture->getOptions());
if ($eavLoaders[$entityType] instanceof EcomDev_PHPUnit_Model_Mysql4_Fixture_RestoreAwareInterface) {
$eavLoaders[$entityType]->saveData($entityType);
}
$eavLoaders[$entityType]->loadEntity($entityType, $values);
}
$this->getResource()->commit();
......@@ -126,16 +131,35 @@ class EcomDev_PHPUnit_Model_Fixture_Processor_Eav
EcomDev_PHPUnit_Model_FixtureInterface::SCOPE_SHARED);
}
$typesToRestore = array();
$this->getResource()->beginTransaction();
foreach (array_keys($data) as $entityType) {
$eavLoader = $this->_getEavLoader($entityType);
if (in_array($entityType, $ignoreCleanUp)) {
if ($eavLoader instanceof EcomDev_PHPUnit_Model_Mysql4_Fixture_RestoreAwareInterface) {
$eavLoader->clearData($entityType);
}
continue;
}
$this->_getEavLoader($entityType)
->cleanEntity($entityType);
}
$eavLoader->cleanEntity($entityType);
if ($eavLoader instanceof EcomDev_PHPUnit_Model_Mysql4_Fixture_RestoreAwareInterface) {
$typesToRestore[$entityType] = $eavLoader;
}
}
$this->getResource()->commit();
if ($typesToRestore) {
$this->getResource()->beginTransaction();
foreach ($typesToRestore as $entityType => $eavLoader) {
$eavLoader->restoreData($entityType)
->clearData($entityType);
}
$this->getResource()->commit();
}
return $this;
}
}
\ No newline at end of file
......@@ -22,7 +22,10 @@
*/
abstract class EcomDev_PHPUnit_Model_Mysql4_Fixture_AbstractEav
extends EcomDev_PHPUnit_Model_Mysql4_Fixture_AbstractComplex
implements EcomDev_PHPUnit_Model_Mysql4_Fixture_RestoreAwareInterface
{
const RESTORE_KEY = 'restore_%s_data';
/**
* List of indexers required to build
*
......@@ -37,6 +40,20 @@ abstract class EcomDev_PHPUnit_Model_Mysql4_Fixture_AbstractEav
*/
protected $_originalIndexers = array();
/**
* List of tables that should be restored after run
*
* @var string[]
*/
protected $_restoreTables = array();
/**
* Default data for eav entity
*
* @var array
*/
protected $_defaultData = array();
/**
* Retrieve required indexers for re-building
*
......@@ -99,6 +116,69 @@ abstract class EcomDev_PHPUnit_Model_Mysql4_Fixture_AbstractEav
return $this;
}
/**
* Saves data for restoring it after fixture has been cleaned up
*
* @param string $code storage code
* @return $this
*/
public function saveData($code)
{
if ($this->_restoreTables) {
$storageKey = sprintf(self::RESTORE_KEY, $code);
$data = array();
foreach ($this->_restoreTables as $table) {
$select = $this->_getReadAdapter()->select();
$select->from($table);
$data[$table] = $this->_getReadAdapter()->fetchAll($select);
}
$this->_fixture->setStorageData($storageKey, $data);
}
return $this;
}
/**
* Restored saved data
*
* @param string $code storage code
* @return $this
*/
public function restoreData($code)
{
if ($this->_restoreTables) {
$storageKey = sprintf(self::RESTORE_KEY, $code);
$data = $this->_fixture->getStorageData($storageKey);
foreach ($this->_restoreTables as $table) {
if (!empty($data[$table])) {
$this->_getWriteAdapter()->insertOnDuplicate(
$table,
$data[$table]
);
}
}
}
return $this;
}
/**
* Clears storage from stored backup data
*
* @param $code
* @return $this
*/
public function clearData($code)
{
if ($this->_restoreTables) {
$storageKey = sprintf(self::RESTORE_KEY, $code);
$this->_fixture->setStorageData($storageKey, array());
}
return $this;
}
/**
* Loads EAV data into DB tables
*
......@@ -112,7 +192,7 @@ abstract class EcomDev_PHPUnit_Model_Mysql4_Fixture_AbstractEav
$this->_originalIndexers = $this->_requiredIndexers;
if (!empty($this->_options['addRequiredIndex'])) {
foreach ($this->_options['addRequiredIndex'] as $data) {
if (preg_match('/^([a-z0-9_\\-])+\\s+([a-z0-9_\\-])\s*$/i', $data, $match)
if (preg_match('/^([a-z0-9_\\-]+)\\s+([a-z0-9_\\-]+)\s*$/i', $data, $match)
&& $match[1] == $entityType) {
$this->_requiredIndexers[] = $match[2];
}
......@@ -139,16 +219,43 @@ abstract class EcomDev_PHPUnit_Model_Mysql4_Fixture_AbstractEav
// and rows list as value
// See getCustomTableRecords
$customValues = array();
if ($this->_defaultData) {
$dataToInsert = $this->_defaultData;
// Prevent insertion of default data,
// if there is already data available
foreach ($values as $index => $row) {
if (isset($row[$this->_getEntityIdField($entityTypeModel)])
&& isset($dataToInsert[$this->_getEntityIdField($entityTypeModel)])) {
$dataToInsert = array();
break;
}
}
foreach ($dataToInsert as $row) {
array_unshift($values, $row);
}
}
foreach ($values as $index => &$row) {
foreach ($values as $index => $row) {
if (!isset($row[$this->_getEntityIdField($entityTypeModel)])) {
throw new RuntimeException('Entity Id should be specified in EAV fixture');
}
// Fulfill necessary information
$row['entity_type_id'] = $entityTypeModel->getEntityTypeId();
$values[$index]['entity_type_id'] = $entityTypeModel->getEntityTypeId();
$row = $values[$index];
if (!isset($row['attribute_set_id'])) {
$row['attribute_set_id'] = $entityTypeModel->getDefaultAttributeSetId();
$defaultAttributeSet = $entityTypeModel->getDefaultAttributeSetId();
// Fix Magento core issue with attribute set information for customer and its address
if (in_array($entityType, array('customer', 'customer_address'))) {
$defaultAttributeSet = 0;
}
$values[$index]['attribute_set_id'] = $defaultAttributeSet;
}
// Preparing entity table record
......
......@@ -23,9 +23,36 @@
*/
class EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Catalog_Category extends EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Catalog_Abstract
{
const XML_PATH_DEFAULT_DATA = 'phpunit/suite/fixture/default_data/category';
protected $_requiredIndexers = array(
'catalog_category_flat'
);
protected function _construct()
{
parent::_construct();
$defaultData = Mage::getConfig()->getNode(self::XML_PATH_DEFAULT_DATA);
if ($defaultData) {
foreach ($defaultData->children() as $item) {
if (!isset($item->entity_id)) {
continue;
}
$entityId = (string)$item->entity_id;
$this->_defaultData[$entityId] = array();
foreach ($item->children() as $value) {
$this->_defaultData[$entityId][$value->getName()] = (string)$value;
}
}
}
$this->_restoreTables[] = $this->getTable('catalog/category');
foreach (array('datetime', 'decimal', 'int', 'text', 'varchar') as $suffix) {
$this->_restoreTables[] = $this->getTable(array('catalog/category', $suffix));
}
}
/**
* Overridden to add easy fixture loading for product associations
......
<?php
interface EcomDev_PHPUnit_Model_Mysql4_Fixture_RestoreAwareInterface
{
/**
* Saves data for restoring it after fixture has been cleaned up
*
* @param string $code storage code
* @return $this
*/
public function saveData($code);
/**
* Restored saved data
*
* @param string $code storage code
* @return $this
*/
public function restoreData($code);
/**
* Clears storage from stored backup data
*
* @param $code
* @return $this
*/
public function clearData($code);
}
\ No newline at end of file
......@@ -43,10 +43,19 @@ class EcomDev_PHPUnit_Test_Case_Helper_Session
*/
public function helperMockSession($classAlias, array $methods = array())
{
if (!empty($methods) && !in_array('start', $methods, true)) {
$methods[] = 'start';
}
$sessionMock = EcomDev_PHPUnit_Helper::invoke('mockModel', $classAlias, $methods)
->disableOriginalConstructor();
TestUtil::replaceByMock('singleton', $classAlias, $sessionMock);
$sessionMock->expects($this->testCase->any())
->method('start')
->willReturnSelf();
return $sessionMock;
}
......@@ -58,6 +67,8 @@ class EcomDev_PHPUnit_Test_Case_Helper_Session
*/
public function helperAdminSession(array $resources = array())
{
$this->helperMockSession('core/session', array('renew'));
$this->helperMockSession('adminhtml/session', array('renew'));
$session = $this->helperMockSession('admin/session', array('refreshAcl'));
$user = $this->createUser();
$this->loadRules($user, $this->getAcl(), $resources);
......
......@@ -50,6 +50,8 @@ class EcomDev_PHPUnit_Test_Suite extends PHPUnit_Framework_TestSuite
$suite = new self('Magento Test Suite');
$excludedModules = Mage::getConfig()->getNode('phpunit/suite/exclude');
// Walk through different groups in modules for finding test cases
foreach ($groups->children() as $group) {
foreach ($modules->children() as $module) {
......@@ -58,6 +60,10 @@ class EcomDev_PHPUnit_Test_Suite extends PHPUnit_Framework_TestSuite
$suite->addTest(self::warning('There is no module with name: ' . $module->getName()));
continue;
}
if (isset($excludedModules->{$module->getName()})) {
continue;
}
$moduleCodeDir = Mage::getBaseDir('code') . DS . (string) $realModule->codePool;
$searchPath = Mage::getModuleDir('', $module->getName()) . DS . 'Test' . DS . (string) $group;
......
......@@ -68,9 +68,18 @@ class EcomDev_PHPUnit_Test_Suite_Group extends PHPUnit_Framework_TestSuite
* impossibility for specifying group by parent test case
* Because it is a very dirty hack :(
**/
$testGroups = array();
$testGroups = EcomDev_Utils_Reflection::getRestrictedPropertyValue($test, 'groups');
foreach ($groups as $group) {
$testGroups[$group] = $test->tests();
if(!isset($testGroups[$group])) {
$testGroups[$group] = $test->tests();
} else {
foreach($test->tests() as $subTest) {
if(!in_array($subTest, $testGroups[$group], true)) {
$testGroups[$group][] = $subTest;
}
}
}
}
EcomDev_Utils_Reflection::setRestrictedPropertyValue(
......
......@@ -55,6 +55,8 @@
</global>
<phpunit>
<suite>
<modules /> <!-- List of modules included into test suite -->
<exclude /> <!-- List of modules that are excluded from test suite -->
<yaml>
<model>ecomdev_phpunit/yaml_loader</model>
<loaders>
......@@ -112,6 +114,37 @@
<catalog_product>ecomdev_phpunit/fixture_eav_catalog_product</catalog_product>
<catalog_category>ecomdev_phpunit/fixture_eav_catalog_category</catalog_category>
</eav>
<default_data>
<category>
<root>
<entity_id>1</entity_id>
<parent_id>0</parent_id>
<path>1</path>
<position>0</position>
<level>0</level>
<children_count>1</children_count>
<name>Root Catalog</name>
<url_key>root-catalog</url_key>
<is_active>1</is_active>
<is_anchor>0</is_anchor>
<attribute_set_id>0</attribute_set_id>
</root>
<default_category>
<entity_id>2</entity_id>
<parent_id>1</parent_id>
<path>1/2</path>
<position>1</position>
<level>1</level>
<children_count>0</children_count>
<name>Default Category</name>
<url_key>default-category</url_key>
<is_active>1</is_active>
<is_anchor>0</is_anchor>
<display_mode>PRODUCTS</display_mode>
<include_in_menu>1</include_in_menu>
</default_category>
</category>
</default_data>
</fixture>
<app>
<!-- Application class name for running tests -->
......
<?php
/**
* @loadSharedFixture testFixtureArrayMerge.yaml
*/
class EcomDev_PHPUnitTest_Test_Model_Fixture extends EcomDev_PHPUnit_Test_Case
{
public function testFixtureArrayMerge()
{
require_once($this->_getVfsUrl('app/code/community/EcomDev/PHPUnit/Test/Model/ExampleClass.php'));
$testCase = new EcomDev_PHPUnitTest_Test_Model_ExampleClass();
$testCase->setName('testLoadFixtureOrder');
$this->getFixture()->loadForClass(get_class($testCase));
$this->getFixture()->loadByTestCase($testCase);
$this->getFixture()->apply();
}
public function testLoadClassBeforeMethodFixtures()
{
require_once($this->_getVfsUrl('app/code/community/EcomDev/PHPUnit/Test/Model/ExampleClass.php'));
$testCase = new EcomDev_PHPUnitTest_Test_Model_ExampleClass();
$testCase->setName('testLoadFixtureOrder');
$this->getFixture()->loadForClass(get_class($testCase));
$this->getFixture()->loadByTestCase($testCase);
$this->getFixture()->apply();
$this->assertEquals('methodFixtureValue', Mage::getStoreConfig('sample/path'));
}
protected function _getVfsUrl($path)
{
return $this->getFixture()->getVfs()->url($path);
}
}
vfs:
app:
code:
community:
EcomDev:
PHPUnit:
Test:
Model:
ExampleClass.php: |
<?php
/**
* @loadSharedFixture sharedClassFixture.yaml
* @loadFixture classFixture.yaml
*/
class EcomDev_PHPUnitTest_Test_Model_ExampleClass extends EcomDev_PHPUnit_Test_Case
{
/**
* @loadSharedFixture sharedMethodFixture.yaml
* @loadFixture methodFixture.yaml
*/
public function testLoadFixtureOrder()
{
}
}
fixtures:
classFixture.yaml: >
config:
default/sample/path: classFixtureValue
sharedClassFixture.yaml: >
config:
default/sample/path: sharedClassFixtureValue
sharedMethodFixture.yaml: >
config:
default/sample/path: sharedMethodFixtureValue
methodFixture.yaml: >
config:
default/sample/path: methodFixtureValue
......@@ -8,6 +8,9 @@
"magento-hackathon/magento-composer-installer": "*",
"phpunit/phpunit": "4.1.*"
},
"replace": {
"ivanchepurnyi/ecomdev_phpunit":"*"
},
"authors":[
{
"name":"Ivan Chepurnyi"
......
......@@ -292,7 +292,7 @@ class EcomDev_PHPUnit_Constraint_Layout_Block extends EcomDev_PHPUnit_Constraint
return false;
}
return $blockInfo['root'] === true;
return $blockInfo['is_root'] === true;
}
/**
......
......@@ -81,7 +81,7 @@ class EcomDev_PHPUnit_Constraint_Layout_Block_Property
* (non-PHPdoc)
* @see EcomDev_PHPUnit_ConstraintAbstract::getActualValue()
*/
protected function getActualValue($other)
protected function getActualValue($other = null)
{
if ($this->_useActualValue) {
if ($this->_actualValue instanceof Varien_Object) {
......
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