Protractor with Angular Mocks Throws "Window Not Defined"
Asked Answered
M

3

10

I've searched around quite a bit on this problem, but can't find a solution.

I'm trying to mock my backend, which is well tested so I can completely isolate my frontend. I've tried using protractor-http-mock and also various efforts with angular-mocks.

Having settled on the angular-mocks method with HttpBackend, I'm getting this error when firing up my protractor tests:

MBP:test-site admin$ protractor protractor.conf.js
Using ChromeDriver directly...
[launcher] Running 1 instances of WebDriver
[launcher] Error: ReferenceError: window is not defined
    at Object.<anonymous> (/Users/Ed/Sites/F4F/web/node_modules/angular/angular.js:30426:4)
    at Module._compile (module.js:413:34)
    at Object.Module._extensions..js (module.js:422:10)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Module.require (module.js:367:17)
    at require (internal/module.js:16:19)
    at Object.<anonymous> (/Users/Ed/Sites/F4F/web/node_modules/angular/index.js:1:1)
    at Module._compile (module.js:413:34)
    at Object.Module._extensions..js (module.js:422:10)
[launcher] Process exited with error code 100

This is my protractor.conf.js

exports.config = {

    directConnect: true,

    // Capabilities to be passed to the webdriver instance.
    capabilities: {
        'browserName': 'chrome'
    },

    chromeOnly: true,
    chromeDriver: './node_modules/protractor/selenium/chromedriver',

    // Framework to use. Jasmine 2 is recommended.
    framework: 'jasmine2',

    baseUrl: 'http://localhost:5000/',
    seleniumAddress: 'http://127.0.0.1:4444/wd/hub',

    // Spec patterns are relative to the current working directly when
    // protractor is called.
    specs: ['./tests/**/*.js'],

    // Options to be passed to Jasmine.
    jasmineNodeOpts: {
        showColors: true,
        defaultTimeoutInterval: 30000
    }

};

And this is my test:

'use strict'

var angular         = require('angular');
var angular_mock    = require('angular-mocks');
var HttpBackend     = require('httpbackend');
var backend         = null;

describe("Footer", function () {

    beforeEach(function() {
        backend = new HttpBackend(browser);
    });

    afterEach(function() {
        backend.clear();
    });

    describe("Display Values", function () {

        it("should show correct contact details", function () {

            backend.whenGET(/app/).respond({
                "name": "ExampleApp",
                "company": {
                    "code": "EXA",
                    "name": "ExampleApp",
                    "brand_name": "ExampleApp",
                    "head_office_id": 3,
                    "display_email": "[email protected]",
                    "display_tel": "+44 (0) 1234 56789"
                }
            });

            browser.get('/');

            var tel_li      = $('#footer .top li:first-child');
            var email_li    = $('#footer .top li:last-child');

            expect(tel_li.getText()).toEqual('+44 (0) 1234 56789');
            expect(email_li.getText()).toEqual('[email protected]');

        });
    });
});

Can anybody help please?

--- Responding to @alecxe's comment

Revising the test to look like this:

'use strict'

describe("Footer", function () {

    describe("Display Values", function () {

        it("should show correct contact details", function () {

            browser.get('/');

        });
    });
});

Gives the following result:

MBP:test-site admin$ protractor protractor.conf.js
Using ChromeDriver directly...
[launcher] Running 1 instances of WebDriver
Started
.


1 spec, 0 failures
Finished in 0.749 seconds
[launcher] 0 instance(s) of WebDriver still running
[launcher] chrome #1 passed
Munda answered 17/2, 2016 at 13:10 Comment(9)
Sounds like a problem with the app itself: what if you go to http://localhost:5000/ - do you see the app loaded and no errors on the console?Halicarnassus
Yep! Outside of the testing the app runs fine. This http call is resolved perfectly via UI-Router. I can use the app as normal. I've pretty much developed it and I'm now coming back to write tests before deployment. I know that's naughty, but...Munda
I've also searched the whole app for loose variables named 'window' on the off chance, but nothing comes up.Munda
Okay, what if you remove all of the requires and mocks from the test and leave browser.get() only - is it passing now with no errors? Thanks!Halicarnassus
@Halicarnassus I'll put the revised test below the last paragraph above.Munda
The problems arise as soon as I start including angular-mocks. If I run the tests to match the data in the backend, everything works fine. When including angular-mocks start mocking responses from the backend, the "ReferenceError: window is not defined" error appears.Munda
I have the same problem with mocha framework, do you resolve it?Unpromising
I still haven't solved this problem.Munda
In case anyone else stumbled upon this problem and is running Angular 2, look no further - mock modules is not supported in Angular 2. None of the answers provided here works on Angular 2. Took me a while to figured this out. #36354733Hinder
H
1

Don't import angular-mocks and angular at all, httpbackend don't need them to be imported:

'use strict'

var HttpBackend     = require('httpbackend');
var backend         = null;

describe("Footer", function () {

    beforeEach(function() {
        backend = new HttpBackend(browser);
    });

    afterEach(function() {
        backend.clear();
    });

    describe("Display Values", function () {

        it("should show correct contact details", function () {

            backend.whenGET(/app/).respond({
                "name": "ExampleApp",
                "company": {
                    "code": "EXA",
                    "name": "ExampleApp",
                    "brand_name": "ExampleApp",
                    "head_office_id": 3,
                    "display_email": "[email protected]",
                    "display_tel": "+44 (0) 1234 56789"
                }
            });

            browser.get('/');

            var tel_li      = $('#footer .top li:first-child');
            var email_li    = $('#footer .top li:last-child');

            expect(tel_li.getText()).toEqual('+44 (0) 1234 56789');
            expect(email_li.getText()).toEqual('[email protected]');

        });
    });
});
Halicarnassus answered 17/2, 2016 at 16:21 Comment(4)
I copied and pasted your code to be sure, but it's still throwing exactly the same error as first mentioned..Munda
If I remove the require("angular"), the error changes from "Error: ReferenceError: window is not defined" to "Error: [$injector:nomod] Module 'ngMockE2E' is not available!" which surely implies that we need to include anuglar-mocks?Munda
@EdStephenson I think it's your application under test that should have angular-mocks loaded, not your test itself. And, you don't need to import angular in the test too.Halicarnassus
Including 'ngMockE2E' causes the whole app to fail both in the tests and when running normally. When running normally, every $http call errors with "Error: Unexpected request: GET". The tests fail with "ReferenceError: window is not defined" again. I also tried mocking the module in the beforeEach part of the test with the 'ngMockE2E' included, and this failed with and "Unexpected ." error. Presumably from the "angular.module(" element, although it didn't give a clear picture of where the unexpected dot was. I'm struggling to understand how this is so hard to get going...!Munda
U
1

I had your exact issue, and ended up solving it by importing angular-mocks as a raw string and injecting it via browser.addMockModule:

const fs = require('fs');
const ngMock = fs.readFileSync(__dirname + '/../../node_modules/angular-mocks/angular-mocks.js', 'utf-8');

browser.addMockModule('ngMockE2E', ngMock);
browser.addMockModule('e2e', function e2e() {
  angular.module('e2e', ['ngMockE2E'])
    .run(['$httpBackend', function($httpBackend) {
      // Your mocked calls here
    }])
});

This will force the driver to compile the script during runtime, where window is available. However, this breaks if you have browser.ignoreSynchronization = true; however.

Umbrian answered 21/2, 2017 at 17:38 Comment(0)
B
0

for me const { element } = require('angular'); was the cause of issue.

Removed this and it resolved my problem.

Billetdoux answered 6/9, 2022 at 17:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.