From ee2941a51e3e926bf67dc9bbd0c3f5e53e98cb8b Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Thu, 22 Feb 2024 17:10:25 +0200 Subject: [PATCH 01/13] Replace console.log with process.stderr --- bin/ui5.cjs | 46 ++++++++------ lib/cli/base.js | 39 +++++++----- lib/cli/commands/add.js | 6 +- lib/cli/commands/init.js | 6 +- lib/cli/commands/remove.js | 6 +- lib/cli/commands/serve.js | 24 +++++--- lib/cli/commands/tree.js | 25 +++++--- lib/cli/commands/use.js | 6 +- lib/cli/commands/versions.js | 2 +- test/bin/ui5.js | 98 +++++++++++++++--------------- test/lib/cli/base.js | 52 ++++++++-------- test/lib/cli/commands/add.js | 22 ++++--- test/lib/cli/commands/config.js | 22 ++++--- test/lib/cli/commands/remove.js | 14 +++-- test/lib/cli/commands/serve.js | 4 +- test/lib/cli/commands/tree.js | 4 +- test/lib/cli/commands/use.js | 10 ++- test/lib/cli/middlewares/logger.js | 12 +++- 18 files changed, 234 insertions(+), 164 deletions(-) diff --git a/bin/ui5.cjs b/bin/ui5.cjs index 1c038497..11e9b735 100755 --- a/bin/ui5.cjs +++ b/bin/ui5.cjs @@ -25,25 +25,37 @@ const ui5 = { pkg.engines && pkg.engines.node && (!semver || !semver.satisfies(nodeVersion, pkg.engines.node, {includePrerelease: true})) ) { - console.log("==================== UNSUPPORTED NODE.JS VERSION ===================="); - console.log("You are using an unsupported version of Node.js"); - console.log("Detected version " + nodeVersion + " but " + pkg.name + " requires " + pkg.engines.node); - console.log(""); - console.log("=> Please upgrade to a supported version of Node.js to use this tool"); - console.log("====================================================================="); + process.stderr.write("==================== UNSUPPORTED NODE.JS VERSION ===================="); + process.stderr.write("\n"); + process.stderr.write("You are using an unsupported version of Node.js"); + process.stderr.write("\n"); + process.stderr.write("Detected version " + nodeVersion + + " but " + pkg.name + " requires " + pkg.engines.node); + process.stderr.write("\n\n"); + process.stderr.write("=> Please upgrade to a supported version of Node.js to use this tool"); + process.stderr.write("\n"); + process.stderr.write("====================================================================="); + process.stderr.write("\n"); return false; } if (semver && semver.prerelease(nodeVersion)) { - console.log("====================== UNSTABLE NODE.JS VERSION ====================="); - console.log("You are using an unstable version of Node.js"); - console.log("Detected Node.js version " + nodeVersion); - console.log(""); - console.log("=> Please note that an unstable version might cause unexpected"); - console.log(" behavior. For productive use please consider using a stable"); - console.log(" version of Node.js! For the release policy of Node.js, see"); - console.log(" https://nodejs.org/en/about/releases"); - console.log("====================================================================="); + process.stderr.write("====================== UNSTABLE NODE.JS VERSION ====================="); + process.stderr.write("\n"); + process.stderr.write("You are using an unstable version of Node.js"); + process.stderr.write("\n"); + process.stderr.write("Detected Node.js version " + nodeVersion); + process.stderr.write("\n\n"); + process.stderr.write("=> Please note that an unstable version might cause unexpected"); + process.stderr.write("\n"); + process.stderr.write(" behavior. For productive use please consider using a stable"); + process.stderr.write("\n"); + process.stderr.write(" version of Node.js! For the release policy of Node.js, see"); + process.stderr.write("\n"); + process.stderr.write(" https://nodejs.org/en/about/releases"); + process.stderr.write("\n"); + process.stderr.write("====================================================================="); + process.stderr.write("\n"); } return true; @@ -98,8 +110,8 @@ module.exports = ui5; if (process.env.NODE_ENV !== "test" || process.env.UI5_CLI_TEST_BIN_RUN_MAIN !== "false") { ui5.main().catch((err) => { - console.log("Fatal Error: Unable to initialize UI5 CLI"); - console.log(err); + process.stderr.write("Fatal Error: Unable to initialize UI5 CLI"); + process.stderr.write(err); process.exit(1); }); } diff --git a/lib/cli/base.js b/lib/cli/base.js index 7bc4893e..7a649616 100644 --- a/lib/cli/base.js +++ b/lib/cli/base.js @@ -91,37 +91,44 @@ export default function(cli) { ConsoleWriter.stop(); // Exception if (isLogLevelEnabled("error")) { - console.log(""); - console.log(chalk.bold.red("⚠️ Process Failed With Error")); + process.stderr.write("\n"); + process.stderr.write(chalk.bold.red("⚠️ Process Failed With Error")); - console.log(""); - console.log(chalk.underline("Error Message:")); - console.log(err.message); + process.stderr.write("\n\n"); + process.stderr.write(chalk.underline("Error Message:")); + process.stderr.write("\n"); + process.stderr.write(err.message); + process.stderr.write("\n"); // Unexpected errors should always be logged with stack trace const unexpectedErrors = ["SyntaxError", "ReferenceError", "TypeError"]; if (unexpectedErrors.includes(err.name) || isLogLevelEnabled("verbose")) { - console.log(""); - console.log(chalk.underline("Stack Trace:")); - console.log(err.stack); - console.log(""); - console.log( + process.stderr.write("\n\n"); + process.stderr.write(chalk.underline("Stack Trace:")); + process.stderr.write("\n"); + process.stderr.write(err.stack); + process.stderr.write("\n"); + process.stderr.write( chalk.dim( `If you think this is an issue of the UI5 Tooling, you might report it using the ` + `following URL: `) + chalk.dim.bold.underline(`https://github.com/SAP/ui5-tooling/issues/new/choose`)); + process.stderr.write("\n"); } else { - console.log(""); - console.log(chalk.dim( + process.stderr.write("\n\n"); + process.stderr.write(chalk.dim( `For details, execute the same command again with an additional '--verbose' parameter`)); + process.stderr.write("\n"); } } } else { // Yargs error - console.log(chalk.bold.yellow("Command Failed:")); - console.log(`${msg}`); - console.log(""); - console.log(chalk.dim(`See 'ui5 --help'`)); + process.stderr.write(chalk.bold.yellow("Command Failed:")); + process.stderr.write("\n"); + process.stderr.write(`${msg}`); + process.stderr.write("\n\n"); + process.stderr.write(chalk.dim(`See 'ui5 --help'`)); + process.stderr.write("\n"); } process.exit(1); }); diff --git a/lib/cli/commands/add.js b/lib/cli/commands/add.js index e1aa86b8..6589b648 100644 --- a/lib/cli/commands/add.js +++ b/lib/cli/commands/add.js @@ -75,7 +75,8 @@ addCommand.handler = async function(argv) { ); } } else { - console.log(`Updated configuration written to ${argv.config || "ui5.yaml"}`); + process.stderr.write(`Updated configuration written to ${argv.config || "ui5.yaml"}`); + process.stderr.write("\n"); let logMessage = `Added framework ${library} ${libraryNames.join(" ")} as`; if (development) { logMessage += " development"; @@ -83,7 +84,8 @@ addCommand.handler = async function(argv) { logMessage += " optional"; } logMessage += libraries.length === 1 ? " dependency": " dependencies"; - console.log(logMessage); + process.stderr.write(logMessage); + process.stderr.write("\n"); } }; diff --git a/lib/cli/commands/init.js b/lib/cli/commands/init.js index 7de0d987..220fdc79 100644 --- a/lib/cli/commands/init.js +++ b/lib/cli/commands/init.js @@ -23,8 +23,10 @@ initCommand.handler = async function() { const yaml = jsYaml.dump(projectConfig, {quotingType: `"`}); await writeFile(yamlPath, yaml); - console.log(`Wrote ui5.yaml to ${yamlPath}:\n`); - console.log(yaml); + process.stderr.write(`Wrote ui5.yaml to ${yamlPath}:`); + process.stderr.write("\n"); + process.stderr.write(yaml); + process.stderr.write("\n"); }; export default initCommand; diff --git a/lib/cli/commands/remove.js b/lib/cli/commands/remove.js index 261e154b..70fe9676 100644 --- a/lib/cli/commands/remove.js +++ b/lib/cli/commands/remove.js @@ -59,10 +59,12 @@ removeCommand.handler = async function(argv) { ); } } else { - console.log(`Updated configuration written to ${argv.config || "ui5.yaml"}`); + process.stderr.write(`Updated configuration written to ${argv.config || "ui5.yaml"}`); + process.stderr.write("\n"); let logMessage = `Removed framework ${library} ${libraryNames.join(" ")} as`; logMessage += libraries.length === 1 ? " dependency": " dependencies"; - console.log(logMessage); + process.stderr.write(logMessage); + process.stderr.write("\n"); } }; diff --git a/lib/cli/commands/serve.js b/lib/cli/commands/serve.js index f37efdc1..f5560903 100644 --- a/lib/cli/commands/serve.js +++ b/lib/cli/commands/serve.js @@ -150,20 +150,26 @@ serve.handler = async function(argv) { const protocol = h2 ? "https" : "http"; let browserUrl = protocol + "://localhost:" + actualPort; if (argv.acceptRemoteConnections) { - console.log(""); - console.log(chalk.bold("⚠️ This server is accepting connections from all hosts on your network")); - console.log(chalk.dim.underline("Please Note:")); - console.log(chalk.bold.dim( + process.stderr.write("\n"); + process.stderr.write(chalk.bold("⚠️ This server is accepting connections from all hosts on your network")); + process.stderr.write("\n"); + process.stderr.write(chalk.dim.underline("Please Note:")); + process.stderr.write("\n"); + process.stderr.write(chalk.bold.dim( "* This server is intended for development purposes only. Do not use it in production.")); - console.log(chalk.dim( + process.stderr.write("\n"); + process.stderr.write(chalk.dim( "* Vulnerable (custom-)middleware can pose a threat to your system when exposed to the network")); - console.log(chalk.dim( + process.stderr.write("\n"); + process.stderr.write(chalk.dim( "* The use of proxy-middleware with preconfigured credentials might enable unauthorized access " + "to a target system for third parties on your network")); - console.log(""); + process.stderr.write("\n\n"); } - console.log("Server started"); - console.log("URL: " + browserUrl); + process.stderr.write("Server started"); + process.stderr.write("\n"); + process.stderr.write("URL: " + browserUrl); + process.stderr.write("\n"); if (argv.open !== undefined) { if (typeof argv.open === "string") { diff --git a/lib/cli/commands/tree.js b/lib/cli/commands/tree.js index 94e4c22f..9767f92d 100644 --- a/lib/cli/commands/tree.js +++ b/lib/cli/commands/tree.js @@ -90,12 +90,13 @@ tree.handler = async function(argv) { if (project.isFrameworkProject()) { name = chalk.blue(name); } - console.log( + process.stderr.write( `${baseString}${connectorString} ${name} ` + `${project.getNamespace() ? chalk.inverse(project.getNamespace()) + " " : ""}` + chalk.dim(`(${project.getVersion()}, ${project.getType()}) `) + chalk.dim.italic(`${project.getRootPath()}`) ); + process.stderr.write("\n"); const lastIdx = dependencies.length - 1; const newConnectorIndices = [...connectorIndices]; @@ -109,7 +110,8 @@ tree.handler = async function(argv) { newConnectorIndices.forEach((idx) => { nextBaseString = `${nextBaseString.slice(0, idx)}│${nextBaseString.slice(idx + 1)}`; }); - console.log(`${nextBaseString}╰─ ${msg}`); + process.stderr.write(`${nextBaseString}╰─ ${msg}`); + process.stderr.write("\n"); return; } if (renderDeps) { @@ -121,7 +123,8 @@ tree.handler = async function(argv) { }); }); - console.log(chalk.bold.underline(`Dependencies (${projects.size}):`)); + process.stderr.write(chalk.bold.underline(`Dependencies (${projects.size}):`)); + process.stderr.write("\n"); if (argv.flat) { // Iterate over list of projects, rendering each individually // We need to transform the map into an array in order to know the index @@ -133,28 +136,32 @@ tree.handler = async function(argv) { // Recursively render the tree, starting with the first entry of the map projects.values().next().value.render(0, [], true); } - console.log(""); + process.stderr.write("\n"); const extensionNames = graph.getExtensionNames(); const extensionCount = extensionNames.length; - console.log(chalk.bold.underline(`Extensions (${extensionCount}):`)); + process.stderr.write(chalk.bold.underline(`Extensions (${extensionCount}):`)); + process.stderr.write("\n"); if (extensionCount) { const lastIdx = extensionCount - 1; extensionNames.forEach((extensionName, idx) => { const extension = graph.getExtension(extensionName); const connectorString = idx === lastIdx ? "╰─" : "├─"; - console.log( + process.stderr.write( `${connectorString} ${extensionName} ` + chalk.dim(`(${extension.getVersion()}, ${extension.getType()}) `) + chalk.dim.italic(`${extension.getRootPath()}`)); + process.stderr.write("\n"); }); } else { - console.log(chalk.italic(`None`)); + process.stderr.write(chalk.italic(`None`)); + process.stderr.write("\n"); } if (argv.perf) { - console.log(""); - console.log(chalk.blue( + process.stderr.write("\n"); + process.stderr.write(chalk.blue( `Dependency graph generation took ${chalk.bold(elapsedTime)}`)); + process.stderr.write("\n"); } }; diff --git a/lib/cli/commands/use.js b/lib/cli/commands/use.js index a8904cad..939a41cc 100644 --- a/lib/cli/commands/use.js +++ b/lib/cli/commands/use.js @@ -81,8 +81,10 @@ useCommand.handler = async function(argv) { throw new Error(`Internal error while updating ui5.yaml to ${usedFramework} version ${usedVersion}`); } } else { - console.log(`Updated configuration written to ${argv.config || "ui5.yaml"}`); - console.log(`This project is now using ${usedFramework} version ${usedVersion}`); + process.stderr.write(`Updated configuration written to ${argv.config || "ui5.yaml"}`); + process.stderr.write("\n"); + process.stderr.write(`This project is now using ${usedFramework} version ${usedVersion}`); + process.stderr.write("\n"); } }; diff --git a/lib/cli/commands/versions.js b/lib/cli/commands/versions.js index 0e671d27..87a3f2c1 100644 --- a/lib/cli/commands/versions.js +++ b/lib/cli/commands/versions.js @@ -34,7 +34,7 @@ versions.handler = async function() { }) )).join("\n"); - console.log(`\n${output}\n`); + process.stderr.write(`\n${output}\n\n`); }; export default versions; diff --git a/test/bin/ui5.js b/test/bin/ui5.js index ee1a85cc..1fb6f806 100644 --- a/test/bin/ui5.js +++ b/test/bin/ui5.js @@ -34,7 +34,7 @@ test.before(() => { test.beforeEach(async (t) => { const sinon = t.context.sinon = sinonGlobal.createSandbox(); - t.context.consoleLogStub = sinon.stub(console, "log"); + t.context.processStderrWriteStub = sinon.stub(process.stderr, "write"); t.context.consoleInfoStub = sinon.stub(console, "info"); t.context.originalArgv = process.argv; process.env.UI5_CLI_TEST_BIN_RUN_MAIN = "false"; // prevent automatic execution of main function @@ -62,7 +62,7 @@ test.afterEach.always((t) => { }); test.serial("checkRequirements: Using supported Node.js version", (t) => { - const {consoleLogStub} = t.context; + const {processStderrWriteStub} = t.context; const {checkRequirements} = require("../../bin/ui5.cjs"); @@ -77,11 +77,11 @@ test.serial("checkRequirements: Using supported Node.js version", (t) => { }); t.true(returnValue); - t.is(consoleLogStub.callCount, 0, "console.log should not be called"); + t.is(processStderrWriteStub.callCount, 0, "console.log should not be called"); }); test.serial("checkRequirements: Using unsupported Node.js version", (t) => { - const {consoleLogStub} = t.context; + const {processStderrWriteStub} = t.context; const {checkRequirements} = require("../../bin/ui5.cjs"); @@ -96,24 +96,23 @@ test.serial("checkRequirements: Using unsupported Node.js version", (t) => { }); t.false(returnValue); - t.is(consoleLogStub.callCount, 6, "console.log should be called 6 times"); + t.is(processStderrWriteStub.callCount, 10, "console.log should be called 6 times"); - t.deepEqual(consoleLogStub.getCall(0).args, + t.deepEqual(processStderrWriteStub.getCall(0).args, ["==================== UNSUPPORTED NODE.JS VERSION ===================="]); - t.deepEqual(consoleLogStub.getCall(1).args, + t.deepEqual(processStderrWriteStub.getCall(2).args, ["You are using an unsupported version of Node.js"]); - t.deepEqual(consoleLogStub.getCall(2).args, + t.deepEqual(processStderrWriteStub.getCall(4).args, [`Detected version v10.0.0 but ui5-cli-engines-test requires ^999`]); - t.deepEqual(consoleLogStub.getCall(3).args, - [""]); - t.deepEqual(consoleLogStub.getCall(4).args, + t.deepEqual(processStderrWriteStub.getCall(5).args, ["\n\n"]); + t.deepEqual(processStderrWriteStub.getCall(6).args, ["=> Please upgrade to a supported version of Node.js to use this tool"]); - t.deepEqual(consoleLogStub.getCall(5).args, + t.deepEqual(processStderrWriteStub.getCall(8).args, ["====================================================================="]); }); test.serial("checkRequirements: logs warning when using pre-release Node.js version", (t) => { - const {consoleLogStub} = t.context; + const {processStderrWriteStub} = t.context; const {checkRequirements} = require("../../bin/ui5.cjs"); @@ -128,30 +127,29 @@ test.serial("checkRequirements: logs warning when using pre-release Node.js vers }); t.true(returnValue); - t.is(consoleLogStub.callCount, 9, "console.log should be called 8 times"); + t.is(processStderrWriteStub.callCount, 16, "console.log should be called 16 times"); - t.is(consoleLogStub.getCall(0).args[0], + t.is(processStderrWriteStub.getCall(0).args[0], "====================== UNSTABLE NODE.JS VERSION ====================="); - t.is(consoleLogStub.getCall(1).args[0], + t.is(processStderrWriteStub.getCall(2).args[0], "You are using an unstable version of Node.js"); - t.is(consoleLogStub.getCall(2).args[0], + t.is(processStderrWriteStub.getCall(4).args[0], "Detected Node.js version v17.0.0-v8-canary202108258414d1aed8"); - t.is(consoleLogStub.getCall(3).args[0], - ""); - t.is(consoleLogStub.getCall(4).args[0], + t.is(processStderrWriteStub.getCall(5).args[0], "\n\n"); + t.is(processStderrWriteStub.getCall(6).args[0], "=> Please note that an unstable version might cause unexpected"); - t.is(consoleLogStub.getCall(5).args[0], + t.is(processStderrWriteStub.getCall(8).args[0], " behavior. For productive use please consider using a stable"); - t.is(consoleLogStub.getCall(6).args[0], + t.is(processStderrWriteStub.getCall(10).args[0], " version of Node.js! For the release policy of Node.js, see"); - t.is(consoleLogStub.getCall(7).args[0], + t.is(processStderrWriteStub.getCall(12).args[0], " https://nodejs.org/en/about/releases"); - t.is(consoleLogStub.getCall(8).args[0], + t.is(processStderrWriteStub.getCall(14).args[0], "====================================================================="); }); test.serial("invokeLocalInstallation: Invokes local installation when found", async (t) => { - const {consoleLogStub, consoleInfoStub} = t.context; + const {processStderrWriteStub, consoleInfoStub} = t.context; importLocalStub.returns({}); @@ -161,7 +159,7 @@ test.serial("invokeLocalInstallation: Invokes local installation when found", as t.true(returnValue); - t.is(consoleLogStub.callCount, 0, "console.log should not be called"); + t.is(processStderrWriteStub.callCount, 0, "console.log should not be called"); t.is(consoleInfoStub.callCount, 2, "console.info should be called 2 times"); t.deepEqual(consoleInfoStub.getCall(0).args, ["INFO: Using local ui5-cli-test installation"]); @@ -175,7 +173,7 @@ test.serial("invokeLocalInstallation: Invokes local installation when found", as }); test.serial("invokeLocalInstallation: Invokes local installation when found (/w --verbose)", async (t) => { - const {consoleLogStub, consoleInfoStub} = t.context; + const {processStderrWriteStub, consoleInfoStub} = t.context; importLocalStub.returns({}); @@ -188,7 +186,7 @@ test.serial("invokeLocalInstallation: Invokes local installation when found (/w t.true(returnValue); - t.is(consoleLogStub.callCount, 0, "console.log should not be called"); + t.is(processStderrWriteStub.callCount, 0, "console.log should not be called"); t.is(consoleInfoStub.callCount, 3, "console.info should be called 3 times"); t.deepEqual(consoleInfoStub.getCall(0).args, [ @@ -207,7 +205,7 @@ test.serial("invokeLocalInstallation: Invokes local installation when found (/w }); test.serial("invokeLocalInstallation: Doesn't invoke local installation when UI5_CLI_NO_LOCAL is set", async (t) => { - const {consoleLogStub, consoleInfoStub} = t.context; + const {processStderrWriteStub, consoleInfoStub} = t.context; process.env.UI5_CLI_NO_LOCAL = "true"; @@ -217,14 +215,14 @@ test.serial("invokeLocalInstallation: Doesn't invoke local installation when UI5 t.false(returnValue); - t.is(consoleLogStub.callCount, 0, "console.log should not be called"); + t.is(processStderrWriteStub.callCount, 0, "console.log should not be called"); t.is(consoleInfoStub.callCount, 0, "console.info should not be called"); t.is(importLocalStub.callCount, 0, "import-local should not be called"); }); test.serial("invokeLocalInstallation: Doesn't invoke local installation when it is not found", async (t) => { - const {consoleLogStub, consoleInfoStub} = t.context; + const {processStderrWriteStub, consoleInfoStub} = t.context; importLocalStub.returns(undefined); @@ -234,14 +232,14 @@ test.serial("invokeLocalInstallation: Doesn't invoke local installation when it t.false(returnValue); - t.is(consoleLogStub.callCount, 0, "console.log should not be called"); + t.is(processStderrWriteStub.callCount, 0, "console.log should not be called"); t.is(consoleInfoStub.callCount, 0, "console.info should not be called"); t.is(importLocalStub.callCount, 1, "import-local should be called"); }); test.serial("main (unsupported Node.js version)", async (t) => { - const {sinon, consoleLogStub} = t.context; + const {sinon, processStderrWriteStub} = t.context; const processExit = new Promise((resolve) => { const processExitStub = sinon.stub(process, "exit"); @@ -263,7 +261,7 @@ test.serial("main (unsupported Node.js version)", async (t) => { const errorCode = await processExit; t.is(errorCode, 1); - t.is(consoleLogStub.callCount, 0); + t.is(processStderrWriteStub.callCount, 0); t.is(ui5.checkRequirements.callCount, 1); t.is(ui5.invokeLocalInstallation.callCount, 0); @@ -271,7 +269,7 @@ test.serial("main (unsupported Node.js version)", async (t) => { }); test.serial("main (invocation of local installation)", async (t) => { - const {sinon, consoleLogStub} = t.context; + const {sinon, processStderrWriteStub} = t.context; const processExitStub = sinon.stub(process, "exit"); @@ -284,7 +282,7 @@ test.serial("main (invocation of local installation)", async (t) => { await main(); t.is(processExitStub.callCount, 0); - t.is(consoleLogStub.callCount, 0); + t.is(processStderrWriteStub.callCount, 0); t.is(ui5.invokeLocalInstallation.callCount, 1); t.is(ui5.invokeCLI.callCount, 0); @@ -297,7 +295,7 @@ test.serial("integration: main / invokeCLI", async (t) => { // Therefore this test is an integration test that really invokes the CLI / yargs to // fail with an unknown command error - const {sinon, consoleLogStub} = t.context; + const {sinon, processStderrWriteStub} = t.context; const processExit = new Promise((resolve) => { const processExitStub = sinon.stub(process, "exit"); @@ -316,14 +314,14 @@ test.serial("integration: main / invokeCLI", async (t) => { const errorCode = await processExit; t.is(errorCode, 1); - t.is(consoleLogStub.callCount, 4); + t.is(processStderrWriteStub.callCount, 6); - t.deepEqual(consoleLogStub.getCall(0).args, [chalk.bold.yellow("Command Failed:")], "Correct error log"); - t.deepEqual(consoleLogStub.getCall(1).args, ["Unknown argument: foo"], "Correct error log"); + t.deepEqual(processStderrWriteStub.getCall(0).args, [chalk.bold.yellow("Command Failed:")], "Correct error log"); + t.deepEqual(processStderrWriteStub.getCall(2).args, ["Unknown argument: foo"], "Correct error log"); }); test.serial("integration: Executing main when required as main module", async (t) => { - const {sinon, consoleLogStub} = t.context; + const {sinon, processStderrWriteStub} = t.context; const processExit = new Promise((resolve) => { const processExitStub = sinon.stub(process, "exit"); @@ -342,14 +340,14 @@ test.serial("integration: Executing main when required as main module", async (t const errorCode = await processExit; t.is(errorCode, 1); - t.is(consoleLogStub.callCount, 4); + t.is(processStderrWriteStub.callCount, 6); - t.deepEqual(consoleLogStub.getCall(0).args, [chalk.bold.yellow("Command Failed:")], "Correct error log"); - t.deepEqual(consoleLogStub.getCall(1).args, ["Unknown argument: foo"], "Correct error log"); + t.deepEqual(processStderrWriteStub.getCall(0).args, [chalk.bold.yellow("Command Failed:")], "Correct error log"); + t.deepEqual(processStderrWriteStub.getCall(2).args, ["Unknown argument: foo"], "Correct error log"); }); test.serial("integration: Executing main when required as main module (catch initialize error)", async (t) => { - const {sinon, consoleLogStub} = t.context; + const {sinon, processStderrWriteStub} = t.context; const processExit = new Promise((resolve) => { const processExitStub = sinon.stub(process, "exit"); @@ -372,10 +370,10 @@ test.serial("integration: Executing main when required as main module (catch ini const errorCode = await processExit; t.is(errorCode, 1); - t.is(consoleLogStub.callCount, 2); + t.is(processStderrWriteStub.callCount, 2); - t.deepEqual(consoleLogStub.getCall(0).args, ["Fatal Error: Unable to initialize UI5 CLI"]); - t.is(consoleLogStub.getCall(1).args.length, 1); - t.true(consoleLogStub.getCall(1).args[0] instanceof Error); - t.is(consoleLogStub.getCall(1).args[0].message, "TEST: Unable to invoke CLI"); + t.deepEqual(processStderrWriteStub.getCall(0).args, ["Fatal Error: Unable to initialize UI5 CLI"]); + t.is(processStderrWriteStub.getCall(1).args.length, 1); + t.true(processStderrWriteStub.getCall(1).args[0] instanceof Error); + t.is(processStderrWriteStub.getCall(1).args[0].message, "TEST: Unable to invoke CLI"); }); diff --git a/test/lib/cli/base.js b/test/lib/cli/base.js index f9ce0f3d..549719c6 100644 --- a/test/lib/cli/base.js +++ b/test/lib/cli/base.js @@ -15,7 +15,7 @@ const ui5Cli = path.join(__dirname, "..", "..", "..", "bin", "ui5.cjs"); const ui5 = (args, options = {}) => execa(ui5Cli, args, options); test.beforeEach(async (t) => { - t.context.consoleLogStub = sinon.stub(console, "log"); + t.context.consoleLogStub = sinon.stub(process.stderr, "write"); t.context.isLogLevelEnabledStub = sinon.stub(); t.context.isLogLevelEnabledStub.withArgs("error").returns(true); @@ -37,13 +37,13 @@ test.afterEach.always((t) => { }); test.serial("ui5 --version", async (t) => { - const {stdout} = await ui5(["--version"]); - t.is(stdout, `${pkg.version} (from ${ui5Cli})`); + const {stderr: stderr} = await ui5(["--version"]); + t.is(stderr, `${pkg.version} (from ${ui5Cli})`); }); test.serial("ui5 -v", async (t) => { - const {stdout} = await ui5(["-v"]); - t.is(stdout, `${pkg.version} (from ${ui5Cli})`); + const {stderr} = await ui5(["-v"]); + t.is(stderr, `${pkg.version} (from ${ui5Cli})`); }); test.serial("Handle multiple options", async (t) => { @@ -80,11 +80,11 @@ test.serial("Yargs error handling", async (t) => { t.is(errorCode, 1, "Should exit with error code 1"); t.is(consoleWriterStopStub.callCount, 0, "ConsoleWriter.stop did not get called"); - t.is(consoleLogStub.callCount, 4); + t.is(consoleLogStub.callCount, 6); t.deepEqual(consoleLogStub.getCall(0).args, [chalk.bold.yellow("Command Failed:")], "Correct error log"); - t.deepEqual(consoleLogStub.getCall(1).args, ["Unknown argument: invalid"], "Correct error log"); - t.deepEqual(consoleLogStub.getCall(2).args, [""], "Correct error log"); - t.deepEqual(consoleLogStub.getCall(3).args, [ + t.deepEqual(consoleLogStub.getCall(2).args, ["Unknown argument: invalid"], "Correct error log"); + t.deepEqual(consoleLogStub.getCall(3).args, ["\n\n"], "Correct error log"); + t.deepEqual(consoleLogStub.getCall(4).args, [ chalk.dim(`See 'ui5 --help'`) ], "Correct error log"); }); @@ -123,12 +123,12 @@ test.serial("Exception error handling", async (t) => { t.is(errorCode, 1, "Should exit with error code 1"); t.is(consoleWriterStopStub.callCount, 1, "ConsoleWriter.stop got called once"); - t.is(consoleLogStub.callCount, 7); + t.is(consoleLogStub.callCount, 10); t.deepEqual(consoleLogStub.getCall(1).args, [chalk.bold.red("⚠️ Process Failed With Error")], "Correct error log"); t.deepEqual(consoleLogStub.getCall(3).args, [chalk.underline("Error Message:")], "Correct error log"); - t.deepEqual(consoleLogStub.getCall(4).args, + t.deepEqual(consoleLogStub.getCall(5).args, ["Some error from foo command"], "Correct error log"); - t.deepEqual(consoleLogStub.getCall(6).args, [chalk.dim( + t.deepEqual(consoleLogStub.getCall(8).args, [chalk.dim( `For details, execute the same command again with an additional '--verbose' parameter`)], "Correct error log"); }); @@ -204,17 +204,17 @@ test.serial("Exception error handling with verbose logging", async (t) => { const errorCode = await processExit; t.is(errorCode, 1, "Should exit with error code 1"); - t.is(consoleLogStub.callCount, 10); + t.is(consoleLogStub.callCount, 14); t.deepEqual(consoleLogStub.getCall(1).args, [chalk.bold.red("⚠️ Process Failed With Error")], "Correct error log"); t.deepEqual(consoleLogStub.getCall(3).args, [chalk.underline("Error Message:")], "Correct error log"); - t.deepEqual(consoleLogStub.getCall(4).args, + t.deepEqual(consoleLogStub.getCall(5).args, ["Some error from foo command"], "Correct error log"); - t.deepEqual(consoleLogStub.getCall(6).args, [chalk.underline("Stack Trace:")], "Correct error log"); - t.is(consoleLogStub.getCall(7).args.length, 1); - t.true(consoleLogStub.getCall(7).args[0] + t.deepEqual(consoleLogStub.getCall(8).args, [chalk.underline("Stack Trace:")], "Correct error log"); + t.is(consoleLogStub.getCall(10).args.length, 1); + t.true(consoleLogStub.getCall(10).args[0] .startsWith("Error: Some error from foo command"), "Correct error log"); - t.deepEqual(consoleLogStub.getCall(consoleLogStub.callCount - 1).args, + t.deepEqual(consoleLogStub.getCall(consoleLogStub.callCount - 2).args, [chalk.dim( `If you think this is an issue of the UI5 Tooling, you might report it using the ` + `following URL: `) + @@ -257,17 +257,17 @@ test.serial("Unexpected error handling", async (t) => { t.is(errorCode, 1, "Should exit with error code 1"); t.is(consoleWriterStopStub.callCount, 0, "ConsoleWriter.stop did not get called"); - t.is(consoleLogStub.callCount, 10); + t.is(consoleLogStub.callCount, 14); t.deepEqual(consoleLogStub.getCall(1).args, [chalk.bold.red("⚠️ Process Failed With Error")], "Correct error log"); t.deepEqual(consoleLogStub.getCall(3).args, [chalk.underline("Error Message:")], "Correct error log"); - t.deepEqual(consoleLogStub.getCall(4).args, + t.deepEqual(consoleLogStub.getCall(5).args, ["Cannot do this"], "Correct error log"); - t.deepEqual(consoleLogStub.getCall(6).args, [chalk.underline("Stack Trace:")], "Correct error log"); - t.is(consoleLogStub.getCall(7).args.length, 1); - t.true(consoleLogStub.getCall(7).args[0] + t.deepEqual(consoleLogStub.getCall(8).args, [chalk.underline("Stack Trace:")], "Correct error log"); + t.is(consoleLogStub.getCall(10).args.length, 1); + t.true(consoleLogStub.getCall(10).args[0] .startsWith("TypeError: Cannot do this"), "Correct error log"); - t.deepEqual(consoleLogStub.getCall(consoleLogStub.callCount - 1).args, + t.deepEqual(consoleLogStub.getCall(consoleLogStub.callCount - 2).args, [chalk.dim( `If you think this is an issue of the UI5 Tooling, you might report it using the ` + `following URL: `) + @@ -276,8 +276,8 @@ test.serial("Unexpected error handling", async (t) => { }); test.serial("ui5 --no-update-notifier", async (t) => { - const {stdout, failed} = await ui5(["versions", "--no-update-notifier"]); - t.regex(stdout, /@ui5\/cli:/, "Output includes version information"); + const {stderr, failed} = await ui5(["versions", "--no-update-notifier"]); + t.regex(stderr, /@ui5\/cli:/, "Output includes version information"); t.false(failed, "Command should not fail"); }); diff --git a/test/lib/cli/commands/add.js b/test/lib/cli/commands/add.js index b5ccf09b..76a291de 100644 --- a/test/lib/cli/commands/add.js +++ b/test/lib/cli/commands/add.js @@ -24,10 +24,10 @@ async function assertAddHandler(t, {argv, expectedLibraries, expectedConsoleLog} }], "Add function should be called with expected args"); - t.is(t.context.consoleLogStub.callCount, expectedConsoleLog.length, + t.is(t.context.processStderrWriteStub.callCount, expectedConsoleLog.length, "console.log should be called " + expectedConsoleLog.length + " times"); expectedConsoleLog.forEach((expectedLog, i) => { - t.deepEqual(t.context.consoleLogStub.getCall(i).args, [expectedLog], + t.deepEqual(t.context.processStderrWriteStub.getCall(i).args, [expectedLog], "console.log should be called with expected string on call index " + i); }); } @@ -49,7 +49,7 @@ async function assertFailingYamlUpdateAddHandler(t, {argv, expectedMessage}) { } test.beforeEach((t) => { - t.context.consoleLogStub = sinon.stub(console, "log"); + t.context.processStderrWriteStub = sinon.stub(process.stderr, "write"); }); test.afterEach.always((t) => { @@ -63,7 +63,9 @@ test.serial("Accepts single library", async (t) => { expectedLibraries: [{name: "sap.ui.lib1"}], expectedConsoleLog: [ "Updated configuration written to ui5.yaml", - "Added framework library sap.ui.lib1 as dependency" + "\n", + "Added framework library sap.ui.lib1 as dependency", + "\n", ] }); }); @@ -74,7 +76,9 @@ test.serial("Accepts multiple libraries", async (t) => { expectedLibraries: [{name: "sap.ui.lib1"}, {name: "sap.ui.lib2"}], expectedConsoleLog: [ "Updated configuration written to ui5.yaml", - "Added framework libraries sap.ui.lib1 sap.ui.lib2 as dependencies" + "\n", + "Added framework libraries sap.ui.lib1 sap.ui.lib2 as dependencies", + "\n", ] }); }); @@ -100,7 +104,9 @@ test.serial("Accepts multiple libraries (--development)", async (t) => { ], expectedConsoleLog: [ "Updated configuration written to ui5.yaml", - "Added framework libraries sap.ui.lib1 sap.ui.lib2 as development dependencies" + "\n", + "Added framework libraries sap.ui.lib1 sap.ui.lib2 as development dependencies", + "\n" ] }); }); @@ -126,7 +132,9 @@ test.serial("Accepts multiple libraries (--optional)", async (t) => { ], expectedConsoleLog: [ "Updated configuration written to ui5.yaml", - "Added framework libraries sap.ui.lib1 sap.ui.lib2 as optional dependencies" + "\n", + "Added framework libraries sap.ui.lib1 sap.ui.lib2 as optional dependencies", + "\n" ] }); }); diff --git a/test/lib/cli/commands/config.js b/test/lib/cli/commands/config.js index 05cf77f8..1b57e0b2 100644 --- a/test/lib/cli/commands/config.js +++ b/test/lib/cli/commands/config.js @@ -227,6 +227,7 @@ test.serial("ui5 config set false should update the configuration", async (t) => test.serial("ui5 config invalid option", async (t) => { await t.throwsAsync(ui5(["config", "set", "_invalid_key_", "https://_snapshot_endpoint_"]), { message: ($) => { + // stderr might include debug information return $.includes("Command failed with exit code 1") && $.includes("Invalid values") && $.includes(`Given: "_invalid_key_", Choices: "`); @@ -236,22 +237,27 @@ test.serial("ui5 config invalid option", async (t) => { test.serial("ui5 config empty option", async (t) => { await t.throwsAsync(ui5(["config", "set"]), { - message: ($) => stripAnsi($) === - `Command failed with exit code 1: ${ui5Cli} config set -Command Failed: + message: ($) => { + const message = stripAnsi($); + // stderr might include debug information + return message.includes(`Command failed with exit code 1: ${ui5Cli} config set`) && + message.includes(`Command Failed: Not enough non-option arguments: got 0, need at least 1 -See 'ui5 --help'` +See 'ui5 --help'`); + } }); }); test.serial("ui5 config unknown command", async (t) => { await t.throwsAsync(ui5(["config", "foo"]), { - message: ($) => stripAnsi($) === - `Command failed with exit code 1: ${ui5Cli} config foo -Command Failed: + message: ($) => { + const message = stripAnsi($); + return message.includes(`Command failed with exit code 1: ${ui5Cli} config foo`) && + message.includes(`Command Failed: Unknown argument: foo -See 'ui5 --help'` +See 'ui5 --help'`); + } }); }); diff --git a/test/lib/cli/commands/remove.js b/test/lib/cli/commands/remove.js index 360534e1..f229ebf0 100644 --- a/test/lib/cli/commands/remove.js +++ b/test/lib/cli/commands/remove.js @@ -50,7 +50,7 @@ async function assertFailingYamlUpdateRemoveHandler(t, {argv, expectedMessage}) } test.beforeEach((t) => { - t.context.consoleLogStub = sinon.stub(console, "log"); + t.context.consoleLogStub = sinon.stub(process.stderr, "write"); }); test.afterEach.always((t) => { @@ -64,7 +64,9 @@ test.serial("Accepts single library", async (t) => { expectedLibraries: [{name: "sap.ui.lib1"}], expectedConsoleLog: [ "Updated configuration written to ui5.yaml", - "Removed framework library sap.ui.lib1 as dependency" + "\n", + "Removed framework library sap.ui.lib1 as dependency", + "\n" ] }); }); @@ -75,7 +77,9 @@ test.serial("Accepts multiple libraries", async (t) => { expectedLibraries: [{name: "sap.ui.lib1"}, {name: "sap.ui.lib2"}], expectedConsoleLog: [ "Updated configuration written to ui5.yaml", - "Removed framework libraries sap.ui.lib1 sap.ui.lib2 as dependencies" + "\n", + "Removed framework libraries sap.ui.lib1 sap.ui.lib2 as dependencies", + "\n" ] }); }); @@ -86,7 +90,9 @@ test.serial("Accepts multiple libraries duplicates", async (t) => { expectedLibraries: [{name: "sap.ui.lib1"}, {name: "sap.ui.lib2"}], expectedConsoleLog: [ "Updated configuration written to ui5.yaml", - "Removed framework libraries sap.ui.lib1 sap.ui.lib2 as dependencies" + "\n", + "Removed framework libraries sap.ui.lib1 sap.ui.lib2 as dependencies", + "\n" ] }); }); diff --git a/test/lib/cli/commands/serve.js b/test/lib/cli/commands/serve.js index 4b0fc883..8789eb90 100644 --- a/test/lib/cli/commands/serve.js +++ b/test/lib/cli/commands/serve.js @@ -59,9 +59,9 @@ test.beforeEach(async (t) => { t.context.consoleOutput = ""; - t.context.consoleLog = sinon.stub(console, "log").callsFake((message) => { + t.context.processStderrWrite = sinon.stub(process.stderr, "write").callsFake((message) => { // NOTE: This fake impl only supports one string arg passed to console.log - t.context.consoleOutput += message + "\n"; + t.context.consoleOutput += message; }); t.context.open = sinon.stub(); diff --git a/test/lib/cli/commands/tree.js b/test/lib/cli/commands/tree.js index a7ad189f..a3792023 100644 --- a/test/lib/cli/commands/tree.js +++ b/test/lib/cli/commands/tree.js @@ -38,9 +38,9 @@ test.beforeEach(async (t) => { }; t.context.consoleOutput = ""; - t.context.consoleLog = sinon.stub(console, "log").callsFake((message) => { + t.context.processStderrWrite = sinon.stub(process.stderr, "write").callsFake((message) => { // NOTE: This fake impl only supports one string arg passed to console.log - t.context.consoleOutput += message + "\n"; + t.context.consoleOutput += message; }); t.context.tree = await esmock.p("../../../../lib/cli/commands/tree.js", { diff --git a/test/lib/cli/commands/use.js b/test/lib/cli/commands/use.js index b6b20cb0..57cdeb6a 100644 --- a/test/lib/cli/commands/use.js +++ b/test/lib/cli/commands/use.js @@ -55,7 +55,7 @@ async function assertFailingYamlUpdateUseHandler(t, {argv, expectedMessage}) { } test.beforeEach(async (t) => { - t.context.consoleLogStub = sinon.stub(console, "log"); + t.context.consoleLogStub = sinon.stub(process.stderr, "write"); t.context.frameworkUseStub = sinon.stub(); @@ -271,7 +271,9 @@ test.serial("Logs framework name, version and default config path when updating const expectedConsoleLog = [ "Updated configuration written to ui5.yaml", - "This project is now using SAPUI5 version 1.76.0" + "\n", + "This project is now using SAPUI5 version 1.76.0", + "\n" ]; t.is(t.context.consoleLogStub.callCount, expectedConsoleLog.length, @@ -295,7 +297,9 @@ test.serial("Logs framework name, version and custom config path when updating c const expectedConsoleLog = [ "Updated configuration written to /path/to/ui5.yaml", - "This project is now using SAPUI5 version 1.76.0" + "\n", + "This project is now using SAPUI5 version 1.76.0", + "\n" ]; t.is(t.context.consoleLogStub.callCount, expectedConsoleLog.length, diff --git a/test/lib/cli/middlewares/logger.js b/test/lib/cli/middlewares/logger.js index ed688a6d..a66396ad 100644 --- a/test/lib/cli/middlewares/logger.js +++ b/test/lib/cli/middlewares/logger.js @@ -102,7 +102,15 @@ const ui5 = (args, options = {}) => execa(ui5Cli, args, options); test("ui5 --verbose", async (t) => { // Using "versions" as a command, as the --verbose flag can't be used standalone const {stderr} = await ui5(["versions", "--verbose"]); - t.is(stripAnsi(stderr), + t.true(stripAnsi(stderr).includes( // Debugger info is also included into the message. We need to exclude it `verb cli:middlewares:base using @ui5/cli version ${pkg.version} (from ${ui5Cli})\n`+ - `verb cli:middlewares:base using node version ${process.version}`); + `verb cli:middlewares:base using node version ${process.version}\n` + + `\n` + + `@ui5/cli: ${pkg.version}\n` + + `@ui5/builder: ${pkg.version}\n` + + `@ui5/server: ${pkg.version}\n` + + `@ui5/fs: ${pkg.version}\n` + + `@ui5/project: ${pkg.version}\n` + + `@ui5/logger: ${pkg.version}\n` + )); }); From b9841ebf43b0e254e63aa6b05fcab696ca527e8c Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Thu, 22 Feb 2024 17:37:13 +0200 Subject: [PATCH 02/13] Fix tests --- bin/ui5.cjs | 11 ++++++----- test/bin/ui5.js | 33 ++++++++++++++------------------- test/lib/cli/base.js | 10 +++++----- 3 files changed, 25 insertions(+), 29 deletions(-) diff --git a/bin/ui5.cjs b/bin/ui5.cjs index 11e9b735..27877e3b 100755 --- a/bin/ui5.cjs +++ b/bin/ui5.cjs @@ -77,13 +77,14 @@ const ui5 = { return false; } if (process.argv.includes("--verbose")) { - console.info(`INFO: This project contains an individual ${pkg.name} installation which ` + + process.stderr.write(`INFO: This project contains an individual ${pkg.name} installation which ` + "will be used over the global one."); - console.info("See https://github.com/SAP/ui5-cli#local-vs-global-installation for details."); - console.info(""); + process.stderr.write("\n"); + process.stderr.write("See https://github.com/SAP/ui5-cli#local-vs-global-installation for details."); + process.stderr.write("\n\n"); } else { - console.info(`INFO: Using local ${pkg.name} installation`); - console.info(""); + process.stderr.write(`INFO: Using local ${pkg.name} installation`); + process.stderr.write("\n\n"); } return true; }, diff --git a/test/bin/ui5.js b/test/bin/ui5.js index 1fb6f806..fbbac297 100644 --- a/test/bin/ui5.js +++ b/test/bin/ui5.js @@ -35,7 +35,6 @@ test.before(() => { test.beforeEach(async (t) => { const sinon = t.context.sinon = sinonGlobal.createSandbox(); t.context.processStderrWriteStub = sinon.stub(process.stderr, "write"); - t.context.consoleInfoStub = sinon.stub(console, "info"); t.context.originalArgv = process.argv; process.env.UI5_CLI_TEST_BIN_RUN_MAIN = "false"; // prevent automatic execution of main function @@ -77,7 +76,7 @@ test.serial("checkRequirements: Using supported Node.js version", (t) => { }); t.true(returnValue); - t.is(processStderrWriteStub.callCount, 0, "console.log should not be called"); + t.is(processStderrWriteStub.callCount, 0, "stderr info should not be provided"); }); test.serial("checkRequirements: Using unsupported Node.js version", (t) => { @@ -149,7 +148,7 @@ test.serial("checkRequirements: logs warning when using pre-release Node.js vers }); test.serial("invokeLocalInstallation: Invokes local installation when found", async (t) => { - const {processStderrWriteStub, consoleInfoStub} = t.context; + const {processStderrWriteStub} = t.context; importLocalStub.returns({}); @@ -159,11 +158,10 @@ test.serial("invokeLocalInstallation: Invokes local installation when found", as t.true(returnValue); - t.is(processStderrWriteStub.callCount, 0, "console.log should not be called"); - t.is(consoleInfoStub.callCount, 2, "console.info should be called 2 times"); + t.is(processStderrWriteStub.callCount, 2, "Information messages should be provided"); - t.deepEqual(consoleInfoStub.getCall(0).args, ["INFO: Using local ui5-cli-test installation"]); - t.deepEqual(consoleInfoStub.getCall(1).args, [""]); + t.deepEqual(processStderrWriteStub.getCall(0).args, ["INFO: Using local ui5-cli-test installation"]); + t.deepEqual(processStderrWriteStub.getCall(1).args, ["\n\n"]); t.is(importLocalStub.callCount, 1, "import-local should be called once"); t.is(importLocalStub.getCall(0).args.length, 1); @@ -173,7 +171,7 @@ test.serial("invokeLocalInstallation: Invokes local installation when found", as }); test.serial("invokeLocalInstallation: Invokes local installation when found (/w --verbose)", async (t) => { - const {processStderrWriteStub, consoleInfoStub} = t.context; + const {processStderrWriteStub} = t.context; importLocalStub.returns({}); @@ -186,16 +184,15 @@ test.serial("invokeLocalInstallation: Invokes local installation when found (/w t.true(returnValue); - t.is(processStderrWriteStub.callCount, 0, "console.log should not be called"); - t.is(consoleInfoStub.callCount, 3, "console.info should be called 3 times"); + t.is(processStderrWriteStub.callCount, 4, "console.info should be called 3 times"); - t.deepEqual(consoleInfoStub.getCall(0).args, [ + t.deepEqual(processStderrWriteStub.getCall(0).args, [ "INFO: This project contains an individual ui5-cli-test installation which " + "will be used over the global one."]); - t.deepEqual(consoleInfoStub.getCall(1).args, [ + t.deepEqual(processStderrWriteStub.getCall(2).args, [ "See https://github.com/SAP/ui5-cli#local-vs-global-installation for details." ]); - t.deepEqual(consoleInfoStub.getCall(2).args, [""]); + t.deepEqual(processStderrWriteStub.getCall(3).args, ["\n\n"]); t.is(importLocalStub.callCount, 1, "import-local should be called once"); t.is(importLocalStub.getCall(0).args.length, 1); @@ -205,7 +202,7 @@ test.serial("invokeLocalInstallation: Invokes local installation when found (/w }); test.serial("invokeLocalInstallation: Doesn't invoke local installation when UI5_CLI_NO_LOCAL is set", async (t) => { - const {processStderrWriteStub, consoleInfoStub} = t.context; + const {processStderrWriteStub} = t.context; process.env.UI5_CLI_NO_LOCAL = "true"; @@ -215,14 +212,13 @@ test.serial("invokeLocalInstallation: Doesn't invoke local installation when UI5 t.false(returnValue); - t.is(processStderrWriteStub.callCount, 0, "console.log should not be called"); - t.is(consoleInfoStub.callCount, 0, "console.info should not be called"); + t.is(processStderrWriteStub.callCount, 0, "Information messages should be provided"); t.is(importLocalStub.callCount, 0, "import-local should not be called"); }); test.serial("invokeLocalInstallation: Doesn't invoke local installation when it is not found", async (t) => { - const {processStderrWriteStub, consoleInfoStub} = t.context; + const {processStderrWriteStub} = t.context; importLocalStub.returns(undefined); @@ -232,8 +228,7 @@ test.serial("invokeLocalInstallation: Doesn't invoke local installation when it t.false(returnValue); - t.is(processStderrWriteStub.callCount, 0, "console.log should not be called"); - t.is(consoleInfoStub.callCount, 0, "console.info should not be called"); + t.is(processStderrWriteStub.callCount, 0, "stderr info should not be provided"); t.is(importLocalStub.callCount, 1, "import-local should be called"); }); diff --git a/test/lib/cli/base.js b/test/lib/cli/base.js index 549719c6..b9309d8e 100644 --- a/test/lib/cli/base.js +++ b/test/lib/cli/base.js @@ -37,18 +37,18 @@ test.afterEach.always((t) => { }); test.serial("ui5 --version", async (t) => { - const {stderr: stderr} = await ui5(["--version"]); - t.is(stderr, `${pkg.version} (from ${ui5Cli})`); + const {stdout} = await ui5(["--version"]); + t.is(stdout, `${pkg.version} (from ${ui5Cli})`); }); test.serial("ui5 -v", async (t) => { - const {stderr} = await ui5(["-v"]); - t.is(stderr, `${pkg.version} (from ${ui5Cli})`); + const {stdout} = await ui5(["-v"]); + t.is(stdout, `${pkg.version} (from ${ui5Cli})`); }); test.serial("Handle multiple options", async (t) => { const {stderr} = await ui5(["versions", "--log-level", "silent", "--log-level", "silly"]); - t.regex(stripAnsi(stderr), /^verb/, "Verbose logging got enabled"); + t.regex(stripAnsi(stderr), /verb/g, "Verbose logging got enabled"); }); test.serial("Yargs error handling", async (t) => { From c2455dbcb8f19d05a9bd49f1446d1218b236cf7d Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Thu, 22 Feb 2024 17:41:59 +0200 Subject: [PATCH 03/13] Update logger tests --- test/lib/cli/middlewares/logger.js | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/test/lib/cli/middlewares/logger.js b/test/lib/cli/middlewares/logger.js index a66396ad..0727aa8d 100644 --- a/test/lib/cli/middlewares/logger.js +++ b/test/lib/cli/middlewares/logger.js @@ -102,15 +102,8 @@ const ui5 = (args, options = {}) => execa(ui5Cli, args, options); test("ui5 --verbose", async (t) => { // Using "versions" as a command, as the --verbose flag can't be used standalone const {stderr} = await ui5(["versions", "--verbose"]); - t.true(stripAnsi(stderr).includes( // Debugger info is also included into the message. We need to exclude it + // Debugger info is also included into the message. We need to exclude it + t.true(stripAnsi(stderr).includes( `verb cli:middlewares:base using @ui5/cli version ${pkg.version} (from ${ui5Cli})\n`+ - `verb cli:middlewares:base using node version ${process.version}\n` + - `\n` + - `@ui5/cli: ${pkg.version}\n` + - `@ui5/builder: ${pkg.version}\n` + - `@ui5/server: ${pkg.version}\n` + - `@ui5/fs: ${pkg.version}\n` + - `@ui5/project: ${pkg.version}\n` + - `@ui5/logger: ${pkg.version}\n` - )); + `verb cli:middlewares:base using node version ${process.version}`)); }); From ab97ceee45a8ff7b12a8990b7618ce5551a49a73 Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Tue, 27 Feb 2024 12:17:38 +0200 Subject: [PATCH 04/13] tree command should output to the stdout --- lib/cli/commands/tree.js | 26 +++++++++++++------------- test/lib/cli/commands/tree.js | 4 +++- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/lib/cli/commands/tree.js b/lib/cli/commands/tree.js index 9767f92d..e683a72b 100644 --- a/lib/cli/commands/tree.js +++ b/lib/cli/commands/tree.js @@ -90,13 +90,13 @@ tree.handler = async function(argv) { if (project.isFrameworkProject()) { name = chalk.blue(name); } - process.stderr.write( + process.stdout.write( `${baseString}${connectorString} ${name} ` + `${project.getNamespace() ? chalk.inverse(project.getNamespace()) + " " : ""}` + chalk.dim(`(${project.getVersion()}, ${project.getType()}) `) + chalk.dim.italic(`${project.getRootPath()}`) ); - process.stderr.write("\n"); + process.stdout.write("\n"); const lastIdx = dependencies.length - 1; const newConnectorIndices = [...connectorIndices]; @@ -110,8 +110,8 @@ tree.handler = async function(argv) { newConnectorIndices.forEach((idx) => { nextBaseString = `${nextBaseString.slice(0, idx)}│${nextBaseString.slice(idx + 1)}`; }); - process.stderr.write(`${nextBaseString}╰─ ${msg}`); - process.stderr.write("\n"); + process.stdout.write(`${nextBaseString}╰─ ${msg}`); + process.stdout.write("\n"); return; } if (renderDeps) { @@ -123,8 +123,8 @@ tree.handler = async function(argv) { }); }); - process.stderr.write(chalk.bold.underline(`Dependencies (${projects.size}):`)); - process.stderr.write("\n"); + process.stdout.write(chalk.bold.underline(`Dependencies (${projects.size}):`)); + process.stdout.write("\n"); if (argv.flat) { // Iterate over list of projects, rendering each individually // We need to transform the map into an array in order to know the index @@ -136,26 +136,26 @@ tree.handler = async function(argv) { // Recursively render the tree, starting with the first entry of the map projects.values().next().value.render(0, [], true); } - process.stderr.write("\n"); + process.stdout.write("\n"); const extensionNames = graph.getExtensionNames(); const extensionCount = extensionNames.length; - process.stderr.write(chalk.bold.underline(`Extensions (${extensionCount}):`)); - process.stderr.write("\n"); + process.stdout.write(chalk.bold.underline(`Extensions (${extensionCount}):`)); + process.stdout.write("\n"); if (extensionCount) { const lastIdx = extensionCount - 1; extensionNames.forEach((extensionName, idx) => { const extension = graph.getExtension(extensionName); const connectorString = idx === lastIdx ? "╰─" : "├─"; - process.stderr.write( + process.stdout.write( `${connectorString} ${extensionName} ` + chalk.dim(`(${extension.getVersion()}, ${extension.getType()}) `) + chalk.dim.italic(`${extension.getRootPath()}`)); - process.stderr.write("\n"); + process.stdout.write("\n"); }); } else { - process.stderr.write(chalk.italic(`None`)); - process.stderr.write("\n"); + process.stdout.write(chalk.italic(`None`)); + process.stdout.write("\n"); } if (argv.perf) { process.stderr.write("\n"); diff --git a/test/lib/cli/commands/tree.js b/test/lib/cli/commands/tree.js index a3792023..f8e8fcad 100644 --- a/test/lib/cli/commands/tree.js +++ b/test/lib/cli/commands/tree.js @@ -39,7 +39,9 @@ test.beforeEach(async (t) => { t.context.consoleOutput = ""; t.context.processStderrWrite = sinon.stub(process.stderr, "write").callsFake((message) => { - // NOTE: This fake impl only supports one string arg passed to console.log + t.context.consoleOutput += message; + }); + t.context.processStdoutWrite = sinon.stub(process.stdout, "write").callsFake((message) => { t.context.consoleOutput += message; }); From 7268aefa4f4c25a5ba48588a64bbcca48eedc52b Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Tue, 27 Feb 2024 12:21:26 +0200 Subject: [PATCH 05/13] Forward versions command to the stdout --- lib/cli/commands/versions.js | 2 +- test/lib/cli/base.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/cli/commands/versions.js b/lib/cli/commands/versions.js index 87a3f2c1..c8b17a0a 100644 --- a/lib/cli/commands/versions.js +++ b/lib/cli/commands/versions.js @@ -34,7 +34,7 @@ versions.handler = async function() { }) )).join("\n"); - process.stderr.write(`\n${output}\n\n`); + process.stdout.write(`\n${output}\n\n`); }; export default versions; diff --git a/test/lib/cli/base.js b/test/lib/cli/base.js index b9309d8e..2ada72fe 100644 --- a/test/lib/cli/base.js +++ b/test/lib/cli/base.js @@ -276,8 +276,8 @@ test.serial("Unexpected error handling", async (t) => { }); test.serial("ui5 --no-update-notifier", async (t) => { - const {stderr, failed} = await ui5(["versions", "--no-update-notifier"]); - t.regex(stderr, /@ui5\/cli:/, "Output includes version information"); + const {stdout, failed} = await ui5(["versions", "--no-update-notifier"]); + t.regex(stdout, /@ui5\/cli:/, "Output includes version information"); t.false(failed, "Command should not fail"); }); From 17f57b8c8a68dded3d2862e36305b530993d017a Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Tue, 27 Feb 2024 12:24:07 +0200 Subject: [PATCH 06/13] Use stdout for "use" command output --- lib/cli/commands/use.js | 8 ++++---- test/lib/cli/commands/use.js | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/cli/commands/use.js b/lib/cli/commands/use.js index 939a41cc..f30f64d7 100644 --- a/lib/cli/commands/use.js +++ b/lib/cli/commands/use.js @@ -81,10 +81,10 @@ useCommand.handler = async function(argv) { throw new Error(`Internal error while updating ui5.yaml to ${usedFramework} version ${usedVersion}`); } } else { - process.stderr.write(`Updated configuration written to ${argv.config || "ui5.yaml"}`); - process.stderr.write("\n"); - process.stderr.write(`This project is now using ${usedFramework} version ${usedVersion}`); - process.stderr.write("\n"); + process.stdout.write(`Updated configuration written to ${argv.config || "ui5.yaml"}`); + process.stdout.write("\n"); + process.stdout.write(`This project is now using ${usedFramework} version ${usedVersion}`); + process.stdout.write("\n"); } }; diff --git a/test/lib/cli/commands/use.js b/test/lib/cli/commands/use.js index 57cdeb6a..061ec786 100644 --- a/test/lib/cli/commands/use.js +++ b/test/lib/cli/commands/use.js @@ -55,7 +55,7 @@ async function assertFailingYamlUpdateUseHandler(t, {argv, expectedMessage}) { } test.beforeEach(async (t) => { - t.context.consoleLogStub = sinon.stub(process.stderr, "write"); + t.context.processStdoutStub = sinon.stub(process.stdout, "write"); t.context.frameworkUseStub = sinon.stub(); @@ -276,10 +276,10 @@ test.serial("Logs framework name, version and default config path when updating "\n" ]; - t.is(t.context.consoleLogStub.callCount, expectedConsoleLog.length, + t.is(t.context.processStdoutStub.callCount, expectedConsoleLog.length, "console.log should be called " + expectedConsoleLog.length + " times"); expectedConsoleLog.forEach((expectedLog, i) => { - t.deepEqual(t.context.consoleLogStub.getCall(i).args, [expectedLog], + t.deepEqual(t.context.processStdoutStub.getCall(i).args, [expectedLog], "console.log should be called with expected string on call index " + i); }); }); @@ -302,10 +302,10 @@ test.serial("Logs framework name, version and custom config path when updating c "\n" ]; - t.is(t.context.consoleLogStub.callCount, expectedConsoleLog.length, + t.is(t.context.processStdoutStub.callCount, expectedConsoleLog.length, "console.log should be called " + expectedConsoleLog.length + " times"); expectedConsoleLog.forEach((expectedLog, i) => { - t.deepEqual(t.context.consoleLogStub.getCall(i).args, [expectedLog], + t.deepEqual(t.context.processStdoutStub.getCall(i).args, [expectedLog], "console.log should be called with expected string on call index " + i); }); }); From 721b8ab9fecdbc3fa10192b8b2c6c9945ac02282 Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Tue, 27 Feb 2024 12:26:09 +0200 Subject: [PATCH 07/13] redirect init command output to stdout --- lib/cli/commands/init.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/cli/commands/init.js b/lib/cli/commands/init.js index 220fdc79..1cda44cd 100644 --- a/lib/cli/commands/init.js +++ b/lib/cli/commands/init.js @@ -23,10 +23,10 @@ initCommand.handler = async function() { const yaml = jsYaml.dump(projectConfig, {quotingType: `"`}); await writeFile(yamlPath, yaml); - process.stderr.write(`Wrote ui5.yaml to ${yamlPath}:`); - process.stderr.write("\n"); - process.stderr.write(yaml); - process.stderr.write("\n"); + process.stdout.write(`Wrote ui5.yaml to ${yamlPath}:`); + process.stdout.write("\n"); + process.stdout.write(yaml); + process.stdout.write("\n"); }; export default initCommand; From 96a66557d019b1dc7466492deccc483e92378150 Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Tue, 27 Feb 2024 12:28:23 +0200 Subject: [PATCH 08/13] Redirect to output to stdout for remove command --- lib/cli/commands/remove.js | 8 ++++---- test/lib/cli/commands/remove.js | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/cli/commands/remove.js b/lib/cli/commands/remove.js index 70fe9676..3665c676 100644 --- a/lib/cli/commands/remove.js +++ b/lib/cli/commands/remove.js @@ -59,12 +59,12 @@ removeCommand.handler = async function(argv) { ); } } else { - process.stderr.write(`Updated configuration written to ${argv.config || "ui5.yaml"}`); - process.stderr.write("\n"); + process.stdout.write(`Updated configuration written to ${argv.config || "ui5.yaml"}`); + process.stdout.write("\n"); let logMessage = `Removed framework ${library} ${libraryNames.join(" ")} as`; logMessage += libraries.length === 1 ? " dependency": " dependencies"; - process.stderr.write(logMessage); - process.stderr.write("\n"); + process.stdout.write(logMessage); + process.stdout.write("\n"); } }; diff --git a/test/lib/cli/commands/remove.js b/test/lib/cli/commands/remove.js index f229ebf0..a2b0afbb 100644 --- a/test/lib/cli/commands/remove.js +++ b/test/lib/cli/commands/remove.js @@ -24,10 +24,10 @@ async function assertRemoveHandler(t, {argv, expectedLibraries, expectedConsoleL }], "Remove function should be called with expected args"); - t.is(t.context.consoleLogStub.callCount, expectedConsoleLog.length, + t.is(t.context.processStdoutStub.callCount, expectedConsoleLog.length, "console.log should be called " + expectedConsoleLog.length + " times"); expectedConsoleLog.forEach((expectedLog, i) => { - t.deepEqual(t.context.consoleLogStub.getCall(i).args, [expectedLog], + t.deepEqual(t.context.processStdoutStub.getCall(i).args, [expectedLog], "console.log should be called with expected string on call index " + i); }); } @@ -50,7 +50,7 @@ async function assertFailingYamlUpdateRemoveHandler(t, {argv, expectedMessage}) } test.beforeEach((t) => { - t.context.consoleLogStub = sinon.stub(process.stderr, "write"); + t.context.processStdoutStub = sinon.stub(process.stdout, "write"); }); test.afterEach.always((t) => { From 6a0ad79c250bd5b003914cbe721f8358d66bbc65 Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Tue, 27 Feb 2024 12:30:38 +0200 Subject: [PATCH 09/13] Forward messages from add command to the stdoutput --- lib/cli/commands/add.js | 8 ++++---- test/lib/cli/commands/add.js | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/cli/commands/add.js b/lib/cli/commands/add.js index 6589b648..d8943a60 100644 --- a/lib/cli/commands/add.js +++ b/lib/cli/commands/add.js @@ -75,8 +75,8 @@ addCommand.handler = async function(argv) { ); } } else { - process.stderr.write(`Updated configuration written to ${argv.config || "ui5.yaml"}`); - process.stderr.write("\n"); + process.stdout.write(`Updated configuration written to ${argv.config || "ui5.yaml"}`); + process.stdout.write("\n"); let logMessage = `Added framework ${library} ${libraryNames.join(" ")} as`; if (development) { logMessage += " development"; @@ -84,8 +84,8 @@ addCommand.handler = async function(argv) { logMessage += " optional"; } logMessage += libraries.length === 1 ? " dependency": " dependencies"; - process.stderr.write(logMessage); - process.stderr.write("\n"); + process.stdout.write(logMessage); + process.stdout.write("\n"); } }; diff --git a/test/lib/cli/commands/add.js b/test/lib/cli/commands/add.js index 76a291de..2f22163e 100644 --- a/test/lib/cli/commands/add.js +++ b/test/lib/cli/commands/add.js @@ -24,10 +24,10 @@ async function assertAddHandler(t, {argv, expectedLibraries, expectedConsoleLog} }], "Add function should be called with expected args"); - t.is(t.context.processStderrWriteStub.callCount, expectedConsoleLog.length, + t.is(t.context.processStdoutStub.callCount, expectedConsoleLog.length, "console.log should be called " + expectedConsoleLog.length + " times"); expectedConsoleLog.forEach((expectedLog, i) => { - t.deepEqual(t.context.processStderrWriteStub.getCall(i).args, [expectedLog], + t.deepEqual(t.context.processStdoutStub.getCall(i).args, [expectedLog], "console.log should be called with expected string on call index " + i); }); } @@ -49,7 +49,7 @@ async function assertFailingYamlUpdateAddHandler(t, {argv, expectedMessage}) { } test.beforeEach((t) => { - t.context.processStderrWriteStub = sinon.stub(process.stderr, "write"); + t.context.processStdoutStub = sinon.stub(process.stdout, "write"); }); test.afterEach.always((t) => { From 6d7af38639eddace3e4f0ecd70e981da65fad69c Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Tue, 27 Feb 2024 12:32:49 +0200 Subject: [PATCH 10/13] Forward some of the messages from serve command to the stdoutput --- lib/cli/commands/serve.js | 8 ++++---- test/lib/cli/commands/serve.js | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/cli/commands/serve.js b/lib/cli/commands/serve.js index f5560903..b2492e4d 100644 --- a/lib/cli/commands/serve.js +++ b/lib/cli/commands/serve.js @@ -166,10 +166,10 @@ serve.handler = async function(argv) { "to a target system for third parties on your network")); process.stderr.write("\n\n"); } - process.stderr.write("Server started"); - process.stderr.write("\n"); - process.stderr.write("URL: " + browserUrl); - process.stderr.write("\n"); + process.stdout.write("Server started"); + process.stdout.write("\n"); + process.stdout.write("URL: " + browserUrl); + process.stdout.write("\n"); if (argv.open !== undefined) { if (typeof argv.open === "string") { diff --git a/test/lib/cli/commands/serve.js b/test/lib/cli/commands/serve.js index 8789eb90..7284c394 100644 --- a/test/lib/cli/commands/serve.js +++ b/test/lib/cli/commands/serve.js @@ -63,6 +63,10 @@ test.beforeEach(async (t) => { // NOTE: This fake impl only supports one string arg passed to console.log t.context.consoleOutput += message; }); + t.context.processStdoutWrite = sinon.stub(process.stdout, "write").callsFake((message) => { + // NOTE: This fake impl only supports one string arg passed to console.log + t.context.consoleOutput += message; + }); t.context.open = sinon.stub(); From 38f463df655ae6eb2dff0222cf46ec6357ac72f5 Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Tue, 27 Feb 2024 12:40:41 +0200 Subject: [PATCH 11/13] Fix new line --- bin/ui5.cjs | 1 + test/bin/ui5.js | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/bin/ui5.cjs b/bin/ui5.cjs index 27877e3b..0068e8fc 100755 --- a/bin/ui5.cjs +++ b/bin/ui5.cjs @@ -112,6 +112,7 @@ module.exports = ui5; if (process.env.NODE_ENV !== "test" || process.env.UI5_CLI_TEST_BIN_RUN_MAIN !== "false") { ui5.main().catch((err) => { process.stderr.write("Fatal Error: Unable to initialize UI5 CLI"); + process.stderr.write("\n"); process.stderr.write(err); process.exit(1); }); diff --git a/test/bin/ui5.js b/test/bin/ui5.js index fbbac297..96dfefad 100644 --- a/test/bin/ui5.js +++ b/test/bin/ui5.js @@ -365,10 +365,10 @@ test.serial("integration: Executing main when required as main module (catch ini const errorCode = await processExit; t.is(errorCode, 1); - t.is(processStderrWriteStub.callCount, 2); + t.is(processStderrWriteStub.callCount, 3); t.deepEqual(processStderrWriteStub.getCall(0).args, ["Fatal Error: Unable to initialize UI5 CLI"]); - t.is(processStderrWriteStub.getCall(1).args.length, 1); - t.true(processStderrWriteStub.getCall(1).args[0] instanceof Error); - t.is(processStderrWriteStub.getCall(1).args[0].message, "TEST: Unable to invoke CLI"); + t.is(processStderrWriteStub.getCall(2).args.length, 1); + t.true(processStderrWriteStub.getCall(2).args[0] instanceof Error); + t.is(processStderrWriteStub.getCall(2).args[0].message, "TEST: Unable to invoke CLI"); }); From 4c3bb2b9984bbfd115cbe1e5e6e9a10d2126657b Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Tue, 27 Feb 2024 14:35:20 +0200 Subject: [PATCH 12/13] Correct messages displayed in stdoutput --- bin/ui5.cjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/ui5.cjs b/bin/ui5.cjs index 0068e8fc..2b84f795 100755 --- a/bin/ui5.cjs +++ b/bin/ui5.cjs @@ -83,8 +83,8 @@ const ui5 = { process.stderr.write("See https://github.com/SAP/ui5-cli#local-vs-global-installation for details."); process.stderr.write("\n\n"); } else { - process.stderr.write(`INFO: Using local ${pkg.name} installation`); - process.stderr.write("\n\n"); + process.stdout.write(`INFO: Using local ${pkg.name} installation`); + process.stdout.write("\n\n"); } return true; }, From d7072616e2c0cebf195cc9c92a02428849eab207 Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Tue, 27 Feb 2024 14:36:55 +0200 Subject: [PATCH 13/13] Fix tests --- test/bin/ui5.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/bin/ui5.js b/test/bin/ui5.js index 96dfefad..65388898 100644 --- a/test/bin/ui5.js +++ b/test/bin/ui5.js @@ -34,6 +34,7 @@ test.before(() => { test.beforeEach(async (t) => { const sinon = t.context.sinon = sinonGlobal.createSandbox(); + t.context.processStdoutWriteStub = sinon.stub(process.stdout, "write"); t.context.processStderrWriteStub = sinon.stub(process.stderr, "write"); t.context.originalArgv = process.argv; process.env.UI5_CLI_TEST_BIN_RUN_MAIN = "false"; // prevent automatic execution of main function @@ -148,7 +149,7 @@ test.serial("checkRequirements: logs warning when using pre-release Node.js vers }); test.serial("invokeLocalInstallation: Invokes local installation when found", async (t) => { - const {processStderrWriteStub} = t.context; + const {processStdoutWriteStub} = t.context; importLocalStub.returns({}); @@ -158,10 +159,10 @@ test.serial("invokeLocalInstallation: Invokes local installation when found", as t.true(returnValue); - t.is(processStderrWriteStub.callCount, 2, "Information messages should be provided"); + t.is(processStdoutWriteStub.callCount, 2, "Information messages should be provided"); - t.deepEqual(processStderrWriteStub.getCall(0).args, ["INFO: Using local ui5-cli-test installation"]); - t.deepEqual(processStderrWriteStub.getCall(1).args, ["\n\n"]); + t.deepEqual(processStdoutWriteStub.getCall(0).args, ["INFO: Using local ui5-cli-test installation"]); + t.deepEqual(processStdoutWriteStub.getCall(1).args, ["\n\n"]); t.is(importLocalStub.callCount, 1, "import-local should be called once"); t.is(importLocalStub.getCall(0).args.length, 1);