Merge branch 'master' of github.com:mirumee/saleor-dashboard into feature/unconfirmed-order-line-manipulation

This commit is contained in:
Tomasz Szymanski 2021-04-02 06:20:26 +02:00
commit fc3abed23d
51 changed files with 842 additions and 214 deletions

View file

@ -27,6 +27,7 @@ All notable, unreleased changes to this project will be documented in this file.
- Use default sort for search products list - #997 by @orzechdev
- Update CollectionBulkDelete error type - #1030 by @d-wysocki
- Remove mailing settings - #1027 by @dominik-zeglen
- Update schema to contain email plugin changes - #1029 by @dominik-zeglen
- Unconfirmed order manipulation - #967 by @tomaszszymanski129
# 2.11.1

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

@ -6841,6 +6841,10 @@
"context": "event",
"string": "Order updated"
},
"src_dot_webhooks_dot_components_dot_WebhookEvents_dot_1616635110": {
"context": "event",
"string": "User notified"
},
"src_dot_webhooks_dot_components_dot_WebhookEvents_dot_2126893364": {
"context": "event",
"string": "Product variant updated"

View file

@ -74,6 +74,7 @@ input AccountInput {
lastName: String
defaultBillingAddress: AddressInput
defaultShippingAddress: AddressInput
languageCode: LanguageCodeEnum
}
type AccountRegister {
@ -87,6 +88,7 @@ input AccountRegisterInput {
email: String!
password: String!
redirectUrl: String
languageCode: LanguageCodeEnum
}
type AccountRequestDeletion {
@ -879,6 +881,7 @@ type Checkout implements Node & ObjectWithMetadata {
subtotalPrice: TaxedMoney
token: UUID!
totalPrice: TaxedMoney
languageCode: LanguageCodeEnum!
}
type CheckoutAddPromoCode {
@ -925,6 +928,7 @@ input CheckoutCreateInput {
email: String
shippingAddress: AddressInput
billingAddress: AddressInput
languageCode: LanguageCodeEnum
}
type CheckoutCustomerAttach {
@ -977,6 +981,12 @@ enum CheckoutErrorCode {
CHANNEL_INACTIVE
}
type CheckoutLanguageCodeUpdate {
errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.")
checkout: Checkout
checkoutErrors: [CheckoutError!]!
}
type CheckoutLine implements Node {
id: ID!
variant: ProductVariant!
@ -1253,6 +1263,7 @@ input ConfigurationItemInput {
enum ConfigurationTypeFieldEnum {
STRING
MULTILINE
BOOLEAN
SECRET
PASSWORD
@ -1607,6 +1618,7 @@ input CustomerInput {
email: String
isActive: Boolean
note: String
languageCode: LanguageCodeEnum
}
type CustomerUpdate {
@ -2227,7 +2239,7 @@ type InvoiceRequestDelete {
invoice: Invoice
}
type InvoiceSendEmail {
type InvoiceSendNotification {
errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.")
invoiceErrors: [InvoiceError!]!
invoice: Invoice
@ -2736,7 +2748,7 @@ type Mutation {
invoiceCreate(input: InvoiceCreateInput!, orderId: ID!): InvoiceCreate
invoiceDelete(id: ID!): InvoiceDelete
invoiceUpdate(id: ID!, input: UpdateInvoiceInput!): InvoiceUpdate
invoiceSendEmail(id: ID!): InvoiceSendEmail
invoiceSendNotification(id: ID!): InvoiceSendNotification
giftCardActivate(id: ID!): GiftCardActivate
giftCardCreate(input: GiftCardCreateInput!): GiftCardCreate
giftCardDeactivate(id: ID!): GiftCardDeactivate
@ -2774,6 +2786,7 @@ type Mutation {
checkoutPaymentCreate(checkoutId: ID!, input: PaymentInput!): CheckoutPaymentCreate
checkoutShippingAddressUpdate(checkoutId: ID!, shippingAddress: AddressInput!): CheckoutShippingAddressUpdate
checkoutShippingMethodUpdate(checkoutId: ID, shippingMethodId: ID!): CheckoutShippingMethodUpdate
checkoutLanguageCodeUpdate(checkoutId: ID!, languageCode: LanguageCodeEnum!): CheckoutLanguageCodeUpdate
channelCreate(input: ChannelCreateInput!): ChannelCreate
channelUpdate(id: ID!, input: ChannelUpdateInput!): ChannelUpdate
channelDelete(id: ID!, input: ChannelDeleteInput): ChannelDelete
@ -2873,7 +2886,6 @@ type Order implements Node & ObjectWithMetadata {
created: DateTime!
status: OrderStatus!
user: User
languageCode: String!
trackingClientId: String!
billingAddress: Address
shippingAddress: Address
@ -2912,6 +2924,8 @@ type Order implements Node & ObjectWithMetadata {
totalBalance: Money!
userEmail: String
isShippingRequired: Boolean!
languageCode: String! @deprecated(reason: "Use the `languageCodeEnum` field to fetch the language code. This field will be removed in Saleor 4.0.")
languageCodeEnum: LanguageCodeEnum!
discount: Money @deprecated(reason: "Use discounts field. This field will be removed in Saleor 4.0.")
discountName: String @deprecated(reason: "Use discounts field. This field will be removed in Saleor 4.0.")
translatedDiscountName: String @deprecated(reason: "Use discounts field. This field will be removed in Saleor 4.0.")
@ -5497,6 +5511,7 @@ type User implements Node & ObjectWithMetadata {
avatar(size: Int): Image
events: [CustomerEvent]
storedPaymentSources: [PaymentSource]
languageCode: LanguageCodeEnum!
}
type UserAvatarDelete {
@ -5536,6 +5551,7 @@ input UserCreateInput {
email: String
isActive: Boolean
note: String
languageCode: LanguageCodeEnum
redirectUrl: String
}
@ -5950,6 +5966,7 @@ enum WebhookEventTypeEnum {
CHECKOUT_CREATED
CHECKOUT_UPDATED
FULFILLMENT_CREATED
NOTIFY_USER
PAGE_CREATED
PAGE_UPDATED
PAGE_DELETED
@ -5976,6 +5993,7 @@ enum WebhookSampleEventTypeEnum {
CHECKOUT_CREATED
CHECKOUT_UPDATED
FULFILLMENT_CREATED
NOTIFY_USER
PAGE_CREATED
PAGE_UPDATED
PAGE_DELETED

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

@ -717,7 +717,7 @@ const invoiceEmailSendMutation = gql`
${invoiceErrorFragment}
${invoiceFragment}
mutation InvoiceEmailSend($id: ID!) {
invoiceSendEmail(id: $id) {
invoiceSendNotification(id: $id) {
errors: invoiceErrors {
...InvoiceErrorFragment
}

View file

@ -9,13 +9,13 @@ import { InvoiceErrorCode, JobStatusEnum } from "./../../types/globalTypes";
// GraphQL mutation operation: InvoiceEmailSend
// ====================================================
export interface InvoiceEmailSend_invoiceSendEmail_errors {
export interface InvoiceEmailSend_invoiceSendNotification_errors {
__typename: "InvoiceError";
code: InvoiceErrorCode;
field: string | null;
}
export interface InvoiceEmailSend_invoiceSendEmail_invoice {
export interface InvoiceEmailSend_invoiceSendNotification_invoice {
__typename: "Invoice";
id: string;
number: string | null;
@ -24,14 +24,14 @@ export interface InvoiceEmailSend_invoiceSendEmail_invoice {
status: JobStatusEnum;
}
export interface InvoiceEmailSend_invoiceSendEmail {
__typename: "InvoiceSendEmail";
errors: InvoiceEmailSend_invoiceSendEmail_errors[];
invoice: InvoiceEmailSend_invoiceSendEmail_invoice | null;
export interface InvoiceEmailSend_invoiceSendNotification {
__typename: "InvoiceSendNotification";
errors: InvoiceEmailSend_invoiceSendNotification_errors[];
invoice: InvoiceEmailSend_invoiceSendNotification_invoice | null;
}
export interface InvoiceEmailSend {
invoiceSendEmail: InvoiceEmailSend_invoiceSendEmail | null;
invoiceSendNotification: InvoiceEmailSend_invoiceSendNotification | null;
}
export interface InvoiceEmailSendVariables {

View file

@ -279,7 +279,7 @@ export const OrderDetailsMessages: React.FC<OrderDetailsMessages> = ({
}
};
const handleInvoiceSend = (data: InvoiceEmailSend) => {
const errs = data.invoiceSendEmail?.errors;
const errs = data.invoiceSendNotification?.errors;
if (errs.length === 0) {
pushMessage({
text: intl.formatMessage({

View file

@ -21681,6 +21681,47 @@ exports[`Storyshots Views / Apps / Webhooks / Create webhook default 1`] = `
</span>
</label>
</div>
<div>
<label
class="MuiFormControlLabel-root-id"
>
<span
aria-disabled="false"
class="MuiButtonBase-root-id MuiIconButton-root-id PrivateSwitchBase-root-id MuiCheckbox-root-id MuiCheckbox-colorPrimary-id MuiIconButton-colorPrimary-id"
>
<span
class="MuiIconButton-label-id"
>
<input
class="PrivateSwitchBase-input-id"
data-indeterminate="false"
name="NOTIFY_USER"
type="checkbox"
/>
<svg
aria-hidden="true"
class="MuiSvgIcon-root-id"
focusable="false"
viewBox="0 0 24 24"
>
<rect
fill="none"
height="14"
stroke="currentColor"
width="14"
x="5"
y="5"
/>
</svg>
</span>
</span>
<span
class="MuiTypography-root-id MuiFormControlLabel-label-id MuiTypography-body1-id"
>
User notified
</span>
</label>
</div>
<div>
<label
class="MuiFormControlLabel-root-id"
@ -22973,6 +23014,47 @@ exports[`Storyshots Views / Apps / Webhooks / Create webhook form errors 1`] = `
</span>
</label>
</div>
<div>
<label
class="MuiFormControlLabel-root-id"
>
<span
aria-disabled="false"
class="MuiButtonBase-root-id MuiIconButton-root-id PrivateSwitchBase-root-id MuiCheckbox-root-id MuiCheckbox-colorPrimary-id MuiIconButton-colorPrimary-id"
>
<span
class="MuiIconButton-label-id"
>
<input
class="PrivateSwitchBase-input-id"
data-indeterminate="false"
name="NOTIFY_USER"
type="checkbox"
/>
<svg
aria-hidden="true"
class="MuiSvgIcon-root-id"
focusable="false"
viewBox="0 0 24 24"
>
<rect
fill="none"
height="14"
stroke="currentColor"
width="14"
x="5"
y="5"
/>
</svg>
</span>
</span>
<span
class="MuiTypography-root-id MuiFormControlLabel-label-id MuiTypography-body1-id"
>
User notified
</span>
</label>
</div>
<div>
<label
class="MuiFormControlLabel-root-id"
@ -24281,6 +24363,49 @@ exports[`Storyshots Views / Apps / Webhooks / Create webhook loading 1`] = `
</span>
</label>
</div>
<div>
<label
class="MuiFormControlLabel-root-id MuiFormControlLabel-disabled-id"
>
<span
aria-disabled="true"
class="MuiButtonBase-root-id MuiIconButton-root-id PrivateSwitchBase-root-id MuiCheckbox-root-id MuiCheckbox-colorPrimary-id PrivateSwitchBase-disabled-id MuiCheckbox-disabled-id MuiIconButton-colorPrimary-id MuiIconButton-disabled-id MuiButtonBase-disabled-id"
tabindex="-1"
>
<span
class="MuiIconButton-label-id"
>
<input
class="PrivateSwitchBase-input-id"
data-indeterminate="false"
disabled=""
name="NOTIFY_USER"
type="checkbox"
/>
<svg
aria-hidden="true"
class="MuiSvgIcon-root-id"
focusable="false"
viewBox="0 0 24 24"
>
<rect
fill="none"
height="14"
stroke="currentColor"
width="14"
x="5"
y="5"
/>
</svg>
</span>
</span>
<span
class="MuiTypography-root-id MuiFormControlLabel-label-id MuiFormControlLabel-disabled-id MuiTypography-body1-id"
>
User notified
</span>
</label>
</div>
<div>
<label
class="MuiFormControlLabel-root-id MuiFormControlLabel-disabled-id"
@ -25612,6 +25737,47 @@ exports[`Storyshots Views / Apps / Webhooks / Webhook details default 1`] = `
</span>
</label>
</div>
<div>
<label
class="MuiFormControlLabel-root-id"
>
<span
aria-disabled="false"
class="MuiButtonBase-root-id MuiIconButton-root-id PrivateSwitchBase-root-id MuiCheckbox-root-id MuiCheckbox-colorPrimary-id MuiIconButton-colorPrimary-id"
>
<span
class="MuiIconButton-label-id"
>
<input
class="PrivateSwitchBase-input-id"
data-indeterminate="false"
name="NOTIFY_USER"
type="checkbox"
/>
<svg
aria-hidden="true"
class="MuiSvgIcon-root-id"
focusable="false"
viewBox="0 0 24 24"
>
<rect
fill="none"
height="14"
stroke="currentColor"
width="14"
x="5"
y="5"
/>
</svg>
</span>
</span>
<span
class="MuiTypography-root-id MuiFormControlLabel-label-id MuiTypography-body1-id"
>
User notified
</span>
</label>
</div>
<div>
<label
class="MuiFormControlLabel-root-id"
@ -26910,6 +27076,47 @@ exports[`Storyshots Views / Apps / Webhooks / Webhook details form errors 1`] =
</span>
</label>
</div>
<div>
<label
class="MuiFormControlLabel-root-id"
>
<span
aria-disabled="false"
class="MuiButtonBase-root-id MuiIconButton-root-id PrivateSwitchBase-root-id MuiCheckbox-root-id MuiCheckbox-colorPrimary-id MuiIconButton-colorPrimary-id"
>
<span
class="MuiIconButton-label-id"
>
<input
class="PrivateSwitchBase-input-id"
data-indeterminate="false"
name="NOTIFY_USER"
type="checkbox"
/>
<svg
aria-hidden="true"
class="MuiSvgIcon-root-id"
focusable="false"
viewBox="0 0 24 24"
>
<rect
fill="none"
height="14"
stroke="currentColor"
width="14"
x="5"
y="5"
/>
</svg>
</span>
</span>
<span
class="MuiTypography-root-id MuiFormControlLabel-label-id MuiTypography-body1-id"
>
User notified
</span>
</label>
</div>
<div>
<label
class="MuiFormControlLabel-root-id"
@ -28224,6 +28431,49 @@ exports[`Storyshots Views / Apps / Webhooks / Webhook details loading 1`] = `
</span>
</label>
</div>
<div>
<label
class="MuiFormControlLabel-root-id MuiFormControlLabel-disabled-id"
>
<span
aria-disabled="true"
class="MuiButtonBase-root-id MuiIconButton-root-id PrivateSwitchBase-root-id MuiCheckbox-root-id MuiCheckbox-colorPrimary-id PrivateSwitchBase-disabled-id MuiCheckbox-disabled-id MuiIconButton-colorPrimary-id MuiIconButton-disabled-id MuiButtonBase-disabled-id"
tabindex="-1"
>
<span
class="MuiIconButton-label-id"
>
<input
class="PrivateSwitchBase-input-id"
data-indeterminate="false"
disabled=""
name="NOTIFY_USER"
type="checkbox"
/>
<svg
aria-hidden="true"
class="MuiSvgIcon-root-id"
focusable="false"
viewBox="0 0 24 24"
>
<rect
fill="none"
height="14"
stroke="currentColor"
width="14"
x="5"
y="5"
/>
</svg>
</span>
</span>
<span
class="MuiTypography-root-id MuiFormControlLabel-label-id MuiFormControlLabel-disabled-id MuiTypography-body1-id"
>
User notified
</span>
</label>
</div>
<div>
<label
class="MuiFormControlLabel-root-id MuiFormControlLabel-disabled-id"
@ -29543,6 +29793,47 @@ exports[`Storyshots Views / Apps / Webhooks / Webhook details unnamed 1`] = `
</span>
</label>
</div>
<div>
<label
class="MuiFormControlLabel-root-id"
>
<span
aria-disabled="false"
class="MuiButtonBase-root-id MuiIconButton-root-id PrivateSwitchBase-root-id MuiCheckbox-root-id MuiCheckbox-colorPrimary-id MuiIconButton-colorPrimary-id"
>
<span
class="MuiIconButton-label-id"
>
<input
class="PrivateSwitchBase-input-id"
data-indeterminate="false"
name="NOTIFY_USER"
type="checkbox"
/>
<svg
aria-hidden="true"
class="MuiSvgIcon-root-id"
focusable="false"
viewBox="0 0 24 24"
>
<rect
fill="none"
height="14"
stroke="currentColor"
width="14"
x="5"
y="5"
/>
</svg>
</span>
</span>
<span
class="MuiTypography-root-id MuiFormControlLabel-label-id MuiTypography-body1-id"
>
User notified
</span>
</label>
</div>
<div>
<label
class="MuiFormControlLabel-root-id"
@ -40897,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"
>
@ -41179,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"
>
@ -41468,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"
>
@ -41887,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"
>
@ -42660,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"
>
@ -43352,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"
>
@ -43967,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"
>
@ -44733,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"
>
@ -45504,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"
>
@ -46270,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"
>
@ -51296,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"
>
@ -52561,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"
>
@ -53245,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"
>
@ -54068,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"
>
@ -55797,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"
>
@ -56506,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"
>
@ -57209,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"
>
@ -136114,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"
>
@ -137008,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"
>
@ -137907,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"
>
@ -162254,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"
>
@ -163251,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"
>
@ -164389,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"
>
@ -171947,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"
>
@ -173421,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"
>
@ -175139,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"
>
@ -176777,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"
>
@ -178637,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"
>
@ -180357,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"
>
@ -181666,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"
>
@ -183039,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"
>
@ -184899,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"
>
@ -186619,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"
>

View file

@ -19,7 +19,7 @@ export const getParsedTranslationInputData = ({
if (fieldsToParse.includes(fieldName)) {
return {
description: getParsedDataForJsonStringField(data as OutputData)
[fieldName]: getParsedDataForJsonStringField(data as OutputData)
};
}

View file

@ -10,7 +10,7 @@ import { LanguageCodeEnum } from "../../types/globalTypes";
import TranslationsPagesPage from "../components/TranslationsPagesPage";
import { TypedUpdatePageTranslations } from "../mutations";
import { usePageTranslationDetails } from "../queries";
import { TranslationInputFieldName } from "../types";
import { PageTranslationInputFieldName } from "../types";
import { UpdatePageTranslations } from "../types/UpdatePageTranslations";
import {
languageEntitiesUrl,
@ -68,7 +68,7 @@ const TranslationsPages: React.FC<TranslationsPagesProps> = ({
<TypedUpdatePageTranslations onCompleted={onUpdate}>
{(updateTranslations, updateTranslationsOpts) => {
const handleSubmit = (
fieldName: TranslationInputFieldName,
fieldName: PageTranslationInputFieldName,
data: string
) => {
updateTranslations({

View file

@ -151,6 +151,7 @@ export enum CollectionSortField {
export enum ConfigurationTypeFieldEnum {
BOOLEAN = "BOOLEAN",
MULTILINE = "MULTILINE",
PASSWORD = "PASSWORD",
SECRET = "SECRET",
SECRETMULTILINE = "SECRETMULTILINE",
@ -999,6 +1000,7 @@ export enum WebhookEventTypeEnum {
INVOICE_DELETED = "INVOICE_DELETED",
INVOICE_REQUESTED = "INVOICE_REQUESTED",
INVOICE_SENT = "INVOICE_SENT",
NOTIFY_USER = "NOTIFY_USER",
ORDER_CANCELLED = "ORDER_CANCELLED",
ORDER_CONFIRMED = "ORDER_CONFIRMED",
ORDER_CREATED = "ORDER_CREATED",
@ -1247,6 +1249,7 @@ export interface CustomerInput {
email?: string | null;
isActive?: boolean | null;
note?: string | null;
languageCode?: LanguageCodeEnum | null;
}
export interface DateRangeInput {
@ -1866,6 +1869,7 @@ export interface UserCreateInput {
email?: string | null;
isActive?: boolean | null;
note?: string | null;
languageCode?: LanguageCodeEnum | null;
redirectUrl?: string | null;
}

View file

@ -143,6 +143,10 @@ const WebhookEvents: React.FC<WebhookEventsProps> = ({
[WebhookEventTypeEnum.PAGE_DELETED]: intl.formatMessage({
defaultMessage: "Page deleted",
description: "event"
}),
[WebhookEventTypeEnum.NOTIFY_USER]: intl.formatMessage({
defaultMessage: "User notified",
description: "event"
})
};