From 7eb1e21adf0c413f5ba2d067ad21bd8da64202ef Mon Sep 17 00:00:00 2001 From: Rachel Dancy Date: Wed, 17 Jun 2026 09:50:11 -0400 Subject: [PATCH 1/9] Updating yml files for GitHub Actions and ability to run tests in unit test folder --- .github/workflows/test-pull-request.yml | 35 +++++++++++++++++++++ .github/workflows/test.yml | 41 +++++++++++++++++++++++++ package.json | 4 ++- src/test/unit/runTest.ts | 32 +++++++++++++++++++ 4 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 src/test/unit/runTest.ts diff --git a/.github/workflows/test-pull-request.yml b/.github/workflows/test-pull-request.yml index cfc8be0..0c2052f 100644 --- a/.github/workflows/test-pull-request.yml +++ b/.github/workflows/test-pull-request.yml @@ -11,6 +11,41 @@ on: permissions: {} jobs: + test-unit: + name: unit-${{ matrix.os }} + runs-on: ${{ matrix.os }} + if: contains(github.event.pull_request.labels.*.name, 'safe to test') + strategy: + fail-fast: false + matrix: + os: [windows-latest, ubuntu-latest, macos-14] + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + ref: "refs/pull/${{ github.event.number }}/merge" + persist-credentials: false + - name: Verify Head + shell: bash + run: | + if [ "$(git ls-remote origin ${{ github.event.number }}/head | awk '{print $1}')" != "${{ github.event.pull_request.head.sha }}" ]; then + echo "HEAD does not match github.event.pull_request.head.sha" + exit 1 + fi + - name: Setup node + uses: actions/setup-node@v4 + - name: npm clean install + run: npm run project-install-clean + - name: Package vsix + run: npm run package + - name: npm install + run: npm run project-install + - name: Run Unit tests + run: npm run test-unit + - name: Run Workspace Browser tests + run: npm run test-wsb + test-smoke: name: smoke-${{ matrix.version }}-${{ matrix.os }} runs-on: ${{ matrix.os }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b9d909f..bea5d81 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -228,3 +228,44 @@ jobs: name: screenshots-macos-${{ matrix.version }} path: ${{ github.workspace }}/.s/screenshots if-no-files-found: ignore + + # UNIT TESTS + test-unit-linux: + name: Unit Tests-linux + needs: build-linux + runs-on: ubuntu-latest + steps: + - *checkout + - *download-linux-build-artifacts + - *setup-node + - *install-dependencies + - &run-unit-tests + name: Run Unit tests + run: npm run test-unit:fast + - &run-wsb-tests + name: Run Workspace Browser tests + run: npm run test-wsb:fast + + test-unit-windows: + name: Unit Tests-windows + needs: build-windows + runs-on: windows-latest + steps: + - *checkout + - *download-windows-build-artifacts + - *setup-node + - *install-dependencies + - *run-unit-tests + - *run-wsb-tests + + test-unit-macos: + name: Unit Tests-macos + needs: build-macos + runs-on: macos-14 + steps: + - *checkout + - *download-macos-build-artifacts + - *setup-node + - *install-dependencies + - *run-unit-tests + - *run-wsb-tests diff --git a/package.json b/package.json index f2db70f..efaf98e 100644 --- a/package.json +++ b/package.json @@ -524,10 +524,12 @@ "test-ui": "npm run test-setup && node ./out/test/ui/runTest.js", "test-smoke:fast": "node ./out/test/smoke/runTest.js", "test-ui:fast": "node ./out/test/ui/runTest.js", + "test-unit": "npm run test-setup && node ./out/test/unit/runTest.js", + "test-unit:fast": "node ./out/test/unit/runTest.js", "test-wsb": "npm run test-setup && node out/test/workspacebrowser/runTest.js", "test-wsb:fast": "node out/test/workspacebrowser/runTest.js", "test": "npm run test-setup && npm run test:fast", - "test:fast": "npm run test-smoke:fast && npm run test-ui:fast && npm run test-wsb:fast", + "test:fast": "npm run test-smoke:fast && npm run test-ui:fast && npm run test-unit:fast && npm run test-wsb:fast", "project-install": "node ./build/projectInstall.js", "project-install-clean": "node ./build/projectInstall.js --clean", "package": "vsce package" diff --git a/src/test/unit/runTest.ts b/src/test/unit/runTest.ts new file mode 100644 index 0000000..b200210 --- /dev/null +++ b/src/test/unit/runTest.ts @@ -0,0 +1,32 @@ +// Copyright 2026 The MathWorks, Inc. + +import { registerMockVscode } from './mock-vscode' +import * as path from 'path' +import * as Mocha from 'mocha' +import * as glob from 'glob' + + +// Register mock before any test imports that depend on vscode +registerMockVscode() + +async function runTests (): Promise { + const mocha = new Mocha({ + ui: 'tdd', + reporter: 'spec' + }) + + const testRoot = path.resolve(__dirname, '**', '*.test.js').split(path.sep).join('/') + const testFiles = glob.sync(testRoot) + testFiles.forEach((file: string) => mocha.addFile(file)) + + return await new Promise((resolve, reject) => { + mocha.run((failures: number) => { + failures > 0 ? reject(new Error(`${failures} tests failed`)) : resolve() + }) + }) +} + +runTests().catch((err: unknown) => { + console.error(err) + process.exit(1) +}) From 704c53fb2326ba8162205b3a73cc8fa90f15caec Mon Sep 17 00:00:00 2001 From: Rachel Dancy Date: Wed, 17 Jun 2026 10:05:12 -0400 Subject: [PATCH 2/9] Fix linting in runTest --- src/test/unit/runTest.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/unit/runTest.ts b/src/test/unit/runTest.ts index b200210..b1352f3 100644 --- a/src/test/unit/runTest.ts +++ b/src/test/unit/runTest.ts @@ -5,7 +5,6 @@ import * as path from 'path' import * as Mocha from 'mocha' import * as glob from 'glob' - // Register mock before any test imports that depend on vscode registerMockVscode() From 56f2b4751cbf2592808d2754f66deced50a10b3a Mon Sep 17 00:00:00 2001 From: Rachel Dancy Date: Wed, 17 Jun 2026 12:20:17 -0400 Subject: [PATCH 3/9] Use import() instead of require() for workspacebrowser tests --- src/test/workspacebrowser/runTest.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/test/workspacebrowser/runTest.ts b/src/test/workspacebrowser/runTest.ts index ee930a1..1b04792 100644 --- a/src/test/workspacebrowser/runTest.ts +++ b/src/test/workspacebrowser/runTest.ts @@ -88,6 +88,22 @@ if (typeof (global as unknown as Record).CSS === 'undefined') { // ── Run Mocha ─────────────────────────────────────────────────── async function runTests (): Promise { + // chai v5 is ESM-only — pre-load via dynamic import and inject into + // the require cache so compiled CommonJS test files can require() it. + const chaiModule = await import('chai') + const chaiPath = require.resolve('chai') + require.cache[chaiPath] = { + id: chaiPath, + filename: chaiPath, + loaded: true, + exports: chaiModule, + children: [], + paths: [], + path: path.dirname(chaiPath), + isPreloading: false, + require + } as unknown as NodeModule + const mocha = new Mocha({ ui: 'tdd', reporter: 'spec' From 67ad4541e0eff0109ebb3016624d2ee41cf7e746 Mon Sep 17 00:00:00 2001 From: Rachel Dancy Date: Wed, 17 Jun 2026 13:23:02 -0400 Subject: [PATCH 4/9] Prevent TypeScript from compiling import() to require() --- src/test/workspacebrowser/runTest.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/workspacebrowser/runTest.ts b/src/test/workspacebrowser/runTest.ts index 1b04792..75fd380 100644 --- a/src/test/workspacebrowser/runTest.ts +++ b/src/test/workspacebrowser/runTest.ts @@ -90,7 +90,9 @@ if (typeof (global as unknown as Record).CSS === 'undefined') { async function runTests (): Promise { // chai v5 is ESM-only — pre-load via dynamic import and inject into // the require cache so compiled CommonJS test files can require() it. - const chaiModule = await import('chai') + // new Function prevents TypeScript from compiling import() to require(). + const dynamicImport = new Function('specifier', 'return import(specifier)') as (s: string) => Promise + const chaiModule = await dynamicImport('chai') const chaiPath = require.resolve('chai') require.cache[chaiPath] = { id: chaiPath, From 836cf7a53d9752203b71f31b5e459ca5d0b05be9 Mon Sep 17 00:00:00 2001 From: Rachel Dancy Date: Wed, 17 Jun 2026 13:40:46 -0400 Subject: [PATCH 5/9] Try updating Node.js --- .github/workflows/test.yml | 2 +- src/test/workspacebrowser/runTest.ts | 18 ------------------ 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index bea5d81..2a44379 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,7 +19,7 @@ jobs: name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 18.x + node-version: 22.x - &install-dependencies name: Install dependencies run: npm run project-install-clean diff --git a/src/test/workspacebrowser/runTest.ts b/src/test/workspacebrowser/runTest.ts index 75fd380..ee930a1 100644 --- a/src/test/workspacebrowser/runTest.ts +++ b/src/test/workspacebrowser/runTest.ts @@ -88,24 +88,6 @@ if (typeof (global as unknown as Record).CSS === 'undefined') { // ── Run Mocha ─────────────────────────────────────────────────── async function runTests (): Promise { - // chai v5 is ESM-only — pre-load via dynamic import and inject into - // the require cache so compiled CommonJS test files can require() it. - // new Function prevents TypeScript from compiling import() to require(). - const dynamicImport = new Function('specifier', 'return import(specifier)') as (s: string) => Promise - const chaiModule = await dynamicImport('chai') - const chaiPath = require.resolve('chai') - require.cache[chaiPath] = { - id: chaiPath, - filename: chaiPath, - loaded: true, - exports: chaiModule, - children: [], - paths: [], - path: path.dirname(chaiPath), - isPreloading: false, - require - } as unknown as NodeModule - const mocha = new Mocha({ ui: 'tdd', reporter: 'spec' From fd19d6b0397cc527af76415ebdeb491cc381eb70 Mon Sep 17 00:00:00 2001 From: Rachel Dancy Date: Wed, 24 Jun 2026 15:57:16 -0400 Subject: [PATCH 6/9] Update test-pull-request after pulling in new changes --- .github/workflows/test-pull-request.yml | 45 +++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/.github/workflows/test-pull-request.yml b/.github/workflows/test-pull-request.yml index 9ff20b2..c6eff0a 100644 --- a/.github/workflows/test-pull-request.yml +++ b/.github/workflows/test-pull-request.yml @@ -7,6 +7,7 @@ on: # Triggers the workflow on pull requests that contain the label 'safe to test' pull_request_target: types: [ labeled ] + workflow_dispatch: permissions: {} @@ -254,3 +255,47 @@ jobs: name: screenshots-macos-${{ matrix.version }} path: ${{ github.workspace }}/.s/screenshots if-no-files-found: ignore + + # UNIT TESTS + test-unit-linux: + name: Unit Tests-linux + needs: build-linux + runs-on: ubuntu-latest + steps: + - *checkout + - *verify-head + - *download-linux-build-artifacts + - *setup-node + - *install-dependencies + - &run-unit-tests + name: Run Unit tests + run: npm run test-unit:fast + - &run-wsb-tests + name: Run Workspace Browser tests + run: npm run test-wsb:fast + + test-unit-windows: + name: Unit Tests-windows + needs: build-windows + runs-on: windows-latest + steps: + - *checkout + - *verify-head + - *download-windows-build-artifacts + - *setup-node + - *install-dependencies + - *run-unit-tests + - *run-wsb-tests + + test-unit-macos: + name: Unit Tests-macos + needs: build-macos + runs-on: macos-14 + steps: + - *checkout + - *verify-head + - *download-macos-build-artifacts + - *setup-node + - *install-dependencies + - *run-unit-tests + - *run-wsb-tests From 628d51bb83f5e0803dbf1d1c10ba80e359cd871c Mon Sep 17 00:00:00 2001 From: Rachel Dancy Date: Wed, 24 Jun 2026 15:59:46 -0400 Subject: [PATCH 7/9] temporary change for workflow to use this yml file --- .github/workflows/test-pull-request.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/test-pull-request.yml b/.github/workflows/test-pull-request.yml index c6eff0a..0676e1c 100644 --- a/.github/workflows/test-pull-request.yml +++ b/.github/workflows/test-pull-request.yml @@ -5,9 +5,8 @@ name: test-pull-request # Controls when the workflow will run on: # Triggers the workflow on pull requests that contain the label 'safe to test' - pull_request_target: + pull_request: types: [ labeled ] - workflow_dispatch: permissions: {} From f88e8decfb31d41adf6728558b118f5383905aca Mon Sep 17 00:00:00 2001 From: Rachel Dancy Date: Wed, 24 Jun 2026 16:27:11 -0400 Subject: [PATCH 8/9] Update node-version --- .github/workflows/test-pull-request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-pull-request.yml b/.github/workflows/test-pull-request.yml index 0676e1c..7553709 100644 --- a/.github/workflows/test-pull-request.yml +++ b/.github/workflows/test-pull-request.yml @@ -35,7 +35,7 @@ jobs: name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 18.x + node-version: 22.x - &install-dependencies name: Install dependencies run: npm run project-install-clean From e15089a355dc470efa1a60eb525924e6fe93977e Mon Sep 17 00:00:00 2001 From: Rachel Dancy Date: Thu, 25 Jun 2026 09:23:21 -0400 Subject: [PATCH 9/9] Revert back to pull_request_target --- .github/workflows/test-pull-request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-pull-request.yml b/.github/workflows/test-pull-request.yml index 7553709..0865f30 100644 --- a/.github/workflows/test-pull-request.yml +++ b/.github/workflows/test-pull-request.yml @@ -5,7 +5,7 @@ name: test-pull-request # Controls when the workflow will run on: # Triggers the workflow on pull requests that contain the label 'safe to test' - pull_request: + pull_request_target: types: [ labeled ] permissions: {}