package org.enumerable.lambda.support.javascript;
import static java.util.Arrays.*;
import static org.enumerable.lambda.Parameters.*;
import static org.enumerable.lambda.support.javascript.LambdaJavaScript.*;
import static org.junit.Assert.*;
import groovy.lang.Closure;
import java.util.List;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import org.enumerable.lambda.Fn1;
import org.enumerable.lambda.Lambda;
import org.enumerable.lambda.enumerable.Enumerable;
import org.enumerable.lambda.support.clojure.ClojureTest;
import org.enumerable.lambda.support.clojure.LambdaClojure;
import org.enumerable.lambda.support.groovy.GroovyTest;
import org.enumerable.lambda.support.groovy.LambdaGroovy;
import org.enumerable.lambda.support.javascript.LambdaJavaScript.FunctionFn2;
import org.enumerable.lambda.support.jruby.JRubyTest;
import org.enumerable.lambda.support.jruby.LambdaJRuby;
import org.enumerable.lambda.support.scala.LambdaScala;
import org.enumerable.lambda.support.scala.ScalaTest;
import org.enumerable.lambda.support.scala.ScalaTest.ScalaInterpreter;
import org.jruby.RubyProc;
import org.junit.Before;
import org.junit.Test;
import scala.Function2;
import sun.org.mozilla.javascript.internal.Context;
import sun.org.mozilla.javascript.internal.Function;
import clojure.lang.IFn;
public class JavaScriptTest {
ScriptEngine js;
@Test
public void interactingWithJavaScript() throws ScriptException {
js.put("f", function(n, n * 2));
assertEquals(4.0, js.eval("f(2);"));
js.put("f", function(b, !b));
assertTrue((Boolean) js.eval("f(false);"));
js.put("f", function(s, s.toUpperCase()));
assertEquals("HELLO", js.eval("f('hello');"));
js.put("f", function(obj, obj));
assertNull(js.eval("f(undefined);"));
assertNull(js.eval("f(null);"));
}
@Test
public void defaultValuesForJavaScriptFunctions() throws ScriptException {
js.put("f", function(n = 2, n * 2));
assertEquals(4.0, js.eval("f()"));
js.put("f", function(n, m = 2, n * m));
assertEquals(8.0, js.eval("f(4)"));
js.put("f", function(n = 2, m = 2, n * m));
assertEquals(4.0, js.eval("f()"));
}
@Test
public void convertFnToFunction() throws ScriptException {
Function f = toFunction(Lambda.λ(s, s.toUpperCase()));
assertEquals("HELLO", f.call(Context.getCurrentContext(), null, null, new Object[] { "hello" }));
}
@Test
public void convertFnToFunctionKeepsDefaultValues() throws ScriptException {
Function f = toFunction(Lambda.λ(s = "world", s.toUpperCase()));
assertEquals("WORLD", f.call(Context.getCurrentContext(), null, null, new Object[0]));
}
@Test(expected = NullPointerException.class)
public void convertedFunctionThrowsExceptionWhenCalledWithTooFewArguments() throws ScriptException {
Function f = toFunction(Lambda.λ(s, s.toUpperCase()));
f.call(Context.getCurrentContext(), null, null, new Object[0]);
}
public void convertedFunctionIgnoresExtraArguments() throws ScriptException {
Function f = toFunction(Lambda.λ(s, s.toUpperCase()));
assertEquals("HELLO", f.call(Context.getCurrentContext(), null, null, new Object[] { "hello", "world" }));
}
@Test
public void convertFunctionToFn() throws ScriptException {
Function f = (Function) js.eval("var f = function(s) { return s.toUpperCase(); }; f;");
assertEquals("HELLO", toFn1(f).call("hello"));
}
@Test
public void interactingWithEnumerableJava() throws Exception {
List<Integer> list = asList(1, 2, 3);
Fn1<Object, Object> block = toFn1((Function) js.eval("var f = function(n) { return n * 2}; f;"));
assertEquals(asList(2.0, 4.0, 6.0), Enumerable.collect(list, block));
}
@Test
public void interactingWithClojure() throws Exception {
IFn star = (IFn) ClojureTest.getClojureEngine().eval("*");
FunctionFn2 f = toFunction(LambdaClojure.toFn2(star));
js.put("f", f);
assertEquals(6.0, js.eval("f(2, 3)"));
}
@Test
public void interactingWithJRuby() throws Exception {
ScriptEngine rb = JRubyTest.getJRubyEngine();
RubyProc proc = (RubyProc) rb.eval(":*.to_proc");
FunctionFn2 f = toFunction(LambdaJRuby.toFn2(proc));
js.put("f", f);
assertEquals(6.0, js.eval("f(2, 3)"));
}
@Test
public void interactingWithGroovy() throws Exception {
ScriptEngine groovy = GroovyTest.getGroovyEngine();
Closure<?> closure = (Closure<?>) groovy.eval("{ n, m -> n * m }");
FunctionFn2 f = toFunction(LambdaGroovy.toFn2(closure));
js.put("f", f);
assertEquals(6.0, js.eval("f(2, 3)"));
}
@SuppressWarnings("unchecked")
@Test
public void interactingWithScala() throws Exception {
ScalaInterpreter scala = ScalaTest.getScalaInterpreter();
Function2<Integer, Integer, Integer> f = (Function2<Integer, Integer, Integer>) scala.eval("(n: Double, m: Double) => n * m");
js.put("f", toFunction(LambdaScala.toFn2(f)));
assertEquals(6.0, js.eval("f(2, 3)"));
}
@Before
public void initEngine() {
js = getJavaScriptEngine();
}
public static ScriptEngine getJavaScriptEngine() {
ScriptEngineManager manager = new ScriptEngineManager();
return manager.getEngineByName("JavaScript");
}
}