SecuredPage tests, now navigationPanel and logout link are tested

git-svn-id: https://svn.apache.org/repos/asf/karaf/sandbox/webconsole/trunk@1165611 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/core/src/main/java/org/apache/karaf/webconsole/core/brand/DefaultBrandProvider.java b/core/src/main/java/org/apache/karaf/webconsole/core/brand/DefaultBrandProvider.java
index a52cfbe..3243e52 100644
--- a/core/src/main/java/org/apache/karaf/webconsole/core/brand/DefaultBrandProvider.java
+++ b/core/src/main/java/org/apache/karaf/webconsole/core/brand/DefaultBrandProvider.java
@@ -16,6 +16,7 @@
  */
 package org.apache.karaf.webconsole.core.brand;
 
+import java.io.Serializable;
 import java.util.Collections;
 import java.util.List;
 
@@ -25,7 +26,7 @@
 import org.apache.wicket.behavior.SimpleAttributeModifier;
 import org.apache.wicket.markup.html.image.Image;
 
-public class DefaultBrandProvider implements BrandProvider {
+public class DefaultBrandProvider implements BrandProvider, Serializable /* for tests mainly */ {
 
     public Image getHeaderImage(String imageId) {
         Image image = new Image(imageId, new ResourceReference(BasePage.class, "images/karaf-logo.png"));
diff --git a/core/src/main/java/org/apache/karaf/webconsole/core/page/SecuredPage.java b/core/src/main/java/org/apache/karaf/webconsole/core/page/SecuredPage.java
index 6aeabbe..86e186c 100644
--- a/core/src/main/java/org/apache/karaf/webconsole/core/page/SecuredPage.java
+++ b/core/src/main/java/org/apache/karaf/webconsole/core/page/SecuredPage.java
@@ -24,7 +24,6 @@
 import org.apache.wicket.Session;
 import org.apache.wicket.authorization.strategies.role.annotations.AuthorizeInstantiation;
 import org.apache.wicket.markup.html.link.Link;
-import org.apache.wicket.markup.html.panel.FeedbackPanel;
 import org.apache.wicket.model.LoadableDetachableModel;
 import org.ops4j.pax.wicket.api.PaxWicketBean;
 
@@ -45,8 +44,6 @@
             }
         }));
 
