Skip to content

Commit fc64923

Browse files
IBX-10592: [Behat] Implemented basic behat coverage for notification feature (#1746)
* Add notification config * Add new scenarios to notification feature * Code cleanup and naming improvments * Fix * Fix after review * Fix flaky issue in notification tests * Fix hover issue in notification tests * Fix mouseoverandclick method * Fix flaky issues * Add count step to scenarios * Fix count scenario * Fixes after review * Fix after CR
1 parent d156ca6 commit fc64923

File tree

4 files changed

+387
-1
lines changed

4 files changed

+387
-1
lines changed

src/bundle/Resources/config/services/test/pages.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,6 @@ services:
6363
Ibexa\AdminUi\Behat\Page\UserSettingsPage: ~
6464

6565
Ibexa\AdminUi\Behat\Page\UserProfilePage: ~
66+
67+
Ibexa\AdminUi\Behat\Page\NotificationsViewAllPage: ~
68+

src/lib/Behat/BrowserContext/UserNotificationContext.php

Lines changed: 134 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use Behat\Gherkin\Node\TableNode;
1313
use Ibexa\AdminUi\Behat\Component\UpperMenu;
1414
use Ibexa\AdminUi\Behat\Component\UserNotificationPopup;
15+
use Ibexa\AdminUi\Behat\Page\NotificationsViewAllPage;
1516
use PHPUnit\Framework\Assert;
1617

1718
class UserNotificationContext implements Context
@@ -22,10 +23,13 @@ class UserNotificationContext implements Context
2223
/** @var \Ibexa\AdminUi\Behat\Component\UserNotificationPopup */
2324
private $userNotificationPopup;
2425

25-
public function __construct(UpperMenu $upperMenu, UserNotificationPopup $userNotificationPopup)
26+
private NotificationsViewAllPage $notificationsViewAllPage;
27+
28+
public function __construct(UpperMenu $upperMenu, UserNotificationPopup $userNotificationPopup, NotificationsViewAllPage $notificationsViewAllPage)
2629
{
2730
$this->upperMenu = $upperMenu;
2831
$this->userNotificationPopup = $userNotificationPopup;
32+
$this->notificationsViewAllPage = $notificationsViewAllPage;
2933
}
3034

3135
/**
@@ -47,4 +51,133 @@ public function iGoToUserNotificationWithDetails(TableNode $notificationDetails)
4751
$this->userNotificationPopup->verifyIsLoaded();
4852
$this->userNotificationPopup->clickNotification($type, $description);
4953
}
54+
55+
/**
56+
* @Then the notification appears with details:
57+
*/
58+
public function notificationAppearsWithDetails(TableNode $notificationDetails): void
59+
{
60+
$type = $notificationDetails->getHash()[0]['Type'];
61+
$author = $notificationDetails->getHash()[0]['Author'];
62+
$description = $notificationDetails->getHash()[0]['Description'];
63+
$date = $notificationDetails->getHash()[0]['Date'];
64+
65+
$this->userNotificationPopup->verifyIsLoaded();
66+
$this->userNotificationPopup->verifyNotification($type, $author, $description, $date, true);
67+
}
68+
69+
/**
70+
* @When I open notification menu with description :description
71+
*/
72+
public function iOpenNotificationMenu(string $description): void
73+
{
74+
$this->userNotificationPopup->openNotificationMenu($description);
75+
}
76+
77+
/**
78+
* @When I perform the :action action on the notification
79+
*/
80+
public function iPerformNotificationAction(string $action): void
81+
{
82+
$this->userNotificationPopup->clickActionButton($action);
83+
}
84+
85+
/**
86+
* @Then the notification should have :expectedAction action available
87+
*/
88+
public function verifyNotificationAction(string $expectedAction): void
89+
{
90+
$this->userNotificationPopup->findActionButton($expectedAction);
91+
}
92+
93+
/**
94+
* @When I mark all notifications as read
95+
*/
96+
public function markAllNotificationsAsRead(): void
97+
{
98+
$this->userNotificationPopup->verifyIsLoaded();
99+
$this->userNotificationPopup->clickOnMarkAllAsReadButton();
100+
}
101+
102+
/**
103+
* @When I go to the list of all notifications
104+
*/
105+
public function goToAllNotificationsList(): void
106+
{
107+
$this->userNotificationPopup->verifyIsLoaded();
108+
$this->userNotificationPopup->clickViewAllNotificationsButton();
109+
}
110+
111+
/**
112+
* @Then there is :notificationTitle notification on list
113+
*/
114+
public function thereIsNotificationOnList(string $notificationTitle): void
115+
{
116+
$this->notificationsViewAllPage->verifyIsLoaded();
117+
$this->notificationsViewAllPage->verifyNotificationIsOnList($notificationTitle);
118+
}
119+
120+
/**
121+
* @When I mark notification as unread with title :notificationTitle
122+
*/
123+
public function iMarkNotificationAsUnread(string $notificationTitle): void
124+
{
125+
$this->notificationsViewAllPage->markAsUnread($notificationTitle);
126+
}
127+
128+
/**
129+
* @Then the notification with title :notificationTitle has status :notificationStatus
130+
*/
131+
public function verifyNotificationStatus(string $notificationTitle, string $notificationStatus): void
132+
{
133+
Assert::assertEquals($notificationStatus, $this->notificationsViewAllPage->getStatusForNotification($notificationTitle));
134+
}
135+
136+
/**
137+
* @When I go to content of notification with title :notificationTitle
138+
*/
139+
public function iGoToContent(string $notificationTitle): void
140+
{
141+
$this->notificationsViewAllPage->goToContent($notificationTitle);
142+
}
143+
144+
/**
145+
* @When I delete notification with title :notificationTitle
146+
*/
147+
public function iDeleteNotification(string $notificationTitle): void
148+
{
149+
$this->notificationsViewAllPage->deleteNotification($notificationTitle);
150+
}
151+
152+
/**
153+
* @Then an empty notifications state in the popup should be visible
154+
*/
155+
public function emptyNotificationsStateInPopup(): void
156+
{
157+
$this->userNotificationPopup->assertEmptyStateVisible();
158+
}
159+
160+
/**
161+
* @Then an empty notifications state should be visible in the All Notifications view
162+
*/
163+
public function emptyNotificationsStateInAllNotificationsView(): void
164+
{
165+
$this->notificationsViewAllPage->assertEmptyStateVisible();
166+
}
167+
168+
/**
169+
* @Then the notifications popup counter should display :expectedCount
170+
*/
171+
public function iShouldSeeNotificationsCountInPopup(int $expectedCount): void
172+
{
173+
$this->userNotificationPopup->verifyNotificationsCount($expectedCount);
174+
}
175+
176+
/**
177+
* @Then I should see :expectedCount notifications in the All Notifications view
178+
*/
179+
public function thereShouldBeNotificationsInAllNotificationsView(int $expectedCount): void
180+
{
181+
$this->notificationsViewAllPage->verifyNotificationsCount($expectedCount);
182+
}
50183
}

