chore: add drone-ci-tests and docker build #1

Merged
polpetta merged 15 commits from drone-ci-tests into devel 2023-03-27 17:16:30 +02:00
35 changed files with 346 additions and 225 deletions

View File

@ -1,9 +1,71 @@
kind: pipeline
type: docker
name: default
name: commit
steps:
- name: Build
- name: checks
image: eclipse-temurin:17-jdk
commands:
- ./mvnw package -B -DskipTests=true
- apt-get update -qq && apt-get install -qy python3 pip git && pip install pre-commit
- pre-commit run --all-files
---
kind: pipeline
type: docker
name: pr
steps:
- name: tests
image: quay.io/testcontainers/dind-drone-plugin
environment:
CI_WORKSPACE: "/drone/src"
settings:
cmd: ./mvnw -B test
build_image: eclipse-temurin:17-jdk
prefetch_images:
- "postgres:13-alpine"
volumes:
- name: dockersock
path: /var/run
# Specify docker:dind as a service
services:
- name: docker
image: docker:dind
privileged: true
volumes:
- name: dockersock
path: /var/run
volumes:
- name: dockersock
temp: {}
trigger:
event:
- pull_request
- cron
---
kind: pipeline
type: docker
name: artifacts
steps:
- name: packaging
image: eclipse-temurin:17-jdk
commands:
- ./mvnw package -B -DskipTests=true -Dmaven.test.skip=true -Dmaven.site.skip=true -Dmaven.javadoc.skip=true
- name: dockerfile
image: thegeeklab/drone-docker-buildx:23
privileged: true
settings:
pull_image: true
dry_run: true
trigger:
branch:
- devel
event:
- push
- tag

2
.markdownlint.yaml Normal file
View File

@ -0,0 +1,2 @@
MD013:
line_length: 120

33
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,33 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
exclude: "mvnw"
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
exclude: "^.*\\.vm$"
- id: check-yaml
args: [--allow-multiple-documents]
- id: check-added-large-files
- id: check-toml
- id: mixed-line-ending
- repo: https://github.com/gruntwork-io/pre-commit
rev: v0.1.17
hooks:
- id: shellcheck
- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
rev: v2.4.0
hooks:
- id: pretty-format-java
args: [--autofix]
- repo: https://github.com/igorshubovych/markdownlint-cli
rev: v0.32.2
hooks:
- id: markdownlint
- id: markdownlint-fix
- repo: https://github.com/jorisroovers/gitlint
rev: v0.17.0
hooks:
- id: gitlint

View File

@ -14,4 +14,4 @@
<option name="Make" enabled="true" />
</method>
</configuration>
</component>
</component>

View File

@ -29,4 +29,4 @@
</extension>
<method v="2" />
</configuration>
</component>
</component>

View File

@ -19,4 +19,4 @@
</deployment>
<method v="2" />
</configuration>
</component>
</component>

View File

@ -15,4 +15,4 @@ FROM gcr.io/distroless/java17:${DEBUG_BUILD}nonroot
COPY --from=builder /build/target/mezzotre.jar /opt/mezzotre.jar
ENTRYPOINT ["java", "-jar", "/opt/mezzotre.jar"]
ENTRYPOINT ["java", "-jar", "/opt/mezzotre.jar"]

View File

