001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing,
013     * software distributed under the License is distributed on an
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     * KIND, either express or implied.  See the License for the
016     * specific language governing permissions and limitations
017     * under the License.
018     */
019    
020    package org.tynamo.test;
021    
022    import com.gargoylesoftware.htmlunit.ElementNotFoundException;
023    import com.gargoylesoftware.htmlunit.WebClient;
024    import com.gargoylesoftware.htmlunit.html.HtmlForm;
025    import com.gargoylesoftware.htmlunit.html.HtmlInput;
026    import com.gargoylesoftware.htmlunit.html.HtmlPage;
027    import org.mortbay.jetty.Connector;
028    import org.mortbay.jetty.Handler;
029    import org.mortbay.jetty.Server;
030    import org.mortbay.jetty.handler.DefaultHandler;
031    import org.mortbay.jetty.handler.HandlerCollection;
032    import org.mortbay.jetty.nio.SelectChannelConnector;
033    import org.mortbay.jetty.webapp.WebAppContext;
034    import org.mortbay.resource.ResourceCollection;
035    import org.testng.annotations.BeforeClass;
036    import org.testng.annotations.BeforeTest;
037    
038    import java.io.IOException;
039    import java.util.List;
040    
041    import static com.gargoylesoftware.htmlunit.WebAssert.assertTextNotPresent;
042    import static com.gargoylesoftware.htmlunit.WebAssert.assertTextPresent;
043    import static org.testng.Assert.*;
044    
045    public abstract class AbstractContainerTest
046    {
047            protected static PauseableServer server;
048    
049            protected static final int port = 8180;
050    
051            protected static final String BASEURI = "http://localhost:" + port + "/";
052    
053            protected final WebClient webClient = new WebClient();
054    
055            static String errorText = "You must correct the following errors before you may continue";
056    
057            @BeforeClass
058            public void startContainer() throws Exception
059            {
060                    if (server == null)
061                    {
062                            server = new PauseableServer();
063                            Connector connector = new SelectChannelConnector();
064                            connector.setPort(port);
065                            server.setConnectors(new Connector[]{connector});
066    
067                            HandlerCollection handlers = new HandlerCollection();
068                            handlers.setHandlers(new Handler[]{buildContext(), new DefaultHandler()});
069                            server.setHandler(handlers);
070                            server.start();
071                            assertTrue(server.isStarted());
072                    }
073            }
074    
075            /**
076             * Non-abstract hook method (with a default implementation) to allow subclasses to provide their own WebAppContext instance.
077             * @return a WebAppContext
078             */
079            public WebAppContext buildContext()
080            {
081                    WebAppContext context = new WebAppContext("src/main/webapp", "/");
082                    ResourceCollection resourceCollection = new ResourceCollection(new String[]{"src/main/webapp", "src/test/webapp"});
083                    context.setBaseResource(resourceCollection);
084    
085                    /**
086                     * like -Dorg.mortbay.jetty.webapp.parentLoaderPriority=true
087                     * Sets the classloading model for the context to avoid an strange "ClassNotFoundException: org.slf4j.Logger"
088                     */
089                    context.setParentLoaderPriority(true);
090                    return context;
091            }
092    
093            /**
094             * Hook method which is called during setup phase, before the first request.
095             * It allows subclasses to modify the  webClient, such as for disabling javascript
096             */
097            @BeforeTest
098            public void configureWebClient()
099            {
100                    webClient.setThrowExceptionOnFailingStatusCode(true);
101            }
102    
103            public void pauseServer(boolean paused)
104            {
105                    if (server != null) server.pause(paused);
106            }
107    
108            public static class PauseableServer extends Server
109            {
110                    public synchronized void pause(boolean paused)
111                    {
112                            try
113                            {
114                                    if (paused) for (Connector connector : getConnectors())
115                                            connector.stop();
116                                    else for (Connector connector : getConnectors())
117                                            connector.start();
118                            } catch (Exception e)
119                            {
120                            }
121                    }
122            }
123    
124            /**
125             * Verifies that the specified xpath is somewhere on the page.
126             *
127             * @param page
128             * @param xpath
129             */
130            protected void assertXPathPresent(HtmlPage page, String xpath)
131            {
132                    String message = "XPath not present: " + xpath;
133                    List list = page.getByXPath(xpath);
134                    if (list.isEmpty()) fail(message);
135                    assertNotNull(list.get(0), message);
136            }
137    
138            /**
139             * Verifies that the specified xpath does NOT appear anywhere on the page.
140             *
141             * @param page
142             * @param xpath
143             */
144            protected void assertXPathNotPresent(HtmlPage page, String xpath)
145            {
146                    if (!page.getByXPath(xpath).isEmpty()) fail("XPath IS present: " + xpath);
147            }
148    
149    
150            protected HtmlPage clickLink(HtmlPage page, String linkText)
151            {
152                    try
153                    {
154                            return (HtmlPage) page.getFirstAnchorByText(linkText).click();
155                    } catch (ElementNotFoundException e)
156                    {
157                            fail("Couldn't find a link with text '" + linkText + "' on page " + page);
158                    } catch (IOException e)
159                    {
160                            fail("Clicking on link '" + linkText + "' on page " + page + " failed because of: ", e);
161                    }
162                    return null;
163            }
164    
165            protected HtmlPage clickButton(HtmlPage page, String buttonId) throws IOException
166            {
167                    return page.getElementById(buttonId).click();
168            }
169    
170            protected HtmlPage clickButton(HtmlForm form, String buttonValue) throws IOException
171            {
172                    try
173                    {
174                            return form.<HtmlInput>getInputByValue(buttonValue).click();
175                    } catch (ElementNotFoundException e)
176                    {
177                            try
178                            {
179                                    return form.getButtonByName(buttonValue).click();
180                            } catch (ElementNotFoundException e1)
181                            {
182                                    fail("Couldn't find a button with text/name '" + buttonValue + "' on form '" + form.getNameAttribute() +
183                                                    "'");
184                            }
185                    }
186                    return null;
187            }
188    
189            protected void assertErrorTextPresent(HtmlPage page)
190            {
191                    assertTextPresent(page, errorText);
192            }
193    
194            protected void assertErrorTextNotPresent(HtmlPage page)
195            {
196                    assertTextNotPresent(page, errorText);
197            }
198    
199    }