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
140 changes: 140 additions & 0 deletions .github/workflows/phase0-qa.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
name: Phase 0 QA

on:
push:
branches: [main]
pull_request:
branches:
- main
- 'release/*'
workflow_dispatch:

permissions:
contents: read

concurrency:
group: phase0-qa-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: true

jobs:
phase0-unit:
name: Phase 0 unit regression
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
with:
lfs: false

- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version-file: .nvmrc

- name: Install dependencies
run: npm ci --ignore-scripts
env:
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Install build dependencies
run: npm ci
working-directory: build

- name: Transpile source
run: npm run transpile-client

- name: Run Phase 0 QA unit tests
run: npm run test-phase0-qa

phase0-cdp-macos:
name: Phase 0 CDP smoke (macOS)
if: github.event_name == 'workflow_dispatch'
runs-on: macos-14
steps:
- name: Checkout
uses: actions/checkout@v6
with:
lfs: false

- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version-file: .nvmrc

- name: Install dependencies
run: npm ci
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Install build dependencies
run: npm ci
working-directory: build

- name: Build React UI
run: npm run buildreact

- name: Build Electron dev app
run: node build/lib/preLaunch.ts

- name: Run Phase 0 QA (unit + CDP)
run: test/cortexide-smoke/run-phase0-qa.sh --cdp
env:
CX_CDP_PORT: 9222
CX_WS: /tmp/cx-phase0-qa-ws
CX_PROFILE: /tmp/cx-phase0-qa-profile

- name: Upload CDP screenshot on failure
if: failure()
uses: actions/upload-artifact@v7
with:
name: phase0-qa-screenshot
path: /tmp/cortexide-phase0-qa.png
if-no-files-found: ignore

phase0-cdp-windows:
name: Phase 0 CDP smoke (Windows — menubar dropdown gate)
if: github.event_name == 'workflow_dispatch'
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v6
with:
lfs: false

- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version-file: .nvmrc

- name: Install dependencies
run: npm ci
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Install build dependencies
run: npm ci
working-directory: build

- name: Build React UI
run: npm run buildreact

- name: Build Electron dev app
run: node build/lib/preLaunch.ts

- name: Run Phase 0 QA (unit + CDP)
shell: bash
run: test/cortexide-smoke/run-phase0-qa.sh --cdp
env:
CX_CDP_PORT: 9222
CX_WS: C:/Temp/cx-phase0-qa-ws
CX_PROFILE: C:/Temp/cx-phase0-qa-profile

- name: Upload CDP screenshot on failure
if: failure()
uses: actions/upload-artifact@v7
with:
name: phase0-qa-windows-screenshot
path: ${{ runner.temp }}/cortexide-phase0-qa.png
if-no-files-found: ignore
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"test-browser": "npx playwright install && node test/unit/browser/index.js",
"test-browser-no-install": "node test/unit/browser/index.js",
"test-node": "mocha test/unit/node/index.js --delay --ui=tdd --timeout=5000 --exit",
"test-phase0-qa": "npm run test-node -- --runGlob \"**/cortexide/test/common/{providerSettingsValidation,onboardingHelpers,attachFileToChat,chatThreadStorageReviver,providerToolFormat,phase0ClaimVerification,modelCapabilities,menubarStackingFix}.test.js\"",
"test-extension": "vscode-test",
"test-build-scripts": "cd build && npm run test",
"check-cyclic-dependencies": "node build/lib/checkCyclicDependencies.ts out",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/

import * as assert from 'assert';
import { readFileSync } from 'fs';
import { dirname, join } from 'path';
import { fileURLToPath } from 'url';
import { suite, test } from 'mocha';

/**
* CSS contract for issues #8 / #68 — menubar dropdowns must not be clipped on Windows/Linux.
* Runs in node (no Electron) so CI can gate Windows release behaviour without a Windows runner.
*/
const cssPath = join(dirname(fileURLToPath(import.meta.url)), '../../browser/media/cortexide.css');
const css = readFileSync(cssPath, 'utf8');

const hasRule = (pattern: RegExp) => pattern.test(css);

suite('menubarStackingFix (#8 / #68 — Windows/Linux dropdown)', () => {

test('titlebar backdrop-filter override exists (prevents stacking-context clip)', () => {
assert.ok(
hasRule(/\.monaco-workbench\s+\.part\.titlebar\s*\{[^}]*backdrop-filter:\s*none/s),
'expected .monaco-workbench .part.titlebar { backdrop-filter: none; }',
);
assert.ok(
hasRule(/\.monaco-workbench\s+\.part\.titlebar\s*\{[^}]*-webkit-backdrop-filter:\s*none/s),
'expected webkit backdrop-filter none on titlebar',
);
});

test('menubar menu container z-index is raised above title bar chrome', () => {
assert.ok(
hasRule(/\.monaco-workbench\s+\.monaco-menu-container[^}]*z-index:\s*2500/s),
'expected .monaco-menu-container { z-index: 2500; }',
);
});

test('status bar keeps blur (titlebar override must not remove status bar styling)', () => {
assert.ok(
hasRule(/\.monaco-workbench\s+\.part\.statusbar[^}]*backdrop-filter:\s*blur/s),
'status bar should retain backdrop blur',
);
});

