--- /dev/null
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * 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.vaadin.client.connectors;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.core.client.JsArrayString;
+import com.google.gwt.dom.client.NativeEvent;
+import com.vaadin.client.JavaScriptConnectorHelper;
+import com.vaadin.client.Util;
+import com.vaadin.client.communication.HasJavaScriptConnectorHelper;
+import com.vaadin.client.connectors.grid.AbstractGridRendererConnector;
+import com.vaadin.client.connectors.grid.GridConnector;
+import com.vaadin.client.renderers.ComplexRenderer;
+import com.vaadin.client.renderers.Renderer;
+import com.vaadin.client.widget.grid.CellReference;
+import com.vaadin.client.widget.grid.RendererCellReference;
+import com.vaadin.shared.JavaScriptExtensionState;
+import com.vaadin.shared.ui.Connect;
+
+import elemental.json.JsonObject;
+import elemental.json.JsonValue;
+
+/**
+ * Connector for server-side renderer implemented using JavaScript.
+ *
+ * @since 7.4
+ * @author Vaadin Ltd
+ */
+// This is really typed to <JsonValue>, but because of the way native strings
+// are not always instanceof JsonValue, we need to accept Object
+@Connect(com.vaadin.ui.renderers.AbstractJavaScriptRenderer.class)
+public class JavaScriptRendererConnector
+ extends AbstractGridRendererConnector<Object>
+ implements HasJavaScriptConnectorHelper {
+ private final JavaScriptConnectorHelper helper = new JavaScriptConnectorHelper(
+ this);
+
+ private final JavaScriptObject cellReferenceWrapper = createCellReferenceWrapper();
+
+ @Override
+ protected void init() {
+ super.init();
+ helper.init();
+
+ addGetRowKey(helper.getConnectorWrapper());
+ }
+
+ private static native JavaScriptObject createCellReferenceWrapper()
+ /*-{
+ var reference = {};
+
+ var setProperty = function(name, getter, setter) {
+ var descriptor = {
+ get: getter
+ }
+ if (setter) {
+ descriptor.set = setter;
+ }
+ Object.defineProperty(reference, name, descriptor);
+ };
+
+ setProperty("element", function() {
+ return reference.target.@CellReference::getElement()();
+ }, null);
+
+ setProperty("rowIndex", function() {
+ return reference.target.@CellReference::getRowIndex()();
+ }, null);
+
+ setProperty("columnIndex", function() {
+ return reference.target.@CellReference::getColumnIndex()();
+ }, null);
+
+ setProperty("colSpan", function() {
+ return reference.target.@RendererCellReference::getColSpan()();
+ }, function(colSpan) {
+ reference.target.@RendererCellReference::setColSpan(*)(colSpan);
+ });
+
+ return reference;
+ }-*/;
+
+ @Override
+ public JavaScriptExtensionState getState() {
+ return (JavaScriptExtensionState) super.getState();
+ }
+
+ private native void addGetRowKey(JavaScriptObject wrapper)
+ /*-{
+ var self = this;
+ wrapper.getRowKey = $entry(function(rowIndex) {
+ return @JavaScriptRendererConnector::findRowKey(*)(self, rowIndex);
+ });
+ }-*/;
+
+ private static String findRowKey(JavaScriptRendererConnector connector,
+ int rowIndex) {
+ GridConnector gc = connector.getGridConnector();
+ JsonObject row = gc.getWidget().getDataSource().getRow(rowIndex);
+ return connector.getRowKey(row);
+ }
+
+ private boolean hasFunction(String name) {
+ return hasFunction(helper.getConnectorWrapper(), name);
+ }
+
+ private static native boolean hasFunction(JavaScriptObject wrapper,
+ String name)
+ /*-{
+ return typeof wrapper[name] === 'function';
+ }-*/;
+
+ @Override
+ protected Renderer<Object> createRenderer() {
+ helper.ensureJavascriptInited();
+
+ if (!hasFunction("render")) {
+ throw new RuntimeException(
+ "JavaScriptRenderer " + helper.getInitFunctionName()
+ + " must have a function named 'render'");
+ }
+
+ final boolean hasInit = hasFunction("init");
+ final boolean hasDestroy = hasFunction("destroy");
+ final boolean hasOnActivate = hasFunction("onActivate");
+ final boolean hasGetConsumedEvents = hasFunction("getConsumedEvents");
+ final boolean hasOnBrowserEvent = hasFunction("onBrowserEvent");
+
+ return new ComplexRenderer<Object>() {
+ @Override
+ public void render(RendererCellReference cell, Object data) {
+ if (data instanceof JsonValue) {
+ data = Util.json2jso((JsonValue) data);
+ }
+ render(helper.getConnectorWrapper(), getJsCell(cell), data);
+ }
+
+ private JavaScriptObject getJsCell(CellReference<?> cell) {
+ updateCellReference(cellReferenceWrapper, cell);
+ return cellReferenceWrapper;
+ }
+
+ public native void render(JavaScriptObject wrapper,
+ JavaScriptObject cell, Object data)
+ /*-{
+ wrapper.render(cell, data);
+ }-*/;
+
+ @Override
+ public void init(RendererCellReference cell) {
+ if (hasInit) {
+ init(helper.getConnectorWrapper(), getJsCell(cell));
+ }
+ }
+
+ private native void init(JavaScriptObject wrapper,
+ JavaScriptObject cell)
+ /*-{
+ wrapper.init(cell);
+ }-*/;
+
+ private native void updateCellReference(
+ JavaScriptObject cellWrapper, CellReference<?> target)
+ /*-{
+ cellWrapper.target = target;
+ }-*/;
+
+ @Override
+ public void destroy(RendererCellReference cell) {
+ if (hasDestroy) {
+ destory(helper.getConnectorWrapper(), getJsCell(cell));
+ } else {
+ super.destroy(cell);
+ }
+ }
+
+ private native void destory(JavaScriptObject wrapper,
+ JavaScriptObject cell)
+ /*-{
+ wrapper.destory(cell);
+ }-*/;
+
+ @Override
+ public boolean onActivate(CellReference<?> cell) {
+ if (hasOnActivate) {
+ return onActivate(helper.getConnectorWrapper(),
+ getJsCell(cell));
+ } else {
+ return super.onActivate(cell);
+ }
+ }
+
+ private native boolean onActivate(JavaScriptObject wrapper,
+ JavaScriptObject cell)
+ /*-{
+ return !!wrapper.onActivate(cell);
+ }-*/;
+
+ @Override
+ public Collection<String> getConsumedEvents() {
+ if (hasGetConsumedEvents) {
+ JsArrayString events = getConsumedEvents(
+ helper.getConnectorWrapper());
+
+ ArrayList<String> list = new ArrayList<>(events.length());
+ for (int i = 0; i < events.length(); i++) {
+ list.add(events.get(i));
+ }
+ return list;
+ } else {
+ return super.getConsumedEvents();
+ }
+ }
+
+ private native JsArrayString getConsumedEvents(
+ JavaScriptObject wrapper)
+ /*-{
+ var rawEvents = wrapper.getConsumedEvents();
+ var events = [];
+ for(var i = 0; i < rawEvents.length; i++) {
+ events[i] = ""+rawEvents[i];
+ }
+ return events;
+ }-*/;
+
+ @Override
+ public boolean onBrowserEvent(CellReference<?> cell,
+ NativeEvent event) {
+ if (hasOnBrowserEvent) {
+ return onBrowserEvent(helper.getConnectorWrapper(),
+ getJsCell(cell), event);
+ } else {
+ return super.onBrowserEvent(cell, event);
+ }
+ }
+
+ private native boolean onBrowserEvent(JavaScriptObject wrapper,
+ JavaScriptObject cell, NativeEvent event)
+ /*-{
+ return !!wrapper.onBrowserEvent(cell, event);
+ }-*/;
+ };
+ }
+
+ @Override
+ public Object decode(JsonValue value) {
+ // Let the js logic decode the raw json that the server sent
+ return value;
+ }
+
+ @Override
+ public void onUnregister() {
+ super.onUnregister();
+ helper.onUnregister();
+ }
+
+ @Override
+ public JavaScriptConnectorHelper getJavascriptConnectorHelper() {
+ return helper;
+ }
+}
* @return the column id for the given column
*/
protected String getColumnId(Column<?, JsonObject> column) {
+ return getGridConnector().getColumnId(column);
+ }
+
+ /**
+ * Gets the grid connector for this renderer connector.
+ *
+ * @return the parent grid connector.
+ */
+ protected GridConnector getGridConnector() {
final ServerConnector parent = getParent();
if (parent instanceof ColumnConnector) {
final ServerConnector parentGrid = parent.getParent();
if (parentGrid instanceof GridConnector) {
- return ((GridConnector) parentGrid).getColumnId(column);
+ return (GridConnector) parentGrid;
}
}
throw new IllegalStateException(
--- /dev/null
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * 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.vaadin.ui.renderers;
+
+import com.vaadin.server.AbstractJavaScriptExtension;
+import com.vaadin.server.JavaScriptCallbackHelper;
+import com.vaadin.server.JsonCodec;
+import com.vaadin.shared.JavaScriptExtensionState;
+import com.vaadin.shared.communication.ServerRpc;
+import com.vaadin.ui.JavaScriptFunction;
+
+import elemental.json.Json;
+import elemental.json.JsonValue;
+
+/**
+ * Base class for Renderers with all client-side logic implemented using
+ * JavaScript.
+ * <p>
+ * When a new JavaScript renderer is initialized in the browser, the framework
+ * will look for a globally defined JavaScript function that will initialize the
+ * renderer. The name of the initialization function is formed by replacing .
+ * with _ in the name of the server-side class. If no such function is defined,
+ * each super class is used in turn until a match is found. The framework will
+ * thus first attempt with <code>com_example_MyRenderer</code> for the
+ * server-side
+ * <code>com.example.MyRenderer extends AbstractJavaScriptRenderer</code> class.
+ * If MyRenderer instead extends <code>com.example.SuperRenderer</code> , then
+ * <code>com_example_SuperRenderer</code> will also be attempted if
+ * <code>com_example_MyRenderer</code> has not been defined.
+ * <p>
+ *
+ * In addition to the general JavaScript extension functionality explained in
+ * {@link AbstractJavaScriptExtension}, this class also provides some
+ * functionality specific for renderers.
+ * <p>
+ * The initialization function will be called with <code>this</code> pointing to
+ * a connector wrapper object providing integration to Vaadin. Please note that
+ * in JavaScript, <code>this</code> is not necessarily defined inside callback
+ * functions and it might therefore be necessary to assign the reference to a
+ * separate variable, e.g. <code>var self = this;</code>. In addition to the
+ * extension functions described for {@link AbstractJavaScriptExtension}, the
+ * connector wrapper object also provides this function:
+ * <ul>
+ * <li><code>getRowKey(rowIndex)</code> - Gets a unique identifier for the row
+ * at the given index. This identifier can be used on the server to retrieve the
+ * corresponding ItemId using {@link #getItemId(String)}.</li>
+ * </ul>
+ * The connector wrapper also supports these special functions that can be
+ * implemented by the connector:
+ * <ul>
+ * <li><code>render(cell, data)</code> - Callback for rendering the given data
+ * into the given cell. The structure of cell and data are described in separate
+ * sections below. The renderer is required to implement this function.
+ * Corresponds to
+ * {@link com.vaadin.client.renderers.Renderer#render(com.vaadin.client.widget.grid.RendererCellReference, Object)}
+ * .</li>
+ * <li><code>init(cell)</code> - Prepares a cell for rendering. Corresponds to
+ * {@link com.vaadin.client.renderers.ComplexRenderer#init(com.vaadin.client.widget.grid.RendererCellReference)}
+ * .</li>
+ * <li><code>destory(cell)</code> - Allows the renderer to release resources
+ * allocate for a cell that will no longer be used. Corresponds to
+ * {@link com.vaadin.client.renderers.ComplexRenderer#destroy(com.vaadin.client.widget.grid.RendererCellReference)}
+ * .</li>
+ * <li><code>onActivate(cell)</code> - Called when the cell is activated by the
+ * user e.g. by double clicking on the cell or pressing enter with the cell
+ * focused. Corresponds to
+ * {@link com.vaadin.client.renderers.ComplexRenderer#onActivate(com.vaadin.client.widget.grid.CellReference)}
+ * .</li>
+ * <li><code>getConsumedEvents()</code> - Returns a JavaScript array of event
+ * names that should cause onBrowserEvent to be invoked whenever an event is
+ * fired for a cell managed by this renderer. Corresponds to
+ * {@link com.vaadin.client.renderers.ComplexRenderer#getConsumedEvents()}.</li>
+ * <li><code>onBrowserEvent(cell, event)</code> - Called by Grid when an event
+ * of a type returned by getConsumedEvents is fired for a cell managed by this
+ * renderer. Corresponds to
+ * {@link com.vaadin.client.renderers.ComplexRenderer#onBrowserEvent(com.vaadin.client.widget.grid.CellReference, com.google.gwt.dom.client.NativeEvent)}
+ * .</li>
+ * </ul>
+ *
+ * <p>
+ * The cell object passed to functions defined by the renderer has these
+ * properties:
+ * <ul>
+ * <li><code>element</code> - The DOM element corresponding to this cell.
+ * Readonly.</li>
+ * <li><code>rowIndex</code> - The current index of the row of this cell.
+ * Readonly.</li>
+ * <li><code>columnIndex</code> - The current index of the column of this cell.
+ * Readonly.</li>
+ * <li><code>colSpan</code> - The number of columns spanned by this cell. Only
+ * supported in the object passed to the <code>render</code> function - other
+ * functions should not use the property. Readable and writable.
+ * </ul>
+ *
+ * @param <T>
+ * the grid type this renderer can be attached to
+ * @param <V>
+ * the type this renderer knows how to present
+ *
+ * @author Vaadin Ltd
+ * @since 8.0
+ */
+public abstract class AbstractJavaScriptRenderer<T, V>
+ extends AbstractRenderer<T, V> {
+ private JavaScriptCallbackHelper callbackHelper = new JavaScriptCallbackHelper(
+ this);
+
+ protected AbstractJavaScriptRenderer(Class<V> presentationType,
+ String nullRepresentation) {
+ super(presentationType, nullRepresentation);
+ }
+
+ protected AbstractJavaScriptRenderer(Class<V> presentationType) {
+ super(presentationType, null);
+ }
+
+ @Override
+ protected <R extends ServerRpc> void registerRpc(R implementation,
+ Class<R> rpcInterfaceType) {
+ super.registerRpc(implementation, rpcInterfaceType);
+ callbackHelper.registerRpc(rpcInterfaceType);
+ }
+
+ /**
+ * Register a {@link JavaScriptFunction} that can be called from the
+ * JavaScript using the provided name. A JavaScript function with the
+ * provided name will be added to the connector wrapper object (initially
+ * available as <code>this</code>). Calling that JavaScript function will
+ * cause the call method in the registered {@link JavaScriptFunction} to be
+ * invoked with the same arguments.
+ *
+ * @param functionName
+ * the name that should be used for client-side callback
+ * @param function
+ * the {@link JavaScriptFunction} object that will be invoked
+ * when the JavaScript function is called
+ */
+ protected void addFunction(String functionName,
+ JavaScriptFunction function) {
+ callbackHelper.registerCallback(functionName, function);
+ }
+
+ /**
+ * Invoke a named function that the connector JavaScript has added to the
+ * JavaScript connector wrapper object. The arguments can be any boxed
+ * primitive type, String, {@link JsonValue} or arrays of any other
+ * supported type. Complex types (e.g. List, Set, Map, Connector or any
+ * JavaBean type) must be explicitly serialized to a {@link JsonValue}
+ * before sending. This can be done either with
+ * {@link JsonCodec#encode(Object, JsonValue, java.lang.reflect.Type, com.vaadin.ui.ConnectorTracker)}
+ * or using the factory methods in {@link Json}.
+ *
+ * @param name
+ * the name of the function
+ * @param arguments
+ * function arguments
+ */
+ protected void callFunction(String name, Object... arguments) {
+ callbackHelper.invokeCallback(name, arguments);
+ }
+
+ @Override
+ protected JavaScriptExtensionState getState() {
+ return (JavaScriptExtensionState) super.getState();
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * 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.vaadin.tests.components.grid;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Grid;
+
+public class JavaScriptRenderers extends AbstractTestUI {
+
+ public static class ItemBean {
+ private Integer id;
+ private String string;
+ private MyBean bean;
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getString() {
+ return string;
+ }
+
+ public void setString(String string) {
+ this.string = string;
+ }
+
+ public MyBean getBean() {
+ return bean;
+ }
+
+ public void setBean(MyBean bean) {
+ this.bean = bean;
+ }
+ }
+
+ public static class MyBean {
+ private int integer;
+ private String string;
+
+ public MyBean(int integer, String string) {
+ super();
+ this.integer = integer;
+ this.string = string;
+ }
+
+ public int getInteger() {
+ return integer;
+ }
+
+ public void setInteger(int integer) {
+ this.integer = integer;
+ }
+
+ public String getString() {
+ return string;
+ }
+
+ public void setString(String string) {
+ this.string = string;
+ }
+ }
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ List<ItemBean> items = new ArrayList<>(1000);
+ for (int i = 0; i < 1000; i++) {
+ ItemBean bean = new ItemBean();
+ bean.setId(i);
+ bean.setString("string" + i);
+ bean.setBean(new MyBean(i + 1, Integer.toString(i - 1)));
+ items.add(bean);
+ }
+
+ Grid<ItemBean> grid = new Grid<>();
+
+ grid.addColumn("id", item -> item.getId().toString());
+ grid.addColumn("bean", ItemBean::getBean, new MyBeanJSRenderer());
+ grid.addColumn("string", ItemBean::getString,
+ new JavaScriptStringRenderer());
+
+ grid.setItems(items);
+
+ addComponent(grid);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * 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.vaadin.tests.components.grid;
+
+import com.vaadin.annotations.JavaScript;
+import com.vaadin.tests.components.grid.JavaScriptRenderers.ItemBean;
+import com.vaadin.ui.renderers.AbstractJavaScriptRenderer;
+
+@JavaScript("JavaScriptStringRenderer.js")
+public class JavaScriptStringRenderer
+ extends AbstractJavaScriptRenderer<ItemBean, String> {
+
+ protected JavaScriptStringRenderer() {
+ super(String.class);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * 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.vaadin.tests.components.grid;
+
+import com.vaadin.annotations.JavaScript;
+import com.vaadin.tests.components.grid.JavaScriptRenderers.ItemBean;
+import com.vaadin.tests.components.grid.JavaScriptRenderers.MyBean;
+import com.vaadin.ui.renderers.AbstractJavaScriptRenderer;
+
+/**
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+@JavaScript("myBeanJsRenderer.js")
+public class MyBeanJSRenderer
+ extends AbstractJavaScriptRenderer<ItemBean, MyBean> {
+
+ public MyBeanJSRenderer() {
+ super(MyBean.class, "");
+ }
+
+}
}
this.render = function(cell, data) {
- cell.element.innerHTML = 'Bean(' + data.integer + ', ' + data.string + ')'
+ if (!cell.renderedText) {
+ cell.element.innerHTML = 'Bean(' + data.integer + ', ' + data.string + ')';
+ }
}
this.getConsumedEvents = function() { return ["click"] };
this.onBrowserEvent = function(cell, event) {
- cell.element.innerHTML = "Clicked " + cell.rowIndex + " with key " + this.getRowKey(cell.rowIndex) +" at " + event.clientX;
+ cell.renderedText ="Clicked " + cell.rowIndex + " with key " + this.getRowKey(cell.rowIndex) +" at " + event.clientX;
+ cell.element.innerHTML=cell.renderedText;
return true;
}
}
\ No newline at end of file
--- /dev/null
+com_vaadin_v7_tests_components_grid_JavaScriptStringRenderer = function() {
+ this.render = function(cell, data) {
+ cell.element.textContent = data;
+ }
+}
\ No newline at end of file
--- /dev/null
+window.com_vaadin_v7_tests_components_grid_MyBeanJSRenderer = function() {
+ this.init = function(cell) {
+ cell.element.setAttribute("column", cell.columnIndex);
+ }
+
+ this.render = function(cell, data) {
+ cell.element.innerHTML = 'Bean(' + data.integer + ', ' + data.string + ')'
+ }
+
+ this.getConsumedEvents = function() { return ["click"] };
+
+ this.onBrowserEvent = function(cell, event) {
+ cell.element.innerHTML = "Clicked " + cell.rowIndex + " with key " + this.getRowKey(cell.rowIndex) +" at " + event.clientX;
+ return true;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * 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.vaadin.tests.components.grid;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.testbench.customelements.GridElement;
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.testbench.parallel.TestCategory;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+@TestCategory("grid")
+public class JavaScriptRenderersTest extends MultiBrowserTest {
+
+ @Test
+ public void testJavaScriptRenderer() {
+ setDebug(true);
+ openTestURL();
+
+ GridElement grid = $(GridElement.class).first();
+ GridCellElement cell_1_1 = grid.getCell(1, 1);
+
+ GridCellElement cell_2_2 = grid.getCell(2, 2);
+
+ // Verify render functionality
+ Assert.assertEquals("Bean(2, 0)", cell_1_1.getText());
+
+ Assert.assertEquals("string2", cell_2_2.getText());
+
+ // Verify init functionality
+ Assert.assertEquals("1", cell_1_1.getAttribute("column"));
+
+ // Verify onbrowserevent
+ cell_1_1.click();
+ Assert.assertTrue(
+ cell_1_1.getText().startsWith("Clicked 1 with key 2 at"));
+ }
+}