diff --git a/.github/workflows/critical-tests.yml b/.github/workflows/critical-tests.yml new file mode 100644 index 000000000..ae976a587 --- /dev/null +++ b/.github/workflows/critical-tests.yml @@ -0,0 +1,67 @@ +name: RUN_CRITICAL_TESTS + +# Only trigger, when the build workflow succeeded +on: + workflow_run: + workflows: [TEST-ENV-DEPLOYMENT] + types: [completed] + +jobs: + cypress-run-critical: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v1 + + - name: Get API_URI + id: api_uri + # Search for API_URI in PR description and use default if not defined + env: + pull_request_body: ${{ github.event.pull_request.body }} + prefix: API_URI= + pattern: (http|https)://[a-zA-Z0-9.-]+/graphql/? + fallback_uri: ${{ secrets.CYPRESS_API_URI }} + run: | + echo "::set-output name=custom_api_uri::$(echo $pull_request_body | grep -Eo "$prefix$pattern" | sed s/$prefix// | head -n 1 | { read custom_uri; if [ -z "$custom_uri" ]; then echo "$fallback_uri"; else echo "$custom_uri"; fi })" + - name: Get base_URL + id: base_URL + run: | + echo "::set-output name=base_URL::https://$(echo ${GITHUB_HEAD_REF}).dashboard.saleor.rocks" + - name: Setup Node + uses: actions/setup-node@v1 + with: + node-version: 14 + + - name: Cache node modules + uses: actions/cache@v2 + env: + cache-name: cache-node-modules + with: + path: ~/.npm + key: ${{ runner.os }}-qa-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-qa-${{ env.cache-name }}- + ${{ runner.os }}-qa- + ${{ runner.os }}- + + - name: Install Dependencies + if: steps.cache-node-modules.outputs.cache-hit != 'true' + run: npm install + + - name: Cypress run critical + uses: cypress-io/github-action@v2 + env: + API_URI: ${{ steps.api_uri.outputs.custom_api_uri }} + APP_MOUNT_URI: ${{ secrets.APP_MOUNT_URI }} + CYPRESS_baseUrl: ${{ steps.base_URL.outputs.base_URL }} + CYPRESS_USER_NAME: ${{ secrets.CYPRESS_USER_NAME }} + CYPRESS_SECOND_USER_NAME: ${{ secrets.CYPRESS_SECOND_USER_NAME }} + CYPRESS_USER_PASSWORD: ${{ secrets.CYPRESS_USER_PASSWORD }} + CYPRESS_PERMISSIONS_USERS_PASSWORD: ${{ secrets.CYPRESS_PERMISSIONS_USERS_PASSWORD }} + with: + command: npm run cy:run:critical + wait-on: ${{ steps.base_URL.outputs.base_URL }} + - uses: actions/upload-artifact@v1 + with: + name: cypress-videos + path: cypress/videos \ No newline at end of file diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 90516815c..aaef1f3d7 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -69,45 +69,4 @@ jobs: if: ${{ failure() }} with: name: cypress-videos - path: cypress/videos - - cypress-run-critical: - if: github.event.pull_request.head.repo.full_name == 'saleor/saleor-dashboard' && ((github.event.label.name != 'run e2e') || !(contains(github.event.pull_request.labels.*.name, 'run e2e'))) - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v1 - - - name: Get API_URI - id: api_uri - # Search for CYPRESS_API_URI in PR description and use default if not defined - env: - pull_request_body: ${{ github.event.pull_request.body }} - prefix: CYPRESS_API_URI= - pattern: (http|https)://[a-zA-Z0-9.-]+/graphql/? - fallback_uri: ${{ secrets.CYPRESS_API_URI }} - run: | - echo "::set-output name=custom_api_uri::$(echo $pull_request_body | grep -Eo "$prefix$pattern" | sed s/$prefix// | head -n 1 | { read custom_uri; if [ -z "$custom_uri" ]; then echo "$fallback_uri"; else echo "$custom_uri"; fi })" - - - name: Cypress run critical - if: ${{ steps.api_uri.outputs.custom_api_uri != 'https://qa.staging.saleor.cloud/graphql/' }} - uses: cypress-io/github-action@v2 - env: - API_URI: ${{ steps.api_uri.outputs.custom_api_uri }} - APP_MOUNT_URI: ${{ secrets.APP_MOUNT_URI }} - CYPRESS_baseUrl: ${{ secrets.CYPRESS_BASEURL }} - CYPRESS_USER_NAME: ${{ secrets.CYPRESS_USER_NAME }} - CYPRESS_SECOND_USER_NAME: ${{ secrets.CYPRESS_SECOND_USER_NAME }} - CYPRESS_USER_PASSWORD: ${{ secrets.CYPRESS_USER_PASSWORD }} - CYPRESS_PERMISSIONS_USERS_PASSWORD: ${{ secrets.CYPRESS_PERMISSIONS_USERS_PASSWORD }} - with: - build: npm run build - start: npx local-web-server --spa index.html - wait-on: http://localhost:9000/ - wait-on-timeout: 120 - command: npm run cy:run:critical - - uses: actions/upload-artifact@v1 - if: ${{ failure() }} - with: - name: cypress-videos - path: cypress/videos + path: cypress/videos \ No newline at end of file diff --git a/cypress.json b/cypress.json index add66683b..ac36119b8 100644 --- a/cypress.json +++ b/cypress.json @@ -6,5 +6,6 @@ "defaultCommandTimeout": 15000, "requestTimeout": 15000, "viewportWidth": 1400, - "viewportHeight": 660 + "viewportHeight": 660, + "videos": false } \ No newline at end of file diff --git a/cypress/fixtures/permissionsUsers.js b/cypress/fixtures/permissionsUsers.js index 22105318b..bece4f5d1 100644 --- a/cypress/fixtures/permissionsUsers.js +++ b/cypress/fixtures/permissionsUsers.js @@ -4,65 +4,81 @@ import { ONE_PERMISSION_USERS, TEST_ADMIN_USER } from "./users"; export const PERMISSIONS_OPTIONS = { all: { user: TEST_ADMIN_USER, - permissions: Object.values(PERMISSIONS) + permissions: Object.values(PERMISSIONS), + testCase: "TC: SALEOR_3401" }, app: { user: ONE_PERMISSION_USERS.app, - permissions: [PERMISSIONS.app] + permissions: [PERMISSIONS.app], + testCase: "TC: SALEOR_3402" }, channel: { user: ONE_PERMISSION_USERS.channel, - permissions: [PERMISSIONS.channel] + permissions: [PERMISSIONS.channel], + testCase: "TC: SALEOR_3403" }, customer: { user: ONE_PERMISSION_USERS.user, - permissions: [PERMISSIONS.customer] + permissions: [PERMISSIONS.customer], + testCase: "TC: SALEOR_3404" }, discount: { user: ONE_PERMISSION_USERS.discount, - permissions: [PERMISSIONS.discounts] + permissions: [PERMISSIONS.discounts], + testCase: "TC: SALEOR_3405" }, giftCard: { - user: ONE_PERMISSION_USERS.giftCard + user: ONE_PERMISSION_USERS.giftCard, + testCase: "TC: SALEOR_3406" }, order: { user: ONE_PERMISSION_USERS.order, - permissions: [PERMISSIONS.order] + permissions: [PERMISSIONS.order], + testCase: "TC: SALEOR_3407" }, page: { user: ONE_PERMISSION_USERS.page, - permissions: [PERMISSIONS.page] + permissions: [PERMISSIONS.page], + testCase: "TC: SALEOR_3408" }, plugin: { user: ONE_PERMISSION_USERS.plugin, - permissions: [PERMISSIONS.plugin] + permissions: [PERMISSIONS.plugin], + testCase: "TC: SALEOR_3409" }, product: { user: ONE_PERMISSION_USERS.product, - permissions: [PERMISSIONS.product, PERMISSIONS.warehouse] + permissions: [PERMISSIONS.product, PERMISSIONS.warehouse], + testCase: "TC: SALEOR_3410" }, productTypeAndAttribute: { user: ONE_PERMISSION_USERS.productTypeAndAttribute, - permissions: [PERMISSIONS.productTypeAndAttribute] + permissions: [PERMISSIONS.productTypeAndAttribute], + testCase: "TC: SALEOR_3411" }, pageTypeAndAttribute: { user: ONE_PERMISSION_USERS.pageTypeAndAttribute, - permissions: [PERMISSIONS.pageTypeAndAttribute] + permissions: [PERMISSIONS.pageTypeAndAttribute], + testCase: "TC: SALEOR_3412" }, settings: { user: ONE_PERMISSION_USERS.settings, - permissions: [PERMISSIONS.settings] + permissions: [PERMISSIONS.settings], + testCase: "TC: SALEOR_3413" }, shipping: { user: ONE_PERMISSION_USERS.shipping, - permissions: [PERMISSIONS.shipping] + permissions: [PERMISSIONS.shipping], + testCase: "TC: SALEOR_3415" }, staff: { user: ONE_PERMISSION_USERS.staff, - permissions: [PERMISSIONS.staff] + permissions: [PERMISSIONS.staff], + testCase: "TC: SALEOR_3414" }, translations: { user: ONE_PERMISSION_USERS.translations, - permissions: [PERMISSIONS.translations] + permissions: [PERMISSIONS.translations], + testCase: "TC: SALEOR_3416" } }; diff --git a/cypress/integration/checkout/purchaseWithProductTypes.js b/cypress/integration/checkout/purchaseWithProductTypes.js index 658bc80c7..a4c7a6e6b 100644 --- a/cypress/integration/checkout/purchaseWithProductTypes.js +++ b/cypress/integration/checkout/purchaseWithProductTypes.js @@ -3,21 +3,13 @@ import faker from "faker"; -import { createAttribute } from "../../support/api/requests/Attribute"; -import { createCategory } from "../../support/api/requests/Category"; import { checkoutShippingAddressUpdate, - checkoutShippingMethodUpdate, checkoutVariantsUpdate, completeCheckout, createCheckout } from "../../support/api/requests/Checkout"; import { getOrder } from "../../support/api/requests/Order"; -import { - createDigitalContent, - createTypeProduct -} from "../../support/api/requests/ProductType"; -import { getDefaultChannel } from "../../support/api/utils/channelsUtils"; import { addPayment, createAndCompleteCheckoutWithoutShipping, @@ -25,110 +17,46 @@ import { getShippingMethodIdFromCheckout, updateShippingInCheckout } from "../../support/api/utils/ordersUtils"; -import { - addDigitalContentAndUpdateProductType, - createProductInChannel, - deleteProductsStartsWith -} from "../../support/api/utils/products/productsUtils"; -import { - createShipping, - deleteShippingStartsWith -} from "../../support/api/utils/shippingUtils"; +import { createDigitalAndPhysicalProductWithNewDataAndDefaultChannel } from "../../support/api/utils/products/productsUtils"; import filterTests from "../../support/filterTests"; -filterTests({ definedTags: ["all", "critical"] }, () => { - describe("Purchase products with all products types", () => { +filterTests({ definedTags: ["all", "critical", "refactored"] }, () => { + describe("As an unlogged customer I want to order physical and digital products", () => { const startsWith = `CyPurchaseByType`; - const name = `${startsWith}${faker.datatype.number()}`; const email = `${startsWith}@example.com`; const testsMessage = "Check order status"; + const digitalName = `${startsWith}${faker.datatype.number()}`; + const physicalName = `${startsWith}${faker.datatype.number()}`; const { softExpect } = chai; let defaultChannel; let address; - let warehouse; - let attribute; - let category; let shippingMethod; - let createProductData; + let digitalVariants; + let physicalVariants; 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; - }); + createDigitalAndPhysicalProductWithNewDataAndDefaultChannel({ + physicalProductName: physicalName, + digitalProductName: digitalName + }).then(resp => { + defaultChannel = resp.defaultChannel; + address = resp.address; + shippingMethod = resp.shippingMethod; + digitalVariants = resp.digitalVariants; + physicalVariants = resp.physicalVariants; + }); }); - 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()}`; - let variants; - - createTypeProduct({ - name: digitalName, - attributeId: attribute.id, - shippable: false + it("should purchase digital product as unlogged customer. TC: SALEOR_0402", () => { + createAndCompleteCheckoutWithoutShipping({ + channelSlug: defaultChannel.slug, + email, + billingAddress: address, + variantsList: digitalVariants, + auth: "token" }) - .then(productType => { - createProductData.name = digitalName; - createProductData.productTypeId = productType.id; - createProductInChannel(createProductData); - }) - .then(({ variantsList }) => { - variants = variantsList; - addDigitalContentAndUpdateProductType( - variants[0].id, - createProductData.productTypeId, - defaultChannel.id - ); - }) - .then(() => { - createAndCompleteCheckoutWithoutShipping({ - channelSlug: defaultChannel.slug, - email, - billingAddress: address, - variantsList: variants, - auth: "token" - }); - }) .then(({ order }) => { getOrder(order.id); }) @@ -141,27 +69,14 @@ filterTests({ definedTags: ["all", "critical"] }, () => { }); }); - it("should purchase physical product", () => { - const physicalName = `${startsWith}${faker.datatype.number()}`; - createTypeProduct({ - name: physicalName, - attributeId: attribute.id, - shippable: true + it("should purchase physical product as unlogged customer. TC: SALEOR_0403", () => { + createWaitingForCaptureOrder({ + channelSlug: defaultChannel.slug, + email, + variantsList: physicalVariants, + shippingMethodName: shippingMethod.name, + address }) - .then(productType => { - createProductData.name = physicalName; - createProductData.productTypeId = productType.id; - createProductInChannel(createProductData); - }) - .then(({ variantsList }) => { - createWaitingForCaptureOrder({ - channelSlug: defaultChannel.slug, - email, - variantsList, - shippingMethodName: shippingMethod.name, - address - }); - }) .then(({ order }) => { getOrder(order.id); }) @@ -174,52 +89,22 @@ filterTests({ definedTags: ["all", "critical"] }, () => { }); }); - it("should purchase multiple products with all product types", () => { - const physicalName = `${startsWith}${faker.datatype.number()}`; - const digitalName = `${startsWith}${faker.datatype.number()}`; - let digitalProductVariantsList; + it("should purchase multiple products with all product types as unlogged customer. TC: SALEOR_0404", () => { let checkout; - createTypeProduct({ - name: digitalName, - attributeId: attribute.id, - shippable: false + + createCheckout({ + channelSlug: defaultChannel.slug, + email, + variantsList: digitalVariants, + billingAddress: address, + auth: "token" }) - .then(productType => { - createProductData.name = digitalName; - createProductData.productTypeId = productType.id; - createProductInChannel(createProductData); - }) - .then(({ variantsList }) => { - digitalProductVariantsList = variantsList; - createDigitalContent(variantsList[0].id); - }) - .then(() => { - createCheckout({ - channelSlug: defaultChannel.slug, - email, - variantsList: digitalProductVariantsList, - billingAddress: address, - auth: "token" - }); - }) .then(({ checkout: 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); + checkoutVariantsUpdate(checkout.id, physicalVariants); }) .then(() => { const shippingMethodId = getShippingMethodIdFromCheckout( diff --git a/cypress/integration/checkout/stocksInCheckout.js b/cypress/integration/checkout/stocksInCheckout.js index 6619cd1cc..598948357 100644 --- a/cypress/integration/checkout/stocksInCheckout.js +++ b/cypress/integration/checkout/stocksInCheckout.js @@ -8,114 +8,70 @@ import { createCheckout } from "../../support/api/requests/Checkout"; import { getVariants } from "../../support/api/requests/Product"; -import { getDefaultChannel } from "../../support/api/utils/channelsUtils"; -import { createOrderWithNewProduct } from "../../support/api/utils/ordersUtils"; -import { - createProductInChannel, - createTypeAttributeAndCategoryForProduct, - deleteProductsStartsWith -} from "../../support/api/utils/products/productsUtils"; -import { - createShipping, - deleteShippingStartsWith -} from "../../support/api/utils/shippingUtils"; +import { createWaitingForCaptureOrder } from "../../support/api/utils/ordersUtils"; +import { createNewProductWithSeveralVariants } from "../../support/api/utils/products/productsUtils"; import filterTests from "../../support/filterTests"; -filterTests({ definedTags: ["all", "critical"] }, () => { - describe("Products stocks in checkout", () => { +filterTests({ definedTags: ["all", "critical", "refactored"] }, () => { + describe("Manage products stocks in checkout", () => { const startsWith = "CyStocksCheckout-"; const name = `${startsWith}${faker.datatype.number()}`; let defaultChannel; let address; - let warehouse; - let attribute; - let category; - let productType; let shippingMethod; + let variantsWithLowStock; + let variantsWithoutTrackInventory; + let lastVariantInStock; before(() => { cy.clearSessionData().loginUserViaRequest(); - deleteProductsStartsWith(startsWith); - deleteShippingStartsWith(startsWith); - cy.fixture("addresses") - .then(addresses => { - address = addresses.usAddress; - getDefaultChannel(); - }) - .then(channel => { - defaultChannel = channel; - createShipping({ - channelId: defaultChannel.id, - name, - address - }); - }) - .then( - ({ - warehouse: warehouseResp, - shippingMethod: shippingMethodResp - }) => { - warehouse = warehouseResp; - shippingMethod = shippingMethodResp; - createTypeAttributeAndCategoryForProduct({ name }); - } - ) - .then( - ({ - attribute: attributeResp, - category: categoryResp, - productType: productTypeResp - }) => { - attribute = attributeResp; - category = categoryResp; - productType = productTypeResp; - } - ); - }); - it("should create checkout with last product in stock", () => { - const productName = `${startsWith}${faker.datatype.number()}`; - createOrderWithNewProduct({ - attributeId: attribute.id, - categoryId: category.id, - productTypeId: productType.id, - channel: defaultChannel, - name: productName, - warehouseId: warehouse.id, - shippingMethod, - address - }).then(({ order }) => { - expect(order, "order should be created").to.be.ok; + const variantsData = [ + { + name: "variantsWithLowStock", + trackInventory: true, + quantityInWarehouse: 1 + }, + { + name: "variantsWithoutTrackInventory", + trackInventory: false, + quantityInWarehouse: 0 + }, + { + name: "lastVariantInStock", + trackInventory: true, + quantityInWarehouse: 1 + } + ]; + + createNewProductWithSeveralVariants(name, variantsData).then(resp => { + defaultChannel = resp.defaultChannel; + address = resp.address; + shippingMethod = resp.shippingMethod; + variantsWithLowStock = resp.createdVariants.find( + variant => variant.name === "variantsWithLowStock" + ); + variantsWithoutTrackInventory = resp.createdVariants.find( + variant => variant.name === "variantsWithoutTrackInventory" + ); + lastVariantInStock = resp.createdVariants.find( + variant => variant.name === "lastVariantInStock" + ); }); }); - it("should not be possible to add product with quantity greater than stock", () => { - const productName = `${startsWith}${faker.datatype.number()}`; - let variants; - - createProductInChannel({ - attributeId: attribute.id, - categoryId: category.id, - productTypeId: productType.id, - channelId: defaultChannel.id, - name: productName, - warehouseId: warehouse.id, - quantityInWarehouse: 1 + it("should not be possible to add product with quantity greater than stock to checkout. TC: SALEOR_0405", () => { + createCheckout({ + channelSlug: defaultChannel.slug, + address, + billingAddress: address, + email: "email@example.com", + variantsList: [variantsWithLowStock], + auth: "token" }) - .then(({ variantsList }) => { - variants = variantsList; - createCheckout({ - channelSlug: defaultChannel.slug, - address, - billingAddress: address, - email: "email@example.com", - variantsList, - auth: "token" - }); - }) .then(({ checkout: checkout }) => { - addProductsToCheckout(checkout.id, variants, 2); + addProductsToCheckout(checkout.id, [variantsWithLowStock], 2); }) .then(({ errors }) => { expect( @@ -125,46 +81,34 @@ filterTests({ definedTags: ["all", "critical"] }, () => { }); }); - it("should buy product with no quantity if tracking is not set", () => { - const productName = `${startsWith}${faker.datatype.number()}`; - - createOrderWithNewProduct({ - attributeId: attribute.id, - categoryId: category.id, - productTypeId: productType.id, - channel: defaultChannel, - name: productName, - warehouseId: warehouse.id, - quantityInWarehouse: 0, - trackInventory: false, - shippingMethod, - address + it("should buy product with no quantity if tracking is not set. TC: SALEOR_0406", () => { + createWaitingForCaptureOrder({ + address, + channelSlug: defaultChannel.slug, + email: "example@example.com", + shippingMethodName: shippingMethod.name, + variantsList: [variantsWithoutTrackInventory] }).then(({ order }) => { expect(order, "order should be created").to.be.ok; }); }); - it("should change product stock after purchase", () => { - const productName = `${startsWith}${faker.datatype.number()}`; - - createOrderWithNewProduct({ - attributeId: attribute.id, - categoryId: category.id, - productTypeId: productType.id, - channel: defaultChannel, - name: productName, - warehouseId: warehouse.id, - quantityInWarehouse: 10, - trackInventory: true, - shippingMethod, - address + it("should create checkout with last product in stock. TC: SALEOR_0419", () => { + createWaitingForCaptureOrder({ + address, + channelSlug: defaultChannel.slug, + email: "example@example.com", + shippingMethodName: shippingMethod.name, + variantsList: [lastVariantInStock] }) - .then(({ variantsList }) => { - getVariants(variantsList); + .then(({ order }) => { + expect(order, "order should be created").to.be.ok; + getVariants([lastVariantInStock]); }) .then(variantsList => { const variant = variantsList.edges[0]; expect(variant.node.stocks[0].quantityAllocated).to.eq(1); + expect(variant.node.stocks[0].quantity).to.eq(1); }); }); }); diff --git a/cypress/integration/homePage/homePageAnalitics.js b/cypress/integration/homePage/homePageAnalitics.js index d53fbfd69..b7496af29 100644 --- a/cypress/integration/homePage/homePageAnalitics.js +++ b/cypress/integration/homePage/homePageAnalitics.js @@ -5,28 +5,32 @@ import faker from "faker"; import { HOMEPAGE_SELECTORS } from "../../elements/homePage/homePage-selectors"; import { urlList } from "../../fixtures/urlList"; -import { - createCustomer, - deleteCustomersStartsWith -} from "../../support/api/requests/Customer"; -import { getDefaultChannel } from "../../support/api/utils/channelsUtils"; +import { createCustomer } from "../../support/api/requests/Customer"; import * as homePageUtils from "../../support/api/utils/homePageUtils"; import { createReadyToFulfillOrder, createWaitingForCaptureOrder } from "../../support/api/utils/ordersUtils"; import * as productsUtils from "../../support/api/utils/products/productsUtils"; -import * as shippingUtils from "../../support/api/utils/shippingUtils"; import filterTests from "../../support/filterTests"; -import { changeChannel } from "../../support/pages/homePage"; +import { + changeChannel, + getOrdersReadyForCaptureRegex, + getOrdersReadyToFulfillRegex, + getProductsOutOfStockRegex, + getSalesAmountRegex, + getTodaysOrdersRegex +} from "../../support/pages/homePage"; -// - -filterTests({ definedTags: ["all", "critical"] }, () => { - describe("Homepage analytics", () => { +filterTests({ definedTags: ["all", "critical", "refactored"] }, () => { + describe("As an admin I want to see correct information on dashboard home page", () => { const startsWith = "CyHomeAnalytics"; + const productPrice = 22; + const shippingPrice = 12; + const randomName = startsWith + faker.datatype.number(); + const randomEmail = `${startsWith}${randomName}@example.com`; - let customerId; + let customer; let defaultChannel; let createdVariants; let productType; @@ -34,72 +38,108 @@ filterTests({ definedTags: ["all", "critical"] }, () => { let category; let warehouse; let shippingMethod; - let addresses; - - const productPrice = 22; - const shippingPrice = 12; - const randomName = startsWith + faker.datatype.number(); - const randomEmail = `${startsWith}${randomName}@example.com`; + let address; + let ordersReadyToFulfillRegexp; + let ordersReadyForCaptureRegexp; + let productsOutOfStockRegexp; + let salesAmountRegexp; + let ordersRegexp; before(() => { cy.clearSessionData().loginUserViaRequest(); - productsUtils.deleteProductsStartsWith(startsWith); - deleteCustomersStartsWith(startsWith); - shippingUtils.deleteShippingStartsWith(startsWith); - getDefaultChannel() - .then(channel => { - defaultChannel = channel; - cy.fixture("addresses"); + productsUtils + .createProductWithShipping({ + name: randomName, + productPrice, + shippingPrice }) - .then(addressesFixture => (addresses = addressesFixture)) - .then(() => - createCustomer(randomEmail, randomName, addresses.plAddress) - ) .then(resp => { - customerId = resp.user.id; - shippingUtils.createShipping({ - channelId: defaultChannel.id, - name: randomName, - address: addresses.plAddress, - price: shippingPrice - }); + createdVariants = resp.variantsList; + address = resp.address; + warehouse = resp.warehouse; + defaultChannel = resp.defaultChannel; + shippingMethod = resp.shippingMethod; + attribute = resp.attribute; + category = resp.category; + productType = resp.productType; + + createCustomer(randomEmail, randomName, address).then( + customerResp => (customer = customerResp) + ); + + homePageUtils + .getOrdersReadyToFulfill(defaultChannel.slug) + .then(ordersReadyToFulfillBefore => { + ordersReadyToFulfillRegexp = getOrdersReadyToFulfillRegex( + ordersReadyToFulfillBefore, + 1 + ); + }); + + homePageUtils + .getOrdersReadyForCapture(defaultChannel.slug) + .then(ordersReadyForCaptureBefore => { + ordersReadyForCaptureRegexp = getOrdersReadyForCaptureRegex( + ordersReadyForCaptureBefore, + 1 + ); + }); + + homePageUtils + .getProductsOutOfStock(defaultChannel.slug) + .then(productsOutOfStockBefore => { + productsOutOfStockRegexp = getProductsOutOfStockRegex( + productsOutOfStockBefore, + 1 + ); + }); + + homePageUtils + .getSalesAmount(defaultChannel.slug) + .then(salesAmount => { + salesAmountRegexp = getSalesAmountRegex( + salesAmount, + productPrice * 2 + shippingPrice + ); + }); + + homePageUtils + .getTodaysOrders(defaultChannel.slug) + .then(ordersBefore => { + ordersRegexp = getTodaysOrdersRegex(ordersBefore, 2); + }); }) - .then( - ({ - warehouse: warehouseResp, - shippingMethod: shippingMethodResp - }) => { - warehouse = warehouseResp; - shippingMethod = shippingMethodResp; - productsUtils.createTypeAttributeAndCategoryForProduct({ - name: randomName - }); - } - ) - .then( - ({ - productType: productTypeResp, - attribute: attributeResp, - category: categoryResp - }) => { - productType = productTypeResp; - attribute = attributeResp; - category = categoryResp; - productsUtils.createProductInChannel({ - name: randomName, - channelId: defaultChannel.id, - warehouseId: warehouse.id, - quantityInWarehouse: 20, - productTypeId: productType.id, - attributeId: attribute.id, - categoryId: category.id, - price: productPrice - }); - } - ) - .then(({ variantsList: variantsResp }) => { - createdVariants = variantsResp; + .then(() => { + createReadyToFulfillOrder({ + customerId: customer.id, + shippingMethodId: shippingMethod.id, + channelId: defaultChannel.id, + variantsList: createdVariants, + address + }); + + createWaitingForCaptureOrder({ + channelSlug: defaultChannel.slug, + email: randomEmail, + variantsList: createdVariants, + shippingMethodName: shippingMethod.name, + address + }); + + const productOutOfStockRandomName = + startsWith + faker.datatype.number(); + + productsUtils.createProductInChannel({ + name: productOutOfStockRandomName, + channelId: defaultChannel.id, + warehouseId: warehouse.id, + quantityInWarehouse: 0, + productTypeId: productType.id, + attributeId: attribute.id, + categoryId: category.id, + price: productPrice + }); }); }); @@ -107,161 +147,25 @@ filterTests({ definedTags: ["all", "critical"] }, () => { cy.clearSessionData().loginUserViaRequest(); }); - it("should all elements be visible on the dashboard", () => { - cy.visit(urlList.homePage) - .softAssertVisibility(HOMEPAGE_SELECTORS.sales) - .softAssertVisibility(HOMEPAGE_SELECTORS.orders) - .softAssertVisibility(HOMEPAGE_SELECTORS.activity) - .softAssertVisibility(HOMEPAGE_SELECTORS.topProducts) - .softAssertVisibility(HOMEPAGE_SELECTORS.ordersReadyToFulfill) - .softAssertVisibility(HOMEPAGE_SELECTORS.paymentsWaitingForCapture) - .softAssertVisibility(HOMEPAGE_SELECTORS.productsOutOfStock); - }); - - it("should correct amount of ready to fullfil orders be displayed", () => { - homePageUtils - .getOrdersReadyToFulfill(defaultChannel.slug) - .as("ordersReadyToFulfill"); - createReadyToFulfillOrder({ - customerId, - shippingMethodId: shippingMethod.id, - channelId: defaultChannel.id, - variantsList: createdVariants, - address: addresses.plAddress - }); - cy.get("@ordersReadyToFulfill").then(ordersReadyToFulfillBefore => { - const allOrdersReadyToFulfill = ordersReadyToFulfillBefore + 1; - const notANumberRegex = "\\D*"; - const ordersReadyToFulfillRegexp = new RegExp( - `${notANumberRegex}${allOrdersReadyToFulfill}${notANumberRegex}` - ); - cy.visit(urlList.homePage); - changeChannel(defaultChannel.name); - cy.contains( - HOMEPAGE_SELECTORS.ordersReadyToFulfill, - ordersReadyToFulfillRegexp - ).should("be.visible"); - }); - }); - - it("should correct amount of payments waiting for capture be displayed", () => { - homePageUtils - .getOrdersReadyForCapture(defaultChannel.slug) - .as("ordersReadyForCapture"); - - createWaitingForCaptureOrder({ - channelSlug: defaultChannel.slug, - email: randomEmail, - variantsList: createdVariants, - shippingMethodName: shippingMethod.name, - address: addresses.plAddress - }); - - cy.get("@ordersReadyForCapture").then(ordersReadyForCaptureBefore => { - const allOrdersReadyForCapture = ordersReadyForCaptureBefore + 1; - const notANumberRegex = "\\D*"; - const ordersReadyForCaptureRegexp = new RegExp( - `${notANumberRegex}${allOrdersReadyForCapture}${notANumberRegex}` - ); - cy.visit(urlList.homePage); - changeChannel(defaultChannel.name); - cy.contains( - HOMEPAGE_SELECTORS.ordersReadyForCapture, - ordersReadyForCaptureRegexp - ).should("be.visible"); - }); - }); - - it("should correct amount of products out of stock be displayed", () => { - homePageUtils - .getProductsOutOfStock(defaultChannel.slug) - .as("productsOutOfStock"); - const productOutOfStockRandomName = startsWith + faker.datatype.number(); - - productsUtils.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; - const notANumberRegex = "\\D*"; - const productsOutOfStockRegexp = new RegExp( - `${notANumberRegex}${allProductsOutOfStock}${notANumberRegex}` - ); - cy.visit(urlList.homePage); - changeChannel(defaultChannel.name); - cy.contains( - HOMEPAGE_SELECTORS.productsOutOfStock, - productsOutOfStockRegexp - ).should("be.visible"); - }); - }); - - it("should correct amount of sales be displayed", () => { - homePageUtils.getSalesAmount(defaultChannel.slug).as("salesAmount"); - - createReadyToFulfillOrder({ - customerId, - shippingMethodId: shippingMethod.id, - channelId: defaultChannel.id, - variantsList: createdVariants, - address: addresses.plAddress - }); - - cy.get("@salesAmount").then(salesAmount => { - const totalAmount = salesAmount + productPrice; - const totalAmountString = totalAmount.toFixed(2); - const totalAmountIntegerValue = totalAmountString.split(".")[0]; - const totalAmountDecimalValue = totalAmountString.split(".")[1]; - const decimalSeparator = "[,.]"; - const totalAmountIntegerWithThousandsSeparator = new Intl.NumberFormat( - "en" - ) - .format(totalAmountIntegerValue) - .replaceAll(",", "[,.]*"); - const totalAmountWithSeparators = `${totalAmountIntegerWithThousandsSeparator}${decimalSeparator}${totalAmountDecimalValue}`; - const notANumberRegex = "\\D*"; - const salesAmountRegexp = new RegExp( - `${notANumberRegex}${totalAmountWithSeparators}${notANumberRegex}` - ); - cy.visit(urlList.homePage); - changeChannel(defaultChannel.name); - cy.contains(HOMEPAGE_SELECTORS.sales, salesAmountRegexp).should( - "be.visible" - ); - }); - }); - - it("should correct amount of orders be displayed", () => { - homePageUtils.getTodaysOrders(defaultChannel.slug).as("todaysOrders"); - - createReadyToFulfillOrder({ - customerId, - shippingMethodId: shippingMethod.id, - channelId: defaultChannel.id, - variantsList: createdVariants, - address: addresses.plAddress - }); - - cy.get("@todaysOrders").then(ordersBefore => { - const allOrders = ordersBefore + 1; - const notANumberRegex = "\\D*"; - const ordersRegexp = new RegExp( - `${notANumberRegex}${allOrders}${notANumberRegex}` - ); - cy.visit(urlList.homePage); - changeChannel(defaultChannel.name); - cy.contains(HOMEPAGE_SELECTORS.orders, ordersRegexp).should( - "be.visible" - ); - }); + it("should display correct information on dashboard home page. SALEOR_2004", () => { + cy.visit(urlList.homePage); + changeChannel(defaultChannel.name); + cy.contains(HOMEPAGE_SELECTORS.orders, ordersRegexp).should("be.visible"); + cy.contains( + HOMEPAGE_SELECTORS.ordersReadyToFulfill, + ordersReadyToFulfillRegexp + ).should("be.visible"); + cy.contains( + HOMEPAGE_SELECTORS.ordersReadyForCapture, + ordersReadyForCaptureRegexp + ).should("be.visible"); + cy.contains(HOMEPAGE_SELECTORS.sales, salesAmountRegexp).should( + "be.visible" + ); + cy.contains( + HOMEPAGE_SELECTORS.productsOutOfStock, + productsOutOfStockRegexp + ).should("be.visible"); }); }); }); diff --git a/cypress/integration/navigation.js b/cypress/integration/navigation.js index d0386cd30..e22d8913c 100644 --- a/cypress/integration/navigation.js +++ b/cypress/integration/navigation.js @@ -5,11 +5,12 @@ import { PERMISSIONS_OPTIONS } from "../fixtures/permissionsUsers"; import filterTests from "../support/filterTests"; import * as permissionsSteps from "../support/pages/permissionsPage"; -describe("Navigation for users with different permissions", () => { +describe("As a staff user I want to navigate through shop using different permissions", () => { Object.keys(PERMISSIONS_OPTIONS).forEach(key => { - const tags = key === "all" ? ["critical", "all"] : ["all"]; + const tags = + key === "all" ? ["critical", "all", "refactored"] : ["all", "refactored"]; filterTests({ definedTags: tags }, () => { - it(`should navigate as an user with ${key} permission`, () => { + it(`should be able to navigate through shop as a staff member using ${key} permission. ${PERMISSIONS_OPTIONS[key].testCase}`, () => { const permissionOption = PERMISSIONS_OPTIONS[key]; const permissions = permissionOption.permissions; cy.clearSessionData(); diff --git a/cypress/integration/products/createProduct.js b/cypress/integration/products/createProduct.js index da1e25e54..6048a195c 100644 --- a/cypress/integration/products/createProduct.js +++ b/cypress/integration/products/createProduct.js @@ -14,7 +14,6 @@ import { expectCorrectProductInformation, expectCorrectProductVariantInformation } from "../../support/api/utils/products/checkProductInfo"; -import * as productUtils from "../../support/api/utils/products/productsUtils"; import filterTests from "../../support/filterTests"; import { metadataForms } from "../../support/pages/catalog/metadataComponent"; import { @@ -25,7 +24,7 @@ import { fillUpCommonFieldsForAllProductTypes } from "../../support/pages/catalo import { selectChannelInDetailsPages } from "../../support/pages/channelsPage"; filterTests({ definedTags: ["all", "critical"] }, () => { - describe("Create product", () => { + describe("As an admin I should be able to create product", () => { const startsWith = "CyCreateProduct-"; const name = `${startsWith}${faker.datatype.number()}`; const generalInfo = { @@ -53,7 +52,6 @@ filterTests({ definedTags: ["all", "critical"] }, () => { before(() => { cy.clearSessionData().loginUserViaRequest(); - productUtils.deleteProductsStartsWith(startsWith); createAttribute({ name }).then(attributeResp => { attribute = attributeResp; }); @@ -62,7 +60,7 @@ filterTests({ definedTags: ["all", "critical"] }, () => { cy.clearSessionData().loginUserViaRequest(); }); - it("should create product with variants", () => { + it("should be able to create product with variants as an admin. SALEOR_2701", () => { const randomName = `${startsWith}${faker.datatype.number()}`; seo.slug = randomName; const productData = { @@ -89,7 +87,7 @@ filterTests({ definedTags: ["all", "critical"] }, () => { }); }); - it("should create product without variants", () => { + it("should be able to create product without variants as an admin. SALEOR_2702", () => { const prices = { sellingPrice: 6, costPrice: 3 }; const randomName = `${startsWith}${faker.datatype.number()}`; seo.slug = randomName; diff --git a/cypress/integration/products/images.js b/cypress/integration/products/images.js index a58b112e3..7f6369f55 100644 --- a/cypress/integration/products/images.js +++ b/cypress/integration/products/images.js @@ -7,7 +7,7 @@ import { SHARED_ELEMENTS } from "../../elements/shared/sharedElements"; import { demoProductsNames } from "../../fixtures/products"; import { productDetailsUrl, urlList } from "../../fixtures/urlList"; import { getFirstProducts } from "../../support/api/requests/Product"; -import { deleteProductsAndCreateNewOneWithNewDataAndDefaultChannel } from "../../support/api/utils/products/productsUtils"; +import { createNewProductWithNewDataAndDefaultChannel } from "../../support/api/utils/products/productsUtils"; import filterTests from "../../support/filterTests"; filterTests({ definedTags: ["all"] }, () => { @@ -71,7 +71,7 @@ filterTests({ definedTags: ["all"] }, () => { const name = "CyImages"; cy.clearSessionData().loginUserViaRequest(); - deleteProductsAndCreateNewOneWithNewDataAndDefaultChannel({ name }) + createNewProductWithNewDataAndDefaultChannel({ name }) .then(({ product }) => { cy.visit(productDetailsUrl(product.id)) .waitForProgressBarToNotBeVisible() diff --git a/cypress/integration/products/productsVariants.js b/cypress/integration/products/productsVariants.js index 55501971a..97aa3f09e 100644 --- a/cypress/integration/products/productsVariants.js +++ b/cypress/integration/products/productsVariants.js @@ -10,10 +10,7 @@ import { createProduct, updateChannelInProduct } from "../../support/api/requests/Product"; -import { - deleteChannelsStartsWith, - getDefaultChannel -} from "../../support/api/utils/channelsUtils"; +import { getDefaultChannel } from "../../support/api/utils/channelsUtils"; import * as productUtils from "../../support/api/utils/products/productsUtils"; import * as shippingUtils from "../../support/api/utils/shippingUtils"; import { getProductVariants } from "../../support/api/utils/storeFront/storeFrontProductUtils"; @@ -23,10 +20,13 @@ import { createVariant, variantsShouldBeVisible } from "../../support/pages/catalog/products/VariantsPage"; -import { enterHomePageChangeChannelAndReturn } from "../../support/pages/channelsPage"; +import { + enterHomePageChangeChannelAndReturn, + selectChannelInHeader +} from "../../support/pages/channelsPage"; -filterTests({ definedTags: ["all", "critical"] }, () => { - describe("Creating variants", () => { +filterTests({ definedTags: ["all", "critical", "refactored"] }, () => { + describe("As an admin I should be able to create variant", () => { const startsWith = "CyCreateVariants-"; const attributeValues = ["value1", "value2"]; @@ -38,43 +38,22 @@ filterTests({ definedTags: ["all", "critical"] }, () => { let newChannel; before(() => { - cy.clearSessionData().loginUserViaRequest(); - shippingUtils.deleteShippingStartsWith(startsWith); - productUtils.deleteProductsStartsWith(startsWith); - deleteChannelsStartsWith(startsWith); - const name = `${startsWith}${faker.datatype.number()}`; - getDefaultChannel() - .then(channel => { - defaultChannel = channel; - cy.fixture("addresses"); - }) - .then(fixtureAddresses => - shippingUtils.createShipping({ - channelId: defaultChannel.id, - name, - address: fixtureAddresses.plAddress - }) - ) - .then(({ warehouse: warehouseResp }) => { - warehouse = warehouseResp; + + cy.clearSessionData().loginUserViaRequest(); + + productUtils + .createShippingProductTypeAttributeAndCategory(name, attributeValues) + .then(resp => { + attribute = resp.attribute; + productType = resp.productType; + category = resp.category; + defaultChannel = resp.defaultChannel; + warehouse = resp.warehouse; + createChannel({ isActive: true, name, currencyCode: "USD" }); }) .then(resp => (newChannel = resp)); - - productUtils - .createTypeAttributeAndCategoryForProduct({ name, attributeValues }) - .then( - ({ - attribute: attributeResp, - productType: productTypeResp, - category: categoryResp - }) => { - attribute = attributeResp; - productType = productTypeResp; - category = categoryResp; - } - ); }); beforeEach(() => { @@ -84,7 +63,7 @@ filterTests({ definedTags: ["all", "critical"] }, () => { ); }); - it("should create variant visible on frontend", () => { + it("should be able to create variant visible for the customers in all channels. TC: SALEOR_2901", () => { const name = `${startsWith}${faker.datatype.number()}`; const price = 10; let createdProduct; @@ -101,6 +80,10 @@ filterTests({ definedTags: ["all", "critical"] }, () => { productId: createdProduct.id, channelId: defaultChannel.id }); + updateChannelInProduct({ + productId: createdProduct.id, + channelId: newChannel.id + }); cy.visit(`${urlList.products}${createdProduct.id}`); createFirstVariant({ sku: name, @@ -111,13 +94,25 @@ filterTests({ definedTags: ["all", "critical"] }, () => { variantsShouldBeVisible({ name, price }); getProductVariants(createdProduct.id, defaultChannel.slug); }) + .then(([variant]) => { + expect(variant).to.have.property("name", attributeValues[0]); + expect(variant).to.have.property("price", price); + selectChannelInHeader(newChannel.name); + variantsShouldBeVisible({ name, price }); + getProductVariants(createdProduct.id, defaultChannel.slug); + }) + .then(([variant]) => { + expect(variant).to.have.property("name", attributeValues[0]); + expect(variant).to.have.property("price", price); + getProductVariants(createdProduct.id, newChannel.slug); + }) .then(([variant]) => { expect(variant).to.have.property("name", attributeValues[0]); expect(variant).to.have.property("price", price); }); }); - it("should create several variants", () => { + it("should be able to create several variants visible for the customers. TC: SALEOR_2902", () => { const name = `${startsWith}${faker.datatype.number()}`; const secondVariantSku = `${startsWith}${faker.datatype.number()}`; const variants = [{ price: 7 }, { name: attributeValues[1], price: 16 }]; @@ -157,52 +152,5 @@ filterTests({ definedTags: ["all", "critical"] }, () => { expect(secondVariant).to.have.property("price", variants[1].price); }); }); - - it("should create variant for many channels", () => { - const name = `${startsWith}${faker.datatype.number()}`; - const variantsPrice = 10; - let createdProduct; - createProduct({ - attributeId: attribute.id, - name, - productTypeId: productType.id, - categoryId: category.id - }) - .then(productResp => { - createdProduct = productResp; - updateChannelInProduct({ - productId: createdProduct.id, - channelId: defaultChannel.id - }); - }) - .then(() => { - updateChannelInProduct({ - productId: createdProduct.id, - channelId: newChannel.id - }); - }) - .then(() => { - cy.visit(`${urlList.products}${createdProduct.id}`); - createFirstVariant({ - sku: name, - price: variantsPrice, - attribute: attributeValues[0] - }); - enterHomePageChangeChannelAndReturn(defaultChannel.name); - variantsShouldBeVisible({ name, price: variantsPrice }); - enterHomePageChangeChannelAndReturn(newChannel.name); - variantsShouldBeVisible({ name, price: variantsPrice }); - getProductVariants(createdProduct.id, defaultChannel.slug); - }) - .then(([variant]) => { - expect(variant).to.have.property("name", attributeValues[0]); - expect(variant).to.have.property("price", variantsPrice); - getProductVariants(createdProduct.id, newChannel.slug); - }) - .then(([variant]) => { - expect(variant).to.have.property("name", attributeValues[0]); - expect(variant).to.have.property("price", variantsPrice); - }); - }); }); }); diff --git a/cypress/integration/products/productsWithoutSku/productsWithoutSkuInOrder.js b/cypress/integration/products/productsWithoutSku/productsWithoutSkuInOrder.js index 864c46d8f..0677281c6 100644 --- a/cypress/integration/products/productsWithoutSku/productsWithoutSkuInOrder.js +++ b/cypress/integration/products/productsWithoutSku/productsWithoutSkuInOrder.js @@ -1,30 +1,18 @@ /// /// -import { - createCustomer, - deleteCustomersStartsWith -} from "../../../support/api/requests/Customer"; +import faker from "faker"; + +import { createCustomer } from "../../../support/api/requests/Customer"; import { createReadyToFulfillOrder } from "../../../support/api/utils/ordersUtils"; -import { - createProductWithShipping, - deleteProductsStartsWith -} from "../../../support/api/utils/products/productsUtils"; -import { deleteShippingStartsWith } from "../../../support/api/utils/shippingUtils"; +import { createProductWithShipping } from "../../../support/api/utils/products/productsUtils"; import filterTests from "../../../support/filterTests"; -filterTests({ definedTags: ["all", "critical"] }, () => { - const name = "ProductsWithoutSkuInOrder"; +filterTests({ definedTags: ["all", "critical", "refactored"] }, () => { + const name = `ProductsWithoutSkuInOrder${faker.datatype.number()}`; - describe("Add productWithout SKU to order", () => { - before(() => { - cy.clearSessionData().loginUserViaRequest(); - deleteProductsStartsWith(name); - deleteShippingStartsWith(name); - deleteCustomersStartsWith(name); - }); - - it("should create order with variant product without sku", () => { + describe("As an admin I should be able to create order with variant without SKU", () => { + it("should create order with variant product without sku. SALEOR_2801", () => { let variants; let channel; let shippingMethodId; diff --git a/cypress/plugins/index.js b/cypress/plugins/index.js index 49f524f12..051aa1547 100644 --- a/cypress/plugins/index.js +++ b/cypress/plugins/index.js @@ -22,7 +22,7 @@ const graphql = require("graphql-request"); module.exports = async (on, config) => { // make env variables visible for cypress - require("cypress-mochawesome-reporter/plugin")(on); + // require("cypress-mochawesome-reporter/plugin")(on); - uncomment to run reports config.env.API_URI = process.env.API_URI; config.env.APP_MOUNT_URI = process.env.APP_MOUNT_URI; config.env.mailHogUrl = process.env.CYPRESS_MAILHOG; diff --git a/cypress/support/api/requests/Product.js b/cypress/support/api/requests/Product.js index 591671e68..8c833fc79 100644 --- a/cypress/support/api/requests/Product.js +++ b/cypress/support/api/requests/Product.js @@ -148,7 +148,7 @@ export function createVariant({ productId, sku, warehouseId, - quantityInWarehouse, + quantityInWarehouse = 1, channelId, attributeId, price = 1, diff --git a/cypress/support/api/utils/products/productsUtils.js b/cypress/support/api/utils/products/productsUtils.js index e68ec18c9..9ac23f1d9 100644 --- a/cypress/support/api/utils/products/productsUtils.js +++ b/cypress/support/api/utils/products/productsUtils.js @@ -12,9 +12,11 @@ import { setProductTypeAsDigital } from "../../requests/ProductType"; import { deleteAttributesStartsWith } from "../attributes/attributeUtils"; -import { deleteCollectionsStartsWith } from "../catalog/collectionsUtils"; import { getDefaultChannel } from "../channelsUtils"; -import { createShipping, deleteShippingStartsWith } from "../shippingUtils"; +import { + createShipping, + createShippingWithDefaultChannelAndAddress +} from "../shippingUtils"; export function createProductInChannel({ name, @@ -116,7 +118,7 @@ export function deleteProductsStartsWith(startsWith) { ); } -export function deleteProductsAndCreateNewOneWithNewDataAndDefaultChannel({ +export function createNewProductWithNewDataAndDefaultChannel({ name, description = name, warehouseId, @@ -128,9 +130,9 @@ export function deleteProductsAndCreateNewOneWithNewDataAndDefaultChannel({ let defaultChannel; let collection; let attribute; + let category; + let productType; - deleteProductsStartsWith(name); - deleteCollectionsStartsWith(name); return getDefaultChannel() .then(channel => { defaultChannel = channel; @@ -140,23 +142,37 @@ export function deleteProductsAndCreateNewOneWithNewDataAndDefaultChannel({ collection = collectionResp; createTypeAttributeAndCategoryForProduct({ name, attributeValues }); }) - .then(({ attribute: attributeResp, category, productType }) => { - attribute = attributeResp; - createProductInChannel({ - attributeId: attribute.id, - categoryId: category.id, - productTypeId: productType.id, - channelId: defaultChannel.id, - name, - collectionId: collection.id, - description, - warehouseId, - price: productPrice, - preorder, - sku - }); - }) - .then(({ product, variantsList }) => ({ product, variantsList })); + .then( + ({ + attribute: attributeResp, + category: categoryResp, + productType: productTypeResp + }) => { + attribute = attributeResp; + category = categoryResp; + productType = productTypeResp; + createProductInChannel({ + attributeId: attribute.id, + categoryId: category.id, + productTypeId: productType.id, + channelId: defaultChannel.id, + name, + collectionId: collection.id, + description, + warehouseId, + price: productPrice, + preorder, + sku + }); + } + ) + .then(({ product, variantsList }) => ({ + product, + variantsList, + attribute, + category, + productType + })); } export function createProductWithShipping({ @@ -173,7 +189,6 @@ export function createProductWithShipping({ let defaultChannel; let shippingZone; - deleteShippingStartsWith(name); return cy .fixture("addresses") .then(addresses => { @@ -198,7 +213,7 @@ export function createProductWithShipping({ warehouse = warehouseResp; shippingMethod = shippingMethodResp; shippingZone = shippingZoneResp; - deleteProductsAndCreateNewOneWithNewDataAndDefaultChannel({ + createNewProductWithNewDataAndDefaultChannel({ name, warehouseId: warehouse.id, productPrice, @@ -208,14 +223,17 @@ export function createProductWithShipping({ }); } ) - .then(({ variantsList, product }) => ({ + .then(({ variantsList, product, attribute, category, productType }) => ({ variantsList, product, warehouse, shippingZone, defaultChannel, shippingMethod, - address + address, + attribute, + category, + productType })); } @@ -264,3 +282,166 @@ export function addDigitalContentAndUpdateProductType( setProductTypeAsDigital(productTypeId); productRequest.updateVariantPrice({ variantId, channelId, price }); } + +export function createDigitalAndPhysicalProductWithNewDataAndDefaultChannel({ + physicalProductName, + digitalProductName +}) { + let physicalVariants; + let digitalVariants; + let warehouse; + let attribute; + let shippingMethod; + let defaultChannel; + let address; + let category; + let digitalProductType; + + return createProductWithShipping({ + name: physicalProductName, + attributeValues: ["physical"] + }) + .then(resp => { + physicalVariants = resp.variantsList; + warehouse = resp.warehouse; + shippingMethod = resp.shippingMethod; + attribute = resp.attribute; + defaultChannel = resp.defaultChannel; + address = resp.address; + category = resp.category; + + createTypeProduct({ + name: digitalProductName, + shippable: false, + attributeId: attribute.id + }); + }) + .then(productType => { + digitalProductType = productType; + createProductInChannel({ + attributeId: attribute.id, + productTypeId: productType.id, + categoryId: category.id, + channelId: defaultChannel.id, + name: digitalProductName, + warehouseId: warehouse.id + }); + }) + .then(({ variantsList }) => { + digitalVariants = variantsList; + addDigitalContentAndUpdateProductType( + digitalVariants[0].id, + digitalProductType.id, + defaultChannel.id + ); + }) + .then(() => ({ + digitalVariants, + physicalVariants, + shippingMethod, + defaultChannel, + address + })); +} + +export function createNewProductWithSeveralVariants(name, variantsData) { + let address; + let defaultChannel; + let warehouse; + let shippingMethod; + const createdVariants = []; + let attribute; + let productType; + let category; + + return cy + .fixture("addresses") + .then(addresses => { + address = addresses.usAddress; + getDefaultChannel(); + }) + .then(channel => { + defaultChannel = channel; + createShipping({ + channelId: defaultChannel.id, + name, + address + }); + }) + .then( + ({ warehouse: warehouseResp, shippingMethod: shippingMethodResp }) => { + warehouse = warehouseResp; + shippingMethod = shippingMethodResp; + + const attributeValues = []; + variantsData.forEach(variant => { + attributeValues.push(variant.name); + }); + + createTypeAttributeAndCategoryForProduct({ + name, + attributeValues + }); + } + ) + .then( + ({ + attribute: attributeResp, + category: categoryResp, + productType: productTypeResp + }) => { + attribute = attributeResp; + category = categoryResp; + productType = productTypeResp; + + createProductInChannelWithoutVariants({ + attributeId: attribute.id, + categoryId: category.id, + productTypeId: productType.id, + channelId: defaultChannel.id, + name + }); + } + ) + .then(product => { + variantsData.forEach(variant => { + productRequest + .createVariant({ + productId: product.id, + attributeId: attribute.id, + channelId: defaultChannel.id, + attributeName: variant.name, + trackInventory: variant.trackInventory, + warehouseId: warehouse.id, + quantityInWarehouse: variant.quantityInWarehouse + }) + .then(variants => { + createdVariants.push(variants[0]); + }); + }); + }) + .then(() => ({ createdVariants, address, shippingMethod, defaultChannel })); +} + +export function createShippingProductTypeAttributeAndCategory( + name, + attributeValues +) { + let warehouse; + let defaultChannel; + + return createShippingWithDefaultChannelAndAddress(name) + .then(({ warehouse: warehouseResp, defaultChannel: channel }) => { + warehouse = warehouseResp; + defaultChannel = channel; + + createTypeAttributeAndCategoryForProduct({ name, attributeValues }); + }) + .then(({ attribute, productType, category }) => ({ + attribute, + productType, + category, + warehouse, + defaultChannel + })); +} diff --git a/cypress/support/api/utils/shippingUtils.js b/cypress/support/api/utils/shippingUtils.js index 2b5130987..da66a1eb0 100644 --- a/cypress/support/api/utils/shippingUtils.js +++ b/cypress/support/api/utils/shippingUtils.js @@ -1,5 +1,6 @@ import * as shippingMethodRequest from "../requests/ShippingMethod"; import * as warehouseRequest from "../requests/Warehouse"; +import { getDefaultChannel } from "./channelsUtils"; export function createShipping({ channelId, @@ -40,6 +41,30 @@ export function createShipping({ }) .then(() => ({ shippingMethod, shippingZone, warehouse })); } + +export function createShippingWithDefaultChannelAndAddress(name) { + let defaultChannel; + + return getDefaultChannel() + .then(channel => { + defaultChannel = channel; + cy.fixture("addresses"); + }) + .then(fixtureAddresses => + createShipping({ + channelId: defaultChannel.id, + name, + address: fixtureAddresses.plAddress + }) + ) + .then(({ shippingMethod, shippingZone, warehouse }) => ({ + shippingMethod, + shippingZone, + warehouse, + defaultChannel + })); +} + export function createShippingRate({ name, shippingZoneId }) { return shippingMethodRequest .createShippingRate({ name, shippingZone: shippingZoneId }) diff --git a/cypress/support/index.js b/cypress/support/index.js index 3e31cfecf..0b60eb0bc 100644 --- a/cypress/support/index.js +++ b/cypress/support/index.js @@ -21,20 +21,8 @@ commandTimings(); import { urlList } from "../fixtures/urlList"; Cypress.Commands.add("clearSessionData", () => { - // Because of known cypress bug, not all local storage data are cleared. - // Here is workaround to ensure tests have no side effects. - // Suggested usage: - // beforeEach(() => { - // cy.clearSessionData(); - // }); - cy.clearCookies(); cy.clearLocalStorage(); - cy.visit(urlList.homePage, { - onBeforeLoad: win => { - win.sessionStorage.clear(); - } - }); }); Cypress.Commands.add("addAliasToGraphRequest", operationName => { diff --git a/cypress/support/pages/homePage.js b/cypress/support/pages/homePage.js index 443f0298a..09abf4a0c 100644 --- a/cypress/support/pages/homePage.js +++ b/cypress/support/pages/homePage.js @@ -18,3 +18,61 @@ export function expectWelcomeMessageIncludes(name) { expect(text, `welcome message should contains ${name}`).to.contains(name); }); } + +export function getOrdersReadyToFulfillRegex( + ordersReadyToFulfillBefore, + quantityOfNewOrders +) { + const allOrdersReadyToFulfill = + ordersReadyToFulfillBefore + quantityOfNewOrders; + const notANumberRegex = "\\D*"; + return new RegExp( + `${notANumberRegex}${allOrdersReadyToFulfill}${notANumberRegex}` + ); +} + +export function getOrdersReadyForCaptureRegex( + ordersReadyForCaptureBefore, + quantityOfNewOrders +) { + const allOrdersReadyForCapture = + ordersReadyForCaptureBefore + quantityOfNewOrders; + const notANumberRegex = "\\D*"; + return new RegExp( + `${notANumberRegex}${allOrdersReadyForCapture}${notANumberRegex}` + ); +} + +export function getProductsOutOfStockRegex( + productsOutOfStockBefore, + quantityOfNewProducts +) { + const allProductsOutOfStock = + productsOutOfStockBefore + quantityOfNewProducts; + const notANumberRegex = "\\D*"; + return new RegExp( + `${notANumberRegex}${allProductsOutOfStock}${notANumberRegex}` + ); +} + +export function getSalesAmountRegex(salesAmountBefore, addedAmount) { + const totalAmount = salesAmountBefore + addedAmount; + const totalAmountString = totalAmount.toFixed(2); + const totalAmountIntegerValue = totalAmountString.split(".")[0]; + const totalAmountDecimalValue = totalAmountString.split(".")[1]; + const decimalSeparator = "[,.]"; + const totalAmountIntegerWithThousandsSeparator = new Intl.NumberFormat("en") + .format(totalAmountIntegerValue) + .replaceAll(",", "[,.]*"); + const totalAmountWithSeparators = `${totalAmountIntegerWithThousandsSeparator}${decimalSeparator}${totalAmountDecimalValue}`; + const notANumberRegex = "\\D*"; + return new RegExp( + `${notANumberRegex}${totalAmountWithSeparators}${notANumberRegex}` + ); +} + +export function getTodaysOrdersRegex(ordersBefore, quantityOfNewOrders) { + const allOrders = ordersBefore + quantityOfNewOrders; + const notANumberRegex = "\\D*"; + return new RegExp(`${notANumberRegex}${allOrders}${notANumberRegex}`); +} diff --git a/package.json b/package.json index 3bbc427f6..d15cf702e 100644 --- a/package.json +++ b/package.json @@ -272,7 +272,9 @@ "cy:run:dashboard": "cypress run --record --key 1fe833f5-fca4-4454-ac55-943815b91c6c", "cy:run:record": "npm run cy:run -- --record", "cy:open": "cypress open", - "cy:run:critical": "cypress run --env tags=critical --spec 'cypress/integration/navigation.js','cypress/integration/products/*.js','cypress/integration/checkout/*.js' --record --key 1fe833f5-fca4-4454-ac55-943815b91c6c", + "cy:run:critical:locally": "cypress run --env tags=critical --spec 'cypress/integration/navigation.js','cypress/integration/products/createProduct.js', 'cypress/integration/products/productsVariants.js','cypress/integration/checkout/purchaseWithProductTypes.js','cypress/integration/checkout/stocksInCheckout.js' --reporter cypress-mochawesome-reporter --reporter-options reportDir='cypress/reports',overwrite=true,charts=true", + "cy:run:refactored:locally": "cypress run --env tags=refactored --spec 'cypress/integration/navigation.js','cypress/integration/products/createProduct.js', 'cypress/integration/products/productsVariants.js','cypress/integration/checkout/purchaseWithProductTypes.js','cypress/integration/checkout/stocksInCheckout.js' --reporter cypress-mochawesome-reporter --reporter-options reportDir='cypress/reports',overwrite=true,charts=true", + "cy:run:critical": "cypress run --env tags=critical --spec 'cypress/integration/navigation.js','cypress/integration/products/*.js','cypress/integration/checkout/*.js'", "cy:run:allEnv": "cypress run --env tags=all --record --key 1fe833f5-fca4-4454-ac55-943815b91c6c", "test:e2e:run": "start-server-and-test start http://localhost:9000 cy:run", "test:e2e:run:record": "start-server-and-test start http://localhost:9000 cy:run:record",