/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, version 2 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program 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 General Public License for more details.
*
*
* Copyright 2006 - 2016 Pentaho Corporation. All rights reserved.
*/
package org.pentaho.aggdes.ui;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.List;
import org.jmock.Expectations;
import org.jmock.integration.junit4.JMock;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.junit.Before;
import org.junit.Test;
import org.junit.internal.runners.InitializationError;
import org.junit.runner.RunWith;
import org.pentaho.aggdes.ui.ext.impl.MondrianFileSchemaProvider;
import org.pentaho.aggdes.ui.form.controller.ConnectionController;
import org.pentaho.aggdes.ui.form.model.ConnectionModel;
import org.pentaho.aggdes.ui.xulstubs.XulSupressingBindingFactoryProxy;
import org.pentaho.di.core.KettleClientEnvironment;
import org.pentaho.ui.xul.XulComponent;
import org.pentaho.ui.xul.XulDomContainer;
import org.pentaho.ui.xul.binding.Binding;
import org.pentaho.ui.xul.binding.BindingFactory;
import org.pentaho.ui.xul.dom.Document;
import org.pentaho.ui.xul.impl.XulEventHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/applicationContext.xml", "/plugins.xml", "/ConnectionControllerITest.xml"})
/**
* Put tests in here that require some orchestration that is achieve in an isolated unit test
* on the model(s) or controller(s). Testing bindings is a good example.
*/
public class ConnectionControllerITest extends JMock {
public ConnectionControllerITest() throws InitializationError {
super(ConnectionControllerITest.class);
try {
KettleClientEnvironment.init();
} catch (Exception e) {
e.printStackTrace();
}
}
private ConnectionController controller;
private JUnit4Mockery context;
private Document doc;
private XulDomContainer container;
private ConnectionModel model;
private List<MondrianFileSchemaProvider> mondrianFileSchemaProviders;
private BindingFactory bindingFactory;
private EventRecorder eventRecorder; //for verifying property change events
@Autowired
public void setController(ConnectionController controller) {
this.controller = controller;
}
@Autowired
public void setModel(ConnectionModel model) {
this.model = model;
}
@Autowired
public void setSchemaProviderExtensions(List<MondrianFileSchemaProvider> mondrianFileSchemaProviders) {
this.mondrianFileSchemaProviders = mondrianFileSchemaProviders;
}
@Autowired
public void setBindingFactory(BindingFactory bindingFactory) {
this.bindingFactory = bindingFactory;
}
@Before
public void setUp() throws Exception {
/*
* In this integration test, we want to mock only the XUL framework, all other components
* we want to be the "real" ones. This will allow us to test application behavior without
* dependency on a UI.
*/
context = new JUnit4Mockery();
eventRecorder = new EventRecorder();
doc = context.mock(Document.class);
container = context.mock(XulDomContainer.class);
// need some expectations here as setXulDomContainer calls getDocumentRoot on the container
context.checking(new Expectations() {
{
allowing(container).getDocumentRoot();
will(returnValue(doc));
allowing(container).addEventHandler(with(any(XulEventHandler.class)));
allowing(doc).addOverlay(with(any(String.class)));
ignoring(container);
allowing(doc).getElementById(with(aNonNull(String.class)));
will(returnValue(context.mock(XulComponent.class, Long.toString(System.currentTimeMillis()))));
allowing(doc).addInitializedBinding(with(any(Binding.class)));
allowing(doc).invokeLater(with(any(Runnable.class))); //don't care if the controller uses invokeLater or not, this is UI stuff
}
});
controller.setXulDomContainer(container);
//In order to really make this an integration test, there needs to be a BindingFactory that is injected into the controller
//so we can mock or stub it out and allow the object->object bindings to actually be bound while the xulcomponent bindings
//are consumed. Here we are proxying the BindingFactory to achieve this.
bindingFactory.setDocument(doc);
//setup the proxy binding factory that will ignore all XUL stuff
XulSupressingBindingFactoryProxy proxy = new XulSupressingBindingFactoryProxy();
proxy.setProxiedBindingFactory(bindingFactory);
controller.setBindingFactory(proxy);
for(MondrianFileSchemaProvider provider : mondrianFileSchemaProviders) {
provider.setXulDomContainer(container);
provider.setBindingFactory(proxy);
}
// this model gets reused across tests. Revert to default value.
model.setApplySchemaSourceEnabled( false );
}
@Test
public void testApplyEnablementForMondrianFileSchemaProvider() throws Exception {
final String PROPNAME = "applySchemaSourceEnabled";
//setup all the bindings
controller.onLoad();
eventRecorder.record(model);
//by default apply should be disabled
assertFalse(model.isApplySchemaSourceEnabled());
//text input should enable apply
mondrianFileSchemaProviders.get(0).setSelected(true);
mondrianFileSchemaProviders.get(0).setMondrianSchemaFilename("text here should enable apply button");
assertTrue(model.isApplySchemaSourceEnabled());
assertEquals(Boolean.TRUE, eventRecorder.getLastValue(PROPNAME));
// clearing the text should disable it again
mondrianFileSchemaProviders.get(0).setMondrianSchemaFilename("");
assertFalse(model.isApplySchemaSourceEnabled());
assertEquals(Boolean.FALSE, eventRecorder.getLastValue(PROPNAME));
}
@Test
public void testApplyEnablementOnProviderSelection() throws Exception {
final String PROPNAME = "applySchemaSourceEnabled";
MondrianFileSchemaProvider prvdr1 = mondrianFileSchemaProviders.get(0);
MondrianFileSchemaProvider prvdr2 = mondrianFileSchemaProviders.get(1);
//setup all the bindings
controller.onLoad();
eventRecorder.record(model);
//select 1st provider and enter data
prvdr1.setMondrianSchemaFilename("abc");
prvdr1.setSelected(true);
assertTrue(model.isApplySchemaSourceEnabled());
assertEquals(Boolean.TRUE, eventRecorder.getLastValue(PROPNAME));
//select 2nd provider
eventRecorder.reset();
prvdr1.setSelected(false);
prvdr2.setSelected(true);
assertFalse(model.isApplySchemaSourceEnabled());
assertEquals(Boolean.FALSE, eventRecorder.getLastValue(PROPNAME));
//reselect 1st provider
eventRecorder.reset();
prvdr2.setSelected(false);
prvdr1.setSelected(true);
assertTrue(model.isApplySchemaSourceEnabled());
assertEquals(Boolean.TRUE, eventRecorder.getLastValue(PROPNAME));
}
// @Test
//This test was never fully implemented.. it's a half-baked approach to testing like a user would
// public void testFormEnablementForEditModeWhenAnAggIsDefined() throws Exception {
// //setup all the bindings
// controller.onLoad();
//
// eventRecorder.record(model);
//
// //
// //Connect to a cube:
// //
//
// //setup db connection
// DatabaseMeta dbMeta = new DatabaseMeta();
// dbMeta.setName("testDB");
// model.setDatabaseMeta(dbMeta);
//
// //select 1st provider and enter schema filename
// MondrianFileSchemaProvider prvdr1 = mondrianFileSchemaProviders.get(0);
// prvdr1.setMondrianSchemaFilename("test schema filename");
// prvdr1.setSelected(true);
// SchemaProviderUiExtension ext = prvdr1;
//
// controller.setSchemaProviders(Arrays.asList(ext));
//
// //apply the schema
// //do what apply() does without all the XUL code
// model.setCubeNames(prvdr1.getCubeNames());
// model.setSelectedSchemaModel(prvdr1.getSchemaModel());
//
// //select first cube
// model.setCubeName(model.getCubeNames().get(0));
//
// //connect
// controller.connect();
// }
}