fix: bunch of TODOs

pull/3/head
Davide Polonio 2023-04-18 17:59:56 +02:00
parent faf7d12001
commit 97c3d50e6b
7 changed files with 238 additions and 6 deletions

View File

@ -8,8 +8,6 @@ import org.apache.velocity.VelocityContext;
import org.apache.velocity.tools.ToolManager;
import org.apache.velocity.util.StringBuilderWriter;
// FIXME tests
/**
* This class aims to generate localized messages or strings either merging Velocity templates or
* taking directly the keys from {@link java.util.ResourceBundle}

View File

@ -1,5 +1,6 @@
package com.github.polpetta.mezzotre.orm;
import com.github.polpetta.mezzotre.orm.model.CallbackQueryContext;
import com.github.polpetta.mezzotre.orm.model.query.QCallbackQueryContext;
import io.ebean.typequery.PString;
import java.util.concurrent.CompletableFuture;
@ -8,7 +9,14 @@ import javax.inject.Inject;
import javax.inject.Singleton;
import org.slf4j.Logger;
// FIXME tests, doc
/**
* This class allows the system to lazily remove {@link CallbackQueryContextCleaner} entries that
* are no more needed, using the {@link BatchBeanCleanerService} service under the hood.
*
* @author Davide Polonio
* @see BatchBeanCleanerService
* @since 1.0
*/
@Singleton
public class CallbackQueryContextCleaner {
@ -26,11 +34,29 @@ public class CallbackQueryContextCleaner {
this.log = log;
}
/**
* Add a group of {@link com.github.polpetta.mezzotre.orm.model.CallbackQueryContext} to be
* removed
*
* @param id the group id of the {@link
* com.github.polpetta.mezzotre.orm.model.CallbackQueryContext}
* @return a {@link CompletableFuture} with an {@link Integer} indicating how many entries have
* been deleted from the persistence layer
* @see CallbackQueryContext#getEntryGroup()
*/
public CompletableFuture<Integer> removeGroupAsync(String id) {
log.trace("CallbackQueryContext entry group " + id + " queued for removal");
return batchBeanCleanerService.removeAsync(id, ENTRY_GROUP.get());
}
/**
* Add a single {@link com.github.polpetta.mezzotre.orm.model.CallbackQueryContext} to be removed
*
* @param id the id of the {@link CallbackQueryContext} to remove
* @return a {@link CompletableFuture} with an {@link Integer} indicating how many entries have
* been deleted from the persistence layer. Can be 0 or 1.
* @see CallbackQueryContext#getId()
*/
public CompletableFuture<Integer> removeIdAsync(String id) {
log.trace("CallbackQueryContext single entity " + id + " queued for removal");
return batchBeanCleanerService.removeAsync(id, SINGLE_ENTRY.get());

View File

@ -1,6 +1,11 @@
package com.github.polpetta.mezzotre.telegram.callbackquery;
// FIXME doc
/**
* This interface is a placeholder to keep all fields in one place
*
* @author Davide Polonio
* @since 1.0
*/
public interface Field {
/**
* Additional fields that are related to {@code changeLanguage} event
@ -22,6 +27,10 @@ public interface Field {
}
}
/**
* Enumerator with custom fields for {@link
* com.github.polpetta.mezzotre.telegram.callbackquery.ShowHelp} callback query
*/
enum ShowHelp {
InvokedFromHelpMessage("invokedFromHelpMessage");

View File

@ -10,7 +10,12 @@ import java.util.concurrent.CompletableFuture;
import javax.inject.Inject;
import org.slf4j.Logger;
// FIXME doc
/**
* Callback query event that is triggered only when a corresponding event is not found in the system
*
* @author Davide Polonio
* @since 1.0
*/
public class NotFound implements Processor {
private final Logger log;

View File

@ -23,11 +23,21 @@ public interface Processor {
*/
String getEventName();
// FIXME javadoc
/**
* Determines if the Callback Query can directly be invoked by the user, such as starting an
* interaction from this point or invoking it from an inline query button
*
* @return true if it is, false otherwise
*/
default boolean canBeDirectlyInvokedByTheUser() {
return false;
}
/**
* Gives the ability to print a localized version of the event, in a pretty way
*
* @return the key for the corresponding localization string
*/
default Optional<String> getPrettyPrintLocaleKeyName() {
return Optional.empty();
}

View File

@ -0,0 +1,103 @@
package com.github.polpetta.mezzotre.i18n;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.Locale;
import java.util.ResourceBundle;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.tools.ToolContext;
import org.apache.velocity.tools.ToolManager;
import org.apache.velocity.util.StringBuilderWriter;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.Execution;
import org.junit.jupiter.api.parallel.ExecutionMode;
import org.mockito.ArgumentCaptor;
@Execution(ExecutionMode.CONCURRENT)
class TemplateContentGeneratorTest {
private LocalizedMessageFactory fakeLocalizedMessageFactory;
private TemplateContentGenerator templateContentGenerator;
@BeforeEach
void setUp() {
fakeLocalizedMessageFactory = mock(LocalizedMessageFactory.class);
templateContentGenerator = new TemplateContentGenerator(fakeLocalizedMessageFactory);
}
@Test
void shouldCallMergeTemplateWithRightArguments() {
final VelocityEngine fakeVelocityEngine = mock(VelocityEngine.class);
final ToolManager fakeToolManager = mock(ToolManager.class);
when(fakeToolManager.getVelocityEngine()).thenReturn(fakeVelocityEngine);
final ToolContext fakeToolContext = mock(ToolContext.class);
when(fakeToolManager.createContext()).thenReturn(fakeToolContext);
when(fakeLocalizedMessageFactory.createVelocityToolManager(Locale.forLanguageTag("en-US")))
.thenReturn(fakeToolManager);
templateContentGenerator.mergeTemplate(
ctx -> {
ctx.put("testtesttest", "value");
},
"en-US",
"a/fake/path.vm");
final ArgumentCaptor<VelocityContext> velocityContextArgumentCaptor =
ArgumentCaptor.forClass(VelocityContext.class);
verify(fakeVelocityEngine, times(1))
.mergeTemplate(
eq("a/fake/path.vm"),
eq(StandardCharsets.UTF_8.name()),
velocityContextArgumentCaptor.capture(),
any(StringBuilderWriter.class));
final VelocityContext gotVelocityContext = velocityContextArgumentCaptor.getValue();
assertEquals("value", gotVelocityContext.get("testtesttest"));
}
@Test
void shouldCallLocaleFactoryWhenRetrievingKey() {
final Locale enUS = Locale.forLanguageTag("en-US");
class StubRB extends ResourceBundle {
@Override
protected Object handleGetObject(@NotNull String s) {
return "testtest123";
}
@NotNull
@Override
public Enumeration<String> getKeys() {
return new Enumeration<String>() {
private boolean next = true;
@Override
public boolean hasMoreElements() {
final boolean toRet = next;
next = !next;
return toRet;
}
@Override
public String nextElement() {
return "doens't matter";
}
};
}
}
final StubRB stubRB = new StubRB();
when(fakeLocalizedMessageFactory.createResourceBundle(any())).thenReturn(stubRB);
final String got = templateContentGenerator.getString(enUS, "a.string");
assertEquals("testtest123", got);
}
}

View File

@ -0,0 +1,81 @@
package com.github.polpetta.mezzotre.orm;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.*;
import com.github.polpetta.mezzotre.helper.Loader;
import com.github.polpetta.mezzotre.helper.TestConfig;
import io.ebean.Database;
import io.ebean.typequery.PString;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
import org.mockito.ArgumentCaptor;
import org.slf4j.LoggerFactory;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
@Tag("slow")
@Tag("database")
@Tag("velocity")
@Testcontainers
class CallbackQueryContextCleanerIntegrationTest {
@Container
private final PostgreSQLContainer<?> postgresServer =
new PostgreSQLContainer<>(TestConfig.POSTGRES_DOCKER_IMAGE);
private Database database;
private BatchBeanCleanerService fakeBatchBeanCleanerService;
private CallbackQueryContextCleaner callbackQueryContextCleaner;
@BeforeEach
void setUp() throws Exception {
database =
Loader.connectToDatabase(Loader.loadDefaultEbeanConfigWithPostgresSettings(postgresServer));
fakeBatchBeanCleanerService = mock(BatchBeanCleanerService.class);
callbackQueryContextCleaner =
new CallbackQueryContextCleaner(
fakeBatchBeanCleanerService,
LoggerFactory.getLogger(CallbackQueryContextCleaner.class));
}
@Test
@Timeout(value = 1, unit = TimeUnit.MINUTES)
void shouldDeleteByGroupId() throws Exception {
when(fakeBatchBeanCleanerService.removeAsync(eq("an id"), any()))
.thenReturn(CompletableFuture.completedFuture(1));
final Integer got = callbackQueryContextCleaner.removeGroupAsync("an id").get();
final ArgumentCaptor<PString> pStringArgumentCaptor = ArgumentCaptor.forClass(PString.class);
verify(fakeBatchBeanCleanerService, times(1))
.removeAsync(eq("an id"), pStringArgumentCaptor.capture());
assertEquals(1, got);
assertEquals("entryGroup", pStringArgumentCaptor.getValue().toString());
}
@Test
@Timeout(value = 1, unit = TimeUnit.MINUTES)
void shouldDeleteById() throws Exception {
when(fakeBatchBeanCleanerService.removeAsync(eq("an id"), any()))
.thenReturn(CompletableFuture.completedFuture(1));
final Integer got = callbackQueryContextCleaner.removeIdAsync("an id").get();
final ArgumentCaptor<PString> pStringArgumentCaptor = ArgumentCaptor.forClass(PString.class);
verify(fakeBatchBeanCleanerService, times(1))
.removeAsync(eq("an id"), pStringArgumentCaptor.capture());
assertEquals(1, got);
assertEquals("id", pStringArgumentCaptor.getValue().toString());
}
}