Add e2e tests for server push events (#36879)
Add e2e tests for the three server push features: - **Notification count**: verifies badge appears when another user creates an issue - **Stopwatch**: verifies stopwatch element is rendered when a stopwatch is active - **Logout propagation**: verifies logout in one tab triggers redirect in another Tests are transport-agnostic in preparation for a future WebSocket migration. --------- Co-authored-by: Claude (Opus 4.6) <noreply@anthropic.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import {GET} from '../modules/fetch.ts';
|
||||
import {toggleElem, createElementFromHTML} from '../utils/dom.ts';
|
||||
import {logoutFromWorker} from '../modules/worker.ts';
|
||||
import {UserEventsSharedWorker} from '../modules/worker.ts';
|
||||
|
||||
const {appSubUrl, notificationSettings, assetVersionEncoded} = window.config;
|
||||
const {appSubUrl, notificationSettings} = window.config;
|
||||
let notificationSequenceNumber = 0;
|
||||
|
||||
async function receiveUpdateCount(event: MessageEvent<{type: string, data: string}>) {
|
||||
@@ -33,56 +33,15 @@ export function initNotificationCount() {
|
||||
|
||||
if (notificationSettings.EventSourceUpdateTime > 0 && window.EventSource && window.SharedWorker) {
|
||||
// Try to connect to the event source via the shared worker first
|
||||
const worker = new SharedWorker(`${window.__webpack_public_path__}js/eventsource.sharedworker.js?v=${assetVersionEncoded}`, 'notification-worker');
|
||||
worker.addEventListener('error', (event) => {
|
||||
console.error('worker error', event);
|
||||
});
|
||||
worker.port.addEventListener('messageerror', () => {
|
||||
console.error('unable to deserialize message');
|
||||
});
|
||||
worker.port.postMessage({
|
||||
type: 'start',
|
||||
url: `${window.location.origin}${appSubUrl}/user/events`,
|
||||
});
|
||||
worker.port.addEventListener('message', (event: MessageEvent<{type: string, data: string}>) => {
|
||||
if (!event.data || !event.data.type) {
|
||||
console.error('unknown worker message event', event);
|
||||
return;
|
||||
}
|
||||
if (event.data.type === 'notification-count') {
|
||||
receiveUpdateCount(event); // no await
|
||||
} else if (event.data.type === 'no-event-source') {
|
||||
// browser doesn't support EventSource, falling back to periodic poller
|
||||
const worker = new UserEventsSharedWorker('notification-worker');
|
||||
worker.addMessageEventListener((event: MessageEvent) => {
|
||||
if (event.data.type === 'no-event-source') {
|
||||
if (!usingPeriodicPoller) startPeriodicPoller(notificationSettings.MinTimeout);
|
||||
} else if (event.data.type === 'error') {
|
||||
console.error('worker port event error', event.data);
|
||||
} else if (event.data.type === 'logout') {
|
||||
if (event.data.data !== 'here') {
|
||||
return;
|
||||
}
|
||||
worker.port.postMessage({
|
||||
type: 'close',
|
||||
});
|
||||
worker.port.close();
|
||||
logoutFromWorker();
|
||||
} else if (event.data.type === 'close') {
|
||||
worker.port.postMessage({
|
||||
type: 'close',
|
||||
});
|
||||
worker.port.close();
|
||||
} else if (event.data.type === 'notification-count') {
|
||||
receiveUpdateCount(event); // no await
|
||||
}
|
||||
});
|
||||
worker.port.addEventListener('error', (e) => {
|
||||
console.error('worker port error', e);
|
||||
});
|
||||
worker.port.start();
|
||||
window.addEventListener('beforeunload', () => {
|
||||
worker.port.postMessage({
|
||||
type: 'close',
|
||||
});
|
||||
worker.port.close();
|
||||
});
|
||||
|
||||
worker.startPort();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import {createTippy} from '../modules/tippy.ts';
|
||||
import {GET} from '../modules/fetch.ts';
|
||||
import {hideElem, queryElems, showElem} from '../utils/dom.ts';
|
||||
import {logoutFromWorker} from '../modules/worker.ts';
|
||||
import {UserEventsSharedWorker} from '../modules/worker.ts';
|
||||
|
||||
const {appSubUrl, notificationSettings, enableTimeTracking, assetVersionEncoded} = window.config;
|
||||
const {appSubUrl, notificationSettings, enableTimeTracking} = window.config;
|
||||
|
||||
export function initStopwatch() {
|
||||
if (!enableTimeTracking) {
|
||||
@@ -47,56 +47,16 @@ export function initStopwatch() {
|
||||
// if the browser supports EventSource and SharedWorker, use it instead of the periodic poller
|
||||
if (notificationSettings.EventSourceUpdateTime > 0 && window.EventSource && window.SharedWorker) {
|
||||
// Try to connect to the event source via the shared worker first
|
||||
const worker = new SharedWorker(`${window.__webpack_public_path__}js/eventsource.sharedworker.js?v=${assetVersionEncoded}`, 'notification-worker');
|
||||
worker.addEventListener('error', (event) => {
|
||||
console.error('worker error', event);
|
||||
});
|
||||
worker.port.addEventListener('messageerror', () => {
|
||||
console.error('unable to deserialize message');
|
||||
});
|
||||
worker.port.postMessage({
|
||||
type: 'start',
|
||||
url: `${window.location.origin}${appSubUrl}/user/events`,
|
||||
});
|
||||
worker.port.addEventListener('message', (event) => {
|
||||
if (!event.data || !event.data.type) {
|
||||
console.error('unknown worker message event', event);
|
||||
return;
|
||||
}
|
||||
if (event.data.type === 'stopwatches') {
|
||||
updateStopwatchData(JSON.parse(event.data.data));
|
||||
} else if (event.data.type === 'no-event-source') {
|
||||
const worker = new UserEventsSharedWorker('stopwatch-worker');
|
||||
worker.addMessageEventListener((event) => {
|
||||
if (event.data.type === 'no-event-source') {
|
||||
// browser doesn't support EventSource, falling back to periodic poller
|
||||
if (!usingPeriodicPoller) startPeriodicPoller(notificationSettings.MinTimeout);
|
||||
} else if (event.data.type === 'error') {
|
||||
console.error('worker port event error', event.data);
|
||||
} else if (event.data.type === 'logout') {
|
||||
if (event.data.data !== 'here') {
|
||||
return;
|
||||
}
|
||||
worker.port.postMessage({
|
||||
type: 'close',
|
||||
});
|
||||
worker.port.close();
|
||||
logoutFromWorker();
|
||||
} else if (event.data.type === 'close') {
|
||||
worker.port.postMessage({
|
||||
type: 'close',
|
||||
});
|
||||
worker.port.close();
|
||||
} else if (event.data.type === 'stopwatches') {
|
||||
updateStopwatchData(JSON.parse(event.data.data));
|
||||
}
|
||||
});
|
||||
worker.port.addEventListener('error', (e) => {
|
||||
console.error('worker port error', e);
|
||||
});
|
||||
worker.port.start();
|
||||
window.addEventListener('beforeunload', () => {
|
||||
worker.port.postMessage({
|
||||
type: 'close',
|
||||
});
|
||||
worker.port.close();
|
||||
});
|
||||
|
||||
worker.startPort();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user