View source
<?php
namespace Drupal\Tests\commerce_product\Functional;
use Drupal\commerce\EntityHelper;
use Drupal\commerce_price\Price;
use Drupal\commerce_product\Entity\Product;
use Drupal\commerce_product\Entity\ProductVariation;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\Tests\TestFileCreationTrait;
use Drupal\user\Entity\Role;
use Drupal\user\RoleInterface;
class ProductAdminTest extends ProductBrowserTestBase {
use TestFileCreationTrait;
protected $testImage;
public static $modules = [
'file',
'image',
];
protected function setUp() : void {
parent::setUp();
FieldStorageConfig::create([
'field_name' => 'field_image',
'type' => 'image',
'entity_type' => 'commerce_product_variation',
])
->save();
FieldConfig::create([
'field_name' => 'field_image',
'entity_type' => 'commerce_product_variation',
'bundle' => 'default',
'label' => 'Image',
'settings' => [
'alt_field_required' => FALSE,
],
])
->save();
$form_display = EntityFormDisplay::load('commerce_product_variation.default.default');
$form_display
->setComponent('field_image', [
'type' => 'image_image',
]);
$form_display
->save();
$file_system = \Drupal::service('file_system');
$this->testImage = current($this
->getTestFiles('image'));
$this->testImage->realpath = $file_system
->realpath($this->testImage->uri);
}
public function testCreateProduct() {
$this
->drupalGet('admin/commerce/products');
$this
->getSession()
->getPage()
->clickLink('Add product');
$store_ids = EntityHelper::extractIds($this->stores);
$title = $this
->randomMachineName();
$edit = [
'title[0][value]' => $title,
];
foreach ($store_ids as $store_id) {
$edit['stores[target_id][value][' . $store_id . ']'] = $store_id;
}
$this
->submitForm($edit, 'Save');
$result = \Drupal::entityTypeManager()
->getStorage('commerce_product')
->getQuery()
->condition("title", $edit['title[0][value]'])
->accessCheck(FALSE)
->range(0, 1)
->execute();
$product_id = reset($result);
$product = Product::load($product_id);
$this
->assertNotNull($product, 'The new product has been created.');
$this
->assertSession()
->pageTextContains(t('The product @title has been successfully saved', [
'@title' => $title,
]));
$this
->assertSession()
->pageTextContains($title);
$this
->assertFieldValues($product
->getStores(), $this->stores, 'Created product has the correct associated stores.');
$this
->assertFieldValues($product
->getStoreIds(), $store_ids, 'Created product has the correct associated store ids.');
$this
->drupalGet($product
->toUrl('canonical'));
$this
->assertSession()
->statusCodeEquals(200);
$this
->assertSession()
->pageTextContains($product
->getTitle());
}
public function testEditProduct() {
$product = $this
->createEntity('commerce_product', [
'type' => 'default',
]);
$this
->drupalGet($product
->toUrl('edit-form'));
$this
->assertSession()
->statusCodeEquals(200);
$this
->assertSession()
->fieldExists('title[0][value]');
$title = $this
->randomMachineName();
$store_ids = EntityHelper::extractIds($this->stores);
$edit = [
'title[0][value]' => $title,
];
foreach ($store_ids as $store_id) {
$edit['stores[target_id][value][' . $store_id . ']'] = $store_id;
}
$this
->submitForm($edit, 'Save');
$this->container
->get('entity_type.manager')
->getStorage('commerce_product')
->resetCache([
$product
->id(),
]);
$product = Product::load($product
->id());
$this
->assertEquals($product
->getTitle(), $title, 'The product title successfully updated.');
$this
->assertFieldValues($product
->getStores(), $this->stores, 'Updated product has the correct associated stores.');
$this
->assertFieldValues($product
->getStoreIds(), $store_ids, 'Updated product has the correct associated store ids.');
}
public function testDeleteProduct() {
$product = $this
->createEntity('commerce_product', [
'title' => $this
->randomMachineName(),
'type' => 'default',
]);
$this
->drupalGet($product
->toUrl('delete-form'));
$this
->assertSession()
->pageTextContains(t("Are you sure you want to delete the product @product?", [
'@product' => $product
->getTitle(),
]));
$this
->assertSession()
->pageTextContains(t('This action cannot be undone.'));
$this
->submitForm([], 'Delete');
$this->container
->get('entity_type.manager')
->getStorage('commerce_product')
->resetCache();
$product_exists = (bool) Product::load($product
->id());
$this
->assertEmpty($product_exists, 'The new product has been deleted from the database.');
}
public function testAdminProducts() {
$this
->drupalGet('admin/commerce/products');
$this
->assertSession()
->statusCodeEquals(200);
$this
->assertSession()
->pageTextNotContains('You are not authorized to access this page.');
$this
->assertNotEmpty($this
->getSession()
->getPage()
->hasLink('Add product'));
$product = $this
->createEntity('commerce_product', [
'type' => 'default',
'title' => 'First product',
'status' => TRUE,
]);
$values = [
'id' => 'random',
'label' => 'Random',
'description' => 'My random product type',
'variationType' => 'default',
];
$product_type = $this
->createEntity('commerce_product_type', $values);
$second_product = $this
->createEntity('commerce_product', [
'type' => 'random',
'title' => 'Second product',
'status' => FALSE,
]);
$third_product = $this
->createEntity('commerce_product', [
'type' => 'random',
'title' => 'Third product',
'status' => TRUE,
]);
$this
->drupalGet('admin/commerce/products');
$this
->assertSession()
->pageTextNotContains('You are not authorized to access this page.');
$row_count = $this
->getSession()
->getPage()
->findAll('xpath', '//table/tbody/tr');
$this
->assertEquals(3, count($row_count));
$page = $this
->getSession()
->getPage();
$product_count = $page
->findAll('xpath', '//table/tbody/tr/td/a[text()="First product"]');
$this
->assertEquals(1, count($product_count), 'First product is displayed.');
$product_count = $page
->findAll('xpath', '//table/tbody/tr/td/a[text()="Second product"]');
$this
->assertEquals(1, count($product_count), 'Second product is displayed.');
$product_count = $page
->findAll('xpath', '//table/tbody/tr/td/a[text()="Third product"]');
$this
->assertEquals(1, count($product_count), 'Third product is displayed.');
$product_count = $page
->findAll('xpath', '//table/tbody/tr/td[starts-with(text(), "Default")]');
$this
->assertEquals(1, count($product_count), 'Default product type exists in the table.');
$product_count = $page
->findAll('xpath', '//table/tbody/tr/td[starts-with(text(), "Random")]');
$this
->assertEquals(2, count($product_count), 'Random product types exist in the table.');
$product_count = $page
->findAll('xpath', '//table/tbody/tr/td[starts-with(text(), "Unpublished")]');
$this
->assertEquals(1, count($product_count), 'Unpublished product exists in the table.');
$product_count = $page
->findAll('xpath', '//table/tbody/tr/td[starts-with(text(), "Published")]');
$this
->assertEquals(2, count($product_count), 'Published products exist in the table.');
$this
->drupalLogout();
$this
->drupalGet('admin/commerce/products');
$this
->assertSession()
->pageTextContains('You are not authorized to access this page.');
$this
->assertEmpty($this
->getSession()
->getPage()
->hasLink('Add product'));
$user = $this
->drupalCreateUser([
'access commerce_product overview',
]);
$this
->drupalLogin($user);
$this
->drupalGet('admin/commerce/products');
$this
->assertSession()
->pageTextNotContains('You are not authorized to access this page.');
$this
->assertEmpty($this
->getSession()
->getPage()
->hasLink('Add product'));
$row_count = $this
->getSession()
->getPage()
->findAll('xpath', '//table/tbody/tr');
$this
->assertEquals(2, count($row_count));
$page = $this
->getSession()
->getPage();
$product_count = $page
->findAll('xpath', '//table/tbody/tr/td/a[text()="First product"]');
$this
->assertEquals(1, count($product_count), 'First product is displayed.');
$product_count = $page
->findAll('xpath', '//table/tbody/tr/td/a[text()="Third product"]');
$this
->assertEquals(1, count($product_count), 'Third product is displayed.');
$product_count = $page
->findAll('xpath', '//table/tbody/tr/td[starts-with(text(), "Unpublished")]');
$this
->assertEquals(0, count($product_count), 'Unpublished product do not exist in the table.');
$product_count = $page
->findAll('xpath', '//table/tbody/tr/td[starts-with(text(), "Published")]');
$this
->assertEquals(2, count($product_count), 'Published products exist in the table.');
$this
->assertSession()
->optionExists('edit-type', 'default');
$this
->assertSession()
->optionExists('edit-type', 'random');
$product_count = $page
->findAll('xpath', '//table/tbody/tr/td[starts-with(text(), "Default")]');
$this
->assertEquals(1, count($product_count));
$product_count = $page
->findAll('xpath', '//table/tbody/tr/td[starts-with(text(), "Random")]');
$this
->assertEquals(1, count($product_count));
$authenticated_role = Role::load(RoleInterface::AUTHENTICATED_ID);
$authenticated_role
->revokePermission('view commerce_product');
$authenticated_role
->save();
$this
->drupalGet('admin/commerce/products');
$this
->assertSession()
->pageTextContains('No products available');
$this
->assertSession()
->optionNotExists('edit-type', 'default');
$this
->assertSession()
->optionNotExists('edit-type', 'random');
$authenticated_role
->grantPermission('view default commerce_product');
$authenticated_role
->save();
$this
->drupalGet('admin/commerce/products');
$this
->assertSession()
->optionExists('edit-type', 'default');
$this
->assertSession()
->optionNotExists('edit-type', 'random');
$product_count = $page
->findAll('xpath', '//table/tbody/tr/td[starts-with(text(), "Default")]');
$this
->assertEquals(1, count($product_count));
$product_count = $page
->findAll('xpath', '//table/tbody/tr/td[starts-with(text(), "Random")]');
$this
->assertEquals(0, count($product_count));
$user = $this
->drupalCreateUser([
'access commerce_product overview',
'view own unpublished commerce_product',
]);
$second_product
->setOwnerId($user
->id());
$second_product
->save();
$this
->drupalLogin($user);
$this
->drupalGet('admin/commerce/products');
$this
->assertSession()
->statusCodeEquals(200);
$this
->assertSession()
->pageTextNotContains('You are not authorized to access this page.');
$product_count = $page
->findAll('xpath', '//table/tbody/tr/td/a[text()="Second product"]');
$this
->assertEquals(1, count($product_count), 'Second product is displayed.');
}
public function testVariationsTab() {
$this
->drupalGet('admin/commerce/products');
$this
->getSession()
->getPage()
->clickLink('Add product');
$store_ids = EntityHelper::extractIds($this->stores);
$title = $this
->randomMachineName();
$edit = [
'title[0][value]' => $title,
];
foreach ($store_ids as $store_id) {
$edit['stores[target_id][value][' . $store_id . ']'] = $store_id;
}
$this
->submitForm($edit, 'Save and add variations');
$this
->assertSession()
->pageTextContains(t('The product @title has been successfully saved', [
'@title' => $title,
]));
$this
->assertSession()
->pageTextContains(t('There are no product variations yet.'));
$this
->getSession()
->getPage()
->clickLink('Add variation');
$variation_sku = $this
->randomMachineName();
$this
->getSession()
->getPage()
->fillField('sku[0][value]', $variation_sku);
$this
->getSession()
->getPage()
->fillField('price[0][number]', '9.99');
$this
->submitForm([
'files[field_image_0]' => $this->testImage->realpath,
], 'field_image_0_upload_button');
$this
->assertSession()
->buttonExists('field_image_0_remove_button');
$this
->submitForm([], 'Save');
$this
->assertSession()
->pageTextContains("Saved the {$title} variation.");
$variation_in_table = $this
->getSession()
->getPage()
->find('xpath', '//table/tbody/tr/td[text()="' . $variation_sku . '"]');
$this
->assertNotEmpty($variation_in_table);
$product = Product::load(1);
$variation = ProductVariation::load(1);
$this
->assertEquals($product
->id(), $variation
->getProductId());
$this
->assertEquals($variation_sku, $variation
->getSku());
$this
->assertFalse($variation
->get('field_image')
->isEmpty());
$this->container
->get('entity_type.manager')
->getStorage('commerce_product')
->resetCache([
$product
->id(),
]);
$product = Product::load($product
->id());
$this
->assertTrue($product
->hasVariation($variation));
}
public function testEditVariation() {
$product = $this
->createEntity('commerce_product', [
'type' => 'default',
]);
$variation = $this
->createEntity('commerce_product_variation', [
'type' => 'default',
'product_id' => $product
->id(),
'sku' => strtolower($this
->randomMachineName()),
]);
$this
->drupalGet($variation
->toUrl('edit-form'));
$this
->assertSession()
->statusCodeEquals(200);
$this
->assertSession()
->fieldExists('sku[0][value]');
$this
->assertSession()
->fieldExists('price[0][number]');
$this
->assertSession()
->buttonExists('Save');
$new_sku = strtolower($this
->randomMachineName());
$new_price_amount = '1.11';
$variations_edit = [
'sku[0][value]' => $new_sku,
'price[0][number]' => $new_price_amount,
'status[value]' => 1,
];
$this
->submitForm($variations_edit, 'Save');
$this
->assertSession()
->addressEquals($variation
->toUrl('collection'));
$this->container
->get('entity_type.manager')
->getStorage('commerce_product_variation')
->resetCache([
$variation
->id(),
]);
$variation = ProductVariation::load($variation
->id());
$this
->assertEquals($new_sku, $variation
->getSku());
$this
->assertEquals($new_price_amount, $variation
->getPrice()
->getNumber());
}
public function testDuplicateVariation() {
$sku = strtolower($this
->randomMachineName());
$product = $this
->createEntity('commerce_product', [
'type' => 'default',
]);
$variation = $this
->createEntity('commerce_product_variation', [
'type' => 'default',
'product_id' => $product
->id(),
'sku' => $sku,
'price' => [
'number' => '12.00',
'currency_code' => 'USD',
],
'status' => TRUE,
]);
$this
->drupalGet($variation
->toUrl('duplicate-form'));
$this
->assertSession()
->statusCodeEquals(200);
$this
->assertSession()
->fieldExists('sku[0][value]');
$this
->assertSession()
->fieldExists('price[0][number]');
$this
->assertSession()
->buttonExists('Save');
$this
->submitForm([], 'Save');
$this
->assertSession()
->addressEquals($variation
->toUrl('duplicate-form'));
$this
->assertSession()
->pageTextContains(sprintf('The SKU "%s" is already in use and must be unique.', $sku));
$new_sku = strtolower($this
->randomMachineName());
$variations_edit = [
'sku[0][value]' => $new_sku,
];
$this
->submitForm($variations_edit, 'Save');
$this
->assertSession()
->addressEquals($variation
->toUrl('collection'));
$expected_variation_id = $variation
->id() + 1;
$variation = ProductVariation::load($expected_variation_id);
$this
->assertEquals($new_sku, $variation
->getSku());
$this
->assertEquals('12.00', $variation
->getPrice()
->getNumber());
$this
->assertTrue($variation
->isPublished());
}
public function testDeleteVariation() {
$product = $this
->createEntity('commerce_product', [
'title' => $this
->randomMachineName(),
'type' => 'default',
]);
$variation = $this
->createEntity('commerce_product_variation', [
'type' => 'default',
'product_id' => $product
->id(),
'sku' => strtolower($this
->randomMachineName()),
]);
$this
->drupalGet($variation
->toUrl('delete-form'));
$this
->assertSession()
->pageTextContains(t("Are you sure you want to delete the @variation variation?", [
'@variation' => $variation
->label(),
]));
$this
->assertSession()
->pageTextContains(t('This action cannot be undone.'));
$this
->submitForm([], 'Delete');
$this
->assertSession()
->addressEquals($variation
->toUrl('collection'));
$this->container
->get('entity_type.manager')
->getStorage('commerce_product_variation')
->resetCache();
$variation_exists = (bool) ProductVariation::load($variation
->id());
$this
->assertEmpty($variation_exists, 'The new variation has been deleted from the database.');
}
public function testSingleVariationMode() {
$this
->drupalGet('admin/commerce/config/product-types/default/edit');
$this
->submitForm([
'multipleVariations' => FALSE,
], 'Save');
$this
->drupalGet('admin/commerce/products');
$this
->getSession()
->getPage()
->clickLink('Add product');
$this
->assertSession()
->buttonNotExists('Save and add variations');
$this
->assertSession()
->fieldExists('variations[entity][sku][0][value]');
$title = 'Mug';
$store_id = $this->stores[0]
->id();
$sku = strtolower($this
->randomMachineName());
$page = $this
->getSession()
->getPage();
$page
->fillField('title[0][value]', $title);
$page
->fillField('stores[target_id][value][' . $store_id . ']', $store_id);
$page
->fillField('variations[entity][sku][0][value]', $sku);
$page
->fillField('variations[entity][price][0][number]', '99.99');
$this
->submitForm([
'files[variations_entity_field_image_0]' => $this->testImage->realpath,
], 'variations_entity_field_image_0_upload_button');
$this
->assertSession()
->buttonExists('variations_entity_field_image_0_remove_button');
$this
->submitForm([], 'Save');
$this
->assertSession()
->pageTextNotContains(sprintf('The SKU "%s" is already in use and must be unique.', $sku));
$this
->assertSession()
->pageTextContains('The product Mug has been successfully saved');
$product = Product::load(1);
$this
->assertNotEmpty($product);
$this
->assertEquals($title, $product
->getTitle());
$this
->assertEquals([
$store_id,
], $product
->getStoreIds());
$variation = $product
->getDefaultVariation();
$this
->assertNotEmpty($variation);
$this
->assertEquals($sku, $variation
->getSku());
$this
->assertEquals(new Price('99.99', 'USD'), $variation
->getPrice());
$this
->assertFalse($variation
->get('field_image')
->isEmpty());
$this
->drupalGet($product
->toUrl('edit-form'));
$edit = [
'title[0][value]' => 'New title',
'variations[entity][price][0][number]' => '199.99',
];
$this
->submitForm($edit, 'Save');
\Drupal::entityTypeManager()
->getStorage('commerce_product')
->resetCache([
1,
]);
\Drupal::entityTypeManager()
->getStorage('commerce_product_variation')
->resetCache([
1,
]);
$product = Product::load(1);
$this
->assertNotEmpty($product);
$this
->assertEquals('New title', $product
->getTitle());
$this
->assertEquals([
$store_id,
], $product
->getStoreIds());
$variation = $product
->getDefaultVariation();
$this
->assertNotEmpty($variation);
$this
->assertEquals(1, $variation
->id());
$this
->assertEquals($sku, $variation
->getSku());
$this
->assertEquals(new Price('199.99', 'USD'), $variation
->getPrice());
$this
->drupalGet($variation
->toUrl('collection'));
$this
->assertSession()
->statusCodeEquals('403');
}
public function testMixedMode() {
$form_display = EntityFormDisplay::load('commerce_product.default.default');
$form_display
->setComponent('variations', [
'type' => 'commerce_product_single_variation',
'weight' => 2,
]);
$form_display
->save();
$this
->drupalGet('admin/commerce/products');
$this
->getSession()
->getPage()
->clickLink('Add product');
$this
->assertSession()
->buttonExists('Save and add variations');
$this
->assertSession()
->fieldExists('variations[entity][sku][0][value]');
$title = 'Mug';
$store_id = $this->stores[0]
->id();
$sku = strtolower($this
->randomMachineName());
$page = $this
->getSession()
->getPage();
$page
->fillField('title[0][value]', $title);
$page
->fillField('stores[target_id][value][' . $store_id . ']', $store_id);
$page
->fillField('variations[entity][sku][0][value]', $sku);
$page
->fillField('variations[entity][price][0][number]', '99.99');
$this
->submitForm([], 'Save and add variations');
$product = Product::load(1);
$this
->assertNotEmpty($product);
$this
->assertEquals($title, $product
->getTitle());
$this
->assertEquals([
$store_id,
], $product
->getStoreIds());
$variation = $product
->getDefaultVariation();
$this
->assertNotEmpty($variation);
$this
->assertEquals($sku, $variation
->getSku());
$this
->assertEquals(new Price('99.99', 'USD'), $variation
->getPrice());
$this
->drupalGet($product
->toUrl('edit-form'));
$edit = [
'title[0][value]' => 'New title',
'variations[entity][price][0][number]' => '199.99',
];
$this
->submitForm($edit, 'Save');
\Drupal::entityTypeManager()
->getStorage('commerce_product')
->resetCache([
1,
]);
\Drupal::entityTypeManager()
->getStorage('commerce_product_variation')
->resetCache([
1,
]);
$product = Product::load(1);
$this
->assertNotEmpty($product);
$this
->assertEquals('New title', $product
->getTitle());
$this
->assertEquals([
$store_id,
], $product
->getStoreIds());
$variation = $product
->getDefaultVariation();
$this
->assertNotEmpty($variation);
$this
->assertEquals(1, $variation
->id());
$this
->assertEquals($sku, $variation
->getSku());
$this
->assertEquals(new Price('199.99', 'USD'), $variation
->getPrice());
}
}