Saleor 2696 tests for product create (#1026)

* test for product create

* tests for creating product

* create new expect product info utils file
This commit is contained in:
Karolina 2021-04-01 14:33:36 +02:00 committed by GitHub
parent c1159861a9
commit 114476d615
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
41 changed files with 505 additions and 199 deletions

View file

@ -132,7 +132,12 @@ export function createVariant({
return cy.sendRequestWithQuery(mutation);
}
export function createTypeProduct(name, attributeId, slug = name) {
export function createTypeProduct(
name,
attributeId,
hasVariants = true,
slug = name
) {
const mutation = `mutation{
productTypeCreate(input: {
name: "${name}"
@ -140,6 +145,7 @@ export function createTypeProduct(name, attributeId, slug = name) {
isShippingRequired: true
productAttributes: "${attributeId}"
variantAttributes: "${attributeId}"
hasVariants: ${hasVariants}
}){
productErrors{
field

View file

@ -0,0 +1,4 @@
export const PRICE_LIST = {
priceInput: "[name*='channel-price']",
costPriceInput: "[name*='channel-costPrice']"
};

View file

@ -0,0 +1,16 @@
export const PRODUCT_DETAILS = {
productNameInput: "[name='name']",
productTypeInput: "[data-test='product-type']",
categoryInput: "[data-test='category']",
categoryItem: "[data-test='singleautocomplete-select-option']",
collectionInput: "[data-test='collections']",
autocompleteDropdown: "[data-test='autocomplete-dropdown']",
firstCategoryItem: "#downshift-0-item-0",
visibleRadioBtn: "[name='isPublished']",
confirmationMsg: "[data-test='notification-success']",
channelAvailabilityItem: "[data-test='channel-availability-item']",
addVariantsButton: "[data-test*='button-add-variant']",
descriptionInput: "[data-test-id='description']",
ratingInput: "[name='rating']",
skuInput: "[name='sku']"
};

View file

@ -1,33 +0,0 @@
export const PRODUCTS_SELECTORS = {
productsList: "[data-test-id][data-test='id']",
products: "[data-test='submenu-item-label'][data-test-id='products']",
createProductBtn: "[data-test='add-product']",
productNameInput: "[name='name']",
productTypeInput: "[data-test='product-type']",
categoryInput: "[data-test='category']",
categoryItem: "[data-test='singleautocomplete-select-option']",
autocompleteDropdown: "[data-test='autocomplete-dropdown']",
firstCategoryItem: "#downshift-0-item-0",
visibleRadioBtn: "[name='isPublished']",
saveBtn: "[data-test='button-bar-confirm']",
confirmationMsg: "[data-test='notification-success']",
channelAvailabilityItem: "[data-test='channel-availability-item']",
searchProducts: "[placeholder='Search Products...']",
availableManageButton:
"[data-test-id='channels-availiability-manage-button']",
channelsAvailabilityForm:
"[data-test-id='manage-products-channels-availiability-list']",
channelAvailabilityColumn:
"[data-test='availability'][data-test-availability='true']",
channelAvailabilityList: "ul[role='menu']",
goBackButton: "[data-test-id='app-header-back-button']",
assignedChannels: "[data-test='channel-availability-item']",
publishedRadioButton: "[role=radiogroup]",
addVariantsButton: "[data-test*='button-add-variant']",
publishedRadioButtons: "[name*='isPublished']",
availableForPurchaseRadioButtons: "[name*='isAvailableForPurchase']",
radioButtonsValueTrue: "[value='true']",
radioButtonsValueFalse: "[value='false']",
visibleInListingsButton: "[name*='visibleInListings']",
emptyProductRow: "[class*='Skeleton']"
};

View file

@ -0,0 +1,6 @@
export const PRODUCTS_LIST = {
productsList: "[data-test-id][data-test='id']",
createProductBtn: "[data-test='add-product']",
searchProducts: "[placeholder='Search Products...']",
emptyProductRow: "[class*='Skeleton']"
};

View file

@ -2,8 +2,6 @@ export const VARIANTS_SELECTORS = {
attributeCheckbox: "[name*='value:']",
valueContainer: "[data-test-id='value-container']",
nextButton: "[class*='MuiButton-containedPrimary']",
priceInput: "[name*='channel-price']",
costPriceInput: "[name*='channel-costPrice']",
warehouseCheckboxes: "[name*='warehouse:']",
skuInput: "input[class*='MuiInputBase'][type='text']",
attributeSelector: "[data-test='attribute-value']",

View file

@ -0,0 +1,10 @@
export const AVAILABLE_CHANNELS_FORM = {
menageChannelsButton: "[data-test-id='channels-availiability-manage-button']",
assignedChannels: "[data-test='channel-availability-item']",
publishedRadioButtons: "[name*='isPublished']",
availableForPurchaseRadioButtons: "[name*='isAvailableForPurchase']",
radioButtonsValueTrue: "[value='true']",
radioButtonsValueFalse: "[value='false']",
visibleInListingsButton: "[name*='visibleInListings']",
availableChannel: "[data-test='channel-availability-item']"
};

View file

@ -1,10 +0,0 @@
export const MENAGE_CHANNEL_AVAILABILITY_FORM = {
channelsMenageButton: "[data-test-id='channels-availiability-manage-button']",
allChannelsCheckbox: "[name='allChannels']",
channelRow: "[data-test-id='channel-row']",
channelCheckbox: "[class*='MuiCheckbox']",
channelsAvailabilityItem: "[data-test='channel-availability-item']",
publishedCheckbox: "[name='isPublished']",
radioButtonsValueTrue: "[value='true']",
radioButtonsValueFalse: "[value='false']"
};

View file

@ -1,17 +0,0 @@
export const MENAGE_CHANNEL_AVAILABILITY = {
availableManageButton:
"[data-test-id='channels-availiability-manage-button']",
channelsAvailabilityForm:
"[data-test-id='manage-products-channels-availiability-list']",
channelAvailabilityColumn:
"[data-test='availability'][data-test-availability='true']",
channelAvailabilityList: "ul[role='menu']",
assignedChannels: "[data-test='channel-availability-item']",
publishedRadioButtons: "[name*='isPublished']",
availableForPurchaseRadioButtons: "[name*='isAvailableForPurchase']",
radioButtonsValueTrue: "[value='true']",
radioButtonsValueFalse: "[value='false']",
visibleInListingsButton: "[name*='visibleInListings']",
allChannelsInput: "[name='allChannels']",
dialog: "[role='dialog']"
};

View file

@ -0,0 +1,8 @@
export const SELECT_CHANNELS_TO_ASSIGN = {
listOfChannels:
"[data-test-id='manage-products-channels-availiability-list']",
allChannelsCheckbox: "[name='allChannels']",
selectChannelsForm: "[role='dialog']",
channelRow: "[data-test-id='channel-row']",
channelCheckbox: "[class*='MuiCheckbox']"
};

View file

@ -2,5 +2,7 @@ export const BUTTON_SELECTORS = {
back: '[data-test="back"]',
submit: '[data-test="submit"]',
confirm: '[data-test="button-bar-confirm"]',
checkbox: "[type='checkbox']"
goBackButton: "[data-test-id='app-header-back-button']",
checkbox: "[type='checkbox']",
selectOption: "[data-test*='select-option']"
};

View file

@ -0,0 +1,8 @@
export const METADATA_FORM = {
metadataForm: "[data-test='metadataEditor'][data-test-is-private='false']",
privateMetadataForm:
"[data-test='metadataEditor'][data-test-is-private='true']",
addFieldButton: "[data-test='addField']",
nameInput: "[name*='name']",
valueField: "[name*='value']"
};

View file

@ -0,0 +1,6 @@
export const SEO_FORM = {
editSeoSettings: "[data-test-id='edit-seo']",
slugInput: "[name='slug']",
titleInput: "[name='seoTitle']",
descriptionInput: "[name='seoDescription']"
};

View file

@ -3,10 +3,12 @@ import faker from "faker";
import { createChannel } from "../apiRequests/Channels";
import { LEFT_MENU_SELECTORS } from "../elements/account/left-menu/left-menu-selectors";
import { PRODUCTS_SELECTORS } from "../elements/catalog/products/product-selectors";
import { PRODUCTS_LIST } from "../elements/catalog/products/products-list";
import { ADD_CHANNEL_FORM_SELECTORS } from "../elements/channels/add-channel-form-selectors";
import { AVAILABLE_CHANNELS_FORM } from "../elements/channels/available-channels-form";
import { CHANNEL_FORM_SELECTORS } from "../elements/channels/channel-form-selectors";
import { CHANNELS_SELECTORS } from "../elements/channels/channels-selectors";
import { SELECT_CHANNELS_TO_ASSIGN } from "../elements/channels/select-channels-to-assign";
import { CONFIGURATION_SELECTORS } from "../elements/configuration/configuration-selectors";
import { HEADER_SELECTORS } from "../elements/header/header-selectors";
import { DRAFT_ORDER_SELECTORS } from "../elements/orders/draft-order-selectors";
@ -65,12 +67,12 @@ describe("Channels", () => {
cy.addAliasToGraphRequest("InitialProductFilterData");
cy.visit(urlList.products);
cy.wait("@InitialProductFilterData");
cy.get(PRODUCTS_SELECTORS.productsList)
cy.get(PRODUCTS_LIST.productsList)
.first()
.click()
.get(PRODUCTS_SELECTORS.availableManageButton)
.get(AVAILABLE_CHANNELS_FORM.menageChannelsButton)
.click()
.get(PRODUCTS_SELECTORS.channelsAvailabilityForm)
.get(SELECT_CHANNELS_TO_ASSIGN.listOfChannels)
.contains(randomChannel);
});

View file

@ -11,7 +11,7 @@ import {
import { urlList } from "../url/urlList";
import * as channelsUtils from "../utils/channelsUtils";
import { deleteCollectionsStartsWith } from "../utils/collectionsUtils";
import * as productsUtils from "../utils/productsUtils";
import * as productsUtils from "../utils/products/productsUtils";
import { deleteShippingStartsWith } from "../utils/shippingUtils";
import {
isCollectionVisible,

View file

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

View file

@ -9,7 +9,7 @@ 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 * as productsUtils from "../../utils/products/productsUtils";
import {
createShipping,
deleteShippingStartsWith

View file

@ -13,7 +13,7 @@ import {
createReadyToFulfillOrder,
createWaitingForCaptureOrder
} from "../../utils/ordersUtils";
import * as productsUtils from "../../utils/productsUtils";
import * as productsUtils from "../../utils/products/productsUtils";
import * as shippingUtils from "../../utils/shippingUtils";
// <reference types="cypress" />

View file

@ -11,7 +11,7 @@ import { selectChannelInPicker } from "../../steps/channelsSteps";
import { finalizeDraftOrder } from "../../steps/draftOrderSteps";
import { urlList } from "../../url/urlList";
import { getDefaultChannel } from "../../utils/channelsUtils";
import * as productsUtils from "../../utils/productsUtils";
import * as productsUtils from "../../utils/products/productsUtils";
import {
createShipping,
deleteShippingStartsWith

View file

@ -11,7 +11,7 @@ import { finalizeDraftOrder } from "../../steps/draftOrderSteps";
import { urlList } from "../../url/urlList";
import { getDefaultChannel } from "../../utils/channelsUtils";
import { createOrder } from "../../utils/ordersUtils";
import * as productsUtils from "../../utils/productsUtils";
import * as productsUtils from "../../utils/products/productsUtils";
import {
createShipping,
deleteShippingStartsWith

View file

@ -0,0 +1,123 @@
// <reference types="cypress" />
import faker from "faker";
import { PRODUCT_DETAILS } from "../../elements/catalog/products/product-details";
import { PRODUCTS_LIST } from "../../elements/catalog/products/products-list";
import { BUTTON_SELECTORS } from "../../elements/shared/button-selectors";
import { metadataForms } from "../../steps/catalog/metadataSteps";
import {
fillUpPriceList,
priceInputLists
} from "../../steps/catalog/products/priceList";
import { fillUpCommonFieldsForProductType } from "../../steps/catalog/products/productSteps";
import { selectChannelInDetailsPages } from "../../steps/channelsSteps";
import { urlList } from "../../url/urlList";
import {
expectCorrectProductInformation,
expectCorrectProductVariantInformation
} from "../../utils/products/checkProductInfo";
import * as productUtils from "../../utils/products/productsUtils";
describe("Create product", () => {
const startsWith = "Cy-";
const name = `${startsWith}${faker.random.number()}`;
const generalInfo = {
name: `${startsWith}${faker.random.number()}`,
description: faker.lorem.sentence(),
rating: 2
};
const seo = {
title: "testTitle",
description: generalInfo.description
};
const metadata = {
public: {
metadataForm: metadataForms.public,
name: "metadataName",
value: "metadataValue"
},
private: {
metadataForm: metadataForms.private,
name: "privateMetadataName",
value: "privateMetadataValue"
}
};
let attribute;
before(() => {
cy.clearSessionData().loginUserViaRequest();
productUtils.deleteProductsStartsWith(startsWith);
productUtils.createAttribute(name).then(attributeResp => {
attribute = attributeResp;
});
});
beforeEach(() => {
cy.clearSessionData().loginUserViaRequest();
cy.visit(urlList.products)
.get(PRODUCTS_LIST.createProductBtn)
.click();
});
it("should create product with variants", () => {
const randomName = `${startsWith}${faker.random.number()}`;
productUtils.createTypeProduct(randomName, attribute.id);
seo.slug = randomName;
const productData = {
generalInfo,
seo,
metadata,
productOrganization: { productType: randomName },
attribute
};
fillUpCommonFieldsForProductType(productData).then(
productOrgResp => (productData.productOrganization = productOrgResp)
);
cy.addAliasToGraphRequest("ProductDetails");
cy.get(BUTTON_SELECTORS.confirm).click();
cy.wait("@ProductDetails");
cy.get(PRODUCT_DETAILS.confirmationMsg).should("be.visible");
cy.get("@ProductDetails")
.its("response.body")
.then(resp => {
const productResp = resp.find(element => element.data.product).data
.product;
expectCorrectProductInformation(productResp, productData);
});
});
it("should create product without variants", () => {
const prices = { sellingPrice: 6, costPrice: 3 };
const randomName = `${startsWith}${faker.random.number()}`;
seo.slug = randomName;
productUtils.createTypeProduct(randomName, attribute.id, false);
const productData = {
generalInfo,
seo,
metadata,
productOrganization: { productType: randomName },
attribute
};
fillUpCommonFieldsForProductType(productData).then(
productOrgResp => (productData.productOrganization = productOrgResp)
);
selectChannelInDetailsPages();
fillUpPriceList(prices.sellingPrice);
fillUpPriceList(prices.costPrice, priceInputLists.costPrice);
cy.get(PRODUCT_DETAILS.skuInput).type(randomName);
cy.addAliasToGraphRequest("ProductDetails");
cy.get(BUTTON_SELECTORS.confirm).click();
cy.wait("@ProductDetails");
cy.get(PRODUCT_DETAILS.confirmationMsg).should("be.visible");
cy.get("@ProductDetails")
.its("response.body")
.then(resp => {
const productResp = resp.find(element => element.data.product).data
.product;
expectCorrectProductInformation(productResp, productData);
expectCorrectProductVariantInformation(
productResp.variants,
randomName,
prices
);
});
});
});

View file

@ -1,10 +1,10 @@
import faker from "faker";
import { getProductDetails } from "../../../apiRequests/storeFront/ProductDetails";
import { updateProductIsAvailableForPurchase } from "../../../steps/products/productSteps";
import { updateProductIsAvailableForPurchase } from "../../../steps/catalog/products/productSteps";
import { productDetailsUrl } from "../../../url/urlList";
import { getDefaultChannel } from "../../../utils/channelsUtils";
import * as productsUtils from "../../../utils/productsUtils";
import * as productsUtils from "../../../utils/products/productsUtils";
import * as shippingUtils from "../../../utils/shippingUtils";
import { isProductAvailableForPurchase } from "../../../utils/storeFront/storeFrontProductUtils";

View file

@ -1,10 +1,10 @@
import faker from "faker";
import { getProductDetails } from "../../../apiRequests/storeFront/ProductDetails";
import { updateProductPublish } from "../../../steps/products/productSteps";
import { updateProductPublish } from "../../../steps/catalog/products/productSteps";
import { productDetailsUrl } from "../../../url/urlList";
import { getDefaultChannel } from "../../../utils/channelsUtils";
import * as productsUtils from "../../../utils/productsUtils";
import * as productsUtils from "../../../utils/products/productsUtils";
import { isProductVisible } from "../../../utils/storeFront/storeFrontProductUtils";
// <reference types="cypress" />

View file

@ -1,10 +1,10 @@
import faker from "faker";
import { searchInShop } from "../../../apiRequests/storeFront/Search";
import { updateProductVisibleInListings } from "../../../steps/products/productSteps";
import { updateProductVisibleInListings } from "../../../steps/catalog/products/productSteps";
import { productDetailsUrl } from "../../../url/urlList";
import { getDefaultChannel } from "../../../utils/channelsUtils";
import * as productsUtils from "../../../utils/productsUtils";
import * as productsUtils from "../../../utils/products/productsUtils";
import { isProductVisibleInSearchResult } from "../../../utils/storeFront/storeFrontProductUtils";
// <reference types="cypress" />

View file

@ -1,43 +0,0 @@
// <reference types="cypress" />
import { PRODUCTS_SELECTORS } from "../../elements/catalog/products/product-selectors";
import { urlList } from "../../url/urlList";
describe("Products", () => {
beforeEach(() => {
cy.clearSessionData().loginUserViaRequest();
});
it("should add new visible product", () => {
cy.visit(urlList.products)
.get(PRODUCTS_SELECTORS.createProductBtn)
.click()
.get(PRODUCTS_SELECTORS.productNameInput)
.click()
.type("Visible test product")
.get(PRODUCTS_SELECTORS.productTypeInput)
.click()
.get(PRODUCTS_SELECTORS.autocompleteDropdown) // trying to fill autocomplete before dropdown will cause error
.get(PRODUCTS_SELECTORS.productTypeInput)
.click()
.type("Cushion")
.get(PRODUCTS_SELECTORS.categoryItem)
.should("have.length", 1)
.get(PRODUCTS_SELECTORS.firstCategoryItem)
.click()
.get(PRODUCTS_SELECTORS.categoryInput)
.click()
.get(PRODUCTS_SELECTORS.categoryItem)
.first()
.click()
.get(PRODUCTS_SELECTORS.channelAvailabilityItem)
.first()
.click()
.get(PRODUCTS_SELECTORS.visibleRadioBtn)
.first()
.click()
.get(PRODUCTS_SELECTORS.saveBtn)
.click()
.get(PRODUCTS_SELECTORS.confirmationMsg)
.contains("Product created");
});
});

View file

@ -8,13 +8,13 @@ import {
import {
createFirstVariant,
createVariant
} from "../../steps/products/VariantsSteps";
} from "../../steps/catalog/products/VariantsSteps";
import { urlList } from "../../url/urlList";
import {
deleteChannelsStartsWith,
getDefaultChannel
} from "../../utils/channelsUtils";
import * as productUtils from "../../utils/productsUtils";
import * as productUtils from "../../utils/products/productsUtils";
import * as shippingUtils from "../../utils/shippingUtils";
import { getProductVariants } from "../../utils/storeFront/storeFrontProductUtils";

View file

@ -0,0 +1,18 @@
import { METADATA_FORM } from "../../elements/shared/metadata/metadata-form";
export const metadataForms = {
private: METADATA_FORM.privateMetadataForm,
public: METADATA_FORM.metadataForm
};
export function addMetadataField({ metadataForm, name, value }) {
cy.get(metadataForm)
.find(METADATA_FORM.addFieldButton)
.click()
.get(metadataForm)
.find(METADATA_FORM.nameInput)
.type(name)
.get(metadataForm)
.find(METADATA_FORM.valueField)
.type(value);
}

View file

@ -1,18 +1,17 @@
import { PRODUCTS_SELECTORS } from "../../elements/catalog/products/product-selectors";
import { VARIANTS_SELECTORS } from "../../elements/catalog/variants-selectors";
import { PRICE_LIST } from "../../../elements/catalog/products/price-list";
import { PRODUCT_DETAILS } from "../../../elements/catalog/products/product-details";
import { VARIANTS_SELECTORS } from "../../../elements/catalog/products/variants-selectors";
import { fillUpPriceList } from "./priceList";
export function createFirstVariant({ sku, warehouseId, price, attribute }) {
cy.get(PRODUCTS_SELECTORS.addVariantsButton).click();
cy.get(PRODUCT_DETAILS.addVariantsButton).click();
cy.get(VARIANTS_SELECTORS.valueContainer)
.contains(attribute)
.find(VARIANTS_SELECTORS.attributeCheckbox)
.click()
.get(VARIANTS_SELECTORS.nextButton)
.click()
.get(VARIANTS_SELECTORS.priceInput)
.each($priceInput => {
cy.wrap($priceInput).type(price);
});
.click();
fillUpPriceList(price);
cy.get(`[name*='${warehouseId}']`)
.click()
.get(VARIANTS_SELECTORS.nextButton)
@ -30,16 +29,16 @@ export function createVariant({
price,
costPrice = price
}) {
cy.get(PRODUCTS_SELECTORS.addVariantsButton)
cy.get(PRODUCT_DETAILS.addVariantsButton)
.click()
.get(VARIANTS_SELECTORS.attributeSelector)
.click()
.get(VARIANTS_SELECTORS.attributeOption)
.contains(attributeName)
.click()
.get(VARIANTS_SELECTORS.priceInput)
.get(PRICE_LIST.priceInput)
.type(price)
.get(VARIANTS_SELECTORS.costPriceInput)
.get(PRICE_LIST.costPriceInput)
.type(costPrice)
.get(VARIANTS_SELECTORS.skuInputInAddVariant)
.type(sku)

View file

@ -0,0 +1,14 @@
import { PRICE_LIST } from "../../../elements/catalog/products/price-list";
export const priceInputLists = {
sellingPrice: PRICE_LIST.priceInput,
costPrice: PRICE_LIST.costPriceInput
};
export function fillUpPriceList(
price = 1,
priceTypeInput = priceInputLists.sellingPrice
) {
cy.get(priceTypeInput).each($priceInput => {
cy.wrap($priceInput).type(price);
});
}

View file

@ -0,0 +1,85 @@
import { PRODUCT_DETAILS } from "../../../elements/catalog/products/product-details";
import { AVAILABLE_CHANNELS_FORM } from "../../../elements/channels/available-channels-form";
import { BUTTON_SELECTORS } from "../../../elements/shared/button-selectors";
import { fillAutocompleteSelect } from "../../shared/autocompleteSelect";
import { addMetadataField } from "../metadataSteps";
import { editSeoSettings } from "../seoSteps";
const valueTrue = AVAILABLE_CHANNELS_FORM.radioButtonsValueTrue;
const valueFalse = AVAILABLE_CHANNELS_FORM.radioButtonsValueFalse;
export function updateProductIsAvailableForPurchase(
productUrl,
isAvailableForPurchase
) {
const isAvailableForPurchaseSelector = isAvailableForPurchase
? valueTrue
: valueFalse;
const availableForPurchaseSelector = `${AVAILABLE_CHANNELS_FORM.availableForPurchaseRadioButtons}${isAvailableForPurchaseSelector}`;
updateProductMenageInChannel(productUrl, availableForPurchaseSelector);
}
export function updateProductPublish(productUrl, isPublished) {
const isPublishedSelector = isPublished ? valueTrue : valueFalse;
const publishedSelector = `${AVAILABLE_CHANNELS_FORM.publishedRadioButtons}${isPublishedSelector}`;
updateProductMenageInChannel(productUrl, publishedSelector);
}
export function updateProductVisibleInListings(productUrl) {
updateProductMenageInChannel(
productUrl,
AVAILABLE_CHANNELS_FORM.visibleInListingsButton
);
}
function updateProductMenageInChannel(productUrl, menageSelector) {
cy.visit(productUrl)
.get(AVAILABLE_CHANNELS_FORM.assignedChannels)
.click()
.get(menageSelector)
.click();
cy.addAliasToGraphRequest("ProductChannelListingUpdate");
cy.get(BUTTON_SELECTORS.confirm)
.click()
.wait("@ProductChannelListingUpdate");
}
export function fillUpCommonFieldsForProductType({
generalInfo,
seo,
metadata,
productOrganization
}) {
fillUpProductGeneralInfo(generalInfo);
editSeoSettings(seo);
addMetadataField(metadata.public);
addMetadataField(metadata.private);
return fillUpProductOrganization(productOrganization).then(
productOrgResp => productOrgResp
);
}
export function fillUpProductGeneralInfo({ name, description, rating }) {
cy.get(PRODUCT_DETAILS.productNameInput)
.click()
.type(name)
.get(PRODUCT_DETAILS.descriptionInput)
.type(description)
.get(PRODUCT_DETAILS.ratingInput)
.type(rating);
}
export function fillUpProductOrganization({
productType,
category,
collection
}) {
const organization = {};
return fillAutocompleteSelect(PRODUCT_DETAILS.productTypeInput, productType)
.then(selected => {
organization.productType = selected;
fillAutocompleteSelect(PRODUCT_DETAILS.categoryInput, category);
})
.then(selected => {
organization.category = selected;
fillAutocompleteSelect(PRODUCT_DETAILS.collectionInput, collection);
})
.then(selected => {
organization.collection = selected;
return organization;
});
}

View file

@ -0,0 +1,11 @@
import { SEO_FORM } from "../../elements/shared/seo/seo-form-selectors";
export function editSeoSettings({ slug, title, description }) {
cy.get(SEO_FORM.editSeoSettings)
.click()
.get(SEO_FORM.slugInput)
.type(slug)
.get(SEO_FORM.titleInput)
.type(title)
.get(SEO_FORM.descriptionInput)
.type(description, { delay: 0 });
}

View file

@ -1,7 +1,8 @@
import { ADD_CHANNEL_FORM_SELECTORS } from "../elements/channels/add-channel-form-selectors";
import { AVAILABLE_CHANNELS_FORM } from "../elements/channels/available-channels-form";
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 { SELECT_CHANNELS_TO_ASSIGN } from "../elements/channels/select-channels-to-assign";
import { HEADER_SELECTORS } from "../elements/header/header-selectors";
import { BUTTON_SELECTORS } from "../elements/shared/button-selectors";
@ -39,14 +40,21 @@ export function selectChannelInHeader(channelName) {
.click();
}
export function selectChannelInDetailsPages(channelName) {
cy.get(MENAGE_CHANNEL_AVAILABILITY.availableManageButton)
cy.get(AVAILABLE_CHANNELS_FORM.menageChannelsButton)
.click()
.get(MENAGE_CHANNEL_AVAILABILITY.allChannelsInput)
.click()
.get(MENAGE_CHANNEL_AVAILABILITY.channelsAvailabilityForm)
.contains(channelName)
.click()
.get(MENAGE_CHANNEL_AVAILABILITY.dialog)
.get(SELECT_CHANNELS_TO_ASSIGN.allChannelsCheckbox)
.click();
if (channelName) {
cy.get(SELECT_CHANNELS_TO_ASSIGN.listOfChannels)
.contains(channelName)
.click();
} else {
cy.get(SELECT_CHANNELS_TO_ASSIGN.channelRow)
.first()
.find(SELECT_CHANNELS_TO_ASSIGN.channelCheckbox)
.click();
}
cy.get(SELECT_CHANNELS_TO_ASSIGN.selectChannelsForm)
.find(BUTTON_SELECTORS.submit)
.click();
}

View file

@ -1,31 +1,30 @@
import { COLLECTION_SELECTORS } from "../elements/catalog/collection-selectors";
import { ASSIGN_PRODUCTS_SELECTORS } from "../elements/catalog/products/assign-products-selectors";
import { MENAGE_CHANNEL_AVAILABILITY_FORM } from "../elements/channels/menage-channel-availability-form";
import { AVAILABLE_CHANNELS_FORM } from "../elements/channels/available-channels-form";
import { SELECT_CHANNELS_TO_ASSIGN } from "../elements/channels/select-channels-to-assign";
import { BUTTON_SELECTORS } from "../elements/shared/button-selectors";
export function createCollection(collectionName, isPublished, channel) {
const publishedSelector = isPublished
? MENAGE_CHANNEL_AVAILABILITY_FORM.radioButtonsValueTrue
: MENAGE_CHANNEL_AVAILABILITY_FORM.radioButtonsValueFalse;
? AVAILABLE_CHANNELS_FORM.radioButtonsValueTrue
: AVAILABLE_CHANNELS_FORM.radioButtonsValueFalse;
cy.get(COLLECTION_SELECTORS.createCollectionButton)
.click()
.get(COLLECTION_SELECTORS.nameInput)
.type(collectionName)
.get(MENAGE_CHANNEL_AVAILABILITY_FORM.channelsMenageButton)
.get(AVAILABLE_CHANNELS_FORM.menageChannelsButton)
.click()
.get(MENAGE_CHANNEL_AVAILABILITY_FORM.allChannelsCheckbox)
.get(SELECT_CHANNELS_TO_ASSIGN.allChannelsCheckbox)
.click();
cy.contains(MENAGE_CHANNEL_AVAILABILITY_FORM.channelRow, channel.name)
.find(MENAGE_CHANNEL_AVAILABILITY_FORM.channelCheckbox)
cy.contains(SELECT_CHANNELS_TO_ASSIGN.channelRow, channel.name)
.find(SELECT_CHANNELS_TO_ASSIGN.channelCheckbox)
.click()
.get(BUTTON_SELECTORS.submit)
.click()
.get(MENAGE_CHANNEL_AVAILABILITY_FORM.channelsAvailabilityItem)
.get(AVAILABLE_CHANNELS_FORM.availableChannel)
.click()
.get(
`${MENAGE_CHANNEL_AVAILABILITY_FORM.publishedCheckbox}${publishedSelector}`
)
.get(`${AVAILABLE_CHANNELS_FORM.publishedRadioButtons}${publishedSelector}`)
.click();
cy.addAliasToGraphRequest("CreateCollection");
cy.get(COLLECTION_SELECTORS.saveButton).click();

View file

@ -1,4 +1,4 @@
import { ASSIGN_PRODUCTS_SELECTORS } from "../../elements/catalog/assign-products";
import { ASSIGN_PRODUCTS_SELECTORS } from "../../elements/catalog/products/assign-products";
import { SALES_SELECTORS } from "../../elements/discounts/sales";
import { BUTTON_SELECTORS } from "../../elements/shared/button-selectors";
import { formatDate } from "../../support/formatDate";

View file

@ -1,37 +0,0 @@
import { PRODUCTS_SELECTORS } from "../../elements/catalog/products/product-selectors";
const valueTrue = PRODUCTS_SELECTORS.radioButtonsValueTrue;
const valueFalse = PRODUCTS_SELECTORS.radioButtonsValueFalse;
export function updateProductIsAvailableForPurchase(
productUrl,
isAvailableForPurchase
) {
const isAvailableForPurchaseSelector = isAvailableForPurchase
? valueTrue
: valueFalse;
const availableForPurchaseSelector = `${PRODUCTS_SELECTORS.availableForPurchaseRadioButtons}${isAvailableForPurchaseSelector}`;
updateProductMenageInChannel(productUrl, availableForPurchaseSelector);
}
export function updateProductPublish(productUrl, isPublished) {
const isPublishedSelector = isPublished ? valueTrue : valueFalse;
const publishedSelector = `${PRODUCTS_SELECTORS.publishedRadioButtons}${isPublishedSelector}`;
updateProductMenageInChannel(productUrl, publishedSelector);
}
export function updateProductVisibleInListings(productUrl) {
updateProductMenageInChannel(
productUrl,
PRODUCTS_SELECTORS.visibleInListingsButton
);
}
function updateProductMenageInChannel(productUrl, menageSelector) {
cy.visit(productUrl)
.get(PRODUCTS_SELECTORS.assignedChannels)
.click()
.get(menageSelector)
.click();
cy.addAliasToGraphRequest("ProductChannelListingUpdate");
cy.get(PRODUCTS_SELECTORS.saveBtn)
.click()
.wait("@ProductChannelListingUpdate");
}

View file

@ -0,0 +1,22 @@
import { BUTTON_SELECTORS } from "../../elements/shared/button-selectors";
export function fillAutocompleteSelect(selectSelector, option) {
cy.get(selectSelector)
.click()
.get(BUTTON_SELECTORS.selectOption)
.should("be.visible");
if (option) {
cy.get(selectSelector).type(option);
cy.contains(BUTTON_SELECTORS.selectOption, option).click();
cy.wrap(option).as("option");
} else {
cy.get(BUTTON_SELECTORS.selectOption)
.first()
.invoke("text")
.as("option");
cy.get(BUTTON_SELECTORS.selectOption)
.first()
.click();
}
return cy.get("@option");
}

View file

@ -0,0 +1,63 @@
const { softExpect } = chai;
export function expectCorrectProductInformation(productResp, productData) {
expectCorrectGeneralInformation(productResp, productData.generalInfo);
expectCorrectSeoInfo(productResp, productData.seo);
expectCorrectMetadataInfo(productResp.metadata, productData.metadata.public);
expectCorrectMetadataInfo(
productResp.privateMetadata,
productData.metadata.private
);
expectCorrectProductOrgInfo(productResp, productData.productOrganization);
expectCorrectAttribute(productResp.attributes, productData.attribute);
}
export function expectCorrectProductVariantInformation(
variantsResp,
variantName,
prices
) {
softExpect(
expect(variantsResp).to.have.length(1),
softExpect(variantsResp[0].sku).to.be.eq(variantName),
softExpect(variantsResp[0].channelListings[0].costPrice.amount).to.be.eq(
prices.costPrice
),
softExpect(variantsResp[0].channelListings[0].price.amount).to.be.eq(
prices.sellingPrice
)
);
}
function expectCorrectGeneralInformation(productResp, generalInfo) {
softExpect(productResp.name).to.be.eq(generalInfo.name);
softExpect(productResp.description).includes(generalInfo.description);
softExpect(productResp.rating).to.be.eq(generalInfo.rating);
}
function expectCorrectSeoInfo(productResp, seo) {
softExpect(productResp.slug).to.be.eq(seo.slug);
softExpect(productResp.seoTitle).to.be.eq(seo.title);
softExpect(productResp.seoDescription).to.be.eq(seo.description);
}
function expectCorrectMetadataInfo(metadataResp, expectedMetadata) {
softExpect(
expect(metadataResp).to.have.length(1),
softExpect(metadataResp[0].key).to.be.eq(expectedMetadata.name),
softExpect(metadataResp[0].value).to.be.eq(expectedMetadata.value)
);
}
function expectCorrectProductOrgInfo(productResp, productOrganization) {
softExpect(productResp.productType.name).to.be.eq(
productOrganization.productType
);
softExpect(productResp.category.name).to.be.eq(productOrganization.category);
softExpect(
expect(productResp.collections).to.have.length(1),
softExpect(productResp.collections[0].name).to.be.eq(
productOrganization.collection
)
);
}
function expectCorrectAttribute(attributes, attribute) {
softExpect(
expect(attributes).to.have.length(1),
softExpect(attributes[0].attribute.name).to.be.eq(attribute.name)
);
}

View file

@ -1,6 +1,6 @@
import * as attributeRequest from "../apiRequests/Attribute";
import * as categoryRequest from "../apiRequests/Category";
import * as productRequest from "../apiRequests/Product";
import * as attributeRequest from "../../apiRequests/Attribute";
import * as categoryRequest from "../../apiRequests/Category";
import * as productRequest from "../../apiRequests/Product";
export function createProductInChannel({
name,
@ -70,9 +70,9 @@ export function createAttribute(name, attributeValues) {
.createAttribute(name, attributeValues)
.its("body.data.attributeCreate.attribute");
}
export function createTypeProduct(name, attributeId) {
export function createTypeProduct(name, attributeId, hasVariants) {
return productRequest
.createTypeProduct(name, attributeId)
.createTypeProduct(name, attributeId, hasVariants)
.its("body.data.productTypeCreate.productType");
}
export function createCategory(name) {

View file

@ -163,7 +163,12 @@ const SeoForm: React.FC<SeoFormProps> = props => {
defaultMessage: "Search Engine Preview"
})}
toolbar={
<Button color="primary" variant="text" onClick={toggleExpansion}>
<Button
color="primary"
variant="text"
onClick={toggleExpansion}
data-test-id="edit-seo"
>
<FormattedMessage
defaultMessage="Edit website SEO"
description="button"

View file

@ -41188,6 +41188,7 @@ exports[`Storyshots Views / Categories / Create category When loading 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -41470,6 +41471,7 @@ exports[`Storyshots Views / Categories / Create category default 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -41759,6 +41761,7 @@ exports[`Storyshots Views / Categories / Create category form errors 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -42178,6 +42181,7 @@ exports[`Storyshots Views / Categories / Update category default 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -42951,6 +42955,7 @@ exports[`Storyshots Views / Categories / Update category form errors 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -43643,6 +43648,7 @@ exports[`Storyshots Views / Categories / Update category loading 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -44258,6 +44264,7 @@ exports[`Storyshots Views / Categories / Update category no background 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -45024,6 +45031,7 @@ exports[`Storyshots Views / Categories / Update category no products 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -45795,6 +45803,7 @@ exports[`Storyshots Views / Categories / Update category no subcategories 1`] =
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -46561,6 +46570,7 @@ exports[`Storyshots Views / Categories / Update category products 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -51587,6 +51597,7 @@ exports[`Storyshots Views / Collections / Collection detailsCollection details d
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -52852,6 +52863,7 @@ exports[`Storyshots Views / Collections / Collection detailsCollection details f
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -53536,6 +53548,7 @@ exports[`Storyshots Views / Collections / Collection detailsCollection details l
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -54359,6 +54372,7 @@ exports[`Storyshots Views / Collections / Collection detailsCollection details n
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -56088,6 +56102,7 @@ exports[`Storyshots Views / Collections / Create collection default 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -56797,6 +56812,7 @@ exports[`Storyshots Views / Collections / Create collection form errors 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -57500,6 +57516,7 @@ exports[`Storyshots Views / Collections / Create collection loading 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -136405,6 +136422,7 @@ exports[`Storyshots Views / Pages / Page details default 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -137299,6 +137317,7 @@ exports[`Storyshots Views / Pages / Page details form errors 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -138198,6 +138217,7 @@ exports[`Storyshots Views / Pages / Page details loading 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -162545,6 +162565,7 @@ exports[`Storyshots Views / Products / Create product When loading 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -163542,6 +163563,7 @@ exports[`Storyshots Views / Products / Create product default 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -164680,6 +164702,7 @@ exports[`Storyshots Views / Products / Create product form errors 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -172238,6 +172261,7 @@ exports[`Storyshots Views / Products / Product edit form errors 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -173712,6 +173736,7 @@ exports[`Storyshots Views / Products / Product edit no product attributes 1`] =
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -175430,6 +175455,7 @@ exports[`Storyshots Views / Products / Product edit no stock and no variants 1`]
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -177068,6 +177094,7 @@ exports[`Storyshots Views / Products / Product edit no stock, no variants and no
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -178928,6 +178955,7 @@ exports[`Storyshots Views / Products / Product edit no variants 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -180648,6 +180676,7 @@ exports[`Storyshots Views / Products / Product edit when data is fully loaded 1`
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -181957,6 +181986,7 @@ exports[`Storyshots Views / Products / Product edit when loading data 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -183330,6 +183360,7 @@ exports[`Storyshots Views / Products / Product edit when product has no images 1
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -185190,6 +185221,7 @@ exports[`Storyshots Views / Products / Product edit when product has no variants
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>
@ -186910,6 +186942,7 @@ exports[`Storyshots Views / Products / Product edit with channels 1`] = `
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
data-test-id="edit-seo"
tabindex="0"
type="button"
>