keycloak-uncached

Details

diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/JavascriptTestExecutor.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/JavascriptTestExecutor.java
index 2194c3b..496c8af 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/JavascriptTestExecutor.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/JavascriptTestExecutor.java
@@ -130,13 +130,27 @@ public class JavascriptTestExecutor {
 
         String arguments = argumentsBuilder.build();
 
-        Object output = jsExecutor.executeAsyncScript(
-                "var callback = arguments[arguments.length - 1];" +
-                "   window.keycloak.init(" + arguments + ").success(function (authenticated) {" +
-                "       callback(\"Init Success (\" + (authenticated ? \"Authenticated\" : \"Not Authenticated\") + \")\");" +
-                "   }).error(function () {" +
-                "       callback(\"Init Error\");" +
-                "   });");
+        String script;
+
+        // phantomjs do not support Native promises
+        if (argumentsBuilder.contains("promiseType", "native") && !"phantomjs".equals(System.getProperty("js.browser"))) {
+            script = "var callback = arguments[arguments.length - 1];" +
+                    "   window.keycloak.init(" + arguments + ").then(function (authenticated) {" +
+                    "       callback(\"Init Success (\" + (authenticated ? \"Authenticated\" : \"Not Authenticated\") + \")\");" +
+                    "   }, function () {" +
+                    "       callback(\"Init Error\");" +
+                    "   });";
+        } else {
+            script = "var callback = arguments[arguments.length - 1];" +
+                    "   window.keycloak.init(" + arguments + ").success(function (authenticated) {" +
+                    "       callback(\"Init Success (\" + (authenticated ? \"Authenticated\" : \"Not Authenticated\") + \")\");" +
+                    "   }).error(function () {" +
+                    "       callback(\"Init Error\");" +
+                    "   });";
+        }
+
+
+        Object output = jsExecutor.executeAsyncScript(script);
 
         if (validator != null) {
             validator.validate(jsDriver, output, events);
@@ -159,8 +173,20 @@ public class JavascriptTestExecutor {
     }
 
     public JavascriptTestExecutor refreshToken(int value, JavascriptStateValidator validator) {
-        Object output = jsExecutor.executeAsyncScript(
-                    "var callback = arguments[arguments.length - 1];" +
+        String script;
+        if (useNativePromises()) {
+            script = "var callback = arguments[arguments.length - 1];" +
+                    "   window.keycloak.updateToken(" + Integer.toString(value) + ").then(function (refreshed) {" +
+                    "       if (refreshed) {" +
+                    "            callback(window.keycloak.tokenParsed);" +
+                    "       } else {" +
+                    "            callback('Token not refreshed, valid for ' + Math.round(window.keycloak.tokenParsed.exp + window.keycloak.timeSkew - new Date().getTime() / 1000) + ' seconds');" +
+                    "       }" +
+                    "   }, function () {" +
+                    "       callback('Failed to refresh token');" +
+                    "   });";
+        } else {
+            script = "var callback = arguments[arguments.length - 1];" +
                     "   window.keycloak.updateToken(" + Integer.toString(value) + ").success(function (refreshed) {" +
                     "       if (refreshed) {" +
                     "            callback(window.keycloak.tokenParsed);" +
@@ -169,7 +195,10 @@ public class JavascriptTestExecutor {
                     "       }" +
                     "   }).error(function () {" +
                     "       callback('Failed to refresh token');" +
-                    "   });");
+                    "   });";
+        }
+
+        Object output = jsExecutor.executeAsyncScript(script);
 
         if(validator != null) {
             validator.validate(jsDriver, output, events);
@@ -178,6 +207,12 @@ public class JavascriptTestExecutor {
         return this;
     }
 
+    public boolean useNativePromises() {
+        return (boolean) jsExecutor.executeScript("if (typeof window.keycloak !== 'undefined') {" +
+                "return window.keycloak.useNativePromise" +
+                "} else { return false}");
+    }
+
     public JavascriptTestExecutor openAccountPage(JavascriptStateValidator validator) {
         jsExecutor.executeScript("window.keycloak.accountManagement()");
         waitForPageToLoad();
@@ -198,13 +233,24 @@ public class JavascriptTestExecutor {
 
     public JavascriptTestExecutor getProfile(JavascriptStateValidator validator) {
 
-        Object output = jsExecutor.executeAsyncScript(
-                "var callback = arguments[arguments.length - 1];" +
-                "   window.keycloak.loadUserProfile().success(function (profile) {" +
-                "       callback(profile);" +
-                "   }).error(function () {" +
-                "       callback('Failed to load profile');" +
-                "   });");
+        String script;
+        if (useNativePromises()) {
+            script = "var callback = arguments[arguments.length - 1];" +
+                    "   window.keycloak.loadUserProfile().then(function (profile) {" +
+                    "       callback(profile);" +
+                    "   }, function () {" +
+                    "       callback('Failed to load profile');" +
+                    "   });";
+        } else {
+            script = "var callback = arguments[arguments.length - 1];" +
+                    "   window.keycloak.loadUserProfile().success(function (profile) {" +
+                    "       callback(profile);" +
+                    "   }).error(function () {" +
+                    "       callback('Failed to load profile');" +
+                    "   });";
+        }
+
+        Object output = jsExecutor.executeAsyncScript(script);
 
         if(validator != null) {
             validator.validate(jsDriver, output, events);
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/JSObjectBuilder.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/JSObjectBuilder.java
index 99a76b1..bb1560f 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/JSObjectBuilder.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/JSObjectBuilder.java
@@ -55,6 +55,10 @@ public class JSObjectBuilder {
         return this;
     }
 
+    public boolean contains(String key, Object value) {
+       return arguments.containsKey(key) && arguments.get(key).equals(value);
+    }
+
     public JSObjectBuilder add(String key, Object value) {
         arguments.put(key, value);
         return this;
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/JavascriptAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/JavascriptAdapterTest.java
index e4a05c1..e344eea 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/JavascriptAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/JavascriptAdapterTest.java
@@ -58,7 +58,7 @@ import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
 public class JavascriptAdapterTest extends AbstractJavascriptTest {
 
     private String testAppUrl;
-    private JavascriptTestExecutor testExecutor;
+    protected JavascriptTestExecutor testExecutor;
     private static int TIME_SKEW_TOLERANCE = 3;
 
     @Rule
@@ -96,7 +96,7 @@ public class JavascriptAdapterTest extends AbstractJavascriptTest {
         setStandardFlowForClient();
     }
 
-    private JSObjectBuilder defaultArguments() {
+    protected JSObjectBuilder defaultArguments() {
         return JSObjectBuilder.create().defaultSettings();
     }
 
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/JavascriptAdapterWithNativePromisesTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/JavascriptAdapterWithNativePromisesTest.java
new file mode 100644
index 0000000..0677e4d
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/JavascriptAdapterWithNativePromisesTest.java
@@ -0,0 +1,42 @@
+package org.keycloak.testsuite.adapter.javascript;
+
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+import org.keycloak.testsuite.util.javascript.JSObjectBuilder;
+
+import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
+
+public class JavascriptAdapterWithNativePromisesTest extends JavascriptAdapterTest {
+    @Override
+    protected JSObjectBuilder defaultArguments() {
+        return super.defaultArguments().add("promiseType", "native");
+    }
+
+    @Before
+    public void skipOnPhantomJS() {
+        Assume.assumeTrue("Native promises are not supported on PhantomJS", !"phantomjs".equals(System.getProperty("js.browser")));
+    }
+
+    @Test
+    @Override
+    public void reentrancyCallbackTest() {
+        testExecutor.logInAndInit(defaultArguments(), testUser, this::assertSuccessfullyLoggedIn)
+                .executeAsyncScript(
+                        "var callback = arguments[arguments.length - 1];" +
+                                "keycloak.updateToken(60).then(function () {" +
+                                "       event(\"First callback\");" +
+                                "       keycloak.updateToken(60).then(function () {" +
+                                "          event(\"Second callback\");" +
+                                "          callback(\"Success\");" +
+                                "       });" +
+                                "    }" +
+                                ");"
+                        , (driver1, output, events) -> {
+                            waitUntilElement(events).text().contains("First callback");
+                            waitUntilElement(events).text().contains("Second callback");
+                            waitUntilElement(events).text().not().contains("Auth Logout");
+                        }
+                );
+    }
+}