/**
* Licensed to the Austrian Association for Software Tool Integration (AASTI)
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. The AASTI licenses this file to you 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 org.openengsb.ui.admin.wiringPage;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.hasEntry;
import static org.hamcrest.Matchers.hasItemInArray;
import static org.hamcrest.Matchers.hasKey;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyMap;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.swing.tree.TreeModel;
import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
import org.apache.wicket.extensions.markup.html.tree.LinkTree;
import org.apache.wicket.feedback.FeedbackMessage;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.util.tester.FormTester;
import org.hamcrest.Description;
import org.hamcrest.Factory;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Before;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.openengsb.core.api.Connector;
import org.openengsb.core.api.ConnectorInstanceFactory;
import org.openengsb.core.api.Constants;
import org.openengsb.core.api.Domain;
import org.openengsb.core.api.context.ContextCurrentService;
import org.openengsb.core.api.model.ConnectorDescription;
import org.openengsb.ui.admin.AbstractUITest;
import org.openengsb.ui.admin.wiringPage.WiringPage.CheckedTree;
import org.ops4j.pax.wicket.test.spring.PaxWicketSpringBeanComponentInjector;
public class WiringPageTest extends AbstractUITest {
public interface TestDomainInterface extends Connector {
}
public interface AnotherTestDomainInterface extends Connector {
}
private String testdomainConnectorId;
private final String globTest = "globTest";
private final String anotherGlob = "anotherGlob";
private Map<String, Object> startproperties;
private FormTester formTester;
@Before
public void setUp() throws Exception {
Map<String, String> globals = new TreeMap<String, String>();
globals.put(globTest, TestDomainInterface.class.getCanonicalName());
globals.put(anotherGlob, AnotherTestDomainInterface.class.getCanonicalName());
when(ruleManager.listGlobals()).thenReturn(globals);
when(ruleManager.getGlobalType(globTest)).thenReturn(globals.get(globTest));
when(ruleManager.getGlobalType(anotherGlob)).thenReturn(globals.get(anotherGlob));
List<String> contextList = new ArrayList<String>();
contextList.add("bar");
contextList.add("one");
contextList.add("two");
contextList.add("twotimes1");
contextList.add("twotimes2");
contextList.add("foo");
ContextCurrentService contextService =
(ContextCurrentService) context.getBean("contextCurrentService");
when(contextService.getAvailableContexts()).thenReturn(contextList);
createConnectors();
tester.getApplication().getComponentInstantiationListeners()
.add(new PaxWicketSpringBeanComponentInjector(tester.getApplication(), context));
tester.startPage(WiringPage.class);
formTester = tester.newFormTester("wiringForm");
}
@Test
public void testWiringPage_shouldBeRendered() throws Exception {
tester.assertRenderedPage(WiringPage.class);
tester.assertComponent("domainChooseForm", Form.class);
tester.assertComponent("domainChooseForm:domains", DropDownChoice.class);
tester.assertInvisible("globals");
tester.assertInvisible("endpoints");
tester.assertComponent("wiringForm", Form.class);
tester.assertComponent("wiringForm:globalName", TextField.class);
tester.assertComponent("wiringForm:wireButton", AjaxSubmitLink.class);
tester.assertComponent("wiringForm:instanceId", TextField.class);
tester.assertComponent("feedbackPanel", FeedbackPanel.class);
tester.assertComponent("wiringForm:contextList", CheckedTree.class);
}
@Test
public void testDomainList_shouldBeLoaded() throws Exception {
@SuppressWarnings("unchecked")
DropDownChoice<Class<? extends Domain>> domains = (DropDownChoice<Class<? extends Domain>>)
tester.getComponentFromLastRenderedPage("domainChooseForm:domains");
assertThat(domains.getChoices().size(), is(2));
assertThat(domains.getChoices().get(0), IsAssignableFrom.isAssignableFrom(AnotherTestDomainInterface.class));
assertThat(domains.getChoices().get(1), IsAssignableFrom.isAssignableFrom(TestDomainInterface.class));
}
@Test
public void testContextList_shouldBeLoaded() throws Exception {
CheckedTree globals = (CheckedTree) tester.getComponentFromLastRenderedPage("wiringForm:contextList");
TreeModel tree = globals.getModelObject();
assertThat(tree.getChildCount(tree.getRoot()), is(6));
assertThat(tree.getChild(tree.getRoot(), 0).toString(), is("bar"));
}
@Test
public void testSelectDomain_shouldUpdateGlobals() throws Exception {
selectDomain(1); // TestDomainInterface
LinkTree globals = (LinkTree) tester.getComponentFromLastRenderedPage("globals");
TreeModel tree = globals.getModelObject();
assertThat(tree.getChildCount(tree.getRoot()), is(1));
assertThat(tree.getChild(tree.getRoot(), 0).toString(), is(globTest));
}
@Test
public void testSelectDomain_shouldUpdateEndpoints() throws Exception {
selectDomain(1); // TestDomainInterface
LinkTree endpoints = (LinkTree) tester.getComponentFromLastRenderedPage("endpoints");
TreeModel tree = endpoints.getModelObject();
assertThat(tree.getChildCount(tree.getRoot()), is(1));
assertThat(tree.getChild(tree.getRoot(), 0).toString(), is(testdomainConnectorId));
}
@Test
public void testSelectGlobal_shouldUpdateTextField() throws Exception {
selectDomain(1);
selectFirstGlobal();
TextField<?> txtGlobalName = (TextField<?>) tester.getComponentFromLastRenderedPage("wiringForm:globalName");
assertThat(txtGlobalName.getDefaultModelObjectAsString(), is(globTest));
}
@Test
public void testSelectRootOfGlobals_shouldNotUpdateTextField() throws Exception {
selectDomain(1);
tester.clickLink("globals:i:0:nodeComponent:contentLink");
TextField<?> txtGlobalName = (TextField<?>) tester.getComponentFromLastRenderedPage("wiringForm:globalName");
assertThat(txtGlobalName.getDefaultModelObjectAsString().isEmpty(), is(true));
}
@Test
public void testSelectEndpoint_shouldUpdateLabel() throws Exception {
selectDomain(1);
selectFirstEndpoint();
TextField<?> txtServiceId = (TextField<?>) tester.getComponentFromLastRenderedPage("wiringForm:instanceId");
assertThat(txtServiceId.getDefaultModelObjectAsString(), is(testdomainConnectorId));
}
@Test
public void testNewLocation_shouldUpdateServiceProperties() throws Exception {
selectDomain(1); // TestDomainInterface
selectFirstEndpoint();
selectContext(1); // bar
setGlobal(globTest);
tester.clickLink("wiringForm:wireButton");
tester.assertNoErrorMessage();
ConnectorDescription description = serviceManager.getAttributeValues(testdomainConnectorId);
assertThat(description.getProperties(), hasEntry("location.bar", (Object) globTest));
}
@Test
public void testUpdateExistingLocation_shouldUpdateServiceProperties() throws Exception {
selectDomain(1); // TestDomainInterface
selectFirstEndpoint();
setGlobal(globTest);
selectContext(2); // one
tester.clickLink("wiringForm:wireButton");
tester.assertNoErrorMessage();
ConnectorDescription description = serviceManager.getAttributeValues(testdomainConnectorId);
Map<String, Object> props = description.getProperties();
assertThat(props, hasKey("location.one"));
Object[] array = (Object[]) props.get("location.one");
assertThat(array.length, is(2));
assertThat(array, hasItemInArray((Object) globTest));
}
@Test
public void testUpdateExistingLocationArray_shouldUpdateServiceProperties() throws Exception {
selectDomain(1); // TestDomainInterface
selectFirstEndpoint();
setGlobal(globTest);
selectContext(3); // two
tester.clickLink("wiringForm:wireButton");
tester.assertNoErrorMessage();
ConnectorDescription description = serviceManager.getAttributeValues(testdomainConnectorId);
Map<String, Object> props = description.getProperties();
assertThat(props, hasKey("location.two"));
Object[] array = (Object[]) props.get("location.two");
assertThat(array.length, is(3));
assertThat(array, hasItemInArray((Object) globTest));
}
@Test
public void testWiringGlobalTwoTimesAtOneContext_shouldNotUpdateServiceProperties() throws Exception {
selectDomain(1); // TestDomainInterface
selectFirstEndpoint();
setGlobal(globTest);
selectContext(4); // twotimes1
tester.clickLink("wiringForm:wireButton");
tester.assertNoErrorMessage();
ConnectorDescription description = serviceManager.getAttributeValues(testdomainConnectorId);
assertThat(description.getProperties().get("location.twotimes1"),
is(startproperties.get("location.twotimes1")));
}
@Test
public void testWiringGlobalTwoTimesAtOneContextArray_shouldNotUpdateServiceProperties() throws Exception {
selectDomain(1); // TestDomainInterface
selectFirstEndpoint();
setGlobal(globTest);
selectContext(5); // twotimes2
tester.clickLink("wiringForm:wireButton");
tester.assertNoErrorMessage();
ConnectorDescription description = serviceManager.getAttributeValues(testdomainConnectorId);
assertThat(description.getProperties().get("location.twotimes2"),
is(startproperties.get("location.twotimes2")));
}
@Test
public void testNewGlobal_shouldUpdateServiceProperties() throws Exception {
selectDomain(1); // TestDomainInterface
selectFirstEndpoint();
setGlobal("newGlob");
selectContext(1); // bar
tester.clickLink("wiringForm:wireButton");
tester.assertNoErrorMessage();
verify(ruleManager).addGlobal(TestDomainInterface.class.getCanonicalName(), "newGlob");
ConnectorDescription description = serviceManager.getAttributeValues(testdomainConnectorId);
assertThat(description.getProperties(), hasEntry("location.bar", (Object) "newGlob"));
}
@Test
public void testWiringExistingGlobalWithAnotherType_shouldNotUpdateServiceProperties() throws Exception {
selectDomain(1); // TestDomainInterface
selectFirstEndpoint();
setGlobal(anotherGlob);
selectContext(2); // one
tester.clickLink("wiringForm:wireButton");
tester.assertNoErrorMessage();
ConnectorDescription description = serviceManager.getAttributeValues(testdomainConnectorId);
assertThat(description.getProperties().get("location.one"), is(startproperties.get("location.one")));
}
@Test
public void testWiringInMultipleContexts_shouldUpdateServiceProperties() throws Exception {
selectDomain(1); // TestDomainInterface
selectFirstEndpoint();
setGlobal(globTest);
selectContext(1); // bar
selectContext(6); // foo
tester.clickLink("wiringForm:wireButton");
tester.assertNoErrorMessage();
ConnectorDescription description = serviceManager.getAttributeValues(testdomainConnectorId);
assertThat(description.getProperties(), hasEntry("location.bar", (Object) globTest));
assertThat(description.getProperties(), hasEntry("location.foo", (Object) globTest));
}
@Test
public void testPressWireButtonWithoutSettedGlobal_shouldShowError() throws Exception {
selectDomain(1); // TestDomainInterface
selectFirstEndpoint();
selectContext(1); // bar
tester.clickLink("wiringForm:wireButton");
assertThat(tester.getMessages(FeedbackMessage.ERROR).size(), is(1));
}
@Test
public void testPressWireButtonWithoutSettedEndpoint_shouldShowError() throws Exception {
selectDomain(1); // TestDomainInterface
setGlobal(globTest);
selectContext(1); // bar
tester.clickLink("wiringForm:wireButton");
assertThat(tester.getMessages(FeedbackMessage.ERROR).size(), is(1));
}
@Test
public void testPressWireButtonWithoutSettedContext_shouldShowError() throws Exception {
selectDomain(1); // TestDomainInterface
selectFirstEndpoint();
setGlobal(globTest);
tester.clickLink("wiringForm:wireButton");
assertThat(tester.getMessages(FeedbackMessage.ERROR).size(), is(1));
}
@Test
public void testWiringWithDeletedConnector_shouldShowError() throws Exception {
selectDomain(1); // TestDomainInterface
selectFirstEndpoint();
setGlobal(globTest);
selectContext(1); // bar
serviceManager.delete(testdomainConnectorId);
tester.clickLink("wiringForm:wireButton");
assertThat(tester.getMessages(FeedbackMessage.ERROR).size(), is(1));
}
private void selectDomain(int index) {
FormTester formTester = tester.newFormTester("domainChooseForm");
formTester.select("domains", index);
tester.executeAjaxEvent("domainChooseForm:domains", "onchange");
}
private void setGlobal(String global) {
formTester.setValue("globalName", global);
}
private void selectFirstGlobal() {
tester.clickLink("globals:i:1:nodeComponent:contentLink");
}
private void selectFirstEndpoint() {
tester.clickLink("endpoints:i:1:nodeComponent:contentLink");
}
private void selectContext(int i) {
formTester.setValue("contextList:i:" + i + ":nodeComponent:check", true);
}
private void createConnectors() throws Exception {
createProviderMocks();
Map<String, String> attributes = new HashMap<String, String>();
attributes.put("value", "42");
Map<String, Object> properties = new Hashtable<String, Object>();
properties.put("location.root", "domain/testdomain/default");
properties.put("location.one", "bar");
properties.put("location.two", new Object[]{ "foo", "bar" });
properties.put("location.twotimes1", globTest);
properties.put("location.twotimes2", new Object[]{ "foo", globTest });
startproperties = new HashMap<String, Object>(properties);
testdomainConnectorId =
serviceManager.create(new ConnectorDescription("testdomain", "testconnector", attributes, properties));
}
private void createProviderMocks() {
createDomainProviderMock(TestDomainInterface.class, "testdomain");
createDomainProviderMock(AnotherTestDomainInterface.class, "anotherTestDomain");
createConnectorProviderMock("testconnector", "testdomain");
ConnectorInstanceFactory factory = mock(ConnectorInstanceFactory.class);
when(factory.createNewInstance(anyString())).thenAnswer(new Answer<Connector>() {
@Override
public Connector answer(InvocationOnMock invocation) throws Throwable {
TestDomainInterface newMock = mock(TestDomainInterface.class);
when(newMock.getInstanceId()).thenReturn((String) invocation.getArguments()[0]);
return newMock;
}
});
when(factory.applyAttributes(any(Connector.class), anyMap())).thenAnswer(new Answer<Connector>() {
@Override
public Connector answer(InvocationOnMock invocation) throws Throwable {
return (Connector) invocation.getArguments()[0];
}
});
Dictionary<String, Object> props = new Hashtable<String, Object>();
props.put(Constants.DOMAIN_KEY, "testdomain");
props.put(Constants.CONNECTOR_KEY, "testconnector");
registerService(factory, props, ConnectorInstanceFactory.class);
}
private static class IsAssignableFrom extends TypeSafeMatcher<Class<?>> {
private final Class<?> clazz;
public IsAssignableFrom(Class<?> clazz) {
this.clazz = clazz;
}
@Override
public boolean matchesSafely(Class<?> toMatch) {
return clazz.isAssignableFrom(toMatch);
}
@Override
public void describeTo(Description description) {
description.appendText("a class assignable from ").appendText(clazz.getCanonicalName());
}
@Factory
public static <T> Matcher<Class<?>> isAssignableFrom(Class<?> clazz) {
return new IsAssignableFrom(clazz);
}
}
}