Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@
{
"files": [
"e2e/**/*",
"src/**/*.test.js"
"src/**/*.test.js",
"src/**/*.test.ts"
],
"env": {
"jest": true
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/e2e-functional-template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,10 @@ jobs:
npm ci
cd e2e && npm ci

- name: e2e/enable-public-links
if: env.MM_TEST_SERVER_URL != ''
run: cd e2e && npm run enable-public-links

- name: e2e/suppress-macos-dialogs
if: runner.os == 'macOS'
run: |
Expand Down
65 changes: 59 additions & 6 deletions e2e/helpers/badge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
import {expect} from '@playwright/test';
import type {ElectronApplication} from 'playwright';

import type {BadgeTestState} from 'src/main/e2e/badgeState';
import type {E2eGlobalRefs} from 'src/main/e2e/hooks';

import {evaluateInMainProcess, evaluateInMainProcessWithArg} from './testRefs';

export type OsBadgeState = {
Expand All @@ -15,7 +18,8 @@ export type OsBadgeState = {
export async function waitForBadgeInfrastructure(app: ElectronApplication): Promise<void> {
await expect.poll(
async () => app.evaluate(() => {
const refs = (global as any).__e2eTestRefs;
const e2eTestRefsKey = '__e2eTestRefs';
const refs = (global as Record<string, unknown>)[e2eTestRefsKey] as E2eGlobalRefs | undefined;
return Boolean(refs?.AppState && refs?.ServerManager);
}),
{timeout: 30_000, message: 'AppState and ServerManager must be exposed on __e2eTestRefs'},
Expand All @@ -24,7 +28,8 @@ export async function waitForBadgeInfrastructure(app: ElectronApplication): Prom

export async function setUnreadBadgeSetting(app: ElectronApplication, enabled: boolean): Promise<void> {
await evaluateInMainProcessWithArg(app, (_electron, showUnreadBadge) => {
const refs = (global as any).__e2eTestRefs;
const e2eTestRefsKey = '__e2eTestRefs';
const refs = (global as Record<string, unknown>)[e2eTestRefsKey] as E2eGlobalRefs | undefined;
if (!refs?.setUnreadBadgeSetting) {
throw new Error('setUnreadBadgeSetting missing from __e2eTestRefs');
}
Expand All @@ -40,7 +45,8 @@ export async function updateServerBadgeViaAppState(
unreads: boolean,
): Promise<void> {
await evaluateInMainProcessWithArg(app, (_electron, {serverName: name, mentions: mentionCount, unreads: hasUnreads}) => {
const refs = (global as any).__e2eTestRefs;
const e2eTestRefsKey = '__e2eTestRefs';
const refs = (global as Record<string, unknown>)[e2eTestRefsKey] as E2eGlobalRefs | undefined;
const AppState = refs?.AppState;
const ServerManager = refs?.ServerManager;
if (!AppState || !ServerManager) {
Expand All @@ -60,7 +66,8 @@ export async function setServerExpiredViaAppState(
expired: boolean,
): Promise<void> {
await evaluateInMainProcessWithArg(app, (_electron, {serverName: name, expired: isExpired}) => {
const refs = (global as any).__e2eTestRefs;
const e2eTestRefsKey = '__e2eTestRefs';
const refs = (global as Record<string, unknown>)[e2eTestRefsKey] as E2eGlobalRefs | undefined;
const AppState = refs?.AppState;
const ServerManager = refs?.ServerManager;
if (!AppState || !ServerManager) {
Expand All @@ -76,7 +83,8 @@ export async function setServerExpiredViaAppState(

export async function clearAllBadgesViaAppState(app: ElectronApplication): Promise<void> {
await evaluateInMainProcess(app, () => {
const refs = (global as any).__e2eTestRefs;
const e2eTestRefsKey = '__e2eTestRefs';
const refs = (global as Record<string, unknown>)[e2eTestRefsKey] as E2eGlobalRefs | undefined;
const AppState = refs?.AppState;
const ServerManager = refs?.ServerManager;
if (!AppState || !ServerManager) {
Expand All @@ -91,9 +99,54 @@ export async function clearAllBadgesViaAppState(app: ElectronApplication): Promi
});
}

/**
* Clear all servers and set one server's badge state in a single main-process
* turn so external AppState updates cannot land between separate clear/set IPC calls.
*/
export async function prepareServerBadgeViaAppState(
app: ElectronApplication,
serverName: string,
mentions: number,
unreads: boolean,
options: {enableUnreadBadge?: boolean} = {},
): Promise<void> {
const {enableUnreadBadge = false} = options;
await evaluateInMainProcessWithArg(app, (_, payload) => {
const e2eTestRefsKey = '__e2eTestRefs';
const refs = (global as Record<string, unknown>)[e2eTestRefsKey] as E2eGlobalRefs | undefined;
const AppState = refs?.AppState;
const ServerManager = refs?.ServerManager;
if (!AppState || !ServerManager) {
throw new Error('AppState or ServerManager missing from __e2eTestRefs');
}

for (const server of ServerManager.getAllServers()) {
AppState.updateUnreadsAndMentionsPerServer(server.id, 0, false);
AppState.updateExpired(server.id, false);
}
refs.Config?.set?.('showUnreadBadge', payload.enableUnreadBadge);
refs.setUnreadBadgeSetting?.(payload.enableUnreadBadge);

const server = ServerManager.getAllServers().find((s: {name: string}) => s.name === payload.serverName);
if (!server) {
throw new Error(`Server not found: ${payload.serverName}`);
}
AppState.updateUnreadsAndMentionsPerServer(server.id, payload.mentions, payload.unreads);
}, {serverName, mentions, unreads, enableUnreadBadge});
}

export async function refreshBadgeStateForTest(app: ElectronApplication): Promise<void> {
await evaluateInMainProcess(app, () => {
const e2eTestRefsKey = '__e2eTestRefs';
const refs = (global as Record<string, unknown>)[e2eTestRefsKey] as E2eGlobalRefs | undefined;
refs?.AppState?.emitStatus();
});
}

export async function readOsBadge(electronApp: ElectronApplication): Promise<OsBadgeState> {
return evaluateInMainProcess(electronApp, ({app}) => {
const testState = (global as any).__testBadgeState;
const testBadgeStateKey = '__testBadgeState';
const testState = (global as Record<string, unknown>)[testBadgeStateKey] as BadgeTestState | undefined;

if (process.platform === 'darwin') {
const badge = app.dock?.getBadge() ?? '';
Expand Down
Loading
Loading