/******************************************************************************* * Copyright (c) 2007, 2014 compeople AG and others. * 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: * compeople AG - initial API and implementation *******************************************************************************/ package org.eclipse.riena.internal.ui.ridgets.swt; import java.beans.PropertyChangeEvent; import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.browser.BrowserFunction; import org.eclipse.swt.browser.LocationListener; import org.eclipse.swt.browser.ProgressListener; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.riena.beans.common.StringBean; import org.eclipse.riena.core.test.collect.UITestCase; import org.eclipse.riena.core.util.ReflectionUtils; import org.eclipse.riena.internal.ui.swt.test.UITestHelper; import org.eclipse.riena.ui.ridgets.IBrowserRidget; import org.eclipse.riena.ui.ridgets.IBrowserRidget.IBrowserRidgetFunction; import org.eclipse.riena.ui.ridgets.listener.ILocationListener; import org.eclipse.riena.ui.ridgets.listener.IProgressListener; import org.eclipse.riena.ui.ridgets.listener.LocationEvent; import org.eclipse.riena.ui.ridgets.listener.ProgressEvent; import org.eclipse.riena.ui.ridgets.swt.uibinding.SwtControlRidgetMapper; /** * Tests for {@link BrowserRidget} */ @UITestCase public class BrowserRidgetTest extends AbstractSWTRidgetTest { @Override protected Browser createWidget(final Composite parent) { return new Browser(parent, SWT.NONE); } @Override protected IBrowserRidget createRidget() { return new BrowserRidget(); } @Override protected Browser getWidget() { return (Browser) super.getWidget(); } @Override protected IBrowserRidget getRidget() { return (IBrowserRidget) super.getRidget(); } public void testRidgetMapping() { final SwtControlRidgetMapper mapper = SwtControlRidgetMapper.getInstance(); assertSame(BrowserRidget.class, mapper.getRidgetClass(getWidget())); } @Override public void testSetFocusable() { // skipping super.testSetFocusable() because of Bug 84532 ok(); } @Override public void testRequestFocus() { // skipping testRequestFocus() because of Bug 84532 ok(); } public void testMapScriptFunctionRidget() { final IBrowserRidget r = new BrowserRidget(); final Map<String, BrowserFunction> functions = ReflectionUtils.getHidden(r, "browserFunctions"); //$NON-NLS-1$ assertNull(r.getUIControl()); assertTrue(functions.isEmpty()); final String functionName = "f1"; //$NON-NLS-1$ r.mapScriptFunction(functionName, new IBrowserRidgetFunction() { public Object execute(final Object[] jsParams) { return null; } }); assertTrue(functions.isEmpty()); // bind r.setUIControl(new Browser(getShell(), SWT.NONE)); assertEquals(1, functions.size()); assertEquals(functionName, functions.get(functionName).getName()); // unbind r.setUIControl(null); assertTrue(functions.isEmpty()); // bind again, function should be created again r.setUIControl(new Browser(getShell(), SWT.NONE)); assertEquals(1, functions.size()); assertEquals(functionName, functions.get(functionName).getName()); // unmap function while ridget is bound to the ui control r.unmapScriptFunction(functionName); assertTrue(functions.isEmpty()); // map function while ridget is bound to the ui control r.mapScriptFunction(functionName, new IBrowserRidgetFunction() { public Object execute(final Object[] jsParams) { return null; } }); assertEquals(1, functions.size()); assertEquals(functionName, functions.get(functionName).getName()); } public void testBindToModel() { final IBrowserRidget ridget = getRidget(); final String url1 = "http://www.redview.org"; final String url2 = "http://www.eclipse.org"; final StringBean bean = new StringBean(url1); ridget.bindToModel(bean, StringBean.PROP_VALUE); assertNull(ridget.getUrl()); ridget.updateFromModel(); assertEquals(url1, bean.getValue()); assertEquals(url1, ridget.getUrl()); bean.setValue(url2); assertEquals(url2, bean.getValue()); assertEquals(url1, ridget.getUrl()); ridget.updateFromModel(); assertEquals(url2, bean.getValue()); assertEquals(url2, ridget.getUrl()); ridget.setUrl(url1); assertEquals(url1, bean.getValue()); assertEquals(url1, ridget.getUrl()); } // TODO enable when switched to the latest SWT version public void atestSetText() { final IBrowserRidget ridget = getRidget(); final String text = "<html><body><h1>Riena</h1></body></html>"; ridget.setText(text); assertEquals(text, ridget.getText()); ridget.setText(""); assertEquals("", ridget.getText()); ridget.setText(null); assertEquals(null, ridget.getText()); } // Bug 433526 causes this test to fail public void ignoredTestSetTextClearsUrl() { final IBrowserRidget ridget = getRidget(); final String text = "<html><body><p>riena</p></body></html>"; ridget.setUrl("http://eclipse.org"); ridget.setText(text); assertEquals(null, ridget.getUrl()); assertEquals(text, ridget.getText()); } public void testSetTextOnOutputOnly() { final IBrowserRidget ridget = getRidget(); final Browser control = getWidget(); assertNull(ridget.getText()); // allow ridget.setText() on output only ridget.setOutputOnly(true); final String text = "<hmtl><body><h2>Riena</h2></body></html>"; ridget.setText(text); UITestHelper.readAndDispatch(control); assertEquals(text, ridget.getText()); // browser may add line breaks - just check if 'Riena' is in the output assertTrue("control.text:" + control.getText(), control.getText().contains("Riena")); } public void testSetUrl() { final IBrowserRidget ridget = getRidget(); ridget.setUrl("http://www.redview.org"); assertEquals("http://www.redview.org", ridget.getUrl()); // control.getUrl() is not reliable because of timing + network acccess // so I'm not testing that... ridget.setUrl("b o g u s"); assertEquals("b o g u s", ridget.getUrl()); ridget.setUrl(""); assertEquals("", ridget.getUrl()); ridget.setUrl(null); assertEquals(null, ridget.getUrl()); ridget.setUrl("about:blank"); assertEquals("about:blank", ridget.getUrl()); } public void testSetUrlClearsText() { final IBrowserRidget ridget = getRidget(); ridget.setText("riena"); ridget.setUrl("http://eclipse.org"); assertEquals("http://eclipse.org", ridget.getUrl()); assertEquals(null, ridget.getText()); } public void testSetUrlOnOutputOnly() { final IBrowserRidget ridget = getRidget(); assertNull(ridget.getUrl()); // allow ridget.setUrl() on output only ridget.setOutputOnly(true); ridget.setUrl("http://www.redview.org"); // ridget.addPropertyChangeListener(new PropertyChangeListener() { // public void propertyChange(PropertyChangeEvent evt) { // System.out.println(evt.getPropertyName() + " " + evt.getNewValue()); // } // }); assertEquals("http://www.redview.org", ridget.getUrl()); // disallow widget.setUrl() on output only - can't test this because // widget.getUrl() is not reliable because of timing + network access } // Bug 433526 causes this test to fail public void ignoredTestSettersFireUrlEvents() { final IBrowserRidget ridget = getRidget(); final String newValue = "http://www.redview.org"; final String oldValue = ridget.getUrl(); assertFalse(newValue.equals(ridget.getUrl())); expectPropertyChangeEvents(new PropertyChangeEvent(ridget, "urlInternal", oldValue, newValue), new PropertyChangeEvent(ridget, IBrowserRidget.PROPERTY_URL, oldValue, newValue)); ridget.setUrl(newValue); verifyPropertyChangeEvents(); expectNoPropertyChangeEvent(); ridget.setUrl(newValue); verifyPropertyChangeEvents(); expectPropertyChangeEvents(new PropertyChangeEvent(ridget, "urlInternal", newValue, null), new PropertyChangeEvent(ridget, IBrowserRidget.PROPERTY_URL, newValue, null)); ridget.setText("<html><body><h1>h1</h1></body></html>"); verifyPropertyChangeEvents(); expectNoPropertyChangeEvent(); ridget.setText("<html><body><h1>h1</h1></body></html>"); verifyPropertyChangeEvents(); } public void testApplyTextOnRebind() throws Exception { final IBrowserRidget ridget = getRidget(); final Browser control1 = getWidget(); final String text = "<html><body><h1>Riena</h1></body></html>"; ridget.setText(text); UITestHelper.readAndDispatch(control1); retry(new Runnable() { public void run() { // browser may add line breaks - just check if 'Riena' is in the output assertTrue("control1.text:" + control1.getText(), control1.getText().contains("Riena")); } }, control1, 3); final Browser control2 = createWidget(getShell()); ridget.setUIControl(control2); UITestHelper.readAndDispatch(control2); retry(new Runnable() { public void run() { assertTrue("control2.text:" + control2.getText(), control2.getText().contains("Riena")); } }, control2, 3); } /** * As per Bug 338602 */ public void testAddLocationListener() { final IBrowserRidget ridget = getRidget(); final Browser control = getWidget(); final LocationListener intLocLi = ReflectionUtils.getHidden(ridget, "internalLocationListener"); intLocLi.changing(createLocationEvent(control, "")); final FTLocationChangingListener changingListener = new FTLocationChangingListener(); ridget.addLocationListener(changingListener); ridget.addLocationListener(changingListener); final FTLocationChangedListener changedListener = new FTLocationChangedListener(); ridget.addLocationListener(changedListener); ridget.addLocationListener(changedListener); intLocLi.changing(createLocationEvent(control, "http://www.eclipse.org")); assertEquals(1, changingListener.getCount()); assertEquals("http://www.eclipse.org", changingListener.getLocation()); assertEquals(0, changedListener.getCount()); intLocLi.changed(createLocationEvent(control, "http://www.eclipse.org")); assertEquals(1, changingListener.getCount()); assertEquals(1, changedListener.getCount()); assertEquals("http://www.eclipse.org", changedListener.getLocation()); ridget.removeLocationListener(changingListener); intLocLi.changing(createLocationEvent(control, "http://www.eclipse.org/riena")); assertEquals(1, changingListener.getCount()); assertEquals(1, changedListener.getCount()); ridget.removeLocationListener(changedListener); intLocLi.changed(createLocationEvent(control, "http://www.eclipse.org/riena")); assertEquals(1, changingListener.getCount()); assertEquals(1, changedListener.getCount()); } /** * As per Bug 338602 */ // Bug 433526 causes this test to fail public void ignoredTestSettersDoNotNotifyLocationListeners() { final IBrowserRidget ridget = getRidget(); final Browser control = getWidget(); final LocationListener intLocLi = ReflectionUtils.getHidden(ridget, "internalLocationListener"); intLocLi.changing(createLocationEvent(control, "")); final FTLocationChangingListener listener = new FTLocationChangingListener(); ridget.addLocationListener(listener); assertEquals(0, listener.getCount()); ridget.setUrl("http://www.eclipse.org"); assertEquals(0, listener.getCount()); ridget.setText("<html><body><h1>Hello</h1></body></html>"); assertEquals(0, listener.getCount()); } /** * As per Bug 338602 */ public void testBlockFromLocationListener() { final IBrowserRidget ridget = getRidget(); final Browser control = getWidget(); final LocationListener intLocLi = ReflectionUtils.getHidden(ridget, "internalLocationListener"); intLocLi.changing(createLocationEvent(control, "")); final FTLocationChangingListener blockListener = new FTLocationChangingListener() { @Override public boolean locationChanging(final LocationEvent event) { super.locationChanging(event); return false; } }; ridget.addLocationListener(blockListener); final FTLocationChangingListener listener = new FTLocationChangingListener(); ridget.addLocationListener(listener); org.eclipse.swt.browser.LocationEvent event = createLocationEvent(control, "http://www.eclipse.org"); intLocLi.changing(event); assertEquals(1, blockListener.getCount()); assertEquals(1, listener.getCount()); assertFalse(listener.isAllowed()); assertFalse(event.doit); ridget.removeLocationListener(blockListener); event = createLocationEvent(control, "http://www.eclipse.org"); intLocLi.changing(event); assertEquals(1, blockListener.getCount()); assertEquals(2, listener.getCount()); assertTrue(listener.isAllowed()); assertTrue(event.doit); } public void testBlockWhenOutputOnly() { final IBrowserRidget ridget = getRidget(); final Browser control = getWidget(); final LocationListener intLocLi = ReflectionUtils.getHidden(ridget, "internalLocationListener"); intLocLi.changing(createLocationEvent(control, "")); final FTLocationChangingListener listener = new FTLocationChangingListener(); ridget.addLocationListener(listener); ridget.setOutputOnly(true); org.eclipse.swt.browser.LocationEvent event = createLocationEvent(control, "http://www.eclipse.org"); intLocLi.changing(event); assertFalse(event.doit); assertEquals(0, listener.getCount()); ridget.setOutputOnly(false); event = createLocationEvent(control, "http://www.eclipse.org"); intLocLi.changing(event); assertTrue(event.doit); assertEquals(1, listener.getCount()); } public void testAddProgressListener() { final IBrowserRidget ridget = getRidget(); final Browser control = getWidget(); final ProgressListener intProLi = ReflectionUtils.getHidden(ridget, "internalProgressListener"); intProLi.changed(createProgressEvent(control, 0, 100)); intProLi.completed(createProgressEvent(control, 100, 100)); final FTProgressChangeListener changingListener = new FTProgressChangeListener(); ridget.addProgressListener(changingListener); ridget.addProgressListener(changingListener); intProLi.changed(createProgressEvent(control, 0, 100)); intProLi.completed(createProgressEvent(control, 100, 100)); assertEquals(1, changingListener.getCountChanged()); assertEquals(1, changingListener.getCountCompleted()); final FTProgressChangeListener changedListener = new FTProgressChangeListener(); ridget.addProgressListener(changedListener); ridget.addProgressListener(changedListener); intProLi.changed(createProgressEvent(control, 0, 100)); assertEquals(2, changingListener.getCountChanged()); assertEquals(1, changingListener.getCountCompleted()); assertEquals(1, changedListener.getCountChanged()); assertEquals(0, changedListener.getCountCompleted()); intProLi.completed(createProgressEvent(control, 100, 100)); assertEquals(2, changingListener.getCountChanged()); assertEquals(2, changingListener.getCountCompleted()); assertEquals(1, changedListener.getCountChanged()); assertEquals(1, changedListener.getCountCompleted()); ridget.removeProgressListener(changingListener); intProLi.changed(createProgressEvent(control, 0, 100)); assertEquals(2, changingListener.getCountChanged()); assertEquals(2, changedListener.getCountChanged()); ridget.removeProgressListener(changedListener); intProLi.changed(createProgressEvent(control, 0, 100)); assertEquals(2, changingListener.getCountChanged()); assertEquals(2, changedListener.getCountChanged()); } // helping methods ////////////////// private org.eclipse.swt.browser.LocationEvent createLocationEvent(final Browser control, final String location) { final org.eclipse.swt.browser.LocationEvent event = new org.eclipse.swt.browser.LocationEvent(control); event.location = location; event.top = true; event.doit = true; return event; } private org.eclipse.swt.browser.ProgressEvent createProgressEvent(final Browser control, final int current, final int total) { final org.eclipse.swt.browser.ProgressEvent event = new org.eclipse.swt.browser.ProgressEvent(control); event.current = current; event.total = total; return event; } /** * Execute the 'closure' op up to {@code tries}-times and process the ui queue between tries. */ private void retry(final Runnable op, final Control withControl, int tries) throws Exception { while (tries > 0) { try { op.run(); tries = 0; } catch (final Exception exc) { tries--; if (tries > 0) { Thread.sleep(500); UITestHelper.readAndDispatch(withControl); } else { throw exc; } } catch (final Error error) { tries--; if (tries > 0) { Thread.sleep(500); UITestHelper.readAndDispatch(withControl); } else { throw error; } } } } // helping classes ////////////////// private static class FTLocationChangingListener implements ILocationListener { private int countChanging; private LocationEvent event; public boolean isAllowed() { return event.isAllowed(); } public int getCount() { return countChanging; } public String getLocation() { return event.getLocation(); } public boolean locationChanging(final LocationEvent event) { countChanging++; this.event = event; return true; } public void locationChanged(final LocationEvent event) { // unused } } private static class FTLocationChangedListener implements ILocationListener { private int countChanged; private LocationEvent event; public int getCount() { return countChanged; } public String getLocation() { return event.getLocation(); } public boolean locationChanging(final LocationEvent event) { // unused return true; } public void locationChanged(final LocationEvent event) { countChanged++; this.event = event; } } private static class FTProgressChangeListener implements IProgressListener { private int countChanged = 0; private int countCompleted = 0; public int getCountChanged() { return countChanged; } public int getCountCompleted() { return countCompleted; } @Override public void progressChanged(final ProgressEvent event) { countChanged++; } @Override public void progressCompleted(final ProgressEvent event) { countCompleted++; } } }