diff --git a/cypress/elements/catalog/products/product-details.js b/cypress/elements/catalog/products/product-details.js
index 254e7972b..b7fed4d89 100644
--- a/cypress/elements/catalog/products/product-details.js
+++ b/cypress/elements/catalog/products/product-details.js
@@ -28,5 +28,6 @@ export const PRODUCT_DETAILS = {
warehouseOption: "[role='menuitem']",
stockInput: '[data-test-id="stock-input"]',
costPriceInput: '[name*="costPrice"]',
- sellingPriceInput: '[name*="channel-price"]'
+ sellingPriceInput: '[name*="channel-price"]',
+ createSingleVariantCheckbox: '[value="single"]'
};
diff --git a/cypress/elements/catalog/products/variants-selectors.js b/cypress/elements/catalog/products/variants-selectors.js
index f24bb2fbd..970e7ca0d 100644
--- a/cypress/elements/catalog/products/variants-selectors.js
+++ b/cypress/elements/catalog/products/variants-selectors.js
@@ -5,11 +5,14 @@ export const VARIANTS_SELECTORS = {
warehouseCheckboxes: "[name*='warehouse:']",
skuInput: "[ data-test-id='sku-input']",
attributeSelector: "[data-test='attribute-value']",
- attributeOption: "[data-test-type='option']",
+ attributeOption:
+ "[data-test-type='option'], [data-test='multiautocomplete-select-option']",
addWarehouseButton: "button[class*='MuiIconButton-colorPrimary']",
warehouseOption: "[role='menuitem']",
saveButton: "[data-test='button-bar-confirm']",
skuInputInAddVariant: "[name='sku']",
+ stockInput: "[data-test-id='stock-input']",
+ booleanAttributeCheckbox: "[name*='attribute'][type='checkbox']",
preorderCheckbox: "[name='isPreorder']",
channelThresholdInput: "[name='channel-threshold']",
setUpEndDateButton: "[name='hasPreorderEndDate']",
diff --git a/cypress/integration/configuration/attributes/attributeVariantSelection.js b/cypress/integration/configuration/attributes/attributeVariantSelection.js
new file mode 100644
index 000000000..ceeef318b
--- /dev/null
+++ b/cypress/integration/configuration/attributes/attributeVariantSelection.js
@@ -0,0 +1,115 @@
+///
+///
+
+import { PRODUCT_DETAILS } from "../../../elements/catalog/products/product-details";
+import { BUTTON_SELECTORS } from "../../../elements/shared/button-selectors";
+import { productDetailsUrl } from "../../../fixtures/urlList";
+import { createAttribute } from "../../../support/api/requests/Attribute";
+import { createCategory } from "../../../support/api/requests/Category";
+import { getVariant } from "../../../support/api/requests/Product";
+import {
+ createTypeProduct,
+ productAttributeAssignmentUpdate
+} from "../../../support/api/requests/ProductType";
+import { getDefaultChannel } from "../../../support/api/utils/channelsUtils";
+import {
+ createProductInChannelWithoutVariants,
+ deleteProductsStartsWith
+} from "../../../support/api/utils/products/productsUtils";
+import filterTests from "../../../support/filterTests";
+import { fillUpVariantDetails } from "../../../support/pages/catalog/products/VariantsPage";
+
+filterTests({ definedTags: ["all"], version: "3.1.0" }, () => {
+ describe("Create attribute with type", () => {
+ const startsWith = "VarSel";
+
+ const attributesTypes = [
+ "DROPDOWN",
+ "MULTISELECT",
+ "BOOLEAN",
+ "NUMERIC",
+ "SWATCH",
+ "DATE"
+ ];
+ let channel;
+ let category;
+ let product;
+
+ before(() => {
+ cy.clearSessionData().loginUserViaRequest();
+ deleteProductsStartsWith(startsWith);
+ getDefaultChannel().then(defaultChannel => (channel = defaultChannel));
+ createCategory(startsWith).then(
+ categoryResp => (category = categoryResp)
+ );
+ });
+
+ beforeEach(() => {
+ cy.clearSessionData().loginUserViaRequest();
+ });
+
+ attributesTypes.forEach(attributeType => {
+ it(`should create variant with ${attributeType} attribute`, () => {
+ const name = `${startsWith}${attributeType}`;
+ const inputType = attributeType;
+ const attributeValues = ["1", "2"];
+ let productType;
+ let attribute;
+
+ createAttribute({
+ name,
+ inputType,
+ attributeValues
+ })
+ .then(attributeResp => {
+ attribute = attributeResp;
+ createTypeProduct({
+ name,
+ attributeId: attribute.id,
+ productAttributes: false
+ });
+ })
+ .then(productTypeResp => {
+ productType = productTypeResp;
+ productAttributeAssignmentUpdate({
+ productTypeId: productType.id,
+ attributeId: attribute.id
+ });
+ })
+ .then(() => {
+ createProductInChannelWithoutVariants({
+ categoryId: category.id,
+ productTypeId: productType.id,
+ name,
+ channelId: channel.id
+ });
+ })
+ .then(productResp => {
+ product = productResp;
+ cy.visit(productDetailsUrl(product.id))
+ .get(PRODUCT_DETAILS.addVariantsButton)
+ .click()
+ .get(PRODUCT_DETAILS.createSingleVariantCheckbox)
+ .click()
+ .get(BUTTON_SELECTORS.submit)
+ .click()
+ .addAliasToGraphRequest("VariantCreate");
+ fillUpVariantDetails({
+ sku: name,
+ attributeName: attributeValues[0],
+ attributeType
+ });
+ cy.wait("@VariantCreate");
+ })
+ .then(({ response }) => {
+ const variant =
+ response.body.data.productVariantCreate.productVariant;
+ getVariant(variant.id, channel.slug);
+ })
+ .then(({ attributes }) => {
+ expect(attributes[0].attribute.inputType).to.eq(inputType);
+ });
+ });
+ });
+ });
+});
diff --git a/cypress/integration/preorders/createAndEditVariantsInPreorder.js b/cypress/integration/preorders/createAndEditVariantsInPreorder.js
index e0c963f2c..2b131e6ff 100644
--- a/cypress/integration/preorders/createAndEditVariantsInPreorder.js
+++ b/cypress/integration/preorders/createAndEditVariantsInPreorder.js
@@ -43,7 +43,7 @@ filterTests({ definedTags: ["all"], version: "3.1.0" }, () => {
address: resp.address,
channelSlug: resp.defaultChannel.slug,
email: "example@example.com",
- shippingMethodId: resp.shippingMethod.id
+ shippingMethodName: resp.shippingMethod.name
};
defaultChannel = resp.defaultChannel;
product = resp.product;
@@ -119,7 +119,7 @@ filterTests({ definedTags: ["all"], version: "3.1.0" }, () => {
const variant = variantsList[0];
checkoutData.variantsList = [variant];
- activatePreorderOnVariant(variant.id);
+ activatePreorderOnVariant({ variantId: variant.id });
cy.visit(variantDetailsUrl(product.id, variant.id));
setUpPreorderEndDate(endDate, endTime);
saveVariant("VariantUpdate");
diff --git a/cypress/support/api/requests/Product.js b/cypress/support/api/requests/Product.js
index adaf4ef44..c8368c579 100644
--- a/cypress/support/api/requests/Product.js
+++ b/cypress/support/api/requests/Product.js
@@ -110,12 +110,17 @@ export function createProduct({
attributeValue,
`values:["${attributeValue}"]`
);
+ const attributesLines = getValueWithDefault(
+ attributeId,
+ `attributes:[{
+ id:"${attributeId}"
+ ${attributeValuesLine}
+ }]`
+ );
+
const mutation = `mutation{
productCreate(input:{
- attributes:[{
- id:"${attributeId}"
- ${attributeValuesLine}
- }]
+ ${attributesLines}
name:"${name}"
slug:"${name}"
seo:{title:"${name}" description:""}
@@ -265,6 +270,14 @@ export function getVariant(id, channelSlug, auth = "auth") {
}
${preorder}
sku
+ attributes{
+ attribute{
+ inputType
+ }
+ values{
+ name
+ }
+ }
pricing{
onSale
discount{
@@ -302,18 +315,24 @@ export function deactivatePreorderOnVariant(variantId) {
.its("body.data.productVariantPreorderDeactivate");
}
-export function activatePreorderOnVariant(variantId, threshold, endDate) {
+export function activatePreorderOnVariant({
+ variantId,
+ threshold = 50,
+ endDate
+}) {
const thresholdLine = getValueWithDefault(
threshold,
`globalThreshold:${threshold}`
);
- const endDateLine = getValueWithDefault(threshold, `endDate:${endDate}`);
+ const endDateLine = getValueWithDefault(endDate, `endDate:${endDate}`);
const mutation = `mutation{
productVariantUpdate(id:"${variantId}", input:{
preorder:{
${thresholdLine}
${endDateLine}
- }errors{
+ }
+ }){
+ errors{
field
message
}
diff --git a/cypress/support/api/requests/ProductType.js b/cypress/support/api/requests/ProductType.js
index efe9e6dcc..bdfb0da01 100644
--- a/cypress/support/api/requests/ProductType.js
+++ b/cypress/support/api/requests/ProductType.js
@@ -7,11 +7,12 @@ export function createTypeProduct({
hasVariants = true,
slug = name,
shippable = true,
- kind = "NORMAL"
+ kind = "NORMAL",
+ productAttributes = true
}) {
const kindLines = returnValueDependsOnShopVersion("3.1", `kind: ${kind}`);
const productAttributesLine = getValueWithDefault(
- attributeId,
+ productAttributes && attributeId,
`productAttributes: "${attributeId}"`
);
const variantAttributesLine = getValueWithDefault(
diff --git a/cypress/support/pages/catalog/products/VariantsPage.js b/cypress/support/pages/catalog/products/VariantsPage.js
index 53729e8e1..e6a112369 100644
--- a/cypress/support/pages/catalog/products/VariantsPage.js
+++ b/cypress/support/pages/catalog/products/VariantsPage.js
@@ -3,6 +3,8 @@ import { PRODUCT_DETAILS } from "../../../../elements/catalog/products/product-d
import { VARIANTS_SELECTORS } from "../../../../elements/catalog/products/variants-selectors";
import { AVAILABLE_CHANNELS_FORM } from "../../../../elements/channels/available-channels-form";
import { BUTTON_SELECTORS } from "../../../../elements/shared/button-selectors";
+import { SHARED_ELEMENTS } from "../../../../elements/shared/sharedElements";
+import { formatDate } from "../../../formatData/formatDate";
import { selectChannelVariantInDetailsPage } from "../../channelsPage";
import { fillUpPriceList } from "./priceListComponent";
@@ -56,7 +58,8 @@ export function createVariant({
quantity = 10
}) {
cy.get(PRODUCT_DETAILS.addVariantsButton).click();
- fillUpGeneralVariantInputs({ attributeName, warehouseName, sku });
+ fillUpVariantDetails({ attributeName, sku, warehouseName, quantity });
+ cy.get(BUTTON_SELECTORS.back);
cy.get(VARIANTS_SELECTORS.saveButton)
.click()
.get(BUTTON_SELECTORS.back)
@@ -72,7 +75,8 @@ export function createVariant({
export function fillUpGeneralVariantInputs({
attributeName,
warehouseName,
- sku
+ sku,
+ quantity
}) {
fillUpVariantAttributeAndSku({ attributeName, sku });
cy.get(VARIANTS_SELECTORS.addWarehouseButton).click();
@@ -82,6 +86,29 @@ export function fillUpGeneralVariantInputs({
cy.get(VARIANTS_SELECTORS.stockInput).type(quantity);
}
+export function fillUpVariantDetails({
+ attributeName,
+ attributeType = "DROPDOWN",
+ sku,
+ warehouseName,
+ quantity
+}) {
+ selectAttributeWithType({ attributeType, attributeName });
+ if (sku) {
+ cy.get(VARIANTS_SELECTORS.skuInputInAddVariant).type(sku);
+ }
+ if (warehouseName) {
+ cy.get(VARIANTS_SELECTORS.addWarehouseButton).click();
+ cy.contains(VARIANTS_SELECTORS.warehouseOption, warehouseName)
+ .click({
+ force: true
+ })
+ .get(VARIANTS_SELECTORS.stockInput)
+ .type(quantity);
+ }
+ cy.get(VARIANTS_SELECTORS.saveButton).click();
+}
+
export function fillUpVariantAttributeAndSku({ attributeName, sku }) {
cy.get(VARIANTS_SELECTORS.attributeSelector)
.click()
@@ -120,6 +147,44 @@ export function selectChannelForVariantAndFillUpPrices({
.should("be.visible");
}
+export function selectOptionsAttribute(attributeName) {
+ cy.get(VARIANTS_SELECTORS.attributeSelector)
+ .click()
+ .get(VARIANTS_SELECTORS.attributeOption)
+ .contains(attributeName)
+ .click();
+}
+
+export function selectBooleanAttributeToTrue() {
+ cy.get(VARIANTS_SELECTORS.booleanAttributeCheckbox).click();
+}
+
+export function selectDateAttribute() {
+ cy.get(VARIANTS_SELECTORS.attributeSelector)
+ .find("input")
+ .type(formatDate(new Date()));
+}
+
+export function selectNumericAttribute(numeric) {
+ cy.get(VARIANTS_SELECTORS.attributeSelector).type(numeric);
+}
+
+export function selectAttributeWithType({ attributeType, attributeName }) {
+ switch (attributeType) {
+ case "DATE":
+ selectDateAttribute();
+ break;
+ case "BOOLEAN":
+ selectBooleanAttributeToTrue();
+ break;
+ case "NUMERIC":
+ selectNumericAttribute(attributeName);
+ break;
+ default:
+ selectOptionsAttribute(attributeName);
+ }
+}
+
export function enablePreorderWithThreshold(threshold) {
cy.get(VARIANTS_SELECTORS.preorderCheckbox)
.click()