@ -5,7 +5,7 @@
Mezzotre is a DnD content management system. Currently, it is still in the first development stages and everything is
still evolving, goals included.
The whole system is based on Java17+ for the language, incoming Webhooks from Telegram, Jooby backend to handle the
The whole system is based on Java17+ for the language, incoming Webhooks from Telegram, Jooby backend to handle the
requests, PostgresSQL to store data and long-term chat context information.
## Shipping and running
@ -14,14 +14,17 @@ Keep in mind that Mezzotre is meant to be run behind a reverse proxy handling al
In the root of the project you can find a `docker-compose.yml` file that can be a useful starting point to generate your
configuration. Finally, you can use the same docker-compose definition as a developer to have a live version running.
Simply run:
```shell
DEBUG_OPTS=debug- docker-compose up -d --build && docker-compose logs -f
```
to run a debug instance. Omit the `DEBUG_OPTS` env variable for a "production" style environment. Note that this
to run a debug instance. Omit the `DEBUG_OPTS` env variable for a "production" style environment. Note that this
configuration requires an `.env` file (that is not committed for obvious reasons) containing the database password and a
valid Telegram Bot token.
To configure Webhook configuration for your bot, open up a terminal and type:
```shell
curl -F "url=https://example.com/api/tg" https://api.telegram.org/bot<YOUR BOT TOKEN>/setWebhook
```
@ -29,11 +32,12 @@ curl -F "url=https://example.com/api/tg" https://api.telegram.org/bot<YOUR BOT T
## Building
Build is achieved through Maven. To build a `jar` run:
```shell
mvn package -DskipTests=true -Dmaven.test.skip=true -Dmaven.site.skip=true -Dmaven.javadoc.skip=true
```
In the `target/` folder wou will find an uber-jar and optionally the possibility to run it via a script and to setup
In the `target/` folder wou will find an uber-jar and optionally the possibility to run it via a script and to setup
auto-startup via systemd or openrc units.
## Developing
@ -44,11 +48,11 @@ You can simply run tests with `mvn test`. This will run `UT` and `IT` tests toge
### Manual testing
For a manual approach, just open a terminal and type `mvn jooby:run`. Assuming you have a database locally available
(check out [application.conf](conf/application.conf)) and a valid Telegram token set (maybe as enviroment variable) you
can develop and see live changes of your Mezzotre on the fly. Finally, by using Postman, you can simulate incoming
For a manual approach, just open a terminal and type `mvn jooby:run`. Assuming you have a database locally available
(check out [application.conf](conf/application.conf)) and a valid Telegram token set (maybe as enviroment variable) you
can develop and see live changes of your Mezzotre on the fly. Finally, by using Postman, you can simulate incoming
Telegram events.
## License
This software is under AGPL3+. You can find all details in the [LICENSE](LICENSE) file.
This software is under AGPL3+. You can find all details in the [LICENSE](LICENSE) file.

View File

@ -8,4 +8,4 @@ telegram.key = akey
application.lang = en en-US it it-IT
server.port = 9191
server.gzip = true
server.gzip = true

View File

@ -27,4 +27,4 @@
"default": 0
}
}
}
}

View File

@ -38,4 +38,4 @@ max_java_memory: 512
# Try to create a symbolic link to java executable in <app_home>/run with
# the name of "<app_name>-java" so that commands like "ps" will make it
# easier to find your app
symlink_java: true
symlink_java: true

View File

