/*
* Copyright 2016 Nokia Solutions and Networks
* Licensed under the Apache License, Version 2.0,
* see license.txt file for details.
*/
package org.robotframework.ide.eclipse.main.plugin.model.cmd;
import static com.google.common.collect.Lists.newArrayList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assume.assumeTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import java.util.Collections;
import java.util.List;
import org.eclipse.e4.core.services.events.IEventBroker;
import org.junit.Test;
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.runner.RunWith;
import org.robotframework.ide.eclipse.main.plugin.mockeclipse.ContextInjector;
import org.robotframework.ide.eclipse.main.plugin.mockmodel.RobotSuiteFileCreator;
import org.robotframework.ide.eclipse.main.plugin.model.RobotCase;
import org.robotframework.ide.eclipse.main.plugin.model.RobotCasesSection;
import org.robotframework.ide.eclipse.main.plugin.model.RobotKeywordCall;
import org.robotframework.ide.eclipse.main.plugin.model.RobotKeywordDefinition;
import org.robotframework.ide.eclipse.main.plugin.model.RobotKeywordsSection;
import org.robotframework.ide.eclipse.main.plugin.model.RobotModelEvents;
import org.robotframework.ide.eclipse.main.plugin.model.RobotSuiteFile;
import org.robotframework.ide.eclipse.main.plugin.tableeditor.EditorCommand;
@RunWith(Theories.class)
public class SetKeywordCallArgumentCommand2Test {
// FIXME : test documentation too
@DataPoints
public static int[] indexes = new int[] { 0, 1, 2, 3, 4, 5, 10, 50, 100 };
@DataPoints
public static RobotKeywordCall[] codeHolders() {
final List<RobotKeywordCall> elements = newArrayList();
for (final RobotCase testCase : createTestCases()) {
elements.addAll(testCase.getChildren());
}
for (final RobotKeywordDefinition keyword : createKeywords()) {
elements.addAll(keyword.getChildren());
}
return elements.toArray(new RobotKeywordCall[0]);
}
@Theory
public void argumentChangesToGivenValue_whenGivenValueIsNonEmpty(final RobotKeywordCall call, final int index) {
final List<String> arguments = call.getArguments();
assumeTrue(arguments.size() > 0);
assumeTrue(index < arguments.size());
final List<String> expectedArgs = newArrayList(arguments);
expectedArgs.set(index, "new_arg");
checkArgumentsChangesProperly(call, "new_arg", index, expectedArgs);
}
@Theory
public void argumentChangesToBackslash_whenGivenValueIsEmptyAndArgumentIsNotLast(final RobotKeywordCall call,
final int index) {
final List<String> arguments = call.getArguments();
assumeTrue(arguments.size() > 1);
assumeTrue(index < arguments.size() - 1);
final List<String> expectedArgs = newArrayList(arguments);
expectedArgs.set(index, "\\");
if (arguments.equals(expectedArgs)) {
// it may happen for elements inside case_3 and keyword_3
checkArgumentsDoesNotChange(call, "", index);
} else {
checkArgumentsChangesProperly(call, "", index, expectedArgs);
}
}
@Theory
public void argumentIsRemoved_whenGivenValueIsEmptyAndArgumentIsLast(final RobotKeywordCall call, final int index) {
final List<String> arguments = call.getArguments();
assumeTrue(arguments.size() > 0);
assumeTrue(index == arguments.size() - 1);
final List<String> expectedArgs = newArrayList(arguments);
expectedArgs.remove(index);
// we expect not needed backslashes to be removed
for (int i = expectedArgs.size() - 1; i >= 0; i--) {
if (expectedArgs.get(i).equals("\\")) {
expectedArgs.remove(i);
} else {
break;
}
}
checkArgumentsChangesProperly(call, "", index, expectedArgs);
}
@Theory
public void argumentIsRemoved_whenGivenValueIsNullAndArgumentIsLast(final RobotKeywordCall call, final int index) {
final List<String> arguments = call.getArguments();
assumeTrue(arguments.size() > 0);
assumeTrue(index == arguments.size() - 1);
final List<String> expectedArgs = newArrayList(arguments);
expectedArgs.remove(index);
// we expect not needed backslashes to be removed
for (int i = expectedArgs.size() - 1; i >= 0; i--) {
if (expectedArgs.get(i).equals("\\")) {
expectedArgs.remove(i);
} else {
break;
}
}
checkArgumentsChangesProperly(call, null, index, expectedArgs);
}
@Theory
public void argumentIsRemoved_whenGivenValueIsNull(final RobotKeywordCall call, final int index) {
final List<String> arguments = call.getArguments();
assumeTrue(arguments.size() > 0);
assumeTrue(index < arguments.size() - 1);
final List<String> expectedArgs = newArrayList(arguments);
expectedArgs.remove(index);
checkArgumentsChangesProperly(call, null, index, expectedArgs);
}
@Theory
public void nothingChanges_whenTryingToSetEmptyValueOutsideOfArgumentsList(final RobotKeywordCall call,
final int index) {
final List<String> arguments = call.getArguments();
assumeTrue(index >= arguments.size());
checkArgumentsDoesNotChange(call, "", index);
}
@Theory
public void nothingChanges_whenTryingToSetNullValueOutsideOfArgumentsList(final RobotKeywordCall call,
final int index) {
final List<String> arguments = call.getArguments();
assumeTrue(index >= arguments.size());
checkArgumentsDoesNotChange(call, null, index);
}
@Theory
public void argumentsAreAugmentedWithBackslashes_whenTryingToSetNonEmptyValueOutsideOfArgumentsList(
final RobotKeywordCall call, final int index) {
final List<String> arguments = call.getArguments();
assumeTrue(index >= arguments.size());
final List<String> expectedArgs = newArrayList(Collections.nCopies(index + 1, "\\"));
for (int i = 0; i < arguments.size() ; i++) {
expectedArgs.set(i, arguments.get(i));
}
expectedArgs.set(index, "new_arg");
checkArgumentsChangesProperly(call, "new_arg", index, expectedArgs);
}
@Test
public void argumentsAndNameAreAugmentedWithBackslash_whenTryingToSetNonEmptyValueOutsideOfArgumentsList_andNameIsEmpty() {
final RobotKeywordCall call = createEmptyKeywordCall();
final IEventBroker eventBroker = mock(IEventBroker.class);
assertThat(call.getName()).isEqualTo("");
assertThat(call.getArguments()).isEmpty();
assertThat(call.getComment()).isEqualTo("# comment");
final SetKeywordCallArgumentCommand2 command = ContextInjector.prepareContext()
.inWhich(eventBroker)
.isInjectedInto(new SetKeywordCallArgumentCommand2(call, 3, "arg"));
command.execute();
assertThat(call.getName()).isEqualTo("\\");
assertThat(call.getArguments()).containsExactlyElementsOf(newArrayList("\\", "\\", "\\", "arg"));
assertThat(call.getComment()).isEqualTo("# comment");
for (final EditorCommand undo : command.getUndoCommands()) {
undo.execute();
}
assertThat(call.getName()).isEqualTo("");
assertThat(call.getArguments()).isEmpty();
assertThat(call.getComment()).isEqualTo("# comment");
verify(eventBroker, times(2)).send(RobotModelEvents.ROBOT_KEYWORD_CALL_ARGUMENT_CHANGE, call);
verify(eventBroker, times(2)).send(RobotModelEvents.ROBOT_KEYWORD_CALL_NAME_CHANGE, call);
verifyNoMoreInteractions(eventBroker);
}
@Test
public void nothingChanges_whenTryingToSetEmptyValueOutsideOfArgumentsList_andCallHasEmptyName() {
checkArgumentsDoesNotChange(createEmptyKeywordCall(), "", 3);
}
@Test
public void nothingChanges_whenTryingToSetNullValueOutsideOfArgumentsList_andCallHasEmptyName() {
checkArgumentsDoesNotChange(createEmptyKeywordCall(), null, 3);
}
private static void checkArgumentsChangesProperly(final RobotKeywordCall call, final String argToSet,
final int argumentIndex, final List<String> expectedArgs) {
final IEventBroker eventBroker = mock(IEventBroker.class);
checkArgumentChanges(eventBroker, call, argToSet, argumentIndex, expectedArgs);
verify(eventBroker, times(2)).send(RobotModelEvents.ROBOT_KEYWORD_CALL_ARGUMENT_CHANGE, call);
verifyNoMoreInteractions(eventBroker);
}
private static void checkArgumentsDoesNotChange(final RobotKeywordCall call, final String argToSet,
final int argumentIndex) {
final IEventBroker eventBroker = mock(IEventBroker.class);
checkArgumentChanges(eventBroker, call, argToSet, argumentIndex, call.getArguments());
verifyZeroInteractions(eventBroker);
}
private static void checkArgumentChanges(final IEventBroker eventBroker, final RobotKeywordCall call,
final String argToSet, final int argumentIndex, final List<String> expectedArgs) {
final String oldName = call.getName();
final List<String> oldArgs = call.getArguments();
final String oldComment = call.getComment();
final SetKeywordCallArgumentCommand2 command = ContextInjector.prepareContext()
.inWhich(eventBroker)
.isInjectedInto(new SetKeywordCallArgumentCommand2(call, argumentIndex, argToSet));
command.execute();
assertThat(call.getName()).isEqualTo(oldName);
assertThat(call.getArguments()).containsExactlyElementsOf(expectedArgs);
assertThat(call.getComment()).isEqualTo(oldComment);
for (final EditorCommand undo : command.getUndoCommands()) {
undo.execute();
}
assertThat(call.getName()).isEqualTo(oldName);
assertThat(call.getArguments()).containsExactlyElementsOf(oldArgs);
assertThat(call.getComment()).isEqualTo(oldComment);
}
private RobotKeywordCall createEmptyKeywordCall() {
final RobotSuiteFile model = new RobotSuiteFileCreator().appendLine("*** Test Cases ***")
.appendLine("case_0")
.appendLine(" # comment")
.build();
return model.findSection(RobotCasesSection.class).get().getChildren().get(0).getChildren().get(0);
}
private static List<RobotCase> createTestCases() {
final RobotSuiteFile model = new RobotSuiteFileCreator().appendLine("*** Test Cases ***")
.appendLine("case_0")
.appendLine(" [tags] # comment")
.appendLine(" [setup] # comment")
.appendLine(" [teardown] # comment")
.appendLine(" [timeout] # comment")
.appendLine(" [template] # comment")
.appendLine(" [unknown] # comment")
.appendLine(" call # comment")
.appendLine("case_1")
.appendLine(" [tags] arg1 # comment")
.appendLine(" [setup] arg1 # comment")
.appendLine(" [teardown] arg1 # comment")
.appendLine(" [timeout] arg1 # comment")
.appendLine(" [template] arg1 # comment")
.appendLine(" [unknown] arg1 # comment")
.appendLine(" call arg1 # comment")
.appendLine("case_2")
.appendLine(" [tags] arg1 arg2 # comment")
.appendLine(" [setup] arg1 arg2 # comment")
.appendLine(" [teardown] arg1 arg2 # comment")
.appendLine(" [timeout] arg1 arg2 # comment")
.appendLine(" [template] arg1 arg2 # comment")
.appendLine(" [unknown] arg1 arg2 # comment")
.appendLine(" call arg1 arg2 # comment")
.appendLine("case_3")
.appendLine(" [tags] arg1 \\ \\ # comment")
.appendLine(" [setup] arg1 \\ \\ # comment")
.appendLine(" [teardown] arg1 \\ \\ # comment")
.appendLine(" [timeout] arg1 \\ \\ # comment")
.appendLine(" [template] arg1 \\ \\ # comment")
.appendLine(" [unknown] arg1 \\ \\ # comment")
.appendLine(" call arg1 \\ \\ # comment")
.build();
return model.findSection(RobotCasesSection.class).get().getChildren();
}
private static List<RobotKeywordDefinition> createKeywords() {
final RobotSuiteFile model = new RobotSuiteFileCreator().appendLine("*** Keywords ***")
.appendLine("keyword_0")
.appendLine(" [tags] # comment")
.appendLine(" [arguments] # comment")
.appendLine(" [teardown] # comment")
.appendLine(" [timeout] # comment")
.appendLine(" [return] # comment")
.appendLine(" [unknown] # comment")
.appendLine(" call # comment")
.appendLine("keyword_1")
.appendLine(" [tags] arg1 # comment")
.appendLine(" [arguments] arg1 # comment")
.appendLine(" [teardown] arg1 # comment")
.appendLine(" [timeout] arg1 # comment")
.appendLine(" [return] arg1 # comment")
.appendLine(" [unknown] arg1 # comment")
.appendLine(" call arg1 # comment")
.appendLine("keyword_2")
.appendLine(" [tags] arg1 arg2 # comment")
.appendLine(" [arguments] arg1 arg2 # comment")
.appendLine(" [teardown] arg1 arg2 # comment")
.appendLine(" [timeout] arg1 arg2 # comment")
.appendLine(" [return] arg1 arg2 # comment")
.appendLine(" [unknown] arg1 arg2 # comment")
.appendLine(" call arg1 arg2 # comment")
.appendLine("keyword_3")
.appendLine(" [tags] arg1 \\ \\ # comment")
.appendLine(" [arguments] arg1 \\ \\ # comment")
.appendLine(" [teardown] arg1 \\ \\ # comment")
.appendLine(" [timeout] arg1 \\ \\ # comment")
.appendLine(" [return] arg1 \\ \\ # comment")
.appendLine(" [unknown] arg1 \\ \\ # comment")
.appendLine(" call arg1 \\ \\ # comment")
.build();
return model.findSection(RobotKeywordsSection.class).get().getChildren();
}
}