[MM-59296] Can't open web client on iOS Safari (#27607)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
db138fd23a
Коммит
1ff54a31bc
@@ -0,0 +1,78 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {screen, waitFor} from '@testing-library/react';
|
||||
import React from 'react';
|
||||
|
||||
import {renderWithContext, userEvent} from 'tests/react_testing_utils';
|
||||
import {requestNotificationPermission, isNotificationAPISupported} from 'utils/notifications';
|
||||
|
||||
import NotificationPermissionBar from './index';
|
||||
|
||||
jest.mock('utils/notifications', () => ({
|
||||
requestNotificationPermission: jest.fn(),
|
||||
isNotificationAPISupported: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('NotificationPermissionBar', () => {
|
||||
const initialState = {
|
||||
entities: {
|
||||
users: {
|
||||
currentUserId: 'user-id',
|
||||
},
|
||||
general: {
|
||||
config: {},
|
||||
license: {},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
(isNotificationAPISupported as jest.Mock).mockReturnValue(true);
|
||||
(window as any).Notification = {permission: 'default'};
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
delete (window as any).Notification;
|
||||
});
|
||||
|
||||
test('should render the notification bar when conditions are met', () => {
|
||||
renderWithContext(<NotificationPermissionBar/>, initialState);
|
||||
|
||||
expect(screen.getByText('We need your permission to show desktop notifications.')).toBeInTheDocument();
|
||||
expect(screen.getByText('Enable notifications')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should not render the notification bar if user is not logged in', () => {
|
||||
renderWithContext(<NotificationPermissionBar/>);
|
||||
|
||||
expect(screen.queryByText('We need your permission to show desktop notifications.')).not.toBeInTheDocument();
|
||||
expect(screen.queryByText('Enable notifications')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should not render the notification bar if Notifications are not supported', () => {
|
||||
delete (window as any).Notification;
|
||||
(isNotificationAPISupported as jest.Mock).mockReturnValue(false);
|
||||
|
||||
renderWithContext(<NotificationPermissionBar/>, initialState);
|
||||
|
||||
expect(screen.queryByText('We need your permission to show desktop notifications.')).not.toBeInTheDocument();
|
||||
expect(screen.queryByText('Enable notifications')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should call requestNotificationPermission and hide the bar when the button is clicked', async () => {
|
||||
(requestNotificationPermission as jest.Mock).mockResolvedValue('granted');
|
||||
|
||||
renderWithContext(<NotificationPermissionBar/>, initialState);
|
||||
|
||||
expect(screen.getByText('We need your permission to show desktop notifications.')).toBeInTheDocument();
|
||||
|
||||
await waitFor(async () => {
|
||||
userEvent.click(screen.getByText('Enable notifications'));
|
||||
});
|
||||
|
||||
expect(requestNotificationPermission).toHaveBeenCalled();
|
||||
expect(screen.queryByText('We need your permission to show desktop notifications.')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -10,25 +10,25 @@ import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
|
||||
import AnnouncementBar from 'components/announcement_bar/default_announcement_bar';
|
||||
|
||||
import {AnnouncementBarTypes} from 'utils/constants';
|
||||
import {requestNotificationPermission, isNotificationAPISupported} from 'utils/notifications';
|
||||
|
||||
export default function NotificationPermissionBar() {
|
||||
const isLoggedIn = Boolean(useSelector(getCurrentUserId));
|
||||
|
||||
const [show, setShow] = useState(Notification.permission === 'default');
|
||||
const [show, setShow] = useState(isNotificationAPISupported() ? Notification.permission === 'default' : false);
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
// If the user closes the bar, don't show the notification bar any more for the rest of the session, but
|
||||
// show it again after refresh.
|
||||
const handleClick = useCallback(async () => {
|
||||
await requestNotificationPermission();
|
||||
setShow(false);
|
||||
}, []);
|
||||
|
||||
const handleClick = useCallback(() => {
|
||||
Notification.requestPermission().then(() => {
|
||||
setShow(false);
|
||||
});
|
||||
const handleClose = useCallback(() => {
|
||||
// If the user closes the bar, don't show the notification bar any more for the rest of the session, but
|
||||
// show it again on app refresh.
|
||||
setShow(false);
|
||||
}, []);
|
||||
|
||||
if (!show || !isLoggedIn) {
|
||||
if (!show || !isLoggedIn || !isNotificationAPISupported()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ export default function NotificationPermissionBar() {
|
||||
type={AnnouncementBarTypes.ANNOUNCEMENT}
|
||||
message={
|
||||
<FormattedMessage
|
||||
id='announcement_bar.notification.needs_permisson'
|
||||
id='announcement_bar.notification.needs_permission'
|
||||
defaultMessage='We need your permission to show desktop notifications.'
|
||||
/>
|
||||
}
|
||||
|
||||
@@ -2814,7 +2814,7 @@
|
||||
"announcement_bar.error.trial_license_expiring_last_day.short": "This is the last day of your free trial.",
|
||||
"announcement_bar.notification.email_verified": "Email verified",
|
||||
"announcement_bar.notification.enable_notifications": "Enable notifications",
|
||||
"announcement_bar.notification.needs_permisson": "We need your permission to show desktop notifications.",
|
||||
"announcement_bar.notification.needs_permission": "We need your permission to show desktop notifications.",
|
||||
"announcement_bar.warn.contact_support_text": "To renew your license, contact support at support@mattermost.com.",
|
||||
"announcement_bar.warn.email_support": "[Contact support](!{email}).",
|
||||
"announcement_bar.warn.no_internet_connection": "Looks like you do not have access to the internet.",
|
||||
|
||||
@@ -3,11 +3,10 @@
|
||||
|
||||
/* eslint-disable global-require */
|
||||
|
||||
// to enable being a typescript file
|
||||
export const a = '';
|
||||
import configureStore from 'tests/test_store';
|
||||
|
||||
import type {showNotification} from './notifications';
|
||||
import {isNotificationAPISupported, requestNotificationPermission} from './notifications';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
@@ -39,20 +38,20 @@ describe('Notifications.showNotification', () => {
|
||||
it('should throw an exception if Notification is not defined on window', async () => {
|
||||
delete window.Notification;
|
||||
|
||||
await expect(store.dispatch(Notifications.showNotification())).rejects.toThrow('Notification not supported');
|
||||
await expect(store.dispatch(Notifications.showNotification())).rejects.toThrow('Notification API is not supported');
|
||||
});
|
||||
|
||||
it('should throw an exception if Notification.requestPermission is not defined', async () => {
|
||||
window.Notification = jest.fn();
|
||||
|
||||
await expect(store.dispatch(Notifications.showNotification())).rejects.toThrow('Notification.requestPermission not supported');
|
||||
await expect(store.dispatch(Notifications.showNotification())).rejects.toThrow('Notification API is not supported');
|
||||
});
|
||||
|
||||
it('should throw an exception if Notification.requestPermission is not a function', async () => {
|
||||
window.Notification = jest.fn();
|
||||
window.Notification.requestPermission = true;
|
||||
|
||||
await expect(store.dispatch(Notifications.showNotification())).rejects.toThrow('Notification.requestPermission not supported');
|
||||
await expect(store.dispatch(Notifications.showNotification())).rejects.toThrow('Notification API is not supported');
|
||||
expect(window.Notification).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -241,3 +240,64 @@ describe('Notifications.showNotification', () => {
|
||||
expect(window.Notification.requestPermission).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Notifications.isNotificationAPISupported', () => {
|
||||
beforeEach(() => {
|
||||
window.Notification = {
|
||||
requestPermission: jest.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
delete (window as any).Notification;
|
||||
});
|
||||
|
||||
it('should return true if Notification is supported', () => {
|
||||
expect(isNotificationAPISupported()).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if Notification is not supported', () => {
|
||||
delete (window as any).Notification;
|
||||
|
||||
expect(isNotificationAPISupported()).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if requestPermission is not a function', () => {
|
||||
(window as any).Notification = {};
|
||||
|
||||
expect(isNotificationAPISupported()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Notifications.requestNotificationPermission', () => {
|
||||
beforeEach(() => {
|
||||
(window as any).Notification = {
|
||||
requestPermission: jest.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
delete (window as any).Notification;
|
||||
});
|
||||
|
||||
it('should return the permission if Notification.requestPermission resolves', async () => {
|
||||
(window as any).Notification.requestPermission = jest.fn().mockResolvedValue('granted');
|
||||
|
||||
const permission = await requestNotificationPermission();
|
||||
expect(permission).toBe('granted');
|
||||
});
|
||||
|
||||
it('should return null if Notification is not supported', async () => {
|
||||
delete (window as any).Notification;
|
||||
|
||||
const permission = await requestNotificationPermission();
|
||||
expect(permission).toBeNull();
|
||||
});
|
||||
|
||||
it('should return null if requestPermission throws an error', async () => {
|
||||
(window as any).Notification.requestPermission = jest.fn().mockRejectedValue('some error');
|
||||
|
||||
const permission = await requestNotificationPermission();
|
||||
expect(permission).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -50,12 +50,8 @@ export function showNotification(
|
||||
icon = iconWS;
|
||||
}
|
||||
|
||||
if (!('Notification' in window)) {
|
||||
throw new Error('Notification not supported');
|
||||
}
|
||||
|
||||
if (typeof Notification.requestPermission !== 'function') {
|
||||
throw new Error('Notification.requestPermission not supported');
|
||||
if (!isNotificationAPISupported()) {
|
||||
throw new Error('Notification API is not supported');
|
||||
}
|
||||
|
||||
if (Notification.permission !== 'granted') {
|
||||
@@ -104,3 +100,20 @@ export function showNotification(
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export function isNotificationAPISupported() {
|
||||
return ('Notification' in window) && (typeof Notification.requestPermission === 'function');
|
||||
}
|
||||
|
||||
export async function requestNotificationPermission() {
|
||||
if (!isNotificationAPISupported()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const notificationPermission = await Notification.requestPermission();
|
||||
return notificationPermission;
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user