Adds non-trivial tests to the default app created by webAppCreator, including one that uses delayTestFinish and sends an RPC. Also shows an example of shared client/server code. Patch by: jlabanca Review by: jgw git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7362 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/tools/AppClassTemplate.javasrc b/user/src/com/google/gwt/user/tools/AppClassTemplate.javasrc index 433a4d0..45429c3 100644 --- a/user/src/com/google/gwt/user/tools/AppClassTemplate.javasrc +++ b/user/src/com/google/gwt/user/tools/AppClassTemplate.javasrc
@@ -1,5 +1,6 @@ package @clientPackage; +import @sharedPackage.FieldVerifier; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; @@ -40,6 +41,7 @@ final Button sendButton = new Button("Send"); final TextBox nameField = new TextBox(); nameField.setText("GWT User"); + final Label errorLabel = new Label(); // We can add style names to widgets sendButton.addStyleName("sendButton"); @@ -48,6 +50,7 @@ // Use RootPanel.get() to get the entire body element RootPanel.get("nameFieldContainer").add(nameField); RootPanel.get("sendButtonContainer").add(sendButton); + RootPanel.get("errorLabelContainer").add(errorLabel); // Focus the cursor on the name field when the app loads nameField.setFocus(true); @@ -103,8 +106,16 @@ * Send the name from the nameField to the server and wait for a response. */ private void sendNameToServer() { - sendButton.setEnabled(false); + // First, we validate the input. + errorLabel.setText(""); String textToServer = nameField.getText(); + if (!FieldVerifier.isValidName(textToServer)) { + errorLabel.setText("Please enter at least four characters"); + return; + } + + // Then, we send the input to the server. + sendButton.setEnabled(false); textToServerLabel.setText(textToServer); serverResponseLabel.setText(""); greetingService.greetServer(textToServer, new AsyncCallback<String>() {
diff --git a/user/src/com/google/gwt/user/tools/AppHtml.htmlsrc b/user/src/com/google/gwt/user/tools/AppHtml.htmlsrc index e85d026..75007e9 100644 --- a/user/src/com/google/gwt/user/tools/AppHtml.htmlsrc +++ b/user/src/com/google/gwt/user/tools/AppHtml.htmlsrc
@@ -56,6 +56,9 @@ <td id="nameFieldContainer"></td> <td id="sendButtonContainer"></td> </tr> + <tr> + <td colspan="2" style="color:red;" id="errorLabelContainer"></td> + </tr> </table> </body> </html>
diff --git a/user/src/com/google/gwt/user/tools/JUnit.gwt.xmlsrc b/user/src/com/google/gwt/user/tools/JUnit.gwt.xmlsrc new file mode 100644 index 0000000..5d70944 --- /dev/null +++ b/user/src/com/google/gwt/user/tools/JUnit.gwt.xmlsrc
@@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?>@gwtModuleDtd +<module> + <!-- Inherit our applications main module. --> + <inherits name='@moduleName'/> + + <!-- Specify the path to any remote services. --> + <servlet path="/@renameTo/greet" class="@serverPackage.GreetingServiceImpl" /> + +</module>
diff --git a/user/src/com/google/gwt/user/tools/JUnitClassTemplate.javasrc b/user/src/com/google/gwt/user/tools/JUnitClassTemplate.javasrc index 25a6a58..b63904b 100644 --- a/user/src/com/google/gwt/user/tools/JUnitClassTemplate.javasrc +++ b/user/src/com/google/gwt/user/tools/JUnitClassTemplate.javasrc
@@ -1,6 +1,10 @@ package @clientPackage; +import @sharedPackage.FieldVerifier; +import com.google.gwt.core.client.GWT; import com.google.gwt.junit.client.GWTTestCase; +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.google.gwt.user.client.rpc.ServiceDefTarget; /** * GWT JUnit tests must extend GWTTestCase. @@ -11,14 +15,54 @@ * Must refer to a valid module that sources this class. */ public String getModuleName() { - return "@moduleName"; + return "@moduleNameJUnit"; } /** - * Add as many tests as you like. + * Tests the FieldVerifier. */ - public void testSimple() { - assertTrue(true); + public void testFieldVerifier() { + assertFalse(FieldVerifier.isValidName(null)); + assertFalse(FieldVerifier.isValidName("")); + assertFalse(FieldVerifier.isValidName("a")); + assertFalse(FieldVerifier.isValidName("ab")); + assertFalse(FieldVerifier.isValidName("abc")); + assertTrue(FieldVerifier.isValidName("abcd")); } + /** + * This test will send a request to the server using the greetServer method in + * GreetingService and verify the response. + */ + public void testGreetingService() { + // Create the service that we will test. + GreetingServiceAsync greetingService = GWT.create(GreetingService.class); + ServiceDefTarget target = (ServiceDefTarget) greetingService; + target.setServiceEntryPoint(GWT.getModuleBaseURL() + "/@renameTo/greet"); + + // Since RPC calls are asynchronous, we will need to wait for a response + // after this test method returns. This line tells the test runner to wait + // up to 10 seconds before timing out. + delayTestFinish(10000); + + // Send a request to the server. + greetingService.greetServer("GWT User", new AsyncCallback<String>() { + public void onFailure(Throwable caught) { + // The request resulted in an unexpected error. + fail("Request failure: " + caught.getMessage()); + } + + public void onSuccess(String result) { + // Verify that the response is correct. + assertTrue(result.startsWith("Hello, GWT User!")); + + // Now that we have received a response, we need to tell the test runner + // that the test is complete. You must call finishTest() after an + // asynchronous test finishes successfully, or the test will time out. + finishTest(); + } + }); + } + + }
diff --git a/user/src/com/google/gwt/user/tools/Module.gwt.xmlsrc b/user/src/com/google/gwt/user/tools/Module.gwt.xmlsrc index 8be3e85..2f0267e 100644 --- a/user/src/com/google/gwt/user/tools/Module.gwt.xmlsrc +++ b/user/src/com/google/gwt/user/tools/Module.gwt.xmlsrc
@@ -17,5 +17,6 @@ <!-- Specify the paths for translatable code --> <source path='client'/> + <source path='shared'/> </module>
diff --git a/user/src/com/google/gwt/user/tools/RpcAsyncClientTemplate.javasrc b/user/src/com/google/gwt/user/tools/RpcAsyncClientTemplate.javasrc index e91fb2e..fe1abcc 100644 --- a/user/src/com/google/gwt/user/tools/RpcAsyncClientTemplate.javasrc +++ b/user/src/com/google/gwt/user/tools/RpcAsyncClientTemplate.javasrc
@@ -6,5 +6,6 @@ * The async counterpart of <code>GreetingService</code>. */ public interface GreetingServiceAsync { - void greetServer(String input, AsyncCallback<String> callback); + void greetServer(String input, AsyncCallback<String> callback) + throws IllegalArgumentException; }
diff --git a/user/src/com/google/gwt/user/tools/RpcClientTemplate.javasrc b/user/src/com/google/gwt/user/tools/RpcClientTemplate.javasrc index 40fcca7..3a68c93 100644 --- a/user/src/com/google/gwt/user/tools/RpcClientTemplate.javasrc +++ b/user/src/com/google/gwt/user/tools/RpcClientTemplate.javasrc
@@ -8,5 +8,5 @@ */ @RemoteServiceRelativePath("greet") public interface GreetingService extends RemoteService { - String greetServer(String name); + String greetServer(String name) throws IllegalArgumentException; }
diff --git a/user/src/com/google/gwt/user/tools/RpcServerTemplate.javasrc b/user/src/com/google/gwt/user/tools/RpcServerTemplate.javasrc index 4278c86..8d00ff5 100644 --- a/user/src/com/google/gwt/user/tools/RpcServerTemplate.javasrc +++ b/user/src/com/google/gwt/user/tools/RpcServerTemplate.javasrc
@@ -1,6 +1,7 @@ package @serverPackage; import @clientPackage.GreetingService; +import @sharedPackage.FieldVerifier; import com.google.gwt.user.server.rpc.RemoteServiceServlet; /** @@ -10,7 +11,15 @@ public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService { - public String greetServer(String input) { + public String greetServer(String input) throws IllegalArgumentException { + // Verify that the input is valid. + if (!FieldVerifier.isValidName(input)) { + // If the input is not valid, throw an IllegalArgumentException back to + // the client. + throw new IllegalArgumentException( + "Name must be at least 4 characters long"); + } + String serverInfo = getServletContext().getServerInfo(); String userAgent = getThreadLocalRequest().getHeader("User-Agent"); return "Hello, " + input + "!<br><br>I am running " + serverInfo
diff --git a/user/src/com/google/gwt/user/tools/SharedClassTemplate.javasrc b/user/src/com/google/gwt/user/tools/SharedClassTemplate.javasrc new file mode 100644 index 0000000..9a3bb0e --- /dev/null +++ b/user/src/com/google/gwt/user/tools/SharedClassTemplate.javasrc
@@ -0,0 +1,42 @@ +package @sharedPackage; + +/** + * <p> + * FieldVerifier validates that the name the user enters is valid. + * </p> + * <p> + * This class is in the <code>shared</code> packing because we use it in both + * the client code and on the server. On the client, we verify that the name is + * valid before sending an RPC request so the user doesn't have to wait for a + * network round trip to get feedback. On the server, we verify that the name is + * correct to ensure that the input is correct regardless of where the RPC + * originates. + * </p> + * <p> + * When creating a class that is used on both the client and the server, be sure + * that all code is translatable and does not use native JavaScript. Code that + * is note translatable (such as code that interacts with a database or the file + * system) cannot be compiled into client side JavaScript. Code that uses native + * JavaScript (such as Widgets) cannot be run on the server. + * </p> + */ +public class FieldVerifier { + + /** + * Verifies that the specified name is valid for our service. + * + * In this example, we only require that the name is at least four + * characters. In your application, you can use more complex checks to ensure + * that usernames, passwords, email addresses, URLs, and other fields have the + * proper syntax. + * + * @param name the name to validate + * @return true if valid, false if invalid + */ + public static boolean isValidName(String name) { + if (name == null) { + return false; + } + return name.length() > 3; + } +}
diff --git a/user/src/com/google/gwt/user/tools/WebAppCreator.java b/user/src/com/google/gwt/user/tools/WebAppCreator.java index ab20988..667de6d 100644 --- a/user/src/com/google/gwt/user/tools/WebAppCreator.java +++ b/user/src/com/google/gwt/user/tools/WebAppCreator.java
@@ -290,8 +290,10 @@ '.', '/'), true); File clientDir = Utility.getDirectory(moduleDir, "client", true); File serverDir = Utility.getDirectory(moduleDir, "server", true); - File clientTestDir = Utility.getDirectory(outDir, "test/" - + modulePackageName.replace('.', '/') + "/client", true); + File sharedDir = Utility.getDirectory(moduleDir, "shared", true); + File moduleTestDir = Utility.getDirectory(outDir, "test/" + + modulePackageName.replace('.', '/'), true); + File clientTestDir = Utility.getDirectory(moduleTestDir, "client", true); // Create a map of replacements Map<String, String> replacements = new HashMap<String, String>(); @@ -299,6 +301,7 @@ replacements.put("@moduleName", moduleName); replacements.put("@clientPackage", modulePackageName + ".client"); replacements.put("@serverPackage", modulePackageName + ".server"); + replacements.put("@sharedPackage", modulePackageName + ".shared"); replacements.put("@gwtSdk", installPath); replacements.put("@gwtUserPath", gwtUserPath); replacements.put("@gwtDevPath", gwtDevPath); @@ -361,16 +364,20 @@ files.add(new FileCreator(webInfDir, "web.xml", "web.xml")); files.add(new FileCreator(clientDir, moduleShortName + ".java", "AppClassTemplate.java")); - files.add(new FileCreator(clientDir, "GreetingService" + ".java", + files.add(new FileCreator(clientDir, "GreetingService.java", "RpcClientTemplate.java")); - files.add(new FileCreator(clientDir, "GreetingServiceAsync" + ".java", + files.add(new FileCreator(clientDir, "GreetingServiceAsync.java", "RpcAsyncClientTemplate.java")); - files.add(new FileCreator(serverDir, "GreetingServiceImpl" + ".java", + files.add(new FileCreator(serverDir, "GreetingServiceImpl.java", "RpcServerTemplate.java")); + files.add(new FileCreator(sharedDir, "FieldVerifier.java", + "SharedClassTemplate.java")); files.add(new FileCreator(outDir, "build.xml", "project.ant.xml")); files.add(new FileCreator(outDir, "README.txt", "README.txt")); if (junitPath != null) { // create the test file. + files.add(new FileCreator(moduleTestDir, moduleShortName + + "JUnit.gwt.xml", "JUnit.gwt.xml")); files.add(new FileCreator(clientTestDir, moduleShortName + "Test" + ".java", "JUnitClassTemplate.java")); }