Author: nbelaevski
Date: 2010-01-18 18:44:20 -0500 (Mon, 18 Jan 2010)
New Revision: 16325
Added:
root/framework/trunk/commons/src/test/
root/framework/trunk/commons/src/test/java/
root/framework/trunk/commons/src/test/java/org/
root/framework/trunk/commons/src/test/java/org/richfaces/
root/framework/trunk/commons/src/test/java/org/richfaces/renderkit/
root/framework/trunk/commons/src/test/java/org/richfaces/renderkit/MockClientBehaviorHolder.java
root/framework/trunk/commons/src/test/java/org/richfaces/renderkit/RenderKitUtilsTest.java
Modified:
root/framework/trunk/commons/pom.xml
root/framework/trunk/commons/src/main/java/org/richfaces/renderkit/ComponentAttribute.java
root/framework/trunk/commons/src/main/java/org/richfaces/renderkit/RenderKitUtils.java
Log:
https://jira.jboss.org/jira/browse/RF-77732
Behaviors rendering support + unit tests
Modified: root/framework/trunk/commons/pom.xml
===================================================================
--- root/framework/trunk/commons/pom.xml 2010-01-18 17:41:11 UTC (rev 16324)
+++ root/framework/trunk/commons/pom.xml 2010-01-18 23:44:20 UTC (rev 16325)
@@ -42,4 +42,21 @@
</build>
</profile>
</profiles>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.test-jsf</groupId>
+ <artifactId>jsf-mock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
</project>
\ No newline at end of file
Modified:
root/framework/trunk/commons/src/main/java/org/richfaces/renderkit/ComponentAttribute.java
===================================================================
---
root/framework/trunk/commons/src/main/java/org/richfaces/renderkit/ComponentAttribute.java 2010-01-18
17:41:11 UTC (rev 16324)
+++
root/framework/trunk/commons/src/main/java/org/richfaces/renderkit/ComponentAttribute.java 2010-01-18
23:44:20 UTC (rev 16325)
@@ -22,6 +22,7 @@
package org.richfaces.renderkit;
+import java.util.Collections;
import java.util.Map;
import java.util.TreeMap;
@@ -53,7 +54,7 @@
result.put(componentAttribute.getName(), componentAttribute);
}
- return result;
+ return Collections.unmodifiableMap(result);
}
/**
Modified:
root/framework/trunk/commons/src/main/java/org/richfaces/renderkit/RenderKitUtils.java
===================================================================
---
root/framework/trunk/commons/src/main/java/org/richfaces/renderkit/RenderKitUtils.java 2010-01-18
17:41:11 UTC (rev 16324)
+++
root/framework/trunk/commons/src/main/java/org/richfaces/renderkit/RenderKitUtils.java 2010-01-18
23:44:20 UTC (rev 16325)
@@ -32,6 +32,8 @@
import javax.faces.component.UIComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.component.behavior.ClientBehavior;
+import javax.faces.component.behavior.ClientBehaviorContext;
+import javax.faces.component.behavior.ClientBehaviorHint;
import javax.faces.component.behavior.ClientBehaviorHolder;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
@@ -42,6 +44,16 @@
*/
public final class RenderKitUtils {
+ /**
+ *
+ */
+ private static final String XHTML_ATTRIBUTE_PREFIX = "xml:";
+
+ /**
+ *
+ */
+ private static final String XHTML_CONTENT_TYPE = "application/xhtml+xml";
+
// TODO - check what's in MyFaces
private static final String ATTRIBUTES_THAT_ARE_SET = UIComponentBase.class.getName()
+ ".attributesThatAreSet";
@@ -51,6 +63,8 @@
private static final String[] URI_ATTRIBUTE_NAMES = { "action",
"background", "cite", "classid", "codebase",
"data", "href", "longdesc", "profile",
"src", "usemap" };
+ private static final String[] XHTML_ATTRIBUTE_NAMES = { "lang" };
+
private RenderKitUtils() {
// utility constructor
}
@@ -66,13 +80,94 @@
return result;
}
- private static Object createBehaviorsChain(Object inlineHandlerValue,
List<ClientBehavior> behaviors) {
- // TODO implement properly
- return inlineHandlerValue;
+ static String escape(String s) {
+ StringBuilder sb = new StringBuilder(s.length());
+ int start = 0;
+ int end = s.length();
+
+ while ((end = s.indexOf('\'', start)) >= 0) {
+ sb.append(s, start, end);
+ sb.append("\\'");
+
+ start = end + 1;
+ }
+
+ sb.append(s, start, s.length());
+
+ return sb.toString();
}
+
+ static boolean chain(StringBuilder sb, Object object, boolean isChained) {
+ if (object != null) {
+ String objectString = object.toString().trim();
+ if (objectString.length() != 0) {
+ final boolean localIsChained;
+
+ if (!isChained && sb.length() != 0) {
+ //extract previously stored handler
+ String previousHandlerString = sb.toString();
+ //clear builder object
+ sb.setLength(0);
+
+ //append escaped handler
+ sb.append("'");
+ sb.append(escape(previousHandlerString));
+ sb.append("'");
+
+ localIsChained = true;
+ } else {
+ //use passed in value of chained indicator
+ localIsChained = isChained;
+ }
+
+ if (localIsChained) {
+ sb.append(",'");
+ sb.append(escape(objectString));
+ sb.append("'");
+
+ return true;
+ } else {
+ sb.append(objectString);
+ return false;
+ }
+ }
+ }
+
+ //no changes, pass chained indicator we initially used
+ return isChained;
+ }
+
+ private static Object createBehaviorsChain(Object inlineHandlerValue,
ClientBehaviorContext behaviorContext,
+ List<ClientBehavior> behaviors) {
- private static boolean shouldRenderAttribute(String attributeName, Object
attributeValue) {
- if (attributeValue instanceof String) {
+ boolean isChained = false;
+ StringBuilder result = new StringBuilder();
+
+ isChained = chain(result, inlineHandlerValue, isChained);
+ for (ClientBehavior behavior : behaviors) {
+ isChained = chain(result, behavior.getScript(behaviorContext), isChained);
+
+ if (behavior.getHints().contains(ClientBehaviorHint.SUBMITTING)) {
+ break;
+ }
+ }
+
+ if (result.length() == 0) {
+ return null;
+ }
+
+ if (isChained) {
+ result.insert(0, "jsf.util.chain(");
+ result.append(")");
+ }
+
+ return result.toString();
+ }
+
+ static boolean shouldRenderAttribute(Object attributeValue) {
+ if (attributeValue == null) {
+ return false;
+ } else if (attributeValue instanceof String) {
return true;
} else if (attributeValue instanceof Boolean &&
Boolean.FALSE.equals(attributeValue)) {
return false;
@@ -95,30 +190,47 @@
return true;
}
+ public static String prefixAttributeName(String attributeName, boolean isXhtmlMode)
{
+ if (isXhtmlMode) {
+ if (Arrays.binarySearch(XHTML_ATTRIBUTE_NAMES, attributeName) >= 0) {
+ return XHTML_ATTRIBUTE_PREFIX + attributeName;
+ }
+ }
+
+ return attributeName;
+ }
+
+ public static String prefixAttributeName(String attributeName, ResponseWriter
responseWriter) {
+ return prefixAttributeName(attributeName,
XHTML_CONTENT_TYPE.equals(responseWriter.getContentType()));
+ }
+
public static void renderAttribute(FacesContext facesContext, String attributeName,
Object attributeValue)
throws IOException {
- if (!shouldRenderAttribute(attributeName, attributeValue)) {
+ if (!shouldRenderAttribute(attributeValue)) {
return;
}
ResponseWriter writer = facesContext.getResponseWriter();
+ String prefixedAttributeName = prefixAttributeName(attributeName, writer);
+
if (Arrays.binarySearch(URI_ATTRIBUTE_NAMES, attributeName) >= 0) {
- writer.writeURIAttribute(attributeName, attributeValue, attributeName);
+ writer.writeURIAttribute(prefixedAttributeName, attributeValue,
attributeName);
} else if (Arrays.binarySearch(BOOLEAN_ATTRIBUTE_NAMES, attributeName) >= 0)
{
boolean booleanAttributeValue =
Boolean.valueOf(String.valueOf(attributeValue));
if (booleanAttributeValue) {
- writer.writeAttribute(attributeName, attributeName, attributeName);
+ // TODO - is passing in Boolean.TRUE value documented somewhere?
+ writer.writeAttribute(prefixedAttributeName, Boolean.TRUE,
attributeName);
}
} else {
- writer.writeAttribute(attributeName, attributeValue, attributeName);
+ writer.writeAttribute(prefixedAttributeName, attributeValue, attributeName);
}
}
public static void renderAttributeAndBehaviors(FacesContext facesContext, UIComponent
component,
ComponentAttribute componentAttribute) throws IOException {
-
+
if (facesContext == null) {
throw new NullPointerException("facesContext");
}
@@ -141,7 +253,12 @@
for (String eventName : eventNames) {
List<ClientBehavior> behaviorsList =
behaviorsMap.get(eventName);
if (behaviorsList != null) {
- attributeValue = createBehaviorsChain(attributeValue,
behaviorsList);
+ if (!behaviorsList.isEmpty()) {
+ // TODO - parameters handling
+ ClientBehaviorContext behaviorContext =
ClientBehaviorContext.createClientBehaviorContext(
+ facesContext, component, eventName, null, null);
+ attributeValue = createBehaviorsChain(attributeValue,
behaviorContext, behaviorsList);
+ }
break;
}
Added:
root/framework/trunk/commons/src/test/java/org/richfaces/renderkit/MockClientBehaviorHolder.java
===================================================================
---
root/framework/trunk/commons/src/test/java/org/richfaces/renderkit/MockClientBehaviorHolder.java
(rev 0)
+++
root/framework/trunk/commons/src/test/java/org/richfaces/renderkit/MockClientBehaviorHolder.java 2010-01-18
23:44:20 UTC (rev 16325)
@@ -0,0 +1,58 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.renderkit;
+
+import static org.jboss.test.faces.mock.FacesMockController.invokeCurrent;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import javax.faces.component.behavior.ClientBehavior;
+import javax.faces.component.behavior.ClientBehaviorHolder;
+
+import org.easymock.IMocksControl;
+import org.jboss.test.faces.mock.component.MockUIComponent;
+
+public class MockClientBehaviorHolder extends MockUIComponent implements
ClientBehaviorHolder {
+
+ public MockClientBehaviorHolder(IMocksControl control, String name) {
+ super(control, name);
+ }
+
+ public void addClientBehavior(String eventName, ClientBehavior behavior) {
+ invokeCurrent(this, eventName, behavior);
+ }
+
+ public Map<String, List<ClientBehavior>> getClientBehaviors() {
+ return invokeCurrent(this);
+ }
+
+ public String getDefaultEventName() {
+ return invokeCurrent(this);
+ }
+
+ public Collection<String> getEventNames() {
+ return invokeCurrent(this);
+ }
+
+}
Added:
root/framework/trunk/commons/src/test/java/org/richfaces/renderkit/RenderKitUtilsTest.java
===================================================================
---
root/framework/trunk/commons/src/test/java/org/richfaces/renderkit/RenderKitUtilsTest.java
(rev 0)
+++
root/framework/trunk/commons/src/test/java/org/richfaces/renderkit/RenderKitUtilsTest.java 2010-01-18
23:44:20 UTC (rev 16325)
@@ -0,0 +1,250 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.renderkit;
+
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.behavior.ClientBehavior;
+import javax.faces.component.behavior.ClientBehaviorContext;
+import javax.faces.component.behavior.ClientBehaviorHint;
+import javax.faces.component.behavior.ClientBehaviorHolder;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+
+import org.easymock.EasyMock;
+import org.jboss.test.faces.mock.FacesMock;
+import org.jboss.test.faces.mock.MockFacesEnvironment;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public class RenderKitUtilsTest {
+
+ private MockFacesEnvironment facesEnvironment;
+
+ private ResponseWriter responseWriter;
+
+ private FacesContext facesContext;
+
+ @Before
+ public void setUp() throws Exception {
+ facesEnvironment = FacesMock.createMockEnvironment();
+ facesEnvironment.resetToNice();
+ facesContext = facesEnvironment.getFacesContext();
+
+ responseWriter = FacesMock.createMock(ResponseWriter.class);
+ expect(facesContext.getResponseWriter()).andReturn(responseWriter).anyTimes();
+
expect(responseWriter.getContentType()).andReturn("application/xhtml+xml").anyTimes();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ this.facesEnvironment = null;
+ this.responseWriter = null;
+ this.facesContext = null;
+ }
+
+ @Test
+ public void testEscape() throws Exception {
+ assertEquals("", RenderKitUtils.escape(""));
+ assertEquals("abcd", RenderKitUtils.escape("abcd"));
+ assertEquals("\\'abcd",
RenderKitUtils.escape("'abcd"));
+ assertEquals("abcd\\'",
RenderKitUtils.escape("abcd'"));
+ assertEquals("ab\\'cd",
RenderKitUtils.escape("ab'cd"));
+ assertEquals("ab\\'\\'cd",
RenderKitUtils.escape("ab''cd"));
+ assertEquals("ab\\'c\\'d",
RenderKitUtils.escape("ab'c'd"));
+ }
+
+ @Test
+ public void testChain() throws Exception {
+ StringBuilder sb = new StringBuilder();
+
+ assertFalse(RenderKitUtils.chain(sb, "", false));
+ assertTrue(sb.length() == 0);
+ assertFalse(RenderKitUtils.chain(sb, null, false));
+ assertTrue(sb.length() == 0);
+
+ assertFalse(RenderKitUtils.chain(sb, "test", false));
+ assertEquals("test", sb.toString());
+
+ assertFalse(RenderKitUtils.chain(sb, "", false));
+ assertEquals("test", sb.toString());
+
+ assertTrue(RenderKitUtils.chain(sb, "another'object", false));
+ assertEquals("'test','another\\'object'",
sb.toString());
+
+ assertTrue(RenderKitUtils.chain(sb, "one more", true));
+ assertEquals("'test','another\\'object','one
more'", sb.toString());
+ }
+
+ @Test
+ public void testShouldRenderAttribute() throws Exception {
+ assertFalse(RenderKitUtils.shouldRenderAttribute(null));
+
+ assertTrue(RenderKitUtils.shouldRenderAttribute(""));
+ assertTrue(RenderKitUtils.shouldRenderAttribute("test"));
+
+ assertTrue(RenderKitUtils.shouldRenderAttribute(new Object()));
+
+ assertTrue(RenderKitUtils.shouldRenderAttribute(Long.valueOf(10)));
+ assertTrue(RenderKitUtils.shouldRenderAttribute(Long.valueOf(0)));
+ assertFalse(RenderKitUtils.shouldRenderAttribute(Long.MIN_VALUE));
+
+ assertTrue(RenderKitUtils.shouldRenderAttribute(Integer.valueOf(10)));
+ assertTrue(RenderKitUtils.shouldRenderAttribute(Integer.valueOf(0)));
+ assertFalse(RenderKitUtils.shouldRenderAttribute(Integer.MIN_VALUE));
+
+ assertTrue(RenderKitUtils.shouldRenderAttribute(Short.valueOf((short) 10)));
+ assertTrue(RenderKitUtils.shouldRenderAttribute(Short.valueOf((short) 0)));
+ assertFalse(RenderKitUtils.shouldRenderAttribute(Short.MIN_VALUE));
+
+
assertTrue(RenderKitUtils.shouldRenderAttribute(Character.valueOf('a')));
+ assertTrue(RenderKitUtils.shouldRenderAttribute(Character.valueOf((char) 13)));
+ assertFalse(RenderKitUtils.shouldRenderAttribute(Character.MIN_VALUE));
+
+ assertTrue(RenderKitUtils.shouldRenderAttribute(Byte.valueOf((byte) 10)));
+ assertTrue(RenderKitUtils.shouldRenderAttribute(Byte.valueOf((byte) 0)));
+ assertFalse(RenderKitUtils.shouldRenderAttribute(Byte.MIN_VALUE));
+
+ assertTrue(RenderKitUtils.shouldRenderAttribute(Double.valueOf(10)));
+ assertTrue(RenderKitUtils.shouldRenderAttribute(Double.valueOf(0)));
+ assertFalse(RenderKitUtils.shouldRenderAttribute(Double.MIN_VALUE));
+
+ assertTrue(RenderKitUtils.shouldRenderAttribute(Float.valueOf(10)));
+ assertTrue(RenderKitUtils.shouldRenderAttribute(Float.valueOf(0)));
+ assertFalse(RenderKitUtils.shouldRenderAttribute(Float.MIN_VALUE));
+
+ assertTrue(RenderKitUtils.shouldRenderAttribute(Boolean.TRUE));
+ assertFalse(RenderKitUtils.shouldRenderAttribute(Boolean.FALSE));
+ }
+
+ @Test
+ public void testRenderPassThroughAttributes() throws Exception {
+ Map<String, ComponentAttribute> knownAttributes = new HashMap<String,
ComponentAttribute>();
+ knownAttributes.put("disabled", new
ComponentAttribute("disabled"));
+ knownAttributes.put("checked", new
ComponentAttribute("checked"));
+ knownAttributes.put("style", new
ComponentAttribute("style"));
+ knownAttributes.put("src", new ComponentAttribute("src"));
+ knownAttributes.put("lang", new ComponentAttribute("lang"));
+
+ Map<String, Object> componentAttributes = new HashMap<String,
Object>();
+ componentAttributes.put("disabled", Boolean.TRUE);
+ componentAttributes.put("checked", Boolean.FALSE);
+ componentAttributes.put("style", "color:red");
+ componentAttributes.put("src", "urn:abc");
+ componentAttributes.put("facelets.Mark", 123);
+ componentAttributes.put("lang", "ru");
+
+ UIComponent component = FacesMock.createMock(UIComponent.class);
+ expect(component.getAttributes()).andReturn(componentAttributes).anyTimes();
+
+ responseWriter.writeAttribute(eq("disabled"), eq(Boolean.TRUE),
eq("disabled"));
+ // checked attribute shouldn't be rendered - it's 'false'
+ responseWriter.writeAttribute(eq("style"), eq("color:red"),
eq("style"));
+ responseWriter.writeURIAttribute(eq("src"), eq("urn:abc"),
eq("src"));
+ // facelets.Mark shouldn't be rendered - it's unknown
+ responseWriter.writeAttribute(eq("xml:lang"), eq("ru"),
eq("lang"));
+
+ FacesMock.replay(facesEnvironment, component, responseWriter);
+
+ RenderKitUtils.renderPassThroughAttributes(facesContext, component,
knownAttributes);
+
+ FacesMock.verify(facesEnvironment, component, responseWriter);
+ }
+
+ private ClientBehavior createClientBehavior(String handlerData,
Set<ClientBehaviorHint> hints) {
+ ClientBehavior behavior = FacesMock.createMock(ClientBehavior.class);
+
expect(behavior.getScript(EasyMock.<ClientBehaviorContext>notNull())).andReturn(
+ MessageFormat.format("prompt({0})", handlerData)).anyTimes();
+
+ expect(behavior.getHints()).andReturn(hints).anyTimes();
+ return behavior;
+ }
+
+ @Test
+ public void testBehaviors() throws Exception {
+ Map<String, ComponentAttribute> knownAttributes = new HashMap<String,
ComponentAttribute>();
+ knownAttributes.put("onclick", new
ComponentAttribute("onclick", new String[] { "click",
"action" }));
+ knownAttributes.put("onmousemove", new
ComponentAttribute("onmousemove", new String[] { "mousemove" }));
+ knownAttributes.put("onkeypress", new
ComponentAttribute("onkeypress", new String[] { "keypress" }));
+ knownAttributes.put("oncontextmenu", new
ComponentAttribute("oncontextmenu", new String[] { "contextmenu" }));
+
+ Map<String, Object> componentAttributes = new HashMap<String,
Object>();
+ componentAttributes.put("onkeypress", "alert(keypress)");
+ componentAttributes.put("onmousemove", "alert(mousemove)");
+ componentAttributes.put("onclick", "alert(click)");
+
+ Set<ClientBehaviorHint> emptyHintsSet =
EnumSet.noneOf(ClientBehaviorHint.class);
+ Set<ClientBehaviorHint> submittingHintsSet =
EnumSet.of(ClientBehaviorHint.SUBMITTING);
+
+ Map<String, List<ClientBehavior>> behaviorsMap = new
HashMap<String, List<ClientBehavior>>();
+
+ ClientBehavior keypressBehavior = createClientBehavior("keypress",
emptyHintsSet);
+ ClientBehavior actionBehavior1 = createClientBehavior("action1",
emptyHintsSet);
+ ClientBehavior actionBehavior2 = createClientBehavior("action2",
submittingHintsSet);
+ ClientBehavior actionBehavior3 = createClientBehavior("action3",
emptyHintsSet);
+ ClientBehavior contextmenuBehavior =
createClientBehavior("contextmenu", emptyHintsSet);
+
+ behaviorsMap.put("keypress", Arrays.asList(keypressBehavior));
+ behaviorsMap.put("action", Arrays.asList(actionBehavior1,
actionBehavior2, actionBehavior3));
+ behaviorsMap.put("contextmenu", Arrays.asList(contextmenuBehavior));
+
+ UIComponent component = FacesMock.createMock(MockClientBehaviorHolder.class);
+ expect(component.getAttributes()).andReturn(componentAttributes).anyTimes();
+ ClientBehaviorHolder behaviorHolder = (ClientBehaviorHolder) component;
+ expect(behaviorHolder.getClientBehaviors()).andReturn(behaviorsMap).anyTimes();
+ expect(behaviorHolder.getEventNames()).andReturn(
+ Arrays.asList("click", "action", "mousemove",
"keypress", "blur", "contextmenu")).anyTimes();
+
+ responseWriter.writeAttribute(eq("onkeypress"),
eq("jsf.util.chain('alert(keypress)','prompt(keypress)')"),
+ eq("onkeypress"));
+ responseWriter.writeAttribute(eq("onclick"),
+
eq("jsf.util.chain('alert(click)','prompt(action1)','prompt(action2)')"),
eq("onclick"));
+ responseWriter.writeAttribute(eq("onmousemove"),
eq("alert(mousemove)"), eq("onmousemove"));
+ responseWriter.writeAttribute(eq("oncontextmenu"),
eq("prompt(contextmenu)"), eq("oncontextmenu"));
+
+ FacesMock.replay(component, facesEnvironment, responseWriter, keypressBehavior,
actionBehavior1, actionBehavior2,
+ actionBehavior3, contextmenuBehavior);
+
+ RenderKitUtils.renderPassThroughAttributes(facesContext, component,
knownAttributes);
+
+ FacesMock.verify(component, facesEnvironment, responseWriter, keypressBehavior,
actionBehavior1, actionBehavior2,
+ actionBehavior3, contextmenuBehavior);
+ }
+}
\ No newline at end of file