ko/archetype/src/main/resources/archetype-resources/src/test/java/JsInteractionTest.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 04 Feb 2014 09:32:27 +0100
changeset 1433 3d696782eab9
permissions -rw-r--r--
Sample usage of @JavaScriptBody annotation. Preprocessing classes and adding a Js/Java interoperability test
     1 package ${package};
     2 
     3 import java.io.Closeable;
     4 import java.io.Reader;
     5 import java.net.URL;
     6 import java.util.ArrayList;
     7 import java.util.List;
     8 import javax.script.Invocable;
     9 import javax.script.ScriptEngine;
    10 import javax.script.ScriptEngineManager;
    11 import javax.script.ScriptException;
    12 import org.apidesign.html.boot.spi.Fn;
    13 import static org.testng.Assert.assertEquals;
    14 import org.testng.annotations.AfterMethod;
    15 import org.testng.annotations.BeforeMethod;
    16 import org.testng.annotations.Test;
    17 
    18 /** Tests for behavior of @JavaScriptBody methods. Set your JavaScript 
    19  * environment up (for example define <code>alert</code> or use some
    20  * emulation library like <em>env.js</em>), register script presenter 
    21  * and then you can call methods that deal with JavaScript in your tests.
    22  */
    23 public class JsInteractionTest {
    24     private Closeable jsEngine;
    25     @BeforeMethod public void initializeJSEngine() throws Exception {
    26         jsEngine = Fn.activate(new ScriptPresenter());
    27     }
    28     
    29     @AfterMethod public void shutdownJSEngine() throws Exception {
    30         jsEngine.close();
    31     }
    32     
    33     @Test public void testCallbackFromJavaScript() throws Exception {
    34         class R implements Runnable {
    35             int called;
    36 
    37             @Override
    38             public void run() {
    39                 called++;
    40             }
    41         }
    42         R callback = new R();
    43         
    44         DataModel.confirmByUser("Hello", callback);
    45         
    46         assertEquals(callback.called, 1, "One immediate callback");
    47     }
    48 
    49     private static class ScriptPresenter implements Fn.Presenter {
    50         private final ScriptEngine eng;
    51         
    52         public ScriptPresenter() throws ScriptException {
    53             eng = new ScriptEngineManager().getEngineByName("javascript");
    54             eng.eval("function alert(msg) { Packages.java.lang.System.out.println(msg); };");
    55         }
    56 
    57         @Override
    58         public Fn defineFn(String code, String... names) {
    59             StringBuilder sb = new StringBuilder();
    60             sb.append("(function() {");
    61             sb.append("  return function(");
    62             String sep = "";
    63             for (String n : names) {
    64                 sb.append(sep).append(n);
    65                 sep = ",";
    66             }
    67             sb.append(") {\n");
    68             sb.append(code);
    69             sb.append("};");
    70             sb.append("})()");
    71             
    72             final Object fn;
    73             try {
    74                 fn = eng.eval(sb.toString());
    75             } catch (ScriptException ex) {
    76                 throw new IllegalStateException(ex);
    77             }
    78             return new Fn(this) {
    79                 @Override
    80                 public Object invoke(Object thiz, Object... args) throws Exception {
    81                     List<Object> all = new ArrayList<Object>(args.length + 1);
    82                     all.add(thiz == null ? fn : thiz);
    83                     for (int i = 0; i < args.length; i++) {
    84                         all.add(args[i]);
    85                     }
    86                     Object ret = ((Invocable)eng).invokeMethod(fn, "call", all.toArray()); // NOI18N
    87                     return fn.equals(ret) ? null : thiz;
    88                 }
    89             };
    90         }
    91 
    92         @Override
    93         public void displayPage(URL page, Runnable onPageLoad) {
    94             // not really displaying anything
    95             onPageLoad.run();
    96         }
    97 
    98         @Override
    99         public void loadScript(Reader code) throws Exception {
   100             eng.eval(code);
   101         }
   102     }
   103 }