Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,23 @@ jobs:

- name: Build
run: npm run build

e2e:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7

- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
node-version: 24.19.0
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Install Xvfb
run: sudo apt-get update && sudo apt-get install -y xvfb

- name: Run e2e tests
run: xvfb-run -a npm run test:e2e
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
node_modules/
dist/
coverage/
out-e2e/
.vscode-test/
.DS_Store
*.log
*.vsix
10 changes: 10 additions & 0 deletions .vscode-test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { defineConfig } from '@vscode/test-cli';

export default defineConfig({
files: 'out-e2e/**/*.test.js',
workspaceFolder: 'test/e2e/fixtures/workspace',
mocha: {
ui: 'bdd',
timeout: 20000
}
});
3 changes: 3 additions & 0 deletions .vscodeignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
node_modules/**
scripts/**
test/**
out-e2e/**
.vscode-test/**
extension.ts
extension.ts.map
tsconfig.json
vitest.config.mts
.vscode-test.mjs
codecov.yml
CLAUDE.md
.gitignore
Expand Down
15 changes: 13 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ drives versioning and publishing off Conventional Commit prefixes on `main`.

Every change is expected to clear this bar before it's mergeable:

- **CI clean.** `npm run lint` (`tsc --noEmit`), `npm run test`, and
`npm run build` all pass — see `.github/workflows/ci.yml`.
- **CI clean.** `npm run lint` (`tsc --noEmit`), `npm run test`,
`npm run build`, and `npm run test:e2e` all pass — see
`.github/workflows/ci.yml`.
- **Unit coverage ≥85%, both patch and project.** Codecov enforces this on
every PR (`codecov.yml`: `project` and `patch`, both `target: 85%,
threshold: 1%`), reported from `npm run test:coverage` (vitest + v8,
Expand All @@ -33,6 +34,16 @@ Every change is expected to clear this bar before it's mergeable:
Codecov's patch gate computes, so a real gap shows up before a CI
round-trip instead of after. Write real tests that close gaps for real —
no padding, no vacuous assertions just to move a number.
- **New features carry e2e coverage, not just unit tests.** Unit tests
(vitest, against `test/vscode-mock.ts`) cover logic in isolation;
`test/e2e/*.test.ts` (mocha, via `@vscode/test-cli` + `@vscode/test-electron`)
runs the real, built extension inside an actual VS Code Extension
Development Host — real command registration, real tree view, real
`workspaceState`. Any new user-facing command or tree behavior needs both:
a unit test for the logic and an e2e test exercising it end-to-end through
the real `vscode` API. Run locally with `npm run test:e2e` (builds the
extension, bundles `test/e2e/**` with esbuild, then launches the test
host — needs a display or `xvfb-run` on headless Linux).
- **Security scanning clean.** CodeQL runs on every push/PR
(`.github/workflows/codeql.yml`); `npm audit --audit-level=high` (via
`scripts/wfb_dep_update.sh`) gates dependency updates on high/critical
Expand Down
10 changes: 9 additions & 1 deletion extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,13 @@ export function computeReorderedIds<T extends { id: string; order?: number }>(
const bookmarkFallbackCompare = (a: Bookmark, b: Bookmark) => b.createdAt - a.createdAt;
const folderFallbackCompare = (a: BookmarkFolder, b: BookmarkFolder) => a.name.localeCompare(b.name);

export function activate(context: vscode.ExtensionContext) {
/** The extension's public API, returned from `activate()` — used by e2e tests to inspect state that isn't reachable through the tree view UI alone. */
export interface ExtensionApi {
store: BookmarkStore;
provider: BookmarksTreeProvider;
}

export function activate(context: vscode.ExtensionContext): ExtensionApi {
const store = new BookmarkStore(context);
const provider = new BookmarksTreeProvider(store, context);

Expand Down Expand Up @@ -93,6 +99,8 @@ export function activate(context: vscode.ExtensionContext) {
vscode.commands.registerCommand('workspace-file-bookmarks.setViewModeList', () => provider.setViewMode('list')),
vscode.commands.registerCommand('workspace-file-bookmarks.setViewModeTree', () => provider.setViewMode('tree'))
);

return { store, provider };
}

export function deactivate() {}
Expand Down
Loading