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

benw pushed a commit to branch TAP5-2745
in repository https://gitbox.apache.org/repos/asf/tapestry-5.git

commit 83c24a77eeea6e79b8fbccaec465a56c535d39a8
Author: Ben Weidig <b...@netzgut.net>
AuthorDate: Sun Jun 25 11:25:35 2023 +0200

    TAP5-2745: Tree component supports empty TreeModel
---
 .../apache/tapestry5/corelib/components/Tree.java  |  7 +++--
 .../apache/tapestry5/tree/DefaultTreeModel.java    |  1 -
 .../tapestry5/integration/app1/TreeTests.groovy    | 11 ++++++++
 .../apache/tapestry5/integration/app1/Stuff.java   | 13 ++++++++-
 .../tapestry5/integration/app1/pages/Index.java    |  2 ++
 .../integration/app1/pages/TreeNoRootsDemo.java    | 31 ++++++++++++++++++++++
 .../integration/app1/pages/TreeNoRootsDemo.tml     |  7 +++++
 7 files changed, 68 insertions(+), 4 deletions(-)

diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Tree.java 
b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Tree.java
index 96f7752db..7167574a4 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Tree.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Tree.java
@@ -255,8 +255,6 @@ public class Tree
 
         public RenderNodes(List<TreeNode> nodes)
         {
-            assert !nodes.isEmpty();
-
             this.nodes = F.flow(nodes).reverse();
         }
 
@@ -265,6 +263,11 @@ public class Tree
             writer.element("ul");
             queue.push(RENDER_CLOSE_TAG);
 
+            // TAP5-2745: Support empty tree model
+            if (nodes.isEmpty()) {
+                return;
+            }
+
             queue.push(toRenderCommand(nodes.first(), true));
 
             nodes.rest().each(new Worker<TreeNode>()
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/tree/DefaultTreeModel.java 
b/tapestry-core/src/main/java/org/apache/tapestry5/tree/DefaultTreeModel.java
index 38780b0a0..45343cff3 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/tree/DefaultTreeModel.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/tree/DefaultTreeModel.java
@@ -133,7 +133,6 @@ public class DefaultTreeModel<T> implements TreeModel<T>
         assert encoder != null;
         assert adapter != null;
         assert roots != null;
-        assert !roots.isEmpty();
 
         this.encoder = encoder;
         this.adapter = adapter;
diff --git 
a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/TreeTests.groovy
 
b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/TreeTests.groovy
index 5301a60ea..753155706 100644
--- 
a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/TreeTests.groovy
+++ 
b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/TreeTests.groovy
@@ -16,6 +16,8 @@ package org.apache.tapestry5.integration.app1
 
 import org.testng.annotations.Test
 
+import spock.lang.Issue
+
 class TreeTests extends App1TestCase {
 
     @Test
@@ -68,4 +70,13 @@ class TreeTests extends App1TestCase {
 
         waitForCssSelectorToAppear "span.selected-leaf-node"
     }
+
+    @Issue("TAP5-2745")
+    @Test
+    void no_roots() {
+        openLinks "Tree Component No Roots Demo"
+
+        assertTrue isElementPresent('css=.tree-container')
+        assertFalse isElementPresent('css=.tree-container span.tree-icon')
+    }
 }
diff --git 
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/Stuff.java 
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/Stuff.java
index 5fb9fed14..7291e4def 100644
--- 
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/Stuff.java
+++ 
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/Stuff.java
@@ -19,6 +19,7 @@ import org.apache.tapestry5.commons.util.CollectionFactory;
 import org.apache.tapestry5.tree.DefaultTreeModel;
 import org.apache.tapestry5.tree.TreeModel;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.UUID;
 
@@ -97,9 +98,19 @@ public class Stuff
     }
 
     public static TreeModel<Stuff> createTreeModel()
+    {
+        return createTreeModel(Stuff.ROOT.children);
+    }
+
+    public static TreeModel<Stuff> createEmptyTreeModel()
+    {
+        return createTreeModel(Collections.emptyList());
+    }
+
+    private static TreeModel<Stuff> createTreeModel(List<Stuff> children)
     {
         ValueEncoder<Stuff> encoder = new StuffValueEncoder();
 
-        return new DefaultTreeModel<Stuff>(encoder, new 
StuffTreeModelAdapter(), Stuff.ROOT.children);
+        return new DefaultTreeModel<Stuff>(encoder, new 
StuffTreeModelAdapter(), children);
     }
 }
diff --git 
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
 
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
index 348118a36..a121afb37 100644
--- 
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
+++ 
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
@@ -129,6 +129,8 @@ public class Index
 
                     new Item("TreeSelectionDemo", "Tree Component Selection 
Demo", "Demo of Selection with Tree Component"),
 
+                    new Item("TreeNoRootsDemo", "Tree Component No Roots 
Demo", "Demo of No Roots with Tree Component"),
+
                     new Item("InvalidExpressionInDynamicTemplate", "Invalid 
Dynamic Expression",
                             "Invalid expression in a Dynamic Template"),
 
diff --git 
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/TreeNoRootsDemo.java
 
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/TreeNoRootsDemo.java
new file mode 100644
index 000000000..c4a085984
--- /dev/null
+++ 
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/TreeNoRootsDemo.java
@@ -0,0 +1,31 @@
+// Copyright 2011 The Apache Software Foundation
+//
+// 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 org.apache.tapestry5.integration.app1.pages;
+
+import org.apache.tapestry5.annotations.InjectComponent;
+import org.apache.tapestry5.corelib.components.Tree;
+import org.apache.tapestry5.integration.app1.Stuff;
+import org.apache.tapestry5.tree.TreeModel;
+
+public class TreeNoRootsDemo
+{
+    @InjectComponent
+    private Tree tree;
+
+    public TreeModel<Stuff> getStuffModel()
+    {
+        return Stuff.createEmptyTreeModel();
+    }
+}
diff --git 
a/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/TreeNoRootsDemo.tml
 
b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/TreeNoRootsDemo.tml
new file mode 100644
index 000000000..32e587ade
--- /dev/null
+++ 
b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/TreeNoRootsDemo.tml
@@ -0,0 +1,7 @@
+<t:border xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd";>
+
+  <h1>Tree No Roots Demo</h1>
+
+  <t:tree class="test-hook" t:id="tree" model="stuffModel"/>
+
+</t:border>
\ No newline at end of file

Reply via email to