You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by hn...@apache.org on 2023/02/28 14:00:17 UTC

[myfaces-tobago] branch main updated: fix: menu store position

This is an automated email from the ASF dual-hosted git repository.

hnoeth pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/myfaces-tobago.git


The following commit(s) were added to refs/heads/main by this push:
     new a13445f8ec fix: menu store position
a13445f8ec is described below

commit a13445f8ecb17e66791d5fb14ead377506630ec6
Author: Henning Noeth <hn...@apache.org>
AuthorDate: Tue Feb 28 12:54:28 2023 +0100

    fix: menu store position
    
    * add test
    * render the menu store at the start of the page
    
    Issue: TOBAGO-2198
---
 .../internal/renderkit/renderer/PageRenderer.java  | 48 ++++++++++------------
 .../tobago/example/demo/ExceptionController.java   | 13 ++++++
 .../50000-java/40-force-npe/Force_NPE.test.js      | 35 ++++++++++++++++
 .../50000-java/40-force-npe/Force_NPE.xhtml        | 36 ++++++++++++++++
 4 files changed, 106 insertions(+), 26 deletions(-)

diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PageRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PageRenderer.java
index 5a5a2a6fbc..fc8d83a06d 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PageRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PageRenderer.java
@@ -19,6 +19,14 @@
 
 package org.apache.myfaces.tobago.internal.renderkit.renderer;
 
+import jakarta.faces.application.Application;
+import jakarta.faces.application.ProjectStage;
+import jakarta.faces.application.ViewHandler;
+import jakarta.faces.component.UIComponent;
+import jakarta.faces.component.UIOutput;
+import jakarta.faces.component.UIViewRoot;
+import jakarta.faces.context.ExternalContext;
+import jakarta.faces.context.FacesContext;
 import org.apache.myfaces.tobago.component.Attributes;
 import org.apache.myfaces.tobago.component.RendererTypes;
 import org.apache.myfaces.tobago.component.Tags;
@@ -52,15 +60,6 @@ import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import jakarta.faces.application.Application;
-import jakarta.faces.application.ProjectStage;
-import jakarta.faces.application.ViewHandler;
-import jakarta.faces.component.UIComponent;
-import jakarta.faces.component.UIOutput;
-import jakarta.faces.component.UIViewRoot;
-import jakarta.faces.context.ExternalContext;
-import jakarta.faces.context.FacesContext;
-
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
 import java.util.ArrayList;
@@ -131,6 +130,7 @@ public class PageRenderer<T extends AbstractUIPage> extends RendererBase<T> {
     final UIViewRoot viewRoot = facesContext.getViewRoot();
     final String viewId = viewRoot.getViewId();
     final String formAction = externalContext.encodeActionURL(viewHandler.getActionURL(facesContext, viewId));
+    final boolean ajax = facesContext.getPartialViewContext().isAjaxRequest();
 
     final String contentType = writer.getContentTypeWithCharSet();
     ResponseUtils.ensureContentTypeHeader(facesContext, contentType);
@@ -276,6 +276,19 @@ public class PageRenderer<T extends AbstractUIPage> extends RendererBase<T> {
       }
     }
 
