Skip to content

Commit 3481c47

Browse files
committed
test: add remaining e2e tests for notifications
1 parent b062017 commit 3481c47

File tree

14 files changed

+356
-39
lines changed

14 files changed

+356
-39
lines changed

apps/browser-extension-wallet/src/features/notifications-center/EmptyState.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ export const EmptyState = (): React.ReactElement => {
99

1010
return (
1111
<Flex flexDirection="column" gap="$20" alignItems="center" justifyContent="center" data-testid="empty-state">
12-
<SmileyFaceIcon className={styles.icon} />
12+
<SmileyFaceIcon data-testid="empty-state-image" className={styles.icon} />
1313
<Flex alignItems="center" flexDirection="column" gap="$0">
14-
<Text.Body.Large>{t('notificationsCenter.emptyState.title')}</Text.Body.Large>
15-
<Text.Body.Small color="secondary">{t('notificationsCenter.emptyState.description')}</Text.Body.Small>
14+
<Text.Body.Large data-testid="empty-state-title">{t('notificationsCenter.emptyState.title')}</Text.Body.Large>
15+
<Text.Body.Small color="secondary" data-testid="empty-state-description">
16+
{t('notificationsCenter.emptyState.description')}
17+
</Text.Body.Small>
1618
</Flex>
1719
</Flex>
1820
);

apps/browser-extension-wallet/src/features/notifications-center/SubscriptionsDropDown.tsx

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,14 @@ export const SubscriptionsDropDown = ({
2222
const { t } = useTranslation();
2323

2424
return (
25-
<Menu className={classnames(styles.container, { [styles.popupView]: popupView })}>
25+
<Menu
26+
className={classnames(styles.container, { [styles.popupView]: popupView })}
27+
data-testid="subscriptions-dropdown"
28+
>
2629
<Flex className={styles.content} gap="$24" flexDirection="column" justifyContent="space-between">
27-
<Text.Label color="secondary">{t('notificationsCenter.chooseSubject')}</Text.Label>
30+
<Text.Label color="secondary" data-testid="subscriptions-dropdown-description">
31+
{t('notificationsCenter.chooseSubject')}
32+
</Text.Label>
2833
<Flex w="$fill" gap="$24" flexDirection="column" justifyContent="space-between">
2934
{topics.map((topic) => (
3035
<Flex
@@ -35,13 +40,18 @@ export const SubscriptionsDropDown = ({
3540
alignItems="center"
3641
justifyContent="space-between"
3742
>
38-
<Text.Body.Normal weight="$medium" className={styles.toggleLabel} color="secondary">
43+
<Text.Body.Normal
44+
weight="$medium"
45+
className={styles.toggleLabel}
46+
color="secondary"
47+
data-testid="subscriptions-toggle-topic-name"
48+
>
3949
{topic.name}
4050
</Text.Body.Normal>
4151
<ToggleSwitch
4252
key={topic.id}
4353
defaultChecked={topic.subscribed}
44-
data-testid={`subscriptions-toggle-${topic.id}`}
54+
testId={`subscriptions-${topic.id}-`}
4555
onCheckedChange={(isChecked) => onTopicChange(topic, isChecked)}
4656
/>
4757
</Flex>

packages/e2e-tests/src/assert/notifications/NotificationCenterAssert.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ class NotificationCenterAssert {
1313
await NotificationCenter.sectionTitleCounter.waitForDisplayed();
1414
expect(await NotificationCenter.getCounterValue()).to.be.greaterThan(0);
1515

16-
await NotificationCenter.subscriptionsDropdown.waitForDisplayed();
17-
expect(await NotificationCenter.subscriptionsDropdown.getText()).to.equal(
16+
await NotificationCenter.subscriptionsButton.waitForDisplayed();
17+
expect(await NotificationCenter.subscriptionsButton.getText()).to.equal(
1818
await t('notificationsCenter.subscriptions')
1919
);
2020
if (mode === 'extended') {
@@ -65,7 +65,11 @@ class NotificationCenterAssert {
6565
}
6666
}
6767

68-
async assertSeeExpectedNumberOfUnreadNotifications(expectedCount: number, location: 'menu' | 'page') {
68+
async assertSeeExpectedNumberOfNotifications(
69+
expectedCount: number,
70+
location: 'menu' | 'page',
71+
status: 'read' | 'unread'
72+
) {
6973
for (let i = 1; i <= expectedCount; i++) {
7074
const notification = new NotificationListItem(location, i);
7175
await notification.title.waitForDisplayed();
@@ -77,7 +81,11 @@ class NotificationCenterAssert {
7781
expect(publisher).to.not.be.empty;
7882

7983
const isUnread = await notification.isUnread();
80-
expect(isUnread).to.be.true;
84+
if (status === 'unread') {
85+
expect(isUnread).to.be.true;
86+
} else {
87+
expect(isUnread).to.be.false;
88+
}
8189
}
8290
}
8391

@@ -97,6 +105,10 @@ class NotificationCenterAssert {
97105
}
98106
);
99107
}
108+
109+
async assertSeeViewAllButton(shouldSee: boolean) {
110+
await NotificationCenter.markAllAsReadButton.waitForDisplayed({ reverse: !shouldSee });
111+
}
100112
}
101113

102114
export default new NotificationCenterAssert();
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import NotificationsEmptyState from '../../elements/notifications/NotificationsEmptyState';
2+
import { expect } from 'chai';
3+
import { t } from '../../utils/translationService';
4+
5+
class NotificationsEmptyStateAssert {
6+
async assertSeeEmptyState(location: 'menu' | 'page') {
7+
const emptyState = new NotificationsEmptyState(location);
8+
9+
await emptyState.emptyStateImage.waitForDisplayed();
10+
11+
await emptyState.emptyStateTitle.waitForDisplayed();
12+
expect(await emptyState.getTitle()).to.equal(await t('notificationsCenter.emptyState.title'));
13+
14+
await emptyState.emptyStateDescription.waitForDisplayed();
15+
expect(await emptyState.getDescription()).to.equal(await t('notificationsCenter.emptyState.description'));
16+
}
17+
}
18+
19+
export default new NotificationsEmptyStateAssert();

packages/e2e-tests/src/assert/notifications/NotificationsMenuAssert.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ class NotificationsMenuAssert {
4242

4343
return { unreadCount, readCount };
4444
}
45+
46+
async assertSeeViewAllButton(shouldSee: boolean) {
47+
await NotificationsMenu.markAllAsReadButton.waitForDisplayed({ reverse: !shouldSee });
48+
}
4549
}
4650

4751
export default new NotificationsMenuAssert();
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import SubscriptionsDropdown from '../../elements/notifications/SubscriptionsDropdown';
2+
import { expect } from 'chai';
3+
import { t } from '../../utils/translationService';
4+
5+
class SubscriptionsDropdownAssert {
6+
async assertSeeSubscriptionsDropdown() {
7+
await SubscriptionsDropdown.dropdownMenu.waitForDisplayed();
8+
9+
await SubscriptionsDropdown.dropdownDescription.waitForDisplayed();
10+
expect(await SubscriptionsDropdown.getDropdownDescriptionText()).to.equal(
11+
await t('notificationsCenter.chooseSubject')
12+
);
13+
}
14+
15+
async assertTopicSubscriptionState(topicId: string, shouldBeSubscribed: boolean) {
16+
const isSubscribed = await SubscriptionsDropdown.isTopicSubscribed(topicId);
17+
expect(isSubscribed).to.equal(shouldBeSubscribed);
18+
}
19+
}
20+
21+
export default new SubscriptionsDropdownAssert();

packages/e2e-tests/src/assert/topNavigationAssert.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,14 @@ class TopNavigationAssert {
3333
}
3434

3535
async assertSeeUnreadNotificationsCounter(expectedCount: number) {
36-
await MenuHeader.unreadNotificationsCounter.waitForDisplayed();
37-
expect(await MenuHeader.unreadNotificationsCounter.getText()).to.equal(expectedCount > 9 ? '9+' : expectedCount);
36+
if (expectedCount === 0) {
37+
await MenuHeader.unreadNotificationsCounter.waitForDisplayed({ reverse: true });
38+
} else {
39+
await MenuHeader.unreadNotificationsCounter.waitForDisplayed();
40+
expect(await MenuHeader.unreadNotificationsCounter.getText()).to.equal(
41+
expectedCount > 9 ? '9+' : expectedCount.toString()
42+
);
43+
}
3844
}
3945

4046
async assertLogoPresent() {

packages/e2e-tests/src/elements/notifications/NotificationCenter.ts

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class NotificationCenter {
66
private readonly SECTION_TITLE = '[data-testid="section-title"]';
77
private readonly NAVIGATION_BUTTON_BACK = '[data-testid="navigation-button-arrow"]';
88
private readonly SECTION_TITLE_COUNTER = '[data-testid="section-title-counter"]';
9-
private readonly SUBSCRIPTIONS_DROPDOWN = '[data-testid="subscriptions"]';
9+
private readonly SUBSCRIPTIONS_BUTTON = '[data-testid="subscriptions"]';
1010
private readonly MARK_ALL_AS_READ_BUTTON = '[data-testid="mark-all-as-read-button"]';
1111
private readonly NOTIFICATIONS_LIST = '[data-testid="notifications-list"]';
1212

@@ -22,8 +22,8 @@ class NotificationCenter {
2222
return $(this.SECTION_TITLE_COUNTER);
2323
}
2424

25-
get subscriptionsDropdown(): ChainablePromiseElement<WebdriverIO.Element> {
26-
return $(this.SUBSCRIPTIONS_DROPDOWN);
25+
get subscriptionsButton(): ChainablePromiseElement<WebdriverIO.Element> {
26+
return $(this.SUBSCRIPTIONS_BUTTON);
2727
}
2828

2929
get markAllAsReadButton(): ChainablePromiseElement<WebdriverIO.Element> {
@@ -34,19 +34,23 @@ class NotificationCenter {
3434
return $(this.NOTIFICATIONS_LIST);
3535
}
3636

37-
async clickBackButton(): Promise<void> {
38-
await this.navigationButtonBack.waitForClickable();
39-
await this.navigationButtonBack.click();
40-
}
41-
42-
async clickSubscriptionsDropdown(): Promise<void> {
43-
await this.subscriptionsDropdown.waitForClickable();
44-
await this.subscriptionsDropdown.click();
45-
}
46-
47-
async clickMarkAllAsReadButton(): Promise<void> {
48-
await this.markAllAsReadButton.waitForClickable();
49-
await this.markAllAsReadButton.click();
37+
async clickOnButton(button: 'Back' | 'Subscriptions' | 'Mark all as read') {
38+
switch (button) {
39+
case 'Back':
40+
await this.navigationButtonBack.waitForClickable();
41+
await this.navigationButtonBack.click();
42+
break;
43+
case 'Subscriptions':
44+
await this.subscriptionsButton.waitForClickable();
45+
await this.subscriptionsButton.click();
46+
break;
47+
case 'Mark all as read':
48+
await this.markAllAsReadButton.waitForClickable();
49+
await this.markAllAsReadButton.click();
50+
break;
51+
default:
52+
throw new Error(`Unsupported button: ${button}`);
53+
}
5054
}
5155

5256
async getCounterValue(): Promise<number> {
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/* global WebdriverIO */
2+
import type { ChainablePromiseElement } from 'webdriverio';
3+
4+
class NotificationsEmptyState {
5+
private readonly EMPTY_STATE_IMAGE = '[data-testid="empty-state-image"]';
6+
private readonly EMPTY_STATE_TITLE = '[data-testid="empty-state-title"]';
7+
private readonly EMPTY_STATE_DESCRIPTION = '[data-testid="empty-state-description"]';
8+
9+
private static readonly ANT_DROPDOWN_MENU = '.ant-dropdown-menu';
10+
private static readonly PAGE_CONTENT = ':is(#content, #contentLayout)';
11+
12+
private readonly location: 'menu' | 'page';
13+
14+
constructor(location: 'menu' | 'page') {
15+
this.location = location;
16+
}
17+
18+
private getSelector(elementSelector: string): string {
19+
const wrapper =
20+
this.location === 'menu' ? NotificationsEmptyState.ANT_DROPDOWN_MENU : NotificationsEmptyState.PAGE_CONTENT;
21+
return `${wrapper} ${elementSelector}`;
22+
}
23+
24+
get emptyStateImage(): ChainablePromiseElement<WebdriverIO.Element> {
25+
return $(this.getSelector(this.EMPTY_STATE_IMAGE));
26+
}
27+
28+
get emptyStateTitle(): ChainablePromiseElement<WebdriverIO.Element> {
29+
return $(this.getSelector(this.EMPTY_STATE_TITLE));
30+
}
31+
32+
get emptyStateDescription(): ChainablePromiseElement<WebdriverIO.Element> {
33+
return $(this.getSelector(this.EMPTY_STATE_DESCRIPTION));
34+
}
35+
36+
async getTitle(): Promise<string> {
37+
return await this.emptyStateTitle.getText();
38+
}
39+
40+
async getDescription(): Promise<string> {
41+
return await this.emptyStateDescription.getText();
42+
}
43+
}
44+
45+
export default NotificationsEmptyState;
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/* global WebdriverIO */
2+
import type { ChainablePromiseElement } from 'webdriverio';
3+
4+
class SubscriptionsDropdown {
5+
private readonly DROPDOWN_MENU = '[data-testid="subscriptions-dropdown"]';
6+
private readonly DROPDOWN_DESCRIPTION = '[data-testid="subscriptions-dropdown-description"]';
7+
8+
get dropdownDescription(): ChainablePromiseElement<WebdriverIO.Element> {
9+
return $(this.DROPDOWN_DESCRIPTION);
10+
}
11+
12+
private getTopicToggleSwitchSelector(topicId: string): string {
13+
return `[data-testid="subscriptions-${topicId}-toggle-switch"]`;
14+
}
15+
16+
get dropdownMenu(): ChainablePromiseElement<WebdriverIO.Element> {
17+
return $(this.DROPDOWN_MENU);
18+
}
19+
20+
getTopicToggleSwitch(topicId: string): ChainablePromiseElement<WebdriverIO.Element> {
21+
return $(this.getTopicToggleSwitchSelector(topicId));
22+
}
23+
24+
async getDropdownDescriptionText(): Promise<string> {
25+
return await this.dropdownDescription.getText();
26+
}
27+
28+
async isTopicSubscribed(topicId: string): Promise<boolean> {
29+
const toggleSwitch = this.getTopicToggleSwitch(topicId);
30+
const ariaChecked = await toggleSwitch.getAttribute('aria-checked');
31+
return ariaChecked === 'true';
32+
}
33+
34+
async toggleTopic(topicId: string): Promise<void> {
35+
const toggleSwitch = this.getTopicToggleSwitch(topicId);
36+
await toggleSwitch.waitForClickable();
37+
await toggleSwitch.click();
38+
}
39+
40+
async enableTopic(topicId: string): Promise<void> {
41+
const isSubscribed = await this.isTopicSubscribed(topicId);
42+
if (!isSubscribed) {
43+
await this.toggleTopic(topicId);
44+
}
45+
}
46+
47+
async disableTopic(topicId: string): Promise<void> {
48+
const isSubscribed = await this.isTopicSubscribed(topicId);
49+
if (isSubscribed) {
50+
await this.toggleTopic(topicId);
51+
}
52+
}
53+
}
54+
55+
export default new SubscriptionsDropdown();

0 commit comments

Comments
 (0)