ACS-3649, ACS-3650 Action validation mechanism + validations against Action Definitions (#1481)

* ACS-3572: Action constraints endpoint + logic + unit tests.

* ACS-3572: Action constraints endpoint + logic + unit tests.

* ACS-3572: Action constraints endpoint fixes.

* ACS-3572: Cleanup after removal of GET all Action constraints.

* ACS-3572: Fixing formatting in tests.

* ACS-3572: Loosening V1 constraints restrictions for aspects, types and properties.

* ACS-3649: Action validators - constraints.

* ACS-3649: Action validators - constraints.

* ACS-3649: Action validators - constraints.

* ACS-3572: Adding validation for extra paramater.

* ACS-3649: Small refactors and fixes.

* ACS-3649: Validations against action definition.

* ACS-3649: Adding @Experimental annotation.

* ACS-3649: Fixes/refactoring after code review.

* ACS-3649: Removing ignored test
This commit is contained in:
Maciej Pichura
2022-10-10 17:13:51 +02:00
committed by GitHub
parent 0cfedbc979
commit 307eaff896
13 changed files with 654 additions and 34 deletions

View File

@@ -0,0 +1,59 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2017 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.actions;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.rest.api.Actions;
import org.alfresco.rest.api.model.ActionParameterConstraint;
import org.alfresco.rest.framework.WebApiDescription;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.resource.EntityResource;
import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.service.Experimental;
@EntityResource(name="action-constraints", title = "Action parameter constraints")
@Experimental
public class ActionConstraintsEntityResource implements EntityResourceAction.ReadById<ActionParameterConstraint>
{
private final Actions actions;
public ActionConstraintsEntityResource(Actions actions)
{
this.actions = actions;
}
@WebApiDescription(title = "Get single action parameters constraint",
description = "Retrieves a single action parameters constraint by constraint name",
successStatus = HttpServletResponse.SC_OK)
@Experimental
@Override
public ActionParameterConstraint readById(String constraintName, Parameters parameters) throws EntityNotFoundException
{
return actions.getActionConstraint(constraintName);
}
}

View File

@@ -0,0 +1,38 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.actions;
import org.alfresco.rest.api.model.rules.Action;
import org.alfresco.service.Experimental;
@Experimental
public interface ActionValidator
{
void validate(Action action);
boolean isEnabled();
}

View File

@@ -453,7 +453,7 @@ public class ActionsImpl implements Actions
map(this::toShortQName).
collect(Collectors.toList());
}
private String toShortQName(QName type)
{
return type.toPrefixString(prefixResolver);

View File

@@ -32,12 +32,14 @@ import static org.alfresco.repo.action.access.ActionAccessRestriction.ACTION_CON
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import org.alfresco.repo.action.ActionImpl;
import org.alfresco.repo.action.CompositeActionImpl;
import org.alfresco.rest.api.actions.ActionValidator;
import org.alfresco.rest.api.impl.rules.ActionParameterConverter;
import org.alfresco.rest.api.model.mapper.RestModelMapper;
import org.alfresco.rest.api.model.rules.Action;
@@ -49,10 +51,13 @@ import org.apache.commons.collections.CollectionUtils;
public class RestRuleActionModelMapper implements RestModelMapper<Action, org.alfresco.service.cmr.action.Action>
{
private final ActionParameterConverter parameterConverter;
private final List<ActionValidator> actionValidators;
public RestRuleActionModelMapper(ActionParameterConverter parameterConverter)
public RestRuleActionModelMapper(ActionParameterConverter parameterConverter,
List<ActionValidator> actionValidators)
{
this.parameterConverter = parameterConverter;
this.actionValidators = actionValidators;
}
/**
@@ -104,8 +109,14 @@ public class RestRuleActionModelMapper implements RestModelMapper<Action, org.al
private org.alfresco.service.cmr.action.Action toServiceAction(Action action)
{
final Map<String, Serializable> params = Optional.ofNullable(action.getParams()).orElse(emptyMap());
validateAction(action);
final Map<String, Serializable> convertedParams =
parameterConverter.getConvertedParams(params, action.getActionDefinitionId());
return new ActionImpl(null, GUID.generate(), action.getActionDefinitionId(), convertedParams);
}
private void validateAction(Action action) {
actionValidators.stream()
.filter(ActionValidator::isEnabled)
.forEach(v -> v.validate(action));
}
}

View File

@@ -0,0 +1,133 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.impl.validator.actions;
import java.io.Serializable;
import java.util.Map;
import org.alfresco.rest.api.Actions;
import org.alfresco.rest.api.actions.ActionValidator;
import org.alfresco.rest.api.model.ActionDefinition;
import org.alfresco.rest.api.model.ActionParameterConstraint;
import org.alfresco.rest.api.model.rules.Action;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
import org.alfresco.service.Experimental;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
/**
* This class will validate all action types against action parameters definitions (mandatory parameters, parameter constraints)
*/
@Experimental
public class ActionParameterDefinitionValidator implements ActionValidator
{
private static final boolean IS_ENABLED = true;
static final String INVALID_PARAMETER_VALUE =
"Action parameter: %s has invalid value (%s). Look up possible values for constraint name %s";
static final String MISSING_PARAMETER = "Missing action's mandatory parameter: %s";
static final String MUST_NOT_CONTAIN_PARAMETER = "Action of definition id: %s must not contain parameter of name: %s";
static final String PARAMS_SHOULD_NOT_BE_EMPTY =
"Action parameters should not be null or empty for this action. See Action Definition for action of: %s";
static final String INVALID_ACTION_DEFINITION = "Invalid action definition requested %s";
private final Actions actions;
public ActionParameterDefinitionValidator(Actions actions)
{
this.actions = actions;
}
/**
* Validates action against its parameters definitions (mandatory parameters, parameter constraints)
*
* @param action Action to be validated
*/
@Override
public void validate(Action action)
{
ActionDefinition actionDefinition;
try
{
actionDefinition = actions.getActionDefinitionById(action.getActionDefinitionId());
} catch (NotFoundException e) {
throw new InvalidArgumentException(String.format(INVALID_ACTION_DEFINITION, action.getActionDefinitionId()));
}
validateParametersSize(action.getParams(), actionDefinition);
final Map<String, Serializable> params = action.getParams();
if (MapUtils.isNotEmpty(params))
{
params.forEach((key, value) -> checkParameterShouldExist(key, actionDefinition));
actionDefinition.getParameterDefinitions().forEach(p -> validateParameterDefinitions(p, params));
}
}
@Override
public boolean isEnabled()
{
return IS_ENABLED;
}
private void validateParametersSize(final Map<String, Serializable> params, final ActionDefinition actionDefinition)
{
if (CollectionUtils.isNotEmpty(actionDefinition.getParameterDefinitions()) && MapUtils.isEmpty(params))
{
throw new IllegalArgumentException(String.format(PARAMS_SHOULD_NOT_BE_EMPTY, actionDefinition.getName()));
}
}
private void validateParameterDefinitions(final ActionDefinition.ParameterDefinition parameterDefinition,
final Map<String, Serializable> params)
{
final Serializable parameterValue = params.get(parameterDefinition.getName());
if (parameterDefinition.isMandatory() && parameterValue == null)
{
throw new IllegalArgumentException(String.format(MISSING_PARAMETER, parameterDefinition.getName()));
}
if (parameterDefinition.getParameterConstraintName() != null)
{
final ActionParameterConstraint actionConstraint =
actions.getActionConstraint(parameterDefinition.getParameterConstraintName());
if (parameterValue != null && actionConstraint.getConstraintValues().stream()
.noneMatch(constraintData -> constraintData.getValue().equals(parameterValue.toString())))
{
throw new IllegalArgumentException(String.format(INVALID_PARAMETER_VALUE, parameterDefinition.getName(), parameterValue,
actionConstraint.getConstraintName()));
}
}
}
private void checkParameterShouldExist(final String parameterName, final ActionDefinition actionDefinition)
{
if (actionDefinition.getParameterDefinitions().stream().noneMatch(pd -> parameterName.equals(pd.getName())))
{
throw new IllegalArgumentException(String.format(MUST_NOT_CONTAIN_PARAMETER, actionDefinition.getName(), parameterName));
}
}
}

View File

@@ -588,7 +588,14 @@
<bean class="org.alfresco.rest.api.actions.ActionParameterConstraintsEntityResource">
<constructor-arg name="actions" ref="Actions"/>
</bean>
<!-- action parameter validators start here -->
<bean id="actionParameterConstraintsValidator" class="org.alfresco.rest.api.impl.validator.actions.ActionParameterDefinitionValidator">
<constructor-arg name="actions" ref="Actions"/>
</bean>
<!-- action parameter validators end here-->
<bean id="Downloads" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.rest.api.Downloads</value>
@@ -965,6 +972,11 @@
<bean id="actionMapper" class="org.alfresco.rest.api.impl.mapper.rules.RestRuleActionModelMapper">
<constructor-arg name="parameterConverter" ref="actionParameterConverter"/>
<constructor-arg name="actionValidators">
<list>
<ref bean="actionParameterConstraintsValidator"/>
</list>
</constructor-arg>
</bean>
<bean id="ruleMapper" class="org.alfresco.rest.api.impl.mapper.rules.RestRuleModelMapper">

View File

@@ -0,0 +1,66 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.actions;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import org.alfresco.rest.api.Actions;
import org.alfresco.rest.api.model.ActionParameterConstraint;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class ActionConstraintsEntityResourceTest
{
@Mock
private Actions actionsMock;
@Mock
private Parameters parametersMock;
@InjectMocks
private ActionConstraintsEntityResource objectUnderTest;
@Test
public void testReadById() {
final String name = "name";
final ActionParameterConstraint dummyConstraint = new ActionParameterConstraint();
given(actionsMock.getActionConstraint(name)).willReturn(dummyConstraint);
//when
ActionParameterConstraint result = objectUnderTest.readById(name, parametersMock);
then(actionsMock).should().getActionConstraint(name);
then(actionsMock).shouldHaveNoMoreInteractions();
assertThat(result).isNotNull().usingRecursiveComparison().isEqualTo(dummyConstraint);
}
}

View File

@@ -43,11 +43,14 @@ import java.util.List;
import java.util.Map;
import org.alfresco.repo.action.ActionImpl;
import org.alfresco.rest.api.actions.ActionValidator;
import org.alfresco.rest.api.impl.rules.ActionParameterConverter;
import org.alfresco.rest.api.model.rules.Action;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
@@ -65,10 +68,17 @@ public class RestRuleActionModelMapperTest
@Mock
private ActionParameterConverter parameterConverter;
@Mock
private ActionValidator sampleValidatorMock;
@InjectMocks
private RestRuleActionModelMapper objectUnderTest;
@Before
public void setUp() {
objectUnderTest = new RestRuleActionModelMapper(parameterConverter, List.of(sampleValidatorMock));
given(sampleValidatorMock.isEnabled()).willReturn(true);
}
@Test
public void testToRestModel()
{

View File

@@ -0,0 +1,217 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.impl.validator.actions;
import static org.alfresco.rest.api.impl.validator.actions.ActionParameterDefinitionValidator.MISSING_PARAMETER;
import static org.alfresco.rest.api.impl.validator.actions.ActionParameterDefinitionValidator.MUST_NOT_CONTAIN_PARAMETER;
import static org.alfresco.rest.api.impl.validator.actions.ActionParameterDefinitionValidator.PARAMS_SHOULD_NOT_BE_EMPTY;
import static org.alfresco.service.cmr.dictionary.DataTypeDefinition.BOOLEAN;
import static org.alfresco.service.cmr.dictionary.DataTypeDefinition.TEXT;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.mockito.BDDMockito.then;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.rest.api.Actions;
import org.alfresco.rest.api.model.ActionDefinition;
import org.alfresco.rest.api.model.rules.Action;
import org.alfresco.service.Experimental;
import org.alfresco.service.namespace.QName;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.BDDMockito;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
@Experimental
@RunWith(MockitoJUnitRunner.class)
public class ActionParameterDefinitionValidatorTest
{
private static final String MANDATORY_PARAM_KEY = "paramKey";
private static final String NON_MANDATORY_PARAM_KEY = "nonMandatoryParamKey";
@Mock
private Actions actionsMock;
@InjectMocks
private ActionParameterDefinitionValidator objectUnderTest;
@Test
public void testSimpleValidationPasses()
{
final Action action = new Action();
final String actionDefinitionId = "properActionDefinition";
action.setActionDefinitionId(actionDefinitionId);
action.setParams(Map.of(MANDATORY_PARAM_KEY, "paramValue"));
final List<ActionDefinition.ParameterDefinition> parameterDefinitions =
List.of(createParameterDefinition(MANDATORY_PARAM_KEY, TEXT, true, null));
final ActionDefinition actionDefinition = createActionDefinition(actionDefinitionId, parameterDefinitions);
BDDMockito.given(actionsMock.getActionDefinitionById(actionDefinitionId)).willReturn(actionDefinition);
//when
objectUnderTest.validate(action);
then(actionsMock).should().getActionDefinitionById(actionDefinitionId);
then(actionsMock).shouldHaveNoMoreInteractions();
}
@Test
public void testValidationPassesWhenNoParametersNeeded()
{
final Action action = new Action();
final String actionDefinitionId = "properActionDefinition";
action.setActionDefinitionId(actionDefinitionId);
final ActionDefinition actionDefinition = createActionDefinition(actionDefinitionId, null);
BDDMockito.given(actionsMock.getActionDefinitionById(actionDefinitionId)).willReturn(actionDefinition);
//when
objectUnderTest.validate(action);
then(actionsMock).should().getActionDefinitionById(actionDefinitionId);
then(actionsMock).shouldHaveNoMoreInteractions();
}
@Test
public void testValidationPassesWhenNoMandatoryParameters()
{
final Action action = new Action();
final String actionDefinitionId = "properActionDefinition";
action.setActionDefinitionId(actionDefinitionId);
action.setParams(Map.of(MANDATORY_PARAM_KEY, "paramValue"));
final List<ActionDefinition.ParameterDefinition> parameterDefinitions =
List.of(createParameterDefinition(MANDATORY_PARAM_KEY, TEXT, true, null),
createParameterDefinition(NON_MANDATORY_PARAM_KEY, BOOLEAN, false, null));
final ActionDefinition actionDefinition = createActionDefinition(actionDefinitionId, parameterDefinitions);
BDDMockito.given(actionsMock.getActionDefinitionById(actionDefinitionId)).willReturn(actionDefinition);
//when
objectUnderTest.validate(action);
then(actionsMock).should().getActionDefinitionById(actionDefinitionId);
then(actionsMock).shouldHaveNoMoreInteractions();
}
@Test
public void testValidationFailsWhenTooManyParameters()
{
final Action action = new Action();
final String actionDefinitionId = "properActionDefinition";
action.setActionDefinitionId(actionDefinitionId);
action.setParams(Map.of(MANDATORY_PARAM_KEY, "paramValue", NON_MANDATORY_PARAM_KEY, false));
final List<ActionDefinition.ParameterDefinition> parameterDefinitions =
List.of(createParameterDefinition(MANDATORY_PARAM_KEY, TEXT, true, null));
final ActionDefinition actionDefinition = createActionDefinition(actionDefinitionId, parameterDefinitions);
BDDMockito.given(actionsMock.getActionDefinitionById(actionDefinitionId)).willReturn(actionDefinition);
//when
assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> objectUnderTest.validate(action))
.withMessageContaining(String.format(MUST_NOT_CONTAIN_PARAMETER, actionDefinitionId, NON_MANDATORY_PARAM_KEY));
then(actionsMock).should().getActionDefinitionById(actionDefinitionId);
then(actionsMock).shouldHaveNoMoreInteractions();
}
@Test
public void testValidationFailsWhenMissingParameters()
{
final Action action = new Action();
final String actionDefinitionId = "properActionDefinition";
action.setActionDefinitionId(actionDefinitionId);
final List<ActionDefinition.ParameterDefinition> parameterDefinitions =
List.of(createParameterDefinition(MANDATORY_PARAM_KEY, TEXT, true, null));
final ActionDefinition actionDefinition = createActionDefinition(actionDefinitionId, parameterDefinitions);
BDDMockito.given(actionsMock.getActionDefinitionById(actionDefinitionId)).willReturn(actionDefinition);
//when
assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> objectUnderTest.validate(action))
.withMessageContaining(String.format(PARAMS_SHOULD_NOT_BE_EMPTY, actionDefinitionId));
then(actionsMock).should().getActionDefinitionById(actionDefinitionId);
then(actionsMock).shouldHaveNoMoreInteractions();
}
@Test
public void testValidationFailsWhenMissingParameterValue()
{
final Action action = new Action();
final String actionDefinitionId = "properActionDefinition";
action.setActionDefinitionId(actionDefinitionId);
final Map<String, java.io.Serializable> params = new HashMap<>();
params.put(MANDATORY_PARAM_KEY, null);
action.setParams(params);
final List<ActionDefinition.ParameterDefinition> parameterDefinitions =
List.of(createParameterDefinition(MANDATORY_PARAM_KEY, TEXT, true, null));
final ActionDefinition actionDefinition = createActionDefinition(actionDefinitionId, parameterDefinitions);
BDDMockito.given(actionsMock.getActionDefinitionById(actionDefinitionId)).willReturn(actionDefinition);
//when
assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> objectUnderTest.validate(action))
.withMessageContaining(String.format(MISSING_PARAMETER, MANDATORY_PARAM_KEY));
then(actionsMock).should().getActionDefinitionById(actionDefinitionId);
then(actionsMock).shouldHaveNoMoreInteractions();
}
@Test
public void testValidationFailsWhenMandatoryParameterIsMissing()
{
final Action action = new Action();
final String actionDefinitionId = "properActionDefinition";
action.setActionDefinitionId(actionDefinitionId);
action.setParams(Map.of(NON_MANDATORY_PARAM_KEY, true));
final List<ActionDefinition.ParameterDefinition> parameterDefinitions =
List.of(createParameterDefinition(MANDATORY_PARAM_KEY, TEXT, true, null),
createParameterDefinition(NON_MANDATORY_PARAM_KEY, BOOLEAN, false, null));
final ActionDefinition actionDefinition = createActionDefinition(actionDefinitionId, parameterDefinitions);
BDDMockito.given(actionsMock.getActionDefinitionById(actionDefinitionId)).willReturn(actionDefinition);
//when
assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> objectUnderTest.validate(action))
.withMessageContaining(String.format(MISSING_PARAMETER, MANDATORY_PARAM_KEY));
then(actionsMock).should().getActionDefinitionById(actionDefinitionId);
then(actionsMock).shouldHaveNoMoreInteractions();
}
private ActionDefinition createActionDefinition(final String actionDefinitionId,
List<ActionDefinition.ParameterDefinition> parameterDefinitions)
{
return new ActionDefinition(actionDefinitionId, actionDefinitionId, "title", "description", Collections.emptyList(), false, false,
parameterDefinitions);
}
private ActionDefinition.ParameterDefinition createParameterDefinition(final String name, final QName qName, final boolean mandatory,
final String constraint)
{
return new ActionDefinition.ParameterDefinition(name, qName.toPrefixString(), false, mandatory, "label", constraint);
}
}