-        add(new FeedbackPanel("feedback"));
-
         add(new Link<Void>("logoutLink") {
             @Override
             public void onClick() {
diff --git a/core/src/main/java/org/apache/karaf/webconsole/core/page/SidebarPage.java b/core/src/main/java/org/apache/karaf/webconsole/core/page/SidebarPage.java
index 0af2cb9..48e6f68 100644
--- a/core/src/main/java/org/apache/karaf/webconsole/core/page/SidebarPage.java
+++ b/core/src/main/java/org/apache/karaf/webconsole/core/page/SidebarPage.java
@@ -18,6 +18,7 @@
 
 import org.apache.karaf.webconsole.core.internal.SidebarPanel;
 import org.apache.karaf.webconsole.core.navigation.SidebarProvider;
+import org.apache.wicket.markup.html.panel.FeedbackPanel;
 import org.apache.wicket.markup.html.panel.Panel;
 
 /**
@@ -28,6 +29,10 @@
 
     private Panel sidebar;
 
+    public SidebarPage() {
+        add(new FeedbackPanel("feedback"));
+    }
+
     protected void setSidebarProvider(SidebarProvider provider) {
         if (sidebar == null) {
             sidebar = new SidebarPanel("sidebar", provider);
diff --git a/core/src/main/java/org/apache/karaf/webconsole/core/page/SinglePage.java b/core/src/main/java/org/apache/karaf/webconsole/core/page/SinglePage.java
index 6e1408e..ea70233 100644
--- a/core/src/main/java/org/apache/karaf/webconsole/core/page/SinglePage.java
+++ b/core/src/main/java/org/apache/karaf/webconsole/core/page/SinglePage.java
@@ -16,13 +16,15 @@
  */
 package org.apache.karaf.webconsole.core.page;
 
+import org.apache.wicket.markup.html.panel.FeedbackPanel;
+
 /**
  * Page which body uses all available space - all screen width.
  */
 public class SinglePage extends SecuredPage {
 
     public SinglePage() {
-        super();
+        add(new FeedbackPanel("feedback"));
     }
 
 }
diff --git a/core/src/test/java/org/apache/karaf/webconsole/core/page/SecuredPageTest.java b/core/src/test/java/org/apache/karaf/webconsole/core/page/SecuredPageTest.java
new file mode 100644
index 0000000..d1f8117
--- /dev/null
+++ b/core/src/test/java/org/apache/karaf/webconsole/core/page/SecuredPageTest.java
@@ -0,0 +1,221 @@
+/*
+ * 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.karaf.webconsole.core.page;
+
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.createStrictMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.karaf.webconsole.core.BasePage;
+import org.apache.karaf.webconsole.core.WebConsoleTest;
+import org.apache.karaf.webconsole.core.brand.DefaultBrandProvider;
+import org.apache.karaf.webconsole.core.navigation.ConsoleTabProvider;
+import org.apache.karaf.webconsole.core.test.AlwaysAuthenticatedWebSession;
+import org.apache.karaf.webconsole.core.test.LinkAnswer;
+import org.apache.karaf.webconsole.core.test.LinksAnswer;
+import org.apache.wicket.Page;
+import org.apache.wicket.authentication.AuthenticatedWebSession;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.util.tester.WicketTester;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.BlockJUnit4ClassRunner;
+
+/**
+ * Test secured page and navigation rendering.
+ */
+@RunWith(BlockJUnit4ClassRunner.class)
+public class SecuredPageTest extends WebConsoleTest {
+
+    /**
+     * Test logout link behavior.
+     */
+    @Test
+    public void testLogout() {
+        WicketTester tester = new WicketTester(application);
+
+        tester.startPage(SecuredPage.class);
+        tester.clickLink("logoutLink");
+        tester.assertRenderedPage(LoginPage.class);
+    }
+
+    /**
+     * Test only one tab without children.
+     */
+    @Test
+    public void testOneTab() {
+        Map<String, Object> values = new HashMap<String, Object>();
+
+        values.put("brandProvider", new DefaultBrandProvider());
+
+        List<ConsoleTabProvider> tabs = new ArrayList<ConsoleTabProvider>();
+
+        SerializableConsoleTabProvider mock = createStrictMock(SerializableConsoleTabProvider.class);
+        expect(mock.getModuleLink(anyString(), anyString())).andAnswer(new LinkAnswer("test", BasePage.class));
+        expect(mock.getItems(anyString(), anyString())).andReturn(emptyLinkList());
+
+        tabs.add(mock);
+        values.put("tabs", tabs);
+        injector.setValues(values);
+
+        replay(mock);
+
+        WicketTester tester = new WicketTester(application);
+        tester.startPage(SecuredPage.class);
+
+        assertTabs(tester, tabs);
+        assertTabLink(tester, 0, "test", BasePage.class);
+
+        verify(mock);
+    }
+
+    /**
+     * Test only one tab, but with two children.
+     */
+    @Test
+    public void testOneTabWithChildren() {
+        Map<String, Object> values = new HashMap<String, Object>();
+
+        values.put("brandProvider", new DefaultBrandProvider());
+
+        List<ConsoleTabProvider> tabs = new ArrayList<ConsoleTabProvider>();
+
+        SerializableConsoleTabProvider mock = createStrictMock(SerializableConsoleTabProvider.class);
+        expect(mock.getModuleLink(anyString(), anyString())).andAnswer(new LinkAnswer("test", BasePage.class));
+        LinksAnswer answer = new LinksAnswer();
+        answer.addLink("A1", SecuredPage.class);
+        answer.addLink("B1", SidebarPage.class);
+        expect(mock.getItems(anyString(), anyString())).andAnswer(answer);
+
+        tabs.add(mock);
+        values.put("tabs", tabs);
+        injector.setValues(values);
+
+        replay(mock);
+
+        WicketTester tester = new WicketTester(application);
+        tester.startPage(SecuredPage.class);
+
+        assertTabs(tester, tabs);
+        assertTabLink(tester, 0, "test", BasePage.class, answer.getPageLinks());
+        tester.assertLabel("navigationPanel:tabs:0:moduleLinks:0:link:label", "A1");
+        tester.assertLabel("navigationPanel:tabs:0:moduleLinks:1:link:label", "B1");
+
+        verify(mock);
+    }
+
+    /**
+     * Test four tabs without children.
+     */
+    @Test
+    public void testTwoTabs() {
+        Map<String, Object> values = new HashMap<String, Object>();
+
+        values.put("brandProvider", new DefaultBrandProvider());
+
+        List<ConsoleTabProvider> tabs = new ArrayList<ConsoleTabProvider>();
+
+        SerializableConsoleTabProvider mock = createStrictMock(SerializableConsoleTabProvider.class);
+        expect(mock.getModuleLink(anyString(), anyString())).andAnswer(new LinkAnswer("test1", BasePage.class));
+        expect(mock.getItems(anyString(), anyString())).andReturn(emptyLinkList());
+        replay(mock);
+        tabs.add(mock);
+
+        mock = createStrictMock(SerializableConsoleTabProvider.class);
+        expect(mock.getModuleLink(anyString(), anyString())).andAnswer(new LinkAnswer("test2", SecuredPage.class));
+        expect(mock.getItems(anyString(), anyString())).andReturn(emptyLinkList());
+        replay(mock);
+        tabs.add(mock);
+
+        mock = createStrictMock(SerializableConsoleTabProvider.class);
+        expect(mock.getModuleLink(anyString(), anyString())).andAnswer(new LinkAnswer("test3", SinglePage.class));
+        expect(mock.getItems(anyString(), anyString())).andReturn(emptyLinkList());
+        replay(mock);
+        tabs.add(mock);
+
+
+        mock = createStrictMock(SerializableConsoleTabProvider.class);
+        expect(mock.getModuleLink(anyString(), anyString())).andAnswer(new LinkAnswer("test4", SidebarPage.class));
+        expect(mock.getItems(anyString(), anyString())).andReturn(emptyLinkList());
+        replay(mock);
+        tabs.add(mock);
+
+        values.put("tabs", tabs);
+        injector.setValues(values);
+
+        WicketTester tester = new WicketTester(application);
+        tester.startPage(SecuredPage.class);
+
+        assertTabs(tester, tabs);
+        assertTabLink(tester, 0, "test1", BasePage.class);
+        assertTabLink(tester, 1, "test2", SecuredPage.class);
+        assertTabLink(tester, 2, "test3", SinglePage.class);
+        assertTabLink(tester, 3, "test4", SidebarPage.class);
+
+        verify(mock);
+    }
+
+    // additional asserts
+
+    private void assertTabs(WicketTester tester, List<ConsoleTabProvider> tabs) {
+        tester.assertListView("navigationPanel:tabs", tabs);
+    }
+
+    private void assertTabLink(WicketTester tester, int position, String label, Class<? extends WebPage> page) {
+        assertTabLink(tester, position, label, page, Collections.<Link<Page>>emptyList());
+    }
+
+    private void assertTabLink(WicketTester tester, int position, String label, Class<? extends WebPage> page, List<Link<Page>> children) {
+        tester.assertLabel("navigationPanel:tabs:" + position + ":moduleLink:moduleLabel", label);
+        tester.assertBookmarkablePageLink("navigationPanel:tabs:" + position + ":moduleLink", page, "");
+        tester.assertListView("navigationPanel:tabs:" + position + ":moduleLinks", children);
+    }
+
+    @Override
+    protected Class<? extends AuthenticatedWebSession> getWebSessionClass() {
+        return AlwaysAuthenticatedWebSession.class;
+    }
+
+    /**
+     * Easy mock argument matcher.
+     */
+    private static String anyString() {
+        return anyObject();
+    }
+
+    /**
+     * Empty list stub.
+     */
+    private static List<Link<Page>> emptyLinkList() {
+        return Collections.<Link<Page>>emptyList();
+    }
+
+    // Marker interface for tests, normally serialization is controlled by paxwicket
+    // as ConsoleTabProviders are OSGi services.
+    interface SerializableConsoleTabProvider extends Serializable, ConsoleTabProvider {}
+
+}
diff --git a/core/src/test/java/org/apache/karaf/webconsole/core/test/BaseLinkAnswer.java b/core/src/test/java/org/apache/karaf/webconsole/core/test/BaseLinkAnswer.java
new file mode 100644
index 0000000..bc4c00e
--- /dev/null
+++ b/core/src/test/java/org/apache/karaf/webconsole/core/test/BaseLinkAnswer.java
@@ -0,0 +1,39 @@
+/*
+ * 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.karaf.webconsole.core.test;
+
+import static org.easymock.EasyMock.getCurrentArguments;
+
+import java.io.Serializable;
+
+import org.easymock.IAnswer;
+
+/**
+ * Base class for link answers in many providers..
+ */
+public abstract class BaseLinkAnswer<T> implements IAnswer<T>, Serializable {
+
+    public final T answer() throws Throwable {
+        String linkId = (String) getCurrentArguments()[0];
+        String labelId = (String) getCurrentArguments()[1];
+
+        return createAnswer(linkId, labelId);
+    }
+
+    protected abstract T createAnswer(String linkId, String labelId) throws Throwable;
+
+}
diff --git a/core/src/test/java/org/apache/karaf/webconsole/core/test/LinkAnswer.java b/core/src/test/java/org/apache/karaf/webconsole/core/test/LinkAnswer.java
new file mode 100644
index 0000000..d46768e
--- /dev/null
+++ b/core/src/test/java/org/apache/karaf/webconsole/core/test/LinkAnswer.java
@@ -0,0 +1,39 @@
+/*
+ * 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.karaf.webconsole.core.test;
+
+import org.apache.karaf.webconsole.core.util.LinkUtils;
+import org.apache.wicket.Page;
+import org.apache.wicket.markup.html.link.Link;
+
+/**
+ * Easy mock answer to return prepared link.
+ */
+public class LinkAnswer extends BaseLinkAnswer<Link<Page>> {
+
+    private String label;
+    private Class<? extends Page> page;
+
+    public LinkAnswer(String label, Class<? extends Page> page) {
+        this.label = label;
+        this.page = page;
+    }
+
+    protected Link<Page> createAnswer(String linkId, String labelId) throws Throwable {
+        return LinkUtils.createPageLink(linkId, labelId, label, page);
+    }
+}
\ No newline at end of file
diff --git a/core/src/test/java/org/apache/karaf/webconsole/core/test/LinksAnswer.java b/core/src/test/java/org/apache/karaf/webconsole/core/test/LinksAnswer.java
new file mode 100644
index 0000000..e380818
--- /dev/null
+++ b/core/src/test/java/org/apache/karaf/webconsole/core/test/LinksAnswer.java
@@ -0,0 +1,52 @@
+/*
+ * 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.karaf.webconsole.core.test;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.karaf.webconsole.core.util.LinkUtils;
+import org.apache.wicket.Page;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.link.Link;
+
+/**
+ * An easy mock answer which returns list of links.
+ */
+public class LinksAnswer extends BaseLinkAnswer<List<Link<Page>>> {
+
+    private Map<String, Class<? extends WebPage>> links = new LinkedHashMap<String, Class<? extends WebPage>>();
+    private List<Link<Page>> pageLinks;
+
+    public void addLink(String label, Class<? extends WebPage> page) {
+        links.put(label, page);
+    }
+
+    @Override
+    protected List<Link<Page>> createAnswer(String linkId, String labelId) throws Throwable {
+        pageLinks = new ArrayList<Link<Page>>();
+
+        for (String label : this.links.keySet()) {
+            pageLinks.add(LinkUtils.createPageLink(linkId, labelId, label, this.links.get(label)));
+        }
+
+        return pageLinks;
+    }
+
+}