Add tests for product types for 3.1 (#1806)

* tests for product types for 3.1

* updated stories

* chage test cases names for product types

* add test for setting attribute as variant selection in product type

* add test for setting attribute as variant selection in product type

* split product types spec file

* uncomment purchase with product types test

* Update cypress/integration/configuration/productTypes/attributesInProduductTypes.js

Co-authored-by: Ewa Czerniak <ewa.czerniak@saleor.io>

Co-authored-by: Ewa Czerniak <ewa.czerniak@saleor.io>
This commit is contained in:
Karolina Rakoczy 2022-02-07 10:30:52 +01:00 committed by GitHub
parent 9f3dfe3bcd
commit 10fb086d6e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 393 additions and 144 deletions

View file

@ -5,5 +5,6 @@ export const PRODUCT_TYPE_DETAILS = {
assignVariantAttributeButton: '[data-test-id="assignVariantsAttributes"]',
hasVariantsButton: '[name="hasVariants"]',
shippingWeightInput: '[name="weight"]',
giftCardKindCheckbox: '[data-test-id="product-type-kind-option-GIFT_CARD"]'
giftCardKindCheckbox: '[data-test-id="product-type-kind-option-GIFT_CARD"]',
variantSelectionCheckbox: '[data-test-id = "variant-selection-checkbox"]'
};

View file

@ -10,7 +10,8 @@ export const BUTTON_SELECTORS = {
deleteButton: '[data-test="button-bar-delete"]',
expandIcon: '[data-test-id="expand-icon"]',
nextPaginationButton: '[data-test="button-pagination-next"]',
deleteIcon: '[data-test-id="deleteIcon"]',
deleteIcon: '[data-test-id="delete-icon"]',
showMoreButton: '[data-test-id="showMoreButton"]',
button: "button"
button: "button",
deleteAssignedItemsConsentCheckbox: '[name="delete-assigned-items-consent"]'
};

View file

@ -21,7 +21,8 @@ export const SHARED_ELEMENTS = {
filters: {
filterGroupActivateCheckbox: '[data-test="filterGroupActive"]',
filterRow: '[data-test="channel-availability-item"]'
}
},
warningDialog: '[data-test-id="warning-dialog"]'
};
export const selectorWithDataValue = value => `[data-value="${value}"]`;

View file

