Skip to content

Commit

Permalink
chore: Add endpoint config Groovy action
Browse files Browse the repository at this point in the history
- Allows users to create new endpoints with Groovy DSL scripts
- Allows users to add beans to the Citrus registry with Groovy DSL scripts
  • Loading branch information
christophd committed Dec 5, 2024
1 parent 421067f commit 0c414c9
Show file tree
Hide file tree
Showing 29 changed files with 1,272 additions and 94 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -350,9 +350,7 @@ public List<String> getValues() {
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"value"
})
@XmlType(name = "")
public static class Script {

@XmlValue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,7 @@ public void setResult(String result) {
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"type"
})
@XmlType(name = "")
public static class Language {
@XmlAttribute
protected String type = "simple";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,10 @@ public static <T> T run(ImportCustomizer ic, Object delegate, String scriptCode,
((GroovyScript) script).setDelegate(delegate);
}

((GroovyScript) script).setCitrusFramework(citrus);
if (citrus != null) {
((GroovyScript) script).setCitrusFramework(citrus);
}

((GroovyScript) script).setContext(context);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import org.citrusframework.context.TestContext;
import org.citrusframework.exceptions.CitrusRuntimeException;
import org.citrusframework.script.GroovyActionBuilder;
import org.citrusframework.spi.Resource;
import org.citrusframework.util.FileUtils;
import org.codehaus.groovy.control.customizers.ImportCustomizer;
Expand All @@ -41,6 +42,14 @@ public static GroovySupport groovy() {
return new GroovySupport();
}

/**
* Delegates to Groovy test actions.
* @return
*/
public GroovyActionBuilder actions() {
return GroovyActionBuilder.groovy();
}

/**
* Loads given Groovy script and return the constructed Java object.
* @param script
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,36 @@
import java.util.Locale;

import groovy.lang.Closure;
import groovy.lang.DelegatesTo;
import groovy.lang.GroovyObjectSupport;
import groovy.lang.GroovyRuntimeException;
import groovy.lang.MissingMethodException;
import org.citrusframework.Citrus;
import org.citrusframework.CitrusContext;
import org.citrusframework.exceptions.CitrusRuntimeException;
import org.citrusframework.message.DefaultMessageQueue;
import org.citrusframework.spi.ReferenceResolver;

public class BeansConfiguration extends GroovyObjectSupport {

private final Citrus citrus;
private final ReferenceResolver referenceResolver;

public BeansConfiguration(Citrus citrus) {
this.citrus = citrus;
this(citrus.getCitrusContext());
}

public BeansConfiguration(CitrusContext citrusContext) {
this(citrusContext.getReferenceResolver());
}

public BeansConfiguration(ReferenceResolver referenceResolver) {
this.referenceResolver = referenceResolver;
}

public void beans(@DelegatesTo(BeansConfiguration.class) Closure<?> callable) {
callable.setResolveStrategy(Closure.DELEGATE_FIRST);
callable.setDelegate(this);
callable.call();
}

public void bean(Class<?> type) {
Expand All @@ -41,18 +58,31 @@ public void bean(Class<?> type) {

public void bean(String name, Class<?> type) {
try {
citrus.getCitrusContext().bind(name, type.getConstructor().newInstance());
referenceResolver.bind(name, type.getConstructor().newInstance());
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
throw new CitrusRuntimeException(String.format("Failed to instantiate bean of type '%s' - no default constructor available", type));
}
}

public void bean(String name, Class<?> type, Closure<?> callable) {
try {
Object bean = type.getDeclaredConstructor().newInstance();
callable.setResolveStrategy(Closure.DELEGATE_ONLY);
callable.setDelegate(bean);
callable.call();

referenceResolver.bind(name, bean);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
throw new CitrusRuntimeException(String.format("Failed to instantiate bean of type '%s' - no default constructor available", type));
}
}

public void queue(String name) {
citrus.getCitrusContext().bind(name, new DefaultMessageQueue(name));
referenceResolver.bind(name, new DefaultMessageQueue(name));
}

public void propertyMissing(String name, Object value) {
citrus.getCitrusContext().bind(name, value);
referenceResolver.bind(name, value);
}

public Object methodMissing(String name, Object argLine) {
Expand All @@ -71,7 +101,7 @@ public Object methodMissing(String name, Object argLine) {
closure.setDelegate(bean);
closure.call();

citrus.getCitrusContext().bind(name, bean);
referenceResolver.bind(name, bean);
return bean;
} catch (IllegalAccessException | InstantiationException | InvocationTargetException | NoSuchMethodException e) {
throw new GroovyRuntimeException(String.format("Failed to instantiate bean of type '%s'", type), e);
Expand All @@ -82,7 +112,7 @@ public Object methodMissing(String name, Object argLine) {
closure.setResolveStrategy(Closure.DELEGATE_ONLY);

Object bean = closure.call();
citrus.getCitrusContext().bind(name, bean);
referenceResolver.bind(name, bean);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,27 @@
package org.citrusframework.groovy.dsl.configuration.beans;

import org.citrusframework.Citrus;
import org.citrusframework.CitrusContext;
import org.citrusframework.message.DefaultMessageQueue;
import org.citrusframework.spi.ReferenceResolver;

public class QueueConfiguration {

private final Citrus citrus;
private final ReferenceResolver referenceResolver;

public QueueConfiguration(Citrus citrus) {
this.citrus = citrus;
this(citrus.getCitrusContext());
}

public QueueConfiguration(CitrusContext citrusContext) {
this(citrusContext.getReferenceResolver());
}

public QueueConfiguration(ReferenceResolver referenceResolver) {
this.referenceResolver = referenceResolver;
}

public void queue(String name) {
citrus.getCitrusContext().bind(name, new DefaultMessageQueue(name));
referenceResolver.bind(name, new DefaultMessageQueue(name));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,54 @@
package org.citrusframework.groovy.dsl.configuration.endpoints;

import org.citrusframework.Citrus;
import org.citrusframework.CitrusContext;
import org.citrusframework.common.InitializingPhase;
import org.citrusframework.context.TestContext;
import org.citrusframework.endpoint.Endpoint;
import org.citrusframework.groovy.dsl.GroovyShellUtils;
import org.citrusframework.spi.ReferenceResolver;
import org.citrusframework.spi.ReferenceResolverAware;
import org.codehaus.groovy.control.customizers.ImportCustomizer;

public class EndpointConfigurationScript {
public class EndpointConfigurationScript implements ReferenceResolverAware {

private final Citrus citrus;
private ReferenceResolver referenceResolver;

private final String script;

public EndpointConfigurationScript(String script, Citrus citrus) {
this(script, citrus.getCitrusContext());
}

public EndpointConfigurationScript(String script, CitrusContext citrusContext) {
this(script, citrusContext.getReferenceResolver());
}

public EndpointConfigurationScript(String script, ReferenceResolver referenceResolver) {
this.script = script;
this.referenceResolver = referenceResolver;
}

public EndpointConfigurationScript(String script) {
this.script = script;
this.citrus = citrus;
}

public void execute(TestContext context) {
EndpointsConfiguration configuration = new EndpointsConfiguration();
ImportCustomizer ic = new ImportCustomizer();
GroovyShellUtils.run(ic, configuration, context.replaceDynamicContentInString(script), citrus, context);
GroovyShellUtils.run(ic, configuration, context.replaceDynamicContentInString(script), null, context);

configuration.getEndpoints().forEach(endpoint -> {
onCreate(endpoint);
if (endpoint instanceof InitializingPhase) {
((InitializingPhase) endpoint).initialize();
}
citrus.getCitrusContext().bind(endpoint.getName(), endpoint);

if (referenceResolver != null) {
referenceResolver.bind(endpoint.getName(), endpoint);
} else {
context.getReferenceResolver().bind(endpoint.getName(), endpoint);
}
});
}

Expand All @@ -54,4 +74,9 @@ public void execute(TestContext context) {
*/
protected void onCreate(Endpoint endpoint) {
}

@Override
public void setReferenceResolver(ReferenceResolver referenceResolver) {
this.referenceResolver = referenceResolver;
}
}
Loading

0 comments on commit 0c414c9

Please sign in to comment.