Skip to content

Commit

Permalink
[e2e] Notifications. Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-tsx committed Nov 29, 2023
1 parent 07c81ed commit c23bc53
Show file tree
Hide file tree
Showing 15 changed files with 100 additions and 107 deletions.
6 changes: 3 additions & 3 deletions e2e/src/features/notifications.feature
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ Feature: Notifications
And I press Notification Icon Button on the Home page

And I am on the NotificationsList page
And I check that a notification with 'Test Title' title and 'Test description' description is displayed
And I click on the notification with 'Test Title' title and 'Test description' description
And I check that new notification is displayed
And I click on the new notification

And I am on the NotificationContent page
And The Notification Title Text on the Notification Content page has correct Test Title value
Expand Down Expand Up @@ -35,7 +35,7 @@ Feature: Notifications
And I press Notification Icon Button on the Home page
And I am on the NotificationsList page

Then I check that a notification with 'Test Title' title and 'Test description' description is NOT displayed
Then I check that new notification is NOT displayed



Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { ImportAccountSelectors } from 'src/app/pages/ImportAccount/selectors';

import { Page } from 'e2e/src/classes/page.class';
import { EMPTY_WORD_FOR_INPUTS } from 'e2e/src/utils/input-data.utils';
import { clearDataFromInput, createPageElement, findElement, findElements } from 'e2e/src/utils/search.utils';
import { EMPTY_WORD_FOR_INPUTS, clearDataFromCurrentInput } from 'e2e/src/utils/input-data.utils';
import { createPageElement, findElement, findElements } from 'e2e/src/utils/search.utils';
import { SHORT_TIMEOUT } from 'e2e/src/utils/timing.utils';

export class ImportAccountMnemonicTab extends Page {
Expand Down Expand Up @@ -35,7 +35,7 @@ export class ImportAccountMnemonicTab extends Page {
const input = wordsInputs[i];

await input.focus();
await clearDataFromInput();
await clearDataFromCurrentInput();
}
}

Expand Down
6 changes: 4 additions & 2 deletions e2e/src/page-objects/pages/importing-existing-wallet.page.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { ImportFromSeedPhraseSelectors } from 'src/app/pages/NewWallet/import/ImportSeedPhrase/ImportFromSeedPhrase.selectors';

import { clearDataFromCurrentInput } from 'e2e/src/utils/input-data.utils';

import { Page } from '../../classes/page.class';
import { clearDataFromInput, createPageElement, findElements } from '../../utils/search.utils';
import { createPageElement, findElements } from '../../utils/search.utils';

export class ImportExistingWalletPage extends Page {
nextButton = createPageElement(ImportFromSeedPhraseSelectors.nextButton);
Expand Down Expand Up @@ -31,7 +33,7 @@ export class ImportExistingWalletPage extends Page {
const input = wordsInputs[i];

await input.focus();
await clearDataFromInput();
await clearDataFromCurrentInput();
}
}
}
39 changes: 22 additions & 17 deletions e2e/src/page-objects/pages/notifications-list.page.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { PreviewItemSelectors } from 'src/lib/notifications/components/notifications/preview-item.selectors';
import type { NotificationInterface } from 'src/lib/notifications/types';

import { VERY_SHORT_TIMEOUT } from 'e2e/src/utils/timing.utils';

import { Page } from '../../classes/page.class';
import { createPageElement, findElement } from '../../utils/search.utils';
import { createPageElement } from '../../utils/search.utils';

