diff --git a/cypress/apiRequests/frontShop/ProductDetails.js b/cypress/apiRequests/frontShop/ProductDetails.js new file mode 100644 index 000000000..bb6e77c95 --- /dev/null +++ b/cypress/apiRequests/frontShop/ProductDetails.js @@ -0,0 +1,32 @@ +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 new file mode 100644 index 000000000..644a698ad --- /dev/null +++ b/cypress/apiRequests/frontShop/Search.js @@ -0,0 +1,34 @@ +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/elements/catalog/product-selectors.js b/cypress/elements/catalog/product-selectors.js index ecc70124c..2fd93e118 100644 --- a/cypress/elements/catalog/product-selectors.js +++ b/cypress/elements/catalog/product-selectors.js @@ -25,8 +25,8 @@ export const PRODUCTS_SELECTORS = { assignedChannels: "[data-test='channel-availability-item']", publishedRadioButtons: "[name*='isPublished']", availableForPurchaseRadioButtons: "[name*='isAvailableForPurchase']", - radioButtonsValueTrue: "[value:'true']", - radioButtonsValueFalse: "[value:'false']", + radioButtonsValueTrue: "[value='true']", + radioButtonsValueFalse: "[value='false']", visibleInListingsButton: "[name*='visibleInListings']", emptyProductRow: "[class*='Skeleton']" }; diff --git a/cypress/integration/products.js b/cypress/integration/products.js deleted file mode 100644 index f1e8f5468..000000000 --- a/cypress/integration/products.js +++ /dev/null @@ -1,54 +0,0 @@ -// -import { LEFT_MENU_SELECTORS } from "../elements/account/left-menu/left-menu-selectors"; -import { PRODUCTS_SELECTORS } from "../elements/catalog/product-selectors"; -import { urlList } from "../url/urlList"; - -describe("Products", () => { - beforeEach(() => { - cy.clearSessionData().loginUserViaRequest(); - }); - - it("should navigate to channels page", () => { - cy.visit(urlList.homePage) - .get(LEFT_MENU_SELECTORS.catalog) - .click() - .get(LEFT_MENU_SELECTORS.products) - .click() - .location("pathname") - .should("contain", "/products"); - }); - - it("should add new visible product", () => { - cy.visit(urlList.products) - .get(PRODUCTS_SELECTORS.createProductBtn) - .click() - .get(PRODUCTS_SELECTORS.productNameInput) - .click() - .type("Visible test product") - .get(PRODUCTS_SELECTORS.productTypeInput) - .click() - .get(PRODUCTS_SELECTORS.autocompleteDropdown) // trying to fill autocomplete before dropdown will cause error - .get(PRODUCTS_SELECTORS.productTypeInput) - .click() - .type("Cushion") - .get(PRODUCTS_SELECTORS.categoryItem) - .should("have.length", 1) - .get(PRODUCTS_SELECTORS.firstCategoryItem) - .click() - .get(PRODUCTS_SELECTORS.categoryInput) - .click() - .get(PRODUCTS_SELECTORS.categoryItem) - .first() - .click() - .get(PRODUCTS_SELECTORS.channelAvailabilityItem) - .first() - .click() - .get(PRODUCTS_SELECTORS.visibleRadioBtn) - .first() - .click() - .get(PRODUCTS_SELECTORS.saveBtn) - .click() - .get(PRODUCTS_SELECTORS.confirmationMsg) - .contains("Product created"); - }); -}); diff --git a/cypress/integration/products/availableForPurchase.js b/cypress/integration/products/availableForPurchaseProducts.js similarity index 58% rename from cypress/integration/products/availableForPurchase.js rename to cypress/integration/products/availableForPurchaseProducts.js index 6c7a55900..198f6a8ef 100644 --- a/cypress/integration/products/availableForPurchase.js +++ b/cypress/integration/products/availableForPurchaseProducts.js @@ -1,17 +1,19 @@ import faker from "faker"; -import { PRODUCTS_SELECTORS } from "../../elements/catalog/product-selectors"; +import ProductSteps from "../../steps/productSteps"; import { URL_LIST } from "../../url/url-list"; import ChannelsUtils from "../../utils/channelsUtils"; +import FrontShopProductUtils from "../../utils/frontShop/frontShopProductUtils"; import ProductsUtils from "../../utils/productsUtils"; import ShippingUtils from "../../utils/shippingUtils"; // -describe("Products", () => { +describe("Products available in listings", () => { const shippingUtils = new ShippingUtils(); const channelsUtils = new ChannelsUtils(); const productsUtils = new ProductsUtils(); - + const productSteps = new ProductSteps(); + const frontShopProductUtils = new FrontShopProductUtils(); const startsWith = "Cy-"; const name = `${startsWith}${faker.random.number()}`; let productTypeId; @@ -46,7 +48,7 @@ describe("Products", () => { cy.clearSessionData().loginUserViaRequest(); }); - it("should be possible to add to cart available for purchase product", () => { + it("should update product to available for purchase", () => { const productName = `${startsWith}${faker.random.number()}`; productsUtils .createProductInChannel( @@ -66,31 +68,19 @@ describe("Products", () => { const productUrl = `${ URL_LIST.products }${productsUtils.getCreatedProductId()}`; - cy.visit(productUrl) - .get(PRODUCTS_SELECTORS.assignedChannels) - .click() - .get( - `${PRODUCTS_SELECTORS.availableForPurchaseRadioButtons}${PRODUCTS_SELECTORS.radioButtonsValueTrue}` - ) - .click() - .get(PRODUCTS_SELECTORS.saveBtn) - .click() - .waitForGraph("ProductChannelListingUpdate") - .getProductDetails( + productSteps.updateProductIsAvailableForPurchase(productUrl, true); + frontShopProductUtils + .isProductAvailableForPurchase( productsUtils.getCreatedProductId(), - defaultChannel.slug + defaultChannel.slug, + productName ) - .then(productDetailsResp => { - expect(productDetailsResp.body[0].data.product.name).to.equal( - productName - ); - expect( - productDetailsResp.body[0].data.product.isAvailableForPurchase - ).to.be.eq(true); + .then(isProductVisible => { + expect(isProductVisible).to.be.eq(true); }); }); }); - xit("shouldn't be possible to add to cart not available for purchase product", () => { + it("should update product to not available for purchase", () => { const productName = `${startsWith}${faker.random.number()}`; productsUtils .createProductInChannel( @@ -110,28 +100,15 @@ describe("Products", () => { const productUrl = `${ URL_LIST.products }${productsUtils.getCreatedProductId()}`; - cy.visit(productUrl) - .get(PRODUCTS_SELECTORS.assignedChannels) - .click() - .get( - `${PRODUCTS_SELECTORS.availableForPurchaseRadioButtons}${PRODUCTS_SELECTORS.radioButtonsValueFalse}` - ) - .click() - .get(PRODUCTS_SELECTORS.saveBtn) - .click() - .waitForGraph("ProductChannelListingUpdate") - .get("@shopUrl") - .getProductDetails( + productSteps.updateProductIsAvailableForPurchase(productUrl, false); + frontShopProductUtils + .isProductAvailableForPurchase( productsUtils.getCreatedProductId(), - defaultChannel.slug + defaultChannel.slug, + productName ) - .then(productDetailsResp => { - expect(productDetailsResp.body[0].data.product.name).to.equal( - productName - ); - expect( - productDetailsResp.body[0].data.product.isAvailableForPurchase - ).to.be.eq(false); + .then(isProductVisible => { + expect(isProductVisible).to.be.eq(false); }); }); }); diff --git a/cypress/integration/products/products.js b/cypress/integration/products/products.js index 9cb780cda..87960c269 100644 --- a/cypress/integration/products/products.js +++ b/cypress/integration/products/products.js @@ -1,37 +1,25 @@ -import faker from "faker"; - -import Channels from "../../apiRequests/Channels"; +// import { LEFT_MENU_SELECTORS } from "../../elements/account/left-menu/left-menu-selectors"; import { PRODUCTS_SELECTORS } from "../../elements/catalog/product-selectors"; -import { BUTTON_SELECTORS } from "../../elements/shared/button-selectors"; -import { URL_LIST } from "../../url/url-list"; -import ChannelsUtils from "../../utils/channelsUtils"; -import ProductsUtils from "../../utils/productsUtils"; +import { urlList } from "../../url/urlList"; -// describe("Products", () => { - const channels = new Channels(); - const channelsUtils = new ChannelsUtils(); - const productsUtils = new ProductsUtils(); - - const startsWith = "Cy-"; - - before(() => { - cy.clearSessionData().loginUserViaRequest(); - productsUtils.deleteProducts(startsWith); - channelsUtils.deleteChannels(startsWith); - }); - beforeEach(() => { cy.clearSessionData().loginUserViaRequest(); }); - xit("should add new visible product", () => { - cy.visit("/") + it("should navigate to channels page", () => { + cy.visit(urlList.homePage) .get(LEFT_MENU_SELECTORS.catalog) .click() - .get(PRODUCTS_SELECTORS.products) + .get(LEFT_MENU_SELECTORS.products) .click() + .location("pathname") + .should("contain", "/products"); + }); + + it("should add new visible product", () => { + cy.visit(urlList.products) .get(PRODUCTS_SELECTORS.createProductBtn) .click() .get(PRODUCTS_SELECTORS.productNameInput) @@ -63,47 +51,4 @@ describe("Products", () => { .get(PRODUCTS_SELECTORS.confirmationMsg) .contains("Product created"); }); - it("should display correct availibility for product in channel", () => { - const name = `${startsWith}${faker.random.number()}`; - cy.fixture("addresses").then(json => { - channels.createChannel(true, name, name, json.plAddress.currency); - productsUtils.createTypeAttributeAndCategoryForProduct(name).then(() => { - const productTypeId = productsUtils.getProductTypeId(); - const attributeId = productsUtils.getAttributeId(); - const categoryId = productsUtils.getCategoryId(); - productsUtils.createProduct( - name, - attributeId, - productTypeId, - categoryId - ); - cy.visit(URL_LIST.products) - .get(PRODUCTS_SELECTORS.searchProducts) - .type(name) - .get(PRODUCTS_SELECTORS.productsList) - .contains(name) - .click() - .get(PRODUCTS_SELECTORS.availableManageButton) - .click() - .get(PRODUCTS_SELECTORS.channelsAvailabilityForm) - .contains(name) - .click() - .get(BUTTON_SELECTORS.submit) - .click() - .get(PRODUCTS_SELECTORS.saveBtn) - .click() - .get(PRODUCTS_SELECTORS.goBackButton) - .click() - .get(PRODUCTS_SELECTORS.searchProducts) - .type(name) - .get(PRODUCTS_SELECTORS.productsList) - .contains(name) - .parentsUntil("tbody") - .find(PRODUCTS_SELECTORS.channelAvailabilityColumn) - .click() - .get(PRODUCTS_SELECTORS.channelAvailabilityList) - .contains(name); - }); - }); - }); }); diff --git a/cypress/integration/products/publish.js b/cypress/integration/products/publish.js deleted file mode 100644 index aa274dee4..000000000 --- a/cypress/integration/products/publish.js +++ /dev/null @@ -1,144 +0,0 @@ -import faker from "faker"; - -import ShopInfo from "../../apiRequests/ShopInfo"; -import { PRODUCTS_SELECTORS } from "../../elements/catalog/product-selectors"; -import { SEARCH_SELECTORS } from "../../elements/frontend-elements/search-selectors"; -import SearchSteps from "../../steps/frontendSteps/searchSteps"; -import { URL_LIST } from "../../url/url-list"; -import ChannelsUtils from "../../utils/channelsUtils"; -import ProductsUtils from "../../utils/productsUtils"; - -// -describe("Products", () => { - const channelsUtils = new ChannelsUtils(); - const productsUtils = new ProductsUtils(); - const searchSteps = new SearchSteps(); - - const shopInfo = new ShopInfo(); - - const startsWith = "Cy-"; - const name = `${startsWith}${faker.random.number()}`; - let productTypeId; - let attributeId; - let categoryId; - - before(() => { - cy.clearSessionData().loginUserViaRequest(); - productsUtils.deleteProducts(startsWith); - productsUtils.createTypeAttributeAndCategoryForProduct(name).then(() => { - productTypeId = productsUtils.getProductTypeId(); - attributeId = productsUtils.getAttributeId(); - categoryId = productsUtils.getCategoryId(); - }); - }); - - beforeEach(() => { - cy.clearSessionData().loginUserViaRequest(); - shopInfo - .getShopInfo() - .its("body.data.shop.domain.url") - .as("shopUrl"); - }); - it("should display on frontend only published products", () => { - const productName = `${startsWith}${faker.random.number()}`; - channelsUtils.getDefaultChannel().then(defaultChannel => { - productsUtils - .createProductInChannel( - productName, - productTypeId, - attributeId, - categoryId, - defaultChannel.id, - false, - false, - true - ) - .then(() => { - cy.visit(`${URL_LIST.products}${productsUtils.getCreatedProductId()}`) - .get(PRODUCTS_SELECTORS.assignedChannels) - .click() - .get(PRODUCTS_SELECTORS.publishedRadioButton) - .contains("Opublikowany") - .click() - .get(PRODUCTS_SELECTORS.saveBtn) - .click() - .waitForGraph("ProductChannelListingUpdate") - .get("@shopUrl") - .then(shopUrl => { - cy.visit(shopUrl); - searchSteps.searchFor(productName); - cy.get(SEARCH_SELECTORS.productItem).contains(productName); - }); - }); - }); - }); - it("shouldn't display not published product for unlogged user", () => { - const productName = `${startsWith}${faker.random.number()}`; - channelsUtils.getDefaultChannel().then(defaultChannel => { - productsUtils - .createProductInChannel( - productName, - productTypeId, - attributeId, - categoryId, - defaultChannel.id, - true, - false, - true - ) - .then(() => { - cy.visit(`${URL_LIST.products}${productsUtils.getCreatedProductId()}`) - .get(PRODUCTS_SELECTORS.assignedChannels) - .click() - .get(PRODUCTS_SELECTORS.publishedRadioButton) - .contains("Nie opublikowano") - .click() - .get(PRODUCTS_SELECTORS.saveBtn) - .click() - .waitForGraph("ProductChannelListingUpdate") - .get("@shopUrl") - .then(shopUrl => { - cy.visit(shopUrl); - searchSteps.searchFor(productName); - cy.get(SEARCH_SELECTORS.productItem).should("not.exist"); - }); - }); - }); - }); - it("should display not published product for staff member", () => { - const productName = `${startsWith}${faker.random.number()}`; - channelsUtils.getDefaultChannel().then(defaultChannel => { - productsUtils - .createProductInChannel( - productName, - productTypeId, - attributeId, - categoryId, - defaultChannel.id, - true, - false, - true - ) - .then(() => { - cy.visit(`${URL_LIST.products}${productsUtils.getCreatedProductId()}`) - .get(PRODUCTS_SELECTORS.assignedChannels) - .click() - .get(PRODUCTS_SELECTORS.publishedRadioButton) - .contains("Nie opublikowano") - .click() - .get(PRODUCTS_SELECTORS.saveBtn) - .click() - .waitForGraph("ProductChannelListingUpdate") - .get("@shopUrl") - .then(shopUrl => { - cy.visit(shopUrl) - .loginInShop() - .then(() => { - searchSteps.searchFor(productName); - cy.get(SEARCH_SELECTORS.productItem).contains(productName); - }); - }); - }); - }); - }); -}); diff --git a/cypress/integration/products/publishedProducts.js b/cypress/integration/products/publishedProducts.js new file mode 100644 index 000000000..5d6a46378 --- /dev/null +++ b/cypress/integration/products/publishedProducts.js @@ -0,0 +1,94 @@ +import faker from "faker"; + +import ProductSteps from "../../steps/productSteps"; +import { URL_LIST } from "../../url/url-list"; +import ChannelsUtils from "../../utils/channelsUtils"; +import FrontShopProductUtils from "../../utils/frontShop/frontShopProductUtils"; +import ProductsUtils from "../../utils/productsUtils"; + +// +describe("Publish products", () => { + const channelsUtils = new ChannelsUtils(); + const productsUtils = new ProductsUtils(); + const productSteps = new ProductSteps(); + const frontShopProductUtils = new FrontShopProductUtils(); + + const startsWith = "Cy-"; + const name = `${startsWith}${faker.random.number()}`; + let productTypeId; + let attributeId; + let categoryId; + + before(() => { + cy.clearSessionData().loginUserViaRequest(); + productsUtils.deleteProducts(startsWith); + productsUtils.createTypeAttributeAndCategoryForProduct(name).then(() => { + productTypeId = productsUtils.getProductTypeId(); + attributeId = productsUtils.getAttributeId(); + categoryId = productsUtils.getCategoryId(); + }); + }); + + beforeEach(() => { + cy.clearSessionData().loginUserViaRequest(); + }); + it("should update product to published", () => { + const productName = `${startsWith}${faker.random.number()}`; + channelsUtils.getDefaultChannel().then(defaultChannel => { + productsUtils + .createProductInChannel( + productName, + productTypeId, + attributeId, + categoryId, + defaultChannel.id, + false, + false, + true + ) + .then(() => { + const productId = productsUtils.getCreatedProductId(); + const productUrl = `${URL_LIST.products}${productId}`; + productSteps.updateProductPublish(productUrl, true); + frontShopProductUtils + .isProductVisible(productId, defaultChannel.slug, productName) + .then(isVisible => { + expect(isVisible).to.be.eq(true); + }); + }); + }); + }); + it("should update product to not published", () => { + const productName = `${startsWith}${faker.random.number()}`; + channelsUtils.getDefaultChannel().then(defaultChannel => { + productsUtils + .createProductInChannel( + productName, + productTypeId, + attributeId, + categoryId, + defaultChannel.id, + true, + false, + true + ) + .then(() => { + const productId = productsUtils.getCreatedProductId(); + const productUrl = `${URL_LIST.products}${productId}`; + productSteps.updateProductPublish(productUrl, false); + frontShopProductUtils + .isProductVisible(productId, defaultChannel.slug, productName) + .then(isVisible => { + expect(isVisible).to.be.eq(false); + }); + cy.loginInShop().then(() => { + frontShopProductUtils + .isProductVisible(productId, defaultChannel.slug, productName) + .then(isVisible => { + expect(isVisible).to.be.eq(true); + }); + }); + }); + }); + }); +}); diff --git a/cypress/integration/products/showInListings.js b/cypress/integration/products/showInListings.js deleted file mode 100644 index a4a67fe72..000000000 --- a/cypress/integration/products/showInListings.js +++ /dev/null @@ -1,144 +0,0 @@ -import faker from "faker"; - -import ShopInfo from "../../apiRequests/ShopInfo"; -import { PRODUCTS_SELECTORS } from "../../elements/catalog/product-selectors"; -import { SEARCH_SELECTORS } from "../../elements/frontend-elements/search-selectors"; -import SearchSteps from "../../steps/frontendSteps/searchSteps"; -import { URL_LIST } from "../../url/url-list"; -import ChannelsUtils from "../../utils/channelsUtils"; -import ProductsUtils from "../../utils/productsUtils"; - -// -describe("Products", () => { - const channelsUtils = new ChannelsUtils(); - const productsUtils = new ProductsUtils(); - const searchSteps = new SearchSteps(); - - const shopInfo = new ShopInfo(); - - const startsWith = "Cy-"; - const name = `${startsWith}${faker.random.number()}`; - let productTypeId; - let attributeId; - let categoryId; - - before(() => { - cy.clearSessionData().loginUserViaRequest(); - productsUtils.deleteProducts(startsWith); - productsUtils.createTypeAttributeAndCategoryForProduct(name).then(() => { - productTypeId = productsUtils.getProductTypeId(); - attributeId = productsUtils.getAttributeId(); - categoryId = productsUtils.getCategoryId(); - }); - }); - - beforeEach(() => { - cy.clearSessionData().loginUserViaRequest(); - shopInfo - .getShopInfo() - .its("body.data.shop.domain.url") - .as("shopUrl"); - }); - it("should display on frontend only visible in listings products", () => { - const productName = `${startsWith}${faker.random.number()}`; - channelsUtils.getDefaultChannel().then(defaultChannel => { - productsUtils - .createProductInChannel( - productName, - productTypeId, - attributeId, - categoryId, - defaultChannel.id, - true, - false, - false - ) - .then(() => { - cy.visit(`${URL_LIST.products}${productsUtils.getCreatedProductId()}`) - .get(PRODUCTS_SELECTORS.assignedChannels) - .click() - .get(PRODUCTS_SELECTORS.visibleInListingsButton) - .contains("Wyświetlaj na liście produktów") - .click() - .get(PRODUCTS_SELECTORS.saveBtn) - .click() - .waitForGraph("ProductChannelListingUpdate") - .get("@shopUrl") - .then(shopUrl => { - cy.visit(shopUrl); - searchSteps.searchFor(productName); - cy.get(SEARCH_SELECTORS.productItem).contains(productName); - }); - }); - }); - }); - it("shouldn't display not visible in listing product for unlogged user", () => { - const productName = `${startsWith}${faker.random.number()}`; - channelsUtils.getDefaultChannel().then(defaultChannel => { - productsUtils - .createProductInChannel( - productName, - productTypeId, - attributeId, - categoryId, - defaultChannel.id, - true, - false, - true - ) - .then(() => { - cy.visit(`${URL_LIST.products}${productsUtils.getCreatedProductId()}`) - .get(PRODUCTS_SELECTORS.assignedChannels) - .click() - .get(PRODUCTS_SELECTORS.visibleInListingsButton) - .contains("Wyświetlaj na liście produktów") - .click() - .get(PRODUCTS_SELECTORS.saveBtn) - .click() - .waitForGraph("ProductChannelListingUpdate") - .get("@shopUrl") - .then(shopUrl => { - cy.visit(shopUrl); - searchSteps.searchFor(productName); - cy.get(SEARCH_SELECTORS.productItem).should("not.exist"); - }); - }); - }); - }); - it("should display not visible in listing product for staff member", () => { - const productName = `${startsWith}${faker.random.number()}`; - channelsUtils.getDefaultChannel().then(defaultChannel => { - productsUtils - .createProductInChannel( - productName, - productTypeId, - attributeId, - categoryId, - defaultChannel.id, - true, - false, - true - ) - .then(() => { - cy.visit(`${URL_LIST.products}${productsUtils.getCreatedProductId()}`) - .get(PRODUCTS_SELECTORS.assignedChannels) - .click() - .get(PRODUCTS_SELECTORS.visibleInListingsButton) - .contains("Wyświetlaj na liście produktów") - .click() - .get(PRODUCTS_SELECTORS.saveBtn) - .click() - .waitForGraph("ProductChannelListingUpdate") - .get("@shopUrl") - .then(shopUrl => { - cy.visit(shopUrl) - .loginInShop() - .then(() => { - searchSteps.searchFor(productName); - cy.get(SEARCH_SELECTORS.productItem).contains(productName); - }); - }); - }); - }); - }); -}); diff --git a/cypress/integration/products/visibleInListingsProducts.js b/cypress/integration/products/visibleInListingsProducts.js new file mode 100644 index 000000000..2d6ff8614 --- /dev/null +++ b/cypress/integration/products/visibleInListingsProducts.js @@ -0,0 +1,94 @@ +import faker from "faker"; + +import ProductSteps from "../../steps/productSteps"; +import { URL_LIST } from "../../url/url-list"; +import ChannelsUtils from "../../utils/channelsUtils"; +import FrontShopProductUtils from "../../utils/frontShop/frontShopProductUtils"; +import ProductsUtils from "../../utils/productsUtils"; + +// +describe("Products displayed in listings", () => { + const channelsUtils = new ChannelsUtils(); + const productsUtils = new ProductsUtils(); + const productSteps = new ProductSteps(); + const frontShopProductUtils = new FrontShopProductUtils(); + + const startsWith = "Cy-"; + const name = `${startsWith}${faker.random.number()}`; + let productTypeId; + let attributeId; + let categoryId; + + before(() => { + cy.clearSessionData().loginUserViaRequest(); + productsUtils.deleteProducts(startsWith); + productsUtils.createTypeAttributeAndCategoryForProduct(name).then(() => { + productTypeId = productsUtils.getProductTypeId(); + attributeId = productsUtils.getAttributeId(); + categoryId = productsUtils.getCategoryId(); + }); + }); + + beforeEach(() => { + cy.clearSessionData().loginUserViaRequest(); + }); + it("should update product to visible in listings", () => { + const productName = `${startsWith}${faker.random.number()}`; + channelsUtils.getDefaultChannel().then(defaultChannel => { + productsUtils + .createProductInChannel( + productName, + productTypeId, + attributeId, + categoryId, + defaultChannel.id, + true, + false, + false + ) + .then(() => { + const productId = productsUtils.getCreatedProductId(); + const productUrl = `${URL_LIST.products}${productId}`; + productSteps.updateProductVisibleInListings(productUrl); + frontShopProductUtils + .isProductVisibleInSearchResult(productName, defaultChannel.slug) + .then(isProductVisible => { + expect(isProductVisible).to.be.eq(true); + }); + }); + }); + }); + it("should update product to not visible in listings", () => { + const productName = `${startsWith}${faker.random.number()}`; + channelsUtils.getDefaultChannel().then(defaultChannel => { + productsUtils + .createProductInChannel( + productName, + productTypeId, + attributeId, + categoryId, + defaultChannel.id, + true, + false, + true + ) + .then(() => { + const productId = productsUtils.getCreatedProductId(); + const productUrl = `${URL_LIST.products}${productId}`; + productSteps.updateProductVisibleInListings(productUrl); + frontShopProductUtils + .isProductVisibleInSearchResult(productName, defaultChannel.slug) + .then(isProductVisible => { + expect(isProductVisible).to.be.eq(false); + }); + cy.loginInShop().then(() => { + frontShopProductUtils + .isProductVisibleInSearchResult(productName, defaultChannel.slug) + .then(isProductVisible => { + expect(isProductVisible).to.be.eq(true); + }); + }); + }); + }); + }); +}); diff --git a/cypress/steps/productSteps.js b/cypress/steps/productSteps.js new file mode 100644 index 000000000..244ab8392 --- /dev/null +++ b/cypress/steps/productSteps.js @@ -0,0 +1,46 @@ +import { PRODUCTS_SELECTORS } from "../elements/catalog/product-selectors"; + +class ProductSteps { + updateProductIsAvailableForPurchase(productUrl, isAvailableForPurchase) { + let isAvailableForPurchaseSelector; + if (isAvailableForPurchase) { + isAvailableForPurchaseSelector = PRODUCTS_SELECTORS.radioButtonsValueTrue; + } else { + isAvailableForPurchaseSelector = + PRODUCTS_SELECTORS.radioButtonsValueFalse; + } + this.updateProductMenageInChannel( + productUrl, + `${PRODUCTS_SELECTORS.availableForPurchaseRadioButtons}${isAvailableForPurchaseSelector}` + ); + } + updateProductPublish(productUrl, isPublished) { + let isPublishedSelector; + if (isPublished) { + isPublishedSelector = PRODUCTS_SELECTORS.radioButtonsValueTrue; + } else { + isPublishedSelector = PRODUCTS_SELECTORS.radioButtonsValueFalse; + } + this.updateProductMenageInChannel( + productUrl, + `${PRODUCTS_SELECTORS.publishedRadioButtons}${isPublishedSelector}` + ); + } + updateProductVisibleInListings(productUrl) { + this.updateProductMenageInChannel( + productUrl, + PRODUCTS_SELECTORS.visibleInListingsButton + ); + } + updateProductMenageInChannel(productUrl, menageSelector) { + cy.visit(productUrl) + .get(PRODUCTS_SELECTORS.assignedChannels) + .click() + .get(menageSelector) + .click() + .get(PRODUCTS_SELECTORS.saveBtn) + .click() + .waitForGraph("ProductChannelListingUpdate"); + } +} +export default ProductSteps; diff --git a/cypress/support/frontShop/index.js b/cypress/support/frontShop/index.js deleted file mode 100644 index ecc38b831..000000000 --- a/cypress/support/frontShop/index.js +++ /dev/null @@ -1,41 +0,0 @@ -/* eslint-disable sort-keys */ - -Cypress.Commands.add("searchInShop", searchQuery => - cy.request({ - method: "POST", - url: Cypress.env("API_URI"), - 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" - } - ] - }) -); -Cypress.Commands.add("getProductDetails", (productId, channelId) => - cy.request({ - method: "POST", - url: Cypress.env("API_URI"), - 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" - } - ] - }) -); diff --git a/cypress/support/index.js b/cypress/support/index.js index 8576cdfa2..03851e2ca 100644 --- a/cypress/support/index.js +++ b/cypress/support/index.js @@ -1,5 +1,4 @@ import "./user"; -import "./frontShop"; import { urlList } from "../url/urlList"; diff --git a/cypress/utils/frontShop/frontShopProductUtils.js b/cypress/utils/frontShop/frontShopProductUtils.js new file mode 100644 index 000000000..1b8411f23 --- /dev/null +++ b/cypress/utils/frontShop/frontShopProductUtils.js @@ -0,0 +1,28 @@ +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;