diff --git a/cypress/apiRequests/Product.js b/cypress/apiRequests/Product.js
index 3e1763da0..e0eda23c9 100644
--- a/cypress/apiRequests/Product.js
+++ b/cypress/apiRequests/Product.js
@@ -1,4 +1,7 @@
+import Utils from "./utils/Utils";
+
class Product {
+ utils = new Utils();
getFirstProducts(first, search) {
const filter = search
? `, filter:{
@@ -23,13 +26,13 @@ class Product {
.then(resp => resp.body.data.products.edges);
}
- updateChannelInProduct(
+ updateChannelInProduct({
productId,
channelId,
isPublished = true,
isAvailableForPurchase = true,
visibleInListings = true
- ) {
+ }) {
const mutation = `mutation{
productChannelListingUpdate(id:"${productId}",
input:{
@@ -94,19 +97,22 @@ class Product {
price = 1,
costPrice = 1
) {
- const channelListings = channelId
- ? `channelListings:{
+ const channelListings = this.utils.getValueWithDefault(
+ channelId,
+ `channelListings:{
channelId:"${channelId}"
price:"${price}"
costPrice:"${costPrice}"
}`
- : "";
- const stocks = warehouseId
- ? `stocks:{
+ );
+
+ const stocks = this.utils.getValueWithDefault(
+ warehouseId,
+ `stocks:{
warehouse:"${warehouseId}"
quantity:${quantity}
}`
- : "";
+ );
const mutation = `mutation{
productVariantBulkCreate(product: "${productId}", variants: {
diff --git a/cypress/apiRequests/frontShop/ProductDetails.js b/cypress/apiRequests/frontShop/ProductDetails.js
deleted file mode 100644
index bb6e77c95..000000000
--- a/cypress/apiRequests/frontShop/ProductDetails.js
+++ /dev/null
@@ -1,32 +0,0 @@
-class ProductDetails {
- getProductDetails(productId, channelId) {
- return cy.request({
- method: "POST",
- url: Cypress.env("API_URI"),
- headers: {
- authorization: `JWT ${window.localStorage.getItem("token")}`
- },
- body: [
- {
- operationName: "ProductDetails",
- variables: {
- channel: channelId,
- id: productId
- },
- query:
- "fragment BasicProductFields on Product {\n id\n name\n thumbnail {\n url\n alt\n __typename\n }\n thumbnail2x: thumbnail(size: 510) {\n url\n __typename\n }\n __typename\n}\n\nfragment SelectedAttributeFields on SelectedAttribute {\n attribute {\n id\n name\n __typename\n }\n values {\n id\n name\n __typename\n }\n __typename\n}\n\nfragment Price on TaxedMoney {\n gross {\n amount\n currency\n __typename\n }\n net {\n amount\n currency\n __typename\n }\n __typename\n}\n\nfragment ProductVariantFields on ProductVariant {\n id\n sku\n name\n quantityAvailable(countryCode: $countryCode)\n images {\n id\n url\n alt\n __typename\n }\n pricing {\n onSale\n priceUndiscounted {\n ...Price\n __typename\n }\n price {\n ...Price\n __typename\n }\n __typename\n }\n attributes(variantSelection: VARIANT_SELECTION) {\n attribute {\n id\n name\n slug\n __typename\n }\n values {\n id\n name\n value: name\n __typename\n }\n __typename\n }\n __typename\n}\n\nfragment ProductPricingField on Product {\n pricing {\n onSale\n priceRangeUndiscounted {\n start {\n ...Price\n __typename\n }\n stop {\n ...Price\n __typename\n }\n __typename\n }\n priceRange {\n start {\n ...Price\n __typename\n }\n stop {\n ...Price\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n}\n\nquery ProductDetails($id: ID!, $channel: String, $countryCode: CountryCode) {\n product(id: $id, channel: $channel) {\n ...BasicProductFields\n ...ProductPricingField\n description\n category {\n id\n name\n products(first: 3, channel: $channel) {\n edges {\n node {\n ...BasicProductFields\n ...ProductPricingField\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n }\n images {\n id\n alt\n url\n __typename\n }\n attributes {\n ...SelectedAttributeFields\n __typename\n }\n variants {\n ...ProductVariantFields\n __typename\n }\n seoDescription\n seoTitle\n isAvailable\n isAvailableForPurchase\n availableForPurchase\n __typename\n }\n}\n"
- }
- ]
- });
- }
- isAvailableForPurchaseFromResp(resp) {
- return resp.body[0].data.product.isAvailableForPurchase;
- }
- isProductExist(resp, name) {
- return (
- resp.body[0].data.product !== null &&
- resp.body[0].data.product.name === name
- );
- }
-}
-export default ProductDetails;
diff --git a/cypress/apiRequests/frontShop/Search.js b/cypress/apiRequests/frontShop/Search.js
deleted file mode 100644
index 644a698ad..000000000
--- a/cypress/apiRequests/frontShop/Search.js
+++ /dev/null
@@ -1,34 +0,0 @@
-class Search {
- searchInShop(searchQuery) {
- return cy.request({
- method: "POST",
- url: Cypress.env("API_URI"),
- headers: {
- authorization: `JWT ${window.localStorage.getItem("token")}`
- },
- body: [
- {
- operationName: "SearchProducts",
- variables: {
- attributes: {},
- channel: "default-channel",
- pageSize: 6,
- priceGte: null,
- priceLte: null,
- query: searchQuery,
- sortBy: null
- },
- query:
- "fragment Price on TaxedMoney {\n gross {\n amount\n currency\n __typename\n }\n net {\n amount\n currency\n __typename\n }\n __typename\n}\n\nfragment ProductPricingField on Product {\n pricing {\n onSale\n priceRangeUndiscounted {\n start {\n ...Price\n __typename\n }\n stop {\n ...Price\n __typename\n }\n __typename\n }\n priceRange {\n start {\n ...Price\n __typename\n }\n stop {\n ...Price\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n}\n\nquery SearchProducts($query: String!, $channel: String!, $attributes: [AttributeInput], $pageSize: Int, $sortBy: ProductOrder, $after: String) {\n products(channel: $channel, filter: {search: $query, attributes: $attributes}, first: $pageSize, sortBy: $sortBy, after: $after) {\n totalCount\n edges {\n node {\n ...ProductPricingField\n id\n name\n thumbnail {\n url\n alt\n __typename\n }\n thumbnail2x: thumbnail(size: 510) {\n url\n __typename\n }\n category {\n id\n name\n __typename\n }\n __typename\n }\n __typename\n }\n pageInfo {\n endCursor\n hasNextPage\n __typename\n }\n __typename\n }\n attributes(filter: {filterableInStorefront: true}, first: 100) {\n edges {\n node {\n id\n name\n slug\n values {\n id\n name\n slug\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n }\n}\n"
- }
- ]
- });
- }
- isProductExist(resp, name) {
- return (
- resp.body[0].data.products.totalCount !== 0 &&
- resp.body[0].data.products.edges[0].node.name === name
- );
- }
-}
-export default Search;
diff --git a/cypress/apiRequests/storeFront/ProductDetails.js b/cypress/apiRequests/storeFront/ProductDetails.js
new file mode 100644
index 000000000..9ad18c5fc
--- /dev/null
+++ b/cypress/apiRequests/storeFront/ProductDetails.js
@@ -0,0 +1,18 @@
+class ProductDetails {
+ getProductDetails(productId, channelId) {
+ const query = `fragment BasicProductFields on Product {
+ id
+ name
+ }
+ query ProductDetails{
+ product(id: "${productId}", channel: "${channelId}") {
+ ...BasicProductFields
+ isAvailable
+ isAvailableForPurchase
+ availableForPurchase
+ }
+ }`;
+ return cy.sendFrontShopRequestWithQuery(query);
+ }
+}
+export default ProductDetails;
diff --git a/cypress/apiRequests/storeFront/Search.js b/cypress/apiRequests/storeFront/Search.js
new file mode 100644
index 000000000..107be2560
--- /dev/null
+++ b/cypress/apiRequests/storeFront/Search.js
@@ -0,0 +1,20 @@
+class Search {
+ searchInShop(searchQuery) {
+ const query = `query SearchProducts {
+ products(channel: "default-channel", filter:{
+ search: "${searchQuery}"
+ }, first:10){
+ totalCount
+ edges{
+ node{
+ id
+ name
+ }
+ }
+ }
+ }`;
+
+ return cy.sendFrontShopRequestWithQuery(query);
+ }
+}
+export default Search;
diff --git a/cypress/apiRequests/utils/Utils.js b/cypress/apiRequests/utils/Utils.js
new file mode 100644
index 000000000..cbb37b751
--- /dev/null
+++ b/cypress/apiRequests/utils/Utils.js
@@ -0,0 +1,6 @@
+class Utils {
+ getValueWithDefault(condition, value, defaultValue = "") {
+ return condition ? value : defaultValue;
+ }
+}
+export default Utils;
diff --git a/cypress/integration/channels.js b/cypress/integration/channels.js
index bfee7abae..0f64da273 100644
--- a/cypress/integration/channels.js
+++ b/cypress/integration/channels.js
@@ -44,10 +44,13 @@ describe("Channels", () => {
it("should create new channel", () => {
const randomChannel = `${channelStartsWith} ${faker.random.number()}`;
- cy.visit(urlList.channels).waitForGraph("Channels");
+ cy.addAliasToGraphRequest("Channels");
+ cy.visit(urlList.channels);
+ cy.wait("@Channels");
+ cy.addAliasToGraphRequest("Channel");
channelsSteps.createChannelByView(randomChannel, currency);
// New channel should be visible in channels list
- cy.waitForGraph("Channel")
+ cy.wait("@Channel")
.get(ADD_CHANNEL_FORM_SELECTORS.backToChannelsList)
.click()
.get(CHANNELS_SELECTORS.channelsTable)
@@ -62,7 +65,9 @@ describe("Channels", () => {
.click();
// new channel should be visible at product availability form
- cy.visit(urlList.products).waitForGraph("InitialProductFilterData");
+ cy.addAliasToGraphRequest("InitialProductFilterData");
+ cy.visit(urlList.products);
+ cy.wait("@InitialProductFilterData");
cy.get(PRODUCTS_SELECTORS.productsList)
.first()
.click()
@@ -103,15 +108,18 @@ describe("Channels", () => {
randomChannelToDelete,
currency
);
- cy.visit(urlList.channels).waitForGraph("Channels");
+ cy.addAliasToGraphRequest("Channels");
+ cy.visit(urlList.channels);
+ cy.wait("@Channels");
cy.get(CHANNELS_SELECTORS.channelName)
.contains(randomChannelToDelete)
.parentsUntil(CHANNELS_SELECTORS.channelsTable)
.find("button")
- .click()
- .get(BUTTON_SELECTORS.submit)
- .click()
- .waitForGraph("Channels");
+ .click();
+ cy.addAliasToGraphRequest("Channels");
+ cy.get(BUTTON_SELECTORS.submit).click();
+ cy.wait("@Channels");
+
cy.get(CHANNELS_SELECTORS.channelName)
.contains(randomChannelToDelete)
.should("not.exist");
diff --git a/cypress/integration/homePage.js b/cypress/integration/homePage.js
index 483eb49cd..3712afd56 100644
--- a/cypress/integration/homePage.js
+++ b/cypress/integration/homePage.js
@@ -48,12 +48,12 @@ describe("Homepage analytics", () => {
)
.then(resp => {
customerId = resp.body.data.customerCreate.user.id;
- shippingUtils.createShipping(
- defaultChannel.id,
- randomName,
- addresses.plAddress,
- shippingPrice
- );
+ shippingUtils.createShipping({
+ channelId: defaultChannel.id,
+ name: randomName,
+ address: addresses.plAddress,
+ price: shippingPrice
+ });
})
.then(() => {
productsUtils.createTypeAttributeAndCategoryForProduct(randomName);
@@ -63,16 +63,16 @@ describe("Homepage analytics", () => {
const productType = productsUtils.getProductType();
const attribute = productsUtils.getAttribute();
const category = productsUtils.getCategory();
- productsUtils.createProductInChannel(
- randomName,
- defaultChannel.id,
- warehouse.id,
- 20,
- productType.id,
- attribute.id,
- category.id,
- productPrice
- );
+ productsUtils.createProductInChannel({
+ name: randomName,
+ channelId: defaultChannel.id,
+ warehouseId: warehouse.id,
+ quantityInWarehouse: 20,
+ productTypeId: productType.id,
+ attributeId: attribute.id,
+ categoryId: category.id,
+ price: productPrice
+ });
});
});
@@ -154,16 +154,16 @@ describe("Homepage analytics", () => {
const attribute = productsUtils.getAttribute();
const category = productsUtils.getCategory();
- productsOutOfStockUtils.createProductInChannel(
- productOutOfStockRandomName,
- defaultChannel.id,
- warehouse.id,
- 0,
- productType.id,
- attribute.id,
- category.id,
- productPrice
- );
+ productsOutOfStockUtils.createProductInChannel({
+ name: productOutOfStockRandomName,
+ channelId: defaultChannel.id,
+ warehouseId: warehouse.id,
+ quantityInWarehouse: 0,
+ productTypeId: productType.id,
+ attributeId: attribute.id,
+ categoryId: category.id,
+ price: productPrice
+ });
cy.get("@productsOutOfStock").then(productsOutOfStockBefore => {
const allProductsOutOfStock = productsOutOfStockBefore + 1;
diff --git a/cypress/integration/products/availableForPurchaseProducts.js b/cypress/integration/products/menageProducts/availableForPurchaseProducts.js
similarity index 58%
rename from cypress/integration/products/availableForPurchaseProducts.js
rename to cypress/integration/products/menageProducts/availableForPurchaseProducts.js
index 659bd2c7e..9c4a3c468 100644
--- a/cypress/integration/products/availableForPurchaseProducts.js
+++ b/cypress/integration/products/menageProducts/availableForPurchaseProducts.js
@@ -1,11 +1,11 @@
import faker from "faker";
-import ProductSteps from "../../steps/productSteps";
-import { urlList } from "../../url/urlList";
-import ChannelsUtils from "../../utils/channelsUtils";
-import FrontShopProductUtils from "../../utils/frontShop/frontShopProductUtils";
-import ProductsUtils from "../../utils/productsUtils";
-import ShippingUtils from "../../utils/shippingUtils";
+import ProductSteps from "../../../steps/productSteps";
+import { productDetailsUrl } from "../../../url/urlList";
+import ChannelsUtils from "../../../utils/channelsUtils";
+import ProductsUtils from "../../../utils/productsUtils";
+import ShippingUtils from "../../../utils/shippingUtils";
+import StoreFrontProductUtils from "../../../utils/storeFront/storeFrontProductUtils";
//
describe("Products available in listings", () => {
@@ -13,7 +13,7 @@ describe("Products available in listings", () => {
const channelsUtils = new ChannelsUtils();
const productsUtils = new ProductsUtils();
const productSteps = new ProductSteps();
- const frontShopProductUtils = new FrontShopProductUtils();
+ const frontShopProductUtils = new StoreFrontProductUtils();
const startsWith = "Cy-";
const name = `${startsWith}${faker.random.number()}`;
let productType;
@@ -34,12 +34,11 @@ describe("Products available in listings", () => {
cy.fixture("addresses");
})
.then(addressesFixture => {
- shippingUtils.createShipping(
- defaultChannel,
+ shippingUtils.createShipping({
+ channelId: defaultChannel.id,
name,
- addressesFixture.plAddress,
- 10
- );
+ address: addressesFixture.plAddress
+ });
})
.then(() => {
warehouse = shippingUtils.getWarehouse();
@@ -59,23 +58,19 @@ describe("Products available in listings", () => {
it("should update product to available for purchase", () => {
const productName = `${startsWith}${faker.random.number()}`;
productsUtils
- .createProductInChannel(
- productName,
- defaultChannel.id,
- warehouse.id,
- 10,
- productType.id,
- attribute.id,
- category.id,
- 1,
- true,
- false,
- true
- )
+ .createProductInChannel({
+ name: productName,
+ channelId: defaultChannel.id,
+ warehouseId: warehouse.id,
+ productTypeId: productType.id,
+ attributeId: attribute.id,
+ categoryId: category.id,
+ isAvailableForPurchase: false
+ })
.then(() => {
- const productUrl = `${urlList.products}${
+ const productUrl = productDetailsUrl(
productsUtils.getCreatedProduct().id
- }`;
+ );
productSteps.updateProductIsAvailableForPurchase(productUrl, true);
})
.then(() => {
@@ -92,33 +87,29 @@ describe("Products available in listings", () => {
it("should update product to not available for purchase", () => {
const productName = `${startsWith}${faker.random.number()}`;
productsUtils
- .createProductInChannel(
- productName,
- defaultChannel.id,
- warehouse.id,
- 10,
- productType.id,
- attribute.id,
- category.id,
- 1,
- true,
- true,
- true
- )
+ .createProductInChannel({
+ name: productName,
+ channelId: defaultChannel.id,
+ warehouseId: warehouse.id,
+ productTypeId: productType.id,
+ attributeId: attribute.id,
+ categoryId: category.id
+ })
.then(() => {
- const productUrl = `${urlList.products}${
+ const productUrl = productDetailsUrl(
productsUtils.getCreatedProduct().id
- }`;
+ );
productSteps.updateProductIsAvailableForPurchase(productUrl, false);
- frontShopProductUtils
- .isProductAvailableForPurchase(
- productsUtils.getCreatedProduct().id,
- defaultChannel.slug,
- productName
- )
- .then(isProductVisible => {
- expect(isProductVisible).to.be.eq(false);
- });
+ })
+ .then(() => {
+ frontShopProductUtils.isProductAvailableForPurchase(
+ productsUtils.getCreatedProduct().id,
+ defaultChannel.slug,
+ productName
+ );
+ })
+ .then(isProductVisible => {
+ expect(isProductVisible).to.be.eq(false);
});
});
});
diff --git a/cypress/integration/products/publishedProducts.js b/cypress/integration/products/menageProducts/publishedProducts.js
similarity index 69%
rename from cypress/integration/products/publishedProducts.js
rename to cypress/integration/products/menageProducts/publishedProducts.js
index f6b23a7ca..48015293f 100644
--- a/cypress/integration/products/publishedProducts.js
+++ b/cypress/integration/products/menageProducts/publishedProducts.js
@@ -1,17 +1,17 @@
import faker from "faker";
-import ProductSteps from "../../steps/productSteps";
-import { urlList } from "../../url/urlList";
-import ChannelsUtils from "../../utils/channelsUtils";
-import FrontShopProductUtils from "../../utils/frontShop/frontShopProductUtils";
-import ProductsUtils from "../../utils/productsUtils";
+import ProductSteps from "../../../steps/productSteps";
+import { productDetailsUrl } from "../../../url/urlList";
+import ChannelsUtils from "../../../utils/channelsUtils";
+import ProductsUtils from "../../../utils/productsUtils";
+import StoreFrontProductUtils from "../../../utils/storeFront/storeFrontProductUtils";
//
describe("Published products", () => {
const channelsUtils = new ChannelsUtils();
const productsUtils = new ProductsUtils();
const productSteps = new ProductSteps();
- const frontShopProductUtils = new FrontShopProductUtils();
+ const frontShopProductUtils = new StoreFrontProductUtils();
const startsWith = "Cy-";
const name = `${startsWith}${faker.random.number()}`;
@@ -39,23 +39,19 @@ describe("Published products", () => {
.getDefaultChannel()
.then(channel => {
defaultChannel = channel;
- productsUtils.createProductInChannel(
- productName,
- defaultChannel.id,
- null,
- null,
- productType.id,
- attribute.id,
- category.id,
- 1,
- false,
- false,
- true
- );
+ productsUtils.createProductInChannel({
+ name: productName,
+ channelId: defaultChannel.id,
+ productTypeId: productType.id,
+ attributeId: attribute.id,
+ categoryId: category.id,
+ isPublished: false,
+ isAvailableForPurchase: false
+ });
})
.then(() => {
const product = productsUtils.getCreatedProduct();
- const productUrl = `${urlList.products}${product.id}`;
+ const productUrl = productDetailsUrl(product.id);
productSteps.updateProductPublish(productUrl, true);
frontShopProductUtils.isProductVisible(
product.id,
@@ -76,19 +72,17 @@ describe("Published products", () => {
.getDefaultChannel()
.then(channel => {
defaultChannel = channel;
- productsUtils.createProductInChannel(
- productName,
- defaultChannel.id,
- null,
- null,
- productType.id,
- attribute.id,
- category.id
- );
+ productsUtils.createProductInChannel({
+ name: productName,
+ channelId: defaultChannel.id,
+ productTypeId: productType.id,
+ attributeId: attribute.id,
+ categoryId: category.id
+ });
})
.then(() => {
product = productsUtils.getCreatedProduct();
- const productUrl = `${urlList.products}${product.id}`;
+ const productUrl = productDetailsUrl(product.id);
productSteps.updateProductPublish(productUrl, false);
frontShopProductUtils.isProductVisible(
product.id,
diff --git a/cypress/integration/products/visibleInListingsProducts.js b/cypress/integration/products/menageProducts/visibleInListingsProducts.js
similarity index 68%
rename from cypress/integration/products/visibleInListingsProducts.js
rename to cypress/integration/products/menageProducts/visibleInListingsProducts.js
index 9d4729740..19463c5ce 100644
--- a/cypress/integration/products/visibleInListingsProducts.js
+++ b/cypress/integration/products/menageProducts/visibleInListingsProducts.js
@@ -1,17 +1,17 @@
import faker from "faker";
-import ProductSteps from "../../steps/productSteps";
-import { urlList } from "../../url/urlList";
-import ChannelsUtils from "../../utils/channelsUtils";
-import FrontShopProductUtils from "../../utils/frontShop/frontShopProductUtils";
-import ProductsUtils from "../../utils/productsUtils";
+import ProductSteps from "../../../steps/productSteps";
+import { productDetailsUrl } from "../../../url/urlList";
+import ChannelsUtils from "../../../utils/channelsUtils";
+import ProductsUtils from "../../../utils/productsUtils";
+import StoreFrontProductUtils from "../../../utils/storeFront/storeFrontProductUtils";
//
describe("Products displayed in listings", () => {
const channelsUtils = new ChannelsUtils();
const productsUtils = new ProductsUtils();
const productSteps = new ProductSteps();
- const frontShopProductUtils = new FrontShopProductUtils();
+ const frontShopProductUtils = new StoreFrontProductUtils();
const startsWith = "Cy-";
const name = `${startsWith}${faker.random.number()}`;
@@ -39,23 +39,19 @@ describe("Products displayed in listings", () => {
.getDefaultChannel()
.then(channel => {
defaultChannel = channel;
- productsUtils.createProductInChannel(
- productName,
- defaultChannel.id,
- null,
- null,
- productType.id,
- attribute.id,
- category.id,
- 1,
- true,
- false,
- false
- );
+ productsUtils.createProductInChannel({
+ name: productName,
+ channelId: defaultChannel.id,
+ productTypeId: productType.id,
+ attributeId: attribute.id,
+ categoryId: category.id,
+ visibleInListings: false,
+ isAvailableForPurchase: false
+ });
})
.then(() => {
const product = productsUtils.getCreatedProduct();
- const productUrl = `${urlList.products}${product.id}`;
+ const productUrl = productDetailsUrl(product.id);
productSteps.updateProductVisibleInListings(productUrl);
frontShopProductUtils.isProductVisibleInSearchResult(
productName,
@@ -73,23 +69,18 @@ describe("Products displayed in listings", () => {
.getDefaultChannel()
.then(channel => {
defaultChannel = channel;
- productsUtils.createProductInChannel(
- productName,
- defaultChannel.id,
- null,
- null,
- productType.id,
- attribute.id,
- category.id,
- 1,
- true,
- false,
- true
- );
+ productsUtils.createProductInChannel({
+ name: productName,
+ channelId: defaultChannel.id,
+ productTypeId: productType.id,
+ attributeId: attribute.id,
+ categoryId: category.id,
+ visibleInListings: true
+ });
})
.then(() => {
const product = productsUtils.getCreatedProduct();
- const productUrl = `${urlList.products}${product.id}`;
+ const productUrl = productDetailsUrl(product.id);
productSteps.updateProductVisibleInListings(productUrl);
frontShopProductUtils
.isProductVisibleInSearchResult(productName, defaultChannel.slug)
diff --git a/cypress/integration/products/productsVariants.js b/cypress/integration/products/productsVariants.js
new file mode 100644
index 000000000..f6f024f51
--- /dev/null
+++ b/cypress/integration/products/productsVariants.js
@@ -0,0 +1,200 @@
+import faker from "faker";
+import { visit } from "graphql";
+
+import Channels from "../../apiRequests/Channels";
+import Product from "../../apiRequests/Product";
+import ProductDetails from "../../apiRequests/storeFront/ProductDetails";
+import VariantsSteps from "../../steps/products/VariantsSteps";
+import { urlList } from "../../url/urlList";
+import ChannelsUtils from "../../utils/channelsUtils";
+import ProductsUtils from "../../utils/productsUtils";
+import ShippingUtils from "../../utils/shippingUtils";
+import StoreFrontProductUtils from "../../utils/storeFront/storeFrontProductUtils";
+
+//
+describe("creating variants", () => {
+ const startsWith = "Cy-";
+
+ const productUtils = new ProductsUtils();
+ const channelsUtils = new ChannelsUtils();
+ const shippingUtils = new ShippingUtils();
+ const storeFrontProductUtils = new StoreFrontProductUtils();
+ const product = new Product();
+ const channels = new Channels();
+ const productDetails = new ProductDetails();
+
+ const variantsSteps = new VariantsSteps();
+
+ let defaultChannel;
+ let warehouse;
+ let attribute;
+ let productType;
+ let category;
+
+ before(() => {
+ cy.clearSessionData().loginUserViaRequest();
+ shippingUtils.deleteShipping(startsWith);
+ productUtils.deleteProperProducts(startsWith);
+
+ const name = `${startsWith}${faker.random.number()}`;
+ channelsUtils
+ .getDefaultChannel()
+ .then(channel => {
+ defaultChannel = channel;
+ cy.fixture("addresses");
+ })
+ .then(fixtureAddresses =>
+ shippingUtils.createShipping({
+ channelId: defaultChannel.id,
+ name,
+ address: fixtureAddresses.plAddress
+ })
+ )
+ .then(() => (warehouse = shippingUtils.getWarehouse()));
+
+ productUtils.createTypeAttributeAndCategoryForProduct(name).then(() => {
+ attribute = productUtils.getAttribute();
+ productType = productUtils.getProductType();
+ category = productUtils.getCategory();
+ });
+ });
+
+ beforeEach(() => {
+ cy.clearSessionData().loginUserViaRequest();
+ });
+
+ it("should create variant visible on frontend", () => {
+ const name = `${startsWith}${faker.random.number()}`;
+ const price = 10;
+ let createdProduct;
+
+ product
+ .createProduct(attribute.id, name, productType.id, category.id)
+ .then(resp => {
+ createdProduct = resp.body.data.productCreate.product;
+ product.updateChannelInProduct({
+ productId: createdProduct.id,
+ channelId: defaultChannel.id
+ });
+ cy.visit(`${urlList.products}${createdProduct.id}`);
+ variantsSteps.createFirstVariant(name, warehouse.id, price);
+ storeFrontProductUtils.getProductVariants(
+ createdProduct.id,
+ defaultChannel.slug
+ );
+ // productDetails
+ // .getProductDetails(createdProduct.id, defaultChannel.slug)
+ })
+ .then(variants => {
+ // expect(productDetailsResp.body[0].data.product.name).to.equal(name);
+ expect(variants[0].name).to.equal(name);
+ expect(variants[0].pricing.price.gross.amount).to.equal(price);
+ // expect(
+ // productDetailsResp.body[0].data.product.variants[0].pricing.price
+ // .gross.amount
+ // ).to.equal(price);
+ });
+ });
+ it("should create several variants", () => {
+ const name = `${startsWith}${faker.random.number()}`;
+ const secondVariantSku = `${startsWith}${faker.random.number()}`;
+ const variantsPrice = 5;
+ let createdProduct;
+
+ productUtils
+ .createProductInChannel({
+ name,
+ channelId: defaultChannel.id,
+ warehouseId: warehouse.id,
+ productTypeId: productType.id,
+ categoryId: category.id,
+ price: variantsPrice
+ })
+ .then(() => {
+ createdProduct = productUtils.getCreatedProduct();
+ cy.visit(`${urlList.products}${createdProduct.id}`);
+ variantsSteps.createVariant(
+ secondVariantSku,
+ warehouse.name,
+ variantsPrice
+ );
+ })
+ .then(
+ () =>
+ storeFrontProductUtils.getProductVariants(
+ createdProduct.id,
+ defaultChannel.slug
+ )
+ // productDetails.getProductDetails(createdProduct.id, defaultChannel.slug)
+ )
+ .then(variants => {
+ expect(variants).to.have.length(2);
+ expect(variants[0].pricing.price.gross.amount).to.equal(variantsPrice);
+ expect(variants[1].pricing.price.gross.amount).to.equal(variantsPrice);
+ // expect(productDetailsResp.body[0].data.product.name).to.equal(name);
+ // expect(productDetailsResp.body[0].data.product.variants).to.have.length(
+ // 2
+ // );
+ // expect(
+ // productDetailsResp.body[0].data.product.variants[0].pricing.price
+ // .gross.amount
+ // ).to.equal(variantsPrice);
+ // expect(
+ // productDetailsResp.body[0].data.product.variants[1].pricing.price
+ // .gross.amount
+ // ).to.equal(variantsPrice);
+ });
+ });
+ it("should create variant for many channels", () => {
+ const name = `${startsWith}${faker.random.number()}`;
+ const variantsPrice = 10;
+ let newChannel;
+ let createdProduct;
+ channels
+ .createChannel(true, name, name, "PLN")
+ .then(resp => {
+ newChannel = resp.body.data.channelCreate.channel;
+ productUtils.createProduct(
+ attribute.id,
+ name,
+ productType.id,
+ category.id
+ );
+ })
+ .then(() => {
+ createdProduct = productUtils.getCreatedProduct();
+ product.updateChannelInProduct({
+ productId: createdProduct.id,
+ channelId: defaultChannel.id
+ });
+ })
+ .then(() => {
+ product.updateChannelInProduct({
+ productId: createdProduct.id,
+ channelId: newChannel.id
+ });
+ })
+ .then(() => {
+ cy.visit(`${urlList.products}${createdProduct.id}`);
+ variantsSteps.createFirstVariant(name, warehouse.id, variantsPrice);
+ // productDetails.getProductDetails(product.id, defaultChannel.slug);
+ storeFrontProductUtils.getProductVariants(
+ product.id,
+ defaultChannel.slug
+ );
+ })
+ .then(variants => {
+ expect(variants[0].pricing.price.gross.amount).to.equal(variantsPrice);
+ })
+ .then(() => {
+ storeFrontProductUtils.getProductVariants(
+ product.id,
+ defaultChannel.slug
+ );
+ // productDetails.getProductDetails(product.id, newChannel.slug);
+ })
+ .then(variants => {
+ expect(variants[0].pricing.price.gross.amount).to.equal(variantsPrice);
+ });
+ });
+});
diff --git a/cypress/integration/productsVariants.js b/cypress/integration/productsVariants.js
deleted file mode 100644
index a8b7d98e6..000000000
--- a/cypress/integration/productsVariants.js
+++ /dev/null
@@ -1,194 +0,0 @@
-import faker from "faker";
-import { visit } from "graphql";
-
-import Channels from "../apiRequests/Channels";
-import ProductDetails from "../apiRequests/frontShop/ProductDetails";
-import Product from "../apiRequests/Product";
-import VariantsSteps from "../steps/products/VariantsSteps";
-import { urlList } from "../url/urlList";
-import ChannelsUtils from "../utils/channelsUtils";
-import ProductsUtils from "../utils/productsUtils";
-import ShippingUtils from "../utils/shippingUtils";
-
-//
-describe("creating variants", () => {
- const startsWith = "Cy-";
-
- const productUtils = new ProductsUtils();
- const channelsUtils = new ChannelsUtils();
- const shippingUtils = new ShippingUtils();
- const product = new Product();
- const channels = new Channels();
- const productDetails = new ProductDetails();
-
- const variantsSteps = new VariantsSteps();
-
- let defaultChannel;
- let warehouse;
- let attribute;
- let productType;
- let category;
-
- before(() => {
- cy.clearSessionData().loginUserViaRequest();
- shippingUtils.deleteShipping(startsWith);
- productUtils.deleteProperProducts(startsWith);
-
- const name = `${startsWith}${faker.random.number()}`;
- channelsUtils
- .getDefaultChannel()
- .then(channel => {
- defaultChannel = channel;
- cy.fixture("addresses");
- })
- .then(fixtureAddresses =>
- shippingUtils.createShipping(
- defaultChannel.id,
- name,
- fixtureAddresses.plAddress,
- 10
- )
- )
- .then(() => (warehouse = shippingUtils.getWarehouse()));
-
- productUtils.createTypeAttributeAndCategoryForProduct(name).then(() => {
- attribute = productUtils.getAttribute();
- productType = productUtils.getProductType();
- category = productUtils.getCategory();
- });
- });
-
- beforeEach(() => {
- cy.clearSessionData().loginUserViaRequest();
- });
-
- it("should create variant visible on frontend", () => {
- const name = `${startsWith}${faker.random.number()}`;
- const price = 10;
- let createdProduct;
-
- product
- .createProduct(attribute.id, name, productType.id, category.id)
- .then(resp => {
- createdProduct = resp.body.data.productCreate.product;
- product.updateChannelInProduct(
- createdProduct.id,
- defaultChannel.id,
- true,
- true,
- true
- );
- cy.visit(`${urlList.products}${createdProduct.id}`);
- variantsSteps.createFirstVariant(name, warehouse.id, price);
- productDetails
- .getProductDetails(createdProduct.id, defaultChannel.slug)
- .then(productDetailsResp => {
- expect(productDetailsResp.body[0].data.product.name).to.equal(name);
- expect(
- productDetailsResp.body[0].data.product.variants[0].pricing.price
- .gross.amount
- ).to.equal(price);
- });
- });
- });
- it("should create several variants", () => {
- const name = `${startsWith}${faker.random.number()}`;
- const secondVariantSku = `${startsWith}${faker.random.number()}`;
- const variantsPrice = 5;
- let createdProduct;
- productUtils
- .createProductInChannel(
- name,
- defaultChannel.id,
- warehouse.id,
- 1,
- productType.id,
- attribute.id,
- category.id,
- variantsPrice
- )
- .then(() => {
- createdProduct = productUtils.getCreatedProduct();
- cy.visit(`${urlList.products}${createdProduct.id}`);
- variantsSteps.createVariant(
- secondVariantSku,
- warehouse.name,
- variantsPrice
- );
- })
- .then(() =>
- productDetails.getProductDetails(createdProduct.id, defaultChannel.slug)
- )
- .then(productDetailsResp => {
- expect(productDetailsResp.body[0].data.product.name).to.equal(name);
- expect(productDetailsResp.body[0].data.product.variants).to.have.length(
- 2
- );
- expect(
- productDetailsResp.body[0].data.product.variants[0].pricing.price
- .gross.amount
- ).to.equal(variantsPrice);
- expect(
- productDetailsResp.body[0].data.product.variants[1].pricing.price
- .gross.amount
- ).to.equal(variantsPrice);
- });
- });
- it("should create variant for many channels", () => {
- const name = `${startsWith}${faker.random.number()}`;
- let newChannel;
- let createdProduct;
- channels
- .createChannel(true, name, name, "PLN")
- .then(resp => {
- newChannel = resp.body.data.channelCreate.channel;
- productUtils.createProduct(
- attribute.id,
- name,
- productType.id,
- category.id
- );
- })
- .then(() => {
- createdProduct = productUtils.getCreatedProduct();
- product.updateChannelInProduct(
- createdProduct.id,
- defaultChannel.id,
- true,
- true,
- true
- );
- })
- .then(() => {
- product.updateChannelInProduct(
- createdProduct.id,
- newChannel.id,
- true,
- true,
- true
- );
- })
- .then(() => {
- cy.visit(`${urlList.products}${createdProduct.id}`);
- variantsSteps.createFirstVariant(warehouse.id);
- productDetails.getProductDetails(product.id, defaultChannel.slug);
- })
- .then(productDetailsResp => {
- expect(productDetailsResp.body[0].data.product.name).to.equal(name);
- expect(
- productDetailsResp.body[0].data.product.variants[0].pricing.price
- .gross.amount
- ).to.equal(10);
- })
- .then(() => {
- productDetails.getProductDetails(product.id, newChannel.slug);
- })
- .then(productDetailsResp => {
- expect(productDetailsResp.body[0].data.product.name).to.equal(name);
- expect(
- productDetailsResp.body[0].data.product.variants[0].pricing.price
- .gross.amount
- ).to.equal(10);
- });
- });
-});
diff --git a/cypress/steps/homePageSteps.js b/cypress/steps/homePageSteps.js
index bd53c0972..72b9c6d96 100644
--- a/cypress/steps/homePageSteps.js
+++ b/cypress/steps/homePageSteps.js
@@ -1,12 +1,12 @@
import { HEADER_SELECTORS } from "../elements/header/header-selectors";
class HomePageSteps {
changeChannel(channelName) {
- cy.get(HEADER_SELECTORS.channelSelect)
- .click()
- .get(HEADER_SELECTORS.channelSelectList)
+ cy.get(HEADER_SELECTORS.channelSelect).click();
+ cy.addAliasToGraphRequest("Home");
+ cy.get(HEADER_SELECTORS.channelSelectList)
.contains(channelName)
- .click()
- .waitForGraph("Home");
+ .click();
+ cy.wait("@Home");
}
}
export default HomePageSteps;
diff --git a/cypress/steps/productSteps.js b/cypress/steps/productSteps.js
index 244ab8392..eec8c3736 100644
--- a/cypress/steps/productSteps.js
+++ b/cypress/steps/productSteps.js
@@ -1,30 +1,20 @@
import { PRODUCTS_SELECTORS } from "../elements/catalog/product-selectors";
class ProductSteps {
+ valueTrue = PRODUCTS_SELECTORS.radioButtonsValueTrue;
+ valueFalse = PRODUCTS_SELECTORS.radioButtonsValueFalse;
+
updateProductIsAvailableForPurchase(productUrl, isAvailableForPurchase) {
- let isAvailableForPurchaseSelector;
- if (isAvailableForPurchase) {
- isAvailableForPurchaseSelector = PRODUCTS_SELECTORS.radioButtonsValueTrue;
- } else {
- isAvailableForPurchaseSelector =
- PRODUCTS_SELECTORS.radioButtonsValueFalse;
- }
- this.updateProductMenageInChannel(
- productUrl,
- `${PRODUCTS_SELECTORS.availableForPurchaseRadioButtons}${isAvailableForPurchaseSelector}`
- );
+ const isAvailableForPurchaseSelector = isAvailableForPurchase
+ ? this.valueTrue
+ : this.valueFalse;
+ const availableForPurchaseSelector = `${PRODUCTS_SELECTORS.availableForPurchaseRadioButtons}${isAvailableForPurchaseSelector}`;
+ this.updateProductMenageInChannel(productUrl, availableForPurchaseSelector);
}
updateProductPublish(productUrl, isPublished) {
- let isPublishedSelector;
- if (isPublished) {
- isPublishedSelector = PRODUCTS_SELECTORS.radioButtonsValueTrue;
- } else {
- isPublishedSelector = PRODUCTS_SELECTORS.radioButtonsValueFalse;
- }
- this.updateProductMenageInChannel(
- productUrl,
- `${PRODUCTS_SELECTORS.publishedRadioButtons}${isPublishedSelector}`
- );
+ const isPublishedSelector = isPublished ? this.valueTrue : this.valueFalse;
+ const publishedSelector = `${PRODUCTS_SELECTORS.publishedRadioButtons}${isPublishedSelector}`;
+ this.updateProductMenageInChannel(productUrl, publishedSelector);
}
updateProductVisibleInListings(productUrl) {
this.updateProductMenageInChannel(
@@ -37,10 +27,11 @@ class ProductSteps {
.get(PRODUCTS_SELECTORS.assignedChannels)
.click()
.get(menageSelector)
+ .click();
+ cy.addAliasToGraphRequest("ProductChannelListingUpdate");
+ cy.get(PRODUCTS_SELECTORS.saveBtn)
.click()
- .get(PRODUCTS_SELECTORS.saveBtn)
- .click()
- .waitForGraph("ProductChannelListingUpdate");
+ .wait("@ProductChannelListingUpdate");
}
}
export default ProductSteps;
diff --git a/cypress/steps/products/VariantsSteps.js b/cypress/steps/products/VariantsSteps.js
index 98a20bb69..7a71c657b 100644
--- a/cypress/steps/products/VariantsSteps.js
+++ b/cypress/steps/products/VariantsSteps.js
@@ -8,16 +8,20 @@ class VariantsSteps {
.first()
.click()
.get(VARIANTS_SELECTORS.nextButton)
- .click()
- .get(VARIANTS_SELECTORS.priceInput)
- .forEach(priceInput => cy.priceInput.type(price));
+ .click();
+ const priceInput = cy.get(VARIANTS_SELECTORS.priceInput);
+ if (Array.isArray(priceInput)) {
+ priceInput.forEach(input => input.type(price));
+ } else {
+ priceInput.type(price);
+ }
cy.get(`[name*='${warehouseId}']`)
.click()
.get(VARIANTS_SELECTORS.nextButton)
.click()
.get(VARIANTS_SELECTORS.skuInput)
.type(sku);
- cy.waitForGraph("ProductVariantBulkCreate");
+ cy.addAliasToGraphRequest("ProductVariantBulkCreate");
cy.get(VARIANTS_SELECTORS.nextButton).click();
cy.wait("@ProductVariantBulkCreate");
}
@@ -38,7 +42,7 @@ class VariantsSteps {
.get(VARIANTS_SELECTORS.addWarehouseButton)
.click();
cy.contains(VARIANTS_SELECTORS.warehouseOption, warehouseName).click();
- cy.waitForGraph("VariantCreate");
+ cy.addAliasToGraphRequest("VariantCreate");
cy.get(VARIANTS_SELECTORS.saveButton).click();
cy.wait("@VariantCreate");
}
diff --git a/cypress/support/index.js b/cypress/support/index.js
index 3c72c2f3f..2d9dad3db 100644
--- a/cypress/support/index.js
+++ b/cypress/support/index.js
@@ -21,7 +21,7 @@ Cypress.Commands.add("clearSessionData", () => {
});
});
-Cypress.Commands.add("waitForGraph", operationName => {
+Cypress.Commands.add("addAliasToGraphRequest", operationName => {
cy.intercept("POST", urlList.apiUri, req => {
req.statusCode = 200;
const requestBody = req.body;
@@ -39,7 +39,10 @@ Cypress.Commands.add("waitForGraph", operationName => {
});
});
-Cypress.Commands.add("sendRequestWithQuery", query =>
+Cypress.Commands.add("sendFrontShopRequestWithQuery", query =>
+ cy.sendRequestWithQuery(query, "token")
+);
+Cypress.Commands.add("sendRequestWithQuery", (query, authorization = "auth") =>
cy.request({
body: {
method: "POST",
@@ -47,7 +50,7 @@ Cypress.Commands.add("sendRequestWithQuery", query =>
url: urlList.apiUri
},
headers: {
- Authorization: `JWT ${window.sessionStorage.getItem("auth")}`
+ Authorization: `JWT ${window.sessionStorage.getItem(authorization)}`
},
method: "POST",
url: urlList.apiUri
diff --git a/cypress/support/user/index.js b/cypress/support/user/index.js
index 1019ac4ab..33fcc4adc 100644
--- a/cypress/support/user/index.js
+++ b/cypress/support/user/index.js
@@ -1,5 +1,4 @@
import { LOGIN_SELECTORS } from "../../elements/account/login-selectors";
-import { urlList } from "../../url/urlList";
Cypress.Commands.add("loginUser", () =>
cy
@@ -11,58 +10,30 @@ Cypress.Commands.add("loginUser", () =>
.click()
);
-Cypress.Commands.add("loginUserViaRequest", () => {
- const logInMutationQuery = `mutation TokenAuth($email: String!, $password: String!) {
- tokenCreate(email: $email, password: $password) {
+Cypress.Commands.add("loginInShop", () => {
+ cy.loginUserViaRequest("token");
+});
+
+Cypress.Commands.add("loginUserViaRequest", (authorization = "auth") => {
+ const mutation = `mutation TokenAuth{
+ tokenCreate(email: "${Cypress.env("USER_NAME")}", password: "${Cypress.env(
+ "USER_PASSWORD"
+ )}") {
token
errors: accountErrors {
code
field
message
- __typename
}
user {
id
- __typename
}
- __typename
}
}`;
-
- return cy
- .request({
- body: {
- operationName: "TokenAuth",
- query: logInMutationQuery,
- variables: {
- email: Cypress.env("USER_NAME"),
- password: Cypress.env("USER_PASSWORD")
- }
- },
- method: "POST",
- url: urlList.apiUri
- })
- .then(resp => {
- window.sessionStorage.setItem("auth", resp.body.data.tokenCreate.token);
- });
-});
-
-Cypress.Commands.add("loginInShop", () => {
- cy.request({
- method: "POST",
- url: Cypress.env("API_URI"),
- body: [
- {
- operationName: "TokenAuth",
- variables: {
- email: Cypress.env("USER_NAME"),
- password: Cypress.env("USER_PASSWORD")
- },
- query:
- "mutation TokenAuth($email: String!, $password: String!) {\n tokenCreate(email: $email, password: $password) {\n token\n errors: accountErrors {\n code\n field\n message\n __typename\n }\n user {\n id\n __typename\n }\n __typename\n }\n}\n"
- }
- ]
- }).then(resp => {
- window.localStorage.setItem("token", resp.body[0].data.tokenCreate.token);
+ return cy.sendRequestWithQuery(mutation, authorization).then(resp => {
+ window.sessionStorage.setItem(
+ authorization,
+ resp.body.data.tokenCreate.token
+ );
});
});
diff --git a/cypress/url/urlList.js b/cypress/url/urlList.js
index 2ceb592c5..c469ba6e6 100644
--- a/cypress/url/urlList.js
+++ b/cypress/url/urlList.js
@@ -7,3 +7,4 @@ export const urlList = {
products: "products/",
warehouses: "warehouses/"
};
+export const productDetailsUrl = productId => `${urlList.products}${productId}`;
diff --git a/cypress/utils/frontShop/frontShopProductUtils.js b/cypress/utils/frontShop/frontShopProductUtils.js
deleted file mode 100644
index 1b8411f23..000000000
--- a/cypress/utils/frontShop/frontShopProductUtils.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import ProductDetails from "../../apiRequests/frontShop/ProductDetails";
-import Search from "../../apiRequests/frontShop/Search";
-
-class FrontShopProductUtils {
- isProductVisible(productId, channelSlug, name) {
- const productDetails = new ProductDetails();
- return productDetails
- .getProductDetails(productId, channelSlug)
- .then(productDetailsResp =>
- productDetails.isProductExist(productDetailsResp, name)
- );
- }
- isProductAvailableForPurchase(productId, channelSlug) {
- const productDetails = new ProductDetails();
- return productDetails
- .getProductDetails(productId, channelSlug)
- .then(productDetailsResp =>
- productDetails.isAvailableForPurchaseFromResp(productDetailsResp)
- );
- }
- isProductVisibleInSearchResult(productName, channelSlug) {
- const search = new Search();
- return search
- .searchInShop(productName, channelSlug)
- .then(resp => search.isProductExist(resp, productName));
- }
-}
-export default FrontShopProductUtils;
diff --git a/cypress/utils/productsUtils.js b/cypress/utils/productsUtils.js
index 94948cdb5..36c49c080 100644
--- a/cypress/utils/productsUtils.js
+++ b/cypress/utils/productsUtils.js
@@ -22,28 +22,28 @@ class ProductsUtils {
).then(() => this.createVariant(this.product.id, name, attributeId));
}
- createProductInChannel(
+ createProductInChannel({
name,
channelId,
- warehouseId,
- quantityInWarehouse,
+ warehouseId = null,
+ quantityInWarehouse = 10,
productTypeId,
attributeId,
categoryId,
- price,
+ price = 1,
isPublished = true,
isAvailableForPurchase = true,
visibleInListings = true
- ) {
+ }) {
return this.createProduct(attributeId, name, productTypeId, categoryId)
.then(() =>
- this.productRequest.updateChannelInProduct(
- this.product.id,
+ this.productRequest.updateChannelInProduct({
+ productId: this.product.id,
channelId,
isPublished,
isAvailableForPurchase,
visibleInListings
- )
+ })
)
.then(() => {
this.createVariant(
diff --git a/cypress/utils/shippingUtils.js b/cypress/utils/shippingUtils.js
index 1fb352907..75eb7501f 100644
--- a/cypress/utils/shippingUtils.js
+++ b/cypress/utils/shippingUtils.js
@@ -8,7 +8,7 @@ class ShippingUtils {
shippingZone;
warehouse;
- createShipping(channelId, name, address, price) {
+ createShipping({ channelId, name, address, price = 1 }) {
return this.createShippingZone(name, address.country)
.then(() => this.createWarehouse(name, this.shippingZone.id, address))
.then(() => this.createShippingRate(name, this.shippingZone.id))
diff --git a/cypress/utils/storeFront/storeFrontProductUtils.js b/cypress/utils/storeFront/storeFrontProductUtils.js
new file mode 100644
index 000000000..3e1935926
--- /dev/null
+++ b/cypress/utils/storeFront/storeFrontProductUtils.js
@@ -0,0 +1,39 @@
+import ProductDetails from "../../apiRequests/storeFront/ProductDetails";
+import Search from "../../apiRequests/storeFront/Search";
+
+class StoreFrontProductUtils {
+ productDetails = new ProductDetails();
+
+ isProductVisible(productId, channelSlug, name) {
+ return this.productDetails
+ .getProductDetails(productId, channelSlug)
+ .then(productDetailsResp => {
+ const product = productDetailsResp.body.data.product;
+ return product !== null && product.name === name;
+ });
+ }
+ isProductAvailableForPurchase(productId, channelSlug) {
+ return this.productDetails
+ .getProductDetails(productId, channelSlug)
+ .then(
+ productDetailsResp =>
+ productDetailsResp.body.data.product.isAvailableForPurchase
+ );
+ }
+ isProductVisibleInSearchResult(productName, channelSlug) {
+ const search = new Search();
+ return search
+ .searchInShop(productName, channelSlug)
+ .then(
+ resp =>
+ resp.body.data.products.totalCount !== 0 &&
+ resp.body.data.products.edges[0].node.name === productName
+ );
+ }
+ getProductVariants(productId, channelSlug) {
+ return this.productDetails
+ .getProductDetails(productId, channelSlug)
+ .then(resp => resp.body.data.product.variants.edges);
+ }
+}
+export default StoreFrontProductUtils;