NativeBridge { @SuppressLint("LambdaLast") public boolean onHandleCommand(@Nullable String url, @NonNull JavaScriptExecutor javaScriptExecutor, @NonNull ActionRunRequestExtender actionRunRequestExtender, @NonNull CommandDelegate commandDelegate) { if (url == null) { return false; } Uri uri = Uri.parse(url); if (uri.getHost() == null || !UA_ACTION_SCHEME.equals(uri.getScheme())) { return false; } Logger.verbose("Intercepting: %s", url); switch (uri.getHost()) { case RUN_BASIC_ACTIONS_COMMAND: Logger.info("Running run basic actions command for URL: %s", url); runActions(actionRunRequestExtender, decodeActionArguments(uri, true)); break; case RUN_ACTIONS_COMMAND: Logger.info("Running run actions command for URL: %s", url); runActions(actionRunRequestExtender, decodeActionArguments(uri, false)); break; case RUN_ACTIONS_COMMAND_CALLBACK: Logger.info("Running run actions command with callback for URL: %s", url); List<String> paths = uri.getPathSegments(); if (paths.size() == 3) { Logger.info("Action: %s, Args: %s, Callback: %s", paths.get(0), paths.get(1), paths.get(2)); runAction(actionRunRequestExtender, javaScriptExecutor, paths.get(0), paths.get(1), paths.get(2)); } else { Logger.error("Unable to run action, invalid number of arguments."); } break; case CLOSE_COMMAND: Logger.info("Running close command for URL: %s", url); commandDelegate.onClose(); break; default: commandDelegate.onAirshipCommand(uri.getHost(), uri); break; } return true; } NativeBridge();  NativeBridge(@NonNull ActionRunRequestFactory actionRunRequestFactory); @VisibleForTesting  NativeBridge(ActionRunRequestFactory actionRunRequestFactory, @NonNull Executor executor); @SuppressLint("LambdaLast") boolean onHandleCommand(@Nullable String url,
                                   @NonNull JavaScriptExecutor javaScriptExecutor,
                                   @NonNull ActionRunRequestExtender actionRunRequestExtender,
                                   @NonNull CommandDelegate commandDelegate); void setActionCompletionCallback(@Nullable ActionCompletionCallback actionCompletionCallback); @NonNull Cancelable loadJavaScriptEnvironment(@NonNull final Context context,
                                                @NonNull final JavaScriptEnvironment javaScriptEnvironment,
                                                @NonNull final JavaScriptExecutor javaScriptExecutor);  }
