diff --git a/cypress/elements/siteSettings/site-settings-details.js b/cypress/elements/siteSettings/site-settings-details.js index 8272239f8..4cb90a3e9 100644 --- a/cypress/elements/siteSettings/site-settings-details.js +++ b/cypress/elements/siteSettings/site-settings-details.js @@ -1,4 +1,8 @@ export const SITE_SETTINGS_DETAILS = { nameInput: '[name="name"]', - descriptionInput: '[name="description"]' + descriptionInput: '[name="description"]', + stockReservationAuthenticatedUserInput: + '[name="reserveStockDurationAuthenticatedUser"]', + stockReservationAnonymousUserInput: + '[name="reserveStockDurationAnonymousUser"]' }; diff --git a/cypress/integration/orders/manageStockReservation.js b/cypress/integration/orders/manageStockReservation.js new file mode 100644 index 000000000..86809884e --- /dev/null +++ b/cypress/integration/orders/manageStockReservation.js @@ -0,0 +1,180 @@ +/// +/// + +import faker from "faker"; + +import { createCheckout } from "../../support/api/requests/Checkout"; +import { updateStockReservation } from "../../support/api/requests/ShopSettings"; +import { getDefaultChannel } from "../../support/api/utils/channelsUtils"; +import { + createProductInChannel, + createTypeAttributeAndCategoryForProduct, + deleteProductsStartsWith +} from "../../support/api/utils/products/productsUtils"; +import { + createShipping, + deleteShippingStartsWith +} from "../../support/api/utils/shippingUtils"; +import filterTests from "../../support/filterTests"; +import { + enterSiteSettingAndSetStockReservation, + userType +} from "../../support/pages/siteSettings"; + +filterTests({ definedTags: ["all"], version: "3.1.0" }, () => { + describe("As an admin I want to manage stock reservation", () => { + const startsWith = "manageStocks"; + const name = `${startsWith}${faker.datatype.number()}`; + const productQuantity = 10; + const customerType = { + authenticated: "auth", + anonymous: "token" + }; + + let defaultChannel; + let address; + let warehouse; + let attribute; + let category; + let productType; + let dataForCheckout; + + 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 }) => { + warehouse = warehouseResp; + createTypeAttributeAndCategoryForProduct({ name }); + }) + .then( + ({ + attribute: attributeResp, + category: categoryResp, + productType: productTypeResp + }) => { + attribute = attributeResp; + category = categoryResp; + productType = productTypeResp; + } + ); + }); + + beforeEach(() => { + const productName = `${startsWith}${faker.datatype.number()}`; + + cy.clearSessionData().loginUserViaRequest(); + + createProductInChannel({ + attributeId: attribute.id, + categoryId: category.id, + channelId: defaultChannel.id, + name: productName, + productTypeId: productType.id, + warehouseId: warehouse.id, + quantityInWarehouse: productQuantity + }).then(({ variantsList }) => { + dataForCheckout = { + email: "example@example.pl", + address, + channelSlug: defaultChannel.slug, + variantsList, + productQuantity + }; + }); + }); + + it("should be able to set stock reservation for authenticated customer in checkout. TC: SALEOR_0415", () => { + dataForCheckout.auth = customerType.authenticated; + + updateStockReservation({}) + .then(() => { + enterSiteSettingAndSetStockReservation(userType.authenticated, 10); + createCheckout(dataForCheckout); + }) + .then(({ checkout }) => { + expect(checkout).to.be.ok; + createCheckout(dataForCheckout); + }) + .then(resp => { + expect(resp.errors, "there should be errors in response").to.not.be + .empty; + expect( + resp.errors[0].field, + "error should be on field quantity" + ).to.be.eq("quantity"); + }); + }); + + it("should be able to set stock reservation for anonymous customer in checkout. TC: SALEOR_0416", () => { + dataForCheckout.auth = customerType.anonymous; + + updateStockReservation({}) + .then(() => { + enterSiteSettingAndSetStockReservation(userType.anonymous, 10); + createCheckout(dataForCheckout); + }) + .then(({ checkout }) => { + expect(checkout).to.be.ok; + createCheckout(dataForCheckout); + }) + .then(resp => { + expect(resp.errors, "there should be errors in response").to.not.be + .empty; + expect( + resp.errors[0].field, + "error should be on field quantity" + ).to.be.eq("quantity"); + }); + }); + + it("should be able to leave empty stock reservation for authenticated customer in checkout. TC: SALEOR_0417", () => { + dataForCheckout.auth = customerType.authenticated; + + updateStockReservation({ authenticatedUserStock: 10 }) + .then(() => { + enterSiteSettingAndSetStockReservation(userType.authenticated); + createCheckout(dataForCheckout); + }) + .then(({ checkout }) => { + expect(checkout).to.be.ok; + createCheckout(dataForCheckout); + }) + .then(resp => { + expect(resp.errors, "there should be no errors in response").to.be + .empty; + }); + }); + + it("should be able to leave empty stock reservation for anonymous customer in checkout. TC: SALEOR_0418", () => { + dataForCheckout.auth = customerType.anonymous; + + updateStockReservation({ anonymousUserStock: 10 }) + .then(() => { + enterSiteSettingAndSetStockReservation(userType.anonymous); + createCheckout(dataForCheckout); + }) + .then(({ checkout }) => { + expect(checkout).to.be.ok; + createCheckout(dataForCheckout); + }) + .then(resp => { + expect(resp.errors, "there should be no errors in response").to.be + .empty; + }); + }); + }); +}); diff --git a/cypress/support/api/requests/Checkout.js b/cypress/support/api/requests/Checkout.js index 598a77f7a..e9866a5ce 100644 --- a/cypress/support/api/requests/Checkout.js +++ b/cypress/support/api/requests/Checkout.js @@ -32,10 +32,12 @@ export function createCheckout({ }` ); + const emailLine = getValueWithDefault(email, `email: "${email}"`); + const mutation = `mutation{ checkoutCreate(input:{ channel:"${channelSlug}" - email:"${email}" + ${emailLine} lines: [${lines.join()}] ${shippingAddress} ${billingAddressLines} diff --git a/cypress/support/api/requests/ShopSettings.js b/cypress/support/api/requests/ShopSettings.js index 8e9aaa606..035c6b21f 100644 --- a/cypress/support/api/requests/ShopSettings.js +++ b/cypress/support/api/requests/ShopSettings.js @@ -20,6 +20,28 @@ export function updateShopWeightUnit(weightUnit) { .its("body.data.shopSettingsUpdate"); } +export function updateStockReservation({ + authenticatedUserStock = 0, + anonymousUserStock = 0 +}) { + const mutation = `mutation{ + shopSettingsUpdate(input:{ + reserveStockDurationAnonymousUser: ${anonymousUserStock}, + reserveStockDurationAuthenticatedUser: ${authenticatedUserStock} + }){ + errors{ + field + message + } + shop{ + reserveStockDurationAnonymousUser, + reserveStockDurationAuthenticatedUser + } + } + }`; + return cy.sendRequestWithQuery(mutation).its("body.data.shopSettingsUpdate"); +} + export function updateShopAddress(address) { const input = getDefaultAddress(address, "input"); const mutation = `mutation{ diff --git a/cypress/support/pages/siteSettings.js b/cypress/support/pages/siteSettings.js new file mode 100644 index 000000000..e32eb84fd --- /dev/null +++ b/cypress/support/pages/siteSettings.js @@ -0,0 +1,21 @@ +import { BUTTON_SELECTORS } from "../../elements/shared/button-selectors"; +import { SITE_SETTINGS_DETAILS } from "../../elements/siteSettings/site-settings-details"; +import { urlList } from "../../fixtures/urlList"; + +export function enterSiteSettingAndSetStockReservation(userType, stockAmount) { + cy.visitAndWaitForProgressBarToDisappear(urlList.siteSettings); + if (stockAmount) { + cy.get(userType).clearAndType(stockAmount); + } else { + cy.get(userType).clear(); + } + cy.addAliasToGraphRequest("ShopSettingsUpdate") + .get(BUTTON_SELECTORS.confirm) + .click() + .waitForRequestAndCheckIfNoErrors("@ShopSettingsUpdate"); +} + +export const userType = { + anonymous: SITE_SETTINGS_DETAILS.stockReservationAnonymousUserInput, + authenticated: SITE_SETTINGS_DETAILS.stockReservationAuthenticatedUserInput +};