/*
* Copyright 2017 ThoughtWorks, Inc.
*
* 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
*
* http://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 com.thoughtworks.go.plugins.presentation;
import com.google.gson.Gson;
import com.thoughtworks.go.config.pluggabletask.PluggableTask;
import com.thoughtworks.go.domain.config.Configuration;
import com.thoughtworks.go.domain.config.ConfigurationProperty;
import com.thoughtworks.go.domain.config.PluginConfiguration;
import com.thoughtworks.go.presentation.MissingPluggableTaskViewModel;
import com.thoughtworks.go.plugin.access.pluggabletask.PluggableTaskConfigStore;
import com.thoughtworks.go.plugin.access.pluggabletask.TaskPreference;
import com.thoughtworks.go.plugin.api.task.TaskView;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.Map;
import java.util.Set;
import static com.thoughtworks.go.domain.packagerepository.ConfigurationPropertyMother.create;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class PluggableTaskViewModelFactoryTest {
private TaskPreference taskPreference;
@Before
public void setUp() throws Exception {
cleanupTaskPreferences();
taskPreference = mock(TaskPreference.class);
PluggableTaskConfigStore.store().setPreferenceFor("plugin-1", taskPreference);
TaskView view = mock(TaskView.class);
when(taskPreference.getView()).thenReturn(view);
when(view.template()).thenReturn("<input type='text' ng-model='abc'></input>");
when(view.displayValue()).thenReturn("First plugin");
}
@After
public void tearDown() throws Exception {
cleanupTaskPreferences();
}
@Test
public void typeForDisplayAndTemplateOfViewModelShouldBeGotFromThePlugin() throws Exception {
PluggableTask pluggableTask = new PluggableTask(new PluginConfiguration("plugin-1", "2"), new Configuration());
PluggableTaskViewModelFactory factory = new PluggableTaskViewModelFactory();
PluggableViewModel<PluggableTask> viewModel = factory.viewModelFor(pluggableTask, "new");
assertThat(viewModel.getTypeForDisplay(), is("First plugin"));
assertThat(viewModel.getParameters().get("template"), is("<input type='text' ng-model='abc'></input>"));
}
@Test
public void templateShouldBeLoadedFromClasspathWithClasspathPrefix() throws Exception {
PluggableViewModel<PluggableTask> viewModel = getModelWithTaskTemplateAt("/com/thoughtworks/go/plugins/presentation/test-template.html");
assertThat(viewModel.getParameters().get("template"), is("<html>my-template</html>"));
}
@Test
public void shouldReturnErrorMessageIfTemplateIsMissingFromPlugin() {
PluggableViewModel<PluggableTask> viewModel = getModelWithTaskTemplateAt("/test-template-missing.html");
assertThat(viewModel.getParameters().get("template"), is("Template \"/test-template-missing.html\" is missing."));
}
@Test
public void shouldProvideATemplateWithAnErrorMessageWhenTemplateProvidedIsNull() throws Exception {
PluggableViewModel<PluggableTask> viewModel = getModelWithTaskTemplateHavingValue(null);
assertThat(viewModel.getParameters().get("template"), is("View template provided by plugin is null."));
}
@Test
public void shouldProvideNoTemplateWhenTemplateProvidedIsEmpty() throws Exception {
PluggableViewModel<PluggableTask> viewModel = getModelWithTaskTemplateHavingValue("");
assertThat(viewModel.getParameters().get("template"), is(""));
}
@Test
public void dataForViewShouldBeGotFromTheTaskInJSONFormat() throws Exception {
Configuration configuration = new Configuration(create("key1", false, "value1"), create("KEY2", false, "value2"));
PluggableTask taskConfig = new PluggableTask(new PluginConfiguration("plugin-1", "2"), configuration);
PluggableTaskViewModelFactory factory = new PluggableTaskViewModelFactory();
PluggableViewModel<PluggableTask> viewModel = factory.viewModelFor(taskConfig, "new");
String actualData = (String) viewModel.getParameters().get("data");
Gson gson = new Gson();
Map actual = gson.fromJson(actualData, Map.class);
Map expected = gson.fromJson("{\"KEY2\":{\"value\":\"value2\"},\"key1\":{\"value\":\"value1\"}}", Map.class);
assertEquals(expected, actual);
}
@Test
public void dataForViewShouldIncludeErrorsIfAny() throws Exception {
ConfigurationProperty property1 = create("key1", false, "value1");
property1.addError("key1", "error msg");
ConfigurationProperty property2 = create("KEY2", false, "value2");
Configuration configuration = new Configuration(property1, property2);
PluggableTask taskConfig = new PluggableTask(new PluginConfiguration("plugin-1", "2"), configuration);
PluggableTaskViewModelFactory factory = new PluggableTaskViewModelFactory();
PluggableViewModel<PluggableTask> viewModel = factory.viewModelFor(taskConfig, "new");
String actualData = (String) viewModel.getParameters().get("data");
Gson gson = new Gson();
Map actual = gson.fromJson(actualData, Map.class);
Map expected = gson.fromJson("{\"KEY2\":{\"value\": \"value2\"},\"key1\":{\"value\" : \"value1\", \"errors\" : \"error msg\"}}", Map.class);
assertEquals(expected, actual);
}
@Test
public void shouldGivePluggableViewModelWithAllTheViewInformationForActionNew() throws Exception {
assertPluggableViewModel("new", "admin/tasks/pluggable_task/new");
}
@Test
public void shouldGivePluggableViewModelWithAllTheViewInformationForActionEdit() throws Exception {
assertPluggableViewModel("edit", "admin/tasks/pluggable_task/edit");
}
@Test
public void shouldGivePluggableViewModelWithAllTheViewInformationForActionListEntry() throws Exception {
assertPluggableViewModel("list-entry", "admin/tasks/pluggable_task/_list_entry.html");
}
@Test
public void shouldReturnMissingPluginTaskViewIfPluginIsMissing() {
String pluginId = "pluginId";
PluggableTaskViewModelFactory factory = new PluggableTaskViewModelFactory();
PluggableViewModel<PluggableTask> viewModel = factory.viewModelFor(new PluggableTask(new PluginConfiguration(pluginId, "1"), new Configuration()), "edit");
assertThat(viewModel.getParameters().get("template"), is(String.format("Associated plugin '%s' not found. Please contact the Go admin to install the plugin.", pluginId)));
assertThat(viewModel.getTypeForDisplay(), is(pluginId));
assertThat(viewModel instanceof MissingPluggableTaskViewModel, is(true));
}
private void assertPluggableViewModel(String actionName, String expectedTemplatePath) {
PluggableTask pluggableTask = new PluggableTask(new PluginConfiguration("plugin-1", "2"), new Configuration());
PluggableTaskViewModelFactory factory = new PluggableTaskViewModelFactory();
PluggableViewModel<PluggableTask> viewModel = factory.viewModelFor(pluggableTask, actionName);
assertThat(viewModel.getModel(), is(pluggableTask));
assertThat(viewModel.getTaskType(), is("pluggable_task_plugin_1"));
assertThat(viewModel.getTemplatePath(), is(expectedTemplatePath));
}
private void cleanupTaskPreferences() {
Set<String> plugins = PluggableTaskConfigStore.store().pluginIds();
for (String pluginId : plugins) {
PluggableTaskConfigStore.store().removePreferenceFor(pluginId);
}
}
private PluggableViewModel<PluggableTask> getModelWithTaskTemplateAt(final String filePath) {
return getModelWithTaskTemplateHavingValue(String.format("classpath:%s", filePath));
}
private PluggableViewModel<PluggableTask> getModelWithTaskTemplateHavingValue(final String templateContentValue) {
when(taskPreference.getView()).thenReturn(new TaskView() {
@Override
public String displayValue() {
return "view";
}
@Override
public String template() {
return templateContentValue;
}
});
PluggableTask pluggableTask = new PluggableTask(new PluginConfiguration("plugin-1", "2"), new Configuration());
PluggableTaskViewModelFactory factory = new PluggableTaskViewModelFactory();
return factory.viewModelFor(pluggableTask, "new");
}
}