Skip to content
Closed
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
32 changes: 32 additions & 0 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*

- name: Install dependencies
run: npm ci

- name: Install Playwright Browsers
run: npx playwright install --with-deps

- name: Run Playwright tests
run: npx playwright test

- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report
path: playwright-report/
retention-days: 30
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,10 @@ src-tauri/gen
.flatpak-builder
release
!src-tauri/release
.tanstack
.tanstack

# Playwright
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
133 changes: 82 additions & 51 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"gen:translations": "lingui extract --clean --overwrite",
"test:typings": "tsc --noEmit --project ./tsconfig.json",
"test:unit": "vitest run",
"test:ui": "playwright test",
"test:lint": "biome ci .",
"test:lint:fix": "biome check --write .",
"package:checksums": "bash scripts/checksum.sh",
Expand Down Expand Up @@ -66,9 +67,11 @@
"@lingui/babel-plugin-lingui-macro": "5.4.0",
"@lingui/cli": "5.4.0",
"@lingui/vite-plugin": "5.4.0",
"@playwright/test": "1.54.2",
"@tanstack/router-plugin": "1.130.12",
"@tauri-apps/cli": "2.7.1",
"@types/lodash-es": "4.17.12",
"@types/node": "24.2.0",
"@types/react": "19.1.9",
"@types/react-dom": "19.1.7",
"@types/semver": "7.7.0",
Expand Down
33 changes: 33 additions & 0 deletions playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import process from 'node:process';

import { defineConfig, devices } from '@playwright/test';

/**
* Playwright Config https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: './tests',
fullyParallel: true,
forbidOnly: process.env.CI !== undefined,
retries: process.env.CI ? 2 : 0, // retries? in our moment of triumph?
workers: process.env.CI ? 1 : undefined,
reporter: process.env.CI ? 'github' : 'list',

use: {
baseURL: 'http://localhost:1420',
trace: 'on-first-retry',
},

projects: [
{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
},
],

webServer: {
command: 'npm run dev',
port: 1420,
reuseExistingServer: !process.env.CI,
},
});
4 changes: 2 additions & 2 deletions src/components/GlobalKeyBindings.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { invoke } from '@tauri-apps/api/core';
import { useCallback } from 'react';
import Keybinding from 'react-keybinding-component';

import SettingsBridge from '../lib/bridge-settings';
import player from '../lib/player';
import { usePlayerAPI } from '../stores/usePlayerStore';

Expand Down Expand Up @@ -32,7 +32,7 @@ function GlobalKeyBindings() {
playerAPI.jumpTo(player.getCurrentTime() + 10);
break;
case 'Alt':
await invoke('plugin:app-menu|toggle');
await SettingsBridge.toggleMenu();
break;
default:
break;
Expand Down
9 changes: 6 additions & 3 deletions src/components/PlayerEvents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { getCurrentWindow } from '@tauri-apps/api/window';
import { sendNotification } from '@tauri-apps/plugin-notification';
import { useEffect } from 'react';

import config from '../lib/config';
import ConfigBridge from '../lib/bridge-config';
import { getCover } from '../lib/cover';
import player from '../lib/player';
import { goToPlayingTrack } from '../lib/queue-origin';
Expand Down Expand Up @@ -59,7 +59,7 @@ function PlayerEvents() {

async function notifyTrackChange() {
const track = player.getTrack();
const isEnabled = await config.get('notifications');
const isEnabled = await ConfigBridge.get('notifications');
const isMinimized = await getCurrentWindow()
.isMinimized()
.catch(logAndNotifyError);
Expand Down Expand Up @@ -90,7 +90,10 @@ function PlayerEvents() {

// If follow track is enabled, switch to the right view + scroll to the track
// Do not do it if the app if focused, as users could be interacting with the app
if ((await config.get('audio_follow_playing_track')) && !isFocused) {
if (
(await ConfigBridge.get('audio_follow_playing_track')) &&
!isFocused
) {
goToPlayingTrack(queueOrigin, navigate);
}
}
Expand Down
20 changes: 9 additions & 11 deletions src/lib/config.ts → src/lib/bridge-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ import type { Config } from '../generated/typings';
import { logAndNotifyError } from './utils';

/**
* Config Bridge for the UI to communicate with the backend
* Config Bridge for the UI to communicate with the backend.
* Grouped here so they're easier to mock in E2E tests.
*/
class ConfigManager {
initialConfig: Config | null = null;

const ConfigBridge = {
/**
* Get the initial value of the config at the time of instantiation.
* Should only be used when starting the app.
Expand All @@ -19,17 +18,16 @@ class ConfigManager {
}

return window.__MUSEEKS_INITIAL_CONFIG[key];
}
},

async getAll(): Promise<Config> {
// TODO: check data shape?
return invoke('plugin:config|get_config');
}
},

async get<T extends keyof Config>(key: T): Promise<Config[T]> {
const config = await this.getAll();
return config[key];
}
},

async set<T extends keyof Config>(key: T, value: Config[T]): Promise<void> {
const config = await this.getAll();
Expand All @@ -42,7 +40,7 @@ class ConfigManager {
}

return;
}
}
},
};

export default new ConfigManager();
export default ConfigBridge;
4 changes: 2 additions & 2 deletions src/lib/database.ts → src/lib/bridge-database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import type {
} from '../generated/typings';

/**
* Bridge for the UI to communicate with the backend and manipulate the Database
* Bridge for the UI to communicate with the backend and manipulate the Database.
* Grouped here so they're easier to mock in E2E tests.
*/

// biome-ignore lint/complexity/noStaticOnlyClass: conflict with decorators rules
class DatabaseBridge {
// ---------------------------------------------------------------------------
Expand Down
Loading
Loading