WebUI: Inject Javascript function


#1

Hey,

I am struggling to inject a js function in a WebUI test, so my page can use that function without declaring it in the backend’s js file.

I tried using Execute JavaScript with “function SaveToken(){alert(‘test’);}”, but that function isn’t registered with the command.
When I paste this code in the browser’s console it works fine.

I also tried “var SaveToken=function(){alert(‘test’);}” without success.

Kind regards
Daniel


#2

First, it would be remiss of me not to issue the following warning: Tip: DO NOT CHANGE THE AUT THROUGH TEST CODE

Having said that, I do inject JS functions into my page(s) all the time. However, there is a difference: my functions do not interfere with the operation of the page and the page isn’t coerced into using them either; they are only used by my groovy test code.

All I can think is you’re somehow breaking the IIFE (anonymous function) that Katalon provides to wrap your js code, because, like I said, this works and I do it myself without any issue.

Perhaps you should post your test code so we can take a closer look.


#3

Hi, thanks for the help.

First, we are integrating this page in a Word Addin, where the “SaveToken” function is implemented in C#, so the only way to test this UI is mocking this functions.

This is my test script:

WebUI.openBrowser(’’)

WebUI.navigateToUrl(‘http://server/Forms/Login’)

WebUI.setText(findTestObject(‘Page_/input_Username_username’), ‘user’)

WebUI.setEncryptedText(findTestObject(‘Page_/input_Password_password’), ‘pw’)

WebUI.executeJavaScript(‘function SaveToken(){alert(‘test’);}’, [])

WebUI.click(findTestObject(‘Page_/button_Einloggen’))

WebUI.verifyAlertPresent(10)


#4

Ahh. I think see the issue.

Katalon has installed your function but you have not called it. Where exactly is the call to SaveToken?

This, for example, should work but probably not how you want to execute it:

WebUI.executeJavaScript(‘function SaveToken(){alert(‘test’); } SaveToken();’, [])

Edited to fix a stupid error! :blush:


#5

The call to SaveToken is executed on the login button click event. But the page doesn’t provide that function. This is why I want to inject it for the test.

Your script indeed shows the alert, but that is not how I want to execute it. It should be shown, when the click on the login button is executed.


#6

Daniel

There’s something crazy going on here, because the mechanism we’re talking about certainly works (all my tests would fail if this didn’t work). So we’re looking for something a bit crazy/stupid/whatever.

In brief, here is what my test code does:

I have a file, helpers.js, which I load from disk and insert into my AUT page. I do this in a listener, like so:

  @BeforeTestCase
  def loginBeforeTestCase(TestCaseContext testCaseContext) {
    comment("loginBeforeTestCase")

    LOGGEDIN = false
    TEST_FAILED = false
    IS_STANDARD_PAGE = false

    String tcId = testCaseContext.testCaseId
    GlobalVariable.TCID = tcId
    GlobalVariable.LAST_AUT_MSG = ""
 
    if(tcId.startsWith("Test Cases/Pages")) {
      IS_STANDARD_PAGE = true
    }

    // ************************************************************
    loadJSHelpers()  //  LOAD helpers.js form Disk 
    // ************************************************************

    getProfileSettings()
    getCredentials(tcId)

    // etc .......... 
}

helpers.js contains things like

function $$(selector, frmSelector) {
  if(frmSelector) {
    return getFrameElement(frmSelector, selector);
  }
  return document.querySelector(selector);
}

function $$prop(selector, prop, frmSelector) {
  if(frmSelector) return getFrameProp(frmSelector, selector, prop);
  var el = $$(selector);
  var style = window.getComputedStyle(el);
  return style.getPropertyValue(prop);
}
// etc ..........

I’m just showing you all that crapola so you can see what you’re trying to do is perfectly fine. It is most certainly going to work.

I (and you) just can’t figure out what is going wrong.

Questions:

1 - did you try this in a trimmed down example test inside a dead simple project?

2 - Did you check the browser console (F12 developer tools) just in case there is an error?

3 - Last resort - did you try kicking the computer? :rage: :rofl:

Let me know how it goes and what you find.

Good luck!


#7

The console jsut shows that “SaveToken” is not defined… Can you please provide the code of “loadJSHeper”? As this is exactly the part where you inject the js.


#8

It’s only a wrapper over the java.io.File object. The key part is reading the file into a global string jsHelpers which is then injected into the page along with the JavaScript I wish to run.

Here is the File reading method:

  static void loadJSHelpers() {
    comment("Loading helpers.js")
    jsHelpers = new File("get/my/project/path/" + "helpers.js").getText("UTF-8")
  }

Here is the wrapper over WebUI.executeJavaScript which injects the content of jsHelpers

  /**
   * Execute JavaScript.
   * @param jsString (String) The JavaScript code to be executed.
   * @param args (List) Arguments to be passed to JavaScript.
   * @return The result returned from JavaScript.
   */
  static Object jsexec(String jsString, List<Object> args) {
    String js = jsHelpers + $/
      try {
        ${jsString}
      } catch(e) {
        console.log('JS in Groovy ***ERROR*** - ' + e.message);
        return e.message;
      }
    /$
    def result = WebUI.executeJavaScript(js, args)
    if(result.toString().startsWith("JS in Groovy")) {
      KeywordLogger log = new KeywordLogger()
      log.logError(result.toString())
      comment(result.toString())
    }
    return result
  }

Note: I believe the logging system may have changed recently so don’t pay too much attention to my error handling (you probably want to write your own anyway).


#9

Ok, unfortunately your code doesn’t help me :confused:

I’m always getting the same error: “Uncaught ReferenceError: SaveToken is not defined”

I have stripped down our login page to a very simple html page, but I can’t get it work. Here is the page:
login.html (930 Bytes)


#10

Daniel

Here’s my test case:

import static com.blah.utils.*
import static com.blah.js.*
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI

public class Test {
  Test() {
    WebUI.navigateToUrl("file:///F:/Utils/login.html")
    jsexec("function r(){ document.querySelector('#inputUser').value = 'russ';};r();", null)
  }
}

try {
  new Test()
  passThisTest()
} catch(Exception e) {
  failThisTest(e.message)
  throw e
}

Here’s the page:

image