Saleor 1746 tests for vouchers (#1014)

* tests for vouchers

* test for vouchers

* test for vouchers

* add getDefaultAddress
This commit is contained in:
Karolina 2021-03-23 11:15:39 +01:00 committed by GitHub
parent 78ba9f4fe9
commit 0da6012bc4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 400 additions and 82 deletions

View file

@ -1,18 +1,24 @@
export function createCheckout(
import { getDefaultAddress } from "./utils/Utils";
export function createCheckout({
channelSlug,
email,
productQuantity,
variantsList
) {
productQuantity = 1,
variantsList,
address,
auth = "auth"
}) {
const lines = variantsList.map(
variant => `{quantity:${productQuantity}
variantId:"${variant.id}"}`
);
const shippingAddress = getDefaultAddress(address, "shippingAddress");
const mutation = `mutation{
checkoutCreate(input:{
channel:"${channelSlug}"
email:"${email}"
lines: [${lines.join()}]
${shippingAddress}
}){
checkoutErrors{
field
@ -24,7 +30,7 @@ export function createCheckout(
}
}
}`;
return cy.sendRequestWithQuery(mutation);
return cy.sendRequestWithQuery(mutation, auth);
}
export function addShippingMethod(checkoutId, shippingMethodId) {
const mutation = `mutation{
@ -69,3 +75,24 @@ export function completeCheckout(checkoutId) {
}`;
return cy.sendRequestWithQuery(mutation);
}
export function addVoucher(checkoutId, voucherCode) {
const mutation = `mutation addVoucher{
checkoutAddPromoCode(checkoutId:"${checkoutId}",
promoCode:"${voucherCode}"
){
checkoutErrors{
field
message
}
checkout{
totalPrice{
gross{
amount
}
}
}
}
}`;
return cy.sendRequestWithQuery(mutation);
}

View file

@ -1,3 +1,4 @@
import { getDefaultAddress } from "./utils/Utils";
export function createCustomer(email, customerName, address, isActive = false) {
const mutation = `
mutation{
@ -6,24 +7,8 @@ export function createCustomer(email, customerName, address, isActive = false) {
lastName: "${customerName}"
email: "${email}"
isActive: ${isActive}
defaultBillingAddress: {
companyName: "${address.companyName}"
streetAddress1: "${address.streetAddress1}"
streetAddress2: "${address.streetAddress2}"
city: "${address.city}"
postalCode: "${address.postalCode}"
country: ${address.country}
phone: "${address.phone}"
}
defaultShippingAddress: {
companyName: "${address.companyName}"
streetAddress1: "${address.streetAddress1}"
streetAddress2: "${address.streetAddress2}"
city: "${address.city}"
postalCode: "${address.postalCode}"
country: ${address.country}
phone: "${address.phone}"
}
${getDefaultAddress(address, "defaultBillingAddress")}
${getDefaultAddress(address, "defaultShippingAddress")}
}){
user{
id

View file

@ -1,4 +1,4 @@
import { getValueWithDefault } from "./utils/Utils";
import { getValueWithDefault } from "../utils/Utils";
export function getSales(first, searchQuery) {
const filter = getValueWithDefault(

View file

@ -0,0 +1,28 @@
export function getVouchers(first, startsWith) {
const query = `query getVouchers{
vouchers(first:${first}, filter:{
search:"${startsWith}"
}){
edges{
node{
id
code
}
}
}
}`;
return cy
.sendRequestWithQuery(query)
.then(resp => resp.body.data.vouchers.edges);
}
export function deleteVouchers(voucherId) {
const mutation = `mutation deleteVouchers{
voucherDelete(id:"${voucherId}"){
discountErrors{
field
message
}
}
}`;
return cy.sendRequestWithQuery(mutation);
}

View file

@ -1,17 +1,12 @@
import { getDefaultAddress } from "./utils/Utils";
export function createWarehouse(name, shippingZone, address, slug = name) {
const mutation = `mutation{
createWarehouse(input:{
name:"${name}"
slug:"${slug}"
shippingZones:"${shippingZone}"
address:{
streetAddress1: "${address.streetAddress1}"
streetAddress2: "${address.streetAddress2}"
city: "${address.city}"
postalCode: "${address.postalCode}"
country: ${address.country}
phone: "${address.phone}"
}
${getDefaultAddress(address, "address", false)}
}){
warehouseErrors{
field

View file

@ -1,2 +1,21 @@
export const getValueWithDefault = (condition, value, defaultValue = "") =>
condition ? value : defaultValue;
export function getDefaultAddress(address, addressType, withName = true) {
if (!address) {
return "";
}
const defaultAddress = `city: "${address.city}"
country: ${address.country}
countryArea: "${address.countryArea}"
phone: "${address.phone}"
postalCode: "${address.postalCode}"
streetAddress1: "${address.streetAddress1}"
streetAddress2: "${address.streetAddress2}"`;
if (withName) {
defaultAddress.concat(`firstName: "Test"
lastName: "Test"
companyName: "${address.companyName}"`);
}
return `${addressType}:{${defaultAddress}}`;
}

View file

@ -12,5 +12,6 @@ export const MENAGE_CHANNEL_AVAILABILITY = {
radioButtonsValueTrue: "[value='true']",
radioButtonsValueFalse: "[value='false']",
visibleInListingsButton: "[name*='visibleInListings']",
allChannelsInput: "[name='allChannels']"
allChannelsInput: "[name='allChannels']",
dialog: "[role='dialog']"
};

View file

@ -0,0 +1,9 @@
export const VOUCHERS_SELECTORS = {
createVoucherButton: "[data-test-id='create-voucher']",
voucherCodeInput: "[name='code']",
discountRadioButtons: "[name='discountType']",
percentageDiscountRadioButton: "[name='discountType'][value='PERCENTAGE']",
fixedDiscountRadioButton: "[name='discountType'][value='FIXED']",
shippingDiscountRadioButton: "[name='discountType'][value='SHIPPING']",
discountValueInputs: "[name='value']"
};

View file

@ -1,5 +1,6 @@
export const BUTTON_SELECTORS = {
back: '[data-test="back"]',
submit: '[data-test="submit"]',
confirm: '[data-test="button-bar-confirm"]',
checkbox: "[type='checkbox']"
};

View file

@ -7,11 +7,11 @@ import {
assignProducts,
createSale,
discountOptions
} from "../../steps/salesSteps";
} from "../../steps/discounts/salesSteps";
import { urlList } from "../../url/urlList";
import * as channelsUtils from "../../utils/channelsUtils";
import { deleteSalesStartsWith } from "../../utils/discounts/salesUtils";
import * as productsUtils from "../../utils/productsUtils";
import { deleteSalesStartsWith } from "../../utils/salesUtils";
import {
createShipping,
deleteShippingStartsWith

View file

@ -0,0 +1,172 @@
// <reference types="cypress" />
import faker from "faker";
import {
createVoucher,
discountOptions
} from "../../steps/discounts/vouchersSteps";
import { urlList } from "../../url/urlList";
import * as channelsUtils from "../../utils/channelsUtils";
import { deleteVouchersStartsWith } from "../../utils/discounts/vouchersUtils";
import { createCheckoutWithVoucher } from "../../utils/ordersUtils";
import * as productsUtils from "../../utils/productsUtils";
import {
createShipping,
deleteShippingStartsWith
} from "../../utils/shippingUtils";
describe("Vouchers discounts", () => {
const startsWith = "Cy-";
const productPrice = 100;
const shippingPrice = 100;
let defaultChannel;
let productType;
let attribute;
let category;
let shippingMethod;
let variants;
let address;
before(() => {
cy.clearSessionData().loginUserViaRequest();
channelsUtils.deleteChannelsStartsWith(startsWith);
productsUtils.deleteProductsStartsWith(startsWith);
deleteShippingStartsWith(startsWith);
deleteVouchersStartsWith(startsWith);
const name = `${startsWith}${faker.random.number()}`;
productsUtils
.createTypeAttributeAndCategoryForProduct(name)
.then(
({
productType: productTypeResp,
attribute: attributeResp,
category: categoryResp
}) => {
productType = productTypeResp;
attribute = attributeResp;
category = categoryResp;
channelsUtils.getDefaultChannel();
}
)
.then(channel => {
defaultChannel = channel;
cy.fixture("addresses");
})
.then(addresses => {
address = addresses.plAddress;
createShipping({
channelId: defaultChannel.id,
name,
address,
price: shippingPrice
});
})
.then(({ shippingMethod: shippingMethodResp, warehouse: warehouse }) => {
shippingMethod = shippingMethodResp;
productsUtils.createProductInChannel({
name,
channelId: defaultChannel.id,
warehouseId: warehouse.id,
productTypeId: productType.id,
attributeId: attribute.id,
categoryId: category.id,
price: productPrice
});
})
.then(({ variants: variantsResp }) => (variants = variantsResp));
});
beforeEach(() => {
cy.clearSessionData().loginUserViaRequest();
cy.visit(urlList.vouchers);
});
it("should create percentage voucher", () => {
const voucherCode = `${startsWith}${faker.random.number()}`;
const voucherValue = 50;
createVoucher({
voucherCode,
voucherValue,
discountOption: discountOptions.PERCENTAGE,
channelName: defaultChannel.name
});
createCheckoutForCreatedVoucher(voucherCode)
.its("checkout.totalPrice.gross.amount")
.then(amount => {
const expectedAmount =
(productPrice * voucherValue) / 100 + shippingPrice;
expect(amount).to.be.eq(expectedAmount);
});
});
it("should create fixed price voucher", () => {
const voucherCode = `${startsWith}${faker.random.number()}`;
const voucherValue = 50;
createVoucher({
voucherCode,
voucherValue,
discountOption: discountOptions.FIXED,
channelName: defaultChannel.name
});
createCheckoutForCreatedVoucher(voucherCode)
.its("checkout.totalPrice.gross.amount")
.then(amount => {
const expectedAmount = productPrice + shippingPrice - voucherValue;
expect(amount).to.be.eq(expectedAmount);
});
});
// Test should pass after fixing - SALEOR-1629 bug
xit("should create free shipping voucher", () => {
const voucherCode = `${startsWith}${faker.random.number()}`;
createVoucher({
voucherCode,
discountOption: discountOptions.SHIPPING,
channelName: defaultChannel.name
});
createCheckoutForCreatedVoucher(voucherCode)
.its("checkout.totalPrice.gross.amount")
.then(amount => {
const expectedAmount = productPrice;
expect(amount).to.be.eq(expectedAmount);
});
});
it("should create voucher not available for selected channel", () => {
const randomName = `${startsWith}${faker.random.number()}`;
const voucherValue = 50;
channelsUtils
.createChannel({ name: randomName })
.then(channel => {
createVoucher({
voucherCode: randomName,
voucherValue,
discountOption: discountOptions.PERCENTAGE,
channelName: channel.name
});
createCheckoutForCreatedVoucher(randomName);
})
.then(resp => {
const errorField = resp.checkoutErrors[0].field;
expect(errorField).to.be.eq("promoCode");
});
});
function createCheckoutForCreatedVoucher(voucherCode) {
return createCheckoutWithVoucher({
channelSlug: defaultChannel.slug,
variantsList: variants,
address,
shippingMethodId: shippingMethod.id,
voucherCode,
auth: "token"
});
}
});

View file

@ -1,7 +1,9 @@
import { ADD_CHANNEL_FORM_SELECTORS } from "../elements/channels/add-channel-form-selectors";
import { CHANNEL_FORM_SELECTORS } from "../elements/channels/channel-form-selectors";
import { CHANNELS_SELECTORS } from "../elements/channels/channels-selectors";
import { MENAGE_CHANNEL_AVAILABILITY } from "../elements/channels/menage-channel-availability";
import { HEADER_SELECTORS } from "../elements/header/header-selectors";
import { BUTTON_SELECTORS } from "../elements/shared/button-selectors";
export function createChannelByView(name, currency, slug = name) {
cy.get(CHANNELS_SELECTORS.createChannelButton)
@ -36,3 +38,15 @@ export function selectChannelInHeader(channelName) {
.contains(channelName)
.click();
}
export function selectChannelInDetailsPages(channelName) {
cy.get(MENAGE_CHANNEL_AVAILABILITY.availableManageButton)
.click()
.get(MENAGE_CHANNEL_AVAILABILITY.allChannelsInput)
.click()
.get(MENAGE_CHANNEL_AVAILABILITY.channelsAvailabilityForm)
.contains(channelName)
.click()
.get(MENAGE_CHANNEL_AVAILABILITY.dialog)
.find(BUTTON_SELECTORS.submit)
.click();
}

View file

@ -1,8 +1,8 @@
import { ASSIGN_PRODUCTS_SELECTORS } from "../elements/catalog/assign-products";
import { MENAGE_CHANNEL_AVAILABILITY } from "../elements/channels/menage-channel-availability";
import { SALES_SELECTORS } from "../elements/discounts/sales";
import { BUTTON_SELECTORS } from "../elements/shared/button-selectors";
import { formatDate } from "../support/formatDate";
import { ASSIGN_PRODUCTS_SELECTORS } from "../../elements/catalog/assign-products";
import { SALES_SELECTORS } from "../../elements/discounts/sales";
import { BUTTON_SELECTORS } from "../../elements/shared/button-selectors";
import { formatDate } from "../../support/formatDate";
import { selectChannelInDetailsPages } from "../channelsSteps";
export const discountOptions = {
PERCENTAGE: SALES_SELECTORS.percentageOption,
@ -22,17 +22,9 @@ export function createSale({
.get(SALES_SELECTORS.nameInput)
.type(saleName)
.get(discountOption)
.click()
.get(MENAGE_CHANNEL_AVAILABILITY.availableManageButton)
.click()
.get(MENAGE_CHANNEL_AVAILABILITY.allChannelsInput)
.click()
.get(MENAGE_CHANNEL_AVAILABILITY.channelsAvailabilityForm)
.contains(channelName)
.click()
.get(BUTTON_SELECTORS.submit)
.click()
.get(SALES_SELECTORS.discountValue)
.click();
selectChannelInDetailsPages(channelName);
cy.get(SALES_SELECTORS.discountValue)
.type(discountValue)
.get(SALES_SELECTORS.startDateInput)
.type(todaysDate);

View file

@ -0,0 +1,27 @@
import { VOUCHERS_SELECTORS } from "../../elements/discounts/vouchers";
import { BUTTON_SELECTORS } from "../../elements/shared/button-selectors";
import { selectChannelInDetailsPages } from "../channelsSteps";
export const discountOptions = {
PERCENTAGE: VOUCHERS_SELECTORS.percentageDiscountRadioButton,
FIXED: VOUCHERS_SELECTORS.fixedDiscountRadioButton,
SHIPPING: VOUCHERS_SELECTORS.shippingDiscountRadioButton
};
export function createVoucher({
voucherCode,
voucherValue,
discountOption,
channelName
}) {
cy.get(VOUCHERS_SELECTORS.createVoucherButton).click();
selectChannelInDetailsPages(channelName);
cy.get(VOUCHERS_SELECTORS.voucherCodeInput)
.type(voucherCode)
.get(discountOption)
.click();
if (discountOption !== discountOptions.SHIPPING) {
cy.get(VOUCHERS_SELECTORS.discountValueInputs).type(voucherValue);
}
cy.get(BUTTON_SELECTORS.confirm).click();
}

View file

@ -1,17 +1,17 @@
Cypress.Commands.add(
"handleDeleteElement",
(element, deleteFunction, startsWith) => {
if (element.node.name.includes(startsWith)) {
(element, deleteFunction, startsWith, name) => {
if (element.node[name].includes(startsWith)) {
deleteFunction(element.node.id);
}
}
);
Cypress.Commands.add(
"deleteElementsStartsWith",
(deleteFunction, getFunction, startsWith, name) => {
(deleteFunction, getFunction, startsWith, name = "name") => {
getFunction(100, startsWith).then(elements => {
elements.forEach(element => {
cy.handleDeleteElement(element, deleteFunction, startsWith);
cy.handleDeleteElement(element, deleteFunction, startsWith, name);
});
});
}

View file

@ -8,6 +8,7 @@ export const urlList = {
products: "products/",
warehouses: "warehouses/",
sales: "discounts/sales/",
collections: "collections/"
collections: "collections/",
vouchers: "discounts/vouchers/"
};
export const productDetailsUrl = productId => `${urlList.products}${productId}`;

View file

@ -1,10 +1,5 @@
import { deleteCollection, getCollections } from "../apiRequests/Collections";
export function deleteCollectionsStartsWith(startsWith) {
cy.deleteElementsStartsWith(
deleteCollection,
getCollections,
startsWith,
"collection"
);
cy.deleteElementsStartsWith(deleteCollection, getCollections, startsWith);
}

View file

@ -0,0 +1,5 @@
import { deleteSale, getSales } from "../../apiRequests/Discounts/Sales";
export function deleteSalesStartsWith(startsWith) {
cy.deleteElementsStartsWith(deleteSale, getSales, startsWith);
}

View file

@ -0,0 +1,8 @@
import {
deleteVouchers,
getVouchers
} from "../../apiRequests/Discounts/Vouchers";
export function deleteVouchersStartsWith(startsWith) {
cy.deleteElementsStartsWith(deleteVouchers, getVouchers, startsWith, "code");
}

View file

@ -8,7 +8,7 @@ export function createWaitingForCaptureOrder(
shippingMethodId
) {
let checkout;
return createCheckout(channelSlug, email, variantsList)
return createCheckout({ channelSlug, email, variantsList })
.then(checkoutResp => {
checkout = checkoutResp;
checkoutRequest.addShippingMethod(checkout.id, shippingMethodId);
@ -17,6 +17,27 @@ export function createWaitingForCaptureOrder(
.then(() => checkoutRequest.completeCheckout(checkout.id))
.then(() => checkout);
}
export function createCheckoutWithVoucher({
channelSlug,
email = "email@example.com",
variantsList,
address,
shippingMethodId,
voucherCode,
auth
}) {
let checkout;
return createCheckout({ channelSlug, email, variantsList, address, auth })
.then(checkoutResp => {
checkout = checkoutResp;
checkoutRequest.addShippingMethod(checkout.id, shippingMethodId);
})
.then(() => {
checkoutRequest.addVoucher(checkout.id, voucherCode);
})
.its("body.data.checkoutAddPromoCode");
}
export function createReadyToFulfillOrder(
customerId,
shippingMethodId,
@ -60,9 +81,22 @@ export function createDraftOrder(customerId, shippingMethodId, channelId) {
.createDraftOrder(customerId, shippingMethodId, channelId)
.its("body.data.draftOrderCreate.order");
}
export function createCheckout(channelSlug, email, variantsList) {
export function createCheckout({
channelSlug,
email,
variantsList,
address,
auth
}) {
return checkoutRequest
.createCheckout(channelSlug, email, 1, variantsList)
.createCheckout({
channelSlug,
email,
productQuantity: 1,
variantsList,
address,
auth
})
.its("body.data.checkoutCreate.checkout");
}
export function addPayment(checkoutId) {

View file

@ -109,19 +109,16 @@ export function deleteProductsStartsWith(startsWith) {
cy.deleteElementsStartsWith(
productRequest.deleteProductType,
productRequest.getProductTypes,
startsWith,
"productType"
startsWith
);
cy.deleteElementsStartsWith(
attributeRequest.deleteAttribute,
attributeRequest.getAttributes,
startsWith,
"attributes"
startsWith
);
cy.deleteElementsStartsWith(
categoryRequest.deleteCategory,
categoryRequest.getCategories,
startsWith,
"categories"
startsWith
);
}

View file

@ -1,5 +0,0 @@
import { deleteSale, getSales } from "../apiRequests/Sales";
export function deleteSalesStartsWith(startsWith) {
cy.deleteElementsStartsWith(deleteSale, getSales, startsWith, "sales");
}

View file

@ -46,13 +46,11 @@ export function deleteShippingStartsWith(startsWith) {
cy.deleteElementsStartsWith(
shippingMethodRequest.deleteShippingZone,
shippingMethodRequest.getShippingZones,
startsWith,
"shippingZONE"
startsWith
);
cy.deleteElementsStartsWith(
warehouseRequest.deleteWarehouse,
warehouseRequest.getWarehouses,
startsWith,
"Warehouse"
startsWith
);
}

View file

@ -46,7 +46,11 @@ const VoucherInfo = ({
title={intl.formatMessage(commonMessages.generalInformations)}
toolbar={
variant === "create" && (
<Button color="primary" onClick={onGenerateCode}>
<Button
color="primary"
onClick={onGenerateCode}
data-test-id="generate-code"
>
<FormattedMessage
defaultMessage="Generate Code"
description="voucher code, button"

View file

@ -53,7 +53,12 @@ const VoucherListPage: React.FC<VoucherListPageProps> = ({
return (
<Container>
<PageHeader title={intl.formatMessage(sectionNames.vouchers)}>
<Button onClick={onAdd} variant="contained" color="primary">
<Button
onClick={onAdd}
variant="contained"
color="primary"
data-test-id="create-voucher"
>
<FormattedMessage
defaultMessage="Create voucher"
description="button"

View file

@ -81428,6 +81428,7 @@ exports[`Storyshots Views / Discounts / Voucher create default 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="generate-code"
tabindex="0"
type="button"
>
@ -82844,6 +82845,7 @@ exports[`Storyshots Views / Discounts / Voucher create form errors 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="generate-code"
tabindex="0"
type="button"
>
@ -90466,6 +90468,7 @@ exports[`Storyshots Views / Discounts / Voucher list default 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-contained-id MuiButton-containedPrimary-id"
data-test-id="create-voucher"
tabindex="0"
type="button"
>
@ -90999,6 +91002,7 @@ exports[`Storyshots Views / Discounts / Voucher list loading 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-contained-id MuiButton-containedPrimary-id"
data-test-id="create-voucher"
tabindex="0"
type="button"
>
@ -91477,6 +91481,7 @@ exports[`Storyshots Views / Discounts / Voucher list no channels 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-contained-id MuiButton-containedPrimary-id"
data-test-id="create-voucher"
tabindex="0"
type="button"
>
@ -92010,6 +92015,7 @@ exports[`Storyshots Views / Discounts / Voucher list no data 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-contained-id MuiButton-containedPrimary-id"
data-test-id="create-voucher"
tabindex="0"
type="button"
>