diff --git a/mock/pom.xml b/mock/pom.xml index 6b35098..1207e69 100644 --- a/mock/pom.xml +++ b/mock/pom.xml @@ -65,6 +65,17 @@ provided + + junit + junit + + + + org.jboss.arquillian + arquillian-junit + + + org.jboss.spec.javax.servlet jboss-servlet-api_3.0_spec @@ -112,6 +123,46 @@ + + + + jbossas-remote-6 + + + org.jboss.arquillian.container + arquillian-jbossas-remote-6 + ${arquillian.version} + test + + + + + org.jboss.spec + jboss-javaee-6.0 + pom + provided + + + + org.jboss.jbossas + jboss-as-client + pom + test + + + + + + src/test/resources + + + + + src/test/resources-jbossas + + + + diff --git a/mock/src/main/java/org/jboss/seam/wicket/mock/SeamTestRequestCycle.java b/mock/src/main/java/org/jboss/seam/wicket/mock/SeamTestRequestCycle.java new file mode 100644 index 0000000..aa38486 --- /dev/null +++ b/mock/src/main/java/org/jboss/seam/wicket/mock/SeamTestRequestCycle.java @@ -0,0 +1,67 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2010, Red Hat, Inc., and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * 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.jboss.seam.wicket.mock; + +import org.apache.wicket.Response; +import org.apache.wicket.protocol.http.WebApplication; +import org.apache.wicket.protocol.http.WebRequest; +import org.jboss.seam.wicket.SeamRequestCycle; + +/** + * Simple request cycle with manual control of detaching conversation context and rest of wicket stuff. + * @author Marek + * Smigielski + * + */ +public class SeamTestRequestCycle extends SeamRequestCycle +{ + private boolean detach; + + + public SeamTestRequestCycle(WebApplication application, WebRequest request, Response response,boolean detach) + { + super(application, request, response); + this.detach=detach; + } + + /** Detach only when you know that conversation scope isn't need any more. + * @see org.jboss.seam.wicket.SeamRequestCycle#detach() + */ + @Override + public void detach() + { + if(isDetach()){ + super.detach(); + } + } + + public void superDetach() + { + super.detach(); + } + + + public boolean isDetach() + { + return detach; + } + + public void setDetach(boolean detach) + { + this.detach = detach; + } +} diff --git a/mock/src/main/java/org/jboss/seam/wicket/mock/SeamWicketTester.java b/mock/src/main/java/org/jboss/seam/wicket/mock/SeamWicketTester.java index f374a5b..7128037 100644 --- a/mock/src/main/java/org/jboss/seam/wicket/mock/SeamWicketTester.java +++ b/mock/src/main/java/org/jboss/seam/wicket/mock/SeamWicketTester.java @@ -1,16 +1,25 @@ package org.jboss.seam.wicket.mock; +import javax.inject.Inject; +import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.wicket.Page; +import org.apache.wicket.Request; +import org.apache.wicket.RequestCycle; +import org.apache.wicket.Response; import org.apache.wicket.protocol.http.HttpSessionStore; import org.apache.wicket.protocol.http.SecondLevelCacheSessionStore; -import org.apache.wicket.protocol.http.SecondLevelCacheSessionStore.IPageStore; +import org.apache.wicket.protocol.http.WebRequest; +import org.apache.wicket.protocol.http.WebRequestCycle; import org.apache.wicket.protocol.http.WebResponse; +import org.apache.wicket.protocol.http.SecondLevelCacheSessionStore.IPageStore; import org.apache.wicket.session.ISessionStore; import org.apache.wicket.util.tester.DummyHomePage; import org.apache.wicket.util.tester.WicketTester; import org.jboss.seam.wicket.SeamApplication; +import org.jboss.seam.wicket.SeamRequestCycle; +import org.jboss.weld.context.http.HttpRequestContext; /** * A helper class for testing Seam Pages containing CDI beans. The @@ -27,12 +36,82 @@ public class SeamWicketTester extends WicketTester { + @Inject + HttpRequestContext requestContext; + + /* + * Override because there is need for manualy restart request context in + * wicket tester. + * + * @see + * org.apache.wicket.protocol.http.MockWebApplication#setupRequestAndResponse + * (boolean) + */ + @Override + public WebRequestCycle setupRequestAndResponse(boolean isAjax) + { + if (requestContext.isActive()) + { + endRequest(getServletRequest()); + } + WebRequestCycle webRequestCycle = super.setupRequestAndResponse(isAjax); + startRequest(getServletRequest()); + return webRequestCycle; + } + + /* + * Start the request, providing a data store which will last the lifetime of + * the request + */ + + public void startRequest(ServletRequest servletRequest) + { + // Associate the store with the context and acticate the context + requestContext.associate(servletRequest); + requestContext.activate(); + } + + /* + * End the request, providing the same data store as was used to start the + * request + */ + public void endRequest(ServletRequest servletRequest) + { + try + { + /* + * Invalidate the request (all bean instances will be scheduled for + * destruction) + */ + requestContext.invalidate(); + /* + * Deactivate the request, causing all bean instances to be destroyed + * (as the context is invalid) + */ + requestContext.deactivate(); + } + finally + { + + /* + * Ensure that whatever happens we dissociate to prevent any memory + * leaks + */ + requestContext.dissociate(servletRequest); + } + } + /** * Default dummy seam web application for testing. Uses * {@link HttpSessionStore} to store pages and the Session. */ public static class DummySeamApplication extends SeamApplication { + // For manually detaching wicket request object and conversation scope + private SeamTestRequestCycle seamTestRequestCycle; + + private boolean manuallyDetach = false; + /** * @see org.apache.wicket.Application#getHomePage() */ @@ -64,6 +143,53 @@ protected void outputDevelopmentModeWarning() { // do nothing } + + /** + * Override to return Seam-specific request cycle with manually detach + * control. + * + * @see SeamRequestCycle + */ + @Override + public RequestCycle newRequestCycle(final Request request, final Response response) + { + seamTestRequestCycle = new SeamTestRequestCycle(this, (WebRequest) request, (WebResponse) response, !manuallyDetach); + return seamTestRequestCycle; + } + + /** + * Detach wicket request object and conversation scope. Should be call + * after all tests on current page. + */ + public void detach() + { + if (seamTestRequestCycle != null) + { + seamTestRequestCycle.superDetach(); + } + } + + /** + * Whether wicket request and conversation scope objects should be + * manually detach or will be detached immediate after rendering page. + * + * @return + */ + public boolean isManuallyDetach() + { + return !seamTestRequestCycle.isDetach(); + } + + /** + * + * @param manuallyDetach wicket request and conversation scope objects + * instead of immediate after rendering page. + */ + public void setManuallyDetach(boolean manuallyDetach) + { + this.manuallyDetach = manuallyDetach; + this.seamTestRequestCycle.setDetach(!manuallyDetach); + } } /** diff --git a/mock/src/test/java/org/jboss/seam/wicket/test/application/AbstractObjectProducer.java b/mock/src/test/java/org/jboss/seam/wicket/test/application/AbstractObjectProducer.java new file mode 100644 index 0000000..c252064 --- /dev/null +++ b/mock/src/test/java/org/jboss/seam/wicket/test/application/AbstractObjectProducer.java @@ -0,0 +1,71 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2010, Red Hat, Inc., and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * 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.jboss.seam.wicket.test.application; + +import java.util.LinkedList; +import java.util.List; + +/** + * Abstract object producer which can be injected and control from test class. + * + * @author Marek Smigielski + * + */ +public class AbstractObjectProducer +{ + + protected List localMessages = new LinkedList(); + + public AbstractObjectProducer() + { + super(); + } + + /** + * Returning next message from the list + * @return StringObject wrapping text message + */ + public StringObject getMessage(){ + if (localMessages.size() > 0) + { + String value = localMessages.remove(0); + return new StringObject().setValue(value); + } + return new StringObject(); + } + + /** + * Get local message list for manipulation. List implements LinkedList. + * + * @return local message list + */ + public List getLocalMessages() + { + return localMessages; + } + + /** + * Add single text message to the end of the list. + * + * @param text + */ + public void add(String text) + { + localMessages.add(text); + } + +} \ No newline at end of file diff --git a/mock/src/test/java/org/jboss/seam/wicket/test/application/ConversationObjectProducer.java b/mock/src/test/java/org/jboss/seam/wicket/test/application/ConversationObjectProducer.java new file mode 100644 index 0000000..7533fc3 --- /dev/null +++ b/mock/src/test/java/org/jboss/seam/wicket/test/application/ConversationObjectProducer.java @@ -0,0 +1,57 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2010, Red Hat, Inc., and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * 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.jboss.seam.wicket.test.application; + + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.ConversationScoped; +import javax.enterprise.inject.Produces; +import javax.inject.Inject; + +import org.jboss.logging.Logger; + +/** + * Request object producer which can be injected and control from test class. + * + * @author Marek + * Smigielski + * + */ +@ApplicationScoped +public class ConversationObjectProducer extends AbstractObjectProducer +{ + + @Inject + Logger log; + + /** + * Produces text message retrieving first element from localMessages. If local + * message list is null or empty returning empty string. + * + * @return simple text message + */ + @Produces + @ConversationScopeQualifier + @ConversationScoped + public StringObject messageProducer() + { + StringObject stringObject = getMessage(); + log.info("Producing conversation object: "+stringObject.getValue()); + return stringObject; + } + +} diff --git a/mock/src/test/java/org/jboss/seam/wicket/test/application/ConversationScopeQualifier.java b/mock/src/test/java/org/jboss/seam/wicket/test/application/ConversationScopeQualifier.java new file mode 100644 index 0000000..c08dd28 --- /dev/null +++ b/mock/src/test/java/org/jboss/seam/wicket/test/application/ConversationScopeQualifier.java @@ -0,0 +1,37 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2010, Red Hat, Inc., and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * 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.jboss.seam.wicket.test.application; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.ElementType.PARAMETER; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.inject.Qualifier; + +@Qualifier +@Retention(RUNTIME) +@Target( { TYPE, METHOD, FIELD, PARAMETER }) +public @interface ConversationScopeQualifier +{ + +} \ No newline at end of file diff --git a/mock/src/test/java/org/jboss/seam/wicket/test/application/ConversationTestPage.java b/mock/src/test/java/org/jboss/seam/wicket/test/application/ConversationTestPage.java new file mode 100644 index 0000000..968d584 --- /dev/null +++ b/mock/src/test/java/org/jboss/seam/wicket/test/application/ConversationTestPage.java @@ -0,0 +1,93 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2010, Red Hat, Inc., and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * 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.jboss.seam.wicket.test.application; + +import javax.enterprise.context.Conversation; +import javax.enterprise.inject.Instance; +import javax.inject.Inject; + +import org.apache.wicket.markup.html.WebPage; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.link.Link; +import org.apache.wicket.model.Model; +import org.apache.wicket.util.value.Count; +import org.jboss.logging.Logger; + +/** + * Simple wicket test page for conversation object injection. Start long running + * conversation immediate after adding all components + * + * @author Marek + * Smigielski + */ +public class ConversationTestPage extends WebPage +{ + @Inject + Logger log; + + @Inject + @ConversationScopeQualifier + StringObject stringObject; + + @Inject + @ConversationScopeQualifier + Instance stringObjectInstance; + + @Inject + Conversation conversation; + + public ConversationTestPage() + { + log.info("Rendering test page"); + + // headerLabel is CDI object cached in wicket + Label headerLabel = new Label("headerLabel", new Model(stringObject.getValue())); + headerLabel.setEscapeModelStrings(false); + add(headerLabel); + + // spanLabel is CDI object retrieved dynamically every request + Label spanLabel = new Label("spanLabel", new Model() + { + @Override + public String getObject() + { + return stringObjectInstance.get().getValue(); + } + }); + spanLabel.setEscapeModelStrings(false); + add(spanLabel); + + // Counter is wicket managed object. + final Count count = new Count(); // simple counter object + Link refresh = new Link("refresh") + { + public void onClick() + { + count.increment(); + } + }; + refresh.add(new Label("number", new Model() + { + public String getObject() + { + return Integer.toString(count.getCount()); + } + })); + add(refresh); + conversation.begin(); + } +} diff --git a/mock/src/test/java/org/jboss/seam/wicket/test/application/EmptyPage.java b/mock/src/test/java/org/jboss/seam/wicket/test/application/EmptyPage.java new file mode 100644 index 0000000..18110cc --- /dev/null +++ b/mock/src/test/java/org/jboss/seam/wicket/test/application/EmptyPage.java @@ -0,0 +1,28 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2010, Red Hat, Inc., and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * 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.jboss.seam.wicket.test.application; + +import org.apache.wicket.markup.html.WebPage; + +/** + * Simple wicket empty test page + * @author Marek Smigielski + */ +public class EmptyPage extends WebPage +{ + +} diff --git a/mock/src/test/java/org/jboss/seam/wicket/test/application/RequestObjectProducer.java b/mock/src/test/java/org/jboss/seam/wicket/test/application/RequestObjectProducer.java new file mode 100644 index 0000000..d4b6627 --- /dev/null +++ b/mock/src/test/java/org/jboss/seam/wicket/test/application/RequestObjectProducer.java @@ -0,0 +1,57 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2010, Red Hat, Inc., and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * 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.jboss.seam.wicket.test.application; + + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.RequestScoped; +import javax.enterprise.inject.Produces; +import javax.inject.Inject; + +import org.jboss.logging.Logger; + +/** + * Request object producer which can be injected and control from test class. + * + * @author Marek + * Smigielski + * + */ +@ApplicationScoped +public class RequestObjectProducer extends AbstractObjectProducer +{ + + @Inject + Logger log; + + /** + * Produces text message retriving first element from localMessages. If local + * message list is null or empty returning empty string. + * + * @return simple text message + */ + @Produces + @RequestScopeQualifier + @RequestScoped + public StringObject messageProducer() + { + StringObject stringObject = getMessage(); + log.info("Producing request object: "+stringObject.getValue()); + return stringObject; + } + +} diff --git a/mock/src/test/java/org/jboss/seam/wicket/test/application/RequestScopeQualifier.java b/mock/src/test/java/org/jboss/seam/wicket/test/application/RequestScopeQualifier.java new file mode 100644 index 0000000..3199f11 --- /dev/null +++ b/mock/src/test/java/org/jboss/seam/wicket/test/application/RequestScopeQualifier.java @@ -0,0 +1,21 @@ +package org.jboss.seam.wicket.test.application; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.ElementType.PARAMETER; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.inject.Qualifier; + +@Qualifier +@Retention(RUNTIME) +@Target( { TYPE, METHOD, FIELD, PARAMETER }) +public @interface RequestScopeQualifier +{ + +} \ No newline at end of file diff --git a/mock/src/test/java/org/jboss/seam/wicket/test/application/RequestTestPage.java b/mock/src/test/java/org/jboss/seam/wicket/test/application/RequestTestPage.java new file mode 100644 index 0000000..605daf5 --- /dev/null +++ b/mock/src/test/java/org/jboss/seam/wicket/test/application/RequestTestPage.java @@ -0,0 +1,80 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2010, Red Hat, Inc., and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * 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.jboss.seam.wicket.test.application; + +import javax.enterprise.inject.Instance; +import javax.inject.Inject; + +import org.apache.wicket.markup.html.WebPage; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.link.Link; +import org.apache.wicket.model.Model; +import org.apache.wicket.util.value.Count; +import org.jboss.logging.Logger; + +/** + * Simple wicket test page for request object injection + * + * @author Marek + * Smigielski + */ +public class RequestTestPage extends WebPage +{ + @Inject + Logger log; + + @Inject @RequestScopeQualifier + StringObject stringObject; + + @Inject @RequestScopeQualifier + Instance stringObjectInstance; + + public RequestTestPage() + { + log.info("Rendering test page"); + // headerLabel is CDI object cached in wicket + Label headerLabel = new Label("headerLabel", new Model(stringObject.getValue())); + headerLabel.setEscapeModelStrings(false); + add(headerLabel); + + // spanLabel is CDI object retrieved dynamically every request + Label spanLabel = new Label("spanLabel", new Model(){ + @Override + public String getObject() + { + return stringObjectInstance.get().getValue(); + } + }); + spanLabel.setEscapeModelStrings(false); + add(spanLabel); + + // Counter is wicket managed object. + final Count count = new Count(); // simple counter object + Link refresh = new Link("refresh") { + public void onClick() { + count.increment(); + } + }; + refresh.add(new Label("number", new Model() { + public String getObject() { + return Integer.toString(count.getCount()); + } + })); + add(refresh); + + } +} diff --git a/mock/src/test/java/org/jboss/seam/wicket/test/application/StringObject.java b/mock/src/test/java/org/jboss/seam/wicket/test/application/StringObject.java new file mode 100644 index 0000000..413f8cb --- /dev/null +++ b/mock/src/test/java/org/jboss/seam/wicket/test/application/StringObject.java @@ -0,0 +1,43 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2010, Red Hat, Inc., and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * 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.jboss.seam.wicket.test.application; + +import java.io.Serializable; + +import org.jboss.seam.solder.core.Veto; + +/** + * Simple object that will be produced. + * @author Marek Smigielski + */ +@Veto +public class StringObject implements Serializable +{ + String value = ""; + + public String getValue() + { + return value; + } + + public StringObject setValue(String value) + { + this.value = value; + return this; + } + +} diff --git a/mock/src/test/java/org/jboss/seam/wicket/test/core/SeamApplicationTest.java b/mock/src/test/java/org/jboss/seam/wicket/test/core/SeamApplicationTest.java new file mode 100644 index 0000000..0b55bac --- /dev/null +++ b/mock/src/test/java/org/jboss/seam/wicket/test/core/SeamApplicationTest.java @@ -0,0 +1,175 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2010, Red Hat, Inc., and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * 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.jboss.seam.wicket.test.core; + +import javax.inject.Inject; + +import org.jboss.arquillian.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.seam.wicket.SeamApplication; +import org.jboss.seam.wicket.mock.SeamWicketTester; +import org.jboss.seam.wicket.mock.SeamWicketTester.DummySeamApplication; +import org.jboss.seam.wicket.test.application.ConversationObjectProducer; +import org.jboss.seam.wicket.test.application.ConversationTestPage; +import org.jboss.seam.wicket.test.application.EmptyPage; +import org.jboss.seam.wicket.test.application.RequestObjectProducer; +import org.jboss.seam.wicket.test.application.RequestTestPage; +import org.jboss.seam.wicket.test.util.MavenArtifactResolver; +import org.jboss.seam.wicket.util.NonContextual; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Base test for wicket and seam integration. + * + * @author Marek + * Smigielski + */ +@RunWith(Arquillian.class) +public class SeamApplicationTest +{ + @Deployment + public static WebArchive createTestArchive() + { + return ShrinkWrap.create(WebArchive.class, "test.war") + .addPackage(SeamApplication.class.getPackage()) + .addPackage(RequestTestPage.class.getPackage()) + .addPackage(NonContextual.class.getPackage()) + .addPackage(SeamWicketTester.class.getPackage()) + // Page for testRenderPage + .addResource("EmptyPage.html", "WEB-INF/classes/org/jboss/seam/wicket/test/application/EmptyPage.html") + .addResource("EmptyPage.html", "WEB-INF/classes/org/jboss/seam/wicket/test/application/EmptyPageExpected.html") + // Page for testRequestScopeInjection + .addResource("RequestTestPage.html", "WEB-INF/classes/org/jboss/seam/wicket/test/application/RequestTestPage.html") + .addResource("RequestTestPageExpected.html", "WEB-INF/classes/org/jboss/seam/wicket/test/application/RequestTestPageExpected.html") + // Page for testConversationScopeInjection + .addResource("ConversationTestPage.html", "WEB-INF/classes/org/jboss/seam/wicket/test/application/ConversationTestPage.html") + .addResource("ConversationTestPageExpected.html", "WEB-INF/classes/org/jboss/seam/wicket/test/application/ConversationTestPageExpected.html") + + .addWebResource(EmptyAsset.INSTANCE, "beans.xml") + .addLibraries(MavenArtifactResolver.resolve("org.apache.wicket:wicket")) + .setWebXML("test-web.xml"); + } + + @Inject + SeamWicketTester tester; + + @Inject + RequestObjectProducer requestObjectProducer; + + @Inject + ConversationObjectProducer conversationObjectProducer; + + /** + * Test that simple rendering works fine and we get what we have expected. + * + * @throws Exception + */ + @Test + public void testRenderPage() throws Exception + { + Assert.assertNotNull(tester); + tester.startPage(EmptyPage.class); + + tester.assertRenderedPage(EmptyPage.class); + + tester.assertResultPage(EmptyPage.class, "EmptyPageExpected.html"); + } + + /** + * Test that page injection of request object works both in and out. + * + * @throws Exception + */ + @Test + public void testRequestScopeInjection() throws Exception + { + Assert.assertNotNull(tester); + // initialize request object values + requestObjectProducer.add("First request message"); + requestObjectProducer.add("Second request message"); + requestObjectProducer.add("This message is not retrived"); + + // test first request + tester.startPage(RequestTestPage.class); + tester.assertRenderedPage(RequestTestPage.class); + tester.assertResultPage(RequestTestPage.class, "RequestTestPageExpected.html"); + + // test second request + tester.clickLink("refresh"); + tester.assertRenderedPage(RequestTestPage.class); + tester.assertLabel("headerLabel", "First request message"); + tester.assertLabel("spanLabel", "Second request message"); + tester.assertLabel("refresh:number", "1"); + } + + /** + * Test that page injection of request object works both in and out. + * + * @throws Exception + */ + @Test + public void testConversationScopeInjection() throws Exception + { + Assert.assertNotNull(tester); + DummySeamApplication application = (DummySeamApplication) tester.getApplication(); + application.setManuallyDetach(true); + // initialize conversation object values + conversationObjectProducer.add("First conversation message"); + conversationObjectProducer.add("Second conversation message"); + conversationObjectProducer.add("This message is not retrived"); + + // test first request in first conversation + tester.startPage(ConversationTestPage.class); + tester.assertRenderedPage(ConversationTestPage.class); + tester.assertResultPage(ConversationTestPage.class, "ConversationTestPageExpected.html"); + // always detach request after all tests on current page + application.detach(); + // test second request in first conversation + tester.clickLink("refresh"); + + tester.assertRenderedPage(ConversationTestPage.class); + // without manually detaching the conversation scope is closed to early. + tester.assertLabel("headerLabel", "First conversation message"); + tester.assertLabel("spanLabel", "First conversation message"); + tester.assertLabel("refresh:number", "1"); + // always detach request after all tests on current page + application.detach(); + + // test first request in second conversation + tester.startPage(ConversationTestPage.class); + tester.assertRenderedPage(ConversationTestPage.class); + tester.assertLabel("headerLabel", "Second conversation message"); + tester.assertLabel("spanLabel", "Second conversation message"); + tester.assertLabel("refresh:number", "0"); + // always detach request after all tests on current page + application.detach(); + + // test second request in second conversation + tester.clickLink("refresh"); + tester.assertRenderedPage(ConversationTestPage.class); + tester.assertLabel("headerLabel", "Second conversation message"); + tester.assertLabel("spanLabel", "Second conversation message"); + tester.assertLabel("refresh:number", "1"); + // always detach request after all tests on current page + application.detach(); + } +} diff --git a/mock/src/test/java/org/jboss/seam/wicket/test/util/MavenArtifactResolver.java b/mock/src/test/java/org/jboss/seam/wicket/test/util/MavenArtifactResolver.java new file mode 100644 index 0000000..6845eed --- /dev/null +++ b/mock/src/test/java/org/jboss/seam/wicket/test/util/MavenArtifactResolver.java @@ -0,0 +1,165 @@ +package org.jboss.seam.wicket.test.util; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Resolves a maven artifact present on the test classpath. + * + * @author Stuart Douglas + * + */ +public class MavenArtifactResolver +{ + + public static File resolve(String groupId, String artifactId) + { + if (groupId == null) + { + throw new IllegalArgumentException("groupId cannot be null"); + } + if (artifactId == null) + { + throw new IllegalArgumentException("artifactId cannot be null"); + } + String path = new MavenArtifactResolver(groupId.trim(), artifactId.trim(), System.getProperty("java.class.path"), File.pathSeparatorChar, File.separatorChar).resolve(); + if (path == null) + { + throw new IllegalArgumentException("Cannot locate artifact for " + groupId + ":" + artifactId); + } + return new File(path); + } + + public static File resolve(String qualifiedArtifactId) + { + String[] segments = qualifiedArtifactId.split(":"); + if (segments.length == 2) + { + return resolve(segments[0], segments[1]); + } + else + { + throw new IllegalArgumentException("Unable to parse " + qualifiedArtifactId + " as a groupId:artifactId"); + } + } + + private final String classPathSeparatorRegex; + private final char fileSeparator; + private final String groupId; + private final String artifactId; + private final String classPath; + + MavenArtifactResolver(String groupId, String artifactId, String classPath, char pathSeparator, char fileSeparator) + { + this.groupId = groupId; + this.artifactId = artifactId; + this.classPath = classPath; + this.classPathSeparatorRegex = "[^" + pathSeparator + "]*"; + this.fileSeparator = fileSeparator; + } + + String resolve() + { + Matcher matches = createFullyQualifiedMatcher(); + if (!matches.find()) + { + matches = createUnqualifiedMatcher(); + if (!matches.find()) + { + matches = createTargetClassesMatcher(); + if (!matches.find()) + { + return null; + } + else + { + String fileName = scanForArtifact(matches); + if (fileName == null) + { + return null; + } + else + { + return fileName; + } + } + } + } + return matches.group(0); + } + + private String scanForArtifact(Matcher targetClassesMatcher) + { + // Locate all target/classes in classpath and store the path to all files + // target/ + List paths = new ArrayList(); + do + { + String path = targetClassesMatcher.group(); + File target = new File(path.substring(0, path.length() - 8)); + if (target.exists()) + { + if (!target.isDirectory()) + { + throw new IllegalStateException("Found ${project.dir}/target/ but it is not a directory!"); + } + for (File file : target.listFiles()) + { + paths.add(file.getPath()); + } + } + } + while (targetClassesMatcher.find()); + return scanForArtifact(paths); + } + + String scanForArtifact(List paths) + { + Pattern pattern = Pattern.compile(artifactId + "-[\\d+\\.]+(?:[\\-\\.]\\p{Alpha}*)?.jar$"); + for (String path : paths) + { + if (pattern.matcher(path).find()) + { + return path; + } + } + return null; + } + + /** + * Creates a matcher that returns any fully qualified matches of the form + * com/acme/acme-core/1.0/acme-core-1.0.jar. This will match + * artifacts on the classpath from the Maven repo. + */ + private Matcher createFullyQualifiedMatcher() + { + String pathString = groupId.replace('.', fileSeparator) + fileSeparator + artifactId + fileSeparator; + Pattern p = Pattern.compile(classPathSeparatorRegex + Pattern.quote(pathString) + classPathSeparatorRegex, Pattern.CASE_INSENSITIVE); + return p.matcher(classPath); + } + + /** + * Creates a matcher that returns any unqualified matches of the form + * target/acme-foo-1.0.jar. This will match artifacts on the + * classpath from the reactor. + */ + private Matcher createUnqualifiedMatcher() + { + Pattern p = Pattern.compile(classPathSeparatorRegex + Pattern.quote("target" + fileSeparator + artifactId) + classPathSeparatorRegex, Pattern.CASE_INSENSITIVE); + return p.matcher(classPath); + } + + /** + * Creates a matcher that returns any unqualified matches of the form + * target/acme-foo-1.0.jar. This locates all + * + */ + private Matcher createTargetClassesMatcher() + { + Pattern p = Pattern.compile(classPathSeparatorRegex + Pattern.quote("target" + fileSeparator + "classes") + classPathSeparatorRegex, Pattern.CASE_INSENSITIVE); + return p.matcher(classPath); + } +} diff --git a/mock/src/test/resources-jbossas/jndi.properties b/mock/src/test/resources-jbossas/jndi.properties new file mode 100644 index 0000000..a20ef47 --- /dev/null +++ b/mock/src/test/resources-jbossas/jndi.properties @@ -0,0 +1,3 @@ +java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory +java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces +java.naming.provider.url=jnp://localhost:1099 diff --git a/mock/src/test/resources-jbossas/test-persistence.xml b/mock/src/test/resources-jbossas/test-persistence.xml new file mode 100644 index 0000000..f514a54 --- /dev/null +++ b/mock/src/test/resources-jbossas/test-persistence.xml @@ -0,0 +1,17 @@ + + + + java:/DefaultDS + + + + + + + + diff --git a/mock/src/test/resources-jbossas/test-web.xml b/mock/src/test/resources-jbossas/test-web.xml new file mode 100644 index 0000000..dd9e4e8 --- /dev/null +++ b/mock/src/test/resources-jbossas/test-web.xml @@ -0,0 +1,22 @@ + + + + wicket-test + + + Wicket Filter + org.apache.wicket.protocol.http.WicketFilter + + applicationClassName + org.jboss.seam.wicket.mock.SeamWicketTester$DummySeamApplication + + + + Wicket Filter + /* + + + diff --git a/mock/src/test/resources/ConversationTestPage.html b/mock/src/test/resources/ConversationTestPage.html new file mode 100644 index 0000000..6016cc6 --- /dev/null +++ b/mock/src/test/resources/ConversationTestPage.html @@ -0,0 +1,12 @@ + + + + +Test page title + + +

Static header text

+Static span text +This is n request + + \ No newline at end of file diff --git a/mock/src/test/resources/ConversationTestPageExpected.html b/mock/src/test/resources/ConversationTestPageExpected.html new file mode 100644 index 0000000..848e6fa --- /dev/null +++ b/mock/src/test/resources/ConversationTestPageExpected.html @@ -0,0 +1,12 @@ + + + + +Test page title + + +

First conversation message

+First conversation message +This is 0 request + + \ No newline at end of file diff --git a/mock/src/test/resources/EmptyPage.html b/mock/src/test/resources/EmptyPage.html new file mode 100644 index 0000000..bbe675c --- /dev/null +++ b/mock/src/test/resources/EmptyPage.html @@ -0,0 +1,10 @@ + + + + +Test page title + + + + + \ No newline at end of file diff --git a/mock/src/test/resources/RequestTestPage.html b/mock/src/test/resources/RequestTestPage.html new file mode 100644 index 0000000..6016cc6 --- /dev/null +++ b/mock/src/test/resources/RequestTestPage.html @@ -0,0 +1,12 @@ + + + + +Test page title + + +

Static header text

+Static span text +This is n request + + \ No newline at end of file diff --git a/mock/src/test/resources/RequestTestPageExpected.html b/mock/src/test/resources/RequestTestPageExpected.html new file mode 100644 index 0000000..03cc70b --- /dev/null +++ b/mock/src/test/resources/RequestTestPageExpected.html @@ -0,0 +1,12 @@ + + + + +Test page title + + +

First request message

+First request message +This is 0 request + + \ No newline at end of file diff --git a/mock/src/test/resources/arquillian.xml b/mock/src/test/resources/arquillian.xml new file mode 100644 index 0000000..5b4c137 --- /dev/null +++ b/mock/src/test/resources/arquillian.xml @@ -0,0 +1,25 @@ + + + + + + + + + 7070 + src/test/resources-glassfish-embedded/sun-resources.xml + + + + + 8080 + + +