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