MOBILE-4496 reminders: Improve notification tests
The previous implementation was too flaky because it relied on test execution timemain
parent
da976a08a7
commit
208ec01b6c
|
@ -1055,14 +1055,24 @@ class behat_app extends behat_app_helper {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send pending notifications.
|
||||
*
|
||||
* @Then /^I flush pending notifications in the app$/
|
||||
*/
|
||||
public function i_flush_notifications() {
|
||||
$this->runtime_js("flushNotifications()");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a notification has been triggered and is present.
|
||||
*
|
||||
* @Then /^a notification with title (".+") is( not)? present in the app$/
|
||||
* @Then /^a notification with title (".+") should( not)? be present in the app$/
|
||||
* @param string $title Notification title
|
||||
* @param bool $not Whether assert that the notification was not found
|
||||
*/
|
||||
public function notification_present_in_the_app(string $title, bool $not = false) {
|
||||
$this->spin(function() use ($not, $title) {
|
||||
$result = $this->runtime_js("notificationIsPresentWithText($title)");
|
||||
|
||||
if ($not && $result === 'YES') {
|
||||
|
@ -1078,6 +1088,50 @@ class behat_app extends behat_app_helper {
|
|||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a notification has been scheduled.
|
||||
*
|
||||
* @Then /^a notification with title (".+") should( not)? be scheduled(?: (\d+) minutes before the "(.+)" assignment due date)? in the app$/
|
||||
* @param string $title Notification title
|
||||
* @param bool $not Whether assert that the notification was not scheduled
|
||||
* @param int $minutes Minutes before the assignment at which the notification was scheduled
|
||||
* @param string $assignment Assignment for which the notification was scheduled
|
||||
*/
|
||||
public function notification_scheduled_in_the_app(string $title, bool $not = false, ?int $minutes = null, ?string $assignment = null) {
|
||||
if (!is_null($minutes)) {
|
||||
global $DB;
|
||||
|
||||
$assign = $DB->get_record('assign', ['name' => $assignment]);
|
||||
|
||||
if (!$assign) {
|
||||
throw new ExpectationException("Couldn't find '$assignment' assignment", $this->getSession()->getDriver());
|
||||
}
|
||||
|
||||
$date = ($assign->duedate - $minutes * 60) * 1000;
|
||||
} else {
|
||||
$date = 'undefined';
|
||||
}
|
||||
|
||||
$this->spin(function() use ($not, $title, $date) {
|
||||
$result = $this->runtime_js("notificationIsScheduledWithText($title, $date)");
|
||||
|
||||
if ($not && $result === 'YES') {
|
||||
throw new ExpectationException("Notification is scheduled", $this->getSession()->getDriver());
|
||||
}
|
||||
|
||||
if (!$not && $result === 'NO') {
|
||||
throw new ExpectationException("Notification is not scheduled", $this->getSession()->getDriver());
|
||||
}
|
||||
|
||||
if ($result !== 'YES' && $result !== 'NO') {
|
||||
throw new DriverException('Error checking scheduled notification - ' . $result);
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -67,6 +67,17 @@ export class LocalNotificationsMock extends LocalNotifications {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush pending notifications.
|
||||
*/
|
||||
flush(): void {
|
||||
for (const notification of this.scheduledNotifications) {
|
||||
this.sendNotification(notification);
|
||||
}
|
||||
|
||||
this.scheduledNotifications = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets timeout for next nofitication.
|
||||
*/
|
||||
|
@ -104,36 +115,7 @@ export class LocalNotificationsMock extends LocalNotifications {
|
|||
|
||||
const notificationTime = nextNotification.trigger?.at?.getTime() || 0;
|
||||
if (notificationTime === 0 || notificationTime <= dateNow) {
|
||||
const body = Array.isArray(nextNotification.text) ? nextNotification.text.join() : nextNotification.text;
|
||||
const notification = new Notification(nextNotification.title || '', {
|
||||
body,
|
||||
data: nextNotification.data,
|
||||
icon: nextNotification.icon,
|
||||
requireInteraction: true,
|
||||
tag: nextNotification.data?.component,
|
||||
});
|
||||
|
||||
this.triggeredNotifications.push(nextNotification);
|
||||
|
||||
this.observables.trigger.next(nextNotification);
|
||||
|
||||
notification.addEventListener('click', () => {
|
||||
this.observables.click.next(nextNotification);
|
||||
|
||||
notification.close();
|
||||
if (nextNotification.id) {
|
||||
delete(this.presentNotifications[nextNotification.id]);
|
||||
}
|
||||
});
|
||||
|
||||
if (nextNotification.id) {
|
||||
this.presentNotifications[nextNotification.id] = notification;
|
||||
|
||||
notification.addEventListener('close', () => {
|
||||
delete(this.presentNotifications[nextNotification.id ?? 0]);
|
||||
});
|
||||
}
|
||||
|
||||
this.sendNotification(nextNotification);
|
||||
this.scheduledNotifications.shift();
|
||||
this.triggerNextNotification();
|
||||
} else {
|
||||
|
@ -141,6 +123,43 @@ export class LocalNotificationsMock extends LocalNotifications {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send notification.
|
||||
*
|
||||
* @param localNotification Notification.
|
||||
*/
|
||||
protected sendNotification(localNotification: ILocalNotification): void {
|
||||
const body = Array.isArray(localNotification.text) ? localNotification.text.join() : localNotification.text;
|
||||
const notification = new Notification(localNotification.title || '', {
|
||||
body,
|
||||
data: localNotification.data,
|
||||
icon: localNotification.icon,
|
||||
requireInteraction: true,
|
||||
tag: localNotification.data?.component,
|
||||
});
|
||||
|
||||
this.triggeredNotifications.push(localNotification);
|
||||
|
||||
this.observables.trigger.next(localNotification);
|
||||
|
||||
notification.addEventListener('click', () => {
|
||||
this.observables.click.next(localNotification);
|
||||
|
||||
notification.close();
|
||||
if (localNotification.id) {
|
||||
delete(this.presentNotifications[localNotification.id]);
|
||||
}
|
||||
});
|
||||
|
||||
if (localNotification.id) {
|
||||
this.presentNotifications[localNotification.id] = notification;
|
||||
|
||||
notification.addEventListener('close', () => {
|
||||
delete(this.presentNotifications[localNotification.id ?? 0]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
|
|
|
@ -62,20 +62,21 @@ Feature: Set a new reminder on activity
|
|||
And I press "Custom..." in the app
|
||||
Then I should find "Custom reminder" in the app
|
||||
When I set the following fields to these values in the app:
|
||||
| Value | 69 |
|
||||
| Value | 40 |
|
||||
| Units | minutes |
|
||||
And I press "Set reminder" in the app
|
||||
Then I should find "Reminder set for" in the app
|
||||
When I wait "50" seconds
|
||||
Then a notification with title "Due: Assignment 01" is present in the app
|
||||
And I close a notification with title "Due: Assignment 01" in the app
|
||||
And a notification with title "Due: Assignment 01" should be scheduled 40 minutes before the "Assignment 01" assignment due date in the app
|
||||
When I flush pending notifications in the app
|
||||
Then a notification with title "Due: Assignment 01" should be present in the app
|
||||
|
||||
# Set and check reminder is cancelled
|
||||
When I press "Set a reminder for \"Assignment 01\" (Due)" in the app
|
||||
When I close a notification with title "Due: Assignment 01" in the app
|
||||
And I press "Set a reminder for \"Assignment 01\" (Due)" in the app
|
||||
And I press "Custom..." in the app
|
||||
Then I should find "Custom reminder" in the app
|
||||
When I set the following fields to these values in the app:
|
||||
| Value | 68 |
|
||||
| Value | 20 |
|
||||
| Units | minutes |
|
||||
And I press "Set reminder" in the app
|
||||
Then I should find "Reminder set for" in the app
|
||||
|
@ -83,8 +84,8 @@ Feature: Set a new reminder on activity
|
|||
Then I should find "Reminder set for" in the app
|
||||
When I press "Delete reminder" in the app
|
||||
Then I should find "Reminder deleted" in the app
|
||||
When I wait "50" seconds
|
||||
Then a notification with title "Due: Assignment 01" is not present in the app
|
||||
But a notification with title "Due: Assignment 01" should not be scheduled in the app
|
||||
And a notification with title "Due: Assignment 01" should not be present in the app
|
||||
|
||||
Scenario: Check toast is correct
|
||||
Given I entered the assign activity "Assignment 02" on course "Course 1" as "student1" in the app
|
||||
|
|
|
@ -30,6 +30,7 @@ import { CoreSites, CoreSitesProvider } from '@services/sites';
|
|||
import { CoreNavigator, CoreNavigatorService } from '@services/navigator';
|
||||
import { CoreSwipeNavigationDirective } from '@directives/swipe-navigation';
|
||||
import { Swiper } from 'swiper';
|
||||
import { LocalNotificationsMock } from '@features/emulator/services/local-notifications';
|
||||
|
||||
/**
|
||||
* Behat runtime servive with public API.
|
||||
|
@ -585,6 +586,13 @@ export class TestingBehatRuntimeService {
|
|||
console.log('BEHAT: ' + nowFormatted, ...args); // eslint-disable-line no-console
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush pending notifications.
|
||||
*/
|
||||
flushNotifications(): void {
|
||||
(LocalNotifications as unknown as LocalNotificationsMock).flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check a notification is present.
|
||||
*
|
||||
|
@ -608,6 +616,23 @@ export class TestingBehatRuntimeService {
|
|||
return (await LocalNotifications.isPresent(notification.id)) ? 'YES' : 'NO';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check a notification is scheduled.
|
||||
*
|
||||
* @param title Title of the notification
|
||||
* @param date Scheduled notification date.
|
||||
* @returns YES or NO: depending on the result.
|
||||
*/
|
||||
async notificationIsScheduledWithText(title: string, date?: number): Promise<string> {
|
||||
const notifications = await LocalNotifications.getAllScheduled();
|
||||
|
||||
const notification = notifications.find(
|
||||
(notification) => notification.title?.includes(title) && (!date || notification.trigger?.at?.getTime() === date),
|
||||
);
|
||||
|
||||
return notification ? 'YES' : 'NO';
|
||||
}
|
||||
|
||||
/**
|
||||
* Close notification.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue