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