export class NotificationsListPage extends Page {
newNotification?: NotificationInterface;
notificationItem = createPageElement(PreviewItemSelectors.notificationItem);
notificationItemTitleText = createPageElement(PreviewItemSelectors.notificationItemTitleText);
notificationItemDescriptionText = createPageElement(PreviewItemSelectors.notificationItemDescriptionText);
Expand All @@ -16,31 +18,34 @@ export class NotificationsListPage extends Page {
await this.notificationItemDescriptionText.waitForDisplayed();
}

async isNotificationDisplayed(title: string, description: string) {
const notificationText = await findElement(
PreviewItemSelectors.notificationItemTitleText,
{ title },
async isNotificationDisplayed({ id, title, description }: NotificationInterface) {
const notificationTextElem = createPageElement(PreviewItemSelectors.notificationItem, { id: String(id) });

await notificationTextElem.waitForDisplayed(
VERY_SHORT_TIMEOUT,
`Notification with ${title} title is not displayed`
);

await findElement(
PreviewItemSelectors.notificationItemDescriptionText,
{ description },
VERY_SHORT_TIMEOUT,
`Notification with ${description} description is not displayed`
);
const titleText = await notificationTextElem
.createChildElement(PreviewItemSelectors.notificationItemTitleText)
.getText();
if (titleText !== title) throw new Error(`Notification title missmatch. Got: ${titleText}`);

return notificationText;
const descriptionText = await notificationTextElem
.createChildElement(PreviewItemSelectors.notificationItemDescriptionText)
.getText();
if (descriptionText !== description) throw new Error(`Notification description missmatch. Got: ${descriptionText}`);
}

async clickOnTheNotification(title: string, description: string) {
const selectedNotification = await this.isNotificationDisplayed(title, description);
await selectedNotification.click();
async clickOnTheNotification({ id }: NotificationInterface) {
const notificationTextElem = createPageElement(PreviewItemSelectors.notificationItem, { id: String(id) });
await notificationTextElem.click();
}

async isNotificationNotDisplayed(title: string, description: string) {
await this.isNotificationDisplayed(title, description).then(
async isNotificationNotDisplayed({ id, title }: NotificationInterface) {
const notificationTextElem = createPageElement(PreviewItemSelectors.notificationItem, { id: String(id) });

await notificationTextElem.waitForDisplayed().then(
() => {
throw new Error(`The notification '${title}' is displayed after turning off 'news' checkbox in settings`);
},
Expand Down
4 changes: 2 additions & 2 deletions e2e/src/step-definitions/common.steps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Given } from '@cucumber/cucumber';

import { BrowserContext } from '../classes/browser-context.class';
import { Pages } from '../page-objects';
import { iEnterValues, IEnterValuesKey } from '../utils/input-data.utils';
import { clearDataFromCurrentInput, iEnterValues, IEnterValuesKey } from '../utils/input-data.utils';
import { createPageElement } from '../utils/search.utils';
import { LONG_TIMEOUT, MEDIUM_TIMEOUT, SHORT_TIMEOUT } from '../utils/timing.utils';

Expand All @@ -19,7 +19,7 @@ Given(
{ timeout: MEDIUM_TIMEOUT },
async (elementName: string, pageName: string) => {
await createPageElement(`${pageName}/${elementName}`).click();
await createPageElement(`${pageName}/${elementName}`).clearInput();
await clearDataFromCurrentInput();
}
);

Expand Down
58 changes: 30 additions & 28 deletions e2e/src/step-definitions/notifications.steps.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,30 @@
import { Given } from '@cucumber/cucumber';
import assert from 'assert';
import axios from 'axios';
import type { NotificationInterface } from 'src/lib/notifications/types';

import { envVars } from 'e2e/src/utils/env.utils';
import { MEDIUM_TIMEOUT } from 'e2e/src/utils/timing.utils';

import { Pages } from '../page-objects';

Given(
/I check that a notification with '(.*)' title and '(.*)' description is displayed/,
{ timeout: MEDIUM_TIMEOUT },
async (title: string, shortDescription: string) => {
await Pages.NotificationsList.isNotificationDisplayed(title, shortDescription);
}
);

Given(
/I check that a notification with '(.*)' title and '(.*)' description is NOT displayed/,
{ timeout: MEDIUM_TIMEOUT },
async (title: string, shortDescription: string) => {
await Pages.NotificationsList.isNotificationNotDisplayed(title, shortDescription);
}
);

Given(
/I click on the notification with '(.*)' title and '(.*)' description/,
{ timeout: MEDIUM_TIMEOUT },
async (title: string, shortDescription: string) => {
await Pages.NotificationsList.clickOnTheNotification(title, shortDescription);
}
);
Given(/I check that new notification is displayed/, { timeout: MEDIUM_TIMEOUT }, async () => {
const notification = Pages.NotificationsList.newNotification;
assert(notification);
await Pages.NotificationsList.isNotificationDisplayed(notification);
});

Given(/I check that new notification is NOT displayed/, { timeout: MEDIUM_TIMEOUT }, async () => {
const notification = Pages.NotificationsList.newNotification;
assert(notification);
await Pages.NotificationsList.isNotificationNotDisplayed(notification);
});

Given(/I click on the new notification/, { timeout: MEDIUM_TIMEOUT }, async () => {
const notification = Pages.NotificationsList.newNotification;
assert(notification);
await Pages.NotificationsList.clickOnTheNotification(notification);
});

Given(/I make request for creating a notification/, { timeout: MEDIUM_TIMEOUT }, async () => {
const currentDate = new Date();
Expand All @@ -49,15 +45,21 @@ Given(/I make request for creating a notification/, { timeout: MEDIUM_TIMEOUT },
expirationDate: expirationDateISO
};

const response = await axios.post('https://temple-api-mainnet.stage.madfish.xyz/api/notifications', requestBody, {
headers: {
'Content-Type': 'application/json',
Authorization: envVars.NOTIFICATION_AUTHORIZATION
const response = await axios.post<NotificationInterface>(
'https://temple-api-mainnet.stage.madfish.xyz/api/notifications',
requestBody,
{
headers: {
'Content-Type': 'application/json',
Authorization: envVars.NOTIFICATION_AUTHORIZATION
}
}
});
);

if (response.status !== 200)
throw new Error(
`Some problems with backend server. Server returns ${response.statusText} with ${response.status} status code`
);

Pages.NotificationsList.newNotification = response.data;
});
6 changes: 3 additions & 3 deletions e2e/src/step-definitions/shared.steps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ Given(
/I got the validation-error '(.*)' in the (.*) on the (.*) page/,
{ timeout: MEDIUM_TIMEOUT },
async (errorName: string, parentElementName: string, pageName: string) => {
const childElement = await createPageElement(`${pageName}/${parentElementName}`).findChildSelectors(
ErrorCaptionSelectors.inputError
);
const childElement = await createPageElement(`${pageName}/${parentElementName}`)
.createChildElement(ErrorCaptionSelectors.inputError)
.findElement();
const getErrorContent = await getElementText(childElement);
expect(getErrorContent).eql(errorName);
}
Expand Down
9 changes: 9 additions & 0 deletions e2e/src/utils/input-data.utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { BrowserContext } from '../classes/browser-context.class';
import { envVars } from './env.utils';

export const iComparePrivateKeys = {
Expand Down Expand Up @@ -84,3 +85,11 @@ export const iSelectTokenSlugs = {
wUSDT: 'KT18fp5rcTW7mbWDmzFwjLDUhs5MeJmagDSZ_18',
OBJKTCOM: 'KT1DGbb333QNo3e2cpN3YGL5aRwWzkADcPA3_2' // 'Temple NFT'
};

export const clearDataFromCurrentInput = async () => {
await BrowserContext.page.keyboard.press('End');
await BrowserContext.page.keyboard.down('Shift');
await BrowserContext.page.keyboard.press('Home');
await BrowserContext.page.keyboard.up('Shift');
await BrowserContext.page.keyboard.press('Backspace');
};
49 changes: 14 additions & 35 deletions e2e/src/utils/search.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import { ElementHandle } from 'puppeteer';
import { BrowserContext } from '../classes/browser-context.class';
import { MEDIUM_TIMEOUT } from './timing.utils';

const buildTestIDSelector = (testID: string) => `[data-testid="${testID}"]`;

type OtherSelectors = Record<string, string>;

export const findElement = async (
Expand All @@ -20,20 +18,6 @@ export const findElement = async (
return await findElementBySelectors(selector, timeout, errorTitle);
};

const buildChildSelector = (parentTestID: string, childTestID: string) =>
`${parentTestID} [data-testid="${childTestID}"]`;

export const findChildElement = async (
parentTestID: string,
childTestID: string,
timeout = MEDIUM_TIMEOUT,
errorTitle?: string
) => {
const selectors = buildChildSelector(`[data-testid="${parentTestID}"]`, childTestID);

return await findElementBySelectors(selectors, timeout, errorTitle);
};

export const findElementBySelectors = async (selectors: string, timeout = MEDIUM_TIMEOUT, errorTitle?: string) => {
const element = await BrowserContext.page.waitForSelector(selectors, { visible: true, timeout }).catch(error => {
if (errorTitle && error instanceof Error) {
Expand Down Expand Up @@ -64,18 +48,19 @@ export const findElements = async (testID: string) => {
class PageElement {
constructor(public selector: string) {}

findElement(timeout?: number, errorTitle?: string) {
return findElementBySelectors(this.selector, timeout, errorTitle);
}

findChildSelectors(childSelector: string, timeout?: number, errorTitle?: string) {
createChildElement(testID: string, otherSelectors?: OtherSelectors) {
const childSelector = buildSelector(testID, otherSelectors);
const selectors = buildChildSelector(this.selector, childSelector);

return findElementBySelectors(selectors, timeout, errorTitle);
return new PageElement(selectors);
}

findElement(timeout?: number, errorTitle?: string) {
return findElementBySelectors(this.selector, timeout, errorTitle);
}

waitForDisplayed(timeout?: number) {
return this.findElement(timeout);
waitForDisplayed(timeout?: number, errorTitle?: string) {
return this.findElement(timeout, errorTitle);
}

async click() {
Expand All @@ -88,13 +73,11 @@ class PageElement {
await element.type(text);
}

async clearInput() {
await clearDataFromInput();
}
async getText() {
const element = await this.findElement();
return getElementText(element);
}

async waitForText(expectedText: string, timeout = MEDIUM_TIMEOUT) {
const element = await this.findElement(timeout);

Expand Down Expand Up @@ -137,13 +120,15 @@ export const getElementText = (element: ElementHandle) =>
return textContent;
});

const buildTestIDSelector = (testID: string) => `[data-testid="${testID}"]`;

const buildSelectorPairs = (selectors: OtherSelectors) => {
return Object.entries(selectors).map(([key, val]) =>
val ? (`data-${key}="${val}"` as const) : (`data-${key}` as const)
);
};

const buildSelector = (testID: string, otherSelectors?: OtherSelectors) => {
export const buildSelector = (testID: string, otherSelectors?: OtherSelectors) => {
const pairs = buildSelectorPairs({ ...otherSelectors, testid: testID });
return `[${pairs.join('][')}]`;
};
Expand All @@ -153,10 +138,4 @@ const buildNotSelector = (notSelectors: OtherSelectors) => {
return `:not([${pairs.join(']):not([')}])`;
};

export const clearDataFromInput = async () => {
await BrowserContext.page.keyboard.press('End');
await BrowserContext.page.keyboard.down('Shift');
await BrowserContext.page.keyboard.press('Home');
await BrowserContext.page.keyboard.up('Shift');
await BrowserContext.page.keyboard.press('Backspace');
};
const buildChildSelector = (parentSelector: string, childSelector: string) => `${parentSelector} ${childSelector}`;
2 changes: 1 addition & 1 deletion src/lib/notifications/components/item/content.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { FC } from 'react';

import { setTestID, TestIDProps } from '../../../analytics';
import { NotificationInterface } from '../../interfaces/notification.interface';
import { NotificationInterface } from '../../types';

type Props = TestIDProps & Pick<NotificationInterface, 'content'>;

Expand Down
Loading

0 comments on commit c23bc53

Please sign in to comment.