tests for publish products
This commit is contained in:
parent
6477d62409
commit
cb528a7744
17 changed files with 886 additions and 48 deletions
49
cypress/apiRequests/Attribute.js
Normal file
49
cypress/apiRequests/Attribute.js
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
class Attribute {
|
||||||
|
createAttribute(name) {
|
||||||
|
const mutation = `mutation{
|
||||||
|
attributeCreate(input:{
|
||||||
|
name:"${name}"
|
||||||
|
valueRequired:false
|
||||||
|
type:PRODUCT_TYPE
|
||||||
|
}){
|
||||||
|
attribute{
|
||||||
|
id
|
||||||
|
}
|
||||||
|
attributeErrors{
|
||||||
|
field
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
return cy.sendRequestWithQuery(mutation);
|
||||||
|
}
|
||||||
|
|
||||||
|
getAttributes(first, search) {
|
||||||
|
const mutation = `query{
|
||||||
|
attributes(first:${first}, filter:{
|
||||||
|
search:"${search}"
|
||||||
|
}){
|
||||||
|
edges{
|
||||||
|
node{
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
return cy.sendRequestWithQuery(mutation);
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteAttribute(attributeId) {
|
||||||
|
const mutation = `mutation{
|
||||||
|
attributeDelete(id:"${attributeId}"){
|
||||||
|
attributeErrors{
|
||||||
|
field
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
return cy.sendRequestWithQuery(mutation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default Attribute;
|
43
cypress/apiRequests/Category.js
Normal file
43
cypress/apiRequests/Category.js
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
class Category {
|
||||||
|
createCategory(name, slug = name) {
|
||||||
|
const mutation = `mutation{
|
||||||
|
categoryCreate(input:{name:"${name}", slug: "${slug}"}){
|
||||||
|
productErrors{
|
||||||
|
field
|
||||||
|
message
|
||||||
|
}
|
||||||
|
category{
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
return cy.sendRequestWithQuery(mutation);
|
||||||
|
}
|
||||||
|
getCategories(first, search) {
|
||||||
|
const mutation = `query{
|
||||||
|
categories(first:${first}, filter:{
|
||||||
|
search:"${search}"
|
||||||
|
}){
|
||||||
|
edges{
|
||||||
|
node{
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
return cy.sendRequestWithQuery(mutation);
|
||||||
|
}
|
||||||
|
deleteCategory(categoryId) {
|
||||||
|
const mutation = `mutation{
|
||||||
|
categoryDelete(id:"${categoryId}"){
|
||||||
|
productErrors{
|
||||||
|
field
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
return cy.sendRequestWithQuery(mutation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default Category;
|
53
cypress/apiRequests/Channels.js
Normal file
53
cypress/apiRequests/Channels.js
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
class Channels {
|
||||||
|
createChannel(isActive, name, slug, currencyCode) {
|
||||||
|
const createChannelMutation = `mutation{
|
||||||
|
channelCreate(input: {
|
||||||
|
isActive: ${isActive}
|
||||||
|
name: "${name}"
|
||||||
|
slug: "${slug}"
|
||||||
|
currencyCode: "${currencyCode}"
|
||||||
|
}){
|
||||||
|
channel{
|
||||||
|
name
|
||||||
|
slug
|
||||||
|
}
|
||||||
|
channelErrors{
|
||||||
|
code
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
return cy.sendRequestWithQuery(createChannelMutation);
|
||||||
|
}
|
||||||
|
|
||||||
|
getChannels() {
|
||||||
|
const getChannelsInfoQuery = `query{
|
||||||
|
channels{
|
||||||
|
name
|
||||||
|
id
|
||||||
|
isActive
|
||||||
|
slug
|
||||||
|
currencyCode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
return cy.sendRequestWithQuery(getChannelsInfoQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteChannel(channelId, targetChennelId) {
|
||||||
|
const deleteChannelMutation = `mutation{
|
||||||
|
channelDelete(id: "${channelId}", input:{
|
||||||
|
targetChannel: "${targetChennelId}"
|
||||||
|
}){
|
||||||
|
channel{
|
||||||
|
name
|
||||||
|
}
|
||||||
|
channelErrors{
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
return cy.sendRequestWithQuery(deleteChannelMutation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default Channels;
|
192
cypress/apiRequests/Product.js
Normal file
192
cypress/apiRequests/Product.js
Normal file
|
@ -0,0 +1,192 @@
|
||||||
|
class Product {
|
||||||
|
getFirstProducts(first, search) {
|
||||||
|
let filter = "";
|
||||||
|
if (search) {
|
||||||
|
filter = `, filter:{
|
||||||
|
search:"${search}"
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
const query = `query{
|
||||||
|
products(first:${first}${filter}){
|
||||||
|
edges{
|
||||||
|
node{
|
||||||
|
id
|
||||||
|
name
|
||||||
|
variants{
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
return cy.sendRequestWithQuery(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateChannelInProduct(
|
||||||
|
productId,
|
||||||
|
channelId,
|
||||||
|
isPublished,
|
||||||
|
isAvailableForPurchase
|
||||||
|
) {
|
||||||
|
const mutation = `mutation{
|
||||||
|
productChannelListingUpdate(id:"${productId}",
|
||||||
|
input:{
|
||||||
|
addChannels:{
|
||||||
|
channelId:"${channelId}"
|
||||||
|
isPublished:${isPublished}
|
||||||
|
isAvailableForPurchase:${isAvailableForPurchase}
|
||||||
|
visibleInListings:true
|
||||||
|
}
|
||||||
|
}){
|
||||||
|
product{
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
return cy.sendRequestWithQuery(mutation);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateChannelPriceInVariant(variantId, channelId) {
|
||||||
|
const mutation = `mutation{
|
||||||
|
productVariantChannelListingUpdate(id: "${variantId}", input:{
|
||||||
|
channelId: "${channelId}"
|
||||||
|
price: 10
|
||||||
|
costPrice: 10
|
||||||
|
}){
|
||||||
|
productChannelListingErrors{
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
return cy.sendRequestWithQuery(mutation);
|
||||||
|
}
|
||||||
|
createProduct(attributeId, name, productType, category) {
|
||||||
|
const mutation = `mutation{
|
||||||
|
productCreate(input:{
|
||||||
|
attributes:[{
|
||||||
|
id:"${attributeId}"
|
||||||
|
}]
|
||||||
|
name:"${name}"
|
||||||
|
productType:"${productType}"
|
||||||
|
category:"${category}"
|
||||||
|
}){
|
||||||
|
product{
|
||||||
|
id
|
||||||
|
}
|
||||||
|
productErrors{
|
||||||
|
field
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
return cy.sendRequestWithQuery(mutation);
|
||||||
|
}
|
||||||
|
|
||||||
|
createVariant(
|
||||||
|
productId,
|
||||||
|
sku,
|
||||||
|
warehouseId,
|
||||||
|
quantity,
|
||||||
|
channelId,
|
||||||
|
price = 1,
|
||||||
|
costPrice = 1
|
||||||
|
) {
|
||||||
|
let channelListings = "";
|
||||||
|
let stocks = "";
|
||||||
|
if (channelId) {
|
||||||
|
channelListings = `channelListings:{
|
||||||
|
channelId:"${channelId}"
|
||||||
|
price:"${price}"
|
||||||
|
costPrice:"${costPrice}"
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
if (warehouseId) {
|
||||||
|
stocks = `stocks:{
|
||||||
|
warehouse:"${warehouseId}"
|
||||||
|
quantity:${quantity}
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
const mutation = `mutation{
|
||||||
|
productVariantBulkCreate(product:"${productId}", variants:{
|
||||||
|
attributes:[]
|
||||||
|
sku:"${sku}"
|
||||||
|
${channelListings}
|
||||||
|
${stocks}
|
||||||
|
}){
|
||||||
|
productVariants{
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
bulkProductErrors{
|
||||||
|
field
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
return cy.sendRequestWithQuery(mutation);
|
||||||
|
}
|
||||||
|
|
||||||
|
createTypeProduct(name, attributeId, slug = name) {
|
||||||
|
const mutation = `mutation{
|
||||||
|
productTypeCreate(input:{
|
||||||
|
name:"${name}"
|
||||||
|
slug: "${slug}"
|
||||||
|
isShippingRequired:true
|
||||||
|
productAttributes:"${attributeId}"
|
||||||
|
}){
|
||||||
|
productErrors{
|
||||||
|
field
|
||||||
|
message
|
||||||
|
}
|
||||||
|
productType{
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
return cy.sendRequestWithQuery(mutation);
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteProduct(productId) {
|
||||||
|
const mutation = `mutation{
|
||||||
|
productDelete(id:"${productId}"){
|
||||||
|
productErrors{
|
||||||
|
field
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
return cy.sendRequestWithQuery(mutation);
|
||||||
|
}
|
||||||
|
|
||||||
|
getProductTypes(first, search) {
|
||||||
|
const query = `query{
|
||||||
|
productTypes(first:${first}, filter:{
|
||||||
|
search:"${search}"
|
||||||
|
}){
|
||||||
|
edges{
|
||||||
|
node{
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
return cy.sendRequestWithQuery(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteProductType(productTypeId) {
|
||||||
|
const mutation = `mutation{
|
||||||
|
productTypeDelete(id:"${productTypeId}"){
|
||||||
|
productErrors{
|
||||||
|
field
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
return cy.sendRequestWithQuery(mutation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Product;
|
13
cypress/apiRequests/ShopInfo.js
Normal file
13
cypress/apiRequests/ShopInfo.js
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
class ShopInfo {
|
||||||
|
getShopInfo() {
|
||||||
|
const query = `query{
|
||||||
|
shop{
|
||||||
|
domain{
|
||||||
|
url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
return cy.sendRequestWithQuery(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default ShopInfo;
|
|
@ -1,5 +1,6 @@
|
||||||
/* eslint-disable sort-keys */
|
/* eslint-disable sort-keys */
|
||||||
export const PRODUCTS_SELECTORS = {
|
export const PRODUCTS_SELECTORS = {
|
||||||
|
productsList: "[data-test-id][data-test='id']",
|
||||||
products: "[data-test='submenu-item-label'][data-test-id='products']",
|
products: "[data-test='submenu-item-label'][data-test-id='products']",
|
||||||
createProductBtn: "[data-test='add-product']",
|
createProductBtn: "[data-test='add-product']",
|
||||||
productNameInput: "[name='name']",
|
productNameInput: "[name='name']",
|
||||||
|
@ -11,5 +12,16 @@ export const PRODUCTS_SELECTORS = {
|
||||||
visibleRadioBtn: "[name='isPublished']",
|
visibleRadioBtn: "[name='isPublished']",
|
||||||
saveBtn: "[data-test='button-bar-confirm']",
|
saveBtn: "[data-test='button-bar-confirm']",
|
||||||
confirmationMsg: "[data-test='notification-success']",
|
confirmationMsg: "[data-test='notification-success']",
|
||||||
channelAvailabilityItem: "[data-test='channel-availability-item']"
|
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]"
|
||||||
};
|
};
|
||||||
|
|
5
cypress/elements/frontend-elements/search-selectors.js
Normal file
5
cypress/elements/frontend-elements/search-selectors.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
export const SEARCH_SELECTORS = {
|
||||||
|
searchButton: "[data-test='menuSearchOverlayLink']",
|
||||||
|
searchInputField: "[placeholder='search']",
|
||||||
|
productItem: ".search__products__item"
|
||||||
|
};
|
5
cypress/fixtures/addresses.json
Normal file
5
cypress/fixtures/addresses.json
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"plAddress":{
|
||||||
|
"currency": "PLN"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,47 +0,0 @@
|
||||||
import { LEFT_MENU_SELECTORS } from "../elements/account/left-menu/left-menu-selectors";
|
|
||||||
import { PRODUCTS_SELECTORS } from "../elements/catalog/product-selectors";
|
|
||||||
|
|
||||||
// <reference types="cypress" />
|
|
||||||
describe("Products", () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.clearSessionData().loginUserViaRequest();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should add new visible product", () => {
|
|
||||||
cy.visit("/")
|
|
||||||
.get(LEFT_MENU_SELECTORS.catalog)
|
|
||||||
.click()
|
|
||||||
.get(PRODUCTS_SELECTORS.products)
|
|
||||||
.click()
|
|
||||||
.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");
|
|
||||||
});
|
|
||||||
});
|
|
109
cypress/integration/products/products.js
Normal file
109
cypress/integration/products/products.js
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
import faker from "faker";
|
||||||
|
|
||||||
|
import Channels from "../../apiRequests/Channels";
|
||||||
|
import { LEFT_MENU_SELECTORS } from "../../elements/account/left-menu/left-menu-selectors";
|
||||||
|
import { PRODUCTS_SELECTORS } from "../../elements/catalog/product-selectors";
|
||||||
|
import { BUTTON_SELECTORS } from "../../elements/shared/button-selectors";
|
||||||
|
import { URL_LIST } from "../../url/url-list";
|
||||||
|
import ChannelsUtils from "../../utils/channelsUtils";
|
||||||
|
import ProductsUtils from "../../utils/productsUtils";
|
||||||
|
|
||||||
|
// <reference types="cypress" />
|
||||||
|
describe("Products", () => {
|
||||||
|
const channels = new Channels();
|
||||||
|
const channelsUtils = new ChannelsUtils();
|
||||||
|
const productsUtils = new ProductsUtils();
|
||||||
|
|
||||||
|
const startsWith = "Cy-";
|
||||||
|
|
||||||
|
before(() => {
|
||||||
|
cy.clearSessionData().loginUserViaRequest();
|
||||||
|
productsUtils.deleteProducts(startsWith);
|
||||||
|
channelsUtils.deleteChannels(startsWith);
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.clearSessionData().loginUserViaRequest();
|
||||||
|
});
|
||||||
|
|
||||||
|
xit("should add new visible product", () => {
|
||||||
|
cy.visit("/")
|
||||||
|
.get(LEFT_MENU_SELECTORS.catalog)
|
||||||
|
.click()
|
||||||
|
.get(PRODUCTS_SELECTORS.products)
|
||||||
|
.click()
|
||||||
|
.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");
|
||||||
|
});
|
||||||
|
it("should display correct availibility for product in channel", () => {
|
||||||
|
const name = `${startsWith}${faker.random.number()}`;
|
||||||
|
cy.fixture("addresses").then(json => {
|
||||||
|
channels.createChannel(true, name, name, json.plAddress.currency);
|
||||||
|
productsUtils.createTypeAttributeAndCategoryForProduct(name).then(() => {
|
||||||
|
const productTypeId = productsUtils.getProductTypeId();
|
||||||
|
const attributeId = productsUtils.getAttributeId();
|
||||||
|
const categoryId = productsUtils.getCategoryId();
|
||||||
|
productsUtils.createProduct(
|
||||||
|
name,
|
||||||
|
attributeId,
|
||||||
|
productTypeId,
|
||||||
|
categoryId
|
||||||
|
);
|
||||||
|
cy.visit(URL_LIST.products)
|
||||||
|
.get(PRODUCTS_SELECTORS.searchProducts)
|
||||||
|
.type(name)
|
||||||
|
.get(PRODUCTS_SELECTORS.productsList)
|
||||||
|
.contains(name)
|
||||||
|
.click()
|
||||||
|
.get(PRODUCTS_SELECTORS.availableManageButton)
|
||||||
|
.click()
|
||||||
|
.get(PRODUCTS_SELECTORS.channelsAvailabilityForm)
|
||||||
|
.contains(name)
|
||||||
|
.click()
|
||||||
|
.get(BUTTON_SELECTORS.submit)
|
||||||
|
.click()
|
||||||
|
.get(PRODUCTS_SELECTORS.saveBtn)
|
||||||
|
.click()
|
||||||
|
.get(PRODUCTS_SELECTORS.goBackButton)
|
||||||
|
.click()
|
||||||
|
.get(PRODUCTS_SELECTORS.searchProducts)
|
||||||
|
.type(name)
|
||||||
|
.get(PRODUCTS_SELECTORS.productsList)
|
||||||
|
.contains(name)
|
||||||
|
.parentsUntil("tbody")
|
||||||
|
.find(PRODUCTS_SELECTORS.channelAvailabilityColumn)
|
||||||
|
.click()
|
||||||
|
.get(PRODUCTS_SELECTORS.channelAvailabilityList)
|
||||||
|
.contains(name);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
141
cypress/integration/products/publish.js
Normal file
141
cypress/integration/products/publish.js
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
import faker from "faker";
|
||||||
|
|
||||||
|
import ShopInfo from "../../apiRequests/ShopInfo";
|
||||||
|
import { PRODUCTS_SELECTORS } from "../../elements/catalog/product-selectors";
|
||||||
|
import { SEARCH_SELECTORS } from "../../elements/frontend-elements/search-selectors";
|
||||||
|
import SearchSteps from "../../steps/frontendSteps/searchSteps";
|
||||||
|
import { URL_LIST } from "../../url/url-list";
|
||||||
|
import ChannelsUtils from "../../utils/channelsUtils";
|
||||||
|
import ProductsUtils from "../../utils/productsUtils";
|
||||||
|
|
||||||
|
// <reference types="cypress" />
|
||||||
|
describe("Products", () => {
|
||||||
|
const channelsUtils = new ChannelsUtils();
|
||||||
|
const productsUtils = new ProductsUtils();
|
||||||
|
const searchSteps = new SearchSteps();
|
||||||
|
|
||||||
|
const shopInfo = new ShopInfo();
|
||||||
|
|
||||||
|
const startsWith = "Cy-";
|
||||||
|
const name = `${startsWith}${faker.random.number()}`;
|
||||||
|
let productTypeId;
|
||||||
|
let attributeId;
|
||||||
|
let categoryId;
|
||||||
|
|
||||||
|
before(() => {
|
||||||
|
cy.clearSessionData().loginUserViaRequest();
|
||||||
|
productsUtils.deleteProducts(startsWith);
|
||||||
|
productsUtils.createTypeAttributeAndCategoryForProduct(name).then(() => {
|
||||||
|
productTypeId = productsUtils.getProductTypeId();
|
||||||
|
attributeId = productsUtils.getAttributeId();
|
||||||
|
categoryId = productsUtils.getCategoryId();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.clearSessionData().loginUserViaRequest();
|
||||||
|
shopInfo
|
||||||
|
.getShopInfo()
|
||||||
|
.its("body.data.shop.domain.url")
|
||||||
|
.as("shopUrl");
|
||||||
|
});
|
||||||
|
xit("should display on frontend only published products", () => {
|
||||||
|
const productName = `${startsWith}${faker.random.number()}`;
|
||||||
|
channelsUtils.getDefaultChannel().then(defaultChannel => {
|
||||||
|
productsUtils
|
||||||
|
.createProductInChannel(
|
||||||
|
productName,
|
||||||
|
productTypeId,
|
||||||
|
attributeId,
|
||||||
|
categoryId,
|
||||||
|
defaultChannel.id,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
.then(() => {
|
||||||
|
cy.visit(`${URL_LIST.products}${productsUtils.getCreatedProductId()}`)
|
||||||
|
.get(PRODUCTS_SELECTORS.assignedChannels)
|
||||||
|
.click()
|
||||||
|
.get(PRODUCTS_SELECTORS.publishedRadioButton)
|
||||||
|
.contains("Opublikowany")
|
||||||
|
.click()
|
||||||
|
.get(PRODUCTS_SELECTORS.saveBtn)
|
||||||
|
.click()
|
||||||
|
.waitForGraph("ProductChannelListingUpdate")
|
||||||
|
.get("@shopUrl")
|
||||||
|
.then(shopUrl => {
|
||||||
|
cy.visit(shopUrl);
|
||||||
|
searchSteps.searchFor(name);
|
||||||
|
cy.get(SEARCH_SELECTORS.productItem).contains(name);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it("shouldn't display not published product for unlogged user", () => {
|
||||||
|
const productName = `${startsWith}${faker.random.number()}`;
|
||||||
|
channelsUtils.getDefaultChannel().then(defaultChannel => {
|
||||||
|
productsUtils
|
||||||
|
.createProductInChannel(
|
||||||
|
productName,
|
||||||
|
productTypeId,
|
||||||
|
attributeId,
|
||||||
|
categoryId,
|
||||||
|
defaultChannel.id,
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
.then(() => {
|
||||||
|
cy.visit(`${URL_LIST.products}${productsUtils.getCreatedProductId()}`)
|
||||||
|
.get(PRODUCTS_SELECTORS.assignedChannels)
|
||||||
|
.click()
|
||||||
|
.get(PRODUCTS_SELECTORS.publishedRadioButton)
|
||||||
|
.contains("Nie opublikowano")
|
||||||
|
.click()
|
||||||
|
.get(PRODUCTS_SELECTORS.saveBtn)
|
||||||
|
.click()
|
||||||
|
.waitForGraph("ProductChannelListingUpdate")
|
||||||
|
.get("@shopUrl")
|
||||||
|
.then(shopUrl => {
|
||||||
|
cy.visit(shopUrl);
|
||||||
|
searchSteps.searchFor(name);
|
||||||
|
cy.get(SEARCH_SELECTORS.productItem).should("not.exist");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
xit("should display not published product for staff member", () => {
|
||||||
|
const productName = `${startsWith}${faker.random.number()}`;
|
||||||
|
channelsUtils.getDefaultChannel().then(defaultChannel => {
|
||||||
|
productsUtils
|
||||||
|
.createProductInChannel(
|
||||||
|
productName,
|
||||||
|
productTypeId,
|
||||||
|
attributeId,
|
||||||
|
categoryId,
|
||||||
|
defaultChannel.id,
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
.then(() => {
|
||||||
|
cy.visit(`${URL_LIST.products}${productsUtils.getCreatedProductId()}`)
|
||||||
|
.get(PRODUCTS_SELECTORS.assignedChannels)
|
||||||
|
.click()
|
||||||
|
.get(PRODUCTS_SELECTORS.publishedRadioButton)
|
||||||
|
.contains("Nie opublikowano")
|
||||||
|
.click()
|
||||||
|
.get(PRODUCTS_SELECTORS.saveBtn)
|
||||||
|
.click()
|
||||||
|
.waitForGraph("ProductChannelListingUpdate")
|
||||||
|
.get("@shopUrl")
|
||||||
|
.then(shopUrl => {
|
||||||
|
cy.visit(shopUrl)
|
||||||
|
.loginInShop()
|
||||||
|
.then(() => {
|
||||||
|
searchSteps.searchFor(name);
|
||||||
|
cy.get(SEARCH_SELECTORS.productItem).contains(name);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
11
cypress/steps/frontendSteps/searchSteps.js
Normal file
11
cypress/steps/frontendSteps/searchSteps.js
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { SEARCH_SELECTORS } from "../../elements/frontend-elements/search-selectors";
|
||||||
|
|
||||||
|
class SearchSteps {
|
||||||
|
searchFor(query) {
|
||||||
|
cy.get(SEARCH_SELECTORS.searchButton)
|
||||||
|
.click()
|
||||||
|
.get(SEARCH_SELECTORS.searchInputField)
|
||||||
|
.type(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default SearchSteps;
|
|
@ -17,3 +17,38 @@ Cypress.Commands.add("clearSessionData", () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Cypress.Commands.add("sendRequestWithQuery", query =>
|
||||||
|
cy.request({
|
||||||
|
method: "POST",
|
||||||
|
body: {
|
||||||
|
method: "POST",
|
||||||
|
url: Cypress.env("API_URI"),
|
||||||
|
query
|
||||||
|
},
|
||||||
|
headers: {
|
||||||
|
Authorization: `JWT ${window.sessionStorage.getItem("auth")}`
|
||||||
|
},
|
||||||
|
url: Cypress.env("API_URI")
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
Cypress.Commands.add("waitForGraph", operationName => {
|
||||||
|
const GRAPH_URL = "/graphql";
|
||||||
|
cy.intercept("POST", GRAPH_URL, req => {
|
||||||
|
req.statusCode = 200;
|
||||||
|
const requestBody = req.body;
|
||||||
|
if (Array.isArray(requestBody)) {
|
||||||
|
requestBody.forEach(element => {
|
||||||
|
if (element.operationName === operationName) {
|
||||||
|
req.alias = operationName;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (requestBody.operationName === operationName) {
|
||||||
|
req.alias = operationName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
cy.wait(`@${operationName}`);
|
||||||
|
});
|
||||||
|
|
|
@ -46,3 +46,23 @@ Cypress.Commands.add("loginUserViaRequest", () => {
|
||||||
window.sessionStorage.setItem("auth", resp.body.data.tokenCreate.token);
|
window.sessionStorage.setItem("auth", resp.body.data.tokenCreate.token);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Cypress.Commands.add("loginInShop", () => {
|
||||||
|
cy.request({
|
||||||
|
method: "POST",
|
||||||
|
url: Cypress.env("API_URI"),
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
operationName: "TokenAuth",
|
||||||
|
variables: {
|
||||||
|
email: Cypress.env("USER_NAME"),
|
||||||
|
password: Cypress.env("USER_PASSWORD")
|
||||||
|
},
|
||||||
|
query:
|
||||||
|
"mutation TokenAuth($email: String!, $password: String!) {\n tokenCreate(email: $email, password: $password) {\n token\n errors: accountErrors {\n code\n field\n message\n __typename\n }\n user {\n id\n __typename\n }\n __typename\n }\n}\n"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}).then(resp => {
|
||||||
|
window.localStorage.setItem("token", resp.body[0].data.tokenCreate.token);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
6
cypress/url/url-list.js
Normal file
6
cypress/url/url-list.js
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
export const URL_LIST = {
|
||||||
|
dashbord: "/",
|
||||||
|
channels: "/channels/",
|
||||||
|
products: "/products/",
|
||||||
|
orders: "/orders/"
|
||||||
|
};
|
38
cypress/utils/channelsUtils.js
Normal file
38
cypress/utils/channelsUtils.js
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import Channels from "../apiRequests/Channels";
|
||||||
|
|
||||||
|
class ChannelsUtils {
|
||||||
|
channels = new Channels();
|
||||||
|
|
||||||
|
deleteChannels(nameStartsWith) {
|
||||||
|
this.channels.getChannels().then(resp => {
|
||||||
|
const channelsArray = new Set(resp.body.data.channels);
|
||||||
|
if (channelsArray) {
|
||||||
|
channelsArray.forEach(element => {
|
||||||
|
if (element.name.startsWith(nameStartsWith)) {
|
||||||
|
const targetChannels = Array.from(channelsArray).filter(function(
|
||||||
|
channelElement
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
element.currencyCode === channelElement.currencyCode &&
|
||||||
|
element.id !== channelElement.id
|
||||||
|
);
|
||||||
|
});
|
||||||
|
if (targetChannels[0]) {
|
||||||
|
this.channels.deleteChannel(element.id, targetChannels[0].id);
|
||||||
|
channelsArray.delete(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getDefaultChannel() {
|
||||||
|
return this.channels.getChannels().then(resp => {
|
||||||
|
const channelsArray = resp.body.data.channels;
|
||||||
|
return channelsArray.find(function(channelElement) {
|
||||||
|
return channelElement.slug === "default-channel";
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default ChannelsUtils;
|
153
cypress/utils/productsUtils.js
Normal file
153
cypress/utils/productsUtils.js
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
import Attribute from "../apiRequests/Attribute";
|
||||||
|
import Category from "../apiRequests/Category";
|
||||||
|
import Product from "../apiRequests/Product";
|
||||||
|
|
||||||
|
class ProductsUtils {
|
||||||
|
createdVariantId;
|
||||||
|
createdProductId;
|
||||||
|
productTypeId;
|
||||||
|
attributeId;
|
||||||
|
categoryId;
|
||||||
|
|
||||||
|
updateChannelInProduct(productsList, channelId) {
|
||||||
|
const product = new Product();
|
||||||
|
productsList.forEach(productElement => {
|
||||||
|
product.updateChannelInProduct(productElement.node.id, channelId);
|
||||||
|
const variants = productElement.node.variants;
|
||||||
|
variants.forEach(variant => {
|
||||||
|
product.updateChannelPriceInVariant(variant.id, channelId);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
createProduct(name, attributeId, productTypeId, categoryId) {
|
||||||
|
const product = new Product();
|
||||||
|
return product
|
||||||
|
.createProduct(attributeId, name, productTypeId, categoryId)
|
||||||
|
.then(createProductResp => {
|
||||||
|
this.createdProductId =
|
||||||
|
createProductResp.body.data.productCreate.product.id;
|
||||||
|
return product
|
||||||
|
.createVariant(this.createdProductId, name)
|
||||||
|
.then(createVariantResp => {
|
||||||
|
this.createdVariantId =
|
||||||
|
createVariantResp.body.data.productVariantBulkCreate.productVariants;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
createProductInChannel(
|
||||||
|
name,
|
||||||
|
productTypeId,
|
||||||
|
attributeId,
|
||||||
|
categoryId,
|
||||||
|
channelId,
|
||||||
|
isPublished,
|
||||||
|
isAvailableForPurchase,
|
||||||
|
warehouseId,
|
||||||
|
quantityInWarehouse,
|
||||||
|
price
|
||||||
|
) {
|
||||||
|
const product = new Product();
|
||||||
|
return product
|
||||||
|
.createProduct(attributeId, name, productTypeId, categoryId)
|
||||||
|
.then(createProductResp => {
|
||||||
|
this.createdProductId =
|
||||||
|
createProductResp.body.data.productCreate.product.id;
|
||||||
|
return product
|
||||||
|
.updateChannelInProduct(
|
||||||
|
this.createdProductId,
|
||||||
|
channelId,
|
||||||
|
isPublished,
|
||||||
|
isAvailableForPurchase
|
||||||
|
)
|
||||||
|
.then(() =>
|
||||||
|
product
|
||||||
|
.createVariant(
|
||||||
|
this.createdProductId,
|
||||||
|
name,
|
||||||
|
warehouseId,
|
||||||
|
quantityInWarehouse,
|
||||||
|
channelId,
|
||||||
|
price
|
||||||
|
)
|
||||||
|
.then(createVariantResp => {
|
||||||
|
this.createdVariantId =
|
||||||
|
createVariantResp.body.data.productVariantBulkCreate.productVariants;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
createTypeAttributeAndCategoryForProduct(name) {
|
||||||
|
const attribute = new Attribute();
|
||||||
|
const category = new Category();
|
||||||
|
const product = new Product();
|
||||||
|
return attribute.createAttribute(name).then(createAttributeResp => {
|
||||||
|
this.attributeId =
|
||||||
|
createAttributeResp.body.data.attributeCreate.attribute.id;
|
||||||
|
return product
|
||||||
|
.createTypeProduct(name, this.attributeId)
|
||||||
|
.then(createTypeProductResp => {
|
||||||
|
this.productTypeId =
|
||||||
|
createTypeProductResp.body.data.productTypeCreate.productType.id;
|
||||||
|
return category.createCategory(name).then(categoryResp => {
|
||||||
|
this.categoryId = categoryResp.body.data.categoryCreate.category.id;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getCreatedVariants() {
|
||||||
|
return this.createdVariantId;
|
||||||
|
}
|
||||||
|
getProductTypeId() {
|
||||||
|
return this.productTypeId;
|
||||||
|
}
|
||||||
|
getAttributeId() {
|
||||||
|
return this.attributeId;
|
||||||
|
}
|
||||||
|
getCategoryId() {
|
||||||
|
return this.categoryId;
|
||||||
|
}
|
||||||
|
getCreatedProductId() {
|
||||||
|
return this.createdProductId;
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteProducts(startsWith) {
|
||||||
|
const product = new Product();
|
||||||
|
const attribute = new Attribute();
|
||||||
|
const category = new Category();
|
||||||
|
product.getProductTypes(100, startsWith).then(resp => {
|
||||||
|
const productTypes = resp.body.data.productTypes.edges;
|
||||||
|
productTypes.forEach(productType => {
|
||||||
|
if (productType.node.name.includes(startsWith)) {
|
||||||
|
product.deleteProductType(productType.node.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
attribute.getAttributes(100, startsWith).then(resp => {
|
||||||
|
const attributes = resp.body.data.attributes.edges;
|
||||||
|
attributes.forEach(attributeElement => {
|
||||||
|
if (attributeElement.node.name.includes(startsWith)) {
|
||||||
|
attribute.deleteAttribute(attributeElement.node.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
category.getCategories(100, startsWith).then(resp => {
|
||||||
|
const categories = resp.body.data.categories.edges;
|
||||||
|
categories.forEach(categoryElement => {
|
||||||
|
if (categoryElement.node.name.includes(startsWith)) {
|
||||||
|
category.deleteCategory(categoryElement.node.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
product.getFirstProducts(100, startsWith).then(getProductResp => {
|
||||||
|
const products = getProductResp.body.data.products.edges;
|
||||||
|
products.forEach(productElement => {
|
||||||
|
if (productElement.node.name.includes(startsWith)) {
|
||||||
|
product.deleteProducts(productElement.node.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default ProductsUtils;
|
Loading…
Reference in a new issue