@ -98,7 +98,7 @@ filterTests({ definedTags: ["all", "critical"] }, () => {
};
});
xit("should purchase digital product", () => {
it("should purchase digital product", () => {
const digitalName = `${startsWith}${faker.datatype.number()}`;
let variants;
@ -141,7 +141,7 @@ filterTests({ definedTags: ["all", "critical"] }, () => {
});
});
xit("should purchase physical product", () => {
it("should purchase physical product", () => {
const physicalName = `${startsWith}${faker.datatype.number()}`;
createTypeProduct({
name: physicalName,

View file

@ -1,122 +0,0 @@
/// <reference types="cypress"/>
/// <reference types="../../support"/>
import faker from "faker";
import { PRODUCT_TYPE_DETAILS } from "../../elements/productTypes/productTypeDetails";
import { productTypeDetailsUrl, urlList } from "../../fixtures/urlList";
import { createAttribute } from "../../support/api/requests/Attribute";
import {
createTypeProduct,
getProductType
} from "../../support/api/requests/ProductType";
import { deleteProductsStartsWith } from "../../support/api/utils/products/productsUtils";
import filterTests from "../../support/filterTests";
import { createProductType } from "../../support/pages/productTypePage";
filterTests({ definedTags: ["all"] }, () => {
describe("As an admin I want to manage product types", () => {
const startsWith = "ProductType";
before(() => {
cy.clearSessionData().loginUserViaRequest();
deleteProductsStartsWith(startsWith);
createAttribute({ name: startsWith });
});
beforeEach(() => {
cy.clearSessionData()
.loginUserViaRequest()
.visit(urlList.productTypes)
.softExpectSkeletonIsVisible();
});
it("As an admin I should be able to create product type without shipping required", () => {
const name = `${startsWith}${faker.datatype.number()}`;
createProductType({ name })
.then(productType => {
getProductType(productType.id);
})
.then(productType => {
expect(productType.name).to.be.eq(name);
expect(productType.isShippingRequired).to.be.false;
expect(productType.kind).to.be.eq("NORMAL");
});
});
it("As an admin I should be able to create product type with shipping required", () => {
const name = `${startsWith}${faker.datatype.number()}`;
const shippingWeight = 10;
createProductType({ name, shippingWeight })
.then(productType => {
getProductType(productType.id);
})
.then(productType => {
expect(productType.name).to.be.eq(name);
expect(productType.isShippingRequired).to.be.true;
expect(productType.weight.value).to.eq(shippingWeight);
expect(productType.kind).to.be.eq("NORMAL");
});
});
it("As an admin I should be able to create product type with gift card kind", () => {
const name = `${startsWith}${faker.datatype.number()}`;
createProductType({ name, giftCard: true })
.then(productType => {
getProductType(productType.id);
})
.then(productType => {
expect(productType.name).to.be.eq(name);
expect(productType.isShippingRequired).to.be.false;
expect(productType.kind).to.be.eq("GIFT_CARD");
});
});
it("As an admin I should be able to update product type with product attribute", () => {
const name = `${startsWith}${faker.datatype.number()}`;
createTypeProduct({ name })
.then(productType => {
cy.visitAndWaitForProgressBarToDisappear(
productTypeDetailsUrl(productType.id)
)
.get(PRODUCT_TYPE_DETAILS.assignProductAttributeButton)
.click()
.addAliasToGraphRequest("AssignProductAttribute")
.assignElements(startsWith, false)
.confirmationMessageShouldDisappear()
.waitForRequestAndCheckIfNoErrors("@AssignProductAttribute");
getProductType(productType.id);
})
.then(productType => {
expect(productType.productAttributes[0].name).to.eq(startsWith);
});
});
it("As an admin I should be able to update product type with variant attribute", () => {
const name = `${startsWith}${faker.datatype.number()}`;
createTypeProduct({ name, hasVariants: false })
.then(productType => {
cy.visitAndWaitForProgressBarToDisappear(
productTypeDetailsUrl(productType.id)
)
.get(PRODUCT_TYPE_DETAILS.hasVariantsButton)
.click({ force: true })
.get(PRODUCT_TYPE_DETAILS.assignVariantAttributeButton)
.click()
.addAliasToGraphRequest("AssignProductAttribute")
.assignElements(startsWith, false)
.confirmationMessageShouldDisappear()
.wait("@AssignProductAttribute");
getProductType(productType.id);
})
.then(productType => {
expect(productType.variantAttributes[0].name).to.eq(startsWith);
});
});
});
});

View file

@ -0,0 +1,168 @@
/// <reference types="cypress"/>
/// <reference types="../../../support"/>
import faker from "faker";
import { PRODUCT_TYPE_DETAILS } from "../../../elements/productTypes/productTypeDetails";
import { BUTTON_SELECTORS } from "../../../elements/shared/button-selectors";
import { productTypeDetailsUrl } from "../../../fixtures/urlList";
import { createAttribute } from "../../../support/api/requests/Attribute";
import { createCategory } from "../../../support/api/requests/Category";
import {
assignAttribute,
createTypeProduct,
getProductType
} from "../../../support/api/requests/ProductType";
import { getDefaultChannel } from "../../../support/api/utils/channelsUtils";
import { deleteProductsStartsWith } from "../../../support/api/utils/products/productsUtils";
import filterTests from "../../../support/filterTests";
filterTests({ definedTags: ["all"] }, () => {
describe("As an admin I want to manage product types", () => {
const startsWith = "productType";
let category;
let channel;
let attribute;
before(() => {
cy.clearSessionData().loginUserViaRequest();
deleteProductsStartsWith(startsWith);
createAttribute({ name: startsWith }).then(resp => (attribute = resp));
createCategory(startsWith).then(resp => (category = resp));
getDefaultChannel().then(resp => (channel = resp));
});
beforeEach(() => {
cy.clearSessionData().loginUserViaRequest();
});
it("should be able to update product type with product attribute. TC: SALEOR_1503", () => {
const name = `${startsWith}${faker.datatype.number()}`;
createTypeProduct({ name })
.then(productType => {
cy.visitAndWaitForProgressBarToDisappear(
productTypeDetailsUrl(productType.id)
)
.get(PRODUCT_TYPE_DETAILS.assignProductAttributeButton)
.click()
.addAliasToGraphRequest("AssignProductAttribute")
.assignElements(startsWith, false)
.confirmationMessageShouldDisappear()
.waitForRequestAndCheckIfNoErrors("@AssignProductAttribute");
getProductType(productType.id);
})
.then(productType => {
expect(productType.productAttributes[0].name).to.eq(startsWith);
});
});
it("should be able to update product type with variant attribute. TC: SALEOR_1504", () => {
const name = `${startsWith}${faker.datatype.number()}`;
createTypeProduct({ name, hasVariants: false })
.then(productType => {
cy.visitAndWaitForProgressBarToDisappear(
productTypeDetailsUrl(productType.id)
)
.get(PRODUCT_TYPE_DETAILS.hasVariantsButton)
.click({ force: true })
.get(PRODUCT_TYPE_DETAILS.assignVariantAttributeButton)
.click()
.addAliasToGraphRequest("AssignProductAttribute")
.assignElements(startsWith, false)
.confirmationMessageShouldDisappear()
.wait("@AssignProductAttribute");
getProductType(productType.id);
})
.then(productType => {
expect(productType.assignedVariantAttributes[0].attribute.name).to.eq(
startsWith
);
});
});
it("should be able to remove variant attribute from product type. TC: SALEOR_1506", () => {
const name = `${startsWith}${faker.datatype.number()}`;
let productType;
createTypeProduct({ name, hasVariants: true })
.then(productTypeResp => {
productType = productTypeResp;
assignAttribute(productType.id, attribute.id);
})
.then(() => {
cy.visitAndWaitForProgressBarToDisappear(
productTypeDetailsUrl(productType.id)
)
.get(BUTTON_SELECTORS.deleteIcon)
.click()
.addAliasToGraphRequest("UnassignProductAttribute")
.get(BUTTON_SELECTORS.submit)
.click()
.wait("@UnassignProductAttribute");
getProductType(productType.id);
})
.then(productType => {
expect(productType.assignedVariantAttributes).to.be.empty;
});
});
it("should be able to remove product attribute from product type. TC: SALEOR_1507", () => {
const name = `${startsWith}${faker.datatype.number()}`;
let productType;
createTypeProduct({ name, hasVariants: false })
.then(productTypeResp => {
productType = productTypeResp;
assignAttribute(productType.id, attribute.id, "PRODUCT");
})
.then(() => {
cy.visitAndWaitForProgressBarToDisappear(
productTypeDetailsUrl(productType.id)
)
.get(BUTTON_SELECTORS.deleteIcon)
.click()
.addAliasToGraphRequest("UnassignProductAttribute")
.get(BUTTON_SELECTORS.submit)
.click()
.wait("@UnassignProductAttribute");
getProductType(productType.id);
})
.then(productType => {
expect(productType.assignedVariantAttributes).to.be.empty;
});
});
it("should be able to select attribute as variant selection. TC: SALEOR_1508", () => {
const name = `${startsWith}${faker.datatype.number()}`;
let productType;
createTypeProduct({ name, hasVariants: true })
.then(productTypeResp => {
productType = productTypeResp;
assignAttribute(productType.id, attribute.id);
})
.then(() => {
cy.visitAndWaitForProgressBarToDisappear(
productTypeDetailsUrl(productType.id)
)
.get(PRODUCT_TYPE_DETAILS.variantSelectionCheckbox)
.click()
.addAliasToGraphRequest("ProductAttributeAssignmentUpdate")
.get(BUTTON_SELECTORS.confirm)
.click()
.wait("@ProductAttributeAssignmentUpdate");
getProductType(productType.id);
})
.then(productType => {
expect(productType.assignedVariantAttributes[0].attribute.name).to.eq(
startsWith
);
expect(
productType.assignedVariantAttributes[0].variantSelection
).to.eq(true);
});
});
});
});

View file

@ -0,0 +1,72 @@
/// <reference types="cypress"/>
/// <reference types="../../../support"/>
import faker from "faker";
import { urlList } from "../../../fixtures/urlList";
import { getProductType } from "../../../support/api/requests/ProductType";
import { deleteProductsStartsWith } from "../../../support/api/utils/products/productsUtils";
import filterTests from "../../../support/filterTests";
import { createProductType } from "../../../support/pages/productTypePage";
filterTests({ definedTags: ["all"] }, () => {
describe("As an admin I want to create product types", () => {
const startsWith = "productType";
before(() => {
cy.clearSessionData().loginUserViaRequest();
deleteProductsStartsWith(startsWith);
});
beforeEach(() => {
cy.clearSessionData()
.loginUserViaRequest()
.visit(urlList.productTypes)
.softExpectSkeletonIsVisible();
});
it("should be able to create product type without shipping required. TC: SALEOR_1501", () => {
const name = `${startsWith}${faker.datatype.number()}`;
createProductType({ name })
.then(productType => {
getProductType(productType.id);
})
.then(productType => {
expect(productType.name).to.be.eq(name);
expect(productType.isShippingRequired).to.be.false;
expect(productType.kind).to.be.eq("NORMAL");
});
});
it("should be able to create product type with shipping required. TC: SALEOR_1502", () => {
const name = `${startsWith}${faker.datatype.number()}`;
const shippingWeight = 10;
createProductType({ name, shippingWeight })
.then(productType => {
getProductType(productType.id);
})
.then(productType => {
expect(productType.name).to.be.eq(name);
expect(productType.isShippingRequired).to.be.true;
expect(productType.weight.value).to.eq(shippingWeight);
expect(productType.kind).to.be.eq("NORMAL");
});
});
it("should be able to create product type with gift card kind. TC: SALEOR_1510", () => {
const name = `${startsWith}${faker.datatype.number()}`;
createProductType({ name, giftCard: true })
.then(productType => {
getProductType(productType.id);
})
.then(productType => {
expect(productType.name).to.be.eq(name);
expect(productType.isShippingRequired).to.be.false;
expect(productType.kind).to.be.eq("GIFT_CARD");
});
});
});
});

View file

@ -0,0 +1,97 @@
/// <reference types="cypress"/>
/// <reference types="../../../support"/>
import faker from "faker";
import { BUTTON_SELECTORS } from "../../../elements/shared/button-selectors";
import { SHARED_ELEMENTS } from "../../../elements/shared/sharedElements";
import { productTypeDetailsUrl } from "../../../fixtures/urlList";
import { createAttribute } from "../../../support/api/requests/Attribute";
import { createCategory } from "../../../support/api/requests/Category";
import {
createTypeProduct,
getProductType
} from "../../../support/api/requests/ProductType";
import { getProductDetails } from "../../../support/api/requests/storeFront/ProductDetails";
import { getDefaultChannel } from "../../../support/api/utils/channelsUtils";
import {
createProductInChannel,
deleteProductsStartsWith
} from "../../../support/api/utils/products/productsUtils";
import filterTests from "../../../support/filterTests";
filterTests({ definedTags: ["all"] }, () => {
describe("As an admin I want to manage product types", () => {
const startsWith = "productType";
let category;
let channel;
let attribute;
before(() => {
cy.clearSessionData().loginUserViaRequest();
deleteProductsStartsWith(startsWith);
createAttribute({ name: startsWith }).then(resp => (attribute = resp));
createCategory(startsWith).then(resp => (category = resp));
getDefaultChannel().then(resp => (channel = resp));
});
beforeEach(() => {
cy.clearSessionData().loginUserViaRequest();
});
it("should be able to delete product type. TC: SALEOR_1505", () => {
const name = `${startsWith}${faker.datatype.number()}`;
createTypeProduct({ name, hasVariants: false }).then(productType => {
cy.visitAndWaitForProgressBarToDisappear(
productTypeDetailsUrl(productType.id)
)
.get(BUTTON_SELECTORS.deleteButton)
.click()
.addAliasToGraphRequest("ProductTypeDelete")
.get(SHARED_ELEMENTS.warningDialog)
.find(BUTTON_SELECTORS.deleteButton)
.click()
.waitForRequestAndCheckIfNoErrors("@ProductTypeDelete");
getProductType(productType.id).should("be.null");
});
});
it("should be able to delete product type with assigned product. TC: SALEOR_1509", () => {
const name = `${startsWith}${faker.datatype.number()}`;
let productType;
createTypeProduct({ name, hasVariants: false })
.then(productTypeResp => {
productType = productTypeResp;
createProductInChannel({
name,
channelId: channel.id,
categoryId: category.id,
productTypeId: productType.id
});
})
.then(({ product }) => {
cy.visitAndWaitForProgressBarToDisappear(
productTypeDetailsUrl(productType.id)
)
.get(BUTTON_SELECTORS.deleteButton)
.click()
.addAliasToGraphRequest("ProductTypeDelete")
.get(SHARED_ELEMENTS.warningDialog)
.find(BUTTON_SELECTORS.deleteButton)
.should("not.be.enabled")
.get(BUTTON_SELECTORS.deleteAssignedItemsConsentCheckbox)
.click()
.get(SHARED_ELEMENTS.warningDialog)
.find(BUTTON_SELECTORS.deleteButton)
.click()
.waitForRequestAndCheckIfNoErrors("@ProductTypeDelete");
getProductType(productType.id).should("be.null");
getProductDetails(product.id)
.its("body.data.product")
.should("be.null");
});
});
});
});

View file

@ -110,17 +110,16 @@ export function createProduct({
attributeValue,
`values:["${attributeValue}"]`
);
const attributesLines = getValueWithDefault(
const attributes = getValueWithDefault(
attributeId,
`attributes:[{
id:"${attributeId}"
${attributeValuesLine}
}]`
id:"${attributeId}"
${attributeValuesLine}
}]`
);
const mutation = `mutation{
productCreate(input:{
${attributesLines}
${attributes}
name:"${name}"
slug:"${name}"
seo:{title:"${name}" description:""}

View file

@ -105,8 +105,11 @@ export function getProductType(productTypeId) {
productAttributes{
name
}
variantAttributes{
name
assignedVariantAttributes{
attribute{
name
}
variantSelection
}
}
}`;
@ -145,3 +148,22 @@ export function setProductTypeAsDigital(productTypeId, isDigital = true) {
}`;
return cy.sendRequestWithQuery(mutation);
}
export function assignAttribute(
productTypeId,
attributeId,
attributeType = "VARIANT"
) {
const mutation = `mutation{
productAttributeAssign(productTypeId:"${productTypeId}", operations:{
id:"${attributeId}"
type: ${attributeType}
}){
errors{
field
message
}
}
}`;
return cy.sendRequestWithQuery(mutation);
}

View file

@ -265,7 +265,7 @@ export const CategoryDetails: React.FC<CategoryDetailsProps> = ({
}
productListToolbar={
<IconButton
data-test-id="deleteIcon"
data-test-id="delete-icon"
color="primary"
onClick={() =>
openModal("delete-products", {

View file

@ -92,7 +92,7 @@ function TypeDeleteWarningDialog<T extends TypeBaseData>({
return (
<Modal open={isOpen}>
<div className={classes.centerContainer}>
<div className={classes.centerContainer} data-test-id="warning-dialog">
<Card className={classes.content}>
<ModalTitle
title={intl.formatMessage(baseMessages.title, {

View file

@ -149,7 +149,7 @@ const PermissionGroupList: React.FC<PermissionGroupListProps> = props => {
{permissionGroup.userCanManage && (
<IconButton
variant="secondary"
data-test-id="deleteIcon"
data-test-id="delete-icon"
color="primary"
onClick={stopPropagation(() =>
onDelete(permissionGroup.id)

View file

@ -177,6 +177,7 @@ const ProductTypeAttributes: React.FC<ProductTypeAttributesProps> = props => {
</TableCell>
<TableCell className={classes.colAction}>
<IconButton
data-test-id="delete-icon"
disabled={disabled}
variant="secondary"
onClick={stopPropagation(() =>

View file

@ -243,10 +243,11 @@ const ProductTypeVariantAttributes: React.FC<ProductTypeVariantAttributesProps>
</TableCell>
<TableCell
className={classes.colVariant}
data-test="variant-selection"
data-test-id="variant-selection"
>
<div className={classes.colVariantContent}>
<Checkbox
data-test-id="variant-selection-checkbox"
checked={isSelected}
disabled={disabled || variantSelectionDisabled}
disableClickPropagation
@ -278,6 +279,7 @@ const ProductTypeVariantAttributes: React.FC<ProductTypeVariantAttributesProps>
</TableCell>
<TableCell className={classes.colAction}>
<IconButton
data-test-id="delete-icon"
onClick={stopPropagation(() =>
onAttributeUnassign(attribute.id)
)}

View file

@ -162738,7 +162738,7 @@ exports[`Storyshots Views / Permission Groups / Permission Group List default 1`
<button
class="MuiButtonBase-root-id IconButton-secondary-id IconButton-hoverOutline-id"
color="primary"
data-test-id="deleteIcon"
data-test-id="delete-icon"
tabindex="0"
type="button"
>
@ -162814,7 +162814,7 @@ exports[`Storyshots Views / Permission Groups / Permission Group List default 1`
<button
class="MuiButtonBase-root-id IconButton-secondary-id IconButton-hoverOutline-id"
color="primary"
data-test-id="deleteIcon"
data-test-id="delete-icon"
tabindex="0"
type="button"
>
@ -162863,7 +162863,7 @@ exports[`Storyshots Views / Permission Groups / Permission Group List default 1`
<button
class="MuiButtonBase-root-id IconButton-secondary-id IconButton-hoverOutline-id"
color="primary"
data-test-id="deleteIcon"
data-test-id="delete-icon"
tabindex="0"
type="button"
>
@ -162912,7 +162912,7 @@ exports[`Storyshots Views / Permission Groups / Permission Group List default 1`
<button
class="MuiButtonBase-root-id IconButton-secondary-id IconButton-hoverOutline-id"
color="primary"
data-test-id="deleteIcon"
data-test-id="delete-icon"
tabindex="0"
type="button"
>
@ -167180,6 +167180,7 @@ exports[`Storyshots Views / Product types / Product type details default 1`] = `
>
<button
class="MuiButtonBase-root-id IconButton-secondary-id IconButton-hoverOutline-id"
data-test-id="delete-icon"
tabindex="0"
type="button"
>
@ -167275,6 +167276,7 @@ exports[`Storyshots Views / Product types / Product type details default 1`] = `
>
<button
class="MuiButtonBase-root-id IconButton-secondary-id IconButton-hoverOutline-id"
data-test-id="delete-icon"
tabindex="0"
type="button"
>
@ -167370,6 +167372,7 @@ exports[`Storyshots Views / Product types / Product type details default 1`] = `
>
<button
class="MuiButtonBase-root-id IconButton-secondary-id IconButton-hoverOutline-id"
data-test-id="delete-icon"
tabindex="0"
type="button"
>
@ -168301,6 +168304,7 @@ exports[`Storyshots Views / Product types / Product type details form errors 1`]
>
<button
class="MuiButtonBase-root-id IconButton-secondary-id IconButton-hoverOutline-id"
data-test-id="delete-icon"
tabindex="0"
type="button"
>
@ -168396,6 +168400,7 @@ exports[`Storyshots Views / Product types / Product type details form errors 1`]
>
<button
class="MuiButtonBase-root-id IconButton-secondary-id IconButton-hoverOutline-id"
data-test-id="delete-icon"
tabindex="0"
type="button"
>
@ -168491,6 +168496,7 @@ exports[`Storyshots Views / Product types / Product type details form errors 1`]
>
<button
class="MuiButtonBase-root-id IconButton-secondary-id IconButton-hoverOutline-id"
data-test-id="delete-icon"
tabindex="0"
type="button"
>
@ -169375,6 +169381,7 @@ exports[`Storyshots Views / Product types / Product type details loading 1`] = `
>
<button
class="MuiButtonBase-root-id IconButton-secondary-id MuiButtonBase-disabled-id"
data-test-id="delete-icon"
disabled=""
tabindex="-1"
type="button"