@ -1,7 +1,9 @@
package com.github.polpetta.mezzotre;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;import io.jooby.Jooby;import org.slf4j.Logger;
import com.google.inject.Provides;
import io.jooby.Jooby;
import org.slf4j.Logger;
public class InjectionModule extends AbstractModule {
private final Jooby jooby;

View File

@ -1,5 +1,7 @@
package com.github.polpetta.mezzotre.i18n;
import java.util.Locale;
import javax.inject.Inject;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.resource.loader.JarResourceLoader;
import org.apache.velocity.tools.Scope;
@ -8,8 +10,6 @@ import org.apache.velocity.tools.ToolManager;
import org.apache.velocity.tools.config.FactoryConfiguration;
import org.apache.velocity.tools.config.ToolConfiguration;
import org.apache.velocity.tools.config.ToolboxConfiguration;
import javax.inject.Inject;
import java.util.Locale;
public class LocalizedMessageFactory {
@ -22,8 +22,7 @@ public class LocalizedMessageFactory {
public ToolManager create(Locale locale) {
// properties.setProperty("file.resource.loader.class", FileResourceLoader.class.getName());.
// properties.setProperty("file.resource.loader.class", FileResourceLoader.class.getName());.
final ToolManager toolManager = new ToolManager();
toolManager.setVelocityEngine(velocityEngine);

View File

@ -1,8 +1,8 @@
package com.github.polpetta.mezzotre.i18n;
import java.util.Locale;
import org.apache.velocity.tools.config.DefaultKey;
import org.apache.velocity.tools.generic.ResourceTool;
import java.util.Locale;
@DefaultKey("i18n")
public class LocalizedTool extends ResourceTool {

View File

@ -1,38 +1,46 @@
package com.github.polpetta.mezzotre.orm.di;
import com.google.inject.AbstractModule;import com.google.inject.Provides;import com.google.inject.Singleton;import com.zaxxer.hikari.HikariConfig;import io.jooby.Extension;import io.jooby.ebean.EbeanModule;import io.jooby.flyway.FlywayModule;import io.jooby.hikari.HikariModule;import javax.inject.Named;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Singleton;
import com.zaxxer.hikari.HikariConfig;
import io.jooby.Extension;
import io.jooby.ebean.EbeanModule;
import io.jooby.flyway.FlywayModule;
import io.jooby.hikari.HikariModule;
import javax.inject.Named;
public class Db extends AbstractModule {
/**
* Returns null. This allows to fetch the configuration from file rather than fetch from other
* environment
*
* @return a {@link HikariConfig} configuration if possible
*/
@Provides
@Singleton
public HikariConfig getHikariConfig() {
return null;
}
/**
* Returns null. This allows to fetch the configuration from file rather than fetch from other
* environment
*
* @return a {@link HikariConfig} configuration if possible
*/
@Provides
@Singleton
public HikariConfig getHikariConfig() {
return null;
}
@Provides
@Singleton
@Named("hikariPoolExtension")
public Extension getHikariExtension() {
return new HikariModule();
}
@Provides
@Singleton
@Named("hikariPoolExtension")
public Extension getHikariExtension() {
return new HikariModule();
}
@Provides
@Singleton
@Named("flyWayMigrationExtension")
public Extension getFlyWayMigrationExtension() {
return new FlywayModule();
}
@Provides
@Singleton
@Named("flyWayMigrationExtension")
public Extension getFlyWayMigrationExtension() {
return new FlywayModule();
}
@Provides
@Singleton
@Named("ebeanExtension")
public Extension getEbeanExtension() {
return new EbeanModule();
}
@Provides
@Singleton
@Named("ebeanExtension")
public Extension getEbeanExtension() {
return new EbeanModule();
}
}

View File

@ -3,11 +3,12 @@ package com.github.polpetta.mezzotre.orm.model;
import io.ebean.Model;
import io.ebean.annotation.WhenCreated;
import io.ebean.annotation.WhenModified;
import javax.persistence.MappedSuperclass;
import java.time.Instant;
import javax.persistence.MappedSuperclass;
/**
* Father class to all the database objects. It allows to add when an object has been created and modifies
* Father class to all the database objects. It allows to add when an object has been created and
* modifies
*
* @author Davide Polonio
* @since 1.0-SNAPSHOT

View File

@ -1,6 +1,6 @@
package com.github.polpetta.mezzotre.route;
public final class Constants {
public final static String V1 = "v1";
public final static String API = "api";
public static final String V1 = "v1";
public static final String API = "api";
}

View File

@ -21,7 +21,10 @@ public class Route extends AbstractModule {
.orElseThrow(
() ->
new IllegalStateException(
"Telegram token is required to make the application work. Please set 'telegram.key = \"value\"' in your application.conf file or as the application argument. Alternatively, you can set 'TELEGRAM_KEY' as an environment variable."));
"Telegram token is required to make the application work. Please set"
+ " 'telegram.key = \"value\"' in your application.conf file or as the"
+ " application argument. Alternatively, you can set 'TELEGRAM_KEY' as"
+ " an environment variable."));
return new TelegramBot(telegramKey);
}
}

View File

@ -3,7 +3,6 @@ package com.github.polpetta.mezzotre.telegram.command;
import com.github.polpetta.mezzotre.orm.model.TgChat;
import com.pengrad.telegrambot.model.Update;
import com.pengrad.telegrambot.request.BaseRequest;
import com.pengrad.telegrambot.request.SendMessage;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
@ -27,10 +26,10 @@ public interface Executor {
/**
* Process the current update
*
* @param chat the chat the {@link Executor} is currently replying to
* @param chat the chat the {@link Executor} is currently replying to
* @param update the update to process
* @return a {@link CompletableFuture} with the result of the computation
*/
// FIXME cannot be void - we don't want pesky side effects!
CompletableFuture<Optional<BaseRequest<?,?>>> process(TgChat chat, Update update);
CompletableFuture<Optional<BaseRequest<?, ?>>> process(TgChat chat, Update update);
}

View File

@ -86,13 +86,13 @@ public class Start implements Executor {
.get();
log.trace("Start command - message to send back: " + message);
final ChatContext chatContext = chat.getChatContext();
chatContext.setLastMessageSentId(update.message().messageId());
chatContext.setStage(getTriggerKeyword());
chatContext.setStep(0);
chatContext.setPreviousMessageUnixTimestampInSeconds(update.message().date());
chat.setChatContext(chatContext);
chat.save();
final ChatContext chatContext = chat.getChatContext();
chatContext.setLastMessageSentId(update.message().messageId());
chatContext.setStage(getTriggerKeyword());
chatContext.setStep(0);
chatContext.setPreviousMessageUnixTimestampInSeconds(update.message().date());
chat.setChatContext(chatContext);
chat.save();
return Optional.of(new SendMessage(chat.getId(), message).parseMode(ParseMode.Markdown));
},

View File

@ -1,28 +1,31 @@
package com.github.polpetta.mezzotre.telegram.command.di;
import com.github.polpetta.mezzotre.telegram.command.Executor;import com.github.polpetta.mezzotre.telegram.command.Start;import com.google.common.io.Resources;import com.google.inject.AbstractModule;import com.google.inject.Provides;import org.apache.velocity.app.VelocityEngine;
import com.github.polpetta.mezzotre.telegram.command.Executor;
import com.github.polpetta.mezzotre.telegram.command.Start;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import java.util.Set;
import javax.inject.Named;
import javax.inject.Singleton;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import javax.inject.Named;
import javax.inject.Singleton;import java.util.Set;
public class Command extends AbstractModule {
@Provides
@Singleton
@Named("commands")
public Set<Executor> getCommandExecutors(
Start start
) {
return Set.of(start);
}
@Provides
@Singleton
@Named("commands")
public Set<Executor> getCommandExecutors(Start start) {
return Set.of(start);
}
@Provides
public VelocityEngine getVelocityEngine() {
final VelocityEngine velocityEngine = new VelocityEngine();
@Provides
public VelocityEngine getVelocityEngine() {
final VelocityEngine velocityEngine = new VelocityEngine();
velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
velocityEngine.setProperty(
"classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
velocityEngine.init();
return velocityEngine;
}
velocityEngine.init();
return velocityEngine;
}
}

View File

@ -2,11 +2,11 @@ package com.github.polpetta.mezzotre.util.di;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import javax.inject.Named;
import javax.inject.Singleton;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ForkJoinPool;
import javax.inject.Named;
import javax.inject.Singleton;
public class ThreadPool extends AbstractModule {
@Provides

View File

@ -21,4 +21,3 @@ create table registered_user (
-- foreign keys and indices
alter table registered_user add constraint fk_registered_user_telegram_id foreign key (telegram_id) references telegram_chat (id) on delete cascade on update restrict;

View File

@ -1,3 +1,3 @@
start.hello=Hello
start.thisIs=This is
start.description=a simple bot focused on DnD content management! Please start by choosing a language down below.
start.description=a simple bot focused on DnD content management! Please start by choosing a language down below.

View File

@ -1,3 +1,3 @@
start.hello=Hello
start.thisIs=This is
start.description=a simple bot focused on DnD content management! Please start by choosing a language down below.
start.description=a simple bot focused on DnD content management! Please start by choosing a language down below.

View File

@ -1,3 +1,3 @@
start.hello=Ciao
start.thisIs=Questo è
start.description=un semplice bot che ci concenta sulla gestione di contenuto per DnD! Per favore comincia selezionando la lingua qui sotto
start.description=un semplice bot che ci concenta sulla gestione di contenuto per DnD! Per favore comincia selezionando la lingua qui sotto

View File

@ -1,3 +1,3 @@
start.hello=Ciao
start.thisIs=Questo è
start.description=un semplice bot che ci concenta sulla gestione di contenuto per DnD! Per favore comincia selezionando la lingua qui sotto
start.description=un semplice bot che ci concenta sulla gestione di contenuto per DnD! Per favore comincia selezionando la lingua qui sotto

View File

@ -3,21 +3,14 @@ package com.github.polpetta.mezzotre;
import static org.junit.jupiter.api.Assertions.assertEquals;
import com.github.polpetta.mezzotre.helper.IntegrationAppFactory;
import com.github.polpetta.mezzotre.helper.Loader;
import com.github.polpetta.mezzotre.helper.TestConfig;
import io.ebean.Database;
import io.jooby.JoobyTest;
import io.jooby.StatusCode;
import java.io.IOException;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
@Tag("slow")
@Tag("database")

View File

@ -1,7 +1,6 @@
package com.github.polpetta.mezzotre.helper;
import com.github.polpetta.mezzotre.App;
import com.github.polpetta.mezzotre.InjectionModule;
import com.github.polpetta.mezzotre.route.di.Route;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;

View File

@ -1,43 +1,52 @@
package com.github.polpetta.mezzotre.helper;
import com.github.polpetta.mezzotre.App;import com.google.common.io.Resources;import com.zaxxer.hikari.HikariConfig;import com.zaxxer.hikari.HikariDataSource;import io.ebean.Database;import io.ebean.DatabaseFactory;import io.ebean.config.DatabaseConfig;import org.apache.commons.lang3.tuple.Pair;import org.testcontainers.containers.PostgreSQLContainer;import java.io.IOException;import java.io.InputStream;import java.net.URL;import java.util.Properties;public class Loader {
import com.google.common.io.Resources;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import io.ebean.Database;
import io.ebean.DatabaseFactory;
import io.ebean.config.DatabaseConfig;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Properties;
import org.apache.commons.lang3.tuple.Pair;
import org.testcontainers.containers.PostgreSQLContainer;
public static Pair<Properties, Properties> loadDefaultEbeanConfigWithPostgresSettings(
PostgreSQLContainer<?> container) throws IOException {
public class Loader {
public static Pair<Properties, Properties> loadDefaultEbeanConfigWithPostgresSettings(
PostgreSQLContainer<?> container) throws IOException {
final URL ebeanRes = Resources.getResource("database-test.properties");
final URL hikariRes = Resources.getResource("hikari.properties");
final Properties ebeanConnectionProperties = new Properties();
final Properties hikariConnectionProperties = new Properties();
try (InputStream ebeanInputStream = ebeanRes.openStream();
InputStream hikariInputStream = hikariRes.openStream()) {
hikariConnectionProperties.load(hikariInputStream);
hikariConnectionProperties.put("username", container.getUsername());
hikariConnectionProperties.put("password", container.getPassword());
hikariConnectionProperties.put("jdbcUrl", container.getJdbcUrl());
final URL hikariRes = Resources.getResource("hikari.properties");
final Properties ebeanConnectionProperties = new Properties();
final Properties hikariConnectionProperties = new Properties();
try (InputStream ebeanInputStream = ebeanRes.openStream();
InputStream hikariInputStream = hikariRes.openStream()) {
hikariConnectionProperties.load(hikariInputStream);
hikariConnectionProperties.put("username", container.getUsername());
hikariConnectionProperties.put("password", container.getPassword());
hikariConnectionProperties.put("jdbcUrl", container.getJdbcUrl());
ebeanConnectionProperties.load(ebeanInputStream);
ebeanConnectionProperties.put("datasource_db_username", container.getUsername());
ebeanConnectionProperties.put("datasource_db_password", container.getPassword());
ebeanConnectionProperties.put("datasource_db_databaseUrl", container.getJdbcUrl());
ebeanConnectionProperties.put("datasource_db_databaseDriver", "org.postgresql.Driver");
}
return Pair.of(ebeanConnectionProperties, hikariConnectionProperties);
ebeanConnectionProperties.load(ebeanInputStream);
ebeanConnectionProperties.put("datasource_db_username", container.getUsername());
ebeanConnectionProperties.put("datasource_db_password", container.getPassword());
ebeanConnectionProperties.put("datasource_db_databaseUrl", container.getJdbcUrl());
ebeanConnectionProperties.put("datasource_db_databaseDriver", "org.postgresql.Driver");
}
return Pair.of(ebeanConnectionProperties, hikariConnectionProperties);
}
public static Database connectToDatabase(
Properties ebean,
Properties hikari
) {
final HikariDataSource hikariDataSource =
new HikariDataSource(new HikariConfig(hikari));
final DatabaseConfig databaseConfig = new DatabaseConfig();
databaseConfig.loadFromProperties(ebean);
databaseConfig.setDataSource(hikariDataSource);
public static Database connectToDatabase(Properties ebean, Properties hikari) {
final HikariDataSource hikariDataSource = new HikariDataSource(new HikariConfig(hikari));
final DatabaseConfig databaseConfig = new DatabaseConfig();
databaseConfig.loadFromProperties(ebean);
databaseConfig.setDataSource(hikariDataSource);
return DatabaseFactory.create(databaseConfig);
}
return DatabaseFactory.create(databaseConfig);
}
public static Database connectToDatabase(Pair<Properties, Properties> connectionProperties) {
return connectToDatabase(connectionProperties.getLeft(), connectionProperties.getRight());
}
public static Database connectToDatabase(Pair<Properties, Properties> connectionProperties) {
return connectToDatabase(connectionProperties.getLeft(), connectionProperties.getRight());
}
}

View File

@ -52,7 +52,8 @@ public class UserIntegrationTest {
final Timestamp timestampFromUnixEpoch = Clock.getTimestampFromUnixEpoch(1L);
final String insertQuery =
"insert into registered_user (id, is_active, telegram_id, email_address, entry_created, entry_modified) values (?, ?, null, ?, ?, ?)";
"insert into registered_user (id, is_active, telegram_id, email_address, entry_created,"
+ " entry_modified) values (?, ?, null, ?, ?, ?)";
final int affectedRows =
database
.sqlUpdate(insertQuery)

View File

@ -78,30 +78,30 @@ class TelegramIntegrationTest {
final Context fakeContext = mock(Context.class);
final Update update =
gson.fromJson(
"""
{
"update_id":10000,
"message":{
"date":1441645532,
"chat":{
"last_name":"Test Lastname",
"id":1111111,
"type": "private",
"first_name":"Test Firstname",
"username":"Testusername"
},
"message_id":1365,
"from":{
"last_name":"Test Lastname",
"id":1111111,
"first_name":"Test Firstname",
"username":"Testusername"
},
"text":"/start"
}
}""",
"{\n"
+ "\"update_id\":10000,\n"
+ "\"message\":{\n"
+ " \"date\":1441645532,\n"
+ " \"chat\":{\n"
+ " \"last_name\":\"Test Lastname\",\n"
+ " \"id\":1111111,\n"
+ " \"type\": \"private\",\n"
+ " \"first_name\":\"Test Firstname\",\n"
+ " \"username\":\"Testusername\"\n"
+ " },\n"
+ " \"message_id\":1365,\n"
+ " \"from\":{\n"
+ " \"last_name\":\"Test Lastname\",\n"
+ " \"id\":1111111,\n"
+ " \"first_name\":\"Test Firstname\",\n"
+ " \"username\":\"Testusername\"\n"
+ " },\n"
+ " \"text\":\"/start\"\n"
+ "}\n"
+ "}\n",
Update.class);
final CompletableFuture<String> integerCompletableFuture = telegram.incomingUpdate(fakeContext, update);
final CompletableFuture<String> integerCompletableFuture =
telegram.incomingUpdate(fakeContext, update);
verify(fakeContext, times(1)).setResponseType(MediaType.JSON);
final String gotReply = integerCompletableFuture.get();
assertDoesNotThrow(() -> gotReply);

View File

@ -1,22 +1,24 @@
package com.github.polpetta.mezzotre.telegram.command;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.github.polpetta.mezzotre.orm.model.TgChat;
import com.github.polpetta.types.json.ChatContext;
import com.google.gson.Gson;
import com.pengrad.telegrambot.model.Update;
import com.pengrad.telegrambot.request.BaseRequest;
import com.pengrad.telegrambot.request.SendMessage;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;import org.junit.jupiter.api.parallel.Execution;
import org.junit.jupiter.api.parallel.ExecutionMode;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.Execution;
import org.junit.jupiter.api.parallel.ExecutionMode;
@Execution(ExecutionMode.CONCURRENT)
class RouterTest {

View File

@ -1,5 +1,7 @@
package com.github.polpetta.mezzotre.telegram.command;
import static org.junit.jupiter.api.Assertions.*;
import com.github.polpetta.mezzotre.helper.Loader;
import com.github.polpetta.mezzotre.helper.TestConfig;
import com.github.polpetta.mezzotre.i18n.LocalizedMessageFactory;
@ -11,6 +13,9 @@ import com.pengrad.telegrambot.model.Update;
import com.pengrad.telegrambot.request.BaseRequest;
import com.pengrad.telegrambot.request.SendMessage;
import io.ebean.Database;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
@ -24,12 +29,6 @@ import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import static org.junit.jupiter.api.Assertions.*;
@Tag("slow")
@Tag("database")
@Tag("velocity")
@ -76,28 +75,27 @@ class StartIntegrationTest {
final Update update =
gson.fromJson(
"""
{
"update_id":10000,
"message":{
"date":1441645532,
"chat":{
"last_name":"Test Lastname",
"id":1111111,
"type": "private",
"first_name":"Test Firstname",
"username":"Testusername"
},
"message_id":1365,
"from":{
"last_name":"Test Lastname",
"id":1111111,
"first_name":"Test Firstname",
"username":"Testusername"
},
"text":"/start"
}
}""",
"{\n"
+ "\"update_id\":10000,\n"
+ "\"message\":{\n"
+ " \"date\":1441645532,\n"
+ " \"chat\":{\n"
+ " \"last_name\":\"Test Lastname\",\n"
+ " \"id\":1111111,\n"
+ " \"type\": \"private\",\n"
+ " \"first_name\":\"Test Firstname\",\n"
+ " \"username\":\"Testusername\"\n"
+ " },\n"
+ " \"message_id\":1365,\n"
+ " \"from\":{\n"
+ " \"last_name\":\"Test Lastname\",\n"
+ " \"id\":1111111,\n"
+ " \"first_name\":\"Test Firstname\",\n"
+ " \"username\":\"Testusername\"\n"
+ " },\n"
+ " \"text\":\"/start\"\n"
+ "}\n"
+ "}",
Update.class);
final CompletableFuture<Optional<BaseRequest<?, ?>>> gotFuture = start.process(tgChat, update);
@ -108,7 +106,9 @@ class StartIntegrationTest {
assertInstanceOf(SendMessage.class, gotMessage);
final String message = (String) gotMessage.getParameters().get("text");
assertEquals(
"**Hello Test Firstname! \uD83D\uDC4B**\n\nThis is _Mezzotre_, a simple bot focused on DnD content management! Please start by choosing a language down below. \uD83D\uDC47",
"**Hello Test Firstname! \uD83D\uDC4B**\n\n"
+ "This is _Mezzotre_, a simple bot focused on DnD content management! Please start by"
+ " choosing a language down below. \uD83D\uDC47",
message);
assertEquals(1111111L, (Long) gotMessage.getParameters().get("chat_id"));

View File

@ -1,5 +1,8 @@
package com.github.polpetta.mezzotre.telegram.command;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
import com.github.polpetta.mezzotre.i18n.LocalizedMessageFactory;
import com.github.polpetta.mezzotre.orm.model.TgChat;
import com.github.polpetta.types.json.ChatContext;
@ -7,6 +10,10 @@ import com.google.gson.Gson;
import com.pengrad.telegrambot.model.Update;
import com.pengrad.telegrambot.request.BaseRequest;
import com.pengrad.telegrambot.request.SendMessage;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
@ -18,14 +25,6 @@ import org.junit.jupiter.api.parallel.Execution;
import org.junit.jupiter.api.parallel.ExecutionMode;
import org.slf4j.Logger;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
@Tag("velocity")
@Execution(ExecutionMode.CONCURRENT)
class StartTest {
@ -38,7 +37,9 @@ class StartTest {
@BeforeAll
static void beforeAll() {
gson = new Gson();
}@BeforeEach
}
@BeforeEach
void setUp() {
velocityEngine = new VelocityEngine();
velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADERS, "classpath");
@ -61,28 +62,27 @@ class StartTest {
final Update update =
gson.fromJson(
"""
{
"update_id":10000,
"message":{
"date":1441645532,
"chat":{
"last_name":"Test Lastname",
"id":1111111,
"type": "private",
"first_name":"Test Firstname",
"username":"Testusername"
},
"message_id":1365,
"from":{
"last_name":"Test Lastname",
"id":1111111,
"first_name":"Test Firstname",
"username":"Testusername"
},
"text":"/start"
}
}""",
"{\n"
+ "\"update_id\":10000,\n"
+ "\"message\":{\n"
+ " \"date\":1441645532,\n"
+ " \"chat\":{\n"
+ " \"last_name\":\"Test Lastname\",\n"
+ " \"id\":1111111,\n"
+ " \"type\": \"private\",\n"
+ " \"first_name\":\"Test Firstname\",\n"
+ " \"username\":\"Testusername\"\n"
+ " },\n"
+ " \"message_id\":1365,\n"
+ " \"from\":{\n"
+ " \"last_name\":\"Test Lastname\",\n"
+ " \"id\":1111111,\n"
+ " \"first_name\":\"Test Firstname\",\n"
+ " \"username\":\"Testusername\"\n"
+ " },\n"
+ " \"text\":\"/start\"\n"
+ "}\n"
+ "}",
Update.class);
final CompletableFuture<Optional<BaseRequest<?, ?>>> gotFuture =
@ -94,7 +94,9 @@ class StartTest {
assertInstanceOf(SendMessage.class, gotMessage);
final String message = (String) gotMessage.getParameters().get("text");
assertEquals(
"**Hello Test Firstname! \uD83D\uDC4B**\n\nThis is _Mezzotre_, a simple bot focused on DnD content management! Please start by choosing a language down below. \uD83D\uDC47",
"**Hello Test Firstname! \uD83D\uDC4B**\n\n"
+ "This is _Mezzotre_, a simple bot focused on DnD content management! Please start by"
+ " choosing a language down below. \uD83D\uDC47",
message);
assertEquals(1111111L, (Long) gotMessage.getParameters().get("chat_id"));
verify(fakeChat, times(1)).save();