Files
mostlymatter/e2e-tests/playwright/support/mock_browser_api.ts

91 строка
3.6 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Page} from '@playwright/test';
type NotificationData = {title: string} & NotificationOptions;
// Extend the Window interface to add custom properties
declare global {
interface Window {
_originalNotification: typeof Notification;
_notifications: NotificationData[];
getNotifications: () => NotificationData[];
}
}
/**
* `stubNotification` intercepts the Notification API to capture notifications.
*
* Note:
* - Works across browsers and devices, except in headless mode, where stubbing the Notification API is supported only in Firefox and WebKit.
* - An `Error: page.evaluate: window.getNotifications is not a function` may occur if the `stubNotification` function is called before the page has fully loaded.
*
* @param page Page object
* @param permission Permission setting for notifications, with possible values: "default" | "granted" | "denied". Note: A notification sound may still occur even when set to "denied", as the browser might attempt to trigger system notifications.
*/
export async function stubNotification(page: Page, permission: NotificationPermission) {
await page.evaluate((notificationPermission: NotificationPermission) => {
// Override the Notification.requestPermission method
window.Notification.requestPermission = () => Promise.resolve(permission);
// Copy the original Notification
if (!window._originalNotification) {
window._originalNotification = window.Notification;
}
// Initialize a list where to capture the notifications
window._notifications = [];
// Override the Notification constructor
class CustomNotification extends window._originalNotification {
constructor(title: string, options?: NotificationOptions) {
super(title, options);
const notification = {title, ...options};
window._notifications.push(notification);
}
}
// Set static properties and permission status
Object.defineProperties(CustomNotification, {
permission: {
get: () => notificationPermission,
},
requestPermission: {
value: () => Promise.resolve(notificationPermission),
},
});
// Replace the global Notification with the custom one
window.Notification = CustomNotification as unknown as typeof Notification;
// Method to get all notifications
window.getNotifications = () => window._notifications;
}, permission);
}
/**
* `waitForNotification` waits for a specified number of notifications to be received on the page within a given timeout.
* @param page Page object
* @param expectedCount Number of notifications to wait for before returning. (default: 1)
* @param timeout Wait time in milliseconds. (default: 5000ms)
* @returns An array of notifications received
*/
export async function waitForNotification(
page: Page,
expectedCount = 1,
timeout: number = 5000,
): Promise<NotificationData[]> {
const start = Date.now();
while (Date.now() - start < timeout) {
const notifications = await page.evaluate(() => window.getNotifications());
if (notifications.length >= expectedCount) {
return notifications;
}
await new Promise((resolve) => setTimeout(resolve, 100));
}
// eslint-disable-next-line no-console
console.error(`Notification not received within the timeout period of ${timeout}ms`);
return [];
}