From 86d344645c1d4c2ccff795176fa3112581a3fb95 Mon Sep 17 00:00:00 2001 From: joshporter Date: Thu, 14 Aug 2014 15:01:28 +0100 Subject: [PATCH 1/3] Initial example for configurable product --- .../Attributes/Provider/YamlProvider.php | 2 +- .../Manager/Builders/Configurable.php | 84 +++++++++++++++++++ src/MageTest/Manager/Builders/Order.php | 5 +- src/MageTest/Manager/FixtureManager.php | 71 +++++----------- .../Manager/Fixtures/Configurable.yml | 35 ++++++++ src/MageTest/Manager/Fixtures/Order.yml | 2 +- src/MageTest/Manager/Fixtures/Product.yml | 5 +- tests/MageTest/Manager/AddressTest.php | 10 ++- .../Manager/ConfigurableProductTest.php | 21 +++++ tests/MageTest/Manager/ProductTest.php | 7 +- tests/MageTest/Manager/WebTestCase.php | 2 +- 11 files changed, 182 insertions(+), 62 deletions(-) create mode 100644 src/MageTest/Manager/Builders/Configurable.php create mode 100644 src/MageTest/Manager/Fixtures/Configurable.yml create mode 100644 tests/MageTest/Manager/ConfigurableProductTest.php diff --git a/src/MageTest/Manager/Attributes/Provider/YamlProvider.php b/src/MageTest/Manager/Attributes/Provider/YamlProvider.php index dbd9210..b4563c8 100644 --- a/src/MageTest/Manager/Attributes/Provider/YamlProvider.php +++ b/src/MageTest/Manager/Attributes/Provider/YamlProvider.php @@ -20,7 +20,7 @@ class YamlProvider implements ProviderInterface */ public function readFile($file) { - $this->yaml = Yaml::parse($file); + return $this->yaml = Yaml::parse($file); } /** diff --git a/src/MageTest/Manager/Builders/Configurable.php b/src/MageTest/Manager/Builders/Configurable.php new file mode 100644 index 0000000..70608a9 --- /dev/null +++ b/src/MageTest/Manager/Builders/Configurable.php @@ -0,0 +1,84 @@ +attributes['configurable_attributes']; + + $configurableProductsData = array(); + $attributeIds = array(); + + foreach($configurableAttributes as $sku => $attributes) + { + $simpleProduct = \Mage::getModel('catalog/product'); + $simpleProduct->addData($this->attributes['simple_product_attributes']); + $simpleProduct->setSku($sku); + + $childAttributes = array(); + + foreach($attributes as $attributeCode => $value) + { + if(!isset($attributeDetails[$attributeCode])){ + $attributeDetails[$attributeCode] = $this->getAttributeDetails($attributeCode); + $attributeIds[] = $attributeDetails[$attributeCode]['id']; + } + + $valueIndex = $attributeDetails[$attributeCode]['options'][$value]; + + $childAttributes[] = array( + 'attribute_id' => $attributeDetails[$attributeCode]['id'], + 'label' => $value, + 'value_index' => $valueIndex, + 'pricing_value' => $simpleProduct->getPrice() + ); + + $simpleProduct->setData($attributeCode, $valueIndex); + } + + $simpleProduct->save(); + + $configurableProductsData[$simpleProduct->getId()] = $childAttributes; + } + + $this->model->addData($this->attributes['default_attributes']); + + $this->model->getTypeInstance()->setUsedProductAttributeIds($attributeIds); + $configurableAttributesData = $this->model->getTypeInstance()->getConfigurableAttributesAsArray(); + + $this->model->setCanSaveConfigurableAttributes(true); + $this->model->setConfigurableAttributesData($configurableAttributesData); + + $this->model->setConfigurableProductsData($configurableProductsData); + + return $this->model; + } + + private function getAttributeDetails($code) + { + $config = \Mage::getSingleton('eav/config'); + $attribute = $config->getAttribute(\Mage_Catalog_Model_Product::ENTITY, $code); + $options = $attribute->getSource()->getAllOptions(); + + $values = array(); + + foreach($options as $option){ + $values[$option['label']] = $option['value']; + } + + return array( + "id" => $attribute->getId(), + "options" => $values + ); + } +} diff --git a/src/MageTest/Manager/Builders/Order.php b/src/MageTest/Manager/Builders/Order.php index a590a54..efef9eb 100644 --- a/src/MageTest/Manager/Builders/Order.php +++ b/src/MageTest/Manager/Builders/Order.php @@ -17,7 +17,10 @@ class Order extends AbstractBuilder implements BuilderInterface */ public function withProduct($product, $qty = 1) { - $this->model->addProduct($product, new \Varien_Object(array( + $newProd = Mage::getModel('catalog/product'); + $newProd->load($newProd->getIdBySku($product->getSku())); + + $this->model->addProduct($newProd, new \Varien_Object(array( 'qty' => $qty ))); return $this; diff --git a/src/MageTest/Manager/FixtureManager.php b/src/MageTest/Manager/FixtureManager.php index 2db3039..54f184b 100644 --- a/src/MageTest/Manager/FixtureManager.php +++ b/src/MageTest/Manager/FixtureManager.php @@ -52,8 +52,11 @@ public function loadFixture($fixtureType, $userFixtureFile = null) $attributesProvider->readFile($fixtureFile); } + $attributes = $attributesProvider->readAttributes(); + $builder = $this->getBuilder($attributesProvider->getModelType()); - $builder->setAttributes($attributesProvider->readAttributes()); + + $builder->setAttributes($attributes); if($attributesProvider->hasFixtureDependencies()) { @@ -64,7 +67,7 @@ public function loadFixture($fixtureType, $userFixtureFile = null) } } - return $this->create($attributesProvider->getModelType(), $builder); + return $this->create($builder); } /** @@ -73,34 +76,25 @@ public function loadFixture($fixtureType, $userFixtureFile = null) * @return mixed * @throws \InvalidArgumentException */ - public function create($name, BuilderInterface $builder) + public function create(BuilderInterface $builder) { - if($this->hasFixture($name)) - { - throw new \InvalidArgumentException("Fixture $name has already been set. Please use unique names."); - } - $model = $builder->build(); + $savedCurrentStoreId = \Mage::app()->getStore()->getId(); \Mage::app()->setCurrentStore(\Mage_Core_Model_App::ADMIN_STORE_ID); $model->save(); - \Mage::app()->setCurrentStore(\Mage_Core_Model_App::DISTRO_STORE_ID); - - return $this->fixtures[$name] = $model; - } + \Mage::app()->setCurrentStore($savedCurrentStoreId); - /** - * @param $name - * @return mixed - * @throws \InvalidArgumentException - */ - public function getFixture($name) - { - if(!$this->hasFixture($name)) + if($model->getTypeId() === \Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE) { - throw new \InvalidArgumentException("Could not find a fixture: $name"); + $childProducts = \Mage::getModel('catalog/product_type_configurable')->getUsedProducts(null, $model); + foreach($childProducts as $product) + { + $this->fixtures[] = $product; + } } - return $this->fixtures[$name]; + + return $this->fixtures[] = $model; } /** @@ -116,39 +110,19 @@ public function clear() $this->fixtures = array(); } - /** - * @param $name - * @return bool - */ - private function hasFixture($name) { - return array_key_exists($name, $this->fixtures); - } - - /** - * @param $name - * @return bool - */ - private function hasBuilder($name) { - return array_key_exists($name, $this->builders); - } - /** * @param $modelType * @return Builders\Address|Builders\Customer|Builders\Order|Builders\Product */ private function getBuilder($modelType) { - if($this->hasBuilder($modelType)) - { - return $this->builders[$modelType]; - } - switch($modelType) { - case 'customer/address': return $this->builders[$modelType] = new Builders\Address($modelType); - case 'customer/customer': return $this->builders[$modelType] = new Builders\Customer($modelType); - case 'catalog/product': return $this->builders[$modelType] = new Builders\Product($modelType); - case 'sales/quote': return $this->builders[$modelType] = new Builders\Order($modelType); + case 'customer/address': return new Builders\Address($modelType); + case 'customer/customer': return new Builders\Customer($modelType); + case 'catalog/product/simple': return new Builders\Product('catalog/product'); + case 'catalog/product/configurable': return new Builders\Configurable('catalog/product'); + case 'sales/quote': return new Builders\Order($modelType); } } @@ -184,7 +158,8 @@ private function getDefaultFixtureTemplate($fixtureType) { case 'customer/address': return $filePath . 'Address.yml'; case 'customer/customer': return $filePath . 'Customer.yml'; - case 'catalog/product': return $filePath . 'Product.yml'; + case 'catalog/product/simple' : return $filePath . 'Product.yml'; + case 'catalog/product/configurable' : return $filePath . 'Configurable.yml'; case 'sales/quote': return $filePath . 'Order.yml'; } } diff --git a/src/MageTest/Manager/Fixtures/Configurable.yml b/src/MageTest/Manager/Fixtures/Configurable.yml new file mode 100644 index 0000000..471c9e0 --- /dev/null +++ b/src/MageTest/Manager/Fixtures/Configurable.yml @@ -0,0 +1,35 @@ +catalog/product/configurable: + default_attributes: + sku: test-conf + attribute_set_id: 9 + name: product name + weight: 2 + price: 100 + description: Product description + short_description: Product short description + tax_class_id: 4 + type_id: configurable + visibility: 4 + status: 1 + stock_data: { use_config_manage_stock: 0, manage_stock: 1, is_in_stock: 1 } + website_ids: [1] + simple_product_attributes: + website_ids: [1] + attribute_set_id: 9 + name: product name + tax_class_id: 4 + status: 1 + weight: 2 + price: 100 + description: Product description + short_description: Product short description + type_id: simple + visibility: 1 + stock_data: { use_config_manage_stock: 0, manage_stock: 1, min_sale_qty: 1, max_sale_qty: 2, is_in_stock: 1, qty: 999 } + configurable_attributes: + test-conf-1: + color: Green + test-conf-2: + color: Blue + test-conf-3: + color: Black \ No newline at end of file diff --git a/src/MageTest/Manager/Fixtures/Order.yml b/src/MageTest/Manager/Fixtures/Order.yml index 7abaad1..906e202 100644 --- a/src/MageTest/Manager/Fixtures/Order.yml +++ b/src/MageTest/Manager/Fixtures/Order.yml @@ -1,3 +1,3 @@ -sales/quote (customer/address catalog/product): +sales/quote (customer/address catalog/product/simple): shipping_method: flatrate_flatrate payment_method: checkmo \ No newline at end of file diff --git a/src/MageTest/Manager/Fixtures/Product.yml b/src/MageTest/Manager/Fixtures/Product.yml index eabc869..c37e26a 100644 --- a/src/MageTest/Manager/Fixtures/Product.yml +++ b/src/MageTest/Manager/Fixtures/Product.yml @@ -1,4 +1,4 @@ -catalog/product: +catalog/product/simple: sku: testsku123 attribute_set_id: 9 name: product name @@ -10,5 +10,6 @@ catalog/product: type_id: simple visibility: 4 status: 1 - stock_data: { is_in_stock: 1, qty: 99999 } + media_gallery: { images: [], values: [] } + stock_data: { use_config_manage_stock: 0, manage_stock: 1, is_in_stock: 1, qty: 999} website_ids: [1] \ No newline at end of file diff --git a/tests/MageTest/Manager/AddressTest.php b/tests/MageTest/Manager/AddressTest.php index 0784f3c..ae32fb7 100644 --- a/tests/MageTest/Manager/AddressTest.php +++ b/tests/MageTest/Manager/AddressTest.php @@ -13,18 +13,20 @@ protected function setUp() public function testAssignAddressToCustomer() { - $customer = $this->manager->getFixture('customer/customer'); + $customer = $this->addressFixture->getCustomer(); - $this->customerLogin($customer->getEmail(), $customer->getPassword()); + //hard coded due to hashing + $this->customerLogin($customer->getEmail(), '123123pass'); $this->assertSession()->pageTextContains($this->addressFixture->getPostcode()); } public function testDeleteAddressOfCustomer() { - $customer = $this->manager->getFixture('customer/customer'); + $customer = $this->addressFixture->getCustomer(); - $this->customerLogin($customer->getEmail(), $customer->getPassword()); + //hard coded due to hashing + $this->customerLogin($customer->getEmail(), '123123pass'); $this->manager->clear(); diff --git a/tests/MageTest/Manager/ConfigurableProductTest.php b/tests/MageTest/Manager/ConfigurableProductTest.php new file mode 100644 index 0000000..22041cd --- /dev/null +++ b/tests/MageTest/Manager/ConfigurableProductTest.php @@ -0,0 +1,21 @@ +configurableProductFixture = $this->manager->loadFixture('catalog/product/configurable'); + } + + public function testCreateConfigurableProduct() + { + $session = $this->getSession(); + $session->visit(getenv('BASE_URL') . '/catalog/product/view/id/' . $this->configurableProductFixture->getId()); + + $this->assertSession()->statusCodeEquals(200); + } +} \ No newline at end of file diff --git a/tests/MageTest/Manager/ProductTest.php b/tests/MageTest/Manager/ProductTest.php index 83154cd..f234f3d 100644 --- a/tests/MageTest/Manager/ProductTest.php +++ b/tests/MageTest/Manager/ProductTest.php @@ -8,7 +8,7 @@ class ProductTest extends WebTestCase protected function setUp() { parent::setUp(); - $this->productFixture = $this->manager->loadFixture('catalog/product'); + $this->productFixture = $this->manager->loadFixture('catalog/product/simple'); } public function testCreateSimpleProduct() @@ -27,16 +27,15 @@ public function testDeleteSimpleProduct() $this->assertSession()->statusCodeEquals(404); } - public function testCreateSimpleProductWithImage() +/* public function testCreateSimpleProductWithImage() { $imageURL = getcwd() . '/tests/MageTest/Manager/Assets/370x370.jpg'; - $this->productFixture->setMediaGallery (array('images'=>array (), 'values'=>array ())); $this->productFixture->addImageToMediaGallery($imageURL, array('image','thumbnail','small_image'), false, false); $this->productFixture->save(); $session = $this->getSession(); $session->visit(getenv('BASE_URL') . '/catalog/product/view/id/' . $this->productFixture->getId()); $this->assertSession()->elementExists('css', '#image'); - } + }*/ } \ No newline at end of file diff --git a/tests/MageTest/Manager/WebTestCase.php b/tests/MageTest/Manager/WebTestCase.php index d14d6a4..2c05daf 100644 --- a/tests/MageTest/Manager/WebTestCase.php +++ b/tests/MageTest/Manager/WebTestCase.php @@ -23,7 +23,7 @@ abstract class WebTestCase extends PHPUnit_Framework_Testcase protected function setUp() { - \Mage::init(); + \Mage::app(); $this->mink = new Mink(array( 'goutte' => new Session(new GoutteDriver()) )); From 72ade8d90516f40b052f807190fc8a8316ecfba1 Mon Sep 17 00:00:00 2001 From: joshporter Date: Fri, 15 Aug 2014 11:49:02 +0100 Subject: [PATCH 2/3] Clean up associated products after config product fixture deletion --- src/MageTest/Manager/FixtureManager.php | 35 ++++++++++++++++--------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/MageTest/Manager/FixtureManager.php b/src/MageTest/Manager/FixtureManager.php index 54f184b..1be2f0b 100644 --- a/src/MageTest/Manager/FixtureManager.php +++ b/src/MageTest/Manager/FixtureManager.php @@ -80,19 +80,9 @@ public function create(BuilderInterface $builder) { $model = $builder->build(); - $savedCurrentStoreId = \Mage::app()->getStore()->getId(); \Mage::app()->setCurrentStore(\Mage_Core_Model_App::ADMIN_STORE_ID); $model->save(); - \Mage::app()->setCurrentStore($savedCurrentStoreId); - - if($model->getTypeId() === \Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE) - { - $childProducts = \Mage::getModel('catalog/product_type_configurable')->getUsedProducts(null, $model); - foreach($childProducts as $product) - { - $this->fixtures[] = $product; - } - } + \Mage::app()->setCurrentStore(\Mage_Core_Model_App::DISTRO_STORE_ID); return $this->fixtures[] = $model; } @@ -104,9 +94,16 @@ public function clear() { foreach ($this->fixtures as $fixture) { \Mage::app()->setCurrentStore(\Mage_Core_Model_App::ADMIN_STORE_ID); + + if ($fixture->getTypeId() === \Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE) { + $this->clearAssociatedProducts($fixture); + } + $fixture->delete(); + \Mage::app()->setCurrentStore(\Mage_Core_Model_App::DISTRO_STORE_ID); } + $this->fixtures = array(); } @@ -163,4 +160,18 @@ private function getDefaultFixtureTemplate($fixtureType) case 'sales/quote': return $filePath . 'Order.yml'; } } -} + + /** + * @param $fixture + */ + private function clearAssociatedProducts($fixture) + { + $childIds = $fixture->getTypeInstance()->getChildrenIds($fixture->getId()); + + foreach ($childIds[0] as $value) { + $product = \Mage::getModel('catalog/product')->load($value); + $product->delete(); + $product->clearInstance(); + } + } +} \ No newline at end of file From 1737cfd99640a8a5820b7f547f68b0a8f42d2d07 Mon Sep 17 00:00:00 2001 From: joshporter Date: Fri, 15 Aug 2014 15:25:41 +0100 Subject: [PATCH 3/3] Implement simple product pricing for config products --- src/MageTest/Manager/Builders/Configurable.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/MageTest/Manager/Builders/Configurable.php b/src/MageTest/Manager/Builders/Configurable.php index 70608a9..eed530c 100644 --- a/src/MageTest/Manager/Builders/Configurable.php +++ b/src/MageTest/Manager/Builders/Configurable.php @@ -25,6 +25,11 @@ public function build() $simpleProduct->addData($this->attributes['simple_product_attributes']); $simpleProduct->setSku($sku); + if(isset($attributes['price'])){ + $simpleProduct->setPrice($attributes['price']); + unset($attributes['price']); + } + $childAttributes = array(); foreach($attributes as $attributeCode => $value)