Add tests for creating products without sku (#1550)

* create products without sku

* update stories

* update stories
This commit is contained in:
Karolina Rakoczy 2021-11-22 15:57:20 +04:00 committed by GitHub
parent 241be6b6ee
commit a311583647
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 304 additions and 18 deletions

View file

@ -23,5 +23,10 @@ export const PRODUCT_DETAILS = {
uploadImageButton: '[data-test="button-upload-image"]',
uploadSavedImagesButton: '[data-test="uploadImages"]',
uploadMediaUrlButton: '[data-test="uploadMediaUrl"]',
saveUploadUrlButton: '[data-test-id="upload-url-button"]'
saveUploadUrlButton: '[data-test-id="upload-url-button"]',
addWarehouseButton: '[data-test-id="add-warehouse"]',
warehouseOption: "[role='menuitem']",
stockInput: '[data-test-id="stock-input"]',
costPriceInput: '[name*="costPrice"]',
sellingPriceInput: '[name*="channel-price"]'
};

View file

@ -9,5 +9,6 @@ export const VARIANTS_SELECTORS = {
addWarehouseButton: "button[class*='MuiIconButton-colorPrimary']",
warehouseOption: "[role='menuitem']",
saveButton: "[data-test='button-bar-confirm']",
skuInputInAddVariant: "[name='sku']"
skuInputInAddVariant: "[name='sku']",
stockInput: "[data-test-id='stock-input']"
};

View file

@ -0,0 +1,243 @@
/// <reference types="cypress"/>
/// <reference types="../../../support"/>
import faker from "faker";
import { PRODUCT_DETAILS } from "../../../elements/catalog/products/product-details";
import { PRODUCTS_LIST } from "../../../elements/catalog/products/products-list";
import { AVAILABLE_CHANNELS_FORM } from "../../../elements/channels/available-channels-form";
import { BUTTON_SELECTORS } from "../../../elements/shared/button-selectors";
import { urlList } from "../../../fixtures/urlList";
import { ONE_PERMISSION_USERS } from "../../../fixtures/users";
import {
createProduct,
updateChannelInProduct
} from "../../../support/api/requests/Product";
import { createTypeProduct } from "../../../support/api/requests/ProductType";
import {
deleteChannelsStartsWith,
getDefaultChannel
} from "../../../support/api/utils/channelsUtils";
import { createWaitingForCaptureOrder } from "../../../support/api/utils/ordersUtils";
import * as productUtils from "../../../support/api/utils/products/productsUtils";
import * as shippingUtils from "../../../support/api/utils/shippingUtils";
import { getProductVariants } from "../../../support/api/utils/storeFront/storeFrontProductUtils";
import filterTests from "../../../support/filterTests";
import {
createFirstVariant,
createVariant
} from "../../../support/pages/catalog/products/VariantsPage";
import { selectChannelInDetailsPages } from "../../../support/pages/channelsPage";
filterTests({ definedTags: ["all", "critical"], version: "3.1.0" }, () => {
describe("Creating variants", () => {
const startsWith = "CyCreateVariants-";
const attributeValues = ["value1", "value2"];
let defaultChannel;
let warehouse;
let attribute;
let productType;
let simpleProductType;
let category;
let shippingMethod;
let address;
before(() => {
cy.clearSessionData().loginUserViaRequest();
shippingUtils.deleteShippingStartsWith(startsWith);
productUtils.deleteProductsStartsWith(startsWith);
deleteChannelsStartsWith(startsWith);
const name = `${startsWith}${faker.datatype.number()}`;
const simpleProductTypeName = `${startsWith}${faker.datatype.number()}`;
getDefaultChannel()
.then(channel => {
defaultChannel = channel;
cy.fixture("addresses");
})
.then(fixtureAddresses => {
address = fixtureAddresses.plAddress;
shippingUtils.createShipping({
channelId: defaultChannel.id,
name,
address
});
})
.then(
({
warehouse: warehouseResp,
shippingMethod: shippingMethodResp
}) => {
warehouse = warehouseResp;
shippingMethod = shippingMethodResp;
}
);
productUtils
.createTypeAttributeAndCategoryForProduct({ name, attributeValues })
.then(
({
attribute: attributeResp,
productType: productTypeResp,
category: categoryResp
}) => {
attribute = attributeResp;
productType = productTypeResp;
category = categoryResp;
createTypeProduct({
name: simpleProductTypeName,
attributeId: attribute.id,
hasVariants: false
});
}
)
.then(type => {
simpleProductType = type;
});
});
beforeEach(() => {
cy.clearSessionData().loginUserViaRequest(
"auth",
ONE_PERMISSION_USERS.product
);
});
it("should create variant without sku by variant creator", () => {
const name = `${startsWith}${faker.datatype.number()}`;
const price = 10;
let createdProduct;
createProduct({
attributeId: attribute.id,
name,
productTypeId: productType.id,
categoryId: category.id
})
.then(resp => {
createdProduct = resp;
updateChannelInProduct({
productId: createdProduct.id,
channelId: defaultChannel.id
});
cy.visit(`${urlList.products}${createdProduct.id}`);
createFirstVariant({
warehouseId: warehouse.id,
price,
attribute: attributeValues[0]
});
getProductVariants(createdProduct.id, defaultChannel.slug);
})
.then(([variant]) => {
expect(variant).to.have.property("name", attributeValues[0]);
expect(variant).to.have.property("price", price);
createWaitingForCaptureOrder({
channelSlug: defaultChannel.slug,
email: "example@example.com",
variantsList: [variant],
shippingMethodId: shippingMethod.id,
address
});
})
.then(({ order }) => {
expect(order.id).to.be.ok;
});
});
it("should create variant without sku", () => {
const name = `${startsWith}${faker.datatype.number()}`;
const variants = [{ price: 7 }, { name: attributeValues[1], price: 16 }];
let createdProduct;
productUtils
.createProductInChannel({
name,
attributeId: attribute.id,
channelId: defaultChannel.id,
warehouseId: warehouse.id,
productTypeId: productType.id,
categoryId: category.id,
price: variants[0].price
})
.then(({ product: productResp }) => {
createdProduct = productResp;
cy.visit(`${urlList.products}${createdProduct.id}`);
createVariant({
warehouseName: warehouse.name,
attributeName: variants[1].name,
price: variants[1].price,
channelName: defaultChannel.name
});
})
.then(() => {
getProductVariants(createdProduct.id, defaultChannel.slug);
})
.then(([firstVariant, secondVariant]) => {
expect(firstVariant).to.have.property("price", variants[0].price);
expect(secondVariant).to.have.property("name", variants[1].name);
expect(secondVariant).to.have.property("price", variants[1].price);
createWaitingForCaptureOrder({
channelSlug: defaultChannel.slug,
email: "example@example.com",
variantsList: [secondVariant],
shippingMethodId: shippingMethod.id,
address
});
})
.then(({ order }) => {
expect(order.id).to.be.ok;
});
});
it("should create simple product without sku", () => {
const name = `${startsWith}${faker.datatype.number()}`;
cy.visit(urlList.products)
.get(PRODUCTS_LIST.createProductBtn)
.click()
.get(PRODUCT_DETAILS.productNameInput)
.type(name)
.fillAutocompleteSelect(
PRODUCT_DETAILS.productTypeInput,
simpleProductType.name
)
.fillAutocompleteSelect(PRODUCT_DETAILS.categoryInput);
selectChannelInDetailsPages(defaultChannel.name);
cy.get(PRODUCT_DETAILS.addWarehouseButton).click();
cy.contains(PRODUCT_DETAILS.warehouseOption, warehouse.name)
.click()
.get(PRODUCT_DETAILS.stockInput)
.clearAndType(10)
.get(PRODUCT_DETAILS.costPriceInput)
.type(10)
.get(PRODUCT_DETAILS.sellingPriceInput)
.type(10)
.get(AVAILABLE_CHANNELS_FORM.assignedChannels)
.click()
.get(
`${AVAILABLE_CHANNELS_FORM.availableForPurchaseRadioButtons}${AVAILABLE_CHANNELS_FORM.radioButtonsValueTrue}`
)
.click()
.get(
`${AVAILABLE_CHANNELS_FORM.publishedRadioButtons}${AVAILABLE_CHANNELS_FORM.radioButtonsValueTrue}`
)
.click()
.addAliasToGraphRequest("VariantCreate")
.get(BUTTON_SELECTORS.confirm)
.click()
.confirmationMessageShouldDisappear()
.wait("@VariantCreate")
.then(({ response }) => {
const variants = [
response.body.data.productVariantCreate.productVariant
];
createWaitingForCaptureOrder({
channelSlug: defaultChannel.slug,
email: "example@example.com",
variantsList: variants,
shippingMethodId: shippingMethod.id,
address
});
});
});
});
});

View file

@ -90,6 +90,23 @@ export function deleteProductType(productTypeId) {
return cy.sendRequestWithQuery(mutation);
}
export function productAttributeAssignmentUpdate({
productTypeId,
attributeId,
variantSelection = true
}) {
const mutation = `mutation {
productAttributeAssignmentUpdate(
operations: {id: "${attributeId}", variantSelection: ${variantSelection}} productTypeId:"${productTypeId}") {
errors {
field
message
}
}
}`;
return cy.sendRequestWithQuery(mutation);
}
export function getProductType(productTypeId) {
const query = `query{
productType(id:"${productTypeId}"){

View file

@ -22,6 +22,7 @@ export const getProductVariants = (productId, channelSlug) => {
getProductDetails(productId, channelSlug).then(resp => {
const variantsList = resp.body.data.product.variants;
return variantsList.map(element => ({
id: element.id,
name: element.name,
price: element.pricing.price.gross.amount
}));

View file

@ -6,12 +6,18 @@ import { BUTTON_SELECTORS } from "../../../../elements/shared/button-selectors";
import { selectChannelVariantInDetailsPage } from "../../channelsPage";
import { fillUpPriceList } from "./priceListComponent";
export function variantsShouldBeVisible({ name, price }) {
cy.contains(PRODUCT_DETAILS.variantRow, name).should("be.visible");
export function variantsShouldBeVisible({ price }) {
cy.get(PRODUCT_DETAILS.variantRow).should("be.visible");
cy.contains(PRODUCT_DETAILS.variantPrice, price);
}
export function createFirstVariant({ sku, warehouseId, price, attribute }) {
export function createFirstVariant({
sku,
warehouseId,
price,
attribute,
quantity = 1
}) {
cy.get(PRODUCT_DETAILS.addVariantsButton).click();
cy.get(PRODUCT_DETAILS.addVariantsOptionDialog.optionMultiple).click();
cy.get(BUTTON_SELECTORS.submit).click();
@ -24,11 +30,14 @@ export function createFirstVariant({ sku, warehouseId, price, attribute }) {
fillUpPriceList(price);
cy.get(`[name*='${warehouseId}']`)
.click()
.get(VARIANTS_SELECTORS.stockInput)
.type(quantity)
.get(VARIANTS_SELECTORS.nextButton)
.click()
.get(VARIANTS_SELECTORS.skuInput)
.type(sku)
.addAliasToGraphRequest("ProductVariantBulkCreate")
.click();
if (sku) {
cy.get(VARIANTS_SELECTORS.skuInput).type(sku);
}
cy.addAliasToGraphRequest("ProductVariantBulkCreate")
.get(VARIANTS_SELECTORS.nextButton)
.click()
.waitForRequestAndCheckIfNoErrors("@ProductVariantBulkCreate")
@ -43,7 +52,8 @@ export function createVariant({
attributeName,
price,
costPrice = price,
channelName
channelName,
quantity = 10
}) {
cy.get(PRODUCT_DETAILS.addVariantsButton)
.click()
@ -51,15 +61,18 @@ export function createVariant({
.click()
.get(VARIANTS_SELECTORS.attributeOption)
.contains(attributeName)
.click()
.get(VARIANTS_SELECTORS.skuInputInAddVariant)
.type(sku)
.get(VARIANTS_SELECTORS.addWarehouseButton)
.click();
cy.contains(VARIANTS_SELECTORS.warehouseOption, warehouseName).click({
force: true
});
cy.get(VARIANTS_SELECTORS.saveButton)
if (sku) {
cy.get(VARIANTS_SELECTORS.skuInputInAddVariant).type(sku);
}
cy.get(VARIANTS_SELECTORS.addWarehouseButton).click();
cy.contains(VARIANTS_SELECTORS.warehouseOption, warehouseName)
.click({
force: true
})
.get(VARIANTS_SELECTORS.stockInput)
.type(quantity)
.get(VARIANTS_SELECTORS.saveButton)
.click()
.get(BUTTON_SELECTORS.back)
.click()

View file

@ -375,6 +375,7 @@ const ProductStocks: React.FC<ProductStocksProps> = ({
</TableCell>
<TableCell className={classes.colQuantity}>
<TextField
data-test-id="stock-input"
disabled={disabled}
fullWidth
inputProps={{

View file

@ -203,6 +203,7 @@ const ProductVariantCreatorStock: React.FC<ProductVariantCreatorStockProps> = pr
}
</Typography>
<TextField
data-test-id="stock-input"
fullWidth
inputProps={{
min: 0,

View file

@ -184251,6 +184251,7 @@ exports[`Storyshots Views / Products / Create multiple variants / prices and SKU
</div>
<div
class="MuiFormControl-root-id MuiTextField-root-id MuiFormControl-fullWidth-id"
data-test-id="stock-input"
>
<label
class="MuiFormLabel-root-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-shrink-id MuiInputLabel-outlined-id MuiFormLabel-filled-id"
@ -184291,6 +184292,7 @@ exports[`Storyshots Views / Products / Create multiple variants / prices and SKU
</div>
<div
class="MuiFormControl-root-id MuiTextField-root-id MuiFormControl-fullWidth-id"
data-test-id="stock-input"
>
<label
class="MuiFormLabel-root-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-shrink-id MuiInputLabel-outlined-id MuiFormLabel-filled-id"
@ -184331,6 +184333,7 @@ exports[`Storyshots Views / Products / Create multiple variants / prices and SKU
</div>
<div
class="MuiFormControl-root-id MuiTextField-root-id MuiFormControl-fullWidth-id"
data-test-id="stock-input"
>
<label
class="MuiFormLabel-root-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-shrink-id MuiInputLabel-outlined-id MuiFormLabel-filled-id"
@ -185160,6 +185163,7 @@ exports[`Storyshots Views / Products / Create multiple variants / prices and SKU
</div>
<div
class="MuiFormControl-root-id MuiTextField-root-id MuiFormControl-fullWidth-id"
data-test-id="stock-input"
>
<label
class="MuiFormLabel-root-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-shrink-id MuiInputLabel-outlined-id MuiFormLabel-filled-id"