Rework help command
- Change help command output to get templated using model classes. - Remove things around ParameterDescription as those are replaced with template classes. - Fixes for native configs. - For now availability and aliases are removed from help to get back in better form. - Aliases has been partly introduced to structure. - Fixes #422
This commit is contained in:
committed by
GitHub
parent
eed1d84653
commit
bd9ab62013
@@ -1,181 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.shell;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
|
||||
import javax.validation.metadata.ElementDescriptor;
|
||||
|
||||
/**
|
||||
* Encapsulates information about a shell invokable method parameter, so that it can be documented.
|
||||
*
|
||||
* <p>Instances of this class are constructed by {@link ParameterResolver#describe(MethodParameter)}.</p>
|
||||
*
|
||||
* @author Eric Bottard
|
||||
*/
|
||||
public class ParameterDescription {
|
||||
|
||||
/**
|
||||
* A string representation of the type of the parameter.
|
||||
*/
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* A string representation of the parameter, as it should appear in a parameter list.
|
||||
* If not provided, this is derived from the parameter type.
|
||||
*/
|
||||
private String formal;
|
||||
|
||||
/**
|
||||
* A string representation of the default value (if the option is left out entirely) for the parameter, if any.
|
||||
*/
|
||||
private Optional<String> defaultValue = Optional.empty();
|
||||
|
||||
/**
|
||||
* A string representation of the default value for this parameter, if it can be used as a mere flag (<em>e.g.</em>
|
||||
* {@literal --force} without a value, being an equivalent to {@literal --force true}).
|
||||
* <p>{@literal Optional.empty()} (the default) means that this parameter cannot be used as a flag.</p>
|
||||
*/
|
||||
private Optional<String> defaultValueWhenFlag = Optional.empty();
|
||||
|
||||
/**
|
||||
* The list of 'keys' that can be used to specify this parameter, if any.
|
||||
*/
|
||||
private List<String> keys = Collections.emptyList();
|
||||
|
||||
/**
|
||||
* Depending on the {@link ParameterResolver}, whether keys are mandatory to identify this parameter.
|
||||
*/
|
||||
private boolean mandatoryKey = true;
|
||||
|
||||
/**
|
||||
* A short description of this parameter.
|
||||
*/
|
||||
private String help = "";
|
||||
|
||||
/**
|
||||
* Allows discovery of bean validation constraints for the command parameter.
|
||||
* <p>Note that most often, constraints will directly come from parameter constraints,
|
||||
* but sometimes (<em>e.g.</em> in case of one method argument mapping to multiple
|
||||
* command options) may come from property constraints.</p>
|
||||
*/
|
||||
private ElementDescriptor elementDescriptor;
|
||||
|
||||
public void type(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public ParameterDescription help(String help) {
|
||||
this.help = help;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean mandatoryKey() {
|
||||
return mandatoryKey;
|
||||
}
|
||||
|
||||
public List<String> keys() {
|
||||
return keys;
|
||||
}
|
||||
|
||||
public Optional<String> defaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public ParameterDescription defaultValue(String defaultValue) {
|
||||
this.defaultValue = Optional.ofNullable(defaultValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ParameterDescription whenFlag(String defaultValue) {
|
||||
this.defaultValueWhenFlag = Optional.of(defaultValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ParameterDescription keys(List<String> keys) {
|
||||
this.keys = keys;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ParameterDescription mandatoryKey(boolean mandatoryKey) {
|
||||
this.mandatoryKey = mandatoryKey;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an ElementDescriptor used to discover constraints. May be {@literal null}.
|
||||
*/
|
||||
public ElementDescriptor elementDescriptor() {
|
||||
return this.elementDescriptor;
|
||||
}
|
||||
|
||||
public ParameterDescription elementDescriptor(ElementDescriptor descriptor) {
|
||||
this.elementDescriptor = descriptor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String type() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String formal() {
|
||||
return formal;
|
||||
}
|
||||
|
||||
public String help() {
|
||||
return help;
|
||||
}
|
||||
|
||||
public Optional<String> defaultValueWhenFlag() {
|
||||
return defaultValueWhenFlag;
|
||||
}
|
||||
|
||||
public ParameterDescription formal(String formal) {
|
||||
this.formal = formal;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s %s", keys.isEmpty() ? "" : keys().iterator().next(), formal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
ParameterDescription that = (ParameterDescription) o;
|
||||
return mandatoryKey == that.mandatoryKey &&
|
||||
// Objects.equals(parameter, that.parameter) &&
|
||||
Objects.equals(type, that.type) &&
|
||||
Objects.equals(formal, that.formal) &&
|
||||
Objects.equals(defaultValue, that.defaultValue) &&
|
||||
Objects.equals(defaultValueWhenFlag, that.defaultValueWhenFlag) &&
|
||||
Objects.equals(keys, that.keys) &&
|
||||
Objects.equals(help, that.help);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(type, formal, defaultValue, defaultValueWhenFlag, keys, mandatoryKey, help);
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.shell;
|
||||
|
||||
/**
|
||||
* Thrown by a {@link ParameterResolver} when a parameter that should have been set has been left out altogether.
|
||||
*
|
||||
* @author Eric Bottard
|
||||
*/
|
||||
public class ParameterMissingResolutionException extends RuntimeException {
|
||||
|
||||
private final ParameterDescription parameterDescription;
|
||||
|
||||
public ParameterMissingResolutionException(ParameterDescription parameterDescription) {
|
||||
this.parameterDescription = parameterDescription;
|
||||
}
|
||||
|
||||
public ParameterDescription getParameterDescription() {
|
||||
return parameterDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return String.format("Parameter '%s' should be specified", parameterDescription);
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.shell.command.CommandAlias;
|
||||
import org.springframework.shell.command.CommandCatalog;
|
||||
import org.springframework.shell.command.CommandExecution;
|
||||
import org.springframework.shell.command.CommandExecution.CommandExecutionException;
|
||||
@@ -155,7 +156,15 @@ public class Shell {
|
||||
|
||||
Optional<CommandRegistration> commandRegistration = commandRegistry.getRegistrations().values().stream()
|
||||
.filter(r -> {
|
||||
return r.getCommand().equals(command);
|
||||
if (r.getCommand().equals(command)) {
|
||||
return true;
|
||||
}
|
||||
for (CommandAlias a : r.getAliases()) {
|
||||
if (a.getCommand().equals(command)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
})
|
||||
.findFirst();
|
||||
|
||||
@@ -255,14 +264,12 @@ public class Shell {
|
||||
// Workaround for https://github.com/spring-projects/spring-shell/issues/150
|
||||
// (sadly, this ties this class to JLine somehow)
|
||||
int lastWordStart = prefix.lastIndexOf(' ') + 1;
|
||||
return commandRegistry.getRegistrations().values().stream()
|
||||
.filter(r -> {
|
||||
return r.getCommand().startsWith(prefix);
|
||||
})
|
||||
.map(r -> {
|
||||
String c = r.getCommand();
|
||||
return commandRegistry.getRegistrations().entrySet().stream()
|
||||
.filter(e -> e.getKey().startsWith(prefix))
|
||||
.map(e -> {
|
||||
String c = e.getKey();
|
||||
c = c.substring(lastWordStart);
|
||||
return toCommandProposal(c, r);
|
||||
return toCommandProposal(c, e.getValue());
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.shell;
|
||||
|
||||
/**
|
||||
* Thrown during parameter resolution, when a parameter has been identified, but could not be correctly resolved.
|
||||
*
|
||||
* @author Eric Bottard
|
||||
*/
|
||||
public class UnfinishedParameterResolutionException extends RuntimeException {
|
||||
|
||||
private final ParameterDescription parameterDescription;
|
||||
|
||||
private final CharSequence input;
|
||||
|
||||
public UnfinishedParameterResolutionException(ParameterDescription parameterDescription, CharSequence input) {
|
||||
this.parameterDescription = parameterDescription;
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
public ParameterDescription getParameterDescription() {
|
||||
return parameterDescription;
|
||||
}
|
||||
|
||||
public CharSequence getInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return String.format("Error trying to resolve '%s' using [%s]", parameterDescription, input);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.shell.command;
|
||||
|
||||
/**
|
||||
* Interface representing an alias in a command.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*/
|
||||
public interface CommandAlias {
|
||||
|
||||
/**
|
||||
* Gets a command an alias.
|
||||
*
|
||||
* @return command
|
||||
*/
|
||||
String getCommand();
|
||||
|
||||
/**
|
||||
* Get group for an alias.
|
||||
*
|
||||
* @return the group
|
||||
*/
|
||||
String getGroup();
|
||||
|
||||
/**
|
||||
* Gets an instance of a default {@link CommandAlias}.
|
||||
*
|
||||
* @param command the command
|
||||
* @param group the group
|
||||
* @return default command alias
|
||||
*/
|
||||
public static CommandAlias of(String command, String group) {
|
||||
return new DefaultCommandAlias(command, group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation of {@link CommandAlias}.
|
||||
*/
|
||||
public static class DefaultCommandAlias implements CommandAlias {
|
||||
|
||||
private final String command;
|
||||
private final String group;
|
||||
|
||||
public DefaultCommandAlias(String command, String group) {
|
||||
this.command = command;
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroup() {
|
||||
return group;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,6 +103,9 @@ public interface CommandCatalog {
|
||||
for (CommandRegistration r : registration) {
|
||||
String commandName = r.getCommand();
|
||||
commandRegistrations.put(commandName, r);
|
||||
for (CommandAlias a : r.getAliases()) {
|
||||
commandRegistrations.put(a.getCommand(), r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,6 +114,9 @@ public interface CommandCatalog {
|
||||
for (CommandRegistration r : registration) {
|
||||
String commandName = r.getCommand();
|
||||
commandRegistrations.remove(commandName);
|
||||
for (CommandAlias a : r.getAliases()) {
|
||||
commandRegistrations.remove(a.getCommand());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,13 +162,5 @@ public interface CommandCatalog {
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
// private static String commandName(String[] commands) {
|
||||
// return Arrays.asList(commands).stream()
|
||||
// .flatMap(c -> Stream.of(c.split(" ")))
|
||||
// .filter(c -> StringUtils.hasText(c))
|
||||
// .map(c -> c.trim())
|
||||
// .collect(Collectors.joining(" "));
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +91,13 @@ public interface CommandRegistration {
|
||||
*/
|
||||
List<CommandOption> getOptions();
|
||||
|
||||
/**
|
||||
* Gets an aliases.
|
||||
*
|
||||
* @return the aliases
|
||||
*/
|
||||
List<CommandAlias> getAliases();
|
||||
|
||||
/**
|
||||
* Gets a new instance of a {@link Buidler}.
|
||||
*
|
||||
@@ -350,6 +357,35 @@ public interface CommandRegistration {
|
||||
Builder and();
|
||||
}
|
||||
|
||||
/**
|
||||
* Spec defining an alias.
|
||||
*/
|
||||
public interface AliasSpec {
|
||||
|
||||
/**
|
||||
* Define commands for an alias.
|
||||
*
|
||||
* @param commands the commands
|
||||
* @return a target spec for chaining
|
||||
*/
|
||||
AliasSpec command(String... commands);
|
||||
|
||||
/**
|
||||
* Define group for an alias.
|
||||
*
|
||||
* @param group the group
|
||||
* @return a target spec for chaining
|
||||
*/
|
||||
AliasSpec group(String group);
|
||||
|
||||
/**
|
||||
* Return a builder for chaining.
|
||||
*
|
||||
* @return a builder for chaining
|
||||
*/
|
||||
Builder and();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder interface for {@link CommandRegistration}.
|
||||
*/
|
||||
@@ -413,6 +449,13 @@ public interface CommandRegistration {
|
||||
*/
|
||||
TargetSpec withTarget();
|
||||
|
||||
/**
|
||||
* Define an alias what this command should execute
|
||||
*
|
||||
* @return alias spec for chaining
|
||||
*/
|
||||
AliasSpec withAlias();
|
||||
|
||||
/**
|
||||
* Builds a {@link CommandRegistration}.
|
||||
*
|
||||
@@ -612,6 +655,40 @@ public interface CommandRegistration {
|
||||
}
|
||||
}
|
||||
|
||||
static class DefaultAliasSpec implements AliasSpec {
|
||||
|
||||
private BaseBuilder builder;
|
||||
private String[] commands;
|
||||
private String group;
|
||||
|
||||
DefaultAliasSpec(BaseBuilder builder) {
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AliasSpec command(String... commands) {
|
||||
Assert.notNull(commands, "commands must be set");
|
||||
this.commands = Arrays.asList(commands).stream()
|
||||
.flatMap(c -> Stream.of(c.split(" ")))
|
||||
.filter(c -> StringUtils.hasText(c))
|
||||
.map(c -> c.trim())
|
||||
.collect(Collectors.toList())
|
||||
.toArray(new String[0]);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AliasSpec group(String group) {
|
||||
this.group = group;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder and() {
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
|
||||
static class DefaultCommandRegistration implements CommandRegistration {
|
||||
|
||||
private String command;
|
||||
@@ -621,10 +698,11 @@ public interface CommandRegistration {
|
||||
private Supplier<Availability> availability;
|
||||
private List<DefaultOptionSpec> optionSpecs;
|
||||
private DefaultTargetSpec targetSpec;
|
||||
private List<DefaultAliasSpec> aliasSpecs;
|
||||
|
||||
public DefaultCommandRegistration(String[] commands, InteractionMode interactionMode, String group,
|
||||
String description, Supplier<Availability> availability, List<DefaultOptionSpec> optionSpecs,
|
||||
DefaultTargetSpec targetSpec) {
|
||||
DefaultTargetSpec targetSpec, List<DefaultAliasSpec> aliasSpecs) {
|
||||
this.command = commandArrayToName(commands);
|
||||
this.interactionMode = interactionMode;
|
||||
this.group = group;
|
||||
@@ -632,6 +710,7 @@ public interface CommandRegistration {
|
||||
this.availability = availability;
|
||||
this.optionSpecs = optionSpecs;
|
||||
this.targetSpec = targetSpec;
|
||||
this.aliasSpecs = aliasSpecs;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -681,6 +760,15 @@ public interface CommandRegistration {
|
||||
throw new IllegalArgumentException("No bean, function or consumer defined");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommandAlias> getAliases() {
|
||||
return this.aliasSpecs.stream()
|
||||
.map(spec -> {
|
||||
return CommandAlias.of(commandArrayToName(spec.commands), spec.group);
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static String commandArrayToName(String[] commands) {
|
||||
return Arrays.asList(commands).stream()
|
||||
.flatMap(c -> Stream.of(c.split(" ")))
|
||||
@@ -702,6 +790,7 @@ public interface CommandRegistration {
|
||||
private String description;
|
||||
private Supplier<Availability> availability;
|
||||
private List<DefaultOptionSpec> optionSpecs = new ArrayList<>();
|
||||
private List<DefaultAliasSpec> aliasSpecs = new ArrayList<>();
|
||||
private DefaultTargetSpec targetSpec;
|
||||
|
||||
@Override
|
||||
@@ -754,13 +843,20 @@ public interface CommandRegistration {
|
||||
return spec;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AliasSpec withAlias() {
|
||||
DefaultAliasSpec spec = new DefaultAliasSpec(this);
|
||||
this.aliasSpecs.add(spec);
|
||||
return spec;
|
||||
};
|
||||
|
||||
@Override
|
||||
public CommandRegistration build() {
|
||||
Assert.notNull(commands, "command cannot be empty");
|
||||
Assert.notNull(targetSpec, "target cannot be empty");
|
||||
Assert.state(!(targetSpec.bean != null && targetSpec.function != null), "only one target can exist");
|
||||
return new DefaultCommandRegistration(commands, interactionMode, group, description, availability,
|
||||
optionSpecs, targetSpec);
|
||||
optionSpecs, targetSpec, aliasSpecs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,22 @@ public class CommandCatalogTests extends AbstractCommandTests {
|
||||
assertThat(catalog.getRegistrations()).hasSize(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCommandAliases () {
|
||||
CommandRegistration r1 = CommandRegistration.builder()
|
||||
.command("group1 sub1")
|
||||
.withAlias()
|
||||
.command("group1 sub2")
|
||||
.and()
|
||||
.withTarget()
|
||||
.function(function1)
|
||||
.and()
|
||||
.build();
|
||||
CommandCatalog catalog = CommandCatalog.of();
|
||||
catalog.register(r1);
|
||||
assertThat(catalog.getRegistrations()).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolver() {
|
||||
// catalog itself would not have any registered command but
|
||||
|
||||
@@ -354,4 +354,31 @@ public class CommandRegistrationTests extends AbstractCommandTests {
|
||||
assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(0);
|
||||
assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(0);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAliases() {
|
||||
CommandRegistration registration = CommandRegistration.builder()
|
||||
.command("command1")
|
||||
.group("Test Group")
|
||||
.withAlias()
|
||||
.command("alias1")
|
||||
.group("Alias Group")
|
||||
.and()
|
||||
.withAlias()
|
||||
.command("alias2")
|
||||
.group("Alias Group")
|
||||
.and()
|
||||
.withTarget()
|
||||
.function(function1)
|
||||
.and()
|
||||
.build();
|
||||
assertThat(registration.getCommand()).isEqualTo("command1");
|
||||
assertThat(registration.getGroup()).isEqualTo("Test Group");
|
||||
assertThat(registration.getAliases()).hasSize(2);
|
||||
assertThat(registration.getAliases().stream().map(CommandAlias::getCommand)).containsExactlyInAnyOrder("alias1",
|
||||
"alias2");
|
||||
assertThat(registration.getAliases().get(0).getGroup()).isEqualTo("Alias Group");
|
||||
assertThat(registration.getAliases().get(1).getGroup()).isEqualTo("Alias Group");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user