9

Is it possible to inject a jQuery script into a page if the page isn't already using jQuery? We have a few pages in our sites where we don't add jQuery if it doesn't need it, but I'm using it to automate the page with WebDriver. I don't want to test my JavaScript on every browser just for these pages.

Example usage of jQuery code:

public static long GetLongValueViaJQuery(IWebDriver driver, string jQueryCode)
{
    IJavaScriptExecutor js = driver as IJavaScriptExecutor;
    return (long)js.ExecuteScript("return " + jQueryCode);
}
1
  • What are you trying to achieve by using jQuery with selenium webdriver? Jun 15, 2018 at 12:51

5 Answers 5

4

I haven't tested this, but in theory it should work. You can use javascript like this to load new js files into memory:

var scriptElt = document.createElement('script'); scriptElt.type = 'text/javascript'; scriptElt.src = jsFile; document.getElementsByTagName('head')[0].appendChild(scriptElt);

You would need to load all of the jquery javascript libraries and then you would be able to call the jqeury functions as you listed above.

3
  • Unless you load jQuery from the same domain as your webapp, you may run into this problem: sqa.stackexchange.com/questions/2850/….
    – user246
    Mar 27, 2012 at 17:57
  • Again, I haven't tested it, but I'm pretty sure the jquery javascript library employs domain lowering to work in this case. Very true that this could cause problems for a lot of .js files though.
    – Sam Woods
    Mar 28, 2012 at 0:12
  • basically, avoid linking a filen then just execute the script content, so the cross-domain problem will be never on your context.
    – m3nda
    Jan 7, 2017 at 5:47
9

Here is a script which loads jQuery through WebDriver. I've been using it successfully for quite some time.

Features:

-- will not overwrite any existing jQuery instance.
-- will not alter the DOM under test or pollute the global namespace
-- cleans up after itself to avoid memory leaks
-- waits for jQuery to be fully loaded before returning.
-- takes an optional parameter specifying a jQuery source (defaults to version 1.7.2 from Google's CDN).
-- cross-browser compatible

The Script:

You must pass this as a string to IJavaScriptExecutor.ExecuteAsyncScript:

/** dynamically load jQuery */
(function(jqueryUrl, callback) {
    if (typeof jqueryUrl != 'string') {
        jqueryUrl = 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js';
    }
    if (typeof jQuery == 'undefined') {
        var script = document.createElement('script');
        var head = document.getElementsByTagName('head')[0];
        var done = false;
        script.onload = script.onreadystatechange = (function() {
            if (!done && (!this.readyState || this.readyState == 'loaded' 
                    || this.readyState == 'complete')) {
                done = true;
                script.onload = script.onreadystatechange = null;
                head.removeChild(script);
                callback();
            }
        });
        script.src = jqueryUrl;
        head.appendChild(script);
    }
    else {
        callback();
    }
})(arguments[0], arguments[arguments.length - 1]);

Example Usage (Java):

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;

/**
 * An example of loading jQuery dynamically using WebDriver.
 */
public class Test {

    // its nice to keep JavaScript snippets in separate files.
    private static final String JQUERY_LOAD_SCRIPT = "resources\\jQuerify.js";

    // driver
    public static void main(String[] args) throws Exception {
        WebDriver driver = new FirefoxDriver();
        driver.get("http://www.google.com");

        String jQueryLoader = readFile(JQUERY_LOAD_SCRIPT);

        // give jQuery time to load asynchronously
        driver.manage().timeouts().setScriptTimeout(10, TimeUnit.SECONDS);
        JavascriptExecutor js = (JavascriptExecutor) driver;
        js.executeAsyncScript(jQueryLoader /*, http://localhost:8080/jquery-1.7.2.js */);

        // ready to rock
        js.executeScript(
            "jQuery(function($) { " +
                " $('input[name=\"q\"]').val('bada-bing').closest('form').submit(); " +
            " }); "
        );
    }

    // helper method
    private static String readFile(String file) throws IOException {
        Charset cs = Charset.forName("UTF-8");
        FileInputStream stream = new FileInputStream(file);
        try {
            Reader reader = new BufferedReader(new InputStreamReader(stream, cs));
            StringBuilder builder = new StringBuilder();
            char[] buffer = new char[8192];
            int read;
            while ((read = reader.read(buffer, 0, buffer.length)) > 0) {
                builder.append(buffer, 0, read);
            }
            return builder.toString();
        }
        finally {
            stream.close();
        }        
    }
}

Credits:

I adapted this script from the excellent jQuerify bookmarklet by Karl Swedberg.

1
  • I was writing a comment about that is not the same to link a file or url then raise the cross-domain problem, than just inject the content of that file directly :-)
    – m3nda
    Jan 7, 2017 at 5:45
2

Here is my extension method I am using with WatiN

The parameter Browser – is WatiN’s browser object.

And also, WitiN required to pass the JavaScript code as a single line. That is why you can see .Replace("\r\n", ""); in the code:

    public static void InjectJQuery(this Browser browser)
    {
        string injectjQuery2 = @"
               function loadScript(scriptUrl) 
               {
                   var head =  document.getElementsByTagName('head')[0];
                   var script = document.createElement('script');
                   script.type = 'text/javascript';
                   script.src = scriptUrl;
                   head.appendChild(script);
               }
               loadScript('https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js');
               loadScript('https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.js');
               ".Replace("\r\n", "");

        browser.Eval(injectjQuery2);
    }
1
  • Clean solution, I like it.
    – Sam Woods
    Mar 28, 2012 at 0:12
2

Here is how it works in Ruby:'

      # test.rb
      require 'selenium-webdriver"
      @browser = Selenium::WebDriver.for :chrome
      @browser.navigate.to "http://www.google.com"
      dir_to_jquery = Dir.pwd + '/features/support/ajax_resources'
      # jQuerify.js is the same java script posted above by Joe Coder
      jquerystring = File.open("#{dir_to_jquery}/jQuerify.js").read

      #Give time for script to load and inject jquery library dynamically
      @browser.manage.timeouts.script_timeout = 10
      @browser.execute_async_script(jquerystring)
      @browser.execute_script("jQuery(function($) { " +" $('input[name=\"q\"]').val('[email protected]').closest('form').submit(); " +" }); ");
-1

I am seeing one issue in this. I am getting "Exception in thread "main" org.openqa.selenium.WebDriverException: jQuery is not defined" exception on executing js.executeAsyncScript(jQueryLoader);

1
  • This looks like a commentary on the post and not an actual answer to the question. Plus this is a very old question you are answering. Consider elaborating a bit further.
    – Dan Snell
    Apr 5, 2014 at 23:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.