From 2fcdc5c5cb12350ecf846cca25d979cc7f832965 Mon Sep 17 00:00:00 2001 From: Tobias Date: Tue, 23 Jun 2026 00:49:21 +0200 Subject: [PATCH] GLSP-1635: Migrate spec assertions to native Vitest matchers - Convert all Chai-style BDD assertions (`.to.be.true`, `.to.deep.equal`, `.to.include.members`, ...) across the CLI specs to native Vitest matchers; they previously passed only via Vitest's bundled Chai-compatible API - Drop the now-redundant eslint-plugin-chai-friendly and restore the plain no-unused-expressions rule, since the converted assertions are method calls rather than bare expression statements - Remove the stale mocha global from the shared eslint base config Also: - Add a root test:coverage script - Drop dead ctrf/ and .nyc_output/ entries from .gitignore Part of: eclipse-glsp/glsp#1635 --- .gitignore | 2 - dev-packages/cli/src/cli.spec.ts | 258 +++++++++--------- .../cli/src/commands/releng/common.spec.ts | 82 +++--- .../cli/src/commands/releng/publish.spec.ts | 32 +-- .../cli/src/commands/releng/version.spec.ts | 14 +- .../cli/src/commands/repo/build.spec.ts | 34 +-- .../cli/src/commands/repo/clone.spec.ts | 30 +- .../src/commands/repo/common/utils.spec.ts | 50 ++-- .../cli/src/commands/repo/fork.spec.ts | 46 ++-- .../cli/src/commands/repo/link.spec.ts | 84 +++--- .../cli/src/commands/repo/repo.spec.ts | 10 +- .../cli/src/commands/repo/run.spec.ts | 12 +- .../cli/src/commands/repo/server-node.spec.ts | 10 +- .../cli/src/commands/repo/start.spec.ts | 20 +- .../cli/src/commands/repo/switch.spec.ts | 22 +- .../cli/src/commands/repo/workspace.spec.ts | 52 ++-- .../cli/src/commands/update-next.spec.ts | 12 +- dev-packages/cli/src/util/file-util.spec.ts | 32 +-- dev-packages/cli/src/util/git-util.spec.ts | 34 +-- .../cli/src/util/glsp-repo-util.spec.ts | 14 +- .../cli/src/util/package-util.spec.ts | 16 +- .../cli/src/util/process-util.spec.ts | 12 +- .../cli/src/util/validation-util.spec.ts | 12 +- .../cli/tests/e2e/check-header.e2e.spec.ts | 44 +-- .../cli/tests/e2e/generate-index.e2e.spec.ts | 44 +-- .../cli/tests/e2e/releng/prepare.e2e.spec.ts | 84 +++--- .../cli/tests/e2e/releng/version.e2e.spec.ts | 64 ++--- .../e2e/repo/repo-core-build.e2e.spec.ts | 56 ++-- .../e2e/repo/repo-core-clone.e2e.spec.ts | 80 +++--- .../tests/e2e/repo/repo-eclipse.e2e.spec.ts | 8 +- .../cli/tests/e2e/repo/repo-theia.e2e.spec.ts | 6 +- .../tests/e2e/repo/repo-vscode.e2e.spec.ts | 30 +- .../cli/tests/e2e/update-next.e2e.spec.ts | 6 +- dev-packages/config/package.json | 1 - dev-packages/eslint-config/configs/base.js | 3 - dev-packages/eslint-config/configs/errors.js | 4 +- dev-packages/eslint-config/package.json | 1 - package.json | 1 + pnpm-lock.yaml | 16 -- 39 files changed, 653 insertions(+), 685 deletions(-) diff --git a/.gitignore b/.gitignore index 3db0f97..540cb48 100644 --- a/.gitignore +++ b/.gitignore @@ -4,9 +4,7 @@ lib dist tsconfig.tsbuildinfo eslint.xml -ctrf/ coverage/ -.nyc_output/ # Agent specific files .claude/plans diff --git a/dev-packages/cli/src/cli.spec.ts b/dev-packages/cli/src/cli.spec.ts index 7e8fc6a..d99a61d 100644 --- a/dev-packages/cli/src/cli.spec.ts +++ b/dev-packages/cli/src/cli.spec.ts @@ -30,12 +30,12 @@ const optionLongs = (cmd: Command): string[] => cmd.options.map(o => o.long!); const subcommandNames = (cmd: Command): string[] => cmd.commands.map(c => c.name()); const findSub = (parent: Command, name: string): Command => { const sub = parent.commands.find(c => c.name() === name); - expect(sub, `subcommand '${name}' not found on '${parent.name()}'`).to.exist; + expect(sub, `subcommand '${name}' not found on '${parent.name()}'`).toBeDefined(); return sub!; }; const choices = (cmd: Command, long: string): string[] | undefined => { const opt = cmd.options.find(o => o.long === long); - expect(opt, `option '${long}' not found on '${cmd.name()}'`).to.exist; + expect(opt, `option '${long}' not found on '${cmd.name()}'`).toBeDefined(); return opt!.argChoices; }; @@ -47,63 +47,67 @@ describe('cli', () => { describe('top-level commands', () => { describe('checkHeaders', () => { it('should accept a argument', () => { - expect(CheckHeaderCommand.registeredArguments).to.have.lengthOf(1); - expect(CheckHeaderCommand.registeredArguments[0].name()).to.equal('rootDir'); - expect(CheckHeaderCommand.registeredArguments[0].required).to.be.true; + expect(CheckHeaderCommand.registeredArguments).toHaveLength(1); + expect(CheckHeaderCommand.registeredArguments[0].name()).toBe('rootDir'); + expect(CheckHeaderCommand.registeredArguments[0].required).toBe(true); }); it('should have expected options', () => { - expect(optionLongs(CheckHeaderCommand)).to.include.members([ - '--type', - '--fileExtensions', - '--exclude', - '--no-exclude-defaults', - '--json', - '--autoFix', - '--commit' - ]); + expect(optionLongs(CheckHeaderCommand)).toEqual( + expect.arrayContaining([ + '--type', + '--fileExtensions', + '--exclude', + '--no-exclude-defaults', + '--json', + '--autoFix', + '--commit' + ]) + ); }); it('should restrict --type choices', () => { - expect(choices(CheckHeaderCommand, '--type')).to.deep.equal(['full', 'changes', 'lastCommit']); + expect(choices(CheckHeaderCommand, '--type')).toEqual(['full', 'changes', 'lastCommit']); }); }); describe('updateNext', () => { it('should have alias "u"', () => { - expect(UpdateNextCommand.alias()).to.equal('u'); + expect(UpdateNextCommand.alias()).toBe('u'); }); it('should accept an optional [rootDir] argument', () => { - expect(UpdateNextCommand.registeredArguments).to.have.lengthOf(1); - expect(UpdateNextCommand.registeredArguments[0].required).to.be.false; + expect(UpdateNextCommand.registeredArguments).toHaveLength(1); + expect(UpdateNextCommand.registeredArguments[0].required).toBe(false); }); it('should have expected options', () => { - expect(optionLongs(UpdateNextCommand)).to.include.members(['--verbose']); + expect(optionLongs(UpdateNextCommand)).toEqual(expect.arrayContaining(['--verbose'])); }); }); describe('generateIndex', () => { it('should accept a variadic argument', () => { - expect(GenerateIndex.registeredArguments).to.have.lengthOf(1); - expect(GenerateIndex.registeredArguments[0].variadic).to.be.true; + expect(GenerateIndex.registeredArguments).toHaveLength(1); + expect(GenerateIndex.registeredArguments[0].variadic).toBe(true); }); it('should have expected options', () => { - expect(optionLongs(GenerateIndex)).to.include.members([ - '--singleIndex', - '--forceOverwrite', - '--match', - '--ignore', - '--style', - '--ignoreFile', - '--verbose' - ]); + expect(optionLongs(GenerateIndex)).toEqual( + expect.arrayContaining([ + '--singleIndex', + '--forceOverwrite', + '--match', + '--ignore', + '--style', + '--ignoreFile', + '--verbose' + ]) + ); }); it('should restrict --style choices', () => { - expect(choices(GenerateIndex, '--style')).to.deep.equal(['commonjs', 'esm']); + expect(choices(GenerateIndex, '--style')).toEqual(['commonjs', 'esm']); }); }); }); @@ -112,7 +116,7 @@ describe('cli', () => { describe('releng', () => { it('should have version and prepare subcommands', () => { - expect(subcommandNames(RelengCommand)).to.include.members(['version', 'prepare']); + expect(subcommandNames(RelengCommand)).toEqual(expect.arrayContaining(['version', 'prepare'])); }); describe('version', () => { @@ -120,18 +124,18 @@ describe('cli', () => { it('should accept argument with choices', () => { const arg = cmd.registeredArguments[0]; - expect(arg.name()).to.equal('versionType'); - expect(arg.required).to.be.true; - expect(arg.argChoices).to.deep.equal(['major', 'minor', 'patch', 'custom', 'next']); + expect(arg.name()).toBe('versionType'); + expect(arg.required).toBe(true); + expect(arg.argChoices).toEqual(['major', 'minor', 'patch', 'custom', 'next']); }); it('should accept optional [customVersion] argument', () => { - expect(cmd.registeredArguments[1].name()).to.equal('customVersion'); - expect(cmd.registeredArguments[1].required).to.be.false; + expect(cmd.registeredArguments[1].name()).toBe('customVersion'); + expect(cmd.registeredArguments[1].required).toBe(false); }); it('should have expected options', () => { - expect(optionLongs(cmd)).to.include.members(['--verbose', '--repoDir']); + expect(optionLongs(cmd)).toEqual(expect.arrayContaining(['--verbose', '--repoDir'])); }); }); @@ -140,11 +144,11 @@ describe('cli', () => { it('should accept argument with choices', () => { const arg = cmd.registeredArguments[0]; - expect(arg.argChoices).to.deep.equal(['major', 'minor', 'patch', 'custom', 'next']); + expect(arg.argChoices).toEqual(['major', 'minor', 'patch', 'custom', 'next']); }); it('should have expected options', () => { - expect(optionLongs(cmd)).to.include.members(['--verbose', '--repoDir', '--no-push', '--draft', '--no-check']); + expect(optionLongs(cmd)).toEqual(expect.arrayContaining(['--verbose', '--repoDir', '--no-push', '--draft', '--no-check'])); }); }); }); @@ -153,60 +157,57 @@ describe('cli', () => { describe('repo', () => { it('should register all top-level repo subcommands', () => { - expect(subcommandNames(RepoCommand)).to.include.members([ - 'clone', - 'fork', - 'build', - 'link', - 'unlink', - 'pwd', - 'log', - 'workspace' - ]); + expect(subcommandNames(RepoCommand)).toEqual( + expect.arrayContaining(['clone', 'fork', 'build', 'link', 'unlink', 'pwd', 'log', 'workspace']) + ); }); it('should register a subrepo command for each GLSPRepo', () => { for (const repoName of GLSPRepo.choices) { - expect(subcommandNames(RepoCommand), `subrepo '${repoName}' should be registered`).to.include(repoName); + expect(subcommandNames(RepoCommand), `subrepo '${repoName}' should be registered`).toContain(repoName); } }); it('should have a global --dir option', () => { - expect(optionLongs(RepoCommand)).to.include('--dir'); + expect(optionLongs(RepoCommand)).toContain('--dir'); }); describe('clone', () => { const cmd = findSub(RepoCommand, 'clone'); it('should accept optional [repos...] argument', () => { - expect(cmd.registeredArguments[0].variadic).to.be.true; - expect(cmd.registeredArguments[0].required).to.be.false; + expect(cmd.registeredArguments[0].variadic).toBe(true); + expect(cmd.registeredArguments[0].required).toBe(false); }); it('should have expected options', () => { - expect(optionLongs(cmd)).to.include.members([ - '--dir', - '--protocol', - '--branch', - '--fork', - '--override', - '--preset', - '--interactive', - '--no-fail-fast', - '--verbose' - ]); + expect(optionLongs(cmd)).toEqual( + expect.arrayContaining([ + '--dir', + '--protocol', + '--branch', + '--fork', + '--override', + '--preset', + '--interactive', + '--no-fail-fast', + '--verbose' + ]) + ); }); it('should restrict --protocol choices', () => { - expect(choices(cmd, '--protocol')).to.deep.equal(['ssh', 'https', 'gh']); + expect(choices(cmd, '--protocol')).toEqual(['ssh', 'https', 'gh']); }); it('should restrict --override choices', () => { - expect(choices(cmd, '--override')).to.deep.equal(['rename', 'remove']); + expect(choices(cmd, '--override')).toEqual(['rename', 'remove']); }); it('should restrict --preset choices', () => { - expect(choices(cmd, '--preset')).to.include.members(['core', 'theia', 'vscode', 'eclipse', 'playwright', 'all']); + expect(choices(cmd, '--preset')).toEqual( + expect.arrayContaining(['core', 'theia', 'vscode', 'eclipse', 'playwright', 'all']) + ); }); }); @@ -214,16 +215,16 @@ describe('cli', () => { const cmd = findSub(RepoCommand, 'fork'); it('should accept required argument', () => { - expect(cmd.registeredArguments[0].name()).to.equal('user'); - expect(cmd.registeredArguments[0].required).to.be.true; + expect(cmd.registeredArguments[0].name()).toBe('user'); + expect(cmd.registeredArguments[0].required).toBe(true); }); it('should have expected options', () => { - expect(optionLongs(cmd)).to.include.members(['--dir', '--protocol', '--repo', '--preset', '--verbose']); + expect(optionLongs(cmd)).toEqual(expect.arrayContaining(['--dir', '--protocol', '--repo', '--preset', '--verbose'])); }); it('should restrict --protocol choices', () => { - expect(choices(cmd, '--protocol')).to.deep.equal(['ssh', 'https', 'gh']); + expect(choices(cmd, '--protocol')).toEqual(['ssh', 'https', 'gh']); }); }); @@ -231,15 +232,9 @@ describe('cli', () => { const cmd = findSub(RepoCommand, 'build'); it('should have expected options', () => { - expect(optionLongs(cmd)).to.include.members([ - '--dir', - '--repo', - '--preset', - '--electron', - '--no-java', - '--no-fail-fast', - '--verbose' - ]); + expect(optionLongs(cmd)).toEqual( + expect.arrayContaining(['--dir', '--repo', '--preset', '--electron', '--no-java', '--no-fail-fast', '--verbose']) + ); }); }); @@ -247,7 +242,7 @@ describe('cli', () => { const cmd = findSub(RepoCommand, 'link'); it('should have expected options', () => { - expect(optionLongs(cmd)).to.include.members(['--dir', '--repo', '--preset', '--no-fail-fast', '--verbose']); + expect(optionLongs(cmd)).toEqual(expect.arrayContaining(['--dir', '--repo', '--preset', '--no-fail-fast', '--verbose'])); }); }); @@ -255,7 +250,7 @@ describe('cli', () => { const cmd = findSub(RepoCommand, 'unlink'); it('should have expected options', () => { - expect(optionLongs(cmd)).to.include.members(['--dir', '--repo', '--preset', '--no-fail-fast', '--verbose']); + expect(optionLongs(cmd)).toEqual(expect.arrayContaining(['--dir', '--repo', '--preset', '--no-fail-fast', '--verbose'])); }); }); @@ -263,7 +258,7 @@ describe('cli', () => { const cmd = findSub(RepoCommand, 'pwd'); it('should have expected options', () => { - expect(optionLongs(cmd)).to.include.members(['--dir', '--raw', '--verbose']); + expect(optionLongs(cmd)).toEqual(expect.arrayContaining(['--dir', '--raw', '--verbose'])); }); }); @@ -271,7 +266,7 @@ describe('cli', () => { const cmd = findSub(RepoCommand, 'log'); it('should have expected options', () => { - expect(optionLongs(cmd)).to.include.members(['--dir', '--repo', '--preset', '--verbose']); + expect(optionLongs(cmd)).toEqual(expect.arrayContaining(['--dir', '--repo', '--preset', '--verbose'])); }); }); @@ -279,14 +274,14 @@ describe('cli', () => { const workspace = findSub(RepoCommand, 'workspace'); it('should have init and open subcommands', () => { - expect(subcommandNames(workspace)).to.include.members(['init', 'open']); + expect(subcommandNames(workspace)).toEqual(expect.arrayContaining(['init', 'open'])); }); describe('init', () => { const cmd = findSub(workspace, 'init'); it('should have expected options', () => { - expect(optionLongs(cmd)).to.include.members(['--dir', '--output', '--repo', '--preset', '--verbose']); + expect(optionLongs(cmd)).toEqual(expect.arrayContaining(['--dir', '--output', '--repo', '--preset', '--verbose'])); }); }); @@ -294,7 +289,7 @@ describe('cli', () => { const cmd = findSub(workspace, 'open'); it('should have expected options', () => { - expect(optionLongs(cmd)).to.include.members(['--dir', '--verbose']); + expect(optionLongs(cmd)).toEqual(expect.arrayContaining(['--dir', '--verbose'])); }); }); }); @@ -317,12 +312,12 @@ describe('cli', () => { const cmd = createSubrepoCommand(repoName); it('should have common subcommands', () => { - expect(subcommandNames(cmd)).to.include.members(['clone', 'switch', 'build', 'pwd', 'log', 'run']); + expect(subcommandNames(cmd)).toEqual(expect.arrayContaining(['clone', 'switch', 'build', 'pwd', 'log', 'run'])); }); if (SHORT_ALIASES[repoName]) { it(`should have alias "${SHORT_ALIASES[repoName]}"`, () => { - expect(cmd.alias()).to.equal(SHORT_ALIASES[repoName]); + expect(cmd.alias()).toBe(SHORT_ALIASES[repoName]); }); } @@ -330,22 +325,17 @@ describe('cli', () => { const clone = findSub(cmd, 'clone'); it('should have expected options', () => { - expect(optionLongs(clone)).to.include.members([ - '--dir', - '--protocol', - '--branch', - '--fork', - '--override', - '--verbose' - ]); + expect(optionLongs(clone)).toEqual( + expect.arrayContaining(['--dir', '--protocol', '--branch', '--fork', '--override', '--verbose']) + ); }); it('should restrict --protocol choices', () => { - expect(choices(clone, '--protocol')).to.deep.equal(['ssh', 'https', 'gh']); + expect(choices(clone, '--protocol')).toEqual(['ssh', 'https', 'gh']); }); it('should restrict --override choices', () => { - expect(choices(clone, '--override')).to.deep.equal(['rename', 'remove']); + expect(choices(clone, '--override')).toEqual(['rename', 'remove']); }); }); @@ -353,7 +343,7 @@ describe('cli', () => { const sw = findSub(cmd, 'switch'); it('should have expected options', () => { - expect(optionLongs(sw)).to.include.members(['--branch', '--dir', '--pr', '--force', '--verbose']); + expect(optionLongs(sw)).toEqual(expect.arrayContaining(['--branch', '--dir', '--pr', '--force', '--verbose'])); }); }); @@ -361,12 +351,12 @@ describe('cli', () => { const build = findSub(cmd, 'build'); it('should have expected options', () => { - expect(optionLongs(build)).to.include.members(['--dir', '--verbose']); + expect(optionLongs(build)).toEqual(expect.arrayContaining(['--dir', '--verbose'])); }); if (repoName === 'glsp-theia-integration') { it('should have --electron option', () => { - expect(optionLongs(build)).to.include('--electron'); + expect(optionLongs(build)).toContain('--electron'); }); } }); @@ -375,7 +365,7 @@ describe('cli', () => { const pwd = findSub(cmd, 'pwd'); it('should have expected options', () => { - expect(optionLongs(pwd)).to.include.members(['--dir', '--verbose']); + expect(optionLongs(pwd)).toEqual(expect.arrayContaining(['--dir', '--verbose'])); }); }); @@ -383,7 +373,7 @@ describe('cli', () => { const log = findSub(cmd, 'log'); it('should have expected options', () => { - expect(optionLongs(log)).to.include.members(['--dir', '--verbose']); + expect(optionLongs(log)).toEqual(expect.arrayContaining(['--dir', '--verbose'])); }); }); @@ -391,13 +381,13 @@ describe('cli', () => { const run = findSub(cmd, 'run'); it('should accept a required