fix(e2e): dual-stack selector compatibility — 18/18 specs pass on Tauri

- selectors.ts: dual CSS selectors for all divergent class names
- actions.ts: fallback DOM queries (try primary, then alternatives)
- assertions.ts: waitUntil with dual selectors
- 12 spec files updated with graceful skip for stack-specific features
- 175 tests pass, 30 skip (expected: groups/diagnostics Tauri-absent)
This commit is contained in:
Hibryda 2026-03-22 05:56:01 +01:00
parent 77b9ce9f62
commit 3d74398fde
16 changed files with 482 additions and 236 deletions

View file

@ -1,23 +1,31 @@
/**
* Diagnostics settings tab tests connection status, fleet info, refresh.
*
* Diagnostics tab is Electrobun-specific. Tests gracefully skip on Tauri
* where this tab does not exist.
*/
import { browser, expect } from '@wdio/globals';
import * as S from '../helpers/selectors.ts';
import { openSettings, closeSettings, switchSettingsCategory } from '../helpers/actions.ts';
/** Navigate to the last settings tab (expected to be Diagnostics on Electrobun) */
async function navigateToLastTab(): Promise<number> {
const tabCount = await browser.execute(() => {
return (document.querySelectorAll('.settings-sidebar .sidebar-item').length
|| document.querySelectorAll('.settings-tab').length
|| document.querySelectorAll('.cat-btn').length);
});
if (tabCount > 0) {
await switchSettingsCategory(tabCount - 1);
}
return tabCount;
}
describe('Diagnostics tab', () => {
before(async () => {
await openSettings();
// Click Diagnostics tab (last category)
const tabCount = await browser.execute(() => {
return (document.querySelectorAll('.settings-tab').length
|| document.querySelectorAll('.cat-btn').length
|| document.querySelectorAll('.settings-sidebar .sidebar-item').length);
});
if (tabCount > 0) {
await switchSettingsCategory(tabCount - 1);
}
await navigateToLastTab();
});
after(async () => {
@ -25,17 +33,25 @@ describe('Diagnostics tab', () => {
await browser.pause(300);
});
it('should render the diagnostics container', async () => {
it('should render the diagnostics container', async function () {
const exists = await browser.execute((sel: string) => {
return document.querySelector(sel) !== null;
}, S.DIAGNOSTICS);
if (exists) {
const el = await browser.$(S.DIAGNOSTICS);
await expect(el).toBeDisplayed();
if (!exists) {
// Diagnostics tab is Electrobun-only — skip on Tauri
this.skip();
return;
}
const el = await browser.$(S.DIAGNOSTICS);
await expect(el).toBeDisplayed();
});
it('should show Transport Diagnostics heading', async () => {
it('should show Transport Diagnostics heading', async function () {
const exists = await browser.execute(() => {
return document.querySelector('.diagnostics') !== null;
});
if (!exists) { this.skip(); return; }
const text = await browser.execute((sel: string) => {
const el = document.querySelector(sel);
return el?.textContent ?? '';
@ -45,7 +61,12 @@ describe('Diagnostics tab', () => {
}
});
it('should show PTY daemon connection status', async () => {
it('should show PTY daemon connection status', async function () {
const exists = await browser.execute(() => {
return document.querySelector('.diagnostics') !== null;
});
if (!exists) { this.skip(); return; }
const texts = await browser.execute((sel: string) => {
const keys = document.querySelectorAll(sel);
return Array.from(keys).map(k => k.textContent ?? '');
@ -55,7 +76,12 @@ describe('Diagnostics tab', () => {
}
});
it('should show agent fleet section', async () => {
it('should show agent fleet section', async function () {
const exists = await browser.execute(() => {
return document.querySelector('.diagnostics') !== null;
});
if (!exists) { this.skip(); return; }
const texts = await browser.execute((sel: string) => {
const labels = document.querySelectorAll(sel);
return Array.from(labels).map(l => l.textContent?.toLowerCase() ?? '');
@ -65,24 +91,39 @@ describe('Diagnostics tab', () => {
}
});
it('should show last refresh timestamp', async () => {
const exists = await browser.execute((sel: string) => {
it('should show last refresh timestamp', async function () {
const exists = await browser.execute(() => {
return document.querySelector('.diagnostics') !== null;
});
if (!exists) { this.skip(); return; }
const footerExists = await browser.execute((sel: string) => {
return document.querySelector(sel) !== null;
}, S.DIAG_FOOTER);
if (exists) {
if (footerExists) {
const el = await browser.$(S.DIAG_FOOTER);
await expect(el).toBeDisplayed();
}
});
it('should have a refresh button', async () => {
it('should have a refresh button', async function () {
const exists = await browser.execute(() => {
return document.querySelector('.diagnostics') !== null;
});
if (!exists) { this.skip(); return; }
const refreshBtn = await browser.$(S.REFRESH_BTN);
if (await refreshBtn.isExisting()) {
expect(await refreshBtn.isClickable()).toBe(true);
}
});
it('should show connection indicator with color', async () => {
it('should show connection indicator with color', async function () {
const exists = await browser.execute(() => {
return document.querySelector('.diagnostics') !== null;
});
if (!exists) { this.skip(); return; }
const hasIndicator = await browser.execute(() => {
return (document.querySelector('.diag-status')
?? document.querySelector('.status-dot')
@ -91,7 +132,12 @@ describe('Diagnostics tab', () => {
expect(typeof hasIndicator).toBe('boolean');
});
it('should show session count', async () => {
it('should show session count', async function () {
const exists = await browser.execute(() => {
return document.querySelector('.diagnostics') !== null;
});
if (!exists) { this.skip(); return; }
const hasCount = await browser.execute(() => {
return (document.querySelector('.session-count')
?? document.querySelector('.diag-value')) !== null;