+    // placeholder for menus
+    writer.startElement(HtmlElements.DIV);
+    writer.writeClassAttribute(TobagoClass.PAGE__MENU_STORE);
+    writer.endElement(HtmlElements.DIV);
+
+    writer.startElement(HtmlElements.SPAN);
+    writer.writeIdAttribute(clientId + ComponentUtils.SUB_SEPARATOR + "faces-state-container");
+    writer.flush();
+    if (!ajax) {
+      viewHandler.writeState(facesContext);
+    }
+    writer.endElement(HtmlElements.SPAN);
+
     if (component.getFacet("backButtonDetector") != null) {
       final UIComponent hidden = component.getFacet("backButtonDetector");
       hidden.encodeAll(facesContext);
@@ -302,23 +315,6 @@ public class PageRenderer<T extends AbstractUIPage> extends RendererBase<T> {
 
     final UIViewRoot viewRoot = facesContext.getViewRoot();
     final TobagoResponseWriter writer = getResponseWriter(facesContext);
-    final String clientId = component.getClientId(facesContext);
-    final Application application = facesContext.getApplication();
-    final ViewHandler viewHandler = application.getViewHandler();
-    final boolean ajax = facesContext.getPartialViewContext().isAjaxRequest();
-
-    // placeholder for menus
-    writer.startElement(HtmlElements.DIV);
-    writer.writeClassAttribute(TobagoClass.PAGE__MENU_STORE);
-    writer.endElement(HtmlElements.DIV);
-
-    writer.startElement(HtmlElements.SPAN);
-    writer.writeIdAttribute(clientId + ComponentUtils.SUB_SEPARATOR + "faces-state-container");
-    writer.flush();
-    if (!ajax) {
-      viewHandler.writeState(facesContext);
-    }
-    writer.endElement(HtmlElements.SPAN);
 
     writer.endElement(HtmlElements.FORM);
 
diff --git a/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ExceptionController.java b/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ExceptionController.java
index 85037a7c2c..cebe28d6fd 100644
--- a/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ExceptionController.java
+++ b/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ExceptionController.java
@@ -31,6 +31,8 @@ import java.io.StringWriter;
 @Named
 public class ExceptionController implements Serializable {
 
+  private boolean returnNpe;
+
   public String getStackTrace() {
     final Throwable exception = (Throwable) FacesContext.getCurrentInstance().getExternalContext()
         .getRequestMap().get("jakarta.servlet.error.exception");
@@ -41,4 +43,15 @@ public class ExceptionController implements Serializable {
     }
     return stringWriter.toString();
   }
+
+  public String getStringOrNpe() {
+    if (returnNpe) {
+      throw new NullPointerException("The exception is thrown by purpose.");
+    }
+    return "no NPE";
+  }
+
+  public void returnNpe() {
+    returnNpe = true;
+  }
 }
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/900-test/50000-java/40-force-npe/Force_NPE.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/900-test/50000-java/40-force-npe/Force_NPE.test.js
new file mode 100644
index 0000000000..30dc11e3fd
--- /dev/null
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/900-test/50000-java/40-force-npe/Force_NPE.test.js
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+import {elementByIdFn, querySelectorFn} from "/script/tobago-test.js";
+import {JasmineTestTool} from "/tobago/test/tobago-test-tool.js";
+
+it("menu store must be available", function (done) {
+  const timestampFn = querySelectorFn("#page\\:mainForm\\:timestamp .form-control-plaintext");
+  const submitFn = elementByIdFn("page:mainForm:submitButton");
+  const forceNpeFn = elementByIdFn("page:mainForm:forceNpeButton");
+  const menuStoreFn = querySelectorFn(".tobago-page-menuStore");
+
+  const timestampValue = timestampFn().textContent;
+
+  let test = new JasmineTestTool(done);
+  test.setup(() => menuStoreFn() !== null, null, "click", submitFn);
+  test.do(() => expect(menuStoreFn()).not.toBeNull());
+  test.event("click", forceNpeFn, () => timestampFn().textContent !== timestampValue);
+  test.do(() => expect(menuStoreFn()).not.toBeNull());
+  test.start();
+});
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/900-test/50000-java/40-force-npe/Force_NPE.xhtml b/tobago-example/tobago-example-demo/src/main/webapp/content/900-test/50000-java/40-force-npe/Force_NPE.xhtml
new file mode 100644
index 0000000000..4a3dc17c8e
--- /dev/null
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/900-test/50000-java/40-force-npe/Force_NPE.xhtml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * 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.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:f="http://xmlns.jcp.org/jsf/core"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
+  <ui:param name="title" value="Ajax Unicode"/>
+
+  <tc:button id="ajaxButton" label="AJAX">
+    <f:ajax render="box"/>
+  </tc:button>
+  <tc:button id="submitButton" label="Submit"/>
+  <tc:button id="forceNpeButton" label="NPE!" action="#{exceptionController.returnNpe()}"/>
+
+  <tc:box id="box" label="Box">
+    <tc:out id="timestamp" label="Timestamp" value="#{ajaxSpecialCharacterController.timestamp}"/>
+    <tc:out label="NPE?" value="#{exceptionController.stringOrNpe}"/>
+  </tc:box>
+</ui:composition>