diff --git a/assets/js/src/newsletter_editor/blocks/products.js b/assets/js/src/newsletter_editor/blocks/products.js index 79a3852949..54c15c34a5 100644 --- a/assets/js/src/newsletter_editor/blocks/products.js +++ b/assets/js/src/newsletter_editor/blocks/products.js @@ -568,6 +568,7 @@ ProductsDisplayOptionsSettingsView = base.BlockSettingsView.extend({ Module.ProductsWidgetView = base.WidgetView.extend({ className: base.WidgetView.prototype.className + ' mailpoet_droppable_layout_block', + id: 'automation_editor_block_products', getTemplate: function getTemplate() { return window.templates.productsInsertion; }, behaviors: { DraggableBehavior: { diff --git a/tests/DataFactories/WooCommerceProduct.php b/tests/DataFactories/WooCommerceProduct.php index c1b4ece394..18e044ef6e 100644 --- a/tests/DataFactories/WooCommerceProduct.php +++ b/tests/DataFactories/WooCommerceProduct.php @@ -22,7 +22,9 @@ class WooCommerceProduct { 'name' => 'Product', 'type' => self::TYPE_SIMPLE, 'sku' => 'WC_PR_'. uniqid(), - 'price' => 10 + 'price' => 10, + 'categoryId' => null, + 'tagId' => null ]; } @@ -50,6 +52,13 @@ class WooCommerceProduct { return $this->update('sku', $sku); } + /** + * @return $this + */ + function withRandomSku() { + return $this->update('sku', 'WC_PR_'. uniqid()); + } + /** * @param int $price * @return $this @@ -58,12 +67,49 @@ class WooCommerceProduct { return $this->update('price', $price); } + /** + * @param int $id + * @return $this + */ + function withCategory($id) { + return $this->update('categoryId', $id); + } + + /** + * @param int $id + * @return $this + */ + function withTag($id) { + return $this->update('tagId', $id); + } + function create() { - $create_output = $this->tester->cliToArray("wc product create --porcelain --allow-root --user=admin --name=\"{$this->data['name']}\" --sku=\"{$this->data['sku']}\" --type=\"{$this->data['type']}\" --regular_price={$this->data['price']}"); + $create_command = "wc product create --porcelain --allow-root --user=admin"; + $create_command .= " --name=\"{$this->data['name']}\""; + $create_command .= " --sku=\"{$this->data['sku']}\""; + $create_command .= " --type=\"{$this->data['type']}\""; + $create_command .= " --regular_price={$this->data['price']}"; + if ($this->data['categoryId']) { + $create_command .= " --categories='[{ \"id\": {$this->data['categoryId']} }]'"; + } + if ($this->data['tagId']) { + $create_command .= " --tags='[{ \"id\": {$this->data['tagId']} }]'"; + } + $create_output = $this->tester->cliToArray($create_command); $product_out = $this->tester->cliToArray("wc product get $create_output[0] --format=json --allow-root --user=admin"); return json_decode($product_out[0], true); } + function createCategory($name) { + $create_output = $this->tester->cliToArray("wc product_cat create --porcelain --allow-root --user=admin --name=\"{$name}\""); + return $create_output[0]; + } + + function createTag($name) { + $create_output = $this->tester->cliToArray("wc product_tag create --porcelain --allow-root --user=admin --name=\"{$name}\""); + return $create_output[0]; + } + /** * @param int $id */ diff --git a/tests/acceptance.suite.yml b/tests/acceptance.suite.yml index 6b9421a58f..7daeb8d911 100644 --- a/tests/acceptance.suite.yml +++ b/tests/acceptance.suite.yml @@ -18,7 +18,7 @@ modules: url: 'http://test.local' browser: chrome port: 4444 - window_size: '1024x768' + window_size: '1280x980' restart: true wait: 0 adminUsername: admin diff --git a/tests/acceptance/EditorProductsCest.php b/tests/acceptance/EditorProductsCest.php new file mode 100644 index 0000000000..9221e1104b --- /dev/null +++ b/tests/acceptance/EditorProductsCest.php @@ -0,0 +1,120 @@ +activateWooCommerce(); + $this->product_factory = new WooCommerceProduct($I); + + // Temporary requirement so products widget is displayed + $this->settings = new SettingsController(); + $this->settings->set('display_wc_products_widget', 1); + + // Create categories + $this->product_factory->createCategory(self::CATEGORY_ZERO_RESULTS); + $category_multiple_results_id = $this->product_factory->createCategory(self::CATEGORY_MULTIPLE_RESULTS); + + // Create products for multiple results + for ($i = 0; $i < self::PRODUCTS_COUNT; $i++) { + $this->product_factory + ->withRandomSku() + ->withName(self::KEYWORD_MULTIPLE_RESULTS . ' ' . Security::generateRandomString()) + ->create(); + $this->product_factory + ->withRandomSku() + ->withName(self::PRODUCT_PREFIX_CATEGORY . ' ' . Security::generateRandomString()) + ->withCategory($category_multiple_results_id) + ->create(); + } + } + + function filterProducts(\AcceptanceTester $I) { + $I->wantTo('Filter products'); + + $newsletterTitle = 'Newsletter Title'; + (new Newsletter()) + ->withSubject($newsletterTitle) + ->loadBodyFrom('newsletterWithText.json') + ->create(); + + $I->login(); + $I->amOnMailpoetPage('Emails'); + $I->waitForText($newsletterTitle); + $I->clickItemRowActionByItemName($newsletterTitle, 'Edit'); + + // Create products block + $I->waitForText('Products'); + $I->wait(1); // just to be sure + $I->dragAndDrop('#automation_editor_block_products', '#mce_0'); + $I->waitForText('PRODUCT SELECTION'); + + // Preload tags and categories + $I->click('.select2-search__field'); + $I->waitForElementNotVisible('.select2-results__option.loading-results'); + + // Zero results for category + $I->selectOptionInSelect2(self::CATEGORY_ZERO_RESULTS); + $I->waitForText('No products available'); + $this->clearCategories($I); + + // Multiple result for category + $I->selectOptionInSelect2(self::CATEGORY_MULTIPLE_RESULTS); + $I->waitForElementNotVisible('.mailpoet_post_scroll_container > div:nth-child(' . (self::PRODUCTS_COUNT + 1) . ')'); + $I->waitForText(self::PRODUCT_PREFIX_CATEGORY, 10, '.mailpoet_post_scroll_container'); + $I->seeNumberOfElements('.mailpoet_post_scroll_container > div', self::PRODUCTS_COUNT); + $this->clearCategories($I); + + // Click select2 to hide results + $I->click('.select2-search__field'); + + // Zero results for keyword + $I->fillField('.mailpoet_products_search_term', self::KEYWORD_ZERO_RESULTS); + $I->waitForText('No products available'); + + // Multiple result for keyword + $I->fillField('.mailpoet_products_search_term', self::KEYWORD_MULTIPLE_RESULTS); + $I->waitForElementNotVisible('.mailpoet_post_scroll_container > div:nth-child(' . (self::PRODUCTS_COUNT + 1) . ')'); + $I->waitForText(self::KEYWORD_MULTIPLE_RESULTS, 10, '.mailpoet_post_scroll_container'); + $I->seeNumberOfElements('.mailpoet_post_scroll_container > div', self::PRODUCTS_COUNT); + + // Product is clickable + $I->click('#mailpoet_select_post_0'); + $I->seeCheckboxIsChecked('#mailpoet_select_post_0'); + + // Searching for existing post should return zero results + $I->fillField('.mailpoet_products_search_term', self::POST_TITLE); + $I->waitForText('No products available'); + } + + private function clearCategories(\AcceptanceTester $I) { + $I->click('.select2-selection__clear'); + } + + function _after(\AcceptanceTester $I) { + $I->deactivateWooCommerce(); + } +}