diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e1943121b..a09db78b2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -36,3 +36,4 @@ jobs: -Dsonar.projectKey=abstracto-abstracto -Dsonar.java.binaries=**/target/classes -Dsonar.coverage.jacoco.xmlReportPaths=abstracto-application/coverage/target/site/jacoco-aggregate/jacoco.xml + -Dsonar.coverage.exclusions=**/*Test.java diff --git a/abstracto-application/coverage/pom.xml b/abstracto-application/coverage/pom.xml index 5adf8bbff..70b57073e 100644 --- a/abstracto-application/coverage/pom.xml +++ b/abstracto-application/coverage/pom.xml @@ -86,6 +86,11 @@ org.jacoco jacoco-maven-plugin + + + **/*Test.java + + report-aggregate diff --git a/abstracto-application/pom.xml b/abstracto-application/pom.xml index 5f77b768d..77cf50638 100644 --- a/abstracto-application/pom.xml +++ b/abstracto-application/pom.xml @@ -33,12 +33,6 @@ org.apache.maven.plugins maven-surefire-plugin 2.19.1 - - - **/*IntegrationTest.java - - 1 - @@ -50,7 +44,12 @@ org.jacoco jacoco-maven-plugin - 0.7.9 + 0.8.5 + + + **/*Test.java + + prepare-unit-tests @@ -63,6 +62,7 @@ + diff --git a/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/methods/DurationMethod.java b/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/methods/DurationMethod.java index a202f5ddb..d436cb4e2 100644 --- a/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/methods/DurationMethod.java +++ b/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/methods/DurationMethod.java @@ -34,7 +34,11 @@ public class DurationMethod implements TemplateMethodModelEx { if (arguments.size() != 1) { throw new TemplateModelException("Incorrect parameters passed."); } - Object wrappedObject = ((StringModel) arguments.get(0)).getWrappedObject(); + Object o = arguments.get(0); + if(!(o instanceof StringModel)) { + throw new TemplateModelException("Passed object was not a StringModel."); + } + Object wrappedObject = ((StringModel) o).getWrappedObject(); if(!(wrappedObject instanceof Duration)) { throw new TemplateModelException("Passed argument was not a duration object"); } diff --git a/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/methods/SafeFieldIterations.java b/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/methods/SafeFieldIterations.java index 7496c41a8..986f70aba 100644 --- a/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/methods/SafeFieldIterations.java +++ b/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/methods/SafeFieldIterations.java @@ -20,15 +20,38 @@ public class SafeFieldIterations implements TemplateMethodModelEx { @Override public Object exec(List arguments) throws TemplateModelException { - List wrappedObject = (List) ((DefaultListAdapter) arguments.get(0)).getWrappedObject(); - String appliedTemplate = ((SimpleScalar) arguments.get(1)).getAsString(); - String nameTemplate = ((SimpleScalar) arguments.get(2)).getAsString(); - String inline = ((SimpleScalar) arguments.get(3)).getAsString(); + if(arguments.size() != 4) { + throw new TemplateModelException("Incorrect amount of parameters."); + } + Object adapterObject = arguments.get(0); + if(!(adapterObject instanceof DefaultListAdapter)) { + throw new TemplateModelException("Passed object was not a DefaultListAdapter."); + } + Object wrappedList = ((DefaultListAdapter) adapterObject).getWrappedObject(); + if(!(wrappedList instanceof List)) { + throw new TemplateModelException("Passed object was not a List."); + } + List wrappedObject = (List) wrappedList; + Object templateParameter = arguments.get(1); + if(!(templateParameter instanceof SimpleScalar)) { + throw new TemplateModelException("Passed object for template was not a SimpleScalar."); + } + String appliedTemplate = ((SimpleScalar) templateParameter).getAsString(); + Object fieldNameTemplateParameter = arguments.get(2); + if(!(fieldNameTemplateParameter instanceof SimpleScalar)) { + throw new TemplateModelException("Passed object for field name template was not a SimpleScalar."); + } + String fieldNameTemplate = ((SimpleScalar) fieldNameTemplateParameter).getAsString(); + Object inlineParameter = arguments.get(3); + if(!(inlineParameter instanceof SimpleScalar)) { + throw new TemplateModelException("Passed object for inline was not a SimpleScalar."); + } + String inline = ((SimpleScalar) inlineParameter).getAsString(); List result = new ArrayList<>(); StringBuilder currentBuilder = new StringBuilder(); - String firstEmbedTitle = service.renderTemplateWithMap(nameTemplate, getEmbedCountParameters(1, wrappedObject)); + String firstEmbedTitle = service.renderTemplateWithMap(fieldNameTemplate, getEmbedCountParameters(1, wrappedObject)); currentBuilder.append(newFieldHeader(firstEmbedTitle, inline)); String finalClosingString = "\"}"; String closingString = finalClosingString + ","; @@ -42,7 +65,7 @@ public class SafeFieldIterations implements TemplateMethodModelEx { result.add(currentBuilder); currentBuilder = new StringBuilder(); splitFieldCounts += 1; - String renderedName = service.renderTemplateWithMap(nameTemplate, getEmbedCountParameters(splitFieldCounts, wrappedObject)); + String renderedName = service.renderTemplateWithMap(fieldNameTemplate, getEmbedCountParameters(splitFieldCounts, wrappedObject)); currentBuilder.append(newFieldHeader(renderedName, inline)); } currentBuilder.append(s); @@ -54,14 +77,14 @@ public class SafeFieldIterations implements TemplateMethodModelEx { for (StringBuilder innerBuilder: result) { bigBuilder.append(innerBuilder.toString()); } - return bigBuilder; + return bigBuilder.toString(); } private String newFieldHeader(String name, String inline) { return String.format("{ \"name\": \"%s\", \"inline\": \"%s\", \"value\": \"", name, inline); } - private HashMap getEmbedCountParameters(Integer count, List objects) { + private HashMap getEmbedCountParameters(Integer count, List objects) { HashMap parameters = new HashMap<>(); parameters.put("count", count); parameters.put("list", objects); diff --git a/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/model/EmbedAuthor.java b/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/model/EmbedAuthor.java index f1cf139b6..5b4e4d8d7 100644 --- a/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/model/EmbedAuthor.java +++ b/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/model/EmbedAuthor.java @@ -1,6 +1,7 @@ package dev.sheldan.abstracto.templating.model; +import lombok.Builder; import lombok.Getter; import lombok.Setter; @@ -9,6 +10,7 @@ import lombok.Setter; */ @Getter @Setter +@Builder public class EmbedAuthor { /** * The name used in the {@link net.dv8tion.jda.api.entities.MessageEmbed} author diff --git a/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/model/EmbedColor.java b/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/model/EmbedColor.java index d19343a80..5b967836f 100644 --- a/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/model/EmbedColor.java +++ b/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/model/EmbedColor.java @@ -1,5 +1,6 @@ package dev.sheldan.abstracto.templating.model; +import lombok.Builder; import lombok.Getter; import lombok.Setter; @@ -8,6 +9,7 @@ import lombok.Setter; */ @Setter @Getter +@Builder public class EmbedColor { /** * The red part of RGB diff --git a/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/model/EmbedConfiguration.java b/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/model/EmbedConfiguration.java index 885983691..93e956724 100644 --- a/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/model/EmbedConfiguration.java +++ b/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/model/EmbedConfiguration.java @@ -1,5 +1,6 @@ package dev.sheldan.abstracto.templating.model; +import lombok.Builder; import lombok.Getter; import lombok.Setter; @@ -12,6 +13,7 @@ import java.util.List; */ @Getter @Setter +@Builder public class EmbedConfiguration { /** * The {@link EmbedAuthor} object holding the configuration for the author of the {@link net.dv8tion.jda.api.entities.MessageEmbed} diff --git a/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/model/EmbedFooter.java b/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/model/EmbedFooter.java index 9db206e2b..d80b975b7 100644 --- a/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/model/EmbedFooter.java +++ b/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/model/EmbedFooter.java @@ -1,5 +1,6 @@ package dev.sheldan.abstracto.templating.model; +import lombok.Builder; import lombok.Getter; import lombok.Setter; @@ -8,6 +9,7 @@ import lombok.Setter; */ @Getter @Setter +@Builder public class EmbedFooter { /** * The text which is going to be used as the footer text diff --git a/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/model/EmbedTitle.java b/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/model/EmbedTitle.java index 9162bdd2c..95d8a782c 100644 --- a/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/model/EmbedTitle.java +++ b/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/model/EmbedTitle.java @@ -1,5 +1,6 @@ package dev.sheldan.abstracto.templating.model; +import lombok.Builder; import lombok.Getter; import lombok.Setter; @@ -8,6 +9,7 @@ import lombok.Setter; */ @Getter @Setter +@Builder public class EmbedTitle { /** * The text which is going to be used as the title of the embed diff --git a/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/service/TemplateServiceBean.java b/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/service/TemplateServiceBean.java index 6fefe8f05..b6ff0419b 100644 --- a/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/service/TemplateServiceBean.java +++ b/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/service/TemplateServiceBean.java @@ -2,18 +2,20 @@ package dev.sheldan.abstracto.templating.service; import com.google.gson.Gson; import dev.sheldan.abstracto.templating.Templatable; +import dev.sheldan.abstracto.templating.exception.TemplatingException; import dev.sheldan.abstracto.templating.model.*; import freemarker.template.Configuration; +import freemarker.template.Template; import freemarker.template.TemplateException; import lombok.extern.slf4j.Slf4j; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.MessageEmbed; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.springframework.ui.freemarker.FreeMarkerTemplateUtils; import java.awt.*; import java.io.IOException; +import java.io.StringWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -89,7 +91,7 @@ public class TemplateServiceBean implements TemplateService { firstBuilder.setFooter(footer.getText(), footer.getIcon()); } if(embedConfiguration.getFields() != null) { - createFieldsForEmbed(key, embedBuilders, embedConfiguration); + createFieldsForEmbed(embedBuilders, embedConfiguration); } firstBuilder.setTimestamp(embedConfiguration.getTimeStamp()); @@ -112,18 +114,14 @@ public class TemplateServiceBean implements TemplateService { .build(); } - private void createFieldsForEmbed(String key, List embedBuilders, EmbedConfiguration configuration) { + private void createFieldsForEmbed(List embedBuilders, EmbedConfiguration configuration) { for (int i = 0; i < configuration.getFields().size(); i++) { EmbedField field = configuration.getFields().get(i); - if(field != null && field.getValue() != null) { - if(field.getValue().length() > MessageEmbed.VALUE_MAX_LENGTH) { - String substring = field.getValue().substring(MessageEmbed.VALUE_MAX_LENGTH); - field.setValue(field.getValue().substring(0, MessageEmbed.VALUE_MAX_LENGTH)); - EmbedField secondPart = EmbedField.builder().inline(field.getInline()).name(field.getName() + " 2").value(substring).build(); - configuration.getFields().add(i + 1, secondPart); - } - } else { - log.warn("Field {} in template {} is null.", i, key); + if(field != null && field.getValue() != null && field.getValue().length() > MessageEmbed.VALUE_MAX_LENGTH) { + String substring = field.getValue().substring(MessageEmbed.VALUE_MAX_LENGTH); + field.setValue(field.getValue().substring(0, MessageEmbed.VALUE_MAX_LENGTH)); + EmbedField secondPart = EmbedField.builder().inline(field.getInline()).name(field.getName() + " 2").value(substring).build(); + configuration.getFields().add(i + 1, secondPart); } } double neededIndex = Math.ceil(configuration.getFields().size() / 25D) - 1; @@ -161,10 +159,10 @@ public class TemplateServiceBean implements TemplateService { @Override public String renderTemplateWithMap(String key, HashMap parameters) { try { - return FreeMarkerTemplateUtils.processTemplateIntoString(configuration.getTemplate(key), parameters); + return renderTemplateToString(key, parameters); } catch (IOException | TemplateException e) { log.warn("Failed to render template. ", e); - throw new RuntimeException(e); + throw new TemplatingException(e); } } @@ -177,13 +175,28 @@ public class TemplateServiceBean implements TemplateService { @Override public String renderTemplate(String key, Object model) { try { - return FreeMarkerTemplateUtils.processTemplateIntoString(configuration.getTemplate(key), model); + return renderTemplateToString(key, model); } catch (IOException | TemplateException e) { log.warn("Failed to render template. ", e); - throw new RuntimeException(e); + throw new TemplatingException(e); } } + /** + * Loads the given key as a template, and renders it, returns the result as a String + * @param key The key of the template to render + * @param model The parameters which are given to the template + * @return The rendered template in a String + * @throws freemarker.template.TemplateNotFoundException In case the template could not be found + * @throws TemplateException In case the rendering failed + */ + private String renderTemplateToString(String key, Object model) throws IOException, TemplateException { + StringWriter result = new StringWriter(); + Template template = configuration.getTemplate(key); + template.process(model, result); + return result.toString(); + } + /** * Renders a simple template identified by key without any model. This will cause exceptions in case there are references to a model in the provided template. * @param key The key of the template to be rendered diff --git a/abstracto-application/templating/templating-impl/src/test/java/dev/sheldan/abstracto/templating/loading/TemplateLoaderTest.java b/abstracto-application/templating/templating-impl/src/test/java/dev/sheldan/abstracto/templating/loading/TemplateLoaderTest.java new file mode 100644 index 000000000..6bd245557 --- /dev/null +++ b/abstracto-application/templating/templating-impl/src/test/java/dev/sheldan/abstracto/templating/loading/TemplateLoaderTest.java @@ -0,0 +1,53 @@ +package dev.sheldan.abstracto.templating.loading; + +import dev.sheldan.abstracto.templating.model.database.Template; +import dev.sheldan.abstracto.templating.service.management.TemplateManagementService; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import java.io.IOException; +import java.io.Reader; +import java.util.Optional; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class TemplateLoaderTest { + + public static final String TEST_CONTENT = "test"; + public static final String TEMPLATE_KEY = "key"; + + @InjectMocks + private DatabaseTemplateLoader loader; + + @Mock + private TemplateManagementService templateManagementService; + + + @Test + public void testProperLoading() throws IOException { + Template mocked = Template.builder().key(TEMPLATE_KEY).content(TEST_CONTENT).build(); + when(templateManagementService.getTemplateByKey(TEMPLATE_KEY)).thenReturn(Optional.of(mocked)); + Template templateSource = (Template) loader.findTemplateSource(TEMPLATE_KEY); + assertThat(TEST_CONTENT, equalTo(templateSource.getContent())); + } + + @Test(expected = IOException.class) + public void testMissingTemplate() throws IOException { + loader.findTemplateSource(TEMPLATE_KEY); + } + + @Test + public void testReader() throws IOException { + Template mocked = Template.builder().key(TEMPLATE_KEY).content(TEST_CONTENT).build(); + Reader reader = loader.getReader(mocked, null); + char[] chars = new char[4]; + reader.read(chars, 0, 4); + assertThat(TEST_CONTENT, equalTo(new String(chars))); + } +} diff --git a/abstracto-application/templating/templating-impl/src/test/java/dev/sheldan/abstracto/templating/methods/DateMethodTest.java b/abstracto-application/templating/templating-impl/src/test/java/dev/sheldan/abstracto/templating/methods/DateMethodTest.java new file mode 100644 index 000000000..395343ca2 --- /dev/null +++ b/abstracto-application/templating/templating-impl/src/test/java/dev/sheldan/abstracto/templating/methods/DateMethodTest.java @@ -0,0 +1,113 @@ +package dev.sheldan.abstracto.templating.methods; + +import freemarker.ext.beans.StringModel; +import freemarker.template.*; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.junit.MockitoJUnitRunner; + +import java.time.Instant; +import java.time.OffsetDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@RunWith(MockitoJUnitRunner.class) +public class DateMethodTest { + + public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss"; + public static final Instant DATE = Instant.ofEpochSecond(1590615937); + + @InjectMocks + private DateMethod dateMethod; + + @Test + public void testInstantFormat() throws TemplateModelException { + String exec = (String) dateMethod.exec(getCorrectParametersInstant()); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_TIME_FORMAT) + .withZone(ZoneId.systemDefault()); + Assert.assertEquals(exec, formatter.format(DATE)); + } + + @Test + public void testOffsetDateTimeObject() throws TemplateModelException { + String exec = (String) dateMethod.exec(getCorrectParametersOffsetDateTime()); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_TIME_FORMAT) + .withZone(ZoneId.systemDefault()); + Assert.assertEquals(exec, formatter.format(DATE)); + } + + @Test(expected = TemplateModelException.class) + public void incorrectParameterCount() throws TemplateModelException { + dateMethod.exec(new ArrayList()); + } + + @Test(expected = IllegalArgumentException.class) + public void testIncorrectDateFormat() throws TemplateModelException { + dateMethod.exec(getIncorrectDateFormat()); + } + + @Test(expected = TemplateModelException.class) + public void incorrectPassedObject() throws TemplateModelException { + dateMethod.exec(getIncorrectTimeParameter()); + } + + private List getIncorrectDateFormat() { + List params = new ArrayList<>(); + params.add(getInstantDateObject()); + params.add(incorrectDateFormat()); + return params; + } + + private List getIncorrectTimeParameter() { + List params = new ArrayList<>(); + params.add(getNotCompatibleObject()); + params.add(incorrectDateFormat()); + return params; + } + + + private List getCorrectParametersInstant() { + List params = new ArrayList<>(); + params.add(getInstantDateObject()); + params.add(simpleDateFormat()); + return params; + } + + private List getCorrectParametersOffsetDateTime() { + List params = new ArrayList<>(); + params.add(getOffsetDateTimeObject()); + params.add(simpleDateFormat()); + return params; + } + + private SimpleScalar simpleDateFormat() { + return new SimpleScalar(DATE_TIME_FORMAT); + } + + private SimpleScalar incorrectDateFormat() { + return new SimpleScalar("INCORRECT"); + } + + private StringModel getInstantDateObject() { + DefaultObjectWrapper wrapper = getWrapper(); + return new StringModel(DATE, wrapper); + } + + private DefaultObjectWrapper getWrapper() { + return new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_0).build(); + } + + private StringModel getOffsetDateTimeObject() { + DefaultObjectWrapper wrapper = getWrapper(); + return new StringModel(OffsetDateTime.ofInstant(DATE, ZoneId.systemDefault()), wrapper); + } + + private StringModel getNotCompatibleObject() { + DefaultObjectWrapper wrapper = getWrapper(); + return new StringModel("", wrapper); + } +} diff --git a/abstracto-application/templating/templating-impl/src/test/java/dev/sheldan/abstracto/templating/methods/DurationMethodTest.java b/abstracto-application/templating/templating-impl/src/test/java/dev/sheldan/abstracto/templating/methods/DurationMethodTest.java new file mode 100644 index 000000000..0db096724 --- /dev/null +++ b/abstracto-application/templating/templating-impl/src/test/java/dev/sheldan/abstracto/templating/methods/DurationMethodTest.java @@ -0,0 +1,124 @@ +package dev.sheldan.abstracto.templating.methods; + +import dev.sheldan.abstracto.templating.service.TemplateService; +import freemarker.ext.beans.StringModel; +import freemarker.template.Configuration; +import freemarker.template.DefaultObjectWrapper; +import freemarker.template.DefaultObjectWrapperBuilder; +import freemarker.template.TemplateModelException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import static org.mockito.Mockito.*; +import org.mockito.junit.MockitoJUnitRunner; + +import java.time.Duration; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; + +@RunWith(MockitoJUnitRunner.class) +public class DurationMethodTest { + public static final long SECOND_AMOUNT = 10L; + public static final long MINUTES_AMOUNT = 2L; + public static final long HOURS_AMOUNT = 3L; + public static final long DAYS_AMOUNT = 5L; + public static final String DURATION_TEMPLATE = "duration_formatting"; + public static final String SECONDS = "seconds"; + public static final String HOURS = "hours"; + public static final String MINUTES = "minutes"; + public static final String DAYS = "days"; + + @InjectMocks + private DurationMethod durationMethod; + + @Mock + private TemplateService templateService; + + + @Test + public void testSeconds() throws TemplateModelException { + durationMethod.exec(getSecondParameters()); + verify(templateService, times(1)).renderTemplateWithMap(DURATION_TEMPLATE, getHashMap(0, 0, 0, SECOND_AMOUNT)); + } + + @Test + public void testMinutes() throws TemplateModelException { + durationMethod.exec(getMinuteParameter()); + verify(templateService, times(1)).renderTemplateWithMap(DURATION_TEMPLATE, getHashMap(0, 0, MINUTES_AMOUNT, 0)); + } + + @Test + public void testHours() throws TemplateModelException { + durationMethod.exec(getHourParameter()); + verify(templateService, times(1)).renderTemplateWithMap(DURATION_TEMPLATE, getHashMap(0, HOURS_AMOUNT, 0, 0)); + } + + + @Test + public void testDays() throws TemplateModelException { + durationMethod.exec(getDayParameter()); + verify(templateService, times(1)).renderTemplateWithMap(DURATION_TEMPLATE, getHashMap(DAYS_AMOUNT, 0, 0, 0)); + } + + @Test + public void testAllTime() throws TemplateModelException { + durationMethod.exec(getMixedParameter()); + verify(templateService, times(1)).renderTemplateWithMap(DURATION_TEMPLATE, getHashMap(DAYS_AMOUNT, HOURS_AMOUNT, MINUTES_AMOUNT, SECOND_AMOUNT)); + } + + @Test(expected = TemplateModelException.class) + public void testNoParamGiven() throws TemplateModelException { + durationMethod.exec(Collections.emptyList()); + } + + @Test(expected = TemplateModelException.class) + public void testNoDurationObject() throws TemplateModelException { + durationMethod.exec(Arrays.asList(new StringModel("", getWrapper()))); + } + + @Test(expected = TemplateModelException.class) + public void testNoStringModelObject() throws TemplateModelException { + durationMethod.exec(Arrays.asList("")); + } + + + private List getSecondParameters() { + return Arrays.asList(new StringModel(Duration.ofSeconds(SECOND_AMOUNT), getWrapper())); + } + + private List getMinuteParameter() { + return Arrays.asList(new StringModel(Duration.ofMinutes(MINUTES_AMOUNT), getWrapper())); + } + + private List getHourParameter() { + return Arrays.asList(new StringModel(Duration.ofHours(HOURS_AMOUNT), getWrapper())); + } + + private List getDayParameter() { + return Arrays.asList(new StringModel(Duration.ofDays(DAYS_AMOUNT), getWrapper())); + } + + private List getMixedParameter() { + return Arrays.asList(new StringModel(Duration.ofSeconds(SECOND_AMOUNT) + .plus(Duration.ofMinutes(MINUTES_AMOUNT)) + .plus(Duration.ofHours(HOURS_AMOUNT)) + .plus(Duration.ofDays(DAYS_AMOUNT)), getWrapper())); + } + + private DefaultObjectWrapper getWrapper() { + return new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_0).build(); + } + + private HashMap getHashMap(long days, long hours, long minutes, long seconds) { + HashMap map = new HashMap<>(); + map.put(DAYS, days); + map.put(HOURS, hours); + map.put(MINUTES, minutes); + map.put(SECONDS, seconds); + return map; + } + +} diff --git a/abstracto-application/templating/templating-impl/src/test/java/dev/sheldan/abstracto/templating/methods/SafeFieldIterationsTest.java b/abstracto-application/templating/templating-impl/src/test/java/dev/sheldan/abstracto/templating/methods/SafeFieldIterationsTest.java new file mode 100644 index 000000000..3457178eb --- /dev/null +++ b/abstracto-application/templating/templating-impl/src/test/java/dev/sheldan/abstracto/templating/methods/SafeFieldIterationsTest.java @@ -0,0 +1,140 @@ +package dev.sheldan.abstracto.templating.methods; + +import dev.sheldan.abstracto.templating.service.TemplateService; +import freemarker.template.*; +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.*; +import static org.mockito.Mockito.times; + +@RunWith(MockitoJUnitRunner.class) +public class SafeFieldIterationsTest { + + public static final String TEMPLATE_KEY = "template"; + public static final String FIELD_NAME_TEMPLATE = "fieldName"; + public static final String FIELD_NAME_VALUE = "fieldName"; + public static final String EXPECTED_START_PART = "{ \"name\": \"" + FIELD_NAME_VALUE + "\", \"inline\": \"true\", \"value\": \""; + public static final String INLINE_VALUE = "true"; + public static final String FIRST_LIST_ENTRY = "text"; + public static final String SIX_HUNDRED_CHARACTERS = RandomStringUtils.randomAlphabetic(600); + + @InjectMocks + private SafeFieldIterations safeFieldIterations; + + @Mock + private TemplateService templateService; + + @Captor + private ArgumentCaptor templateKeyCaptor; + + + @Before + public void setup() { + when(templateService.renderTemplateWithMap(eq(FIELD_NAME_TEMPLATE), any())).thenReturn(FIELD_NAME_VALUE); + } + + @Test + public void testEmptyList() throws TemplateModelException { + String resultingValue = (String) safeFieldIterations.exec(getSimpleParameters()); + verify(templateService, times(1)).renderTemplateWithMap(templateKeyCaptor.capture(), any()); + List usedTemplateKeys = templateKeyCaptor.getAllValues(); + assertEquals(FIELD_NAME_TEMPLATE, usedTemplateKeys.get(0)); + assertEquals(EXPECTED_START_PART + "\"}", resultingValue); + } + + @Test + public void testOneElement() throws TemplateModelException { + when(templateService.renderTemplateWithMap(eq(TEMPLATE_KEY), any())).thenReturn(FIRST_LIST_ENTRY); + String resultingValue = (String) safeFieldIterations.exec(oneListEntryParameter()); + assertEquals(EXPECTED_START_PART + FIRST_LIST_ENTRY + "\"}", resultingValue); + } + + @Test + public void testTwoElements() throws TemplateModelException { + when(templateService.renderTemplateWithMap(eq(TEMPLATE_KEY), any())).thenReturn(FIRST_LIST_ENTRY); + String resultingValue = (String) safeFieldIterations.exec(twoListEntryParameter()); + assertEquals(EXPECTED_START_PART + FIRST_LIST_ENTRY + FIRST_LIST_ENTRY + "\"}", resultingValue); + } + + @Test + public void testElementsStaySolo() throws TemplateModelException { + when(templateService.renderTemplateWithMap(eq(TEMPLATE_KEY), any())).thenReturn(SIX_HUNDRED_CHARACTERS); + String resultingValue = (String) safeFieldIterations.exec(twoListEntryParameter()); + assertEquals(EXPECTED_START_PART + SIX_HUNDRED_CHARACTERS + "\"}," + EXPECTED_START_PART + SIX_HUNDRED_CHARACTERS + "\"}", resultingValue); + } + + @Test(expected = TemplateModelException.class) + public void testTooLittleParameters() throws TemplateModelException { + safeFieldIterations.exec(Arrays.asList("")); + } + + @Test(expected = TemplateModelException.class) + public void testWrongListAdapterType() throws TemplateModelException { + safeFieldIterations.exec(wrongListAdapter()); + } + + @Test(expected = TemplateModelException.class) + public void testWrongTemplateKeyParameterType() throws TemplateModelException { + safeFieldIterations.exec(wrongTemplateKeyParameterType()); + } + + @Test(expected = TemplateModelException.class) + public void testWrongFieldNameTemplateKeyParameterType() throws TemplateModelException { + safeFieldIterations.exec(wrongFieldNameTemplateKeyParameterType()); + } + + @Test(expected = TemplateModelException.class) + public void testWrongInlineParameterType() throws TemplateModelException { + safeFieldIterations.exec(wrongInLineValueParameterType()); + } + + + public List wrongListAdapter() { + return Arrays.asList(new Object(), new Object(), new SimpleScalar(FIELD_NAME_TEMPLATE), new SimpleScalar(INLINE_VALUE)); + } + + public List wrongTemplateKeyParameterType() { + return Arrays.asList(validEmptyList(), new Object(), new SimpleScalar(FIELD_NAME_TEMPLATE), new SimpleScalar(INLINE_VALUE)); + } + + public List wrongFieldNameTemplateKeyParameterType() { + return Arrays.asList(validEmptyList(), new SimpleScalar(TEMPLATE_KEY), new Object(), new SimpleScalar(INLINE_VALUE)); + } + + public List wrongInLineValueParameterType() { + return Arrays.asList(validEmptyList(), new SimpleScalar(TEMPLATE_KEY), new SimpleScalar(FIELD_NAME_TEMPLATE), new Object()); + } + + public List getSimpleParameters() { + return Arrays.asList(validEmptyList(), new SimpleScalar(TEMPLATE_KEY), new SimpleScalar(FIELD_NAME_TEMPLATE), new SimpleScalar(INLINE_VALUE)); + } + + private DefaultListAdapter validEmptyList() { + return DefaultListAdapter.adapt(new ArrayList(), getWrapper()); + } + + public List oneListEntryParameter() { + return Arrays.asList(DefaultListAdapter.adapt(Arrays.asList("testing"), getWrapper()), new SimpleScalar(TEMPLATE_KEY), new SimpleScalar(FIELD_NAME_TEMPLATE), new SimpleScalar(INLINE_VALUE)); + } + + public List twoListEntryParameter() { + return Arrays.asList(DefaultListAdapter.adapt(Arrays.asList("testing", "othertext"), getWrapper()), new SimpleScalar(TEMPLATE_KEY), new SimpleScalar(FIELD_NAME_TEMPLATE), new SimpleScalar(INLINE_VALUE)); + } + + private DefaultObjectWrapper getWrapper() { + return new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_0).build(); + } +} diff --git a/abstracto-application/templating/templating-impl/src/test/java/dev/sheldan/abstracto/templating/service/TemplateServiceBeanTest.java b/abstracto-application/templating/templating-impl/src/test/java/dev/sheldan/abstracto/templating/service/TemplateServiceBeanTest.java new file mode 100644 index 000000000..e0db15542 --- /dev/null +++ b/abstracto-application/templating/templating-impl/src/test/java/dev/sheldan/abstracto/templating/service/TemplateServiceBeanTest.java @@ -0,0 +1,330 @@ +package dev.sheldan.abstracto.templating.service; + +import com.google.gson.Gson; +import dev.sheldan.abstracto.templating.Templatable; +import dev.sheldan.abstracto.templating.exception.TemplatingException; +import dev.sheldan.abstracto.templating.model.*; +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateException; +import freemarker.template.TemplateNotFoundException; +import net.dv8tion.jda.api.entities.MessageEmbed; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.RandomStringUtils; +import org.jetbrains.annotations.NotNull; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.ui.freemarker.FreeMarkerConfigurationFactory; + +import java.awt.*; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; + +import static org.mockito.Mockito.*; + +@RunWith(MockitoJUnitRunner.class) +public class TemplateServiceBeanTest { + + public static final String EXAMPLE_URL = "https://example.com"; + public static final String FIELD_VALUE = "value"; + public static final String EMBED_PAGE_COUNT_TEMPLATE = "embed_page_count"; + public static final String FIELD_TEMPLATE = "{\n" + + "\"name\": \"name\",\n" + + "\"value\": \"value\",\n" + + "\"inline\": \"true\"\n" + + "}"; + + public static final String FIELD_TEMPLATE_WITH_VALUE = "{\n" + + "\"name\": \"name\",\n" + + "\"value\": \"%s\",\n" + + "\"inline\": \"true\"\n" + + "}"; + @InjectMocks + private TemplateServiceBean templateServiceBean; + + @Mock + private Configuration configuration; + + @Mock + private Gson gson; + + @Autowired + private Gson actualGsonInstance; + + private static final String SIMPLE_TEMPLATE_SOURCE = "source"; + private static final String TEMPLATE_KEY = "template"; + + @Test + public void testSimpleTemplate() throws IOException, TemplateException { + when(configuration.getTemplate(TEMPLATE_KEY)).thenReturn(getSimpleTemplate()); + String rendered = templateServiceBean.renderSimpleTemplate(TEMPLATE_KEY); + Assert.assertEquals(SIMPLE_TEMPLATE_SOURCE, rendered); + } + + @Test + public void renderTemplatable() throws IOException, TemplateException { + when(configuration.getTemplate(TEMPLATE_KEY)).thenReturn(getSimpleTemplate()); + Templatable templatable = getTemplatableWithSimpleTemplate(); + String rendered = templateServiceBean.renderTemplatable(templatable); + Assert.assertEquals(SIMPLE_TEMPLATE_SOURCE, rendered); + } + + @Test + public void testTemplateWithMapParameter() throws IOException, TemplateException { + when(configuration.getTemplate(TEMPLATE_KEY)).thenReturn(getSimpleTemplate()); + String rendered = templateServiceBean.renderTemplateWithMap(TEMPLATE_KEY, new HashMap<>()); + Assert.assertEquals(SIMPLE_TEMPLATE_SOURCE, rendered); + } + + @Test + public void testEmbedWithDescription() throws IOException, TemplateException { + String descriptionText = "test"; + String fullEmbedTemplateKey = getEmbedTemplateKey(); + when(configuration.getTemplate(fullEmbedTemplateKey)).thenReturn(getEmbedTemplateWithDescription(descriptionText)); + when(gson.fromJson(embedTemplateWithDescription(descriptionText), EmbedConfiguration.class)).thenReturn(embedConfigWithDescription(descriptionText)); + MessageToSend messageToSend = templateServiceBean.renderEmbedTemplate(TEMPLATE_KEY, new HashMap<>()); + Assert.assertEquals(descriptionText, messageToSend.getEmbeds().get(0).getDescription()); + } + + @Test + public void testEmbedWithAllUsableAttributes() throws IOException, TemplateException { + when(configuration.getTemplate(getEmbedTemplateKey())).thenReturn(getEmbedTemplateWithFallFieldsUsedOnce()); + when(gson.fromJson(getFullEmbedConfigString(), EmbedConfiguration.class)).thenReturn(getFullEmbedConfiguration()); + MessageToSend messageToSend = templateServiceBean.renderEmbedTemplate(TEMPLATE_KEY, new HashMap<>()); + Assert.assertEquals(messageToSend.getMessage(), "additionalMessage"); + MessageEmbed onlyEmbed = messageToSend.getEmbeds().get(0); + Assert.assertEquals(onlyEmbed.getAuthor().getIconUrl(), EXAMPLE_URL); + Assert.assertEquals(onlyEmbed.getAuthor().getName(), "name"); + Assert.assertEquals(onlyEmbed.getDescription(), "description"); + MessageEmbed.Field onlyField = onlyEmbed.getFields().get(0); + Assert.assertEquals(onlyField.getName(), "name"); + Assert.assertEquals(onlyField.getValue(), FIELD_VALUE); + Assert.assertTrue(onlyField.isInline()); + Color color = onlyEmbed.getColor(); + Assert.assertEquals(color.getBlue(), 255); + Assert.assertEquals(color.getRed(), 255); + Assert.assertEquals(color.getGreen(), 255); + Assert.assertEquals(onlyEmbed.getUrl(), EXAMPLE_URL); + Assert.assertEquals(onlyEmbed.getFooter().getText(), "text"); + Assert.assertEquals(onlyEmbed.getFooter().getIconUrl(), EXAMPLE_URL); + Assert.assertEquals(onlyEmbed.getImage().getUrl(), EXAMPLE_URL); + Assert.assertEquals(onlyEmbed.getThumbnail().getUrl(), EXAMPLE_URL); + Assert.assertEquals(1, messageToSend.getEmbeds().size()); + } + + @Test + public void testEmbedWithTooLongDescription() throws IOException, TemplateException { + int tooMuchCharacterCount = 1024; + String descriptionText = RandomStringUtils.randomAlphabetic(MessageEmbed.TEXT_MAX_LENGTH + tooMuchCharacterCount); + when(configuration.getTemplate(getEmbedTemplateKey())).thenReturn(getEmbedTemplateWithDescription(descriptionText)); + when(configuration.getTemplate(EMBED_PAGE_COUNT_TEMPLATE)).thenReturn(getPageCountTemplate(1)); + when(gson.fromJson(embedTemplateWithDescription(descriptionText), EmbedConfiguration.class)).thenReturn(embedConfigWithDescription(descriptionText)); + MessageToSend messageToSend = templateServiceBean.renderEmbedTemplate(TEMPLATE_KEY, new HashMap<>()); + MessageEmbed firstEmbed = messageToSend.getEmbeds().get(0); + Assert.assertEquals(MessageEmbed.TEXT_MAX_LENGTH, firstEmbed.getDescription().length()); + Assert.assertEquals(descriptionText.substring(0, MessageEmbed.TEXT_MAX_LENGTH), firstEmbed.getDescription()); + MessageEmbed secondEmbed = messageToSend.getEmbeds().get(1); + Assert.assertEquals(tooMuchCharacterCount, secondEmbed.getDescription().length()); + Assert.assertEquals(descriptionText.substring(MessageEmbed.TEXT_MAX_LENGTH, MessageEmbed.TEXT_MAX_LENGTH + tooMuchCharacterCount), secondEmbed.getDescription()); + } + + @Test + public void testEmbedWithTooManyFields() throws IOException, TemplateException { + int totalFieldCount = 30; + when(configuration.getTemplate(getEmbedTemplateKey())).thenReturn(getEmbedTemplateWithFieldCount(totalFieldCount)); + when(configuration.getTemplate(EMBED_PAGE_COUNT_TEMPLATE)).thenReturn(getPageCountTemplate(1)); + when(gson.fromJson(getFieldsEmbedConfigAsString(totalFieldCount), EmbedConfiguration.class)).thenReturn(getTooManyFieldsEmbedConfiguration()); + MessageToSend messageToSend = templateServiceBean.renderEmbedTemplate(TEMPLATE_KEY, new HashMap<>()); + MessageEmbed firstEmbed = messageToSend.getEmbeds().get(0); + Assert.assertEquals(25, firstEmbed.getFields().size()); + MessageEmbed secondEmbed = messageToSend.getEmbeds().get(1); + Assert.assertEquals(totalFieldCount % 25, secondEmbed.getFields().size()); + } + + @Test + public void testEmbedWithTooLongField() throws IOException, TemplateException { + String fieldValue = RandomStringUtils.randomAlphabetic(1500); + when(configuration.getTemplate(getEmbedTemplateKey())).thenReturn(getEmbedTemplateWithTooLongField(fieldValue)); + when(gson.fromJson(getSingleFieldWithValue(fieldValue), EmbedConfiguration.class)).thenReturn(getEmbedWithSingleFieldOfValue(fieldValue)); + MessageToSend messageToSend = templateServiceBean.renderEmbedTemplate(TEMPLATE_KEY, new HashMap<>()); + MessageEmbed firstEmbed = messageToSend.getEmbeds().get(0); + Assert.assertEquals(2, firstEmbed.getFields().size()); + Assert.assertEquals(fieldValue.substring(0, MessageEmbed.VALUE_MAX_LENGTH), firstEmbed.getFields().get(0).getValue()); + Assert.assertEquals(fieldValue.substring(MessageEmbed.VALUE_MAX_LENGTH), firstEmbed.getFields().get(1).getValue()); + } + + @Test(expected = TemplatingException.class) + public void tryToRenderMissingTemplate() throws IOException { + when(configuration.getTemplate(TEMPLATE_KEY)).thenThrow(new TemplateNotFoundException(TEMPLATE_KEY, new Object(), "")); + templateServiceBean.renderSimpleTemplate(TEMPLATE_KEY); + } + + @Test(expected = TemplatingException.class) + public void tryToRenderMissingEmbedTemplate() throws IOException { + when(configuration.getTemplate(getEmbedTemplateKey())).thenThrow(new TemplateNotFoundException(TEMPLATE_KEY, new Object(), "")); + templateServiceBean.renderEmbedTemplate(TEMPLATE_KEY, new Object()); + } + + @NotNull + private String getEmbedTemplateKey() { + return TEMPLATE_KEY + "_embed"; + } + + @Test(expected = TemplatingException.class) + public void tryToRenderMissingTemplateWithMap() throws IOException { + when(configuration.getTemplate(TEMPLATE_KEY)).thenThrow(new TemplateNotFoundException(TEMPLATE_KEY, new Object(), "")); + templateServiceBean.renderTemplateWithMap(TEMPLATE_KEY, new HashMap<>()); + } + + private EmbedConfiguration embedConfigWithDescription(String descriptionText) { + return EmbedConfiguration.builder().description(descriptionText).build(); + } + + private EmbedConfiguration getEmbedWithSingleFieldOfValue(String value) { + List fields = new ArrayList<>(); + fields.add(EmbedField.builder().name("name").value(value).build()); + return EmbedConfiguration.builder().fields(fields).build(); + } + + private EmbedConfiguration getTooManyFieldsEmbedConfiguration() { + List fields = new ArrayList<>(); + for (int i = 0; i < 30; i++) { + EmbedField field = EmbedField + .builder() + .value(FIELD_VALUE) + .inline(true) + .name("name") + .build(); + fields.add(field); + } + return EmbedConfiguration.builder().fields(fields).build(); + } + + private Templatable getTemplatableWithSimpleTemplate() { + return new Templatable() { + @Override + public String getTemplateName() { + return TEMPLATE_KEY; + } + + @Override + public Object getTemplateModel() { + return new Object(); + } + }; + } + + private EmbedConfiguration getFullEmbedConfiguration() { + + EmbedAuthor author = EmbedAuthor + .builder() + .avatar(EXAMPLE_URL) + .name("name") + .url(EXAMPLE_URL) + .build(); + + EmbedColor color = EmbedColor + .builder() + .r(255) + .g(255) + .b(255) + .build(); + + EmbedField field = EmbedField + .builder() + .value(FIELD_VALUE) + .inline(true) + .name("name") + .build(); + + EmbedFooter footer = EmbedFooter + .builder() + .icon(EXAMPLE_URL) + .text("text") + .build(); + + EmbedTitle title = EmbedTitle + .builder() + .title("title") + .url(EXAMPLE_URL) + .build(); + return EmbedConfiguration + .builder() + .fields(Arrays.asList(field)) + .footer(footer) + .author(author) + .title(title) + .color(color) + .description("description") + .additionalMessage("additionalMessage") + .imageUrl(EXAMPLE_URL) + .thumbnail(EXAMPLE_URL) + .build(); + } + + private Template getSimpleTemplate() throws IOException, TemplateException { + return new Template(TEMPLATE_KEY, SIMPLE_TEMPLATE_SOURCE, getNonMockedConfiguration()); + } + + private Template getEmbedTemplateWithDescription(String description) throws IOException, TemplateException { + return new Template(getEmbedTemplateKey(), embedTemplateWithDescription(description), getNonMockedConfiguration()); + } + + private Template getPageCountTemplate(Integer page) throws IOException, TemplateException { + return new Template(EMBED_PAGE_COUNT_TEMPLATE, getEmbedPageCount(page), getNonMockedConfiguration()); + } + + private Template getEmbedTemplateWithFallFieldsUsedOnce() throws IOException, TemplateException { + return new Template(getEmbedTemplateKey(), getFullEmbedConfigString(), getNonMockedConfiguration()); + } + + private Template getEmbedTemplateWithFieldCount(Integer count) throws IOException, TemplateException { + return new Template(getEmbedTemplateKey(), getFieldsEmbedConfigAsString(count), getNonMockedConfiguration()); + } + + private Template getEmbedTemplateWithTooLongField(String value) throws IOException, TemplateException { + return new Template(getEmbedTemplateKey(), getSingleFieldWithValue(value), getNonMockedConfiguration()); + } + + private String getFullEmbedConfigString() throws IOException { + return IOUtils.toString(this.getClass().getResourceAsStream("/full_embed.json"), StandardCharsets.UTF_8); + } + + private String getFieldsEmbedConfigAsString(Integer count) { + StringBuilder sb = new StringBuilder(); + sb.append("{\"fields\": ["); + for (int i = 0; i < count - 1; i++) { + sb.append(FIELD_TEMPLATE + ","); + } + sb.append(FIELD_TEMPLATE + + "]\n" + + "}"); + return sb.toString(); + } + + private String getSingleFieldWithValue(String value) { + return String.format("{\"fields\": [" + FIELD_TEMPLATE_WITH_VALUE + "]\n}",value); + } + + private String embedTemplateWithDescription(String description) { + return String.format("{ \"description\": \"%s\"}", description); + } + + private String getEmbedPageCount(Integer page) { + return String.format("Page %d", page); + } + + private Configuration getNonMockedConfiguration() throws IOException, TemplateException { + return new FreeMarkerConfigurationFactory().createConfiguration(); + } + +} diff --git a/abstracto-application/templating/templating-impl/src/test/java/dev/sheldan/abstracto/templating/service/management/TemplateManagementServiceBeanTest.java b/abstracto-application/templating/templating-impl/src/test/java/dev/sheldan/abstracto/templating/service/management/TemplateManagementServiceBeanTest.java new file mode 100644 index 000000000..7c09eff6e --- /dev/null +++ b/abstracto-application/templating/templating-impl/src/test/java/dev/sheldan/abstracto/templating/service/management/TemplateManagementServiceBeanTest.java @@ -0,0 +1,67 @@ +package dev.sheldan.abstracto.templating.service.management; + +import dev.sheldan.abstracto.templating.model.database.Template; +import dev.sheldan.abstracto.templating.repository.TemplateRepository; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import java.time.Duration; +import java.time.Instant; +import java.util.Optional; + +import static org.mockito.Mockito.*; + +@RunWith(MockitoJUnitRunner.class) +public class TemplateManagementServiceBeanTest { + + @InjectMocks + private TemplateManagementServiceBean templateManagementServiceBean; + + @Mock + private TemplateRepository repository; + + private static final String TEMPLATE_KEY = "templateKey"; + private static final String TEMPLATE_SOURCE = "source"; + + @Test + public void testFindByKey() { + when(repository.findById(TEMPLATE_KEY)).thenReturn(Optional.of(getTemplate())); + Optional