diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4e97c65e44..03ce25356b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -54,6 +54,9 @@ importers: '@types/vscode': specifier: 1.96.0 version: 1.96.0 + '@vitest/ui': + specifier: ^3.2.3 + version: 3.2.3(vitest@3.2.3) '@vscode/test-cli': specifier: ^0.0.10 version: 0.0.10 @@ -81,6 +84,9 @@ importers: typescript-eslint: specifier: ^8.34.0 version: 8.34.0(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3) + vitest: + specifier: ^3.2.3 + version: 3.2.3(@types/debug@4.1.12)(@types/node@20.11.25)(@vitest/ui@3.2.3)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.19.4)(yaml@2.8.0) vscode/react: dependencies: @@ -171,7 +177,7 @@ importers: version: 6.3.5(@types/node@22.15.30)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.19.4)(yaml@2.8.0) vitest: specifier: ^3.2.3 - version: 3.2.3(@types/debug@4.1.12)(@types/node@22.15.30)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.19.4)(yaml@2.8.0) + version: 3.2.3(@types/debug@4.1.12)(@types/node@22.15.30)(@vitest/ui@3.2.3)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.19.4)(yaml@2.8.0) web-vitals: specifier: ^4.2.4 version: 4.2.4 @@ -346,7 +352,7 @@ importers: version: 3.5.2(vite@6.3.5(@types/node@22.15.30)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.19.4)(yaml@2.8.0)) vitest: specifier: ^3.2.3 - version: 3.2.3(@types/debug@4.1.12)(@types/node@22.15.30)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.19.4)(yaml@2.8.0) + version: 3.2.3(@types/debug@4.1.12)(@types/node@22.15.30)(@vitest/ui@3.2.3)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.19.4)(yaml@2.8.0) optionalDependencies: '@swc/core-linux-x64-gnu': specifier: ^1.11.31 @@ -976,6 +982,9 @@ packages: engines: {node: '>=18'} hasBin: true + '@polka/url@1.0.0-next.29': + resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + '@radix-ui/number@1.1.1': resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==} @@ -2273,6 +2282,11 @@ packages: '@vitest/spy@3.2.3': resolution: {integrity: sha512-JHu9Wl+7bf6FEejTCREy+DmgWe+rQKbK+y32C/k5f4TBIAlijhJbRBIRIOCEpVevgRsCQR2iHRUH2/qKVM/plw==} + '@vitest/ui@3.2.3': + resolution: {integrity: sha512-9aR2tY/WT7GRHGEH/9sSIipJqeA21Eh3C6xmiOVmfyBCFmezUSUFLalpaSmRHlRzWCKQU10yz3AHhKuYcdnZGQ==} + peerDependencies: + vitest: 3.2.3 + '@vitest/utils@3.2.3': resolution: {integrity: sha512-4zFBCU5Pf+4Z6v+rwnZ1HU1yzOKKvDkMXZrymE2PBlbjKJRlrOxbvpfPSvJTGRIwGoahaOGvp+kbCoxifhzJ1Q==} @@ -3246,6 +3260,9 @@ packages: picomatch: optional: true + fflate@0.8.2: + resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} + file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} @@ -4252,6 +4269,10 @@ packages: engines: {node: '>= 14.0.0'} hasBin: true + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} + engines: {node: '>=10'} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -4965,6 +4986,10 @@ packages: simple-get@4.0.1: resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} + sirv@3.0.1: + resolution: {integrity: sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==} + engines: {node: '>=18'} + slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} @@ -5265,6 +5290,10 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + tough-cookie@5.1.2: resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} engines: {node: '>=16'} @@ -6578,6 +6607,8 @@ snapshots: dependencies: playwright: 1.52.0 + '@polka/url@1.0.0-next.29': {} + '@radix-ui/number@1.1.1': {} '@radix-ui/primitive@1.1.2': {} @@ -8040,6 +8071,14 @@ snapshots: chai: 5.2.0 tinyrainbow: 2.0.0 + '@vitest/mocker@3.2.3(vite@6.3.5(@types/node@20.11.25)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.19.4)(yaml@2.8.0))': + dependencies: + '@vitest/spy': 3.2.3 + estree-walker: 3.0.3 + magic-string: 0.30.17 + optionalDependencies: + vite: 6.3.5(@types/node@20.11.25)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.19.4)(yaml@2.8.0) + '@vitest/mocker@3.2.3(vite@6.3.5(@types/node@22.15.30)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.19.4)(yaml@2.8.0))': dependencies: '@vitest/spy': 3.2.3 @@ -8068,6 +8107,17 @@ snapshots: dependencies: tinyspy: 4.0.3 + '@vitest/ui@3.2.3(vitest@3.2.3)': + dependencies: + '@vitest/utils': 3.2.3 + fflate: 0.8.2 + flatted: 3.3.3 + pathe: 2.0.3 + sirv: 3.0.1 + tinyglobby: 0.2.14 + tinyrainbow: 2.0.0 + vitest: 3.2.3(@types/debug@4.1.12)(@types/node@20.11.25)(@vitest/ui@3.2.3)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.19.4)(yaml@2.8.0) + '@vitest/utils@3.2.3': dependencies: '@vitest/pretty-format': 3.2.3 @@ -9195,6 +9245,8 @@ snapshots: optionalDependencies: picomatch: 4.0.2 + fflate@0.8.2: {} + file-entry-cache@8.0.0: dependencies: flat-cache: 4.0.1 @@ -10322,6 +10374,8 @@ snapshots: yargs-parser: 20.2.9 yargs-unparser: 2.0.0 + mrmime@2.0.1: {} + ms@2.1.3: {} mute-stream@0.0.8: {} @@ -11178,6 +11232,12 @@ snapshots: simple-concat: 1.0.1 optional: true + sirv@3.0.1: + dependencies: + '@polka/url': 1.0.0-next.29 + mrmime: 2.0.1 + totalist: 3.0.1 + slash@3.0.0: {} slash@5.1.0: {} @@ -11537,6 +11597,8 @@ snapshots: dependencies: is-number: 7.0.0 + totalist@3.0.1: {} + tough-cookie@5.1.2: dependencies: tldts: 6.1.86 @@ -11789,6 +11851,27 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.2 + vite-node@3.2.3(@types/node@20.11.25)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.19.4)(yaml@2.8.0): + dependencies: + cac: 6.7.14 + debug: 4.4.1(supports-color@8.1.1) + es-module-lexer: 1.7.0 + pathe: 2.0.3 + vite: 6.3.5(@types/node@20.11.25)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.19.4)(yaml@2.8.0) + transitivePeerDependencies: + - '@types/node' + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + vite-node@3.2.3(@types/node@22.15.30)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.19.4)(yaml@2.8.0): dependencies: cac: 6.7.14 @@ -11814,6 +11897,23 @@ snapshots: dependencies: vite: 6.3.5(@types/node@22.15.30)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.19.4)(yaml@2.8.0) + vite@6.3.5(@types/node@20.11.25)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.19.4)(yaml@2.8.0): + dependencies: + esbuild: 0.25.5 + fdir: 6.4.5(picomatch@4.0.2) + picomatch: 4.0.2 + postcss: 8.5.4 + rollup: 4.41.1 + tinyglobby: 0.2.14 + optionalDependencies: + '@types/node': 20.11.25 + fsevents: 2.3.3 + jiti: 2.4.2 + lightningcss: 1.30.1 + terser: 5.42.0 + tsx: 4.19.4 + yaml: 2.8.0 + vite@6.3.5(@types/node@22.15.30)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.19.4)(yaml@2.8.0): dependencies: esbuild: 0.25.5 @@ -11831,7 +11931,51 @@ snapshots: tsx: 4.19.4 yaml: 2.8.0 - vitest@3.2.3(@types/debug@4.1.12)(@types/node@22.15.30)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.19.4)(yaml@2.8.0): + vitest@3.2.3(@types/debug@4.1.12)(@types/node@20.11.25)(@vitest/ui@3.2.3)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.19.4)(yaml@2.8.0): + dependencies: + '@types/chai': 5.2.2 + '@vitest/expect': 3.2.3 + '@vitest/mocker': 3.2.3(vite@6.3.5(@types/node@20.11.25)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.19.4)(yaml@2.8.0)) + '@vitest/pretty-format': 3.2.3 + '@vitest/runner': 3.2.3 + '@vitest/snapshot': 3.2.3 + '@vitest/spy': 3.2.3 + '@vitest/utils': 3.2.3 + chai: 5.2.0 + debug: 4.4.1(supports-color@8.1.1) + expect-type: 1.2.1 + magic-string: 0.30.17 + pathe: 2.0.3 + picomatch: 4.0.2 + std-env: 3.9.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.14 + tinypool: 1.1.0 + tinyrainbow: 2.0.0 + vite: 6.3.5(@types/node@20.11.25)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.19.4)(yaml@2.8.0) + vite-node: 3.2.3(@types/node@20.11.25)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.19.4)(yaml@2.8.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/debug': 4.1.12 + '@types/node': 20.11.25 + '@vitest/ui': 3.2.3(vitest@3.2.3) + jsdom: 26.1.0 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + vitest@3.2.3(@types/debug@4.1.12)(@types/node@22.15.30)(@vitest/ui@3.2.3)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.19.4)(yaml@2.8.0): dependencies: '@types/chai': 5.2.2 '@vitest/expect': 3.2.3 @@ -11859,6 +12003,7 @@ snapshots: optionalDependencies: '@types/debug': 4.1.12 '@types/node': 22.15.30 + '@vitest/ui': 3.2.3(vitest@3.2.3) jsdom: 26.1.0 transitivePeerDependencies: - jiti diff --git a/vscode/extension/.vscodeignore b/vscode/extension/.vscodeignore index 0ae5ea9583..e50f31046d 100644 --- a/vscode/extension/.vscodeignore +++ b/vscode/extension/.vscodeignore @@ -16,4 +16,12 @@ assets/logo.svg esbuild.js openapi.json test-results/** -E2E_TESTING.md \ No newline at end of file +E2E_TESTING.md +**/*.test.ts +**/*.test.js +.mocharc.json +tsconfig.test.json +tsconfig.build.json +src/test/** +tests/** +.claude \ No newline at end of file diff --git a/vscode/extension/esbuild.js b/vscode/extension/esbuild.js index 40a11421e2..f24f83a687 100644 --- a/vscode/extension/esbuild.js +++ b/vscode/extension/esbuild.js @@ -18,6 +18,14 @@ async function main() { plugins: [ /* add to the end of plugins array */ esbuildProblemMatcherPlugin, + { + name: 'exclude-tests', + setup(build) { + build.onResolve({ filter: /\.test\.ts$/ }, args => { + return { external: true } + }) + }, + }, ], }) if (watch) { diff --git a/vscode/extension/eslint.config.mjs b/vscode/extension/eslint.config.mjs index be80cd9ab1..6d939bdc51 100644 --- a/vscode/extension/eslint.config.mjs +++ b/vscode/extension/eslint.config.mjs @@ -26,4 +26,30 @@ export default tseslint.config( '@typescript-eslint/no-unsafe-member-access': 'off', }, }, + { + files: ['**/*.ts'], + ignores: ['**/*.test.ts'], + rules: { + 'no-restricted-imports': [ + 'error', + { + patterns: ['*.test', '*.test.ts', '**/test/**'], + }, + ], + }, + }, + { + files: ['**/*.test.ts'], + languageOptions: { + parserOptions: { + projectService: false, + project: './tsconfig.test.json', + tsconfigRootDir: import.meta.dirname, + }, + }, + rules: { + '@typescript-eslint/no-unsafe-call': 'off', + '@typescript-eslint/no-unsafe-member-access': 'off', + }, + }, ) diff --git a/vscode/extension/package.json b/vscode/extension/package.json index 8e36c459c1..254ee8ef16 100644 --- a/vscode/extension/package.json +++ b/vscode/extension/package.json @@ -65,33 +65,33 @@ "commands": [ { "command": "sqlmesh.format", - "title": "Format SQLMesh Project", + "title": "SQLMesh: Format Project", "description": "SQLMesh" }, { "command": "sqlmesh.restart", - "title": "Restart SQLMesh Servers", + "title": "SQLMesh: Restart Servers", "description": "SQLMesh" }, { "command": "sqlmesh.signin", - "title": "Sign in to Tobiko Cloud", + "title": "SQLMesh: Sign in to Tobiko Cloud", "description": "SQLMesh" }, { "command": "sqlmesh.signinSpecifyFlow", - "title": "Sign in to Tobiko Cloud (Specify Auth Flow)", + "title": "SQLMesh: Sign in to Tobiko Cloud (Specify Auth Flow)", "description": "SQLMesh" }, { "command": "sqlmesh.signout", - "title": "Sign out from Tobiko Cloud", + "title": "SQLMesh: Sign out from Tobiko Cloud", "description": "SQLMesh" }, { "command": "sqlmesh.renderModel", - "title": "Render Model", - "description": "Render the model in the current editor", + "title": "SQLMesh: Render Model", + "description": "SQLMesh", "icon": "$(open-preview)" } ], @@ -106,15 +106,16 @@ } }, "scripts": { - "ci": "pnpm run lint && pnpm run compile", + "ci": "pnpm run lint && pnpm run compile && pnpm run test:unit", "lint": "eslint src", "lint:fix": "eslint src --fix", + "test:unit": "vitest run", "test:e2e": "playwright test", "test:e2e:ui": "playwright test --ui", "test:e2e:headed": "playwright test --headed", "fetch-vscode": "tsx scripts/fetch-vscode.ts", "compile": "pnpm run check-types && node esbuild.js", - "check-types": "tsc --noEmit", + "check-types": "tsc --noEmit -p ./tsconfig.build.json", "watch": "node esbuild.js --watch", "watch:tsc": "tsc --noEmit --watch --project tsconfig.json", "vscode:package": "vsce package --no-dependencies", @@ -135,6 +136,7 @@ "@types/mocha": "^10.0.10", "@types/node": "20.11.25", "@types/vscode": "1.96.0", + "@vitest/ui": "^3.2.3", "@vscode/test-cli": "^0.0.10", "@vscode/test-electron": "^2.5.2", "@vscode/vsce": "^3.5.0", @@ -143,6 +145,7 @@ "ts-loader": "^9.5.2", "tsx": "^4.19.4", "typescript": "^5.8.3", - "typescript-eslint": "^8.34.0" + "typescript-eslint": "^8.34.0", + "vitest": "^3.2.3" } } diff --git a/vscode/extension/src/commands/commands.test.ts b/vscode/extension/src/commands/commands.test.ts new file mode 100644 index 0000000000..7f531a2ce1 --- /dev/null +++ b/vscode/extension/src/commands/commands.test.ts @@ -0,0 +1,19 @@ +import { assert, describe, it } from 'vitest' +import * as fs from 'fs' +import * as path from 'path' + +describe('Commands', () => { + it('all commands should start with "SQLMesh: " prefix', () => { + const packageJsonPath = path.join(__dirname, '..', '..', 'package.json') + const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')) + + const commands = packageJson.contributes?.commands || [] + + commands.forEach((command: any) => { + assert( + command.title.startsWith('SQLMesh: '), + `Command "${command.command}" title "${command.title}" should start with "SQLMesh: "`, + ) + }) + }) +}) diff --git a/vscode/extension/tsconfig.build.json b/vscode/extension/tsconfig.build.json new file mode 100644 index 0000000000..2ea6c120ab --- /dev/null +++ b/vscode/extension/tsconfig.build.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "exclude": [ + "node_modules", + "../node_modules", + "../../node_modules", + "src/**/*.test.ts", + "tests/**/*", + "scripts/**/*" + ] +} diff --git a/vscode/extension/tsconfig.json b/vscode/extension/tsconfig.json index f6b6d29681..a20a2f08d3 100644 --- a/vscode/extension/tsconfig.json +++ b/vscode/extension/tsconfig.json @@ -16,5 +16,11 @@ } }, "include": ["tests/**/*", "src/**/*", "../bus/src/**/*"], - "exclude": ["node_modules", "../node_modules", "../../node_modules"] + "exclude": [ + "node_modules", + "../node_modules", + "../../node_modules", + "tests/**/*.test.ts", + "src/**/*.test.ts" + ] } diff --git a/vscode/extension/tsconfig.test.json b/vscode/extension/tsconfig.test.json new file mode 100644 index 0000000000..752c0f0952 --- /dev/null +++ b/vscode/extension/tsconfig.test.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "types": ["node"] + }, + "include": ["src/**/*.test.ts", "tests/**/*"], + "exclude": ["node_modules", "../node_modules", "../../node_modules"] +} diff --git a/vscode/extension/vitest.config.ts b/vscode/extension/vitest.config.ts new file mode 100644 index 0000000000..49fbea3be3 --- /dev/null +++ b/vscode/extension/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + globals: true, + include: ['src/**/*.test.ts'], + exclude: ['**/node_modules/**', '**/dist/**', '**/out/**'], + }, +})