Protractor: How do I inject a javascript file into the DOM and use its functions in a test

Created on 3 Oct 2015  路  2Comments  路  Source: angular/protractor

I am trying to use Protractor for testing content scripts of a chrome extension. Chrome extension framework has a method for injecting a javascript file that you specify into the DOM and run it in a semi-isolated mode.

I want to simulate that by injecting the scripts myself into the DOM and then interacting with that JS and run some tests against the javascript that was inject.

So far I have figured out how to inject the javascript into the DOM. That part work but I can't seem to access the injected code in my tests. the variable dm which I set in the injected script is not accessible in the Protractor scope for some reason.

My tests:

describe('inject content script -', function () {

var contentScript;

beforeEach(function () {
    browser.driver.ignoreSynchronization = true;
    browser.driver.get('http://cnn.com');
    browser.executeScript(function () {

        //Script loading function
        function load_script(urls) {

            for (i = 0; i < urls.length; i++) {
                var new_script = document.createElement('script');
                new_script.type = 'text/javascript';
                new_script.src = urls[i];
                new_script.async = false;
                new_script.defer = false;

                document.getElementsByTagName('head')[0].appendChild(new_script);
                console.log("injected " + urls[i]);
            }
        }

        load_script([
            "http://localhost:8000/bower_components/jquery/dist/jquery.min.js",
            "http://localhost:8000/src/js/content-lib.js"
        ]);

        console.log("finished injecting scripts");

        // now attempting to wait until variable dm set by content script 
       //  as global variable in DOM
        function checkVariable() {
            if (dm != undefined) {      
                return dm;        //     <=  this is never reached because dm is always undefined.
            }
            else {
                setTimeout(checkVariable(), 100);
            }
        }

        console.log("wait for dm to be ready");
        checkVariable();

    }).then(function (dm) {
        console.log("dm is ready");
        console.log(dm);
        contentScript = dm;
    });

    console.log("contentScript is ready");
    console.log(contentScript);
});

it('basic content verication test', function () {
      console.log(contentScript);
});

});

content-lib.js file:

dm = {};
dm.test=function (){
return "Hello world";
}

Some questions:

Will beforeEach() wait until all the injected scripts are loaded before execution is passed to it() call?

How can I interact with the code that was injected into a DOM dynamically.

Most helpful comment

I solved the problem. This works in case someone else is looking for it.

beforeAll(function (done) {
    browser.driver.ignoreSynchronization = true;
    browser.driver.get('http://cnn.com');
    browser.executeAsyncScript(function () {

        var callback = arguments[arguments.length - 1];

        //Script loading function
        function load_script(urls) {

            for (i = 0; i < urls.length; i++) {
                var new_script = document.createElement('script');
                new_script.type = 'text/javascript';
                new_script.src = urls[i];
                new_script.async = false;
                new_script.defer = false;

                document.getElementsByTagName('head')[0].appendChild(new_script);
                console.log("injected " + urls[i]);
            }

            console.log("finished injecting scripts");
        }

        console.log("Before scripts");
        load_script([
            "http://localhost:8000/src/js/content-lib.js"
        ]);

        setTimeout(function () {
            callback(window.dm);
        }, 2000);

    }).then(function (dm) {
        xm = dm;
        done();
    });

}, 10000); // wait 10 seconds to timeout the script injection

All 2 comments

Hi there!

Your question is better suited for StackOverflow or Gitter. Please ask a question there with the 'protractor' tag or post in the Gitter Channel to get help.

From the the getting help section of the README:

Please ask usage and debugging questions on StackOverflow (use the "protractor" tag) or in the Angular discussion group. (Please do not ask support questions here on Github.)

I solved the problem. This works in case someone else is looking for it.

beforeAll(function (done) {
    browser.driver.ignoreSynchronization = true;
    browser.driver.get('http://cnn.com');
    browser.executeAsyncScript(function () {

        var callback = arguments[arguments.length - 1];

        //Script loading function
        function load_script(urls) {

            for (i = 0; i < urls.length; i++) {
                var new_script = document.createElement('script');
                new_script.type = 'text/javascript';
                new_script.src = urls[i];
                new_script.async = false;
                new_script.defer = false;

                document.getElementsByTagName('head')[0].appendChild(new_script);
                console.log("injected " + urls[i]);
            }

            console.log("finished injecting scripts");
        }

        console.log("Before scripts");
        load_script([
            "http://localhost:8000/src/js/content-lib.js"
        ]);

        setTimeout(function () {
            callback(window.dm);
        }, 2000);

    }).then(function (dm) {
        xm = dm;
        done();
    });

}, 10000); // wait 10 seconds to timeout the script injection
Was this page helpful?
0 / 5 - 0 ratings