src/lib/Behat/Component/UserNotificationPopup.php

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@
1010

1111
use Exception;
1212
use Ibexa\Behat\Browser\Component\Component;
13+
use Ibexa\Behat\Browser\Element\Action\MouseOverAndClick;
14+
use Ibexa\Behat\Browser\Element\Condition\ElementExistsCondition;
15+
use Ibexa\Behat\Browser\Element\Condition\ElementNotExistsCondition;
16+
use Ibexa\Behat\Browser\Element\Criterion\ChildElementTextCriterion;
17+
use Ibexa\Behat\Browser\Element\Criterion\ElementTextCriterion;
18+
use Ibexa\Behat\Browser\Element\ElementInterface;
1319
use Ibexa\Behat\Browser\Locator\VisibleCSSLocator;
1420

1521
class UserNotificationPopup extends Component
@@ -41,6 +47,120 @@ public function clickNotification(string $expectedType, string $expectedDescript
4147
throw new Exception(sprintf('Notification of type: %s with description: %d not found', $expectedType, $expectedDescription));
4248
}
4349

50+
public function verifyNotification(string $expectedType, string $expectedAuthor, string $expectedDescription, ?string $expectedDate = null, bool $shouldExist = true): void
51+
{
52+
$notifications = $this->getHTMLPage()->setTimeout(5)->findAll($this->getLocator('notificationItem'));
53+
54+
foreach ($notifications as $notification) {
55+
$criteria = [
56+
new ChildElementTextCriterion($this->getLocator('notificationType'), $expectedType),
57+
new ChildElementTextCriterion($this->getLocator('notificationDescriptionTitle'), $expectedAuthor),
58+
new ChildElementTextCriterion($this->getLocator('notificationDescriptionText'), $expectedDescription),
59+
];
60+
61+
if ($expectedDate !== null && $expectedDate !== 'XXXX-XX-XX') {
62+
$criteria[] = new ChildElementTextCriterion($this->getLocator('notificationDate'), $expectedDate);
63+
}
64+
65+
foreach ($criteria as $criterion) {
66+
if (!$criterion->matches($notification)) {
67+
continue 2;
68+
}
69+
}
70+
71+
if ($shouldExist) {
72+
return;
73+
} else {
74+
throw new \Exception(sprintf(
75+
'Notification of type "%s" with author "%s" and description "%s" should not exist, but was found.',
76+
$expectedType,
77+
$expectedAuthor,
78+
$expectedDescription
79+
));
80+
}
81+
}
82+
83+
if ($shouldExist) {
84+
throw new \Exception(sprintf(
85+
'Notification of type "%s" with author "%s" and description "%s" was not found.',
86+
$expectedType,
87+
$expectedAuthor,
88+
$expectedDescription
89+
));
90+
}
91+
}
92+
93+
public function openNotificationMenu(string $expectedDescription): void
94+
{
95+
$this->getHTMLPage()->setTimeout(5)->findAll($this->getLocator('notificationItem'))
96+
->filterBy(new ChildElementTextCriterion($this->getLocator('notificationDescriptionText'), $expectedDescription))
97+
->first()->find($this->getLocator('notificationMenuButton'))->click();
98+
99+
$this->getHTMLPage()
100+
->setTimeout(10)
101+
->waitUntilCondition(
102+
new ElementExistsCondition(
103+
$this->getHTMLPage(),
104+
$this->getLocator('notificationActionsPopup'),
105+
)
106+
);
107+
}
108+
109+
public function clickActionButton(string $buttonText): void
110+
{
111+
$this->getHTMLPage()
112+
->setTimeout(10)
113+
->findAll($this->getLocator('notificationMenuItemContent'))
114+
->filterBy(new ElementTextCriterion($buttonText))->first()->execute(new MouseOverAndClick());
115+
116+
$this->getHTMLPage()
117+
->setTimeout(10)
118+
->waitUntilCondition(
119+
new ElementNotExistsCondition(
120+
$this->getHTMLPage(),
121+
$this->getLocator('notificationActionsPopup')
122+
)
123+
);
124+
}
125+
126+
public function findActionButton(string $buttonText): ?ElementInterface
127+
{
128+
$this->getHTMLPage()
129+
->setTimeout(10)
130+
->waitUntilCondition(
131+
new ElementExistsCondition(
132+
$this->getHTMLPage(),
133+
$this->getLocator('notificationMenuItemContent')
134+
)
135+
);
136+
137+
return $this->getHTMLPage()
138+
->setTimeout(10)
139+
->findAll($this->getLocator('notificationMenuItemContent'))
140+
->filterBy(new ElementTextCriterion($buttonText))
141+
->first();
142+
}
143+
144+
public function assertEmptyStateVisible(): void
145+
{
146+
$this->getHTMLPage()->setTimeout(5)->find($this->getLocator('notificationsEmptyText'))->assert()->isVisible();
147+
}
148+
149+
public function clickOnMarkAllAsReadButton(): void
150+
{
151+
$this->getHTMLPage()->setTimeout(5)->find($this->getLocator('markAllAsReadButton'))->click();
152+
}
153+
154+
public function clickViewAllNotificationsButton(): void
155+
{
156+
$this->getHTMLPage()->setTimeout(3)->find($this->getLocator('viewAllNotificationsButton'))->click();
157+
}
158+
159+
public function verifyNotificationsCount(int $expectedCount): void
160+
{
161+
$this->getHTMLPage()->setTimeout(10)->find($this->getLocator('notificationsCount'))->assert()->textEquals('(' . $expectedCount . ')');
162+
}
163+
44164
public function verifyIsLoaded(): void
45165
{
46166
$this->getHTMLPage()
@@ -57,6 +177,14 @@ protected function specifyLocators(): array
57177
new VisibleCSSLocator('notificationType', '.ibexa-notifications-modal__type-content .type__text'),
58178
new VisibleCSSLocator('notificationDescriptionTitle', '.ibexa-notifications-modal__description .description__title'),
59179
new VisibleCSSLocator('notificationDescriptionText', '.ibexa-notifications-modal__type-content .description__text'),
180+
new VisibleCSSLocator('notificationDate', '.ibexa-notifications-modal__item--date'),
181+
new VisibleCSSLocator('notificationMenuButton', '.ibexa-notifications-modal__actions'),
182+
new VisibleCSSLocator('notificationMenuItemContent', '.ibexa-popup-menu__item-content.ibexa-multilevel-popup-menu__item-content'),
183+
new VisibleCSSLocator('markAllAsReadButton', '.ibexa-notifications-modal__mark-all-read-btn'),
184+
new VisibleCSSLocator('viewAllNotificationsButton', '.ibexa-notifications-modal__view-all-btn'),
185+
new VisibleCSSLocator('notificationActionsPopup', '.ibexa-notification-actions-popup-menu:not(.ibexa-popup-menu--hidden)'),
186+
new VisibleCSSLocator('notificationsEmptyText', '.ibexa-notifications-modal__empty-text'),
187+
new VisibleCSSLocator('notificationsCount', '.ibexa-notifications-modal__count'),
60188
];
61189
}
62190
}

0 commit comments

Comments
 (0)