diff --git a/package-lock.json b/package-lock.json index 4c13d1ee4e22..ea5066951e2e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6203,11 +6203,6 @@ "@types/node": "*" } }, - "node_modules/@types/parse-json": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", - "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" - }, "node_modules/@types/plist": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.5.tgz", @@ -9097,18 +9092,52 @@ "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" }, "node_modules/cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" }, "engines": { - "node": ">=8" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cosmiconfig/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/cosmiconfig/node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/cosmiconfig/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, "node_modules/crc": { @@ -17818,6 +17847,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, "engines": { "node": ">=8" } @@ -21223,7 +21253,7 @@ "version": "5.4.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", - "dev": true, + "devOptional": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -22809,9 +22839,9 @@ "@stoplight/spectral-ruleset-bundler": "^1.5.2", "@stoplight/spectral-rulesets": "^1.18.1", "@stoplight/types": "^14.1.1", - "commander": "^5.1.0", + "commander": "^12.1.0", "consola": "^2.15.0", - "cosmiconfig": "^6.0.0", + "cosmiconfig": "^9.0.0", "enquirer": "^2.4.1", "insomnia-send-request": "../insomnia-send-request", "string-argv": "^0.3.2", @@ -23201,6 +23231,14 @@ "node": ">=12" } }, + "packages/insomnia-inso/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "engines": { + "node": ">=18" + } + }, "packages/insomnia-inso/node_modules/esbuild": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", diff --git a/packages/insomnia-inso/package.json b/packages/insomnia-inso/package.json index 89f976344fa9..ba902181de95 100644 --- a/packages/insomnia-inso/package.json +++ b/packages/insomnia-inso/package.json @@ -51,9 +51,9 @@ "@stoplight/spectral-ruleset-bundler": "^1.5.2", "@stoplight/spectral-rulesets": "^1.18.1", "@stoplight/types": "^14.1.1", - "commander": "^5.1.0", + "commander": "^12.1.0", "consola": "^2.15.0", - "cosmiconfig": "^6.0.0", + "cosmiconfig": "^9.0.0", "enquirer": "^2.4.1", "insomnia-send-request": "../insomnia-send-request", "@seald-io/nedb": "^4.0.4", diff --git a/packages/insomnia-inso/src/__snapshots__/inso-snapshot.test.ts.snap b/packages/insomnia-inso/src/__snapshots__/inso-snapshot.test.ts.snap index ae5163f5b357..c03c7a77fe2c 100644 --- a/packages/insomnia-inso/src/__snapshots__/inso-snapshot.test.ts.snap +++ b/packages/insomnia-inso/src/__snapshots__/inso-snapshot.test.ts.snap @@ -4,16 +4,21 @@ exports[`Snapshot for "inso --help" 1`] = ` "Usage: inso [options] [command] A CLI for Insomnia! - With this tool you can lint, test and export your Insomnia data. - It can read from three data sources, but will use local Insomnia application data as a default: - - Insomnia data directory (~/.config/Insomnia/) - - Insomnia export file (eg. export.json) - - Git repository (~/git/myproject) + With this tool you can test, lint, and export your Insomnia data. + + Inso accepts 3 types of input: + Insomnia application data - will be automatically detected, or you can set --workingDir to an alternaitve application data path. + Insomnia export files - set --src to the file path. + Git repositories - set --workingDir to the repository path. + + Inso also supports configuration files, by default it will look for .insorc in the current working directory or --workingDir. Options: -v, --version output the version number - -w, --workingDir set working directory + -w, --workingDir set working directory, defaults to current working + directory, will detect a git repository or Insomnia + data directory --src set the file read from, defaults to installed Insomnia data directory --verbose show additional logs while running the command @@ -34,16 +39,21 @@ exports[`Snapshot for "inso -h" 1`] = ` "Usage: inso [options] [command] A CLI for Insomnia! - With this tool you can lint, test and export your Insomnia data. - It can read from three data sources, but will use local Insomnia application data as a default: - - Insomnia data directory (~/.config/Insomnia/) - - Insomnia export file (eg. export.json) - - Git repository (~/git/myproject) + With this tool you can test, lint, and export your Insomnia data. + + Inso accepts 3 types of input: + Insomnia application data - will be automatically detected, or you can set --workingDir to an alternaitve application data path. + Insomnia export files - set --src to the file path. + Git repositories - set --workingDir to the repository path. + + Inso also supports configuration files, by default it will look for .insorc in the current working directory or --workingDir. Options: -v, --version output the version number - -w, --workingDir set working directory + -w, --workingDir set working directory, defaults to current working + directory, will detect a git repository or Insomnia + data directory --src set the file read from, defaults to installed Insomnia data directory --verbose show additional logs while running the command @@ -88,16 +98,21 @@ exports[`Snapshot for "inso generate -h" 1`] = ` "Usage: inso [options] [command] A CLI for Insomnia! - With this tool you can lint, test and export your Insomnia data. - It can read from three data sources, but will use local Insomnia application data as a default: - - Insomnia data directory (~/.config/Insomnia/) - - Insomnia export file (eg. export.json) - - Git repository (~/git/myproject) + With this tool you can test, lint, and export your Insomnia data. + + Inso accepts 3 types of input: + Insomnia application data - will be automatically detected, or you can set --workingDir to an alternaitve application data path. + Insomnia export files - set --src to the file path. + Git repositories - set --workingDir to the repository path. + + Inso also supports configuration files, by default it will look for .insorc in the current working directory or --workingDir. Options: -v, --version output the version number - -w, --workingDir set working directory + -w, --workingDir set working directory, defaults to current working + directory, will detect a git repository or Insomnia + data directory --src set the file read from, defaults to installed Insomnia data directory --verbose show additional logs while running the command @@ -118,16 +133,21 @@ exports[`Snapshot for "inso help" 1`] = ` "Usage: inso [options] [command] A CLI for Insomnia! - With this tool you can lint, test and export your Insomnia data. - It can read from three data sources, but will use local Insomnia application data as a default: - - Insomnia data directory (~/.config/Insomnia/) - - Insomnia export file (eg. export.json) - - Git repository (~/git/myproject) + With this tool you can test, lint, and export your Insomnia data. + + Inso accepts 3 types of input: + Insomnia application data - will be automatically detected, or you can set --workingDir to an alternaitve application data path. + Insomnia export files - set --src to the file path. + Git repositories - set --workingDir to the repository path. + + Inso also supports configuration files, by default it will look for .insorc in the current working directory or --workingDir. Options: -v, --version output the version number - -w, --workingDir set working directory + -w, --workingDir set working directory, defaults to current working + directory, will detect a git repository or Insomnia + data directory --src set the file read from, defaults to installed Insomnia data directory --verbose show additional logs while running the command diff --git a/packages/insomnia-inso/src/cli.ts b/packages/insomnia-inso/src/cli.ts index 735163d37011..7a382cb607c7 100644 --- a/packages/insomnia-inso/src/cli.ts +++ b/packages/insomnia-inso/src/cli.ts @@ -35,10 +35,11 @@ export const OptionsSupportedInConfigFile: (keyof GlobalOptions)[] = [ 'printOptions', ]; -export const loadCosmiConfig = async (configFile?: string) => { +export const loadCosmiConfig = async (configFile?: string, workingDir?: string) => { try { const explorer = await cosmiconfig('inso'); - const results = configFile ? await explorer.load(configFile) : await explorer.search(); + // set or detect .insorc in workingDir or cwd https://github.com/cosmiconfig/cosmiconfig?tab=readme-ov-file#explorersearch + const results = configFile ? await explorer.load(configFile) : await explorer.search(workingDir || process.cwd()); if (results && !results?.isEmpty) { logger.debug(`Found config file at ${results?.filepath}.`); @@ -52,7 +53,7 @@ export const loadCosmiConfig = async (configFile?: string) => { return acc; }, {}); - return { __configFile: { options, scripts, filePath } }; + return { options, scripts, filePath }; } } catch (error) { // Report fatal error when loading from explicitly defined config file @@ -65,55 +66,6 @@ export const loadCosmiConfig = async (configFile?: string) => { return {}; }; -interface CommandObj { - parent?: CommandObj; - opts: () => GlobalOptions; -} - -export const extractCommandOptions = (cmd: CommandObj): Partial => { - let opts: Partial = {}; - let command: CommandObj | undefined = cmd; - - do { - // overwrite options with more specific ones - opts = { ...command.opts(), ...opts }; - command = command.parent; - } while (command); - - return opts; -}; - -export const getOptions = async (cmd: CommandObj, defaultOptions = {}) => { - const commandOptions = extractCommandOptions(cmd); - const { __configFile } = await loadCosmiConfig(commandOptions.config); - - if (__configFile) { - return { - ...defaultOptions, - ...__configFile.options, - ...commandOptions, - __configFile, - }; - } - - return { - ...defaultOptions, - ...commandOptions, - }; -}; - -export const noConsoleLog = async (callback: () => Promise): Promise => { - const oldConsoleLog = console.log; - - console.log = () => { }; - - try { - return await callback(); - } finally { - console.log = oldConsoleLog; - } -}; - export type LogsByType = { [t in logType]?: string[] }; @@ -135,13 +87,6 @@ const consolaLogger = consola.create({ export const logger = consolaLogger as ModifiedConsola; -export const configureLogger = (verbose = false, ci = false) => { - logger.level = verbose ? LogLevel.Verbose : LogLevel.Info; - - if (ci) { - logger.setReporters([new BasicReporter()]); - } -}; export class InsoError extends Error { cause?: Error | null; @@ -164,95 +109,33 @@ export const logErrorAndExit = (err?: Error) => { process.exit(1); }; -const prepareCommand = (options: Partial) => { - configureLogger(options.verbose, options.ci); - options.printOptions && logger.log('Loaded options', options, '\n'); - return options; -}; - -const addScriptCommand = (originalCommand: commander.Command) => { - // inso script - originalCommand - .command('script ', { - isDefault: true, - }) - .description('Run scripts defined in .insorc') - .allowUnknownOption() - .action(async (scriptName: 'lint', cmd) => { - // Load scripts - let options = await getOptions(cmd); - options = prepareCommand(options); - - // Ignore the first arg because that will be scriptName, get the rest - const passThroughArgs = cmd.args.slice(1); +export const go = (args?: string[]) => { - // Find script - const scriptTask = options.__configFile?.scripts?.[scriptName]; - - if (!scriptTask) { - logger.fatal(`Could not find inso script "${scriptName}" in the config file.`); - return process.exit(1); - - } - - if (!scriptTask.startsWith('inso')) { - logger.fatal('Tasks in a script should start with `inso`.'); - return process.exit(1); - } - - // Collect args - const scriptArgs: string[] = parseArgsStringToArgv( - `self ${scriptTask} ${passThroughArgs.join(' ')}`, - ); - - // Print command - logger.debug(`>> ${scriptArgs.slice(1).join(' ')}`); // Run - - originalCommand.parseAsync(scriptArgs).catch(logErrorAndExit); - return; - }); -}; - -export const go = (args?: string[], exitOverride?: boolean) => { - const commandCreator = (cmd?: string) => { - const command = new commander.Command(cmd).storeOptionsAsProperties(false); - - if (exitOverride) { - command.exitOverride(); - } - - return command; - }; - - configureLogger(); - - // inso - const cmd = commandCreator(); + const program = new commander.Command(); const version = process.env.VERSION || packageJson.version; + const defaultReporter: TestReporter = 'spec'; - // Version and description - cmd + program .version(version, '-v, --version') .description(`A CLI for Insomnia! - With this tool you can lint, test and export your Insomnia data. - It can read from three data sources, but will use local Insomnia application data as a default: - - Insomnia data directory (~/.config/Insomnia/) - - Insomnia export file (eg. export.json) - - Git repository (~/git/myproject) -`); - - // Global options - cmd - .option('-w, --workingDir ', 'set working directory') + With this tool you can test, lint, and export your Insomnia data. + + Inso accepts 3 types of input: + Insomnia application data - will be automatically detected, or you can set --workingDir to an alternaitve application data path. + Insomnia export files - set --src to the file path. + Git repositories - set --workingDir to the repository path. + + Inso also supports configuration files, by default it will look for .insorc in the current working directory or --workingDir. +`) + .option('-w, --workingDir ', 'set working directory, defaults to current working directory, will detect a git repository or Insomnia data directory') .option('--src ', 'set the file read from, defaults to installed Insomnia data directory') .option('--verbose', 'show additional logs while running the command') .option('--ci', 'run in CI, disables all prompts') .option('--config ', 'path to configuration file containing above options') .option('--printOptions', 'print the loaded options'); - const run = commandCreator('run').description('Execution utilities'); - const defaultReporter: TestReporter = 'spec'; - run + program.command('run') + .description('Execution utilities') .command('test [identifier]') .description('Run Insomnia unit test suites') .option('-e, --env ', 'environment to use') @@ -265,44 +148,101 @@ export const go = (args?: string[], exitOverride?: boolean) => { .option('--keepFile', 'do not delete the generated test file') .option('--disableCertValidation', 'disable certificate validation for requests with SSL') .action(async (identifier, cmd) => { - let options = await getOptions(cmd, { + const commandOptions = { ...program.optsWithGlobals(), ...cmd }; + const __configFile = await loadCosmiConfig(commandOptions.config, commandOptions.workingDir); + + const options = { reporter: defaultReporter, - }); - options = prepareCommand(options); + ...__configFile?.options || {}, + ...commandOptions, + ...(__configFile ? { __configFile } : {}), + }; + logger.level = options.verbose ? LogLevel.Verbose : LogLevel.Info; + options.ci && logger.setReporters([new BasicReporter()]); + options.printOptions && logger.log('Loaded options', options, '\n'); + return runInsomniaTests(identifier, options) .then(success => process.exit(success ? 0 : 1)).catch(logErrorAndExit); }); - const lint = commandCreator('lint').description('Linting utilities'); - lint + program.command('lint') + .description('Linting utilities') .command('spec [identifier]') .description('Lint an API Specification') .action(async (identifier, cmd) => { - let options = await getOptions(cmd); - options = prepareCommand(options); + const commandOptions = { ...program.optsWithGlobals(), ...cmd }; + const __configFile = await loadCosmiConfig(commandOptions.config, commandOptions.workingDir); + + const options = { + ...__configFile?.options || {}, + ...commandOptions, + ...(__configFile ? { __configFile } : {}), + }; + logger.level = options.verbose ? LogLevel.Verbose : LogLevel.Info; + options.ci && logger.setReporters([new BasicReporter()]); return lintSpecification(identifier, options) .then(success => process.exit(success ? 0 : 1)).catch(logErrorAndExit); }); - const exportCmd = commandCreator('export').description('Export data from insomnia models'); - exportCmd + program.command('export').description('Export data from insomnia models') .command('spec [identifier]') .description('Export an API Specification to a file') .option('-o, --output ', 'save the generated config to a file') .option('-s, --skipAnnotations', 'remove all "x-kong-" annotations ', false) .action(async (identifier, cmd) => { - let options = await getOptions(cmd); - options = prepareCommand(options); + const commandOptions = { ...program.optsWithGlobals(), ...cmd }; + const __configFile = await loadCosmiConfig(commandOptions.config, commandOptions.workingDir); + + const options = { + ...__configFile?.options || {}, + ...commandOptions, + ...(__configFile ? { __configFile } : {}), + }; + options.printOptions && logger.log('Loaded options', options, '\n'); return exportSpecification(identifier, options) .then(success => process.exit(success ? 0 : 1)).catch(logErrorAndExit); }); - cmd - .addCommand(run) - .addCommand(lint) - .addCommand(exportCmd); - // Add script base command - addScriptCommand(cmd); - cmd.parseAsync(args || process.argv).catch(logErrorAndExit); + program.command('script ') + .description('Run scripts defined in .insorc') + .allowUnknownOption() + .action(async (scriptName: string, cmd) => { + const commandOptions = { ...program.optsWithGlobals(), ...cmd }; + // TODO: getAbsolutePath to working directory and use it to check from config file + const __configFile = await loadCosmiConfig(commandOptions.config, commandOptions.workingDir); + + const options = { + ...__configFile?.options || {}, + ...commandOptions, + ...(__configFile ? { __configFile } : {}), + }; + logger.level = options.verbose ? LogLevel.Verbose : LogLevel.Info; + options.ci && logger.setReporters([new BasicReporter()]); + options.printOptions && logger.log('Loaded options', options, '\n'); + + const scriptTask = options.__configFile?.scripts?.[scriptName]; + + if (!scriptTask) { + logger.fatal(`Could not find inso script "${scriptName}" in the config file.`); + return process.exit(1); + } + + if (!scriptTask.startsWith('inso')) { + logger.fatal('Tasks in a script should start with `inso`.'); + return process.exit(1); + } + + // Get args after script name + const passThroughArgs = program.args.slice(program.args.indexOf(scriptName) + 1); + const scriptArgs: string[] = parseArgsStringToArgv( + `self ${scriptTask} ${passThroughArgs.join(' ')}`, + ); + + logger.debug(`>> ${scriptArgs.slice(1).join(' ')}`); + + program.parseAsync(scriptArgs).catch(logErrorAndExit); + }); + + program.parseAsync(args || process.argv).catch(logErrorAndExit); }; diff --git a/packages/insomnia-inso/src/commands/export-specification.ts b/packages/insomnia-inso/src/commands/export-specification.ts index 8be3bb8ed9d9..1ddb39878b24 100644 --- a/packages/insomnia-inso/src/commands/export-specification.ts +++ b/packages/insomnia-inso/src/commands/export-specification.ts @@ -10,16 +10,6 @@ export type ExportSpecificationOptions = GlobalOptions & { skipAnnotations?: boolean; }; -function deleteField(obj: any, field: any): void { - Object.keys(obj).forEach(key => { - if (key.startsWith(field)) { - delete obj[key]; - } else if (typeof obj[key] === 'object') { - deleteField(obj[key], field); - } - }); -} - export async function exportSpecification( identifier: string | null | undefined, { output, skipAnnotations, workingDir, ci, src }: ExportSpecificationOptions, @@ -37,19 +27,34 @@ export async function exportSpecification( return false; } - let contents = specFromDb.contents; - if (skipAnnotations) { - const yamlObj = YAML.parse(contents); - deleteField(yamlObj, 'x-kong-'); - contents = YAML.stringify(yamlObj); + if (!skipAnnotations) { + if (!output) { + logger.log(specFromDb.contents); + return true; + } + const outputPath = await writeFileWithCliOptions(output, specFromDb.contents, workingDir); + logger.log(`Specification exported to "${outputPath}".`); + return true; } - if (output) { - const outputPath = await writeFileWithCliOptions(output, contents, workingDir); - logger.log(`Specification exported to "${outputPath}".`); - } else { - logger.log(contents); + const recursiveDeleteKey = (obj: any) => { + Object.keys(obj).forEach(key => { + if (key.startsWith('x-kong-')) { + delete obj[key]; + } else if (typeof obj[key] === 'object') { + recursiveDeleteKey(obj[key]); + } + }); + return obj; + }; + const cleaned = YAML.stringify(recursiveDeleteKey(YAML.parse(specFromDb.contents))); + logger.debug('Removed keys starting with x-kong-'); + if (!output) { + logger.log(cleaned); + return true; } + const outputPath = await writeFileWithCliOptions(output, cleaned, workingDir); + logger.log(`Specification exported to "${outputPath}".`); return true; } diff --git a/packages/insomnia-inso/src/commands/run-tests.ts b/packages/insomnia-inso/src/commands/run-tests.ts index 23f77b444bbd..1157427ef875 100644 --- a/packages/insomnia-inso/src/commands/run-tests.ts +++ b/packages/insomnia-inso/src/commands/run-tests.ts @@ -1,6 +1,6 @@ import { generate, runTestsCli, TestSuite } from 'insomnia-testing'; -import { type GlobalOptions, logger, noConsoleLog } from '../cli'; +import { type GlobalOptions, logger } from '../cli'; import { loadDb } from '../db'; import { loadEnvironment, promptEnvironment } from '../db/models/environment'; import type { UnitTest, UnitTestSuite } from '../db/models/types'; @@ -46,6 +46,16 @@ const createTestSuite = (dbSuite: UnitTestSuite, dbTests: UnitTest[]): TestSuite })), }); +const noConsoleLog = async (callback: () => Promise): Promise => { + const oldConsoleLog = console.log; + console.log = () => { }; + try { + return await callback(); + } finally { + console.log = oldConsoleLog; + } +}; + // Identifier can be the id or name of a workspace, apiSpec, or unit test suite export async function runInsomniaTests( identifier: string | null | undefined, diff --git a/packages/insomnia-inso/src/db/fixtures/git-repo/.insorc b/packages/insomnia-inso/src/db/fixtures/git-repo/.insorc new file mode 100644 index 000000000000..78753323645d --- /dev/null +++ b/packages/insomnia-inso/src/db/fixtures/git-repo/.insorc @@ -0,0 +1,11 @@ +options: + # loading data from an git repo + workingDir: packages/insomnia-inso/src/db/fixtures/git-repo + ci: false + verbose: true +scripts: + lintSpecPrompt: inso lint spec + lintSpecKey: inso lint spec spc_3b2850 + lintSpecName: inso lint spec "Imported Workspace" + exportSpec: inso export spec + runTest: inso run test diff --git a/packages/insomnia-inso/src/db/index.ts b/packages/insomnia-inso/src/db/index.ts index 2508be3beb06..83f56707afe4 100644 --- a/packages/insomnia-inso/src/db/index.ts +++ b/packages/insomnia-inso/src/db/index.ts @@ -77,7 +77,7 @@ export const getAbsolutePath = ({ workingDir, src }: { workingDir?: string; src? if (!hasWorkingDirOrSrc) { return getAppDataDir(getDefaultProductName()); } - return workingDir ? path.resolve(workingDir, src || '') : path.resolve('.', src || ''); + return workingDir ? path.resolve(workingDir, src || '') : path.resolve(process.cwd(), src || ''); }; export const loadDb = async ({ workingDir, diff --git a/packages/insomnia-inso/src/fixtures/.insorc-from-file-example.yaml b/packages/insomnia-inso/src/fixtures/.insorc-from-file-example.yaml index e235d52cd349..29fe1c1a62cb 100644 --- a/packages/insomnia-inso/src/fixtures/.insorc-from-file-example.yaml +++ b/packages/insomnia-inso/src/fixtures/.insorc-from-file-example.yaml @@ -3,6 +3,7 @@ options: workingDir: packages/insomnia-inso/src/db/fixtures/insomnia-v4 src: insomnia_v4.json ci: false + verbose: true scripts: lintSpecPrompt: inso lint spec lintSpecKey: inso lint spec spc_3b2850 diff --git a/packages/insomnia-inso/src/fixtures/.insorc-from-git-example.yaml b/packages/insomnia-inso/src/fixtures/.insorc-from-git-example.yaml index 21c6ae321639..78753323645d 100644 --- a/packages/insomnia-inso/src/fixtures/.insorc-from-git-example.yaml +++ b/packages/insomnia-inso/src/fixtures/.insorc-from-git-example.yaml @@ -2,6 +2,7 @@ options: # loading data from an git repo workingDir: packages/insomnia-inso/src/db/fixtures/git-repo ci: false + verbose: true scripts: lintSpecPrompt: inso lint spec lintSpecKey: inso lint spec spc_3b2850 diff --git a/packages/insomnia-inso/src/fixtures/.insorc-with-scripts.yaml b/packages/insomnia-inso/src/fixtures/.insorc-with-scripts.yaml index 670cd207cd1a..ee59f05f39ea 100644 --- a/packages/insomnia-inso/src/fixtures/.insorc-with-scripts.yaml +++ b/packages/insomnia-inso/src/fixtures/.insorc-with-scripts.yaml @@ -2,11 +2,9 @@ options: ci: false scripts: lint: inso lint spec "Designer Demo" - test: inso run test "Designer Demo" --env UnitTest --bail --reporter progress test:200s: inso test --testNamePattern 200 test:404s: inso test --testNamePattern 404 test:suite:math: inso run test uts_8783c30a24b24e9a851d96cce48bd1f2 --env UnitTest --bail --reporter progress test:suite:requests: inso run test uts_bce4af --env UnitTest --bail --reporter progress - invalid-script: blah blah "blah" diff --git a/packages/insomnia-inso/src/fixtures/.insorc.yaml b/packages/insomnia-inso/src/fixtures/.insorc.yaml index 70ee67b0acf1..dd7d5bb768f9 100644 --- a/packages/insomnia-inso/src/fixtures/.insorc.yaml +++ b/packages/insomnia-inso/src/fixtures/.insorc.yaml @@ -1,6 +1,7 @@ options: ci: false shouldBeIgnored: this should be ignored because it is not a global option + verbose: true scripts: lintSpec: inso lint spec exportSpec: inso export spec diff --git a/packages/insomnia-inso/src/get-options.test.ts b/packages/insomnia-inso/src/get-options.test.ts index 4a5ac2b9af59..6a3dbaf76626 100644 --- a/packages/insomnia-inso/src/get-options.test.ts +++ b/packages/insomnia-inso/src/get-options.test.ts @@ -1,48 +1,25 @@ import { describe, expect, it, jest } from '@jest/globals'; -import commander from 'commander'; import path from 'path'; -import { extractCommandOptions, getOptions, loadCosmiConfig } from './cli'; +import { loadCosmiConfig } from './cli'; jest.unmock('cosmiconfig'); const fixturesDir = path.join('src', 'fixtures'); -describe('extractCommandOptions()', () => { - it('should combine options from all commands into one object', () => { - const command = new commander.Command('command').exitOverride(); - command - .command('subCommand') - .option('-s, --subCmd') - .action(cmd => { - expect(extractCommandOptions(cmd)).toEqual({ - global: true, - subCmd: true, - }); - }); - const parent = new commander.Command() - .exitOverride() - .option('-g, --global') - .addCommand(command); - parent.parse('self inso command subCommand --global --subCmd'.split(' ')); - }); -}); - describe('loadCosmiConfig()', () => { it('should load .insorc-test.yaml config file in fixtures dir', async () => { const result = await loadCosmiConfig(path.join(fixturesDir, '.insorc-test.yaml')); expect(result).toEqual({ - __configFile: { - options: { - }, - scripts: { - exportSpec: 'inso export spec', - lintSpec: 'inso lint spec', - }, - filePath: path.resolve(fixturesDir, '.insorc-test.yaml'), + options: { }, + scripts: { + exportSpec: 'inso export spec', + lintSpec: 'inso lint spec', + }, + filePath: path.resolve(fixturesDir, '.insorc-test.yaml'), }); - expect(result.__configFile?.options?.shouldBeIgnored).toBe(undefined); + expect(result?.options?.shouldBeIgnored).toBe(undefined); }); it('should return empty object and report error if specified config file not found', async () => { @@ -62,95 +39,9 @@ describe('loadCosmiConfig()', () => { it('should return blank properties and ignore extra items if settings and scripts not found in file', async () => { const result = await loadCosmiConfig(path.join(fixturesDir, '.insorc-missing-properties.yaml')); expect(result).toEqual({ - __configFile: { - options: {}, - scripts: {}, - filePath: path.resolve(fixturesDir, '.insorc-missing-properties.yaml'), - }, - }); - }); -}); - -describe('getOptions', () => { - it('should load default options', async () => { - const commandOptions = { - opts: () => ({}), - }; - const defaultOptions = { - src: 'default', - }; - const result = await getOptions(commandOptions, defaultOptions); - expect(result).toEqual({ - src: 'default', - }); - }); - - it('should combine default options with command options, favouring command', async () => { - const commandOptions = { - opts: () => ({ - src: 'command', - }), - }; - const defaultOptions = { - src: 'default', - anotherDefault: '0', - }; - const result = await getOptions(commandOptions, defaultOptions); - expect(result).toEqual({ - src: 'command', - anotherDefault: '0', - }); - }); - - it('should combine config file options with default options, favouring config file', async () => { - // Will also load src/fixtures/.insorc-test.yaml - const commandOptions = { - opts: () => ({ - config: path.join(fixturesDir, '.insorc-test.yaml'), - }), - }; - const defaultOptions = { - src: 'defaultOption', - anotherDefault: '0', - }; - const result = await getOptions(commandOptions, defaultOptions); - expect(result).toEqual({ - src: 'defaultOption', - anotherDefault: '0', - config: path.join(fixturesDir, '.insorc-test.yaml'), - __configFile: { - options: { - }, - scripts: { - exportSpec: 'inso export spec', - lintSpec: 'inso lint spec', - }, - filePath: path.resolve(fixturesDir, '.insorc-test.yaml'), - }, - }); - }); - - it('should print error to console if config file not found', async () => { - const logSpy = jest.spyOn(console, 'log').mockImplementation(() => { }); - const errSpy = jest.spyOn(console, 'error').mockImplementation(() => { }); - const configFilePath = path.join(fixturesDir, '.insorc-not-found.yaml'); - // Will also load src/fixtures/.insorc-test.yaml - const commandOptions = { - opts: () => ({ - config: configFilePath, - }), - }; - const defaultOptions = { - src: 'default', - anotherDefault: '0', - }; - const result = await getOptions(commandOptions, defaultOptions); - expect(result).toEqual({ - src: 'default', - anotherDefault: '0', - config: configFilePath, + options: {}, + scripts: {}, + filePath: path.resolve(fixturesDir, '.insorc-missing-properties.yaml'), }); - expect(logSpy).toHaveBeenCalledWith(`Could not find config file at ${configFilePath}.`); - expect(errSpy).toHaveBeenCalled(); }); }); diff --git a/packages/insomnia-inso/src/write-file.test.ts b/packages/insomnia-inso/src/write-file.test.ts index 690f42aaa95a..75500a5b4e9a 100644 --- a/packages/insomnia-inso/src/write-file.test.ts +++ b/packages/insomnia-inso/src/write-file.test.ts @@ -42,13 +42,13 @@ describe('writeFileWithCliOptions', () => { const contents = 'contents'; const workingDir = 'working/dir'; const promise = writeFileWithCliOptions(output, contents, workingDir); - await expect(promise).resolves.toBe(path.normalize('working/dir/file.yaml')); + await expect(promise).resolves.toBe(path.resolve(process.cwd(), 'working/dir/file.yaml')); }); it('should ensure the output directory exists', async () => { const output = 'output/dir/file.yaml'; const contents = 'contents'; const workingDir = 'working/dir'; const result = await writeFileWithCliOptions(output, contents, workingDir); - expect(result).toEqual(path.normalize('working/dir/output/dir/file.yaml')); + expect(result).toEqual(path.resolve(process.cwd(), 'working/dir/output/dir/file.yaml')); }); }); diff --git a/packages/insomnia-inso/src/write-file.ts b/packages/insomnia-inso/src/write-file.ts index 63a288be5eb2..e7d2c0f8a591 100644 --- a/packages/insomnia-inso/src/write-file.ts +++ b/packages/insomnia-inso/src/write-file.ts @@ -9,7 +9,7 @@ export async function writeFileWithCliOptions( contents: string, workingDir?: string, ): Promise { - const outputPath = path.isAbsolute(output) ? output : path.join(workingDir || process.cwd(), output); + const outputPath = path.isAbsolute(output) ? output : path.resolve(workingDir || process.cwd(), output); try { await mkdir(path.dirname(outputPath), { recursive: true }); diff --git a/packages/insomnia-smoke-test/CLI.md b/packages/insomnia-smoke-test/CLI.md index 8cbbb4d9a917..369f5d1e0432 100644 --- a/packages/insomnia-smoke-test/CLI.md +++ b/packages/insomnia-smoke-test/CLI.md @@ -8,7 +8,7 @@ npm run test -w insomnia-inso # will default to insomnia app database $PWD/packages/insomnia-inso/bin/inso run test # will use config, useful for testing with fewer args -$PWD/packages/insomnia-inso/bin/inso script whatever --config packages/insomnia-inso/src/fixtures/.insorc.yaml +$PWD/packages/insomnia-inso/bin/inso -w packages/insomnia-inso/src/db/fixtures/git-repo script runTest ``` ## install node version of libcurl