Skip to content

Commit

Permalink
Merge pull request #7 from stelitop/v0.0.3
Browse files Browse the repository at this point in the history
V0.0.3
  • Loading branch information
stelitop authored Sep 8, 2023
2 parents 1205478 + 9c9de98 commit b1358ba
Show file tree
Hide file tree
Showing 11 changed files with 340 additions and 1 deletion.
28 changes: 27 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ plugins {
id 'java'
id 'org.springframework.boot' version '3.1.3'
id 'io.spring.dependency-management' version '1.1.3'
id 'jacoco'
id 'maven-publish'
}

group = 'net.stelitop'
version = '0.0.2'
version = '0.0.3'

java {
sourceCompatibility = '17'
Expand Down Expand Up @@ -34,6 +35,9 @@ dependencies {
annotationProcessor 'org.projectlombok:lombok'

testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'junit:junit:4.13.1'
testImplementation 'org.assertj:assertj-core:3.24.2'
testImplementation 'org.mockito:mockito-core:5.4.0'
}

publishing {
Expand All @@ -56,4 +60,26 @@ publishing {

tasks.named('test') {
useJUnitPlatform()
jacoco {
enabled = true
includes = ['net.stelitop.mad4j.*']
excludes = []
}
}

jacocoTestCoverageVerification() {
dependsOn test
violationRules {
rule {
enabled = true
element = 'CLASS'
includes = ['net.stelitop.madj4.*']

limit {
counter = 'BRANCH'
value = 'COVEREDRATIO'
minimum = 0.1
}
}
}
}
68 changes: 68 additions & 0 deletions src/main/java/net/stelitop/mad4j/Mad4jConfig.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,75 @@
package net.stelitop.mad4j;

import discord4j.core.GatewayDiscordClient;
import net.stelitop.mad4j.autocomplete.AutocompletionExecutor;
import net.stelitop.mad4j.listeners.CommandOptionAutocompleteListener;
import net.stelitop.mad4j.listeners.ComponentEventListener;
import net.stelitop.mad4j.listeners.SlashCommandListener;
import net.stelitop.mad4j.requirements.CommandRequirementExecutor;
import org.checkerframework.checker.units.qual.C;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import java.util.List;

@ComponentScan("net.stelitop.mad4j")
@Configuration
public class Mad4jConfig {

}
//@Configuration
//public class Mad4jConfig {
//
// @Bean
// public SlashCommandRegistrar slashCommandRegistrar(
// GatewayDiscordClient gatewayDiscordClient,
// CommandOptionAutocompleteListener commandOptionAutocompleteListener,
// ApplicationContext applicationContext,
// Environment environment
// ) {
// return new SlashCommandRegistrar(
// gatewayDiscordClient,
// commandOptionAutocompleteListener,
// applicationContext,
// environment
// );
// }
//
// @Bean
// public CommandOptionAutocompleteListener commandOptionAutocompleteListener(
// GatewayDiscordClient client,
// List<AutocompletionExecutor> autocompletionExecutors
// ) {
// return new CommandOptionAutocompleteListener(
// client,
// autocompletionExecutors
// );
// }
//
// @Bean
// public ComponentEventListener componentEventListener(
// GatewayDiscordClient client,
// ApplicationContext applicationContext
// ) {
// return new ComponentEventListener(
// client,
// applicationContext
// );
// }
//
// @Bean
// public SlashCommandListener slashCommandListener(
// ApplicationContext applicationContext,
// GatewayDiscordClient client,
// List<CommandRequirementExecutor> possibleRequirements
// ) {
// return new SlashCommandListener(
// applicationContext,
// client,
// possibleRequirements
// );
// }
//}
15 changes: 15 additions & 0 deletions src/main/java/net/stelitop/mad4j/SlashCommandRegistrar.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import discord4j.discordjson.json.ApplicationCommandOptionData;
import discord4j.discordjson.json.ApplicationCommandRequest;
import discord4j.discordjson.json.ImmutableApplicationCommandOptionData;
import discord4j.discordjson.possible.Possible;
import discord4j.rest.RestClient;
import lombok.AllArgsConstructor;
import lombok.ToString;
Expand All @@ -16,6 +17,7 @@
import net.stelitop.mad4j.utils.OptionType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.ApplicationContext;
Expand Down Expand Up @@ -50,6 +52,7 @@ public class SlashCommandRegistrar implements ApplicationRunner {
private final ApplicationContext applicationContext;
private final Environment environment;

@Autowired
public SlashCommandRegistrar(
GatewayDiscordClient gatewayDiscordClient,
CommandOptionAutocompleteListener commandOptionAutocompleteListener,
Expand Down Expand Up @@ -292,6 +295,18 @@ private ApplicationCommandOptionData parseRegularCommandParam(
String paramName = annotation.name().toLowerCase();
commandOptionAutocompleteListener.addMapping(commandName, paramName, annotation.autocomplete());
}
if (annotation.minValue() != Double.MIN_VALUE) {
acodBuilder.minValue(annotation.minValue());
}
if (annotation.maxValue() != Double.MAX_VALUE) {
acodBuilder.maxValue(annotation.maxValue());
}
if (annotation.minLength() > 0) {
acodBuilder.minLength(annotation.minLength());
}
if (annotation.maxLength() != Integer.MAX_VALUE) {
acodBuilder.maxLength(annotation.maxLength());
}

addChoicesToCommandParam(acodBuilder, annotation.choices());
return acodBuilder.build();
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/net/stelitop/mad4j/commands/CommandParam.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,22 @@
*/
Class<? extends AutocompletionExecutor> autocomplete() default NullAutocompleteExecutor.class;

/**
* The minimum value that this parameter must take. Only works for numerical params.
*/
double minValue() default Double.MIN_VALUE;
/**
* The maximum value that this parameter must take. Only works for numerical params.
*/
double maxValue() default Double.MAX_VALUE;

/**
* The minimum length for a string parameter.
*/
int minLength() default 0;

/**
* The maximum length for a string parameter.
*/
int maxLength() default Integer.MAX_VALUE;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
Expand All @@ -30,6 +31,7 @@ public class CommandOptionAutocompleteListener implements ApplicationRunner {
private final Map<Class<? extends AutocompletionExecutor>, AutocompletionExecutor> autocompletionExecutorBeans;
private final Map<Pair<String, String>, Class<? extends AutocompletionExecutor>> commandNameParamToExecutor;

@Autowired
public CommandOptionAutocompleteListener(
GatewayDiscordClient client,
List<AutocompletionExecutor> autocompletionExecutors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.ApplicationContext;
Expand All @@ -38,6 +39,7 @@ public class ComponentEventListener implements ApplicationRunner {
private final GatewayDiscordClient client;
private final ApplicationContext applicationContext;

@Autowired
public ComponentEventListener(
GatewayDiscordClient client,
ApplicationContext applicationContext
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import net.stelitop.mad4j.requirements.CommandRequirement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.ApplicationContext;
Expand Down Expand Up @@ -55,6 +56,7 @@ public class SlashCommandListener implements ApplicationRunner {
private final Map<Class<? extends CommandRequirementExecutor>, CommandRequirementExecutor> possibleRequirements;
private List<SlashCommandEntry> slashCommands;

@Autowired
public SlashCommandListener(
ApplicationContext applicationContext,
GatewayDiscordClient client,
Expand Down
45 changes: 45 additions & 0 deletions src/test/java/slashcommands/registering/BaseTestConfiguration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package slashcommands.registering;

import discord4j.core.GatewayDiscordClient;
import discord4j.rest.RestClient;
import discord4j.rest.service.ApplicationService;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@SpringBootConfiguration
@ComponentScan("net.stelitop.mad4j")
public class BaseTestConfiguration {

public static long TEST_APPLICATION_ID = 1L;

@Bean
public GatewayDiscordClient gatewayDiscordClient(RestClient restClientMock) {
GatewayDiscordClient gatewayDiscordClientMock = mock(GatewayDiscordClient.class);
when(gatewayDiscordClientMock.getRestClient()).thenReturn(restClientMock);
when(gatewayDiscordClientMock.on(any(), any())).thenReturn(Flux.empty());
return gatewayDiscordClientMock;
}

@Bean
public RestClient restClient(ApplicationService applicationServiceMock) {
RestClient restClientMock = mock(RestClient.class);
when(restClientMock.getApplicationId()).thenReturn(Mono.just(TEST_APPLICATION_ID));
when(restClientMock.getApplicationService()).thenReturn(applicationServiceMock);
return restClientMock;
}

@Bean
ApplicationService applicationService() {
ApplicationService applicationServiceMock = mock(ApplicationService.class);
when(applicationServiceMock.bulkOverwriteGlobalApplicationCommand(eq(TEST_APPLICATION_ID), any())).thenReturn(Flux.empty());
return applicationServiceMock;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package slashcommands.registering;

import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
@Import(BaseTestConfiguration.class)
public class BaseTestConfigurationTest {

@Test
void testSpringTestContext() {

}
}
73 changes: 73 additions & 0 deletions src/test/java/slashcommands/registering/CommandGroupTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package slashcommands.registering;

import discord4j.core.event.domain.interaction.ChatInputInteractionEvent;
import discord4j.discordjson.json.ApplicationCommandOptionData;
import discord4j.discordjson.json.ApplicationCommandRequest;
import discord4j.rest.service.ApplicationService;
import net.stelitop.mad4j.DiscordEventsComponent;
import net.stelitop.mad4j.InteractionEvent;
import net.stelitop.mad4j.commands.CommandParam;
import net.stelitop.mad4j.commands.SlashCommand;
import net.stelitop.mad4j.utils.OptionType;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;
import reactor.core.publisher.Mono;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

@RunWith(SpringRunner.class)
@SpringBootTest
@Import({BaseTestConfiguration.class, CommandGroupTest.TestComponent.class})
public class CommandGroupTest {

@Autowired
private ApplicationService applicationServiceMock;

@DiscordEventsComponent
public static class TestComponent {

static final String commandDescription = "Adds two numbers.";
static final String param1Description = "The first number.";
static final String param2Description = "The second number.";

@SlashCommand(name = "add numbers", description = commandDescription)
public Mono<Void> addTwoNumbersCommand(
@InteractionEvent ChatInputInteractionEvent event,
@CommandParam(name = "x", description = param1Description) long x,
@CommandParam(name = "y", description = param2Description) long y
) {
return event.reply("The sum is " + x + y);
}
}

@Test
public void testLoadingCommand() {
ArgumentCaptor<List<ApplicationCommandRequest>> argumentCaptor = ArgumentCaptor.forClass(List.class);
verify(applicationServiceMock, times(1)).bulkOverwriteGlobalApplicationCommand(
eq(BaseTestConfiguration.TEST_APPLICATION_ID), argumentCaptor.capture());

assertThat(argumentCaptor.getValue()).hasSize(1);
ApplicationCommandRequest request = argumentCaptor.getValue().get(0);
assertThat(request.name()).isEqualTo("add");
assertThat(request.options().get()).hasSize(1);
assertThat(request.options().get().get(0).type()).isEqualTo(OptionType.SUB_COMMAND);
assertThat(request.options().get().get(0).name()).isEqualTo("numbers");
assertThat(request.options().get().get(0).description()).isEqualTo(TestComponent.commandDescription);
assertThat(request.options().get().get(0).options().get()).containsExactly(
ApplicationCommandOptionData.builder().name("x").type(OptionType.INTEGER).required(true)
.description(TestComponent.param1Description).build(),
ApplicationCommandOptionData.builder().name("y").type(OptionType.INTEGER).required(true)
.description(TestComponent.param2Description).build()
);
}
}
Loading

0 comments on commit b1358ba

Please sign in to comment.