/*******************************************************************************
* Copyright (c) 2013, 2017 Pivotal Software, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* GoPivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.test;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.preference.IPreferenceStore;
import org.junit.Assert;
import org.springframework.ide.eclipse.boot.core.initializr.InitializrServiceSpec;
import org.springframework.ide.eclipse.boot.core.initializr.InitializrServiceSpec.Dependency;
import org.springframework.ide.eclipse.boot.wizard.CheckBoxesSection.CheckBoxModel;
import org.springframework.ide.eclipse.boot.wizard.HierarchicalMultiSelectionFieldModel;
import org.springframework.ide.eclipse.boot.wizard.MultiSelectionFieldModel;
import org.springframework.ide.eclipse.boot.wizard.NewSpringBootWizardModel;
import org.springframework.ide.eclipse.boot.wizard.PopularityTracker;
import org.springframework.ide.eclipse.boot.wizard.RadioGroup;
import org.springframework.ide.eclipse.boot.wizard.RadioGroups;
import org.springframework.ide.eclipse.boot.wizard.RadioInfo;
import org.springframework.ide.eclipse.boot.wizard.content.BuildType;
import org.springframework.ide.eclipse.boot.wizard.importing.ImportStrategy;
import org.springframework.ide.eclipse.core.StringUtils;
import org.springsource.ide.eclipse.commons.frameworks.core.downloadmanager.URLConnectionFactory;
import org.springsource.ide.eclipse.commons.livexp.core.FieldModel;
import org.springsource.ide.eclipse.commons.livexp.core.LiveExpression;
import org.springsource.ide.eclipse.commons.livexp.core.LiveVariable;
import org.springsource.ide.eclipse.commons.livexp.core.ValidationResult;
import org.springsource.ide.eclipse.commons.livexp.util.Filter;
import org.springsource.ide.eclipse.commons.livexp.util.Filters;
import org.springsource.ide.eclipse.commons.tests.util.StsTestUtil;
import junit.framework.TestCase;
/**
* Tests whether NewSpringBootWizardModel adequately parses initializer form data.
*
* @author Kris De Volder
*/
public class NewSpringBootWizardModelTest extends TestCase {
//private static final String INITIALIZR_JSON = "initializr.json";
private static final String INITIALIZR_JSON = "initializr-v2.1.json";
@Override
protected void setUp() throws Exception {
super.setUp();
StsTestUtil.cleanUpProjects();
}
public static NewSpringBootWizardModel parseFrom(String resourcePath, IPreferenceStore store) throws Exception {
URL formUrl = resourceUrl(resourcePath);
return new NewSpringBootWizardModel(new URLConnectionFactory(), formUrl.toString(), store);
}
public static NewSpringBootWizardModel parseFrom(String resourcePath) throws Exception {
return parseFrom(resourcePath, new MockPrefsStore());
}
public static URL resourceUrl(String resourcePath) {
URL formUrl = NewSpringBootWizardModelTest.class.getResource(resourcePath);
return formUrl;
}
public void testParsedRadios() throws Exception {
NewSpringBootWizardModel model = parseFrom(INITIALIZR_JSON);
RadioGroups radioGroups = model.getRadioGroups();
assertGroupNames(radioGroups, "type", "packaging", "javaVersion", "language", "bootVersion");
}
public void testPackagingRadios() throws Exception {
NewSpringBootWizardModel model = parseFrom(INITIALIZR_JSON);
RadioGroup packagingTypes = model.getRadioGroups().getGroup("packaging");
assertNotNull(packagingTypes);
assertGroupValues(packagingTypes, "jar", "war");
assertEquals("jar", packagingTypes.getDefaultValue().getValue());
}
public void testJavaVersionRadios() throws Exception {
NewSpringBootWizardModel model = parseFrom(INITIALIZR_JSON);
RadioGroup group = model.getRadioGroups().getGroup("javaVersion");
assertNotNull(group);
assertGroupValues(group, "1.6", "1.7", "1.8");
assertEquals("1.8", group.getDefaultValue().getValue());
}
public void testBuildTypeRadios() throws Exception {
String jsonFile = INITIALIZR_JSON;
NewSpringBootWizardModel model = parseFrom(jsonFile);
String starterZipUrl = resourceUrl(jsonFile).toURI().resolve("/starter.zip").toString();
assertEquals(starterZipUrl, model.baseUrl.getValue());
RadioGroup group = model.getRadioGroups().getGroup("type");
assertNotNull(group);
assertGroupValues(group, "MAVEN", "GRADLE-STS", "GRADLE-Buildship 1.x", "GRADLE-Buildship 2.x");
assertEquals("MAVEN", group.getDefaultValue().getValue());
group.getSelection().selection.setValue(group.getRadio("MAVEN"));
assertEquals(BuildType.MAVEN, model.getBuildType());
assertEquals(starterZipUrl, model.baseUrl.getValue());
for (ImportStrategy gradleStrategy : BuildType.GRADLE.getImportStrategies()) {
group.getSelection().selection.setValue(group.getRadio(gradleStrategy.getId()));
assertEquals(BuildType.GRADLE, model.getBuildType());
assertEquals(gradleStrategy, model.getImportStrategy());
assertEquals(starterZipUrl, model.baseUrl.getValue());
}
}
public void testBuildTypeRadiosVariant() throws Exception {
//Hypothetical variant where the json "types" lists different actions for maven and gradle zip
String jsonFile = "initializr-variant.json";
String mavenZipUrl = resourceUrl(jsonFile).toURI().resolve("/maven.zip").toString();
String gradleZipUrl = resourceUrl(jsonFile).toURI().resolve("/gradle.zip").toString();
NewSpringBootWizardModel model = parseFrom(jsonFile);
RadioGroup group = model.getRadioGroups().getGroup("type");
assertNotNull(group);
assertGroupValues(group, "MAVEN", "GRADLE-STS", "GRADLE-Buildship 1.x", "GRADLE-Buildship 2.x");
assertEquals("MAVEN", group.getDefaultValue().getValue());
assertEquals(mavenZipUrl, model.baseUrl.getValue());
for (ImportStrategy gradleStrat : BuildType.GRADLE.getImportStrategies()) {
group.getSelection().selection.setValue(group.getRadio(gradleStrat.getId()));
assertEquals(BuildType.GRADLE, model.getBuildType());
assertEquals(gradleStrat, model.getImportStrategy());
assertEquals(gradleZipUrl, model.baseUrl.getValue());
}
group.getSelection().selection.setValue(group.getRadio("MAVEN"));
assertEquals(BuildType.MAVEN, model.getBuildType());
assertEquals(mavenZipUrl, model.baseUrl.getValue());
}
public void testStarters() throws Exception {
NewSpringBootWizardModel model = parseFrom(INITIALIZR_JSON);
Collection<Dependency> styles = getAllChoices(model.dependencies);
assertNotNull(styles);
assertTrue(styles.size()>10);
for (String catName : model.dependencies.getCategories()) {
String lastLabel = null; //check that style labels are sorted within each category
MultiSelectionFieldModel<Dependency> cat = model.dependencies.getContents(catName);
for (Dependency choice : cat.getChoices()) {
String label = cat.getLabel(choice);
if (lastLabel!=null) {
assertTrue("Labels not sorted: '"+lastLabel+"' > '"+label+"'", lastLabel.compareTo(label)<0);
}
lastLabel = label;
assertNotNull("No tooltip for: "+choice+" ["+label+"]", cat.getTooltipHtml(choice).get());
}
}
}
private <T> Collection<T> getAllChoices(
HierarchicalMultiSelectionFieldModel<T> dependencies) {
ArrayList<T> choices = new ArrayList<>();
for (String catName : dependencies.getCategories()) {
MultiSelectionFieldModel<T> cat = dependencies.getContents(catName);
choices.addAll(Arrays.asList(cat.getChoices()));
}
return choices;
}
public void testVersionRangesBuildSnaphotBug() throws Exception {
//See https://www.pivotaltracker.com/story/show/100963226
NewSpringBootWizardModel model = parseFrom(INITIALIZR_JSON);
Dependency devtools = getDependencyById(model, "devtools");
RadioGroup bootVersion = model.getBootVersion();
RadioInfo newer1 = bootVersion.getRadio("1.3.0.M2");
RadioInfo newer2 = bootVersion.getRadio("1.3.0.BUILD-SNAPSHOT");
RadioInfo older = bootVersion.getRadio("1.2.6.BUILD-SNAPSHOT");
LiveExpression<Boolean> devtoolsEnabled = getEnablement(model.dependencies, devtools);
bootVersion.setValue(older);
assertFalse(devtoolsEnabled.getValue());
bootVersion.setValue(newer1);
assertTrue(devtoolsEnabled.getValue());
bootVersion.setValue(newer2);
assertTrue(devtoolsEnabled.getValue());
}
public void testVersionRanges() throws Exception {
NewSpringBootWizardModel model = parseFrom(INITIALIZR_JSON);
Dependency bitronix = getDependencyById(model, "jta-bitronix");
Dependency thymeleaf = getDependencyById(model, "thymeleaf");
assertEquals("1.2.0.M1", bitronix.getVersionRange());
assertFalse(StringUtils.hasText(thymeleaf.getVersionRange()));
RadioGroup bootVersion = model.getBootVersion();
assertNotNull(bootVersion);
assertGroupValues(bootVersion,
"1.3.0.M2",
"1.3.0.BUILD-SNAPSHOT",
"1.2.6.BUILD-SNAPSHOT",
"1.2.5.RELEASE",
"1.1.12.RELEASE"
);
RadioInfo older = bootVersion.getRadio("1.1.12.RELEASE");
RadioInfo newer = bootVersion.getRadio("1.2.5.RELEASE");
LiveExpression<Boolean> bitronixEnabled = getEnablement(model.dependencies, bitronix);
LiveExpression<Boolean> thymeleafEnabled = getEnablement(model.dependencies, thymeleaf);
bootVersion.setValue(older);
assertFalse(bitronixEnabled.getValue());
assertTrue(thymeleafEnabled.getValue());
bootVersion.setValue(newer);
assertTrue(bitronixEnabled.getValue());
assertTrue(thymeleafEnabled.getValue());
bootVersion.setValue(older);
Set<Dependency> selectedDepedencies = getSelecteds(model.dependencies);
assertTrue(selectedDepedencies.isEmpty());
select(model.dependencies, bitronix);
select(model.dependencies, thymeleaf);
selectedDepedencies = getSelecteds(model.dependencies);
assertEquals(2, selectedDepedencies.size());
String url = model.downloadUrl.getValue();
assertContains("thymeleaf", url);
assertFalse(url.contains("bitronix"));
}
public void testPopularityTracking() throws Exception {
IPreferenceStore store = new MockPrefsStore();
NewSpringBootWizardModel model = parseFrom(INITIALIZR_JSON, store);
assertTrue(model.getMostPopular(10).isEmpty());
Dependency web = getDependencyById(model, "web");
Dependency actuator = getDependencyById(model, "actuator");
Dependency thymeleaf = getDependencyById(model, "thymeleaf");
select(model.dependencies, web);
select(model.dependencies, thymeleaf);
select(model.dependencies, actuator);
model.updateUsageCounts();
PopularityTracker tracker = new PopularityTracker(store);
assertEquals(1, tracker.getUsageCount(web));
assertEquals(1, tracker.getUsageCount(thymeleaf));
assertEquals(1, tracker.getUsageCount(actuator));
model.updateUsageCounts();
assertEquals(2, tracker.getUsageCount(web));
assertEquals(2, tracker.getUsageCount(thymeleaf));
assertEquals(2, tracker.getUsageCount(actuator));
unselect(model.dependencies, actuator);
model.updateUsageCounts();
unselect(model.dependencies, thymeleaf);
model.updateUsageCounts();
assertEquals(4, tracker.getUsageCount(web));
assertEquals(3, tracker.getUsageCount(thymeleaf));
assertEquals(2, tracker.getUsageCount(actuator));
assertCheckboxes(model.getMostPopular(10),
web, thymeleaf, actuator);
/////////////////////////////////////////////////////////////////////////////
// check that model counts are limitted according to 'howMany' argument
assertCheckboxes(model.getMostPopular(3),
web, thymeleaf, actuator);
assertCheckboxes(model.getMostPopular(2),
web, thymeleaf);
assertCheckboxes(model.getMostPopular(1),
web);
assertCheckboxes(model.getMostPopular(0)
/*nothing*/);
}
public void testPopularCheckboxSharesSelectionState() throws Exception {
IPreferenceStore store = new MockPrefsStore();
NewSpringBootWizardModel model = parseFrom(INITIALIZR_JSON, store);
assertTrue(model.getMostPopular(10).isEmpty());
Dependency web = getDependencyById(model, "web");
PopularityTracker tracker = new PopularityTracker(store);
tracker.incrementUsageCount(web);
String webCat = getCategory(model.dependencies, web);
MultiSelectionFieldModel<Dependency> webGroup = model.dependencies.getContents(webCat);
List<CheckBoxModel<Dependency>> allWebBoxes = webGroup.getCheckBoxModels();
CheckBoxModel<Dependency> normalBox = getCheckboxById(allWebBoxes, web.getId());
CheckBoxModel<Dependency> popularBox = getCheckboxById(model.getMostPopular(10), web.getId());
assertFalse(normalBox.getSelection().getValue());
assertFalse(popularBox.getSelection().getValue());
normalBox.getSelection().setValue(true);
assertTrue(normalBox.getSelection().getValue());
assertTrue(popularBox.getSelection().getValue());
popularBox.getSelection().setValue(false);
assertFalse(normalBox.getSelection().getValue());
assertFalse(popularBox.getSelection().getValue());
}
public void testDefaultDependencies() throws Exception {
IPreferenceStore store = new MockPrefsStore();
NewSpringBootWizardModel model = parseFrom(INITIALIZR_JSON, store);
assertTrue(model.getDefaultDependencies().isEmpty());
select(model.dependencies, getDependencyById(model, "web"));
select(model.dependencies, getDependencyById(model, "actuator"));
select(model.dependencies, getDependencyById(model, "thymeleaf"));
assertTrue(model.saveDefaultDependencies());
// Initialize new model and check if default dependencies are selected
model = parseFrom(INITIALIZR_JSON, store);
assertEquals(3, model.getDefaultDependencies().size());
Set<String> selectedIds = model.dependencies.getCurrentSelection().stream().map(Dependency::getId).collect(Collectors.toSet());
Set<String> defaultIds = model.getDefaultDependencies().stream().map(checkboxModel -> {
return checkboxModel.getValue().getId();
}).collect(Collectors.toSet());
assertEquals(defaultIds, selectedIds);
}
public void testUnselectAll() throws Exception {
IPreferenceStore store = new MockPrefsStore();
NewSpringBootWizardModel model = parseFrom(INITIALIZR_JSON, store);
assertTrue(model.getDefaultDependencies().isEmpty());
select(model.dependencies, getDependencyById(model, "web"));
select(model.dependencies, getDependencyById(model, "actuator"));
select(model.dependencies, getDependencyById(model, "thymeleaf"));
assertEquals(3, model.dependencies.getCurrentSelection().size());
model.dependencies.clearSelection();
assertTrue(model.dependencies.getCurrentSelection().isEmpty());
}
public void testDependencySearchBox() throws Exception {
// The trickies bit of implementing the search box is, unfortunately, making the
// SWT gui widgetry apply the filter and hide / show corresponding ui elements.
// This unfortunately not tested here. This test only verifies the filter's
// matching logic.
NewSpringBootWizardModel model = parseFrom(INITIALIZR_JSON);
LiveVariable<String> searchBox = model.getDependencyFilterBoxText();
LiveExpression<Filter<Dependency>> filter = model.getDependencyFilter();
assertEquals("", searchBox.getValue());
assertEquals(Filters.acceptAll(),filter.getValue());
assertFilterAccepts(model, true, "web", "web", "Web", "Full stack yada yada");
assertFilterAccepts(model, true, "WeB", "web", "Web", "Full stack yada yada");
assertFilterAccepts(model, false, "ZZZZZZZZZZ", "web", "Web", "Full stack yada yada");
assertFilterAccepts(model, true, "foo", "something", "label FoO label", "desc");
assertFilterAccepts(model, true, "foo", "something", "label", "desc FOO desc");
assertFilterAccepts(model, false, "foo", "foo", "label", "desc");
}
public void testValidDefaultProjectName() throws Exception {
IProject p1 = ResourcesPlugin.getWorkspace().getRoot().getProject("demo");
if (!p1.exists()) {
p1.create(new NullProgressMonitor());
}
IProject p2 = ResourcesPlugin.getWorkspace().getRoot().getProject("demo-1");
if (!p2.exists()) {
p2.create(new NullProgressMonitor());
}
NewSpringBootWizardModel model = parseFrom(INITIALIZR_JSON);
assertEquals("demo-2", model.getProjectName().getValue());
assertEquals("demo-2", model.getArtifactId().getValue());
assertEquals(ValidationResult.OK, model.getProjectName().getValidator().getValue());
}
public void testArtifactIdSyncWithProjectName() throws Exception {
NewSpringBootWizardModel model = parseFrom(INITIALIZR_JSON);
assertEquals("demo", model.getProjectName().getValue());
assertEquals("demo", model.getArtifactId().getValue());
model.getProjectName().setValue("demo-1");
assertEquals("demo-1", model.getProjectName().getValue());
assertEquals("demo-1", model.getArtifactId().getValue());
model.getArtifactId().setValue("demo-project");
assertEquals("demo-1", model.getProjectName().getValue());
assertEquals("demo-project", model.getArtifactId().getValue());
model.getProjectName().setValue("demo-2");
assertEquals("demo-2", model.getProjectName().getValue());
assertEquals("demo-project", model.getArtifactId().getValue());
model.getArtifactId().setValue("demo-2");
assertEquals("demo-2", model.getProjectName().getValue());
assertEquals("demo-2", model.getArtifactId().getValue());
model.getProjectName().setValue("demo-3");
assertEquals("demo-3", model.getProjectName().getValue());
assertEquals("demo-3", model.getArtifactId().getValue());
}
public void testRestoreFromOldBuildtypePreference() throws Exception {
//We here test a weak requirement that the wizard model 'handles' it okay when
// the preference saved in the workspace is from before the buildship refactoring.
//The requirements are:
// - it doesn't crash
// - it just chooses the maven build type / strategy by default. We do not
// attempt to map the old type-ids to the new ones.
MockPrefsStore prefs = new MockPrefsStore();
prefs.putValue("org.springframework.ide.eclipse.wizard.gettingstarted.boot.PreferredSelections.type", "gradle-project");
NewSpringBootWizardModel wizard = parseFrom(INITIALIZR_JSON, prefs);
assertEquals(BuildType.MAVEN, wizard.getBuildType());
assertEquals(BuildType.MAVEN.getDefaultStrategy(), wizard.getImportStrategy());
}
private CheckBoxModel<Dependency> getCheckboxById(NewSpringBootWizardModel model, String id) {
CheckBoxModel<Dependency> found = null;
for (String cat : model.dependencies.getCategories()) {
for (CheckBoxModel<Dependency> cb : model.dependencies.getContents(cat).getCheckBoxModels()) {
if (cb.getValue().getId().equals(id)) {
Assert.assertNull(found);
found = cb;
}
}
}
return found;
}
private void assertFilterAccepts(NewSpringBootWizardModel model, boolean expect, String pattern,
String id, String label, String desc) {
LiveVariable<String> searchBox = model.getDependencyFilterBoxText();
searchBox.setValue(pattern);
Filter<Dependency> filter = model.getDependencyFilter().getValue();
Dependency dep = new Dependency();
dep.setId(id);
dep.setName(label);
dep.setDescription(desc);
assertEquals(expect, filter.accept(dep));
}
private CheckBoxModel<Dependency> getCheckboxById(List<CheckBoxModel<Dependency>> list, String id) {
for (CheckBoxModel<Dependency> cb : list) {
if (id.equals(cb.getValue().getId())) {
return cb;
}
}
return null;
}
private void assertCheckboxes(List<CheckBoxModel<Dependency>> actuals, Dependency... expecteds) {
StringBuilder expectedIds = new StringBuilder();
for (Dependency e : expecteds) {
expectedIds.append(e.getId()+"\n");
}
StringBuilder actualIds = new StringBuilder();
for (CheckBoxModel<Dependency> cb : actuals) {
actualIds.append(cb.getValue().getId()+"\n");
}
assertEquals(expectedIds.toString(), actualIds.toString());
}
private void unselect(HierarchicalMultiSelectionFieldModel<Dependency> dependencies,
Dependency dep) {
String cat = getCategory(dependencies, dep);
MultiSelectionFieldModel<Dependency> selecteds = dependencies.getContents(cat);
selecteds.unselect(dep);
}
private void select(HierarchicalMultiSelectionFieldModel<Dependency> dependencies,
Dependency dep) {
String cat = getCategory(dependencies, dep);
MultiSelectionFieldModel<Dependency> selecteds = dependencies.getContents(cat);
selecteds.select(dep);
}
private Set<Dependency> getSelecteds(HierarchicalMultiSelectionFieldModel<Dependency> dependencies) {
HashSet<Dependency> selecteds = new HashSet<>();
for (String catName : dependencies.getCategories()) {
MultiSelectionFieldModel<Dependency> cat = dependencies.getContents(catName);
selecteds.addAll(cat.getCurrentSelection());
}
return selecteds;
}
private LiveExpression<Boolean> getEnablement(HierarchicalMultiSelectionFieldModel<Dependency> dependencies, Dependency dep) {
String cat = getCategory(dependencies, dep);
return dependencies.getContents(cat).getEnablement(dep);
}
private String getCategory( HierarchicalMultiSelectionFieldModel<Dependency> dependencies, Dependency dep) {
for (String cat : dependencies.getCategories()) {
if (contains(dependencies.getContents(cat).getChoices(), dep)) {
return cat;
}
}
throw new Error("Shouldn't get here");
}
private boolean contains(Dependency[] deps, Dependency find) {
for (Dependency dep : deps) {
if (find.equals(dep)) {
return true;
}
}
return false;
}
public void assertContains(String needle, String haystack) {
if (haystack==null || !haystack.contains(needle)) {
fail("Not found: "+needle+"\n in \n"+haystack);
}
}
private Dependency getDependencyById(NewSpringBootWizardModel model, String depId) {
for (Dependency dep : getAllChoices(model.dependencies)) {
if (dep.getId().equals(depId)) {
return dep;
}
}
return null;
}
public void testLabels() throws Exception {
NewSpringBootWizardModel model = parseFrom(INITIALIZR_JSON);
Iterator<FieldModel<String>> stringInputs = model.stringInputs.iterator();
while (stringInputs.hasNext()) {
FieldModel<String> input = stringInputs.next();
assertRealLabel(input.getLabel());
}
for (RadioGroup group : model.getRadioGroups().getGroups()) {
String label = group.getLabel();
assertRealLabel(label);
for (RadioInfo radio : group.getRadios()) {
label = radio.getLabel();
assertRealLabel(label);
}
}
}
public void testPrintLabels() throws Exception {
//print all radios in groups with lable for quick visual inspection.
NewSpringBootWizardModel model = parseFrom(INITIALIZR_JSON);
for (RadioGroup group : model.getRadioGroups().getGroups()) {
String label = group.getLabel();
System.out.println(group + " -> "+label);
for (RadioInfo radio : group.getRadios()) {
label = radio.getLabel();
System.out.println(" " + radio + " -> "+label);
}
}
}
/**
* Basic test of the 'spec parser'. Just check that it accepts a well-formed
* json spec document and doesn't crash on it.
*/
public void testInitializrSpecParser() throws Exception {
doParseTest(INITIALIZR_JSON);
}
private void doParseTest(String resource) throws IOException, Exception {
URL url = NewSpringBootWizardModelTest.class.getResource(resource);
URLConnection conn = new URLConnectionFactory().createConnection(url);
conn.connect();
InputStream input = conn.getInputStream();
try {
InitializrServiceSpec spec = InitializrServiceSpec.parseFrom(input);
assertNotNull(spec);
} finally {
input.close();
}
}
/**
* Test that radio params are wired up in the model so that selecting them changes the downloadUrl.
*/
public void testRadioQueryParams() throws Exception {
NewSpringBootWizardModel model = parseFrom(INITIALIZR_JSON);
RadioGroup packaging = model.getRadioGroups().getGroup("packaging");
LiveVariable<RadioInfo> selection = packaging.getSelection().selection;
assertEquals("jar", selection.getValue().getValue());
String urlParam = getUrlParam(model.downloadUrl.getValue(), "packaging");
assertEquals("jar", urlParam);
selection.setValue(packaging.getRadio("war"));
urlParam = getUrlParam(model.downloadUrl.getValue(), "packaging");
assertEquals("war", urlParam);
}
/**
* Test that radio params for 'type' properly use the typenames from start.spring.io spec
* and not the ids used internally to distinguish between grade+buildship versus gradle+sts
*/
public void testTypeRadioQueryParams() throws Exception {
NewSpringBootWizardModel model = parseFrom(INITIALIZR_JSON);
RadioGroup type = model.getRadioGroups().getGroup("type");
LiveVariable<RadioInfo> selection = type.getSelection().selection;
assertEquals("MAVEN", selection.getValue().getValue());
String urlParam = getUrlParam(model.downloadUrl.getValue(), "type");
assertEquals("maven-project", urlParam);
selection.setValue(type.getRadio("GRADLE-STS"));
urlParam = getUrlParam(model.downloadUrl.getValue(), "type");
assertEquals("gradle-project", urlParam);
selection.setValue(type.getRadio("GRADLE-Buildship 1.x"));
urlParam = getUrlParam(model.downloadUrl.getValue(), "type");
assertEquals("gradle-project", urlParam);
selection.setValue(type.getRadio("GRADLE-Buildship 2.x"));
urlParam = getUrlParam(model.downloadUrl.getValue(), "type");
assertEquals("gradle-project", urlParam);
}
public static Map<String, List<String>> getQueryParams(String url) throws Exception {
Map<String, List<String>> params = new HashMap<>();
String[] urlParts = url.split("\\?");
if (urlParts.length > 1) {
String query = urlParts[1];
for (String param : query.split("&")) {
String[] pair = param.split("=");
String key = URLDecoder.decode(pair[0], "UTF-8");
String value = "";
if (pair.length > 1) {
value = URLDecoder.decode(pair[1], "UTF-8");
}
List<String> values = params.get(key);
if (values == null) {
values = new ArrayList<>();
params.put(key, values);
}
values.add(value);
}
}
return params;
}
private String getUrlParam(String url, String name) throws Exception {
Map<String, List<String>> params = getQueryParams(url);
List<String> values = params.get(name);
if (values!=null && !values.isEmpty()) {
assertEquals(1, values.size());
return values.get(0);
}
return null;
}
private void assertRealLabel(String label) {
assertNotNull("Label is null", label); //have a label
assertFalse("Label is empty", "".equals(label.trim())); //label not empty
if (Character.isDigit(label.charAt(0))) {
//labels like '1.6.' are okay too.
return;
}
assertTrue("Label doesn't start with uppercase: '"+label+"'", Character.isUpperCase(label.charAt(0))); //'real' label, not just the default taken from the name.
}
private void assertGroupValues(RadioGroup group, String... expecteds) {
Set<String> expectedSet = new HashSet<>(Arrays.asList(expecteds));
RadioInfo[] radios = group.getRadios();
for (int i = 0; i < radios.length; i++) {
String actual = radios[i].getValue();
if (!expectedSet.contains(actual)) {
fail("Unexpected: "+actual);
}
expectedSet.remove(actual);
}
if (!expectedSet.isEmpty()) {
StringBuilder notFound = new StringBuilder();
for (String missing : expectedSet) {
notFound.append(" "+missing);
}
fail("Missing: "+notFound);
}
}
private void assertGroupNames(RadioGroups radioGroups, String... expectNames) {
List<RadioGroup> groups = radioGroups.getGroups();
assertEquals(expectNames.length, groups.size());
for (int i = 0; i < expectNames.length; i++) {
assertEquals(expectNames[i], groups.get(i).getName());
}
}
public void testTemplateVariableSubstitution() throws Exception {
Map<String, String> values = new HashMap<>();
values.put("bootVersion", "2.0.0");
values.put("stars", "5");
String actual = InitializrServiceSpec.substituteTemplateVariables("Here is Spring Boot {bootVersion} version. It's rated with {stars} stars.", values);
assertEquals("Here is Spring Boot 2.0.0 version. It's rated with 5 stars.", actual);
actual = InitializrServiceSpec.substituteTemplateVariables("Here is Spring Boot {bootVersion} version.", values);
assertEquals("Here is Spring Boot 2.0.0 version.", actual);
try {
InitializrServiceSpec.substituteTemplateVariables("Here is Spring Boot {bootVersion} version. It's really {awesome} stuff!", values);
fail("Should have failed the template string variable substitution! Unknown variable expected!");
} catch (CoreException e) {
// ignore - let the test pass
}
}
}