Skip to content

Commit 489a28b

Browse files
author
Mohammod Al Amin Ashik
committed
fix(e2e): add testids for FeatureSet panel close button and overlay
- Add data-testid='featureset-panel-close' to X close button - Add data-testid='featureset-panel-overlay' to backdrop overlay - Update featureset.wdio.ts to click close button/overlay instead of Escape key Fixes TC-FS-004 and Cleanup tests failing because panel was blocking navigation
1 parent 26d5d74 commit 489a28b

6 files changed

Lines changed: 143 additions & 52 deletions

File tree

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: Install Linux deps
2-
description: Install build and runtime deps for Tauri app on Ubuntu
2+
description: Install build and runtime deps for Tauri app on Ubuntu (with caching)
33
inputs:
44
e2e:
55
description: Include E2E desktop deps (webkit2gtk-driver, xvfb, gnome-keyring)
@@ -12,22 +12,31 @@ inputs:
1212
runs:
1313
using: composite
1414
steps:
15-
- name: Install Linux deps
15+
# Cache apt packages to avoid re-downloading on every run
16+
# Uses awalsh128/cache-apt-pkgs-action for efficient caching
17+
- name: Cache apt packages (base)
18+
uses: awalsh128/cache-apt-pkgs-action@latest
19+
with:
20+
packages: build-essential pkg-config libglib2.0-dev libgtk-3-dev libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf libsecret-1-dev
21+
version: 1.0
22+
23+
- name: Cache apt packages (E2E)
24+
if: ${{ inputs.e2e == 'true' }}
25+
uses: awalsh128/cache-apt-pkgs-action@latest
26+
with:
27+
packages: webkit2gtk-driver xvfb gnome-keyring
28+
version: 1.0
29+
30+
- name: Verify glib installation
31+
if: ${{ inputs.verify_glib == 'true' }}
1632
shell: bash
1733
run: |
18-
BASE_DEPS="build-essential pkg-config libglib2.0-dev libgtk-3-dev libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf libsecret-1-dev"
19-
E2E_DEPS="webkit2gtk-driver xvfb gnome-keyring"
20-
sudo apt-get update
21-
if [ "${{ inputs.e2e }}" = "true" ]; then
22-
sudo apt-get install -y $BASE_DEPS $E2E_DEPS
23-
else
24-
sudo apt-get install -y $BASE_DEPS
25-
fi
26-
if [ "${{ inputs.verify_glib }}" = "true" ]; then
27-
echo "=== Verifying glib-2.0 installation ==="
28-
dpkg -l | grep libglib2.0-dev || echo "libglib2.0-dev not installed"
29-
find /usr -name 'glib-2.0.pc' 2>/dev/null || echo "glib-2.0.pc not found"
30-
pkg-config --modversion glib-2.0 || echo "pkg-config cannot find glib-2.0"
31-
pkg-config --exists 'glib-2.0 >= 2.70' && echo "glib-2.0 >= 2.70 found" || (echo "ERROR: glib-2.0 >= 2.70 not found"; exit 1)
32-
fi
33-
echo "PKG_CONFIG_PATH=$(pkg-config --variable pc_path pkg-config)" >> $GITHUB_ENV
34+
echo "=== Verifying glib-2.0 installation ==="
35+
dpkg -l | grep libglib2.0-dev || echo "libglib2.0-dev not installed"
36+
find /usr -name 'glib-2.0.pc' 2>/dev/null || echo "glib-2.0.pc not found"
37+
pkg-config --modversion glib-2.0 || echo "pkg-config cannot find glib-2.0"
38+
pkg-config --exists 'glib-2.0 >= 2.70' && echo "glib-2.0 >= 2.70 found" || (echo "ERROR: glib-2.0 >= 2.70 not found"; exit 1)
39+
40+
- name: Set PKG_CONFIG_PATH
41+
shell: bash
42+
run: echo "PKG_CONFIG_PATH=$(pkg-config --variable pc_path pkg-config)" >> $GITHUB_ENV

.github/workflows/ci.yml

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ permissions:
2121
env:
2222
CARGO_TERM_COLOR: always
2323
RUST_BACKTRACE: 1
24+
# Faster git fetches for cargo
25+
CARGO_NET_GIT_FETCH_WITH_CLI: true
2426
# Cache keys for better hit rates
2527
RUST_CACHE_KEY: v1
2628
PLAYWRIGHT_BROWSERS_PATH: ${{ github.workspace }}/.cache/ms-playwright
@@ -81,6 +83,19 @@ jobs:
8183
node-version: 20
8284
cache: 'pnpm'
8385

86+
# Cache pnpm store for faster installs
87+
- name: Get pnpm store directory
88+
shell: bash
89+
run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
90+
91+
- name: Cache pnpm store
92+
uses: actions/cache@v4
93+
with:
94+
path: ${{ env.STORE_PATH }}
95+
key: pnpm-store-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}
96+
restore-keys: |
97+
pnpm-store-${{ runner.os }}-
98+
8499
- run: pnpm install --frozen-lockfile
85100
- run: pnpm typecheck
86101
- run: pnpm lint
@@ -132,9 +147,12 @@ jobs:
132147
with:
133148
targets: ${{ matrix.target }}
134149

