diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..ccd0e16 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,33 @@ +name: Publish to VS Code Marketplace + +on: + push: + tags: + - 'v*' # Se déclenche uniquement quand on pousse un tag, ex: git tag v0.1.1 && git push --tags + +jobs: + publish: + name: Publish Extension + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 18.x + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Run Tests + run: xvfb-run -a npm test + + - name: Publish Pre-release (Beta) + uses: liximomo/vsceaction@v1 + with: + args: publish --pre-release + env: + VSCE_PAT: ${{ secrets.VSCE_PAT }} diff --git a/.gitignore b/.gitignore index 08012c4..614af59 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ ccoretrace-sarif-tscancode.json Thumbs.db # test.vscode-test/ +.vscode-test/ diff --git a/src/test/command.test.ts b/src/test/command.test.ts new file mode 100644 index 0000000..c7bc098 --- /dev/null +++ b/src/test/command.test.ts @@ -0,0 +1,30 @@ +import * as assert from 'assert'; +import { parseAndValidateParams } from '../ctrace/CommandBuilder'; + +suite('CommandBuilder Test Suite', () => { + test('Validates safe parameters correctly', () => { + const result = parseAndValidateParams('--entry-points=main --log-level=debug --all'); + assert.deepStrictEqual(result, ['--entry-points=main', '--log-level=debug', '--all']); + }); + + test('Throws on malicious shell injections', () => { + const maliciousPayloads = [ + '--flag && rm -rf /', + '-I path; ls -la', + '--out=$(whoami)', + '--test `cat /etc/passwd`', + '--option | grep root' + ]; + + for (const payload of maliciousPayloads) { + assert.throws(() => { + parseAndValidateParams(payload); + }, /Unsafe CLI/, `Failed to block payload: ${payload}`); + } + }); + + test('Handles empty or whitespace-only params', () => { + assert.deepStrictEqual(parseAndValidateParams(''), []); + assert.deepStrictEqual(parseAndValidateParams(' '), []); + }); +}); diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts index 2077b4a..c0eb35a 100644 --- a/src/test/extension.test.ts +++ b/src/test/extension.test.ts @@ -1,9 +1,32 @@ import * as assert from 'assert'; import * as vscode from 'vscode'; -suite('Extension Test Suite', () => { - test('Sample test', () => { - assert.strictEqual(-1, [1, 2, 3].indexOf(5)); - assert.strictEqual(-1, [1, 2, 3].indexOf(0)); +suite('Extension Activation & Integration Test Suite', () => { + + test('Extension should be present', () => { + const extension = vscode.extensions.getExtension('CoreTrace.ctrace-audit'); + assert.ok(extension, 'Extension not found. Check the publisher.name in package.json.'); + }); + + test('Extension should activate successfully', async () => { + const extension = vscode.extensions.getExtension('CoreTrace.ctrace-audit'); + assert.ok(extension, 'Extension not found. Cannot activate.'); + + // Will throw if activation fails (e.g. fs access errors, dependency crashes) + await extension.activate(); + assert.strictEqual(extension.isActive, true, 'Extension failed to switch to active state.'); + }); + + test('Extension registers all expected commands', async () => { + const extension = vscode.extensions.getExtension('CoreTrace.ctrace-audit'); + assert.ok(extension, 'Extension not found. Cannot check commands.'); + await extension.activate(); + + // This will grab all registered commands in vscode + const commands = await vscode.commands.getCommands(); + + assert.ok(commands.includes('ctrace.runAnalysis'), 'Command ctrace.runAnalysis is missing'); + assert.ok(commands.includes('ctrace.runWorkspaceAnalysis'), 'Command ctrace.runWorkspaceAnalysis is missing'); + assert.ok(commands.includes('ctrace.clearAnalysisCache'), 'Command ctrace.clearAnalysisCache is missing'); }); });