@Test public void testRunBasicActionsCommand() { ActionRunRequest actionRunRequest = Mockito.mock(StubbedActionRunRequest.class, Mockito.CALLS_REAL_METHODS); when(runRequestFactory.createActionRequest("action")).thenReturn(actionRunRequest); ActionRunRequest anotherActionRunRequest = Mockito.mock(StubbedActionRunRequest.class, Mockito.CALLS_REAL_METHODS); when(runRequestFactory.createActionRequest("anotherAction")).thenReturn(anotherActionRunRequest); String url = "uairship: assertTrue(nativeBridge.onHandleCommand(url, javaScriptExecutor, runRequestExtender, commandDelegate)); verify(actionRunRequest).setValue(ActionValue.wrap("value")); verify(actionRunRequest).setSituation(Action.SITUATION_WEB_VIEW_INVOCATION); verify(actionRunRequest).run(any(ActionCompletionCallback.class)); verify(anotherActionRunRequest).setValue(eq(ActionValue.wrap("anotherValue"))); verify(anotherActionRunRequest).setSituation(Action.SITUATION_WEB_VIEW_INVOCATION); verify(anotherActionRunRequest).run(any(ActionCompletionCallback.class)); verify(runRequestExtender).extend(actionRunRequest); verify(runRequestExtender).extend(anotherActionRunRequest); verifyZeroInteractions(javaScriptExecutor, commandDelegate); }
@Test public void testRunBasicActionsCommandEncodedParameters() { ActionRunRequest removeTagRunRequest = Mockito.mock(StubbedActionRunRequest.class, Mockito.CALLS_REAL_METHODS); ActionRunRequest addTagRunRequest = Mockito.mock(StubbedActionRunRequest.class, Mockito.CALLS_REAL_METHODS); when(runRequestFactory.createActionRequest("^-t")).thenReturn(removeTagRunRequest); when(runRequestFactory.createActionRequest("^+t")).thenReturn(addTagRunRequest); String encodedUrl = "uairship: assertTrue(nativeBridge.onHandleCommand(encodedUrl, javaScriptExecutor, runRequestExtender, commandDelegate)); verify(removeTagRunRequest).setValue(ActionValue.wrap("removeTag")); verify(removeTagRunRequest).setSituation(Action.SITUATION_WEB_VIEW_INVOCATION); verify(removeTagRunRequest).run(any(ActionCompletionCallback.class)); verify(addTagRunRequest).setValue(ActionValue.wrap("addTag")); verify(addTagRunRequest).setSituation(Action.SITUATION_WEB_VIEW_INVOCATION); verify(addTagRunRequest).run(any(ActionCompletionCallback.class)); verify(runRequestExtender).extend(removeTagRunRequest); verify(runRequestExtender).extend(addTagRunRequest); verifyZeroInteractions(javaScriptExecutor, commandDelegate); }
@Test public void testRunActionsCommandEncodedParametersWithBogusParameter() { String encodedUrl = "uairship: assertTrue(nativeBridge.onHandleCommand(encodedUrl, javaScriptExecutor, runRequestExtender, commandDelegate)); verify(runRequestFactory, never()).createActionRequest(Mockito.anyString()); }
@Test public void testRunBasicActionsCommandNoActionArgs() { ActionRunRequest addTagRunRequest = Mockito.mock(StubbedActionRunRequest.class, Mockito.CALLS_REAL_METHODS); when(runRequestFactory.createActionRequest("addTag")).thenReturn(addTagRunRequest); String url = "uairship: assertTrue(nativeBridge.onHandleCommand(url, javaScriptExecutor, runRequestExtender, commandDelegate)); verify(addTagRunRequest).setValue(new ActionValue()); verify(addTagRunRequest).setSituation(Action.SITUATION_WEB_VIEW_INVOCATION); verify(addTagRunRequest).run(any(ActionCompletionCallback.class)); }
@Test public void testRunBasicActionsCommandNoParameters() { String url = "uairship: assertTrue(nativeBridge.onHandleCommand(url, javaScriptExecutor, runRequestExtender, commandDelegate)); verify(runRequestFactory, never()).createActionRequest(Mockito.anyString()); }
@Test public void testRunActionsCommand() throws ActionValueException { ActionRunRequest actionRunRequest = Mockito.mock(StubbedActionRunRequest.class, Mockito.CALLS_REAL_METHODS); when(runRequestFactory.createActionRequest("action")).thenReturn(actionRunRequest); ActionRunRequest anotherActionRunRequest = Mockito.mock(StubbedActionRunRequest.class, Mockito.CALLS_REAL_METHODS); when(runRequestFactory.createActionRequest("anotherAction")).thenReturn(anotherActionRunRequest); String url = "uairship: assertTrue(nativeBridge.onHandleCommand(url, javaScriptExecutor, runRequestExtender, commandDelegate)); Map<String, Object> expectedMap = new HashMap<>(); expectedMap.put("key", "value"); verify(actionRunRequest).setValue(ActionValue.wrap(expectedMap)); verify(actionRunRequest).setSituation(Action.SITUATION_WEB_VIEW_INVOCATION); verify(actionRunRequest).run(any(ActionCompletionCallback.class)); List<String> expectedList = new ArrayList<>(); expectedList.add("one"); expectedList.add("two"); verify(anotherActionRunRequest).setValue(ActionValue.wrap(expectedList)); verify(anotherActionRunRequest).setSituation(Action.SITUATION_WEB_VIEW_INVOCATION); verify(anotherActionRunRequest).run(any(ActionCompletionCallback.class)); verify(runRequestExtender).extend(actionRunRequest); verify(runRequestExtender).extend(anotherActionRunRequest); verifyZeroInteractions(javaScriptExecutor, commandDelegate); }
@Test public void testRunActionsCommandNoParameters() { String url = "uairship: assertTrue(nativeBridge.onHandleCommand(url, javaScriptExecutor, runRequestExtender, commandDelegate)); verify(runRequestFactory, never()).createActionRequest(Mockito.anyString()); }
@Test public void testRunActionsCommandNoActionArgs() { ActionRunRequest actionRunRequest = Mockito.mock(StubbedActionRunRequest.class, Mockito.CALLS_REAL_METHODS); when(runRequestFactory.createActionRequest("action")).thenReturn(actionRunRequest); String url = "uairship: assertTrue(nativeBridge.onHandleCommand(url, javaScriptExecutor, runRequestExtender, commandDelegate)); verify(actionRunRequest).setValue(new ActionValue()); verify(actionRunRequest).setSituation(Action.SITUATION_WEB_VIEW_INVOCATION); verify(actionRunRequest).run(any(ActionCompletionCallback.class)); verify(runRequestExtender).extend(actionRunRequest); verifyZeroInteractions(javaScriptExecutor, commandDelegate); }
@Test public void testActionCallInvalidArguments() { String url = "uairship: assertTrue(nativeBridge.onHandleCommand(url, javaScriptExecutor, runRequestExtender, commandDelegate)); verify(javaScriptExecutor) .executeJavaScript("UAirship.finishAction(new Error(\"Unable to decode arguments payload\"), null, 'callbackId');"); }
@Test public void testActionCallActionNotFound() { final ActionResult result = ActionTestUtils.createResult(null, null, ActionResult.STATUS_ACTION_NOT_FOUND); final ActionArguments arguments = ActionTestUtils.createArgs(Action.SITUATION_WEB_VIEW_INVOCATION, "what"); ActionRunRequest runRequest = Mockito.mock(StubbedActionRunRequest.class, Mockito.CALLS_REAL_METHODS); when(runRequestFactory.createActionRequest("actionName")).thenReturn(runRequest); doAnswer(new Answer<Void>() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { Object[] args = invocation.getArguments(); ActionCompletionCallback callback = (ActionCompletionCallback) args[0]; callback.onFinish(arguments, result); return null; } }).when(runRequest).run(Mockito.any(ActionCompletionCallback.class)); String url = "uairship: assertTrue(nativeBridge.onHandleCommand(url, javaScriptExecutor, runRequestExtender, commandDelegate)); verify(javaScriptExecutor) .executeJavaScript("UAirship.finishAction(new Error(\"Action actionName not found\"), null, 'callbackId');"); }
@Test public void testActionCallActionRejectedArguments() { final ActionResult result = ActionTestUtils.createResult(null, null, ActionResult.STATUS_REJECTED_ARGUMENTS); final ActionArguments arguments = ActionTestUtils.createArgs(Action.SITUATION_WEB_VIEW_INVOCATION, "what"); ActionRunRequest runRequest = Mockito.mock(StubbedActionRunRequest.class, Mockito.CALLS_REAL_METHODS); when(runRequestFactory.createActionRequest("actionName")).thenReturn(runRequest); doAnswer(new Answer<Void>() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { Object[] args = invocation.getArguments(); ActionCompletionCallback callback = (ActionCompletionCallback) args[0]; callback.onFinish(arguments, result); return null; } }).when(runRequest).run(Mockito.any(ActionCompletionCallback.class)); String url = "uairship: assertTrue(nativeBridge.onHandleCommand(url, javaScriptExecutor, runRequestExtender, commandDelegate)); verify(javaScriptExecutor).executeJavaScript("UAirship.finishAction(new Error(\"Action actionName rejected its arguments\"), null, 'callbackId');"); }
@Test public void testActionCallActionExecutionError() { final ActionResult result = ActionTestUtils.createResult(null, new Exception("error!"), ActionResult.STATUS_EXECUTION_ERROR); final ActionArguments arguments = ActionTestUtils.createArgs(Action.SITUATION_WEB_VIEW_INVOCATION, "what"); ActionRunRequest runRequest = Mockito.mock(StubbedActionRunRequest.class, Mockito.CALLS_REAL_METHODS); when(runRequestFactory.createActionRequest("actionName")).thenReturn(runRequest); doAnswer(new Answer<Void>() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { Object[] args = invocation.getArguments(); ActionCompletionCallback callback = (ActionCompletionCallback) args[0]; callback.onFinish(arguments, result); return null; } }).when(runRequest).run(Mockito.any(ActionCompletionCallback.class)); String url = "uairship: assertTrue(nativeBridge.onHandleCommand(url, javaScriptExecutor, runRequestExtender, commandDelegate)); verify(javaScriptExecutor) .executeJavaScript("UAirship.finishAction(new Error(\"error!\"), null, 'callbackId');"); }
@Test public void testActionCallAction() throws ActionValueException { final ActionResult result = ActionTestUtils.createResult("action_result", null, ActionResult.STATUS_COMPLETED); final ActionArguments arguments = ActionTestUtils.createArgs(Action.SITUATION_WEB_VIEW_INVOCATION, "what"); ActionRunRequest runRequest = Mockito.mock(StubbedActionRunRequest.class, Mockito.CALLS_REAL_METHODS); when(runRequestFactory.createActionRequest("actionName")).thenReturn(runRequest); doAnswer(new Answer<Void>() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { Object[] args = invocation.getArguments(); ActionCompletionCallback callback = (ActionCompletionCallback) args[0]; callback.onFinish(arguments, result); return null; } }).when(runRequest).run(Mockito.any(ActionCompletionCallback.class)); String url = "uairship: assertTrue(nativeBridge.onHandleCommand(url, javaScriptExecutor, runRequestExtender, commandDelegate)); verify(javaScriptExecutor) .executeJavaScript("UAirship.finishAction(null, \"action_result\", 'callbackId');"); verify(runRequest).run(any(ActionCompletionCallback.class)); verify(runRequest).setSituation(Action.SITUATION_WEB_VIEW_INVOCATION); verify(runRequest).setValue(ActionValue.wrap(true)); }
@Test public void testCloseCommand() { String url = "uairship: assertTrue(nativeBridge.onHandleCommand(url, javaScriptExecutor, runRequestExtender, commandDelegate)); verify(commandDelegate).onClose(); }
@Test public void testExtendingBridge() { String url = "uairship: assertTrue(nativeBridge.onHandleCommand(url, javaScriptExecutor, runRequestExtender, commandDelegate)); verify(commandDelegate).onAirshipCommand("foo", Uri.parse(url)); }