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