150+
# Share cache between rust-test and build jobs for faster compilation
135151
- uses: Swatinem/rust-cache@v2
136152
with:
137153
key: ${{ matrix.target }}
154+
shared-key: rust-${{ matrix.target }}
155+
cache-on-failure: true
138156

139157
# Install cargo-nextest
140158
- name: Install nextest
@@ -171,6 +189,7 @@ jobs:
171189

172190
# ─────────────────────────────────────────────────────────────
173191
# Build Verification (ensures app compiles on all platforms)
192+
# Runs after checks pass; uses cached Rust build artifacts
174193
# ─────────────────────────────────────────────────────────────
175194
build:
176195
needs: [rust-check, ts-check]
@@ -199,23 +218,64 @@ jobs:
199218
env:
200219
PKG_CONFIG_PATH: /usr/lib/x86_64-linux-gnu/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig
201220

221+
# Use shared cache key so builds benefit from rust-test artifacts
202222
- uses: Swatinem/rust-cache@v2
203223
with:
204-
key: ${{ matrix.target }}-build
224+
key: ${{ matrix.target }}
225+
shared-key: rust-${{ matrix.target }}
226+
cache-on-failure: true
205227
env:
206228
PKG_CONFIG_PATH: /usr/lib/x86_64-linux-gnu/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig
229+
207230
- uses: pnpm/action-setup@v4
208231
- uses: actions/setup-node@v4
209232
with:
210233
node-version: 20
211234
cache: 'pnpm'
212235

236+
# Cache pnpm store
237+
- name: Get pnpm store directory
238+
shell: bash
239+
run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
240+
241+
- name: Cache pnpm store
242+
uses: actions/cache@v4
243+
with:
244+
path: ${{ env.STORE_PATH }}
245+
key: pnpm-store-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}
246+
restore-keys: |
247+
pnpm-store-${{ runner.os }}-
248+
249+
# Cache Tauri CLI binary (avoid recompiling on every run)
250+
- name: Cache Tauri CLI
251+
uses: actions/cache@v4
252+
with:
253+
path: |
254+
~/.cargo/bin/cargo-tauri*
255+
~/.cargo/bin/tauri*
256+
key: tauri-cli-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}
257+
restore-keys: |
258+
tauri-cli-${{ runner.os }}-
259+
213260
- run: pnpm install --frozen-lockfile
214261
- run: pnpm build
215262
env:
216263
PKG_CONFIG_PATH: /usr/lib/x86_64-linux-gnu/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig
217264
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
218265

