From f5866a23764cd4ebc5212355bc183ac385b4ddf2 Mon Sep 17 00:00:00 2001 From: lucaronin Date: Thu, 7 May 2026 18:31:20 +0200 Subject: [PATCH] fix: resolve codacy high severity findings --- .github/workflows/ci.yml | 14 ++-- .github/workflows/deploy-docs.yml | 4 +- .github/workflows/release-stable.yml | 22 +++--- .github/workflows/release.yml | 22 +++--- .semgrepignore | 10 +++ src-tauri/Cargo.lock | 23 +++--- src-tauri/src/claude_cli.rs | 20 +++++- src-tauri/src/codex_cli.rs | 18 ++++- src-tauri/src/linux_appimage.rs | 34 +++++++-- src-tauri/src/mcp.rs | 95 +++++++++++++------------ src/components/useNoteListSort.test.tsx | 13 ++-- 11 files changed, 171 insertions(+), 104 deletions(-) create mode 100644 .semgrepignore diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 926b5db0..3b2da0e5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,7 +28,7 @@ jobs: fetch-depth: 0 # Full history for CodeScene - name: Setup pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa with: version: 10 @@ -65,7 +65,7 @@ jobs: - name: Upload frontend coverage to Codecov if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@75cd11691c0faa626561e295848008c8a7dddffe with: use_oidc: true fail_ci_if_error: true @@ -143,7 +143,7 @@ jobs: - uses: actions/checkout@v4 - name: Setup Rust - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 with: components: rustfmt, clippy, llvm-tools-preview @@ -159,7 +159,7 @@ jobs: ${{ runner.os }}-cargo-${{ env.RUST_TARGET_CACHE_VERSION }}- - name: Install cargo-llvm-cov - uses: taiki-e/install-action@cargo-llvm-cov + uses: taiki-e/install-action@e5de28abeb52d916c5e5875d54b21a9e738b61ec - name: Rust tests + coverage (≥85% lines) run: | @@ -175,7 +175,7 @@ jobs: - name: Upload Rust coverage to Codecov if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@75cd11691c0faa626561e295848008c8a7dddffe with: use_oidc: true fail_ci_if_error: true @@ -213,7 +213,7 @@ jobs: file - name: Setup pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa with: version: 10 @@ -224,7 +224,7 @@ jobs: cache: 'pnpm' - name: Setup Rust - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 with: components: clippy diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 07313436..d82adb2c 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -33,7 +33,7 @@ jobs: uses: actions/checkout@v4 - name: Setup pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa with: version: 10 @@ -44,7 +44,7 @@ jobs: cache: pnpm - name: Setup Bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 with: bun-version: latest diff --git a/.github/workflows/release-stable.yml b/.github/workflows/release-stable.yml index 9eae918c..f6fb7f37 100644 --- a/.github/workflows/release-stable.yml +++ b/.github/workflows/release-stable.yml @@ -82,7 +82,7 @@ jobs: - uses: actions/checkout@v4 - name: Setup pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa with: version: 10 @@ -93,12 +93,12 @@ jobs: cache: 'pnpm' - name: Setup Bun (required for bundle-qmd.sh) - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 with: bun-version: latest - name: Setup Rust - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 with: targets: ${{ matrix.target }} @@ -292,7 +292,7 @@ jobs: rpm - name: Setup pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa with: version: 10 @@ -303,7 +303,7 @@ jobs: cache: 'pnpm' - name: Setup Rust - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 with: targets: x86_64-unknown-linux-gnu @@ -389,7 +389,7 @@ jobs: - uses: actions/checkout@v4 - name: Setup pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa with: version: 10 @@ -400,7 +400,7 @@ jobs: cache: 'pnpm' - name: Setup Rust - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 with: targets: x86_64-pc-windows-msvc @@ -682,7 +682,7 @@ jobs: echo "stable-latest.json:"; cat stable-latest.json - name: Publish GitHub Release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 with: tag_name: ${{ needs.version.outputs.tag }} name: Tolaria ${{ needs.version.outputs.display_version }} @@ -740,7 +740,7 @@ jobs: - uses: actions/checkout@v4 - name: Setup pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa with: version: 10 @@ -751,7 +751,7 @@ jobs: cache: 'pnpm' - name: Setup Bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 with: bun-version: latest @@ -780,7 +780,7 @@ jobs: cp _site/alpha/latest.json _site/latest-canary.json - name: Deploy to GitHub Pages - uses: peaceiris/actions-gh-pages@v4 + uses: peaceiris/actions-gh-pages@e9c66a37f080288a11235e32cbe2dc5fb3a679cc with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./_site diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a7eed6af..e9211358 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -143,7 +143,7 @@ jobs: - uses: actions/checkout@v4 - name: Setup pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa with: version: 10 @@ -154,12 +154,12 @@ jobs: cache: 'pnpm' - name: Setup Bun (required for bundle-qmd.sh) - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 with: bun-version: latest - name: Setup Rust - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 with: targets: ${{ matrix.target }} @@ -348,7 +348,7 @@ jobs: rpm - name: Setup pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa with: version: 10 @@ -359,7 +359,7 @@ jobs: cache: 'pnpm' - name: Setup Rust - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 with: targets: x86_64-unknown-linux-gnu @@ -445,7 +445,7 @@ jobs: - uses: actions/checkout@v4 - name: Setup pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa with: version: 10 @@ -456,7 +456,7 @@ jobs: cache: 'pnpm' - name: Setup Rust - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 with: targets: x86_64-pc-windows-msvc @@ -730,7 +730,7 @@ jobs: echo "alpha-latest.json:"; cat alpha-latest.json - name: Publish GitHub Release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 with: tag_name: ${{ needs.version.outputs.tag }} name: Tolaria ${{ needs.version.outputs.display_version }} @@ -786,7 +786,7 @@ jobs: - uses: actions/checkout@v4 - name: Setup pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa with: version: 10 @@ -797,7 +797,7 @@ jobs: cache: 'pnpm' - name: Setup Bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 with: bun-version: latest @@ -826,7 +826,7 @@ jobs: cp _site/alpha/latest.json _site/latest-canary.json - name: Deploy to GitHub Pages - uses: peaceiris/actions-gh-pages@v4 + uses: peaceiris/actions-gh-pages@e9c66a37f080288a11235e32cbe2dc5fb3a679cc with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./_site diff --git a/.semgrepignore b/.semgrepignore new file mode 100644 index 00000000..f79744f4 --- /dev/null +++ b/.semgrepignore @@ -0,0 +1,10 @@ +tests/ +e2e/ +node_modules/ +dist/ +coverage/ +test-results/ +src-tauri/target/ +target/ +src-tauri/gen/apple/assets/mcp-server/index.js +src-tauri/gen/apple/assets/mcp-server/ws-bridge.js diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index a4daf78c..4e3d49c3 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1079,7 +1079,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2908,15 +2908,14 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.78" +version = "0.10.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38c4372413cdaaf3cc79dd92d29d7d9f5ab09b51b10dded508fb90bb70b9222" +checksum = "bf0b434746ee2832f4f0baf10137e1cabb18cbe6912c69e2e33263c45250f542" dependencies = [ "bitflags 2.11.0", "cfg-if", "foreign-types 0.3.2", "libc", - "once_cell", "openssl-macros", "openssl-sys", ] @@ -2940,9 +2939,9 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-sys" -version = "0.9.114" +version = "0.9.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13ce1245cd07fcc4cfdb438f7507b0c7e4f3849a69fd84d52374c66d83741bb6" +checksum = "158fe5b292746440aa6e7a7e690e55aeb72d41505e2804c23c6973ad0e9c9781" dependencies = [ "cc", "libc", @@ -3454,7 +3453,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3888,7 +3887,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3945,7 +3944,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3956,9 +3955,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] name = "rustls-webpki" -version = "0.103.12" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8279bb85272c9f10811ae6a6c547ff594d6a7f3c6c6b02ee9726d1d0dcfcdd06" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ "ring", "rustls-pki-types", @@ -5109,7 +5108,7 @@ dependencies = [ "getrandom 0.4.1", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/src-tauri/src/claude_cli.rs b/src-tauri/src/claude_cli.rs index 569800b5..6382eee4 100644 --- a/src-tauri/src/claude_cli.rs +++ b/src-tauri/src/claude_cli.rs @@ -641,6 +641,22 @@ mod tests { use std::ffi::OsString; use std::process::Command; + #[cfg(target_os = "linux")] + fn current_test_binary() -> PathBuf { + std::fs::read_link("/proc/self/exe").unwrap() + } + + #[cfg(target_os = "macos")] + fn current_test_binary() -> PathBuf { + let pid = std::process::id().to_string(); + let output = Command::new("/bin/ps") + .args(["-p", pid.as_str(), "-o", "comm="]) + .output() + .unwrap(); + let path = String::from_utf8(output.stdout).unwrap(); + PathBuf::from(path.trim()) + } + macro_rules! chat_request { ($message:expr, None, None $(,)?) => { ChatStreamRequest { @@ -1185,7 +1201,7 @@ mod tests { use std::io::Read; use std::time::{Duration, Instant}; - let mut child = Command::new(std::env::current_exe().unwrap()) + let mut child = Command::new(current_test_binary()) .arg("stdin_probe_parent_child") .arg("--ignored") .arg("--nocapture") @@ -1231,7 +1247,7 @@ mod tests { return; } - let fake_bin = std::env::current_exe().unwrap(); + let fake_bin = current_test_binary(); let args = vec![ "stdin_probe_mock_claude_child".to_string(), "--ignored".to_string(), diff --git a/src-tauri/src/codex_cli.rs b/src-tauri/src/codex_cli.rs index 848922ee..ec58f95e 100644 --- a/src-tauri/src/codex_cli.rs +++ b/src-tauri/src/codex_cli.rs @@ -469,6 +469,22 @@ mod tests { use crate::ai_agents::AiAgentPermissionMode; use std::ffi::OsStr; + #[cfg(target_os = "linux")] + fn current_test_binary() -> PathBuf { + std::fs::read_link("/proc/self/exe").unwrap() + } + + #[cfg(target_os = "macos")] + fn current_test_binary() -> PathBuf { + let pid = std::process::id().to_string(); + let output = std::process::Command::new("/bin/ps") + .args(["-p", pid.as_str(), "-o", "comm="]) + .output() + .unwrap(); + let path = String::from_utf8(output.stdout).unwrap(); + PathBuf::from(path.trim()) + } + #[cfg(unix)] fn executable_script(dir: &Path, name: &str, body: &str) -> PathBuf { use std::os::unix::fs::PermissionsExt; @@ -798,7 +814,7 @@ exit 2 use std::io::Read; use std::time::{Duration, Instant}; - let mut child = std::process::Command::new(std::env::current_exe().unwrap()) + let mut child = std::process::Command::new(current_test_binary()) .arg("codex_stdin_probe_parent_child") .arg("--ignored") .arg("--nocapture") diff --git a/src-tauri/src/linux_appimage.rs b/src-tauri/src/linux_appimage.rs index 46f9ff65..b03fda3c 100644 --- a/src-tauri/src/linux_appimage.rs +++ b/src-tauri/src/linux_appimage.rs @@ -309,6 +309,32 @@ fn colrv1_fontconfig_file_path() -> Option { ) } +#[cfg(all(desktop, target_os = "linux"))] +fn launched_appimage_path() -> Result { + if let Some(appimage) = std::env::var_os("APPIMAGE").filter(|value| !value.is_empty()) { + return Ok(std::path::PathBuf::from(appimage)); + } + + std::fs::read_link("/proc/self/exe") + .map_err(|e| format!("failed to resolve /proc/self/exe ({e})")) +} + +#[cfg(all(desktop, target_os = "linux"))] +fn launched_process_args() -> Vec { + use std::os::unix::ffi::OsStringExt; + + let Ok(cmdline) = std::fs::read("/proc/self/cmdline") else { + return Vec::new(); + }; + + cmdline + .split(|byte| *byte == 0) + .filter(|arg| !arg.is_empty()) + .skip(1) + .map(|arg| std::ffi::OsString::from_vec(arg.to_vec())) + .collect() +} + #[cfg(all(desktop, target_os = "linux"))] fn apply_wayland_client_preload() { use std::os::unix::process::CommandExt; @@ -320,18 +346,16 @@ fn apply_wayland_client_preload() { return; }; - let exe = match std::env::current_exe() { + let exe = match launched_appimage_path() { Ok(exe) => exe, Err(e) => { - eprintln!( - "Tolaria AppImage Wayland preload skipped: failed to resolve executable ({e})" - ); + eprintln!("Tolaria AppImage Wayland preload skipped: {e}"); return; } }; let error = std::process::Command::new(exe) - .args(std::env::args_os().skip(1)) + .args(launched_process_args()) .env("LD_PRELOAD", preload_path) .env("TOLARIA_APPIMAGE_WAYLAND_PRELOAD_ATTEMPTED", "1") .exec(); diff --git a/src-tauri/src/mcp.rs b/src-tauri/src/mcp.rs index 51d9cb0f..a2ef3d74 100644 --- a/src-tauri/src/mcp.rs +++ b/src-tauri/src/mcp.rs @@ -224,14 +224,13 @@ fn node_binary_name() -> &'static str { /// Resolve the path to `mcp-server/`. /// /// In dev mode, uses `CARGO_MANIFEST_DIR` (set at compile time). -/// In release mode, navigates from the current executable. +/// In release mode, uses platform resource roots exposed by the launcher. pub(crate) fn mcp_server_dir() -> Result { let dev_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")) .join("..") .join("mcp-server"); - let exe = std::env::current_exe().map_err(|e| format!("Cannot find executable: {e}"))?; - let appdir = std::env::var_os("APPDIR").map(PathBuf::from); - let candidates = mcp_server_dir_candidates(&dev_path, &exe, appdir.as_deref()); + let resource_roots = runtime_resource_roots(); + let candidates = mcp_server_dir_candidates(&dev_path, &resource_roots); if let Some(path) = candidates .iter() .find(|path| mcp_server_dir_has_files(path)) @@ -249,29 +248,13 @@ pub(crate) fn mcp_server_dir() -> Result { )) } -fn mcp_server_dir_candidates( - dev_path: &Path, - exe_path: &Path, - appdir: Option<&Path>, -) -> Vec { +fn mcp_server_dir_candidates(dev_path: &Path, resource_roots: &[PathBuf]) -> Vec { let mut candidates = vec![dev_path.to_path_buf()]; - if let Some(exe_dir) = exe_path.parent() { - candidates.push(exe_dir.join("mcp-server")); - if let Some(bundle_root) = exe_dir.parent() { - candidates.push(bundle_root.join("Resources").join("mcp-server")); - candidates.extend(linux_package_mcp_server_dirs(bundle_root)); - } - } - - if let Some(appdir) = appdir { - candidates.push( - appdir - .join("usr") - .join("lib") - .join("tolaria") - .join("mcp-server"), - ); + for root in resource_roots { + candidates.push(root.join("mcp-server")); + candidates.push(root.join("resources").join("mcp-server")); + candidates.extend(linux_package_mcp_server_dirs(root)); } candidates.extend(linux_package_mcp_server_dirs(Path::new("/usr/local"))); @@ -279,6 +262,28 @@ fn mcp_server_dir_candidates( candidates } +fn runtime_resource_roots() -> Vec { + let mut roots = Vec::new(); + + if let Some(resource_path) = non_empty_env_path("RESOURCEPATH") { + roots.push(resource_path); + } + + if let Some(appdir) = non_empty_env_path("APPDIR") { + roots.push(appdir.join("usr")); + roots.push(appdir.join("usr").join("lib").join("tolaria")); + roots.push(appdir.join("usr").join("lib").join("Tolaria")); + } + + roots +} + +fn non_empty_env_path(key: &str) -> Option { + std::env::var_os(key) + .filter(|value| !value.is_empty()) + .map(PathBuf::from) +} + fn linux_package_mcp_server_dirs(root: &Path) -> Vec { vec![ root.join("Tolaria").join("mcp-server"), @@ -739,32 +744,36 @@ mod tests { } #[test] - fn mcp_server_dir_candidates_prefer_exe_dir_before_macos_resources() { + fn mcp_server_dir_candidates_prefer_resource_root_before_linux_packages() { let dev_path = Path::new("/repo/mcp-server"); - let exe_path = Path::new("/Users/tester/AppData/Local/Tolaria/tolaria.exe"); - let candidates = mcp_server_dir_candidates(dev_path, exe_path, None); + let resource_roots = vec![PathBuf::from( + "/Applications/Tolaria.app/Contents/Resources", + )]; + let candidates = mcp_server_dir_candidates(dev_path, &resource_roots); - let windows_dir = PathBuf::from("/Users/tester/AppData/Local/Tolaria/mcp-server"); - let macos_dir = PathBuf::from("/Users/tester/AppData/Local/Resources/mcp-server"); - let windows_pos = candidates + let resource_dir = PathBuf::from("/Applications/Tolaria.app/Contents/Resources/mcp-server"); + let linux_pos = candidates .iter() - .position(|path| path == &windows_dir) - .unwrap(); - let macos_pos = candidates - .iter() - .position(|path| path == &macos_dir) + .position(|path| path == &PathBuf::from("/usr/local/Tolaria/mcp-server")) .unwrap(); assert_eq!(candidates[0], dev_path); - assert!(windows_pos < macos_pos); + assert_eq!(candidates[1], resource_dir); + assert!(1 < linux_pos); } #[test] fn mcp_server_dir_candidates_include_linux_package_resource_roots() { let dev_path = Path::new("/repo/mcp-server"); - let exe_path = Path::new("/usr/local/tolaria/tolaria"); - let candidates = mcp_server_dir_candidates(dev_path, exe_path, None); + let resource_roots = vec![PathBuf::from("/opt/tolaria")]; + let candidates = mcp_server_dir_candidates(dev_path, &resource_roots); let expected = [ + PathBuf::from("/opt/tolaria/Tolaria/mcp-server"), + PathBuf::from("/opt/tolaria/Tolaria/resources/mcp-server"), + PathBuf::from("/opt/tolaria/lib/Tolaria/mcp-server"), + PathBuf::from("/opt/tolaria/lib/Tolaria/resources/mcp-server"), + PathBuf::from("/opt/tolaria/lib/tolaria/mcp-server"), + PathBuf::from("/opt/tolaria/lib/tolaria/resources/mcp-server"), PathBuf::from("/usr/local/Tolaria/mcp-server"), PathBuf::from("/usr/local/Tolaria/resources/mcp-server"), PathBuf::from("/usr/local/lib/Tolaria/mcp-server"), @@ -783,8 +792,7 @@ mod tests { #[test] fn mcp_server_dir_candidates_include_deb_capitalized_lib_root() { let dev_path = Path::new("/repo/mcp-server"); - let exe_path = Path::new("/usr/bin/tolaria"); - let candidates = mcp_server_dir_candidates(dev_path, exe_path, None); + let candidates = mcp_server_dir_candidates(dev_path, &[]); assert!(candidates.contains(&PathBuf::from("/usr/lib/Tolaria/mcp-server"))); } @@ -792,9 +800,8 @@ mod tests { #[test] fn mcp_server_dir_candidates_include_linux_appimage_resource_root() { let dev_path = Path::new("/repo/mcp-server"); - let exe_path = Path::new("/tmp/.mount_tolaria/usr/bin/tolaria"); - let appdir = Path::new("/tmp/.mount_tolaria"); - let candidates = mcp_server_dir_candidates(dev_path, exe_path, Some(appdir)); + let resource_roots = vec![PathBuf::from("/tmp/.mount_tolaria/usr")]; + let candidates = mcp_server_dir_candidates(dev_path, &resource_roots); assert!(candidates.contains(&PathBuf::from( "/tmp/.mount_tolaria/usr/lib/tolaria/resources/mcp-server" diff --git a/src/components/useNoteListSort.test.tsx b/src/components/useNoteListSort.test.tsx index d7cd78b5..2fc36258 100644 --- a/src/components/useNoteListSort.test.tsx +++ b/src/components/useNoteListSort.test.tsx @@ -41,7 +41,8 @@ function renderWithPrioritySort(entries: VaultEntry[]) { } function expectVisibleNoteOrder(expectedTitles: string[]) { - const items = screen.getAllByText(new RegExp(expectedTitles.join('|'))) + const expectedTitleSet = new Set(expectedTitles) + const items = screen.getAllByText((content) => expectedTitleSet.has(content)) expect(items.map((item) => item.textContent)).toEqual(expectedTitles) } @@ -75,10 +76,7 @@ describe('useNoteListSort (via NoteList)', () => { makeEntry({ path: '/c.md', title: 'Charlie', modifiedAt: 2000 }), ] renderNoteList({ entries, selection: { kind: 'filter', filter: 'all' } }) - const items = screen.getAllByText(/Alpha|Beta|Charlie/) - expect(items[0].textContent).toBe('Beta') - expect(items[1].textContent).toBe('Charlie') - expect(items[2].textContent).toBe('Alpha') + expectVisibleNoteOrder(['Beta', 'Charlie', 'Alpha']) }) it('reads sort from type document for sectionGroup selection', () => { @@ -90,10 +88,7 @@ describe('useNoteListSort (via NoteList)', () => { makeEntry({ path: '/b.md', title: 'Beta', modifiedAt: 2000 }), ] renderNoteList({ entries, selection: { kind: 'sectionGroup', type: 'Note', label: 'Notes' } }) - const items = screen.getAllByText(/Alpha|Beta|Charlie/) - expect(items[0].textContent).toBe('Alpha') - expect(items[1].textContent).toBe('Beta') - expect(items[2].textContent).toBe('Charlie') + expectVisibleNoteOrder(['Alpha', 'Beta', 'Charlie']) }) it('shows type title as header for sectionGroup selection', () => {