Run critical tests after test env deployment (#1902)

* run critical tests after test env deployment

* add cache

* add all branches

* change workflow name

* add run on pull request for testing

* change type

* add run on deployment

* run on copleted

* test critical

* add quote

* change baseUrl

* fix base url

* fix base url

* upload reports

* run in parallel

* save build folder

* remove build from gitignore

* remove build

* update nide version

* last try with parallel

* save build

* save build

* Run critical

* change cypress API url

* run critical in parallel

* check which workflow has lower duration time

* save all reports with container in name

* add reports on failure

* remove reporters

* fix jobs

* merge

* add group name

* run critical

* Refactor critical tests (#1906)

* refactored tag added to purchaseWithProductsTypes, navigation, stocksInCheckout

* homePageAnalitics - refactor

* refactor home page

* refactor creating variants

* refactor adding product without sku to order

* add script to run critical locally

* change tests cases names

* fix names, remove comments, add script to run refactored tests

* remove workflow for parallel

* remove key
This commit is contained in:
Karolina Rakoczy 2022-03-21 16:17:37 +04:00 committed by GitHub
parent f3bca9af39
commit f85786f203
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 686 additions and 721 deletions

67
.github/workflows/critical-tests.yml vendored Normal file
View file

@ -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

View file

@ -70,44 +70,3 @@ jobs:
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

View file

@ -6,5 +6,6 @@
"defaultCommandTimeout": 15000,
"requestTimeout": 15000,
"viewportWidth": 1400,
"viewportHeight": 660
"viewportHeight": 660,
"videos": false
}

View file

@ -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"
}
};

View file

@ -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(

View file

@ -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);
});
});
});

View file

@ -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";
// <reference types="cypress" />
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");
});
});
});

View file

@ -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();

View file

@ -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;

View file

@ -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()

View file

@ -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);
});
});
});
});

View file

@ -1,30 +1,18 @@
/// <reference types="cypress"/>
/// <reference types="../../../support"/>
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;

View file

@ -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;

View file

@ -148,7 +148,7 @@ export function createVariant({
productId,
sku,
warehouseId,
quantityInWarehouse,
quantityInWarehouse = 1,
channelId,
attributeId,
price = 1,

View file

@ -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
}));
}

View file

@ -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 })

View file

@ -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 => {

View file

@ -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}`);
}

View file

@ -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",