diff --git a/dsl/camel-jbang/camel-jbang-plugin-test/pom.xml b/dsl/camel-jbang/camel-jbang-plugin-test/pom.xml
index b660622ff8ea7..593ee0288eeef 100644
--- a/dsl/camel-jbang/camel-jbang-plugin-test/pom.xml
+++ b/dsl/camel-jbang/camel-jbang-plugin-test/pom.xml
@@ -49,7 +49,7 @@
org.citrusframework
- citrus-jbang-connector
+ citrus-base
${citrus-version}
diff --git a/dsl/camel-jbang/camel-jbang-plugin-test/src/main/java/org/apache/camel/dsl/jbang/core/commands/test/TestInit.java b/dsl/camel-jbang/camel-jbang-plugin-test/src/main/java/org/apache/camel/dsl/jbang/core/commands/test/TestInit.java
new file mode 100644
index 0000000000000..7bc2aedbabddf
--- /dev/null
+++ b/dsl/camel-jbang/camel-jbang-plugin-test/src/main/java/org/apache/camel/dsl/jbang/core/commands/test/TestInit.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.jbang.core.commands.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.apache.camel.dsl.jbang.core.commands.CamelCommand;
+import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
+import org.apache.camel.dsl.jbang.core.commands.ExportHelper;
+import org.apache.camel.util.IOHelper;
+import org.citrusframework.CitrusVersion;
+import picocli.CommandLine;
+
+/**
+ * Initializes a new Citrus test file from a template. Creates the test subfolder if it does not exist and writes a
+ * template test source for the given file type. Also creates a jbang.properties file with default Citrus dependencies
+ * when not already present.
+ */
+@CommandLine.Command(name = "init",
+ description = "Initialize a new Citrus test from a template")
+public class TestInit extends CamelCommand {
+
+ public static final String TEST_DIR = "test";
+
+ @CommandLine.Parameters(index = "0", description = "Test file name (e.g. MyTest.yaml, MyTest.xml, MyTest.java)")
+ String file;
+
+ @CommandLine.Option(names = { "-d", "--directory" }, description = "Target directory", defaultValue = ".")
+ String directory;
+
+ public TestInit(CamelJBangMain main) {
+ super(main);
+ }
+
+ @Override
+ public Integer doCall() throws Exception {
+ // Determine file extension and base name
+ String ext = getFileExtension(file);
+ String baseName = getBaseName(file);
+
+ if (ext.isEmpty()) {
+ printer().println("Cannot determine file type for: " + file);
+ return 1;
+ }
+
+ // Load template for the file type
+ String template;
+ try (InputStream is = TestInit.class.getClassLoader().getResourceAsStream("templates/citrus-" + ext + ".tmpl")) {
+ if (is == null) {
+ printer().println("Unsupported test file type: " + ext);
+ return 1;
+ }
+ template = IOHelper.loadText(is);
+ }
+
+ // Replace template placeholders
+ template = template.replaceAll("\\{\\{ \\.Name }}", baseName);
+
+ // Determine the working directory
+ Path workingDir = resolveTestDir();
+ if (workingDir == null) {
+ printer().println("Cannot create test working directory");
+ return 1;
+ }
+
+ // Create target directory if specified
+ Path targetDir;
+ if (".".equals(directory)) {
+ targetDir = workingDir;
+ } else {
+ targetDir = workingDir.resolve(directory);
+ Files.createDirectories(targetDir);
+ }
+
+ // Create jbang properties with default dependencies if not present
+ createJBangProperties(workingDir);
+
+ // Write the test file
+ Path testFile = targetDir.resolve(file);
+ Files.writeString(testFile, template);
+
+ printer().println("Created test file: " + testFile);
+ return 0;
+ }
+
+ /**
+ * Resolves and creates the test directory. Automatically uses the test subfolder as the working directory.
+ */
+ private Path resolveTestDir() {
+ Path currentDir = Paths.get(".");
+ Path workingDir;
+ if (TEST_DIR.equals(currentDir.toAbsolutePath().normalize().getFileName().toString())) {
+ // current directory is already the test subfolder
+ workingDir = currentDir;
+ } else if (currentDir.resolve(TEST_DIR).toFile().exists()) {
+ // navigate to existing test subfolder
+ workingDir = currentDir.resolve(TEST_DIR);
+ } else if (currentDir.resolve(TEST_DIR).toFile().mkdirs()) {
+ // create test subfolder and navigate to it
+ workingDir = currentDir.resolve(TEST_DIR);
+ } else {
+ return null;
+ }
+ return workingDir;
+ }
+
+ /**
+ * Creates jbang.properties with default Citrus dependencies if not already present.
+ */
+ private void createJBangProperties(Path workingDir) {
+ if (!workingDir.resolve("jbang.properties").toFile().exists()) {
+ Path jbangProperties = workingDir.resolve("jbang.properties");
+ try (InputStream is
+ = TestInit.class.getClassLoader().getResourceAsStream("templates/jbang-properties.tmpl")) {
+ String context = IOHelper.loadText(is);
+ context = context.replaceAll("\\{\\{ \\.CitrusVersion }}", CitrusVersion.version());
+ ExportHelper.safeCopy(new ByteArrayInputStream(context.getBytes(StandardCharsets.UTF_8)), jbangProperties);
+ } catch (Exception e) {
+ printer().println("Failed to create jbang.properties for tests in: " + jbangProperties);
+ }
+ }
+ }
+
+ private static String getFileExtension(String fileName) {
+ int dotIndex = fileName.lastIndexOf('.');
+ if (dotIndex > 0 && dotIndex < fileName.length() - 1) {
+ return fileName.substring(dotIndex + 1);
+ }
+ return "";
+ }
+
+ private static String getBaseName(String fileName) {
+ int dotIndex = fileName.lastIndexOf('.');
+ if (dotIndex > 0) {
+ return fileName.substring(0, dotIndex);
+ }
+ return fileName;
+ }
+}
diff --git a/dsl/camel-jbang/camel-jbang-plugin-test/src/main/java/org/apache/camel/dsl/jbang/core/commands/test/TestPlugin.java b/dsl/camel-jbang/camel-jbang-plugin-test/src/main/java/org/apache/camel/dsl/jbang/core/commands/test/TestPlugin.java
index a556df43b7c31..085fd9cb294df 100644
--- a/dsl/camel-jbang/camel-jbang-plugin-test/src/main/java/org/apache/camel/dsl/jbang/core/commands/test/TestPlugin.java
+++ b/dsl/camel-jbang/camel-jbang-plugin-test/src/main/java/org/apache/camel/dsl/jbang/core/commands/test/TestPlugin.java
@@ -16,27 +16,12 @@
*/
package org.apache.camel.dsl.jbang.core.commands.test;
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
import java.util.Optional;
-import org.apache.camel.RuntimeCamelException;
import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
-import org.apache.camel.dsl.jbang.core.commands.ExportHelper;
import org.apache.camel.dsl.jbang.core.common.CamelJBangPlugin;
import org.apache.camel.dsl.jbang.core.common.Plugin;
import org.apache.camel.dsl.jbang.core.common.PluginExporter;
-import org.apache.camel.util.IOHelper;
-import org.citrusframework.CitrusVersion;
-import org.citrusframework.jbang.JBangSettings;
-import org.citrusframework.jbang.JBangSupport;
-import org.citrusframework.jbang.ProcessAndOutput;
import picocli.CommandLine;
@CamelJBangPlugin(name = "camel-jbang-plugin-test", firstVersion = "4.14.0")
@@ -44,138 +29,15 @@ public class TestPlugin implements Plugin {
@Override
public void customize(CommandLine commandLine, CamelJBangMain main) {
- commandLine.setExecutionStrategy(new CitrusExecutionStrategy(main))
- .addSubcommand("test", new CommandLine(new TestCommand(main))
- .setUnmatchedArgumentsAllowed(true)
- .setUnmatchedOptionsAllowedAsOptionParameters(true));
+ var cmd = new CommandLine(new TestCommand(main))
+ .addSubcommand("init", new CommandLine(new TestInit(main)))
+ .addSubcommand("run", new CommandLine(new TestRun(main)));
+
+ commandLine.addSubcommand("test", cmd);
}
@Override
public Optional getExporter() {
return Optional.of(new TestPluginExporter());
}
-
- /**
- * Command execution strategy delegates to Citrus JBang for subcommands like init or run. Performs special command
- * preparations and makes sure to run the proper Citrus version for this Camel release.
- *
- * @param main Camel JBang main that provides the output printer.
- */
- private record CitrusExecutionStrategy(CamelJBangMain main) implements CommandLine.IExecutionStrategy {
-
- public static final String TEST_DIR = "test";
-
- @Override
- public int execute(CommandLine.ParseResult parseResult)
- throws CommandLine.ExecutionException, CommandLine.ParameterException {
-
- String command;
- List args = Collections.emptyList();
-
- if (parseResult.originalArgs().size() > 2) {
- command = parseResult.originalArgs().get(1);
- args = parseResult.originalArgs().subList(2, parseResult.originalArgs().size());
- } else if (parseResult.originalArgs().size() == 2) {
- command = parseResult.originalArgs().get(1);
- } else {
- // run help command by default
- command = "--help";
- }
-
- JBangSupport citrus = JBangSupport.jbang().app(JBangSettings.getApp())
- .withSystemProperty("citrus.jbang.version", CitrusVersion.version());
-
- // Prepare commands
- if ("init".equals(command)) {
- return executeInitCommand(citrus, args);
- } else if ("run".equals(command)) {
- return executeRunCommand(citrus, args);
- }
-
- return execute(citrus, command, args);
- }
-
- /**
- * Prepare and execute init command. Automatically uses test subfolder as a working directory for creating new
- * tests. Automatically adds a jbang.properties configuration to add required Camel Citrus dependencies.
- */
- private int executeInitCommand(JBangSupport citrus, List args) {
- Path currentDir = Paths.get(".");
- Path workingDir;
- // Automatically set test subfolder as a working directory
- if (TEST_DIR.equals(currentDir.getFileName().toString())) {
- // current directory is already the test subfolder
- workingDir = currentDir;
- } else if (currentDir.resolve(TEST_DIR).toFile().exists()) {
- // navigate to existing test subfolder
- workingDir = currentDir.resolve(TEST_DIR);
- citrus.workingDir(workingDir);
- } else if (currentDir.resolve(TEST_DIR).toFile().mkdirs()) {
- // create test subfolder and navigate to it
- workingDir = currentDir.resolve(TEST_DIR);
- citrus.workingDir(workingDir);
- } else {
- throw new RuntimeCamelException("Cannot create test working directory in: " + currentDir);
- }
-
- // Create jbang properties with default dependencies if not present
- if (!workingDir.resolve("jbang.properties").toFile().exists()) {
- Path jbangProperties = workingDir.resolve("jbang.properties");
- try (InputStream is
- = TestPlugin.class.getClassLoader().getResourceAsStream("templates/jbang-properties.tmpl")) {
- String context = IOHelper.loadText(is);
-
- context = context.replaceAll("\\{\\{ \\.CitrusVersion }}", CitrusVersion.version());
-
- ExportHelper.safeCopy(new ByteArrayInputStream(context.getBytes(StandardCharsets.UTF_8)), jbangProperties);
- } catch (Exception e) {
- main.getOut().println("Failed to create jbang.properties for tests in:" + jbangProperties);
- }
- }
-
- return execute(citrus, "init", args);
- }
-
- /**
- * Prepare and execute Citrus run command. Automatically navigates to test subfolder if it is present and uses
- * this as a working directory. Runs command asynchronous streaming logs to the main output of this Camel JBang
- * process.
- */
- private int executeRunCommand(JBangSupport citrus, List args) {
- Path currentDir = Paths.get(".");
- List runArgs = new ArrayList<>(args);
- // automatically navigate to test subfolder for test execution
- if (currentDir.resolve(TEST_DIR).toFile().exists()) {
- // set test subfolder as working directory
- citrus.workingDir(currentDir.resolve(TEST_DIR));
-
- // remove test folder prefix in test file path if present
- if (!args.isEmpty() && args.get(0).startsWith(TEST_DIR + "/")) {
- runArgs = new ArrayList<>(args.subList(1, args.size()));
- runArgs.add(0, args.get(0).substring((TEST_DIR + "/").length()));
- }
- }
-
- citrus.withOutputListener(output -> main.getOut().print(output));
- ProcessAndOutput pao = citrus.runAsync("run", runArgs);
- try {
- pao.waitFor();
- } catch (InterruptedException e) {
- main.getOut().printErr("Interrupted while running Citrus command", e);
- }
-
- return pao.getProcess().exitValue();
- }
-
- /**
- * Uses given Citrus JBang instance to run the given command using the given arguments.
- *
- * @return exit code of the command process.
- */
- private int execute(JBangSupport citrus, String command, List args) {
- ProcessAndOutput pao = citrus.run(command, args);
- main.getOut().print(pao.getOutput());
- return pao.getProcess().exitValue();
- }
- }
}
diff --git a/dsl/camel-jbang/camel-jbang-plugin-test/src/main/java/org/apache/camel/dsl/jbang/core/commands/test/TestRun.java b/dsl/camel-jbang/camel-jbang-plugin-test/src/main/java/org/apache/camel/dsl/jbang/core/commands/test/TestRun.java
new file mode 100644
index 0000000000000..6d1094ada2824
--- /dev/null
+++ b/dsl/camel-jbang/camel-jbang-plugin-test/src/main/java/org/apache/camel/dsl/jbang/core/commands/test/TestRun.java
@@ -0,0 +1,229 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.jbang.core.commands.test;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.dsl.jbang.core.commands.CamelCommand;
+import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
+import org.citrusframework.TestSource;
+import org.citrusframework.main.TestEngine;
+import org.citrusframework.main.TestRunConfiguration;
+import org.citrusframework.util.FileUtils;
+import picocli.CommandLine;
+
+/**
+ * Runs Citrus test files directly using the Citrus test engine. This replaces the indirect JBang process call with a
+ * direct in-process test execution.
+ */
+@CommandLine.Command(name = "run",
+ description = "Run Citrus tests")
+public class TestRun extends CamelCommand {
+
+ public static final String TEST_DIR = "test";
+ public static final String WORK_DIR = ".citrus-jbang";
+
+ private static final String[] ACCEPTED_FILE_EXT = { "xml", "yaml", "yml", "java", "groovy", "feature" };
+
+ @CommandLine.Parameters(description = "Test files or directories to run", arity = "0..*")
+ String[] files;
+
+ @CommandLine.Option(names = { "--engine" }, description = "Test engine to use", defaultValue = "default")
+ String engine;
+
+ @CommandLine.Option(names = { "--verbose" }, description = "Enable verbose output")
+ boolean verbose;
+
+ @CommandLine.Option(names = { "-p", "--property" }, description = "Set system properties (key=value)")
+ String[] properties;
+
+ @CommandLine.Option(names = { "--includes" }, description = "Test name include patterns")
+ String[] includes;
+
+ public TestRun(CamelJBangMain main) {
+ super(main);
+ }
+
+ @Override
+ public Integer doCall() throws Exception {
+ Path currentDir = Paths.get(".");
+
+ // Determine working directory (prefer test subfolder)
+ Path workDir;
+ if (currentDir.resolve(TEST_DIR).toFile().exists()) {
+ workDir = currentDir.resolve(TEST_DIR);
+ } else {
+ workDir = currentDir;
+ }
+
+ // Set up system properties
+ Map props = new HashMap<>();
+ if (properties != null) {
+ for (String prop : properties) {
+ String[] parts = prop.split("=", 2);
+ if (parts.length == 2) {
+ props.put(parts[0], parts[1]);
+ }
+ }
+ }
+
+ // Apply system properties
+ for (Map.Entry entry : props.entrySet()) {
+ System.setProperty(entry.getKey(), entry.getValue());
+ }
+
+ // Clean and create work directory
+ File citrusWorkDir = new File(WORK_DIR);
+ removeDir(citrusWorkDir);
+ if (!citrusWorkDir.mkdirs()) {
+ printer().println("Failed to create working directory " + WORK_DIR);
+ return 1;
+ }
+
+ // Resolve test sources
+ List testSources = new ArrayList<>();
+ resolveTests(files, testSources, workDir);
+
+ // If no explicit files given, scan current directory
+ if (testSources.isEmpty()) {
+ resolveTests(new String[] { workDir.toString() }, testSources, workDir);
+ }
+
+ if (testSources.isEmpty()) {
+ printer().println("No test files found");
+ return 1;
+ }
+
+ // Build test run configuration
+ TestRunConfiguration configuration = getRunConfiguration(testSources, workDir);
+
+ // Look up and run the test engine
+ TestEngine testEngine = TestEngine.lookup(configuration);
+ testEngine.run();
+
+ return 0;
+ }
+
+ /**
+ * Creates a test run configuration from the resolved test sources.
+ */
+ protected TestRunConfiguration getRunConfiguration(List testSources, Path workDir) {
+ String ext = FileUtils.getFileExtension(testSources.get(0));
+
+ TestRunConfiguration configuration = new TestRunConfiguration();
+ configuration.setWorkDir(workDir.toAbsolutePath().toString());
+
+ if (!"default".equals(engine)) {
+ configuration.setEngine(engine);
+ } else if ("feature".equals(ext)) {
+ configuration.setEngine("cucumber");
+ }
+
+ configuration.setVerbose(verbose);
+
+ if (includes != null) {
+ configuration.setIncludes(includes);
+ }
+
+ // Add test sources
+ List sources = new ArrayList<>();
+ for (String source : testSources) {
+ String sourceExt = FileUtils.getFileExtension(source);
+ String baseName = FileUtils.getBaseName(new File(source).getName());
+ sources.add(new TestSource(sourceExt, baseName, source));
+ }
+ configuration.setTestSources(sources);
+
+ return configuration;
+ }
+
+ /**
+ * Resolves test file paths from the given arguments. Handles both individual files and directories.
+ */
+ private void resolveTests(String[] testArgs, List resolved, Path workDir) {
+ if (testArgs == null) {
+ return;
+ }
+
+ for (String arg : testArgs) {
+ // Adjust path if it starts with test/ prefix and we're using the test subfolder
+ String filePath = arg;
+ if (filePath.startsWith(TEST_DIR + "/")) {
+ filePath = filePath.substring((TEST_DIR + "/").length());
+ }
+
+ File resolved0 = workDir.resolve(filePath).toFile();
+ if (!resolved0.exists()) {
+ resolved0 = new File(filePath);
+ }
+ final File testFile = resolved0;
+
+ if (testFile.isDirectory()) {
+ // Scan directory for test files
+ String[] dirFiles = testFile.list();
+ if (dirFiles != null) {
+ String[] fullPaths = Arrays.stream(dirFiles)
+ .filter(f -> !skipFile(f))
+ .map(f -> new File(testFile, f).getPath())
+ .toArray(String[]::new);
+ resolveTests(fullPaths, resolved, workDir);
+ }
+ } else if (testFile.exists() && !skipFile(testFile.getName())) {
+ resolved.add(testFile.getPath());
+ }
+ }
+ }
+
+ /**
+ * Checks if a file should be skipped based on its extension.
+ */
+ private boolean skipFile(String fileName) {
+ if (fileName.startsWith(".")) {
+ return true;
+ }
+ String ext = FileUtils.getFileExtension(fileName);
+ return Arrays.stream(ACCEPTED_FILE_EXT).noneMatch(e -> e.equals(ext));
+ }
+
+ /**
+ * Recursively removes a directory.
+ */
+ private static void removeDir(File dir) {
+ if (dir.exists()) {
+ delete(dir);
+ }
+ }
+
+ private static void delete(File file) {
+ if (file.isDirectory()) {
+ File[] children = file.listFiles();
+ if (children != null) {
+ for (File child : children) {
+ delete(child);
+ }
+ }
+ }
+ file.delete();
+ }
+}
diff --git a/dsl/camel-jbang/camel-jbang-plugin-test/src/main/resources/templates/citrus-feature.tmpl b/dsl/camel-jbang/camel-jbang-plugin-test/src/main/resources/templates/citrus-feature.tmpl
new file mode 100644
index 0000000000000..88c4e347d8a12
--- /dev/null
+++ b/dsl/camel-jbang/camel-jbang-plugin-test/src/main/resources/templates/citrus-feature.tmpl
@@ -0,0 +1,8 @@
+Feature: {{ .Name }}
+
+ Background:
+ Given variables
+ | message | "Citrus rocks!" |
+
+ Scenario: Print message
+ Then print '${message}'
diff --git a/dsl/camel-jbang/camel-jbang-plugin-test/src/main/resources/templates/citrus-groovy.tmpl b/dsl/camel-jbang/camel-jbang-plugin-test/src/main/resources/templates/citrus-groovy.tmpl
new file mode 100644
index 0000000000000..0acce60ab4ccc
--- /dev/null
+++ b/dsl/camel-jbang/camel-jbang-plugin-test/src/main/resources/templates/citrus-groovy.tmpl
@@ -0,0 +1,5 @@
+variables {
+ message = "Citrus rocks!"
+}
+
+$(echo('${message}'))
diff --git a/dsl/camel-jbang/camel-jbang-plugin-test/src/main/resources/templates/citrus-java.tmpl b/dsl/camel-jbang/camel-jbang-plugin-test/src/main/resources/templates/citrus-java.tmpl
new file mode 100644
index 0000000000000..f99d9dbac01e3
--- /dev/null
+++ b/dsl/camel-jbang/camel-jbang-plugin-test/src/main/resources/templates/citrus-java.tmpl
@@ -0,0 +1,21 @@
+import org.citrusframework.TestActionSupport;
+import org.citrusframework.TestCaseRunner;
+import org.citrusframework.annotations.CitrusResource;
+
+
+public class {{ .Name }} implements Runnable, TestActionSupport {
+
+ @CitrusResource
+ TestCaseRunner t;
+
+ @Override
+ public void run() {
+ t.given(
+ createVariables().variable("message", "Citrus rocks!")
+ );
+
+ t.then(
+ echo().message("${message}")
+ );
+ }
+}
diff --git a/dsl/camel-jbang/camel-jbang-plugin-test/src/main/resources/templates/citrus-xml.tmpl b/dsl/camel-jbang/camel-jbang-plugin-test/src/main/resources/templates/citrus-xml.tmpl
new file mode 100644
index 0000000000000..e394315b7f6b4
--- /dev/null
+++ b/dsl/camel-jbang/camel-jbang-plugin-test/src/main/resources/templates/citrus-xml.tmpl
@@ -0,0 +1,12 @@
+
+ Sample test in XML
+
+
+
+
+
+
+
+
diff --git a/dsl/camel-jbang/camel-jbang-plugin-test/src/main/resources/templates/citrus-yaml.tmpl b/dsl/camel-jbang/camel-jbang-plugin-test/src/main/resources/templates/citrus-yaml.tmpl
new file mode 100644
index 0000000000000..c88c446241158
--- /dev/null
+++ b/dsl/camel-jbang/camel-jbang-plugin-test/src/main/resources/templates/citrus-yaml.tmpl
@@ -0,0 +1,10 @@
+name: {{ .Name }}
+author: Citrus
+status: FINAL
+description: Sample test in YAML
+variables:
+ - name: message
+ value: Citrus rocks!
+actions:
+ - echo:
+ message: "${message}"
diff --git a/dsl/camel-jbang/camel-launcher/pom.xml b/dsl/camel-jbang/camel-launcher/pom.xml
index dbb49c2668662..4d1cd8f45e45c 100644
--- a/dsl/camel-jbang/camel-launcher/pom.xml
+++ b/dsl/camel-jbang/camel-launcher/pom.xml
@@ -66,12 +66,16 @@
-
org.apache.camel
camel-jbang-plugin-generate
${project.version}
+
+ org.apache.camel
+ camel-jbang-plugin-test
+ ${project.version}
+
org.apache.camel
camel-jbang-plugin-kubernetes
diff --git a/dsl/camel-jbang/camel-launcher/src/main/java/org/apache/camel/dsl/jbang/launcher/CamelLauncherMain.java b/dsl/camel-jbang/camel-launcher/src/main/java/org/apache/camel/dsl/jbang/launcher/CamelLauncherMain.java
index 594c916bfb810..8acfc37760ae1 100644
--- a/dsl/camel-jbang/camel-launcher/src/main/java/org/apache/camel/dsl/jbang/launcher/CamelLauncherMain.java
+++ b/dsl/camel-jbang/camel-launcher/src/main/java/org/apache/camel/dsl/jbang/launcher/CamelLauncherMain.java
@@ -19,6 +19,7 @@
import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
import org.apache.camel.dsl.jbang.core.commands.generate.GeneratePlugin;
import org.apache.camel.dsl.jbang.core.commands.kubernetes.KubernetesPlugin;
+import org.apache.camel.dsl.jbang.core.commands.test.TestPlugin;
import org.apache.camel.dsl.jbang.core.commands.validate.ValidatePlugin;
import picocli.CommandLine;
@@ -32,6 +33,7 @@ public void postAddCommands(CommandLine commandLine, String[] args) {
// install embedded plugins
new GeneratePlugin().customize(commandLine, this);
new KubernetesPlugin().customize(commandLine, this);
+ new TestPlugin().customize(commandLine, this);
new ValidatePlugin().customize(commandLine, this);
}