test('titlebar blur rule is scoped separately from the none override', () => {
// Both rules exist: shared blur on titlebar+statusbar, then titlebar-only reset.
const titlebarNoneIdx = css.indexOf('.monaco-workbench .part.titlebar {\n\tbackdrop-filter: none');
const sharedBlurIdx = css.indexOf('.monaco-workbench .part.titlebar,\n.monaco-workbench .part.statusbar');
assert.ok(sharedBlurIdx >= 0, 'shared titlebar/statusbar blur block missing');
assert.ok(titlebarNoneIdx >= 0, 'titlebar backdrop-filter:none block missing');
assert.ok(titlebarNoneIdx > sharedBlurIdx, 'titlebar none override must come AFTER shared blur rule');
});
});
20 changes: 20 additions & 0 deletions test/cortexide-smoke/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ Chrome DevTools Protocol (CDP). Used to confirm the editor actually boots and it
otherwise makes Electron run as plain Node. Uses throwaway user-data/extensions dirs.
- `cdp-smoke.mjs` — connects with Playwright `connectOverCDP`, finds the workbench page
(`workbench-dev.html` in dev builds), and asserts core + CortexIDE surfaces exist.
- `phase0-qa-verify.mjs` — CDP regression for merged Phase 0 fixes (PR #69): provider
validation, local tool format, attach-file commands, menubar stacking, theme scoping.
- `run-phase0-qa.sh` — runs `npm run test-phase0-qa` (unit) and optionally `--cdp` live verify.

## Usage
```bash
Expand All @@ -24,6 +27,23 @@ node test/cortexide-smoke/cdp-smoke.mjs --port 9222
```
Exit code 0 = all checks passed. A screenshot is written to the OS temp dir.

### Phase 0 QA (PR #69 regression)

```bash
# Fast — unit tests only (CI runs this on every PR):
npm run test-phase0-qa

# Full — unit tests + live CDP verify (needs a built dev app):
node build/lib/preLaunch.ts
npm run buildreact # if you touched React UI
test/cortexide-smoke/run-phase0-qa.sh --cdp
```

CI: `.github/workflows/phase0-qa.yml` runs unit tests on every PR/push to `main`.
Trigger CDP jobs manually via **Actions → Phase 0 QA → Run workflow**:
- **Windows** job clicks the in-window menubar and verifies the dropdown is visible (release gate for #8).
- **macOS** job runs module + CSS checks (native menu bar — no live click).

## Why CDP and not Playwright `_electron.launch()`
VS Code / CortexIDE manages its own (re)launching, so Playwright's stdout-handshake
Electron launcher fails with "Process failed to launch!". Launching the app ourselves
Expand Down
11 changes: 10 additions & 1 deletion test/cortexide-smoke/launch-dev.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ WS="${2:-/tmp/cx-ws-cdp}"

APP="$ROOT/.build/electron/CortexIDE.app/Contents/MacOS/CortexIDE"
if [[ ! -x "$APP" ]]; then
# Linux / other: fall back to applicationName binary.
APP="$ROOT/.build/electron/cortexide"
fi
if [[ ! -x "$APP" ]] && [[ -f "$ROOT/.build/electron/cortexide.exe" ]]; then
APP="$ROOT/.build/electron/cortexide.exe"
fi
if [[ ! -x "$APP" ]]; then
echo "ERROR: built app not found. Run: node build/lib/preLaunch.ts" >&2
exit 1
Expand All @@ -43,6 +45,13 @@ UDD="$PROFILE/user-data"
EXT="$PROFILE/extensions"
mkdir -p "$UDD" "$EXT"

# Ensure in-window menubar on Windows/Linux (required for #8 dropdown QA).
SETTINGS="$UDD/User/settings.json"
if [[ ! -f "$SETTINGS" ]]; then
mkdir -p "$(dirname "$SETTINGS")"
printf '%s\n' '{"window.menuBarVisibility":"classic","window.titleBarStyle":"custom"}' > "$SETTINGS"
fi

echo "Launching CortexIDE (port $PORT, ws $WS, profile $PROFILE)"
# --password-store=basic: the ad-hoc-signed dev build (Identifier "Electron", no Team ID) can't be
# stably attributed to its macOS Keychain item, so safeStorage prompts for the login password on
Expand Down
Loading
Loading