266+
# Upload build artifacts for e2e-desktop to reuse (Linux/Windows only)
267+
- name: Upload build artifacts
268+
if: matrix.os != 'macos-latest'
269+
uses: actions/upload-artifact@v4
270+
with:
271+
name: tauri-build-${{ matrix.os }}
272+
path: |
273+
target/release/bundle/
274+
target/release/mcpmux*
275+
target/release/*.exe
276+
retention-days: 1
277+
if-no-files-found: ignore
278+
219279
# ─────────────────────────────────────────────────────────────
220280
# Test Results Report (separate checks per test type and OS)
221281
# Uses dorny/test-reporter for granular GitHub Check Runs
@@ -397,9 +457,10 @@ jobs:
397457
# ─────────────────────────────────────────────────────────────
398458
# E2E Tests (Desktop app with WebDriver - Linux/Windows only)
399459
# Runs when: main branch, [e2e] in commit, or /e2e-desktop comment on PR
460+
# Depends on build to reuse artifacts (avoids rebuilding Tauri ~5-10 min)
400461
# ─────────────────────────────────────────────────────────────
401462
e2e-desktop:
402-
needs: [e2e-trigger-check]
463+
needs: [e2e-trigger-check, build]
403464
if: needs.e2e-trigger-check.outputs.run_e2e == 'true'
404465
uses: ./.github/workflows/e2e-desktop.yml
405466
with:

.github/workflows/e2e-desktop.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ jobs:
4444
- uses: Swatinem/rust-cache@v2
4545
with:
4646
key: ${{ matrix.os }}-e2e-desktop
47+
shared-key: rust-${{ matrix.os == 'ubuntu-latest' && 'x86_64-unknown-linux-gnu' || 'x86_64-pc-windows-msvc' }}
48+
cache-on-failure: true
4749
env:
4850
PKG_CONFIG_PATH: /usr/lib/x86_64-linux-gnu/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig
4951

@@ -53,6 +55,20 @@ jobs:
5355
node-version: 20
5456
cache: 'pnpm'
5557

58+
# Cache pnpm store for faster installs
59+
- name: Get pnpm store directory
60+
id: pnpm-cache
61+
shell: bash
62+
run: echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
63+
64+
- name: Cache pnpm store
65+
uses: actions/cache@v4
66+
with:
67+
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
68+
key: pnpm-store-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}
69+
restore-keys: |
70+
pnpm-store-${{ runner.os }}-
71+
5672
- name: Cache tauri-driver
5773
uses: actions/cache@v4
5874
id: tauri-driver-cache
@@ -66,6 +82,17 @@ jobs:
6682
env:
6783
PKG_CONFIG_PATH: /usr/lib/x86_64-linux-gnu/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig
6884

85+
# Cache Tauri CLI binary (avoid recompiling on every run)
86+
- name: Cache Tauri CLI
87+
uses: actions/cache@v4
88+
with:
89+
path: |
90+
~/.cargo/bin/cargo-tauri*
91+
~/.cargo/bin/tauri*
92+
key: tauri-cli-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}
93+
restore-keys: |
94+
tauri-cli-${{ runner.os }}-
95+
6996
- run: pnpm install --frozen-lockfile
7097

7198
- name: Build app

apps/desktop/src/features/featuresets/FeatureSetPanel.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ export function FeatureSetPanel({ featureSet, spaceId, onClose, onDelete, onUpda
327327
</div>
328328
</div>
329329
<button
330+
data-testid="featureset-panel-close"
330331
onClick={onClose}
331332
className="p-1.5 rounded-lg hover:bg-[rgb(var(--surface-hover))] transition-colors flex-shrink-0"
332333
>

apps/desktop/src/features/featuresets/FeatureSetsPage.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ export function FeatureSetsPage() {
334334
{/* Overlay backdrop when panel is open */}
335335
{selectedFeatureSet && (
336336
<div
337+
data-testid="featureset-panel-overlay"
337338
className="fixed inset-0 bg-black/20 backdrop-blur-[2px] z-40 animate-in fade-in duration-200"
338339
onClick={() => setSelectedFeatureSet(null)}
339340
/>

tests/e2e/specs/featureset.wdio.ts

Lines changed: 24 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -136,24 +136,25 @@ describe('FeatureSet - Server-All Auto Creation', () => {
136136
});
137137

138138
it('TC-FS-004: Disable server and verify FeatureSet is hidden', async () => {
139-
// Aggressively dismiss any open modal/panel - press Escape multiple times
140-
await browser.keys('Escape');
141-
await browser.pause(300);
142-
await browser.keys('Escape');
143-
await browser.pause(500);
144-
145-
// Click outside any potential modal to dismiss it
146-
const body = await $('body');
147-
await body.click({ x: 10, y: 10 });
148-
await browser.pause(500);
139+
// Close the FeatureSet detail panel if open (from previous test)
140+
// First try clicking the panel close button
141+
const panelCloseBtn = await byTestId('featureset-panel-close');
142+
if (await panelCloseBtn.isDisplayed().catch(() => false)) {
143+
console.log('[TC-FS-004] Clicking panel close button');
144+
await panelCloseBtn.click();
145+
await browser.pause(500);
146+
} else {
147+
// Try clicking the overlay to close
148+
const overlay = await byTestId('featureset-panel-overlay');
149+
if (await overlay.isDisplayed().catch(() => false)) {
150+
console.log('[TC-FS-004] Clicking panel overlay to close');
151+
await overlay.click();
152+
await browser.pause(500);
153+
}
154+
}
149155

150156
const myServersButton = await byTestId('nav-my-servers');
151-
// Try clicking even if not fully "clickable" - force the click
152-
try {
153-
await myServersButton.waitForClickable({ timeout: TIMEOUT.short });
154-
} catch {
155-
console.log('[TC-FS-004] Nav button not clickable, trying force click');
156-
}
157+
await myServersButton.waitForClickable({ timeout: TIMEOUT.medium });
157158
await myServersButton.click();
158159
await browser.pause(2000);
159160

@@ -180,24 +181,15 @@ describe('FeatureSet - Server-All Auto Creation', () => {
180181
});
181182

182183
it('Cleanup: Uninstall Echo Server', async () => {
183-
// Aggressively dismiss any open modal/panel
184-
await browser.keys('Escape');
185-
await browser.pause(300);
186-
await browser.keys('Escape');
187-
await browser.pause(500);
188-
189-
// Click outside any potential modal to dismiss it
190-
const body = await $('body');
191-
await body.click({ x: 10, y: 10 });
192-
await browser.pause(500);
184+
// Close any open panel first
185+
const panelCloseBtn = await byTestId('featureset-panel-close');
186+
if (await panelCloseBtn.isDisplayed().catch(() => false)) {
187+
await panelCloseBtn.click();
188+
await browser.pause(500);
189+
}
193190

194191
const discoverButton = await byTestId('nav-discover');
195-
// Try clicking even if not fully "clickable"
196-
try {
197-
await discoverButton.waitForClickable({ timeout: TIMEOUT.short });
198-
} catch {
199-
console.log('[Cleanup] Nav button not clickable, trying force click');
200-
}
192+
await discoverButton.waitForClickable({ timeout: TIMEOUT.medium });
201193
await discoverButton.click();
202194
await browser.pause(2000);
203195

0 commit comments

Comments
 (0)