From 074c0f7a6c3fe6f2bfc3c2322d71d127f7058f97 Mon Sep 17 00:00:00 2001 From: Karolina Rakoczy Date: Wed, 28 Apr 2021 15:10:47 +0200 Subject: [PATCH] Saleor 2960 checkout products without shipment (#1075) * add tests for puchase by type * add expect for isShippingRequired --- cypress/apiRequests/Attribute.js | 4 +- cypress/apiRequests/Category.js | 4 +- cypress/apiRequests/Channels.js | 11 +- cypress/apiRequests/Checkout.js | 71 +++++- cypress/apiRequests/Order.js | 16 +- cypress/apiRequests/Product.js | 41 +-- cypress/apiRequests/ShippingMethod.js | 4 +- cypress/apiRequests/Warehouse.js | 4 +- cypress/apiRequests/utils/Utils.js | 6 + .../catalog/products/product-details.js | 2 + cypress/elements/shared/button-selectors.js | 1 + cypress/fixtures/addresses.json | 14 +- cypress/integration/collections.js | 4 +- cypress/integration/configuration/channels.js | 26 +- .../productTypes/purchaseWithProductTypes.js | 233 ++++++++++++++++++ .../configuration/shippingMethod.js | 17 +- cypress/integration/discounts/sales.js | 7 +- cypress/integration/discounts/vouchers.js | 6 +- .../integration/homePage/homePageAnalitics.js | 2 +- .../orders/channelsInDraftOrders.js | 3 +- cypress/integration/orders/orders.js | 2 +- cypress/integration/products/createProduct.js | 12 +- .../productsList/filteringProducts.js | 4 +- .../integration/products/productsVariants.js | 23 +- .../integration/products/updatingProducts.js | 2 +- .../steps/catalog/products/VariantsSteps.js | 10 +- cypress/steps/draftOrderSteps.js | 65 ++--- cypress/utils/channelsUtils.js | 10 - cypress/utils/ordersUtils.js | 55 ++--- cypress/utils/products/productsUtils.js | 93 ++----- cypress/utils/shippingUtils.js | 20 +- 31 files changed, 537 insertions(+), 235 deletions(-) create mode 100644 cypress/integration/configuration/productTypes/purchaseWithProductTypes.js diff --git a/cypress/apiRequests/Attribute.js b/cypress/apiRequests/Attribute.js index eec70b621..1ea732286 100644 --- a/cypress/apiRequests/Attribute.js +++ b/cypress/apiRequests/Attribute.js @@ -18,7 +18,9 @@ export function createAttribute(name, attributeValues = ["value"]) { } } }`; - return cy.sendRequestWithQuery(mutation); + return cy + .sendRequestWithQuery(mutation) + .its("body.data.attributeCreate.attribute"); } export function getAttributes(first, search) { diff --git a/cypress/apiRequests/Category.js b/cypress/apiRequests/Category.js index cf94221fb..cb4be5384 100644 --- a/cypress/apiRequests/Category.js +++ b/cypress/apiRequests/Category.js @@ -11,7 +11,9 @@ export function createCategory(name, slug = name) { } } }`; - return cy.sendRequestWithQuery(mutation); + return cy + .sendRequestWithQuery(mutation) + .its("body.data.categoryCreate.category"); } export function getCategories(first, search) { const mutation = `query{ diff --git a/cypress/apiRequests/Channels.js b/cypress/apiRequests/Channels.js index c9780e2b6..2dd730d2b 100644 --- a/cypress/apiRequests/Channels.js +++ b/cypress/apiRequests/Channels.js @@ -1,4 +1,9 @@ -export function createChannel(isActive, name, slug, currencyCode) { +export function createChannel({ + isActive = true, + name, + slug = name, + currencyCode = "PLN" +}) { const createChannelMutation = `mutation{ channelCreate(input: { isActive: ${isActive} @@ -17,7 +22,9 @@ export function createChannel(isActive, name, slug, currencyCode) { } } }`; - return cy.sendRequestWithQuery(createChannelMutation); + return cy + .sendRequestWithQuery(createChannelMutation) + .its("body.data.channelCreate.channel"); } export function getChannels() { const getChannelsInfoQuery = `query{ diff --git a/cypress/apiRequests/Checkout.js b/cypress/apiRequests/Checkout.js index f088b44f0..ccab375e4 100644 --- a/cypress/apiRequests/Checkout.js +++ b/cypress/apiRequests/Checkout.js @@ -1,17 +1,20 @@ -import { getDefaultAddress } from "./utils/Utils"; +import { getDefaultAddress, getVariantsLines } from "./utils/Utils"; + export function createCheckout({ channelSlug, email, productQuantity = 1, variantsList, address, + billingAddress, auth = "auth" }) { - const lines = variantsList.map( - variant => `{quantity:${productQuantity} - variantId:"${variant.id}"}` - ); + const lines = getVariantsLines(variantsList, productQuantity); const shippingAddress = getDefaultAddress(address, "shippingAddress"); + const billingAddressLines = getDefaultAddress( + billingAddress, + "billingAddress" + ); const mutation = `mutation{ checkoutCreate(input:{ @@ -19,6 +22,7 @@ export function createCheckout({ email:"${email}" lines: [${lines.join()}] ${shippingAddress} + ${billingAddressLines} }){ checkoutErrors{ field @@ -33,7 +37,9 @@ export function createCheckout({ } } }`; - return cy.sendRequestWithQuery(mutation, auth); + return cy + .sendRequestWithQuery(mutation, auth) + .its("body.data.checkoutCreate.checkout"); } export function addShippingMethod(checkoutId, shippingMethodId) { const mutation = `mutation{ @@ -47,6 +53,7 @@ export function addShippingMethod(checkoutId, shippingMethodId) { }`; return cy.sendRequestWithQuery(mutation); } + export function addPayment(checkoutId, gateway, token) { const mutation = `mutation{ checkoutPaymentCreate(checkoutId:"${checkoutId}", @@ -60,8 +67,11 @@ export function addPayment(checkoutId, gateway, token) { } } }`; - return cy.sendRequestWithQuery(mutation); + return cy + .sendRequestWithQuery(mutation) + .its("body.data.checkoutPaymentCreate"); } + export function completeCheckout(checkoutId) { const mutation = `mutation{ checkoutComplete(checkoutId:"${checkoutId}"){ @@ -76,7 +86,9 @@ export function completeCheckout(checkoutId) { } } }`; - return cy.sendRequestWithQuery(mutation); + return cy + .sendRequestWithQuery(mutation) + .its("body.data.checkoutComplete.order"); } export function addVoucher(checkoutId, voucherCode) { @@ -99,3 +111,46 @@ export function addVoucher(checkoutId, voucherCode) { }`; return cy.sendRequestWithQuery(mutation); } + +export function checkoutVariantsUpdate(checkoutId, variantsList) { + const lines = getVariantsLines(variantsList, 1); + const mutation = `mutation{ + checkoutLinesUpdate(checkoutId:"${checkoutId}", + lines: [${lines.join()}]){ + checkoutErrors{ + field + message + } + } + }`; + return cy.sendRequestWithQuery(mutation); +} + +export function checkoutShippingMethodUpdate(checkoutId, shippingMethodId) { + const mutation = `mutation{ + checkoutShippingMethodUpdate(checkoutId:"${checkoutId}" shippingMethodId:"${shippingMethodId}"){ + checkoutErrors{ + field + message + } + } + }`; + return cy + .sendRequestWithQuery(mutation) + .its("body.data.checkoutShippingMethodUpdate"); +} + +export function checkoutShippingAddressUpdate(checkoutId, address) { + const shippingAddress = getDefaultAddress(address, "shippingAddress"); + const mutation = `mutation{ + checkoutShippingAddressUpdate(checkoutId:"${checkoutId}", + ${shippingAddress} + ){ + checkoutErrors{ + field + message + } + } + }`; + return cy.sendRequestWithQuery(mutation); +} diff --git a/cypress/apiRequests/Order.js b/cypress/apiRequests/Order.js index 454b96cc4..e10dd1710 100644 --- a/cypress/apiRequests/Order.js +++ b/cypress/apiRequests/Order.js @@ -39,7 +39,9 @@ export function createDraftOrder(customerId, shippingMethodId, channelId) { } } }`; - return cy.sendRequestWithQuery(mutation); + return cy + .sendRequestWithQuery(mutation) + .its("body.data.draftOrderCreate.order"); } export function completeOrder(orderId) { const mutation = `mutation{ @@ -54,3 +56,15 @@ export function completeOrder(orderId) { }`; return cy.sendRequestWithQuery(mutation); } +export function getOrder(orderId) { + const query = `query getOrder{ + order(id:"${orderId}"){ + status + isShippingRequired + shippingMethod{ + id + } + } + }`; + cy.sendRequestWithQuery(query).its("body.data.order"); +} diff --git a/cypress/apiRequests/Product.js b/cypress/apiRequests/Product.js index f1b0ebc48..68da6345c 100644 --- a/cypress/apiRequests/Product.js +++ b/cypress/apiRequests/Product.js @@ -36,7 +36,9 @@ export function updateProduct(productId, input) { } } `; - return cy.sendRequestWithQuery(mutation); + return cy + .sendRequestWithQuery(mutation) + .its("body.data.productUpdate.product"); } export function updateChannelInProduct({ @@ -83,14 +85,14 @@ export function updateChannelPriceInVariant(variantId, channelId) { } `; return cy.sendRequestWithQuery(mutation); } -export function createProduct( +export function createProduct({ attributeId, name, - productType, - category, + productTypeId, + categoryId, collectionId, description -) { +}) { const collection = getValueWithDefault( collectionId, `collections:["${collectionId}"]` @@ -107,8 +109,8 @@ export function createProduct( name:"${name}" slug:"${name}" seo:{title:"${name}" description:""} - productType:"${productType}" - category:"${category}" + productType:"${productTypeId}" + category:"${categoryId}" ${collection} ${descriptionLine} }){ @@ -122,14 +124,16 @@ export function createProduct( } } }`; - return cy.sendRequestWithQuery(mutation); + return cy + .sendRequestWithQuery(mutation) + .its("body.data.productCreate.product"); } export function createVariant({ productId, sku, warehouseId, - quantity, + quantityInWarehouse, channelId, attributeId, price = 1, @@ -148,7 +152,7 @@ export function createVariant({ warehouseId, `stocks:{ warehouse:"${warehouseId}" - quantity:${quantity} + quantity:${quantityInWarehouse} }` ); @@ -172,23 +176,26 @@ export function createVariant({ } } }`; - return cy.sendRequestWithQuery(mutation); + return cy + .sendRequestWithQuery(mutation) + .its("body.data.productVariantBulkCreate.productVariants"); } -export function createTypeProduct( +export function createTypeProduct({ name, attributeId, hasVariants = true, - slug = name -) { + slug = name, + shippable = true +}) { const mutation = `mutation{ productTypeCreate(input: { name: "${name}" slug: "${slug}" - isShippingRequired: true productAttributes: "${attributeId}" variantAttributes: "${attributeId}" hasVariants: ${hasVariants} + isShippingRequired:${shippable} }){ productErrors{ field @@ -200,7 +207,9 @@ export function createTypeProduct( } } } `; - return cy.sendRequestWithQuery(mutation); + return cy + .sendRequestWithQuery(mutation) + .its("body.data.productTypeCreate.productType"); } export function deleteProduct(productId) { diff --git a/cypress/apiRequests/ShippingMethod.js b/cypress/apiRequests/ShippingMethod.js index 7afb51c10..f41720d97 100644 --- a/cypress/apiRequests/ShippingMethod.js +++ b/cypress/apiRequests/ShippingMethod.js @@ -26,7 +26,9 @@ export function createShippingZone(name, country, channelId) { } } }`; - return cy.sendRequestWithQuery(mutation); + return cy + .sendRequestWithQuery(mutation) + .its("body.data.shippingZoneCreate.shippingZone"); } export function addChannelToShippingZone(shippingZoneId, channelId) { const mutation = `mutation addCh{ diff --git a/cypress/apiRequests/Warehouse.js b/cypress/apiRequests/Warehouse.js index 3cb58b414..1b97f7499 100644 --- a/cypress/apiRequests/Warehouse.js +++ b/cypress/apiRequests/Warehouse.js @@ -22,7 +22,9 @@ export function createWarehouse({ name, shippingZone, address, slug = name }) { } } }`; - return cy.sendRequestWithQuery(mutation); + return cy + .sendRequestWithQuery(mutation) + .its("body.data.createWarehouse.warehouse"); } export function getWarehouses(first, search) { const query = `query{ diff --git a/cypress/apiRequests/utils/Utils.js b/cypress/apiRequests/utils/Utils.js index c848f889c..4bd266a87 100644 --- a/cypress/apiRequests/utils/Utils.js +++ b/cypress/apiRequests/utils/Utils.js @@ -19,3 +19,9 @@ export function getDefaultAddress(address, addressType, withName = true) { } return `${addressType}:{${defaultAddress}}`; } +export function getVariantsLines(variantsList, quantity) { + return variantsList.map( + variant => `{quantity:${quantity} + variantId:"${variant.id}"}` + ); +} diff --git a/cypress/elements/catalog/products/product-details.js b/cypress/elements/catalog/products/product-details.js index 7e685c086..cc69741d0 100644 --- a/cypress/elements/catalog/products/product-details.js +++ b/cypress/elements/catalog/products/product-details.js @@ -13,6 +13,8 @@ export const PRODUCT_DETAILS = { descriptionInput: "[data-test-id='description']", ratingInput: "[name='rating']", skuInput: "[name='sku']", + variantRow: "[data-test-id='product-variant-row']", + variantPrice: '[data-test="price"]', collectionRemoveButtons: '[data-test-id="collectionRemove"]', variantRow: "[data-test-id='product-variant-row']" }; diff --git a/cypress/elements/shared/button-selectors.js b/cypress/elements/shared/button-selectors.js index ceb5c1b1c..2062b20dc 100644 --- a/cypress/elements/shared/button-selectors.js +++ b/cypress/elements/shared/button-selectors.js @@ -4,6 +4,7 @@ export const BUTTON_SELECTORS = { confirm: '[data-test="button-bar-confirm"]', goBackButton: "[data-test-id='app-header-back-button']", checkbox: "[type='checkbox']", + checked: "[class*='checked']", selectOption: "[data-test*='select-option']", notSelectedOption: ":not([aria-selected])", deleteButton: '[data-test="button-bar-delete"]', diff --git a/cypress/fixtures/addresses.json b/cypress/fixtures/addresses.json index 4a4ee677a..820b814fe 100644 --- a/cypress/fixtures/addresses.json +++ b/cypress/fixtures/addresses.json @@ -10,5 +10,17 @@ "phone": "123456787", "currency": "PLN", "countryFullName": "Poland" - } + }, + "usAddress": { + "companyName": "Test3", + "streetAddress1": "Amber Prairie", + "streetAddress2": "483", + "city": "KIRKSHIRE", + "postalCode": "52216", + "country": "US", + "countryArea": "IA", + "currency": "USD", + "phone": "+12025550180", + "countryFullName": "United States of America" + } } \ No newline at end of file diff --git a/cypress/integration/collections.js b/cypress/integration/collections.js index 21c0ad97f..4677d3544 100644 --- a/cypress/integration/collections.js +++ b/cypress/integration/collections.js @@ -1,6 +1,7 @@ // import faker from "faker"; +import { createChannel } from "../apiRequests/Channels"; import { updateChannelInProduct } from "../apiRequests/Product"; import { getCollection } from "../apiRequests/storeFront/Collections"; import { searchInShop } from "../apiRequests/storeFront/Search"; @@ -108,8 +109,7 @@ describe("Collections", () => { let collection; let channel; - channelsUtils - .createChannel({ name: collectionName }) + createChannel({ name: collectionName }) .then(channelResp => { channel = channelResp; updateChannelInProduct(product.id, channel.id); diff --git a/cypress/integration/configuration/channels.js b/cypress/integration/configuration/channels.js index 2ea8f65ba..0cc10de34 100644 --- a/cypress/integration/configuration/channels.js +++ b/cypress/integration/configuration/channels.js @@ -83,7 +83,12 @@ describe("Channels", () => { it("should validate slug name", () => { const randomChannel = `${channelStartsWith} ${faker.datatype.number()}`; - createChannel(false, randomChannel, randomChannel, currency); + createChannel({ + isActive: false, + name: randomChannel, + slug: randomChannel, + currencyCode: currency + }); cy.visit(urlList.channels); createChannelByView(randomChannel, currency); cy.get(ADD_CHANNEL_FORM_SELECTORS.slugValidationMessage).should( @@ -102,12 +107,12 @@ describe("Channels", () => { it("should delete channel", () => { const randomChannelToDelete = `${channelStartsWith} ${faker.datatype.number()}`; - createChannel( - false, - randomChannelToDelete, - randomChannelToDelete, - currency - ); + createChannel({ + isActive: false, + name: randomChannelToDelete, + slug: randomChannelToDelete, + currencyCode: currency + }); cy.addAliasToGraphRequest("Channels"); cy.visit(urlList.channels); cy.wait("@Channels"); @@ -126,7 +131,12 @@ describe("Channels", () => { it("should not be possible to add products to order with inactive channel", () => { const randomChannel = `${channelStartsWith} ${faker.datatype.number()}`; - createChannel(false, randomChannel, randomChannel, currency); + createChannel({ + isActive: false, + name: randomChannel, + slug: randomChannel, + currencyCode: currency + }); cy.visit(urlList.orders) .get(ORDERS_SELECTORS.createOrder) .click() diff --git a/cypress/integration/configuration/productTypes/purchaseWithProductTypes.js b/cypress/integration/configuration/productTypes/purchaseWithProductTypes.js new file mode 100644 index 000000000..91d0498aa --- /dev/null +++ b/cypress/integration/configuration/productTypes/purchaseWithProductTypes.js @@ -0,0 +1,233 @@ +import faker from "faker"; + +import { createAttribute } from "../../../apiRequests/Attribute"; +import { createCategory } from "../../../apiRequests/Category"; +import { + checkoutShippingAddressUpdate, + checkoutShippingMethodUpdate, + checkoutVariantsUpdate, + completeCheckout, + createCheckout +} from "../../../apiRequests/Checkout"; +import { getOrder } from "../../../apiRequests/Order"; +import { createTypeProduct } from "../../../apiRequests/Product"; +import { getDefaultChannel } from "../../../utils/channelsUtils"; +import { + addPayment, + createAndCompleteCheckoutWithoutShipping, + createWaitingForCaptureOrder +} from "../../../utils/ordersUtils"; +import { + createProductInChannel, + deleteProductsStartsWith +} from "../../../utils/products/productsUtils"; +import { + createShipping, + deleteShippingStartsWith +} from "../../../utils/shippingUtils"; + +describe("Purchase products with all products types", () => { + const startsWith = `CyPurchaseByType`; + const name = `${startsWith}${faker.datatype.number()}`; + const email = `${startsWith}@example.com`; + const testsMessage = "Check order status"; + const { softExpect } = chai; + + let defaultChannel; + let address; + let warehouse; + let attribute; + let category; + let shippingMethod; + let createProductData; + + before(() => { + cy.clearSessionData().loginUserViaRequest(); + deleteProductsStartsWith(startsWith); + deleteShippingStartsWith(startsWith); + getDefaultChannel().then(channelResp => (defaultChannel = channelResp)); + cy.fixture("addresses") + .then(addresses => { + address = addresses.usAddress; + createShipping({ + channelId: defaultChannel.id, + name, + address, + price: 10 + }); + }) + .then( + ({ warehouse: warehouseResp, shippingMethod: shippingMethodResp }) => { + warehouse = warehouseResp; + shippingMethod = shippingMethodResp; + } + ); + createAttribute(name) + .then(attributeResp => { + attribute = attributeResp; + createCategory(name); + }) + .then(categoryResp => { + category = categoryResp; + }); + }); + + beforeEach(() => { + cy.clearSessionData().loginUserViaRequest(); + createProductData = { + channelId: defaultChannel.id, + warehouseId: warehouse.id, + quantityInWarehouse: 10, + attributeId: attribute.id, + categoryId: category.id, + price: 10 + }; + }); + + it("should purchase digital product", () => { + const digitalName = `${startsWith}${faker.datatype.number()}`; + createTypeProduct({ + name: digitalName, + attributeId: attribute.id, + shippable: false + }) + .then(productType => { + createProductData.name = digitalName; + createProductData.productTypeId = productType.id; + createProductInChannel(createProductData); + }) + .then(({ variantsList }) => { + createAndCompleteCheckoutWithoutShipping({ + channelSlug: defaultChannel.slug, + email, + billingAddress: address, + variantsList, + auth: "token" + }); + }) + .then(({ order }) => { + getOrder(order.id); + }) + .then(order => { + softExpect( + order.isShippingRequired, + "Check if is shipping required in order" + ).to.eq(false); + expect(order.status, testsMessage).to.be.eq("UNFULFILLED"); + }); + }); + + it("should purchase physical product", () => { + const physicalName = `${startsWith}${faker.datatype.number()}`; + createTypeProduct({ + name: physicalName, + attributeId: attribute.id, + shippable: true + }) + .then(productType => { + createProductData.name = physicalName; + createProductData.productTypeId = productType.id; + createProductInChannel(createProductData); + }) + .then(({ variantsList }) => { + createWaitingForCaptureOrder( + defaultChannel.slug, + email, + variantsList, + shippingMethod.id, + address + ); + }) + .then(({ order }) => { + getOrder(order.id); + }) + .then(order => { + softExpect( + order.isShippingRequired, + "Check if is shipping required in order" + ).to.eq(true); + expect(order.status, testsMessage).to.be.eq("UNFULFILLED"); + }); + }); + it("should purchase multiple products with all product types", () => { + const physicalName = `${startsWith}${faker.datatype.number()}`; + const digitalName = `${startsWith}${faker.datatype.number()}`; + let digitalProductVariantsList; + let checkout; + createTypeProduct({ + name: digitalName, + attributeId: attribute.id, + shippable: false + }) + .then(productType => { + createProductData.name = digitalName; + createProductData.productTypeId = productType.id; + createProductInChannel(createProductData); + }) + .then(({ variantsList }) => { + digitalProductVariantsList = variantsList; + createCheckout({ + channelSlug: defaultChannel.slug, + email, + variantsList: digitalProductVariantsList, + billingAddress: address, + auth: "token" + }); + }) + .then(checkoutResp => { + checkout = checkoutResp; + addPayment(checkout.id); + }) + .then(() => { + createTypeProduct({ + name: physicalName, + attributeId: attribute.id, + shippable: true + }); + }) + .then(productType => { + createProductData.name = physicalName; + createProductData.productTypeId = productType.id; + createProductInChannel(createProductData); + }) + .then(({ variantsList }) => { + checkoutVariantsUpdate(checkout.id, variantsList); + }) + .then(() => { + checkoutShippingMethodUpdate(checkout.id, shippingMethod.id); + }) + .then(({ checkoutErrors }) => { + expect( + checkoutErrors, + "Should be not possible to add shipping method without shipping address" + ).to.have.lengthOf(1); + checkoutShippingAddressUpdate(checkout.id, address); + }) + .then(() => { + addPayment(checkout.id); + }) + .then(({ paymentErrors }) => { + expect( + paymentErrors, + "Should be not possible to add payment without shipping" + ).to.have.lengthOf(1); + checkoutShippingMethodUpdate(checkout.id, shippingMethod.id); + }) + .then(() => { + addPayment(checkout.id); + }) + .then(() => { + completeCheckout(checkout.id); + }) + .then(order => { + getOrder(order.id); + }) + .then(order => { + softExpect( + order.isShippingRequired, + "Check if is shipping required in order" + ).to.eq(true); + expect(order.status, testsMessage).to.be.eq("UNFULFILLED"); + }); + }); +}); diff --git a/cypress/integration/configuration/shippingMethod.js b/cypress/integration/configuration/shippingMethod.js index b5330bd38..0b6ff900c 100644 --- a/cypress/integration/configuration/shippingMethod.js +++ b/cypress/integration/configuration/shippingMethod.js @@ -1,10 +1,13 @@ // import faker from "faker"; +import { createChannel } from "../../apiRequests/Channels"; +import { createCheckout } from "../../apiRequests/Checkout"; import { addChannelToShippingMethod, addChannelToShippingZone } from "../../apiRequests/ShippingMethod"; +import { createWarehouse } from "../../apiRequests/Warehouse"; import { SHIPPING_ZONE_DETAILS } from "../../elements/shipping/shipping-zone-details"; import { selectChannelInHeader } from "../../steps/channelsSteps"; import { @@ -15,7 +18,6 @@ import { import { getFormattedCurrencyAmount } from "../../support/format/formatCurrencyAmount"; import { urlList } from "../../url/urlList"; import * as channelsUtils from "../../utils/channelsUtils"; -import { createCheckout } from "../../utils/ordersUtils"; import * as productsUtils from "../../utils/products/productsUtils"; import * as shippingUtils from "../../utils/shippingUtils"; import { isShippingAvailableInCheckout } from "../../utils/storeFront/checkoutUtils"; @@ -43,7 +45,7 @@ describe("Shipping methods", () => { }) .then(addresses => { plAddress = addresses.plAddress; - shippingUtils.createWarehouse({ name, address: plAddress }); + createWarehouse({ name, address: plAddress }); }) .then(warehouseResp => { warehouse = warehouseResp; @@ -66,7 +68,7 @@ describe("Shipping methods", () => { }); } ) - .then(({ variants: variantsListResp }) => { + .then(({ variantsList: variantsListResp }) => { variantsList = variantsListResp; }); }); @@ -86,11 +88,10 @@ describe("Shipping methods", () => { let shippingZone; let createdChannel; - channelsUtils - .createChannel({ - name: shippingName, - currencyCode: createdChannelCurrency - }) + createChannel({ + name: shippingName, + currencyCode: createdChannelCurrency + }) .then(channel => { createdChannel = channel; shippingUtils.createShipping({ diff --git a/cypress/integration/discounts/sales.js b/cypress/integration/discounts/sales.js index fbb261869..00145c0cc 100644 --- a/cypress/integration/discounts/sales.js +++ b/cypress/integration/discounts/sales.js @@ -2,6 +2,7 @@ import faker from "faker"; +import { createChannel } from "../../apiRequests/Channels"; import { updateChannelInProduct } from "../../apiRequests/Product"; import { assignProducts, @@ -144,9 +145,9 @@ describe("Sales discounts", () => { const discountValue = 50; const productPrice = 100; - channelsUtils - .createChannel({ name: saleName }) - .then(channelResp => (channel = channelResp)); + createChannel({ name: saleName }).then( + channelResp => (channel = channelResp) + ); productsUtils .createProductInChannel({ name: saleName, diff --git a/cypress/integration/discounts/vouchers.js b/cypress/integration/discounts/vouchers.js index d744edb1e..48bf82bca 100644 --- a/cypress/integration/discounts/vouchers.js +++ b/cypress/integration/discounts/vouchers.js @@ -1,6 +1,7 @@ // import faker from "faker"; +import { createChannel } from "../../apiRequests/Channels"; import { createVoucher, discountOptions @@ -77,7 +78,7 @@ describe("Vouchers discounts", () => { price: productPrice }); }) - .then(({ variants: variantsResp }) => (variants = variantsResp)); + .then(({ variantsList: variantsResp }) => (variants = variantsResp)); }); beforeEach(() => { @@ -142,8 +143,7 @@ describe("Vouchers discounts", () => { const randomName = `${startsWith}${faker.datatype.number()}`; const voucherValue = 50; - channelsUtils - .createChannel({ name: randomName }) + createChannel({ name: randomName }) .then(channel => { createVoucher({ voucherCode: randomName, diff --git a/cypress/integration/homePage/homePageAnalitics.js b/cypress/integration/homePage/homePageAnalitics.js index d516e43d3..feb6f7d92 100644 --- a/cypress/integration/homePage/homePageAnalitics.js +++ b/cypress/integration/homePage/homePageAnalitics.js @@ -85,7 +85,7 @@ describe("Homepage analytics", () => { }); } ) - .then(({ variants: variantsResp }) => { + .then(({ variantsList: variantsResp }) => { createdVariants = variantsResp; }); }); diff --git a/cypress/integration/orders/channelsInDraftOrders.js b/cypress/integration/orders/channelsInDraftOrders.js index 4de2fb9c8..f24b4590a 100644 --- a/cypress/integration/orders/channelsInDraftOrders.js +++ b/cypress/integration/orders/channelsInDraftOrders.js @@ -1,6 +1,7 @@ // import faker from "faker"; +import { createChannel } from "../../apiRequests/Channels"; import { CHANNEL_FORM_SELECTORS } from "../../elements/channels/channel-form-selectors"; import { HEADER_SELECTORS } from "../../elements/header/header-selectors"; import { DRAFT_ORDER_SELECTORS } from "../../elements/orders/draft-order-selectors"; @@ -26,7 +27,7 @@ describe("Channels in draft orders", () => { .getDefaultChannel() .then(channel => { defaultChannel = channel; - channelsUtils.createChannel({ name: randomName }); + createChannel({ name: randomName }); }) .then(channelResp => { otherChannel = channelResp; diff --git a/cypress/integration/orders/orders.js b/cypress/integration/orders/orders.js index 86ee05bce..7422fdc40 100644 --- a/cypress/integration/orders/orders.js +++ b/cypress/integration/orders/orders.js @@ -77,7 +77,7 @@ describe("Orders", () => { }); } ) - .then(({ variants: variantsResp }) => { + .then(({ variantsList: variantsResp }) => { variantsList = variantsResp; }); }); diff --git a/cypress/integration/products/createProduct.js b/cypress/integration/products/createProduct.js index 3dd358e50..da7538338 100644 --- a/cypress/integration/products/createProduct.js +++ b/cypress/integration/products/createProduct.js @@ -1,6 +1,8 @@ // import faker from "faker"; +import { createAttribute } from "../../apiRequests/Attribute"; +import { createTypeProduct } from "../../apiRequests/Product"; import { PRODUCT_DETAILS } from "../../elements/catalog/products/product-details"; import { PRODUCTS_LIST } from "../../elements/catalog/products/products-list"; import { BUTTON_SELECTORS } from "../../elements/shared/button-selectors"; @@ -47,7 +49,7 @@ describe("Create product", () => { before(() => { cy.clearSessionData().loginUserViaRequest(); productUtils.deleteProductsStartsWith(startsWith); - productUtils.createAttribute(name).then(attributeResp => { + createAttribute(name).then(attributeResp => { attribute = attributeResp; }); }); @@ -60,7 +62,7 @@ describe("Create product", () => { it("should create product with variants", () => { const randomName = `${startsWith}${faker.datatype.number()}`; - productUtils.createTypeProduct(randomName, attribute.id); + createTypeProduct({ name: randomName, attributeId: attribute.id }); seo.slug = randomName; const productData = { generalInfo, @@ -88,7 +90,11 @@ describe("Create product", () => { const prices = { sellingPrice: 6, costPrice: 3 }; const randomName = `${startsWith}${faker.datatype.number()}`; seo.slug = randomName; - productUtils.createTypeProduct(randomName, attribute.id, false); + createTypeProduct({ + name: randomName, + attributeId: attribute.id, + hasVariants: false + }); const productData = { generalInfo, seo, diff --git a/cypress/integration/products/productsList/filteringProducts.js b/cypress/integration/products/productsList/filteringProducts.js index f710b32a2..80a39d461 100644 --- a/cypress/integration/products/productsList/filteringProducts.js +++ b/cypress/integration/products/productsList/filteringProducts.js @@ -1,6 +1,7 @@ import faker from "faker"; import { createCollection } from "../../../apiRequests/Collections"; +import { updateProduct } from "../../../apiRequests/Product"; import { PRODUCTS_LIST } from "../../../elements/catalog/products/products-list"; import { selectFilterOption, @@ -12,8 +13,7 @@ import { getDefaultChannel } from "../../../utils/channelsUtils"; import { createProductInChannel, createTypeAttributeAndCategoryForProduct, - deleteProductsStartsWith, - updateProduct + deleteProductsStartsWith } from "../../../utils/products/productsUtils"; import { createShipping, diff --git a/cypress/integration/products/productsVariants.js b/cypress/integration/products/productsVariants.js index 4d4e2c0cb..2c8755fac 100644 --- a/cypress/integration/products/productsVariants.js +++ b/cypress/integration/products/productsVariants.js @@ -76,9 +76,14 @@ describe("Creating variants", () => { const price = 10; let createdProduct; - createProduct(attribute.id, name, productType.id, category.id) + createProduct({ + attributeId: attribute.id, + name, + productTypeId: productType.id, + categoryId: category.id + }) .then(resp => { - createdProduct = resp.body.data.productCreate.product; + createdProduct = resp; updateChannelInProduct({ productId: createdProduct.id, channelId: defaultChannel.id @@ -145,15 +150,15 @@ describe("Creating variants", () => { const variantsPrice = 10; let newChannel; let createdProduct; - createChannel(true, name, name, "PLN") + createChannel({ isActive: true, name, currencyCode: "PLN" }) .then(resp => { - newChannel = resp.body.data.channelCreate.channel; - productUtils.createProduct( - attribute.id, + newChannel = resp; + createProduct({ + attributeId: attribute.id, name, - productType.id, - category.id - ); + productTypeId: productType.id, + categoryId: category.id + }); }) .then(productResp => { createdProduct = productResp; diff --git a/cypress/integration/products/updatingProducts.js b/cypress/integration/products/updatingProducts.js index 360ed9207..dfa64ad81 100644 --- a/cypress/integration/products/updatingProducts.js +++ b/cypress/integration/products/updatingProducts.js @@ -1,5 +1,6 @@ import faker from "faker"; +import { createCategory } from "../../apiRequests/Category"; import { createCollection } from "../../apiRequests/Collections"; import { getProductDetails } from "../../apiRequests/storeFront/ProductDetails"; import { PRODUCT_DETAILS } from "../../elements/catalog/products/product-details"; @@ -11,7 +12,6 @@ import { getDefaultChannel } from "../../utils/channelsUtils"; import { deleteCollectionsStartsWith } from "../../utils/collectionsUtils"; import { expectCorrectProductInformation } from "../../utils/products/checkProductInfo"; import { - createCategory, createProductInChannel, createTypeAttributeAndCategoryForProduct, deleteProductsStartsWith diff --git a/cypress/steps/catalog/products/VariantsSteps.js b/cypress/steps/catalog/products/VariantsSteps.js index 2fcbc562e..d8fd2c168 100644 --- a/cypress/steps/catalog/products/VariantsSteps.js +++ b/cypress/steps/catalog/products/VariantsSteps.js @@ -8,8 +8,11 @@ import { selectChannelVariantInDetailsPage } from "../../channelsSteps"; import { fillUpPriceList } from "./priceList"; export function variantsShouldBeVisible({ name, price }) { - cy.contains(PRODUCT_DETAILS.variantRow, name).should("be.visible"); - cy.contains(PRODUCT_DETAILS.variantRow, price).should("be.visible"); + cy.contains(PRODUCT_DETAILS.variantRow, name) + .should("be.visible") + .find(PRODUCT_DETAILS.variantPrice) + .invoke("text") + .then(text => expect(text).to.includes(price)); } export function createFirstVariant({ sku, warehouseId, price, attribute }) { cy.get(PRODUCT_DETAILS.addVariantsButton).click(); @@ -17,6 +20,9 @@ export function createFirstVariant({ sku, warehouseId, price, attribute }) { .contains(attribute) .find(VARIANTS_SELECTORS.attributeCheckbox) .click() + .get(VARIANTS_SELECTORS.valueContainer) + .find(BUTTON_SELECTORS.checked) + .should("exist") .get(VARIANTS_SELECTORS.nextButton) .click(); fillUpPriceList(price); diff --git a/cypress/steps/draftOrderSteps.js b/cypress/steps/draftOrderSteps.js index bce9746a6..a8b98909c 100644 --- a/cypress/steps/draftOrderSteps.js +++ b/cypress/steps/draftOrderSteps.js @@ -3,37 +3,40 @@ import { DRAFT_ORDER_SELECTORS } from "../elements/orders/draft-order-selectors" import { SELECT_SHIPPING_METHOD_FORM } from "../elements/shipping/select-shipping-method-form"; export function finalizeDraftOrder(name) { - cy.get(DRAFT_ORDER_SELECTORS.addProducts) + return cy + .get(DRAFT_ORDER_SELECTORS.addProducts) .click() .get(ASSIGN_PRODUCTS_SELECTORS.searchInput) - .type(name); - cy.contains(ASSIGN_PRODUCTS_SELECTORS.tableRow, name) - .find(ASSIGN_PRODUCTS_SELECTORS.checkbox) - .click() - .get(ASSIGN_PRODUCTS_SELECTORS.submitButton) - .click() - .get(DRAFT_ORDER_SELECTORS.editCustomerButton) - .click() - .get(DRAFT_ORDER_SELECTORS.selectCustomer) - .type(name); - cy.contains(DRAFT_ORDER_SELECTORS.selectCustomerOption, name) - .click() - .get(DRAFT_ORDER_SELECTORS.addShippingCarrierLink) - .click() - .get(SELECT_SHIPPING_METHOD_FORM.selectShippingMethod) - .click() - .get(SELECT_SHIPPING_METHOD_FORM.shippingMethodOption) - .first() - .click(); - cy.addAliasToGraphRequest("OrderShippingMethodUpdate") - .get(SELECT_SHIPPING_METHOD_FORM.submitButton) - .click(); - cy.wait("@OrderShippingMethodUpdate"); - cy.getTextFromElement(DRAFT_ORDER_SELECTORS.pageHeader).as( - "draftOrderNumber" - ); - cy.addAliasToGraphRequest("OrderDraftFinalize"); - cy.get(DRAFT_ORDER_SELECTORS.finalizeButton).click(); - cy.wait("@OrderDraftFinalize"); - return cy.get("@draftOrderNumber"); + .type(name) + .then(() => { + cy.contains(ASSIGN_PRODUCTS_SELECTORS.tableRow, name) + .find(ASSIGN_PRODUCTS_SELECTORS.checkbox) + .click() + .get(ASSIGN_PRODUCTS_SELECTORS.submitButton) + .click() + .get(DRAFT_ORDER_SELECTORS.editCustomerButton) + .click() + .get(DRAFT_ORDER_SELECTORS.selectCustomer) + .type(name); + cy.contains(DRAFT_ORDER_SELECTORS.selectCustomerOption, name) + .click() + .get(DRAFT_ORDER_SELECTORS.addShippingCarrierLink) + .click() + .get(SELECT_SHIPPING_METHOD_FORM.selectShippingMethod) + .click() + .get(SELECT_SHIPPING_METHOD_FORM.shippingMethodOption) + .first() + .click(); + cy.addAliasToGraphRequest("OrderShippingMethodUpdate") + .get(SELECT_SHIPPING_METHOD_FORM.submitButton) + .click(); + cy.wait("@OrderShippingMethodUpdate"); + cy.getTextFromElement(DRAFT_ORDER_SELECTORS.pageHeader).as( + "draftOrderNumber" + ); + cy.addAliasToGraphRequest("OrderDraftFinalize"); + cy.get(DRAFT_ORDER_SELECTORS.finalizeButton).click(); + cy.wait("@OrderDraftFinalize"); + return cy.get("@draftOrderNumber"); + }); } diff --git a/cypress/utils/channelsUtils.js b/cypress/utils/channelsUtils.js index c9bf434aa..4590d3ef7 100644 --- a/cypress/utils/channelsUtils.js +++ b/cypress/utils/channelsUtils.js @@ -32,13 +32,3 @@ export function getDefaultChannel() { }); }); } -export function createChannel({ - isActive = true, - name, - slug = name, - currencyCode = "PLN" -}) { - return channels - .createChannel(isActive, name, slug, currencyCode) - .its("body.data.channelCreate.channel"); -} diff --git a/cypress/utils/ordersUtils.js b/cypress/utils/ordersUtils.js index ad47cf0de..4cd7676b9 100644 --- a/cypress/utils/ordersUtils.js +++ b/cypress/utils/ordersUtils.js @@ -11,14 +11,15 @@ export function createWaitingForCaptureOrder( let checkout; const auth = "token"; cy.loginInShop(); - return createCheckout({ channelSlug, email, variantsList, address, auth }) + return checkoutRequest + .createCheckout({ channelSlug, email, variantsList, address, auth }) .then(checkoutResp => { checkout = checkoutResp; checkoutRequest.addShippingMethod(checkout.id, shippingMethodId); }) .then(() => addPayment(checkout.id)) .then(() => checkoutRequest.completeCheckout(checkout.id)) - .then(() => checkout); + .then(order => ({ checkout, order })); } export function createCheckoutWithVoucher({ channelSlug, @@ -30,7 +31,8 @@ export function createCheckoutWithVoucher({ auth }) { let checkout; - return createCheckout({ channelSlug, email, variantsList, address, auth }) + return checkoutRequest + .createCheckout({ channelSlug, email, variantsList, address, auth }) .then(checkoutResp => { checkout = checkoutResp; checkoutRequest.addShippingMethod(checkout.id, shippingMethodId); @@ -48,7 +50,8 @@ export function createReadyToFulfillOrder( variantsList ) { let order; - return createDraftOrder(customerId, shippingMethodId, channelId) + return orderRequest + .createDraftOrder(customerId, shippingMethodId, channelId) .then(orderResp => { order = orderResp; assignVariantsToOrder(order, variantsList); @@ -64,7 +67,8 @@ export function createOrder({ variantsList }) { let order; - return createDraftOrder(customerId, shippingMethodId, channelId) + return orderRequest + .createDraftOrder(customerId, shippingMethodId, channelId) .then(orderResp => { order = orderResp; assignVariantsToOrder(order, variantsList); @@ -78,30 +82,6 @@ function assignVariantsToOrder(order, variantsList) { orderRequest.addProductToOrder(order.id, variantElement.id); }); } - -export function createDraftOrder(customerId, shippingMethodId, channelId) { - return orderRequest - .createDraftOrder(customerId, shippingMethodId, channelId) - .its("body.data.draftOrderCreate.order"); -} -export function createCheckout({ - channelSlug, - email, - variantsList, - address, - auth -}) { - return checkoutRequest - .createCheckout({ - channelSlug, - email, - productQuantity: 1, - variantsList, - address, - auth - }) - .its("body.data.checkoutCreate.checkout"); -} export function addPayment(checkoutId) { return checkoutRequest.addPayment( checkoutId, @@ -109,3 +89,20 @@ export function addPayment(checkoutId) { "not-charged" ); } +export function createAndCompleteCheckoutWithoutShipping({ + channelSlug, + email, + variantsList, + billingAddress, + auth +}) { + let checkout; + return checkoutRequest + .createCheckout({ channelSlug, email, variantsList, billingAddress, auth }) + .then(checkoutResp => { + checkout = checkoutResp; + addPayment(checkout.id); + }) + .then(() => checkoutRequest.completeCheckout(checkout.id)) + .then(order => ({ checkout, order })); +} diff --git a/cypress/utils/products/productsUtils.js b/cypress/utils/products/productsUtils.js index 6969d2e46..847f1aabe 100644 --- a/cypress/utils/products/productsUtils.js +++ b/cypress/utils/products/productsUtils.js @@ -18,15 +18,16 @@ export function createProductInChannel({ description = null }) { let product; - let variants; - return createProduct( - attributeId, - name, - productTypeId, - categoryId, - collectionId, - description - ) + let variantsList; + return productRequest + .createProduct({ + attributeId, + name, + productTypeId, + categoryId, + collectionId, + description + }) .then(productResp => { product = productResp; productRequest.updateChannelInProduct({ @@ -38,7 +39,7 @@ export function createProductInChannel({ }); }) .then(() => { - createVariant({ + productRequest.createVariant({ productId: product.id, sku: name, attributeId, @@ -49,8 +50,8 @@ export function createProductInChannel({ }); }) .then(variantsResp => { - variants = variantsResp; - return { product, variants }; + variantsList = variantsResp; + return { product, variantsList }; }); } @@ -61,81 +62,21 @@ export function createTypeAttributeAndCategoryForProduct( let attribute; let productType; let category; - return createAttribute(name, attributeValues) + return attributeRequest + .createAttribute(name, attributeValues) .then(attributeResp => { attribute = attributeResp; - createTypeProduct(name, attributeResp.id); + productRequest.createTypeProduct({ name, attributeId: attributeResp.id }); }) .then(productTypeResp => { productType = productTypeResp; - createCategory(name); + categoryRequest.createCategory(name); }) .then(categoryResp => { category = categoryResp; return { attribute, category, productType }; }); } -export function createAttribute(name, attributeValues) { - return attributeRequest - .createAttribute(name, attributeValues) - .its("body.data.attributeCreate.attribute"); -} -export function createTypeProduct(name, attributeId, hasVariants) { - return productRequest - .createTypeProduct(name, attributeId, hasVariants) - .its("body.data.productTypeCreate.productType"); -} -export function createCategory(name) { - return categoryRequest - .createCategory(name) - .its("body.data.categoryCreate.category"); -} -export function createProduct( - attributeId, - name, - productTypeId, - categoryId, - collectionId, - description -) { - return productRequest - .createProduct( - attributeId, - name, - productTypeId, - categoryId, - collectionId, - description - ) - .its("body.data.productCreate.product"); -} -export function updateProduct(productId, input) { - return productRequest - .updateProduct(productId, input) - .its("body.data.productUpdate.product"); -} -export function createVariant({ - productId, - sku, - attributeId, - warehouseId, - quantityInWarehouse, - channelId, - price -}) { - return productRequest - .createVariant({ - productId, - sku, - attributeId, - warehouseId, - quantity: quantityInWarehouse, - channelId, - price - }) - .its("body.data.productVariantBulkCreate.productVariants"); -} - export function deleteProductsStartsWith(startsWith) { cy.deleteElementsStartsWith( productRequest.deleteProductType, diff --git a/cypress/utils/shippingUtils.js b/cypress/utils/shippingUtils.js index 7608208b0..d49cd7b4f 100644 --- a/cypress/utils/shippingUtils.js +++ b/cypress/utils/shippingUtils.js @@ -6,10 +6,15 @@ export function createShipping({ channelId, name, address, price = 1 }) { let shippingZone; let warehouse; - return createShippingZone(name, address.country, channelId) + return shippingMethodRequest + .createShippingZone(name, address.country, channelId) .then(shippingZoneResp => { shippingZone = shippingZoneResp; - createWarehouse({ name, shippingZoneId: shippingZone.id, address }); + warehouseRequest.createWarehouse({ + name, + shippingZone: shippingZone.id, + address + }); }) .then(warehouseResp => { warehouse = warehouseResp; @@ -25,17 +30,6 @@ export function createShipping({ channelId, name, address, price = 1 }) { }) .then(() => ({ shippingMethod, shippingZone, warehouse })); } - -export function createShippingZone(name, country, channelId) { - return shippingMethodRequest - .createShippingZone(name, country, channelId) - .its("body.data.shippingZoneCreate.shippingZone"); -} -export function createWarehouse({ name, shippingZoneId, address }) { - return warehouseRequest - .createWarehouse({ name, shippingZone: shippingZoneId, address }) - .its("body.data.createWarehouse.warehouse"); -} export function createShippingRate(name, shippingZoneId) { return shippingMethodRequest .createShippingRate(name, shippingZoneId)