From d12cbffda7166bbbc75f85a8823657971a5a70b1 Mon Sep 17 00:00:00 2001 From: Hibryda Date: Sun, 8 Mar 2026 21:58:23 +0100 Subject: [PATCH] fix(e2e): consolidate specs into single file and fix WebDriver click issues Tauri creates one app session per spec file; multiple files caused invalid session id on subsequent specs. WebDriver clicks on Svelte 5 components inside scrollable panels dont trigger onclick handlers via WebKit2GTK/tauri-driver - use browser.execute() JS clicks. Also removed tauri-plugin-log (redundant with telemetry::init()). --- v2/Cargo.lock | 312 +-------------------------- v2/src-tauri/Cargo.toml | 1 - v2/src-tauri/src/lib.rs | 12 +- v2/tests/e2e/specs/bterminal.test.ts | 268 +++++++++++++++++++++++ v2/tests/e2e/wdio.conf.js | 8 +- 5 files changed, 279 insertions(+), 322 deletions(-) create mode 100644 v2/tests/e2e/specs/bterminal.test.ts diff --git a/v2/Cargo.lock b/v2/Cargo.lock index dcf71d3..d8dabae 100644 --- a/v2/Cargo.lock +++ b/v2/Cargo.lock @@ -8,17 +8,6 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" -[[package]] -name = "ahash" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" -dependencies = [ - "getrandom 0.2.17", - "once_cell", - "version_check", -] - [[package]] name = "ahash" version = "0.8.12" @@ -55,23 +44,6 @@ dependencies = [ "alloc-no-stdlib", ] -[[package]] -name = "android_log-sys" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84521a3cf562bc62942e294181d9eef17eb38ceb8c68677bc49f144e4c3d4f8d" - -[[package]] -name = "android_logger" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb4e440d04be07da1f1bf44fb4495ebd58669372fe0cffa6e48595ac5bd88a3" -dependencies = [ - "android_log-sys", - "env_filter 0.1.4", - "log", -] - [[package]] name = "android_system_properties" version = "0.1.5" @@ -146,12 +118,6 @@ dependencies = [ "derive_arbitrary", ] -[[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" - [[package]] name = "async-trait" version = "0.1.89" @@ -225,18 +191,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - [[package]] name = "block-buffer" version = "0.10.4" @@ -255,29 +209,6 @@ dependencies = [ "objc2", ] -[[package]] -name = "borsh" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1da5ab77c1437701eeff7c88d968729e7766172279eab0676857b3d63af7a6f" -dependencies = [ - "borsh-derive", - "cfg_aliases", -] - -[[package]] -name = "borsh-derive" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0686c856aa6aac0c4498f936d7d6a02df690f614c03e4d906d1018062b5c5e2c" -dependencies = [ - "once_cell", - "proc-macro-crate 3.5.0", - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "brotli" version = "8.0.2" @@ -318,7 +249,6 @@ dependencies = [ "tauri", "tauri-build", "tauri-plugin-dialog", - "tauri-plugin-log", "tauri-plugin-updater", "tempfile", "tokio", @@ -362,40 +292,6 @@ version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" -[[package]] -name = "byte-unit" -version = "5.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c6d47a4e2961fb8721bcfc54feae6455f2f64e7054f9bc67e875f0e77f4c58d" -dependencies = [ - "rust_decimal", - "schemars 1.2.1", - "serde", - "utf8-width", -] - -[[package]] -name = "bytecheck" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" -dependencies = [ - "bytecheck_derive", - "ptr_meta", - "simdutf8", -] - -[[package]] -name = "bytecheck_derive" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "bytemuck" version = "1.25.0" @@ -527,12 +423,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - [[package]] name = "chrono" version = "0.4.44" @@ -978,16 +868,6 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" -[[package]] -name = "env_filter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" -dependencies = [ - "log", - "regex", -] - [[package]] name = "env_filter" version = "1.0.0" @@ -1006,7 +886,7 @@ checksum = "b2daee4ea451f429a58296525ddf28b45a3b64f1acf6587e2067437bb11e218d" dependencies = [ "anstream", "anstyle", - "env_filter 1.0.0", + "env_filter", "jiff", "log", ] @@ -1065,15 +945,6 @@ dependencies = [ "simd-adler32", ] -[[package]] -name = "fern" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4316185f709b23713e41e3195f90edef7fb00c3ed4adc79769cf09cc762a3b29" -dependencies = [ - "log", -] - [[package]] name = "field-offset" version = "0.3.6" @@ -1194,12 +1065,6 @@ dependencies = [ "libc", ] -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - [[package]] name = "futf" version = "0.1.5" @@ -1600,9 +1465,6 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash 0.7.8", -] [[package]] name = "hashbrown" @@ -1610,7 +1472,7 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ - "ahash 0.8.12", + "ahash", ] [[package]] @@ -2257,9 +2119,6 @@ name = "log" version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" -dependencies = [ - "value-bag", -] [[package]] name = "mac" @@ -2535,15 +2394,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "num_threads" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" -dependencies = [ - "libc", -] - [[package]] name = "objc2" version = "0.6.4" @@ -3261,26 +3111,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "ptr_meta" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" -dependencies = [ - "ptr_meta_derive", -] - -[[package]] -name = "ptr_meta_derive" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "quick-xml" version = "0.38.4" @@ -3311,12 +3141,6 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - [[package]] name = "rand" version = "0.7.3" @@ -3493,15 +3317,6 @@ version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" -[[package]] -name = "rend" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" -dependencies = [ - "bytecheck", -] - [[package]] name = "reqwest" version = "0.12.28" @@ -3613,35 +3428,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "rkyv" -version = "0.7.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2297bf9c81a3f0dc96bc9521370b88f054168c29826a75e89c55ff196e7ed6a1" -dependencies = [ - "bitvec", - "bytecheck", - "bytes", - "hashbrown 0.12.3", - "ptr_meta", - "rend", - "rkyv_derive", - "seahash", - "tinyvec", - "uuid", -] - -[[package]] -name = "rkyv_derive" -version = "0.7.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84d7b42d4b8d06048d3ac8db0eb31bcb942cbeb709f0b5f2b2ebde398d3038f5" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "rusqlite" version = "0.31.0" @@ -3656,22 +3442,6 @@ dependencies = [ "smallvec", ] -[[package]] -name = "rust_decimal" -version = "1.40.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61f703d19852dbf87cbc513643fa81428361eb6940f1ac14fd58155d295a3eb0" -dependencies = [ - "arrayvec", - "borsh", - "bytes", - "num-traits", - "rand 0.8.5", - "rkyv", - "serde", - "serde_json", -] - [[package]] name = "rustc_version" version = "0.4.1" @@ -3854,12 +3624,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "seahash" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" - [[package]] name = "security-framework" version = "3.7.0" @@ -4192,12 +3956,6 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" -[[package]] -name = "simdutf8" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" - [[package]] name = "siphasher" version = "0.3.11" @@ -4438,12 +4196,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - [[package]] name = "tar" version = "0.4.44" @@ -4632,28 +4384,6 @@ dependencies = [ "url", ] -[[package]] -name = "tauri-plugin-log" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7545bd67f070a4500432c826e2e0682146a1d6712aee22a2786490156b574d93" -dependencies = [ - "android_logger", - "byte-unit", - "fern", - "log", - "objc2", - "objc2-foundation", - "serde", - "serde_json", - "serde_repr", - "swift-rs", - "tauri", - "tauri-plugin", - "thiserror 2.0.18", - "time", -] - [[package]] name = "tauri-plugin-updater" version = "2.10.0" @@ -4877,9 +4607,7 @@ checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", - "libc", "num-conv", - "num_threads", "powerfmt", "serde_core", "time-core", @@ -4912,21 +4640,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "tinyvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" version = "1.50.0" @@ -5432,12 +5145,6 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" -[[package]] -name = "utf8-width" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1292c0d970b54115d14f2492fe0170adf21d68a1de108eebc51c1df4f346a091" - [[package]] name = "utf8_iter" version = "1.0.4" @@ -5468,12 +5175,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" -[[package]] -name = "value-bag" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba6f5989077681266825251a52748b8c1d8a4ad098cc37e440103d0ea717fc0" - [[package]] name = "vcpkg" version = "0.2.15" @@ -6452,15 +6153,6 @@ dependencies = [ "x11-dl", ] -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - [[package]] name = "x11" version = "2.21.0" diff --git a/v2/src-tauri/Cargo.toml b/v2/src-tauri/Cargo.toml index a702493..8b0b6ad 100644 --- a/v2/src-tauri/Cargo.toml +++ b/v2/src-tauri/Cargo.toml @@ -22,7 +22,6 @@ serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } log = "0.4" tauri = { version = "2.10.3", features = [] } -tauri-plugin-log = "2" rusqlite = { version = "0.31", features = ["bundled"] } dirs = "5" notify = { version = "6", features = ["macos_fsevent"] } diff --git a/v2/src-tauri/src/lib.rs b/v2/src-tauri/src/lib.rs index a47e695..3100bc7 100644 --- a/v2/src-tauri/src/lib.rs +++ b/v2/src-tauri/src/lib.rs @@ -621,14 +621,10 @@ pub fn run() { .plugin(tauri_plugin_updater::Builder::new().build()) .plugin(tauri_plugin_dialog::init()) .setup(move |app| { - if cfg!(debug_assertions) { - // Ignore error if logger already initialized (telemetry::init sets up tracing-subscriber) - let _ = app.handle().plugin( - tauri_plugin_log::Builder::default() - .level(log::LevelFilter::Info) - .build(), - ); - } + // Note: tauri-plugin-log is NOT initialized here because telemetry::init() + // already sets up tracing-subscriber (which bridges the `log` crate via + // tracing's compatibility layer). Adding plugin-log would panic with + // "attempted to set a logger after the logging system was already initialized". // Create TauriEventSink for core managers let sink: Arc = diff --git a/v2/tests/e2e/specs/bterminal.test.ts b/v2/tests/e2e/specs/bterminal.test.ts new file mode 100644 index 0000000..fdfcfac --- /dev/null +++ b/v2/tests/e2e/specs/bterminal.test.ts @@ -0,0 +1,268 @@ +import { browser, expect } from '@wdio/globals'; + +// All E2E tests run in a single spec file because Tauri launches one app +// instance per session, and tauri-driver doesn't support re-creating sessions. + +describe('BTerminal — Smoke Tests', () => { + it('should render the application window', async () => { + const title = await browser.getTitle(); + expect(title).toBe('BTerminal'); + }); + + it('should display the status bar', async () => { + const statusBar = await browser.$('.status-bar'); + await expect(statusBar).toBeDisplayed(); + }); + + it('should show version text in status bar', async () => { + const version = await browser.$('.status-bar .version'); + await expect(version).toBeDisplayed(); + const text = await version.getText(); + expect(text).toContain('BTerminal'); + }); + + it('should display the sidebar rail', async () => { + const sidebarRail = await browser.$('.sidebar-rail'); + await expect(sidebarRail).toBeDisplayed(); + }); + + it('should display the workspace area', async () => { + const workspace = await browser.$('.workspace'); + await expect(workspace).toBeDisplayed(); + }); + + it('should toggle sidebar with settings button', async () => { + const settingsBtn = await browser.$('.rail-btn'); + await settingsBtn.click(); + + const sidebarPanel = await browser.$('.sidebar-panel'); + await expect(sidebarPanel).toBeDisplayed(); + + // Click again to close + await settingsBtn.click(); + await expect(sidebarPanel).not.toBeDisplayed(); + }); +}); + +describe('BTerminal — Workspace & Projects', () => { + it('should display the project grid', async () => { + const grid = await browser.$('.project-grid'); + await expect(grid).toBeDisplayed(); + }); + + it('should render at least one project box', async () => { + const boxes = await browser.$$('.project-box'); + expect(boxes.length).toBeGreaterThanOrEqual(1); + }); + + it('should show project header with name', async () => { + const header = await browser.$('.project-header'); + await expect(header).toBeDisplayed(); + + const name = await browser.$('.project-name'); + const text = await name.getText(); + expect(text.length).toBeGreaterThan(0); + }); + + it('should show project-level tabs (Claude, Files, Context)', async () => { + const box = await browser.$('.project-box'); + const tabs = await box.$$('.ptab'); + expect(tabs.length).toBe(3); + }); + + it('should highlight active project on click', async () => { + const header = await browser.$('.project-header'); + await header.click(); + + const activeBox = await browser.$('.project-box.active'); + await expect(activeBox).toBeDisplayed(); + }); + + it('should switch project tabs', async () => { + // Use JS click — WebDriver clicks don't always trigger Svelte onclick + // on buttons inside complex components via WebKit2GTK/tauri-driver + const switched = await browser.execute(() => { + const box = document.querySelector('.project-box'); + if (!box) return false; + const tabs = box.querySelectorAll('.ptab'); + if (tabs.length < 2) return false; + (tabs[1] as HTMLElement).click(); + return true; + }); + expect(switched).toBe(true); + await browser.pause(500); + + const box = await browser.$('.project-box'); + const activeTab = await box.$('.ptab.active'); + const text = await activeTab.getText(); + expect(text.toLowerCase()).toContain('files'); + + // Switch back to Claude tab + await browser.execute(() => { + const tab = document.querySelector('.project-box .ptab'); + if (tab) (tab as HTMLElement).click(); + }); + await browser.pause(300); + }); + + it('should display the status bar with project count', async () => { + const statusBar = await browser.$('.status-bar .left'); + const text = await statusBar.getText(); + expect(text).toContain('projects'); + }); + + it('should display agent count in status bar', async () => { + const statusBar = await browser.$('.status-bar .left'); + const text = await statusBar.getText(); + expect(text).toContain('agents'); + }); +}); + +describe('BTerminal — Settings Panel', () => { + before(async () => { + // Open settings panel + const settingsBtn = await browser.$('.rail-btn'); + await settingsBtn.click(); + const panel = await browser.$('.sidebar-panel'); + await panel.waitForDisplayed({ timeout: 5000 }); + }); + + after(async () => { + // Close settings if still open — use keyboard shortcut as most reliable method + const panel = await browser.$('.sidebar-panel'); + if (await panel.isDisplayed()) { + await browser.keys('Escape'); + await browser.pause(500); + } + }); + + it('should display the settings tab container', async () => { + const settingsTab = await browser.$('.settings-tab'); + await expect(settingsTab).toBeDisplayed(); + }); + + it('should show settings sections', async () => { + const sections = await browser.$$('.settings-section'); + expect(sections.length).toBeGreaterThanOrEqual(1); + }); + + it('should display theme dropdown', async () => { + const dropdown = await browser.$('.custom-dropdown .dropdown-trigger'); + await expect(dropdown).toBeDisplayed(); + }); + + it('should open theme dropdown and show options', async () => { + // Use JS click — WebDriver clicks don't reliably trigger Svelte onclick + // on buttons inside scrollable panels via WebKit2GTK/tauri-driver + await browser.execute(() => { + const trigger = document.querySelector('.custom-dropdown .dropdown-trigger'); + if (trigger) (trigger as HTMLElement).click(); + }); + await browser.pause(500); + + const menu = await browser.$('.dropdown-menu'); + await menu.waitForExist({ timeout: 3000 }); + + const options = await browser.$$('.dropdown-option'); + expect(options.length).toBeGreaterThan(0); + + // Close dropdown by clicking trigger again + await browser.execute(() => { + const trigger = document.querySelector('.custom-dropdown .dropdown-trigger'); + if (trigger) (trigger as HTMLElement).click(); + }); + await browser.pause(300); + }); + + it('should display group list', async () => { + const groupList = await browser.$('.group-list'); + await expect(groupList).toBeDisplayed(); + }); + + it('should close settings panel with close button', async () => { + // Ensure settings is open + const panel = await browser.$('.sidebar-panel'); + if (!(await panel.isDisplayed())) { + const settingsBtn = await browser.$('.rail-btn'); + await settingsBtn.click(); + await panel.waitForDisplayed({ timeout: 3000 }); + } + + // Use JS click for reliability + await browser.execute(() => { + const btn = document.querySelector('.panel-close'); + if (btn) (btn as HTMLElement).click(); + }); + await browser.pause(500); + + await expect(panel).not.toBeDisplayed(); + }); +}); + +describe('BTerminal — Keyboard Shortcuts', () => { + it('should open command palette with Ctrl+K', async () => { + // Focus the app window via JS to ensure keyboard events are received + await browser.execute(() => document.body.focus()); + await browser.pause(200); + await browser.keys(['Control', 'k']); + + const palette = await browser.$('.palette'); + await palette.waitForDisplayed({ timeout: 3000 }); + + const input = await browser.$('.palette-input'); + await expect(input).toBeDisplayed(); + + // Close with Escape + await browser.keys('Escape'); + await palette.waitForDisplayed({ timeout: 3000, reverse: true }); + }); + + it('should toggle settings with Ctrl+,', async () => { + await browser.keys(['Control', ',']); + + const panel = await browser.$('.sidebar-panel'); + await panel.waitForDisplayed({ timeout: 3000 }); + + // Close with Ctrl+, + await browser.keys(['Control', ',']); + await panel.waitForDisplayed({ timeout: 3000, reverse: true }); + }); + + it('should toggle sidebar with Ctrl+B', async () => { + // Open sidebar first + await browser.keys(['Control', ',']); + const panel = await browser.$('.sidebar-panel'); + await panel.waitForDisplayed({ timeout: 3000 }); + + // Toggle off with Ctrl+B + await browser.keys(['Control', 'b']); + await panel.waitForDisplayed({ timeout: 3000, reverse: true }); + }); + + it('should close sidebar with Escape', async () => { + // Open sidebar + await browser.keys(['Control', ',']); + const panel = await browser.$('.sidebar-panel'); + await panel.waitForDisplayed({ timeout: 3000 }); + + // Close with Escape + await browser.keys('Escape'); + await panel.waitForDisplayed({ timeout: 3000, reverse: true }); + }); + + it('should show command palette with group list', async () => { + await browser.keys(['Control', 'k']); + + const palette = await browser.$('.palette'); + await palette.waitForDisplayed({ timeout: 3000 }); + + const items = await browser.$$('.palette-item'); + expect(items.length).toBeGreaterThanOrEqual(1); + + const groupName = await browser.$('.palette-item .group-name'); + await expect(groupName).toBeDisplayed(); + + await browser.keys('Escape'); + await palette.waitForDisplayed({ timeout: 3000, reverse: true }); + }); +}); diff --git a/v2/tests/e2e/wdio.conf.js b/v2/tests/e2e/wdio.conf.js index 6e5bccc..250168e 100644 --- a/v2/tests/e2e/wdio.conf.js +++ b/v2/tests/e2e/wdio.conf.js @@ -22,7 +22,9 @@ export const config = { path: '/', // ── Specs ── - specs: [resolve(__dirname, 'specs/**/*.test.ts')], + // Single spec file — Tauri launches one app instance per session, + // and tauri-driver can't re-create sessions between spec files. + specs: [resolve(__dirname, 'specs/bterminal.test.ts')], // ── Capabilities ── capabilities: [{ @@ -77,7 +79,7 @@ export const config = { }, /** - * Spawn tauri-driver before each session. + * Spawn tauri-driver before the session. * tauri-driver bridges WebDriver protocol to WebKit2GTK's inspector. */ beforeSession() { @@ -105,7 +107,7 @@ export const config = { }, /** - * Kill tauri-driver after each session. + * Kill tauri-driver after the test run. */ afterSession() { if (tauriDriver) {