tests for dashboard

This commit is contained in:
Karolina Rakoczy 2021-02-11 13:20:00 +01:00
parent fe9f55ee81
commit 27e5d912e4
14 changed files with 81 additions and 49 deletions

View file

@ -55,10 +55,10 @@ class Channels {
}); });
} }
deleteChannel(channelId, targetChennelId) { deleteChannel(channelId, targetChannelId) {
const deleteChannelMutation = `mutation{ const deleteChannelMutation = `mutation{
channelDelete(id: "${channelId}", input:{ channelDelete(id: "${channelId}", input:{
targetChannel: "${targetChennelId}" targetChannel: "${targetChannelId}"
}){ }){
channel{ channel{
name name

View file

@ -50,7 +50,7 @@ class Checkout {
}`; }`;
return cy.sendRequestWithQuery(mutation); return cy.sendRequestWithQuery(mutation);
} }
compliteCheckout(checkoutId) { completeCheckout(checkoutId) {
const mutation = `mutation{ const mutation = `mutation{
checkoutComplete(checkoutId:"${checkoutId}"){ checkoutComplete(checkoutId:"${checkoutId}"){
order{ order{

View file

@ -1,11 +1,10 @@
export const DASHBOARD_SELECTORS = { export const DASHBOARD_SELECTORS = {
sales: "div:nth-child(1) > [class*='HomeAnalyticsCard-cardContent']", sales: "[data-test-id='sales-analytics']",
orders: "div:nth-child(2) > [class*='HomeAnalyticsCard-cardContent']", orders: "[data-test-id='orders-analytics']",
activity: "[class*='Grid-root'] > div:nth-child(2) > [class*='MuiPaper']", activity: "[data-test-id='activity-card']",
topProducts: topProducts: "[data-test-id='top-products']",
"[class*='Grid-root'] > div:nth-child(1) > [class*='MuiPaper']:nth-child(4)", ordersReadyToFulfill: "[data-test-id='orders-to-fulfill']",
ordersReadyToFulfill: "[class*='HomeNotificationTable'] > tr:nth-child(1)", paymentsWaitingForCapture: "[data-test-id='orders-to-capture']",
paymentsWaitingForCapture: productsOutOfStock: "[data-test-id='products-out-of-stock']",
"[class*='HomeNotificationTable'] > tr:nth-child(2)", dataAreLoading: "[class*='Skeleton-skeleton']"
productsOutOfStock: "[class*='HomeNotificationTable'] > tr:nth-child(3)"
}; };

View file

@ -30,15 +30,15 @@ describe("User authorization", () => {
cy.clearSessionData().loginUserViaRequest(); cy.clearSessionData().loginUserViaRequest();
}); });
xit("should all elements be visible on the dashboard", () => { it("should all elements be visible on the dashboard", () => {
cy.visit("/"); cy.visit("/")
softAssertVisibility(DASHBOARD_SELECTORS.sales); .softAssertVisibility(DASHBOARD_SELECTORS.sales)
softAssertVisibility(DASHBOARD_SELECTORS.orders); .softAssertVisibility(DASHBOARD_SELECTORS.orders)
softAssertVisibility(DASHBOARD_SELECTORS.activity); .softAssertVisibility(DASHBOARD_SELECTORS.activity)
softAssertVisibility(DASHBOARD_SELECTORS.topProducts); .softAssertVisibility(DASHBOARD_SELECTORS.topProducts)
softAssertVisibility(DASHBOARD_SELECTORS.ordersReadyToFulfill); .softAssertVisibility(DASHBOARD_SELECTORS.ordersReadyToFulfill)
softAssertVisibility(DASHBOARD_SELECTORS.paymentsWaitingForCapture); .softAssertVisibility(DASHBOARD_SELECTORS.paymentsWaitingForCapture)
softAssertVisibility(DASHBOARD_SELECTORS.productsOutOfStock); .softAssertVisibility(DASHBOARD_SELECTORS.productsOutOfStock);
}); });
it("should correct amount of orders be displayed", () => { it("should correct amount of orders be displayed", () => {
@ -47,6 +47,9 @@ describe("User authorization", () => {
const randomNameProductOutOfStock = `${startsWith}${faker.random.number()}`; const randomNameProductOutOfStock = `${startsWith}${faker.random.number()}`;
const shippingPrice = 12; const shippingPrice = 12;
const productPrice = 22; const productPrice = 22;
let sales = productPrice * 2 + shippingPrice;
// Create channel, customer, product - everything needed to create order
cy.fixture("addresses").then(json => { cy.fixture("addresses").then(json => {
channels channels
.createChannel(true, randomName, randomName, json.plAddress.currency) .createChannel(true, randomName, randomName, json.plAddress.currency)
@ -87,12 +90,16 @@ describe("User authorization", () => {
) )
.then(() => { .then(() => {
const variantsList = productsUtils.getCreatedVariants(); const variantsList = productsUtils.getCreatedVariants();
ordersUtils.createReadyToFullfillOrder(
// Create order ready to fulfill
ordersUtils.createReadyToFulfillOrder(
customerId, customerId,
shippingId, shippingId,
channelId, channelId,
variantsList variantsList
); );
// Create order waiting for capture
ordersUtils.createWaitingForCaptureOrder( ordersUtils.createWaitingForCaptureOrder(
channelSlug, channelSlug,
customerEmail, customerEmail,
@ -100,6 +107,8 @@ describe("User authorization", () => {
shippingId shippingId
); );
}); });
// Create product out of stock
productsUtils.createProductInChannel( productsUtils.createProductInChannel(
randomNameProductOutOfStock, randomNameProductOutOfStock,
channelId, channelId,
@ -120,18 +129,18 @@ describe("User authorization", () => {
.click() .click()
.get(HEADER_SELECTORS.channelSelectList) .get(HEADER_SELECTORS.channelSelectList)
.contains(randomName) .contains(randomName)
.click(); .click()
.get(DASHBOARD_SELECTORS.dataAreLoading)
.should("not.exist");
const regex = /^1\D+/;
sales = sales.toFixed(2).replace(".", ",");
cy.softAssertMatch(DASHBOARD_SELECTORS.ordersReadyToFulfill, regex)
.softAssertMatch(DASHBOARD_SELECTORS.paymentsWaitingForCapture, regex)
.softAssertMatch(DASHBOARD_SELECTORS.productsOutOfStock, regex)
.softAssertMatch(
DASHBOARD_SELECTORS.sales,
new RegExp(`\\D+${sales}\\D+`)
)
.softAssertMatch(DASHBOARD_SELECTORS.orders, /\D+2\D*/);
}); });
function softAssertVisibility(selector) {
cy.get(selector).then(element => chai.softExpect(element).to.be.visible);
}
function softAssertMatch(selector, regexp) {
cy.get(selector)
.invoke("text")
.then(text =>
chai.softExpect(assert.match(text, regexp, "regexp matches"))
);
}
}); });

View file

@ -76,3 +76,14 @@ afterEach(() => {
errors = []; errors = [];
isSoftAssertion = false; isSoftAssertion = false;
}); });
Cypress.Commands.add("softAssertMatch", (selector, regexp) => {
cy.get(selector)
.invoke("text")
.then(text =>
chai.softExpect(assert.match(text, regexp, "regexp matches"))
);
});
Cypress.Commands.add("softAssertVisibility", selector => {
cy.get(selector).then(element => chai.softExpect(element).to.be.visible);
});

View file

@ -19,11 +19,11 @@ class OrdersUtils {
.then(() => .then(() =>
checkout checkout
.addPayment(checkoutId, "mirumee.payments.dummy", "not-charged") .addPayment(checkoutId, "mirumee.payments.dummy", "not-charged")
.then(() => checkout.compliteCheckout(checkoutId)) .then(() => checkout.completeCheckout(checkoutId))
); );
}); });
} }
createReadyToFullfillOrder( createReadyToFulfillOrder(
customerId, customerId,
shippingMethodId, shippingMethodId,
channelId, channelId,

View file

@ -121,4 +121,4 @@ class ProductsUtils {
}); });
} }
} }
export default productsUtils; export default ProductsUtils;

View file

@ -38,6 +38,7 @@ const AppChannelSelect: React.FC<AppChannelSelectProps> = ({
return ( return (
<div className={classes.root}> <div className={classes.root}>
<SingleSelectField <SingleSelectField
testId="app-channel-select"
choices={mapNodeToChoice(channels)} choices={mapNodeToChoice(channels)}
disabled={disabled} disabled={disabled}
value={selectedChannelId} value={selectedChannelId}

View file

@ -35,6 +35,7 @@ export interface Choice {
export type Choices = Choice[]; export type Choices = Choice[];
interface SingleSelectFieldProps { interface SingleSelectFieldProps {
testId?: string;
choices: Choices; choices: Choices;
className?: string; className?: string;
disabled?: boolean; disabled?: boolean;
@ -62,7 +63,8 @@ export const SingleSelectField: React.FC<SingleSelectFieldProps> = props => {
hint, hint,
selectProps, selectProps,
placeholder, placeholder,
InputProps InputProps,
testId
} = props; } = props;
const classes = useStyles(props); const classes = useStyles(props);
@ -84,6 +86,7 @@ export const SingleSelectField: React.FC<SingleSelectFieldProps> = props => {
{label} {label}
</InputLabel> </InputLabel>
<Select <Select
data-test-id={testId}
variant="outlined" variant="outlined"
fullWidth fullWidth
renderValue={choiceValue => renderValue={choiceValue =>

View file

@ -30,16 +30,17 @@ const useStyles = makeStyles(
interface HomeActivityCardProps { interface HomeActivityCardProps {
activities: Home_activities_edges_node[]; activities: Home_activities_edges_node[];
testId?: string;
} }
const HomeActivityCard: React.FC<HomeActivityCardProps> = props => { const HomeActivityCard: React.FC<HomeActivityCardProps> = props => {
const { activities } = props; const { activities, testId } = props;
const classes = useStyles(props); const classes = useStyles(props);
const intl = useIntl(); const intl = useIntl();
return ( return (
<Card> <Card data-test-id={testId}>
<CardTitle <CardTitle
title={intl.formatMessage({ title={intl.formatMessage({
defaultMessage: "Activity", defaultMessage: "Activity",

View file

@ -53,19 +53,20 @@ const useStyles = makeStyles(
); );
interface HomeAnalyticsCardProps { interface HomeAnalyticsCardProps {
testId?: string;
icon: React.ReactElement<IconProps>; icon: React.ReactElement<IconProps>;
title: string; title: string;
children?: React.ReactNode; children?: React.ReactNode;
} }
const HomeAnalyticsCard: React.FC<HomeAnalyticsCardProps> = props => { const HomeAnalyticsCard: React.FC<HomeAnalyticsCardProps> = props => {
const { children, title, icon } = props; const { children, title, icon, testId } = props;
const classes = useStyles(props); const classes = useStyles(props);
return ( return (
<Card className={classes.cardSpacing}> <Card className={classes.cardSpacing}>
<CardContent className={classes.cardContent}> <CardContent className={classes.cardContent} data-test-id={testId}>
<div> <div>
<Typography className={classes.cardTitle} variant="subtitle1"> <Typography className={classes.cardTitle} variant="subtitle1">
{title} {title}

View file

@ -111,7 +111,7 @@ const HomeNotificationTable: React.FC<HomeNotificationTableProps> = props => {
requiredPermissions={[PermissionEnum.MANAGE_ORDERS]} requiredPermissions={[PermissionEnum.MANAGE_ORDERS]}
> >
<TableRow hover={true} onClick={onOrdersToFulfillClick}> <TableRow hover={true} onClick={onOrdersToFulfillClick}>
<TableCell> <TableCell data-test-id="orders-to-fulfill">
{ordersToFulfill === undefined ? ( {ordersToFulfill === undefined ? (
<Skeleton /> <Skeleton />
) : ordersToFulfill === 0 ? ( ) : ordersToFulfill === 0 ? (
@ -131,7 +131,7 @@ const HomeNotificationTable: React.FC<HomeNotificationTableProps> = props => {
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow hover={true} onClick={onOrdersToCaptureClick}> <TableRow hover={true} onClick={onOrdersToCaptureClick}>
<TableCell> <TableCell data-test-id="orders-to-capture">
{ordersToCapture === undefined ? ( {ordersToCapture === undefined ? (
<Skeleton /> <Skeleton />
) : ordersToCapture === 0 ? ( ) : ordersToCapture === 0 ? (
@ -156,7 +156,7 @@ const HomeNotificationTable: React.FC<HomeNotificationTableProps> = props => {
requiredPermissions={[PermissionEnum.MANAGE_PRODUCTS]} requiredPermissions={[PermissionEnum.MANAGE_PRODUCTS]}
> >
<TableRow hover={true} onClick={onProductsOutOfStockClick}> <TableRow hover={true} onClick={onProductsOutOfStockClick}>
<TableCell> <TableCell data-test-id="products-out-of-stock">
{productsOutOfStock === undefined ? ( {productsOutOfStock === undefined ? (
<Skeleton /> <Skeleton />
) : productsOutOfStock === 0 ? ( ) : productsOutOfStock === 0 ? (

View file

@ -95,6 +95,7 @@ const HomePage: React.FC<HomePageProps> = props => {
<div className={classes.cardContainer}> <div className={classes.cardContainer}>
<HomeAnalyticsCard <HomeAnalyticsCard
title={"Sales"} title={"Sales"}
testId="sales-analytics"
icon={ icon={
<Sales <Sales
className={classes.icon} className={classes.icon}
@ -113,6 +114,7 @@ const HomePage: React.FC<HomePageProps> = props => {
</HomeAnalyticsCard> </HomeAnalyticsCard>
<HomeAnalyticsCard <HomeAnalyticsCard
title={"Orders"} title={"Orders"}
testId="orders-analytics"
icon={ icon={
<Orders <Orders
className={classes.icon} className={classes.icon}
@ -152,6 +154,7 @@ const HomePage: React.FC<HomePageProps> = props => {
]} ]}
> >
<HomeProductListCard <HomeProductListCard
testId="top-products"
onRowClick={onProductClick} onRowClick={onProductClick}
topProducts={topProducts} topProducts={topProducts}
/> />
@ -165,7 +168,10 @@ const HomePage: React.FC<HomePageProps> = props => {
userPermissions={userPermissions} userPermissions={userPermissions}
requiredPermissions={[PermissionEnum.MANAGE_ORDERS]} requiredPermissions={[PermissionEnum.MANAGE_ORDERS]}
> >
<HomeActivityCard activities={activities} /> <HomeActivityCard
activities={activities}
testId="activity-card"
/>
</RequirePermissions> </RequirePermissions>
</div> </div>
)} )}

View file

@ -46,18 +46,19 @@ const useStyles = makeStyles(
); );
interface HomeProductListProps { interface HomeProductListProps {
testId?: string;
topProducts: Home_productTopToday_edges_node[]; topProducts: Home_productTopToday_edges_node[];
onRowClick: (productId: string, variantId: string) => void; onRowClick: (productId: string, variantId: string) => void;
} }
export const HomeProductList: React.FC<HomeProductListProps> = props => { export const HomeProductList: React.FC<HomeProductListProps> = props => {
const { topProducts, onRowClick } = props; const { topProducts, onRowClick, testId } = props;
const classes = useStyles(props); const classes = useStyles(props);
const intl = useIntl(); const intl = useIntl();
return ( return (
<Card> <Card data-test-id={testId}>
<CardTitle <CardTitle
title={intl.formatMessage({ title={intl.formatMessage({
defaultMessage: "Top Products", defaultMessage: "Top Products",