11cb0ef41Sopenharmony_ci// Our coverage mapping means that stuff like this doen't count for coverage. 21cb0ef41Sopenharmony_ci// It does ensure that every command has a usage that renders, contains its 31cb0ef41Sopenharmony_ci// name, a description, and if it has completion it is a function. That it 41cb0ef41Sopenharmony_ci// renders also ensures that any params we've defined in our commands work. 51cb0ef41Sopenharmony_ciconst t = require('tap') 61cb0ef41Sopenharmony_ciconst util = require('util') 71cb0ef41Sopenharmony_ciconst { load: loadMockNpm } = require('../fixtures/mock-npm.js') 81cb0ef41Sopenharmony_ciconst { commands } = require('../../lib/utils/cmd-list.js') 91cb0ef41Sopenharmony_ciconst BaseCommand = require('../../lib/base-command.js') 101cb0ef41Sopenharmony_ci 111cb0ef41Sopenharmony_ciconst isAsyncFn = (v) => typeof v === 'function' && /^\[AsyncFunction:/.test(util.inspect(v)) 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_cit.test('load each command', async t => { 141cb0ef41Sopenharmony_ci const counts = { 151cb0ef41Sopenharmony_ci completion: 0, 161cb0ef41Sopenharmony_ci ignoreImplicitWorkspace: 0, 171cb0ef41Sopenharmony_ci workspaces: 0, 181cb0ef41Sopenharmony_ci noParams: 0, 191cb0ef41Sopenharmony_ci } 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ci for (const cmd of commands) { 221cb0ef41Sopenharmony_ci await t.test(cmd, async t => { 231cb0ef41Sopenharmony_ci const { npm, outputs, cmd: impl } = await loadMockNpm(t, { 241cb0ef41Sopenharmony_ci command: cmd, 251cb0ef41Sopenharmony_ci config: { usage: true }, 261cb0ef41Sopenharmony_ci }) 271cb0ef41Sopenharmony_ci const ctor = impl.constructor 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci t.notOk(impl.completion, 'completion is static, not on instance') 301cb0ef41Sopenharmony_ci if (ctor.completion) { 311cb0ef41Sopenharmony_ci t.ok(isAsyncFn(ctor.completion), 'completion is async function') 321cb0ef41Sopenharmony_ci counts.completion++ 331cb0ef41Sopenharmony_ci } 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci // exec fn 361cb0ef41Sopenharmony_ci t.ok(isAsyncFn(impl.exec), 'exec is async') 371cb0ef41Sopenharmony_ci t.ok(impl.exec.length <= 1, 'exec fn has 0 or 1 args') 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci // workspaces 401cb0ef41Sopenharmony_ci t.type(ctor.ignoreImplicitWorkspace, 'boolean', 'ctor has ignoreImplictWorkspace boolean') 411cb0ef41Sopenharmony_ci if (ctor.ignoreImplicitWorkspace !== BaseCommand.ignoreImplicitWorkspace) { 421cb0ef41Sopenharmony_ci counts.ignoreImplicitWorkspace++ 431cb0ef41Sopenharmony_ci } 441cb0ef41Sopenharmony_ci 451cb0ef41Sopenharmony_ci t.type(ctor.workspaces, 'boolean', 'ctor has workspaces boolean') 461cb0ef41Sopenharmony_ci if (ctor.workspaces !== BaseCommand.workspaces) { 471cb0ef41Sopenharmony_ci counts.workspaces++ 481cb0ef41Sopenharmony_ci } 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci if (ctor.workspaces) { 511cb0ef41Sopenharmony_ci t.ok(isAsyncFn(impl.execWorkspaces), 'execWorkspaces is async') 521cb0ef41Sopenharmony_ci t.ok(impl.exec.length <= 1, 'execWorkspaces fn has 0 or 1 args') 531cb0ef41Sopenharmony_ci } else { 541cb0ef41Sopenharmony_ci t.notOk(impl.execWorkspaces, 'has no execWorkspaces fn') 551cb0ef41Sopenharmony_ci } 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ci // name/desc 581cb0ef41Sopenharmony_ci t.ok(impl.description, 'implementation has a description') 591cb0ef41Sopenharmony_ci t.equal(impl.description, ctor.description, 'description is same on instance and ctor') 601cb0ef41Sopenharmony_ci t.ok(impl.name, 'implementation has a name') 611cb0ef41Sopenharmony_ci t.equal(impl.name, ctor.name, 'name is same on instance and ctor') 621cb0ef41Sopenharmony_ci t.equal(cmd, impl.name, 'command list and name are the same') 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ci // params are optional 651cb0ef41Sopenharmony_ci if (impl.params) { 661cb0ef41Sopenharmony_ci t.equal(impl.params, ctor.params, 'params is same on instance and ctor') 671cb0ef41Sopenharmony_ci t.ok(impl.params, 'implementation has a params') 681cb0ef41Sopenharmony_ci } else { 691cb0ef41Sopenharmony_ci counts.noParams++ 701cb0ef41Sopenharmony_ci } 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ci // usage 731cb0ef41Sopenharmony_ci t.match(impl.usage, cmd, 'usage contains the command') 741cb0ef41Sopenharmony_ci await npm.exec(cmd, []) 751cb0ef41Sopenharmony_ci t.match(outputs[0][0], impl.usage, 'usage is what is output') 761cb0ef41Sopenharmony_ci t.match(outputs[0][0], ctor.describeUsage, 'usage is what is output') 771cb0ef41Sopenharmony_ci t.notOk(impl.describeUsage, 'describe usage is only static') 781cb0ef41Sopenharmony_ci }) 791cb0ef41Sopenharmony_ci } 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci // make sure refactors dont move or rename these static properties since 821cb0ef41Sopenharmony_ci // we guard against the tests for them above 831cb0ef41Sopenharmony_ci t.ok(counts.completion > 0, 'has some completion functions') 841cb0ef41Sopenharmony_ci t.ok(counts.ignoreImplicitWorkspace > 0, 'has some commands that change ignoreImplicitWorkspace') 851cb0ef41Sopenharmony_ci t.ok(counts.workspaces > 0, 'has some commands that change workspaces') 861cb0ef41Sopenharmony_ci t.ok(counts.noParams > 0, 'has some commands that do not have params') 871cb0ef41Sopenharmony_ci}) 88