diff --git a/lib/cli/commands/build.js b/lib/cli/commands/build.js index b34c51db..3dec442d 100644 --- a/lib/cli/commands/build.js +++ b/lib/cli/commands/build.js @@ -121,6 +121,22 @@ build.builder = function(cli) { default: false, type: "boolean" }) + .option("output-style", { + describe: + "Processes build results into a specific directory structure. \r\n\r\n" + + "- Flat: Omits the project namespace and the \"resources\" directory.\r\n" + + "- Namespace: Respects the project namespace and the \"resources\" directory, " + + "maintaining the original structure.\r\n" + + "- Default: The default directory structure for every project type. For applications, " + + "this is identical to \"Flat\", and for libraries, it is \"Namespace\". Other types have a " + + "more distinct default output style.", + type: "string", + default: "Default", + choices: ["Default", "Flat", "Namespace"], + }) + .coerce("output-style", (opt) => { + return opt.charAt(0).toUpperCase() + opt.slice(1).toLowerCase(); + }) .example("ui5 build", "Preload build for project without dependencies") .example("ui5 build self-contained", "Self-contained build for project") .example("ui5 build --exclude-task=* --include-task=minify generateComponentPreload", @@ -176,7 +192,8 @@ async function handleBuild(argv) { jsdoc: command === "jsdoc", includedTasks: argv["include-task"], excludedTasks: argv["exclude-task"], - cssVariables: argv["experimental-css-variables"] + cssVariables: argv["experimental-css-variables"], + outputStyle: argv["output-style"], }); } diff --git a/test/lib/cli/base.js b/test/lib/cli/base.js index ae0d0650..9f924adc 100644 --- a/test/lib/cli/base.js +++ b/test/lib/cli/base.js @@ -281,3 +281,27 @@ test.serial("ui5 --no-update-notifier", async (t) => { t.regex(stdout, /@ui5\/cli:/, "Output includes version information"); t.false(failed, "Command should not fail"); }); + +test.serial("ui5 --output-style", async (t) => { + await t.throwsAsync(ui5(["build", "--output-style", "nonExistent"]), { + message: /Argument: output-style, Given: "Nonexistent", Choices: "Default", "Flat", "Namespace"/s + }, "Coercion correctly capitalizes the first letter and makes the rest lowercase"); + + + // "--output-style" uses a coerce to transform the input into the correct letter case. + // It is hard/unmaintainable to spy on internal implementation, so we check the output. + // The coerce goes before the real ui5 build, so we just need to check whether + // an invalid "--output-style" choice exception is not thrown. + // Of course, the build would throw another exception, because there's nothing actually to build. + await t.throwsAsync(ui5(["build", "--output-style", "flat"]), { + message: /^((?!Argument: output-style, Given: "Flat).)*$/s + }, "Does not throw an exception because of the --output-style input"); + + await t.throwsAsync(ui5(["build", "--output-style", "nAmEsPaCe"]), { + message: /^((?!Argument: output-style, Given: "Namespace).)*$/s + }, "Does not throw an exception because of the --output-style input"); + + await t.throwsAsync(ui5(["build", "--output-style", "Default"]), { + message: /^((?!Argument: output-style, Given: "Default).)*$/s + }, "Does not throw an exception because of the --output-style input"); +}); diff --git a/test/lib/cli/commands/build.js b/test/lib/cli/commands/build.js index 3e0e0ca3..ac36226c 100644 --- a/test/lib/cli/commands/build.js +++ b/test/lib/cli/commands/build.js @@ -25,6 +25,7 @@ function getDefaultArgv() { "experimentalCssVariables": false, "cache-mode": "Default", "cacheMode": "Default", + "output-style": "Default", "$0": "ui5" }; } @@ -50,7 +51,8 @@ function getDefaultBuilderArgs() { jsdoc: false, includedTasks: undefined, excludedTasks: undefined, - cssVariables: false + cssVariables: false, + outputStyle: "Default" }; } @@ -364,3 +366,15 @@ test.serial("ui5 build --experimental-css-variables", async (t) => { t.deepEqual(builder.getCall(0).args[0], expectedBuilderArgs, "Build with activated CSS Variables is called with expected arguments"); }); + +test.serial("ui5 build --output-style", async (t) => { + const {build, argv, builder, expectedBuilderArgs} = t.context; + + argv["output-style"] = "Flat"; + + await build.handler(argv); + + expectedBuilderArgs.outputStyle = "Flat"; + t.deepEqual(builder.getCall(0).args[0], expectedBuilderArgs, + "Build with activated outputStyle='Flat' is called with expected arguments"); +});