diff --git a/cypress/elements/catalog/products/variants-selectors.js b/cypress/elements/catalog/products/variants-selectors.js
index 494a44742..68911eefc 100644
--- a/cypress/elements/catalog/products/variants-selectors.js
+++ b/cypress/elements/catalog/products/variants-selectors.js
@@ -10,5 +10,10 @@ export const VARIANTS_SELECTORS = {
warehouseOption: "[role='menuitem']",
saveButton: "[data-test='button-bar-confirm']",
skuInputInAddVariant: "[name='sku']",
+ preorderCheckbox: "[name='isPreorder']",
+ setUpEndDateButton: "[name='hasPreorderEndDate']",
+ preorderEndDateInput: "[name='preorderEndDateTime:date']",
+ preorderEndTimeInput: "[name='preorderEndDateTime:time']",
+ globalThresholdInput: "[name='globalThreshold']",
stockInput: "[data-test-id='stock-input']"
};
diff --git a/cypress/fixtures/urlList.js b/cypress/fixtures/urlList.js
index a45d1e332..a3a4be248 100644
--- a/cypress/fixtures/urlList.js
+++ b/cypress/fixtures/urlList.js
@@ -28,6 +28,7 @@ export const urlList = {
translations: "translations/",
variants: "variant/",
vouchers: "discounts/vouchers/",
+ variant: "variant/",
warehouses: "warehouses/",
weightRete: "weight/"
};
@@ -80,5 +81,8 @@ export const saleDetailsUrl = saleId => `${urlList.sales}${saleId}`;
export const voucherDetailsUrl = voucherId => `${urlList.vouchers}${voucherId}`;
+export const variantDetailsUrl = (productId, variantId) =>
+ `${urlList.products}${productId}/${urlList.variant}${variantId}`;
+
export const stripeConfirmationUrl = id =>
`https://api.stripe.com/v1/payment_intents/${id}/confirm`;
diff --git a/cypress/integration/preorders/createAndEditVariantsInPreorder.js b/cypress/integration/preorders/createAndEditVariantsInPreorder.js
new file mode 100644
index 000000000..e0c963f2c
--- /dev/null
+++ b/cypress/integration/preorders/createAndEditVariantsInPreorder.js
@@ -0,0 +1,133 @@
+///
+///
+
+import { PRODUCT_DETAILS } from "../../elements/catalog/products/product-details";
+import { BUTTON_SELECTORS } from "../../elements/shared/button-selectors";
+import { productDetailsUrl, variantDetailsUrl } from "../../fixtures/urlList";
+import {
+ activatePreorderOnVariant,
+ deactivatePreorderOnVariant,
+ getVariant
+} from "../../support/api/requests/Product";
+import { createWaitingForCaptureOrder } from "../../support/api/utils/ordersUtils";
+import { createProductWithShipping } from "../../support/api/utils/products/productsUtils";
+import filterTests from "../../support/filterTests";
+import { formatDate, formatTime } from "../../support/formatData/formatDate";
+import {
+ enablePreorderWithThreshold,
+ fillUpVariantAttributeAndSku,
+ saveVariant,
+ selectChannelForVariantAndFillUpPrices,
+ setUpPreorderEndDate
+} from "../../support/pages/catalog/products/VariantsPage";
+
+filterTests({ definedTags: ["all"], version: "3.1.0" }, () => {
+ describe("Creating variants", () => {
+ const startsWith = "CreatePreOrder";
+ const attributeValues = ["value1", "value2", "value3"];
+ const threshold = 100;
+ const futureDate = new Date().setDate(new Date().getDate() + 14);
+ const endDate = formatDate(futureDate);
+ const endTime = formatTime(futureDate);
+
+ let defaultChannel;
+ let product;
+ let variantsList;
+ let checkoutData;
+
+ before(() => {
+ cy.clearSessionData().loginUserViaRequest();
+ createProductWithShipping({ name: startsWith, attributeValues }).then(
+ resp => {
+ checkoutData = {
+ address: resp.address,
+ channelSlug: resp.defaultChannel.slug,
+ email: "example@example.com",
+ shippingMethodId: resp.shippingMethod.id
+ };
+ defaultChannel = resp.defaultChannel;
+ product = resp.product;
+ variantsList = resp.variantsList;
+ }
+ );
+ });
+
+ beforeEach(() => {
+ cy.clearSessionData().loginUserViaRequest();
+ });
+
+ it("should create variant in preorder", () => {
+ let variant;
+
+ cy.visit(productDetailsUrl(product.id))
+ .get(PRODUCT_DETAILS.addVariantsButton)
+ .click();
+ fillUpVariantAttributeAndSku({
+ attributeName: attributeValues[1],
+ sku: attributeValues[1]
+ });
+ enablePreorderWithThreshold(threshold);
+ setUpPreorderEndDate(endDate, endTime);
+ saveVariant()
+ .then(({ response }) => {
+ variant = response.body.data.productVariantCreate.productVariant;
+ cy.get(BUTTON_SELECTORS.back).click();
+ selectChannelForVariantAndFillUpPrices({
+ channelName: defaultChannel.name,
+ attributeName: attributeValues[1],
+ price: 10
+ });
+ })
+ .then(() => {
+ checkoutData.variantsList = [variant];
+ createWaitingForCaptureOrder(checkoutData);
+ })
+ .then(({ order }) => {
+ expect(order.id).to.be.ok;
+ getVariant(variant.id, defaultChannel.slug);
+ })
+ .then(({ preorder }) => {
+ const respEndDate = new Date(preorder.endDate);
+
+ expect(preorder.globalThreshold).to.eq(threshold);
+ expect(preorder.globalSoldUnits).to.eq(1);
+ expect(endDate).to.eq(formatDate(respEndDate));
+ expect(endTime).to.eq(formatTime(respEndDate));
+ });
+ });
+
+ it("should enable preorder on active variant", () => {
+ const variant = variantsList[0];
+ checkoutData.variantsList = [variant];
+
+ deactivatePreorderOnVariant(variant.id);
+ cy.visit(variantDetailsUrl(product.id, variant.id));
+ enablePreorderWithThreshold(threshold);
+ saveVariant("VariantUpdate");
+ createWaitingForCaptureOrder(checkoutData)
+ .then(({ order }) => {
+ expect(order.id).to.be.ok;
+ getVariant(variant.id, defaultChannel.slug);
+ })
+ .then(({ preorder }) => {
+ expect(preorder.globalThreshold).to.eq(threshold);
+ expect(preorder.globalSoldUnits).to.eq(1);
+ });
+ });
+
+ it("should set end date on preorder variant", () => {
+ const variant = variantsList[0];
+ checkoutData.variantsList = [variant];
+
+ activatePreorderOnVariant(variant.id);
+ cy.visit(variantDetailsUrl(product.id, variant.id));
+ setUpPreorderEndDate(endDate, endTime);
+ saveVariant("VariantUpdate");
+ getVariant(variant.id, defaultChannel.slug).then(({ preorder }) => {
+ const respEndDate = new Date(preorder.endDate);
+ expect(endDate).to.eq(formatDate(respEndDate));
+ expect(endTime).to.eq(formatTime(respEndDate));
+ });
+ });
+ });
+});
diff --git a/cypress/support/api/requests/Product.js b/cypress/support/api/requests/Product.js
index 3467caa16..c021a95b6 100644
--- a/cypress/support/api/requests/Product.js
+++ b/cypress/support/api/requests/Product.js
@@ -1,9 +1,6 @@
import { stringify } from "../.././formatData/formatJson";
-import {
- getValuesInArray,
- getValueWithDefault,
- getVariantsListIds
-} from "./utils/Utils";
+import { returnValueDependsOnShopVersion } from "../../formatData/dataDependingOnVersion";
+import { getValueWithDefault, getVariantsListIds } from "./utils/Utils";
export function getFirstProducts(first, search) {
const filter = search
@@ -241,10 +238,20 @@ export function getVariants(variantsList) {
}
export function getVariant(id, channel, auth = "auth") {
+ const preorder = returnValueDependsOnShopVersion(
+ "3.1",
+ `preorder{
+ globalThreshold
+ globalSoldUnits
+ endDate
+ }`
+ );
+
const query = `query{
productVariant(id:"${id}" channel:"${channel}"){
id
name
+ ${preorder}
sku
pricing{
onSale
@@ -268,3 +275,41 @@ export function getVariant(id, channel, auth = "auth") {
}`;
return cy.sendRequestWithQuery(query, auth).its("body.data.productVariant");
}
+
+export function deactivatePreorderOnVariant(variantId) {
+ const mutation = `mutation{
+ productVariantPreorderDeactivate(id:"${variantId}"){
+ errors{
+ field
+ message
+ }
+ }
+ }`;
+ return cy
+ .sendRequestWithQuery(mutation)
+ .its("body.data.productVariantPreorderDeactivate");
+}
+
+export function activatePreorderOnVariant(variantId, threshold, endDate) {
+ const thresholdLine = getValueWithDefault(
+ threshold,
+ `globalThreshold:${threshold}`
+ );
+ const endDateLine = getValueWithDefault(threshold, `endDate:${endDate}`);
+ const mutation = `mutation{
+ productVariantUpdate(id:"${variantId}", input:{
+ preorder:{
+ ${thresholdLine}
+ ${endDateLine}
+ }
+ }){
+ errors{
+ field
+ message
+ }
+ }
+ }`;
+ return cy
+ .sendRequestWithQuery(mutation)
+ .its("body.data.productVariantUpdate");
+}
diff --git a/cypress/support/api/utils/products/productsUtils.js b/cypress/support/api/utils/products/productsUtils.js
index 28f689315..f9059c270 100644
--- a/cypress/support/api/utils/products/productsUtils.js
+++ b/cypress/support/api/utils/products/productsUtils.js
@@ -12,7 +12,7 @@ import {
import { deleteAttributesStartsWith } from "../attributes/attributeUtils";
import { deleteCollectionsStartsWith } from "../catalog/collectionsUtils";
import { getDefaultChannel } from "../channelsUtils";
-import { createShipping } from "../shippingUtils";
+import { createShipping, deleteShippingStartsWith } from "../shippingUtils";
export function createProductInChannel({
name,
@@ -116,6 +116,7 @@ export function deleteProductsAndCreateNewOneWithNewDataAndDefaultChannel({
name,
description = name,
warehouseId,
+ attributeValues = ["value"],
sku = name,
productPrice = 10
}) {
@@ -132,7 +133,7 @@ export function deleteProductsAndCreateNewOneWithNewDataAndDefaultChannel({
})
.then(collectionResp => {
collection = collectionResp;
- createTypeAttributeAndCategoryForProduct({ name });
+ createTypeAttributeAndCategoryForProduct({ name, attributeValues });
})
.then(({ attribute: attributeResp, category, productType }) => {
attribute = attributeResp;
@@ -154,6 +155,7 @@ export function deleteProductsAndCreateNewOneWithNewDataAndDefaultChannel({
export function createProductWithShipping({
name,
+ attributeValues = ["value"],
sku = name,
productPrice = 10,
shippingPrice = 10
@@ -164,6 +166,7 @@ export function createProductWithShipping({
let defaultChannel;
let shippingZone;
+ deleteShippingStartsWith(name);
return cy
.fixture("addresses")
.then(addresses => {
@@ -191,6 +194,7 @@ export function createProductWithShipping({
deleteProductsAndCreateNewOneWithNewDataAndDefaultChannel({
name,
warehouseId: warehouse.id,
+ attributeValues,
sku,
productPrice
});
diff --git a/cypress/support/formatData/formatDate.js b/cypress/support/formatData/formatDate.js
index 324d7261a..1140a381a 100644
--- a/cypress/support/formatData/formatDate.js
+++ b/cypress/support/formatData/formatDate.js
@@ -10,3 +10,11 @@ function getPeriodValue(date, option) {
const formatter = new Intl.DateTimeFormat("en-us", option);
return formatter.format(date);
}
+
+export function formatTime(date) {
+ const formatter = new Intl.DateTimeFormat([], {
+ hour: "numeric",
+ minute: "numeric"
+ });
+ return formatter.format(date);
+}
diff --git a/cypress/support/index.d.ts b/cypress/support/index.d.ts
index 56916ff8d..1db07d05b 100644
--- a/cypress/support/index.d.ts
+++ b/cypress/support/index.d.ts
@@ -48,5 +48,6 @@ declare namespace Cypress {
createNewOption(selectSelector: string, newOption: string): Chainable;
findElementOnTable(elementName: string): Chainable;
searchInTable(query: string): Chainable;
+ waitForRequestAndCheckIfNoErrors(alias: string): Chainable;
}
}
diff --git a/cypress/support/pages/catalog/products/VariantsPage.js b/cypress/support/pages/catalog/products/VariantsPage.js
index ae4077e47..53729e8e1 100644
--- a/cypress/support/pages/catalog/products/VariantsPage.js
+++ b/cypress/support/pages/catalog/products/VariantsPage.js
@@ -55,28 +55,50 @@ export function createVariant({
channelName,
quantity = 10
}) {
- cy.get(PRODUCT_DETAILS.addVariantsButton)
+ cy.get(PRODUCT_DETAILS.addVariantsButton).click();
+ fillUpGeneralVariantInputs({ attributeName, warehouseName, sku });
+ cy.get(VARIANTS_SELECTORS.saveButton)
.click()
- .get(VARIANTS_SELECTORS.attributeSelector)
+ .get(BUTTON_SELECTORS.back)
+ .click();
+ selectChannelForVariantAndFillUpPrices({
+ channelName,
+ attributeName,
+ price,
+ costPrice
+ });
+}
+
+export function fillUpGeneralVariantInputs({
+ attributeName,
+ warehouseName,
+ sku
+}) {
+ fillUpVariantAttributeAndSku({ attributeName, sku });
+ cy.get(VARIANTS_SELECTORS.addWarehouseButton).click();
+ cy.contains(VARIANTS_SELECTORS.warehouseOption, warehouseName).click({
+ force: true
+ });
+ cy.get(VARIANTS_SELECTORS.stockInput).type(quantity);
+}
+
+export function fillUpVariantAttributeAndSku({ attributeName, sku }) {
+ cy.get(VARIANTS_SELECTORS.attributeSelector)
.click()
.get(VARIANTS_SELECTORS.attributeOption)
.contains(attributeName)
- .click();
- if (sku) {
- cy.get(VARIANTS_SELECTORS.skuInputInAddVariant).type(sku);
- }
- cy.get(VARIANTS_SELECTORS.addWarehouseButton).click();
- cy.contains(VARIANTS_SELECTORS.warehouseOption, warehouseName)
- .click({
- force: true
- })
- .get(VARIANTS_SELECTORS.stockInput)
- .type(quantity)
- .get(VARIANTS_SELECTORS.saveButton)
.click()
- .get(BUTTON_SELECTORS.back)
- .click()
- .addAliasToGraphRequest("ProductChannelListingUpdate");
+ .get(VARIANTS_SELECTORS.skuInputInAddVariant)
+ .type(sku);
+}
+
+export function selectChannelForVariantAndFillUpPrices({
+ channelName,
+ attributeName,
+ price,
+ costPrice = price
+}) {
+ cy.addAliasToGraphRequest("ProductChannelListingUpdate");
selectChannelVariantInDetailsPage(channelName, attributeName);
cy.get(BUTTON_SELECTORS.confirm)
.click()
@@ -97,3 +119,27 @@ export function createVariant({
.get(AVAILABLE_CHANNELS_FORM.menageChannelsButton)
.should("be.visible");
}
+
+export function enablePreorderWithThreshold(threshold) {
+ cy.get(VARIANTS_SELECTORS.preorderCheckbox)
+ .click()
+ .get(VARIANTS_SELECTORS.globalThresholdInput)
+ .type(threshold);
+}
+
+export function setUpPreorderEndDate(endDate, endTime) {
+ cy.get(VARIANTS_SELECTORS.setUpEndDateButton)
+ .click()
+ .get(VARIANTS_SELECTORS.preorderEndDateInput)
+ .type(endDate)
+ .get(VARIANTS_SELECTORS.preorderEndTimeInput)
+ .type(endTime);
+}
+
+export function saveVariant(waitForAlias = "VariantCreate") {
+ return cy
+ .addAliasToGraphRequest(waitForAlias)
+ .get(BUTTON_SELECTORS.confirm)
+ .click()
+ .waitForRequestAndCheckIfNoErrors(`@${waitForAlias}`);
+}