added unittests for https://stackoverflow.com/questions/61142033/postaddtoview-event-not-fired-for-head-in-myfaces
diff --git a/impl/src/test/java/org/apache/myfaces/application/ApplicationImplAnnotationTest.java b/impl/src/test/java/org/apache/myfaces/application/ApplicationImplAnnotationTest.java
index f5574e0..f7db2a7 100644
--- a/impl/src/test/java/org/apache/myfaces/application/ApplicationImplAnnotationTest.java
+++ b/impl/src/test/java/org/apache/myfaces/application/ApplicationImplAnnotationTest.java
@@ -139,6 +139,7 @@
@ResourceDependency(library = "testLib", name = "testResource.js")
public static class TestRendererA extends Renderer implements ComponentSystemEventListener
{
+ @Override
public void processEvent(ComponentSystemEvent event)
{
FacesContext.getCurrentInstance().getAttributes().put("oam.test.TestRendererA", Boolean.TRUE);
@@ -160,6 +161,7 @@
return delegate;
}
+ @Override
public void processEvent(ComponentSystemEvent event)
{
// Note there is no @ListenerFor annotation, so this should not happen, but the interesting thing
@@ -187,6 +189,7 @@
return delegate;
}
+ @Override
public void processEvent(ComponentSystemEvent event)
{
FacesContext.getCurrentInstance().getAttributes().put("oam.test.TestRendererWrapper", Boolean.TRUE);
diff --git a/impl/src/test/java/org/apache/myfaces/event/GlobalPostAddToViewEventTestCase.java b/impl/src/test/java/org/apache/myfaces/event/GlobalPostAddToViewEventTestCase.java
new file mode 100644
index 0000000..4568290
--- /dev/null
+++ b/impl/src/test/java/org/apache/myfaces/event/GlobalPostAddToViewEventTestCase.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.myfaces.event;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.html.HtmlHead;
+import javax.faces.event.PostAddToViewEvent;
+import javax.faces.event.SystemEvent;
+import javax.faces.event.SystemEventListener;
+import org.apache.myfaces.test.base.junit4.AbstractJsfConfigurableMockTestCase;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class GlobalPostAddToViewEventTestCase extends AbstractJsfConfigurableMockTestCase
+{
+ public class HeadResourceListener implements SystemEventListener
+ {
+ @Override
+ public boolean isListenerForSource(Object source)
+ {
+ return "javax.faces.Head".equals(((UIComponent) source).getRendererType());
+ }
+
+ @Override
+ public void processEvent(SystemEvent event)
+ {
+ event.getFacesContext().getAttributes().put("SystemEventListenerInvokedForHead", Boolean.TRUE);
+ }
+ }
+
+ @Test
+ public void testPostAddToViewForHead() throws Exception
+ {
+ application.subscribeToEvent(PostAddToViewEvent.class, new HeadResourceListener());
+
+ application.addComponent(HtmlHead.COMPONENT_TYPE,
+ HtmlHead.class.getName());
+
+ HtmlHead comp = (HtmlHead) application.createComponent(facesContext,
+ HtmlHead.COMPONENT_TYPE,
+ "javax.faces.Head");
+
+ // Invoke PostAddToViewEvent
+ facesContext.getViewRoot().getChildren().add(comp);
+
+ Assert.assertTrue(facesContext.getAttributes().containsKey("SystemEventListenerInvokedForHead"));
+ }
+}
diff --git a/impl/src/test/java/org/apache/myfaces/event/PostAddToViewEventTestCase.java b/impl/src/test/java/org/apache/myfaces/event/PostAddToViewEventTestCase.java
index bab34fe..d40efdc 100644
--- a/impl/src/test/java/org/apache/myfaces/event/PostAddToViewEventTestCase.java
+++ b/impl/src/test/java/org/apache/myfaces/event/PostAddToViewEventTestCase.java
@@ -21,6 +21,7 @@
import javax.faces.application.StateManager;
import javax.faces.component.UICommand;
import javax.faces.component.UIForm;
+import javax.faces.component.UIOutput;
import javax.faces.component.UIPanel;
import javax.faces.component.UIViewRoot;
import javax.faces.event.ComponentSystemEvent;
@@ -60,16 +61,11 @@
PostAddToViewEventBean bean = EasyMock.createMock(PostAddToViewEventBean.class);
bean.invokePostAddToViewEvent(EasyMock.isA(ComponentSystemEvent.class));
- EasyMock.expectLastCall().andAnswer(new IAnswer<Object>()
- {
- public Object answer()
- {
- ComponentSystemEvent e = (ComponentSystemEvent) EasyMock
- .getCurrentArguments()[0];
- Assert.assertTrue(e.getComponent() instanceof UIViewRoot);
- Assert.assertEquals(PhaseId.RENDER_RESPONSE, facesContext.getCurrentPhaseId());
- return null;
- }
+ EasyMock.expectLastCall().andAnswer(() -> {
+ ComponentSystemEvent e = (ComponentSystemEvent) EasyMock.getCurrentArguments()[0];
+ Assert.assertTrue(e.getComponent() instanceof UIViewRoot);
+ Assert.assertEquals(PhaseId.RENDER_RESPONSE, facesContext.getCurrentPhaseId());
+ return null;
}).once();
EasyMock.replay(bean);
//Put on request map
@@ -86,31 +82,22 @@
// but when building initial state.
if (WebConfigParamUtils.getBooleanInitParameter(externalContext, StateManager.PARTIAL_STATE_SAVING_PARAM_NAME))
{
- EasyMock.expectLastCall().andAnswer(new IAnswer<Object>()
- {
- public Object answer()
- {
- ComponentSystemEvent e = (ComponentSystemEvent) EasyMock
- .getCurrentArguments()[0];
- Assert.assertTrue(e.getComponent() instanceof UIViewRoot);
- Assert.assertEquals(PhaseId.RESTORE_VIEW, facesContext.getCurrentPhaseId());
- Assert.assertTrue(facesContext.getAttributes().containsKey("javax.faces.IS_BUILDING_INITIAL_STATE"));
- Assert.assertFalse(FaceletViewDeclarationLanguage.isRefreshingTransientBuild(facesContext));
- return null;
- }
+ EasyMock.expectLastCall().andAnswer(() -> {
+ ComponentSystemEvent e = (ComponentSystemEvent) EasyMock.getCurrentArguments()[0];
+ Assert.assertTrue(e.getComponent() instanceof UIViewRoot);
+ Assert.assertEquals(PhaseId.RESTORE_VIEW, facesContext.getCurrentPhaseId());
+ Assert.assertTrue(facesContext.getAttributes().containsKey("javax.faces.IS_BUILDING_INITIAL_STATE"));
+ Assert.assertFalse(FaceletViewDeclarationLanguage.isRefreshingTransientBuild(facesContext));
+ return null;
}).once();
}
else
{
// Without PSS the listener should not be called, because it was already
// called on the first request
- EasyMock.expectLastCall().andAnswer(new IAnswer<Object>()
- {
- public Object answer()
- {
- Assert.fail();
- return null;
- }
+ EasyMock.expectLastCall().andAnswer(() -> {
+ Assert.fail();
+ return null;
}).anyTimes();
}
@@ -211,15 +198,12 @@
PostAddToViewEventBean bean = EasyMock.createMock(PostAddToViewEventBean.class);
bean.invokePostAddToViewEvent(EasyMock.isA(ComponentSystemEvent.class));
- EasyMock.expectLastCall().andAnswer(new IAnswer<Object>()
- {
- public Object answer()
- {
- Assert.fail();
- return null;
- }
+ EasyMock.expectLastCall().andAnswer(() -> {
+ Assert.fail();
+ return null;
}).anyTimes();
EasyMock.replay(bean);
+
//Put on request map
request.setAttribute("postAddToViewEventBean", bean);
request.setAttribute("condition", Boolean.FALSE);
@@ -231,13 +215,9 @@
bean = EasyMock.createMock(PostAddToViewEventBean.class);
bean.invokePostAddToViewEvent(EasyMock.isA(ComponentSystemEvent.class));
- EasyMock.expectLastCall().andAnswer(new IAnswer<Object>()
- {
- public Object answer()
- {
- Assert.fail();
- return null;
- }
+ EasyMock.expectLastCall().andAnswer(() -> {
+ Assert.fail();
+ return null;
}).anyTimes();
EasyMock.replay(bean);
@@ -248,16 +228,11 @@
bean = EasyMock.createMock(PostAddToViewEventBean.class);
bean.invokePostAddToViewEvent(EasyMock.isA(ComponentSystemEvent.class));
- EasyMock.expectLastCall().andAnswer(new IAnswer<Object>()
- {
- public Object answer()
- {
- ComponentSystemEvent e = (ComponentSystemEvent) EasyMock
- .getCurrentArguments()[0];
- Assert.assertTrue(e.getComponent() instanceof UIPanel);
- Assert.assertEquals(PhaseId.RENDER_RESPONSE, facesContext.getCurrentPhaseId());
- return null;
- }
+ EasyMock.expectLastCall().andAnswer(() -> {
+ ComponentSystemEvent e = (ComponentSystemEvent) EasyMock.getCurrentArguments()[0];
+ Assert.assertTrue(e.getComponent() instanceof UIPanel);
+ Assert.assertEquals(PhaseId.RENDER_RESPONSE, facesContext.getCurrentPhaseId());
+ return null;
}).once();
EasyMock.replay(bean);
@@ -266,4 +241,57 @@
renderResponse();
EasyMock.verify(bean);
}
+
+
+ @Test
+ public void testPostAddToViewOnComponentHead() throws Exception
+ {
+ startViewRequest("/postAddToViewEvent_4.xhtml");
+
+ PostAddToViewEventBean bean = EasyMock.createMock(PostAddToViewEventBean.class);
+ bean.invokePostAddToViewEvent(EasyMock.isA(ComponentSystemEvent.class));
+ EasyMock.expectLastCall().andAnswer(() -> {
+ ComponentSystemEvent e = (ComponentSystemEvent) EasyMock.getCurrentArguments()[0];
+ Assert.assertTrue(e.getComponent() instanceof UIOutput);
+ Assert.assertTrue(e.getComponent().getRendererType().equals("javax.faces.Head"));
+ return null;
+ }).once();
+ EasyMock.replay(bean);
+ //Put on request map
+ request.setAttribute("postAddToViewEventBean", bean);
+ processLifecycleExecuteAndRender();
+ EasyMock.verify(bean);
+
+ UICommand button = (UICommand) facesContext.getViewRoot().findComponent("mainForm:submit");
+ client.submit(button);
+
+ bean = EasyMock.createMock(PostAddToViewEventBean.class);
+ bean.invokePostAddToViewEvent(EasyMock.isA(ComponentSystemEvent.class));
+ // With PSS PostAddToViewEvent is called again on restore view phase
+ // but when building initial state.
+ if (WebConfigParamUtils.getBooleanInitParameter(externalContext, StateManager.PARTIAL_STATE_SAVING_PARAM_NAME))
+ {
+ EasyMock.expectLastCall().andAnswer(() -> {
+ ComponentSystemEvent e = (ComponentSystemEvent) EasyMock.getCurrentArguments()[0];
+ Assert.assertTrue(e.getComponent() instanceof UIOutput);
+ Assert.assertTrue(e.getComponent().getRendererType().equals("javax.faces.Head"));
+ return null;
+ }).once();
+ }
+ else
+ {
+ // Without PSS the listener should not be called, because it was already
+ // called on the first request
+ EasyMock.expectLastCall().andAnswer(() -> {
+ Assert.fail();
+ return null;
+ }).anyTimes();
+ }
+
+ EasyMock.replay(bean);
+ //Put on request map
+ request.setAttribute("postAddToViewEventBean", bean);
+ processLifecycleExecute();
+ EasyMock.verify(bean);
+ }
}
diff --git a/impl/src/test/resources/org/apache/myfaces/event/postAddToViewEvent_4.xhtml b/impl/src/test/resources/org/apache/myfaces/event/postAddToViewEvent_4.xhtml
new file mode 100644
index 0000000..114bf28
--- /dev/null
+++ b/impl/src/test/resources/org/apache/myfaces/event/postAddToViewEvent_4.xhtml
@@ -0,0 +1,29 @@
+<?xml version='1.0' encoding='UTF-8' ?>
+<!--
+ 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.
+-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<ui:composition xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:ui="http://java.sun.com/jsf/facelets">
+
+ <h:head>
+ <f:event type="postAddToView"
+ listener="#{postAddToViewEventBean.invokePostAddToViewEvent}"/>
+ </h:head>
+
+ <h:form id="mainForm">
+ <h:commandButton id="submit"/>
+ </h:form>
+</ui:composition>
\ No newline at end of file