diff --git a/package-lock.json b/package-lock.json index 8d7342153..6f56e046b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,7 +35,6 @@ "oxlint": "1.61.0", "oxlint-tsgolint": "^0.22.1", "patch-package": "^8.0.1", - "picomatch": "4.0.5", "playwright": "^1.56.1", "typescript": "^5.9.3", "ws": "^8.20.0" diff --git a/package.json b/package.json index 1f0a9a6ce..ec45bed38 100644 --- a/package.json +++ b/package.json @@ -127,7 +127,6 @@ "oxlint": "1.61.0", "oxlint-tsgolint": "^0.22.1", "patch-package": "^8.0.1", - "picomatch": "4.0.5", "playwright": "^1.56.1", "typescript": "^5.9.3", "ws": "^8.20.0" diff --git a/packages/desktop/package.json b/packages/desktop/package.json index 42a5ce0c1..ad86d6c5a 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -23,7 +23,7 @@ "test:e2e:renderer": "cross-env E2E_DESKTOP_RUNTIME=1 playwright test --config=playwright.config.ts --project=desktop", "test:e2e:browser-tabs": "npm run build:main && node ./e2e/browser-tabs.e2e.mjs", "verify:electron-cdp": "node ./scripts/verify-electron-cdp.mjs", - "test": "vitest run", + "test": "vitest run --exclude \"e2e/**\"", "typecheck": "tsgo --noEmit -p tsconfig.json" }, "dependencies": { diff --git a/scripts/ci-workflow.test.mjs b/scripts/ci-workflow.test.mjs index 99ca30f15..ea6714460 100644 --- a/scripts/ci-workflow.test.mjs +++ b/scripts/ci-workflow.test.mjs @@ -1,8 +1,7 @@ import assert from "node:assert/strict"; import { readFileSync, readdirSync } from "node:fs"; -import { relative as relativePath } from "node:path"; +import { matchesGlob, relative as relativePath } from "node:path"; import test from "node:test"; -import picomatch from "picomatch"; const repoRoot = new URL("../", import.meta.url); const ciWorkflowPath = new URL(".github/workflows/ci.yml", repoRoot); @@ -10,6 +9,7 @@ const dockerWorkflowPath = new URL(".github/workflows/docker.yml", repoRoot); const nixWorkflowPath = new URL(".github/workflows/nix.yml", repoRoot); const filtersPath = new URL(".github/ci-paths.yml", repoRoot); const serverTsconfigPath = new URL("packages/server/tsconfig.server.json", repoRoot); +const desktopPackagePath = new URL("packages/desktop/package.json", repoRoot); const gatedCiJobs = new Map([ ["format", { name: "format", contract: "format" }], @@ -65,7 +65,17 @@ function loadFilters(path) { } function matchesFilter(filters, filterName, changedPath) { - return filters[filterName].some((pattern) => picomatch(pattern, { dot: true })(changedPath)); + const visiblePath = exposeDotSegments(changedPath); + return filters[filterName].some((pattern) => + matchesGlob(visiblePath, exposeDotSegments(pattern)), + ); +} + +// dorny/paths-filter uses picomatch with `dot: true`. Node's dependency-free +// matcher hides dot-prefixed path segments by default, so make those segments +// ordinary in both operands before matching. +function exposeDotSegments(value) { + return value.replace(/(^|\/)\./g, "$1__dot__"); } function filesUnder(relativeDirectory, predicate) { @@ -245,6 +255,9 @@ test("browser and desktop tests have exclusive, directory-owned suites", () => { assert.ok(desktopSpecs.every((path) => path.startsWith("packages/desktop/e2e/"))); assert.ok(electronModules.every((path) => path.startsWith("packages/app/src/desktop/"))); + const desktopPackage = JSON.parse(readFileSync(desktopPackagePath, "utf8")); + assert.match(desktopPackage.scripts.test, /--exclude ["']e2e\/\*\*["']/); + for (const path of browserSpecs) { assert.equal(matchesFilter(filters, "browser", path), true, path); assert.equal(matchesFilter(filters, "desktop", path), false, path);