ng:test no injector found for element argument to getTestability - javascript

There other question on SO with same problem, but the solutions didnt worked for me.
Here my spec.js
describe('Protractor Demo App', function() {
it('should have a title', function() {
browser.driver.get('http://rent-front-static.s3-website-us-east-1.amazonaws.com/');
expect(browser.getTitle()).toEqual('How It Works');
});
});
And here my conf.js
exports.config = {
framework: 'jasmine',
rootElement: 'body',
seleniumAddress: 'http://localhost:4444/wd/hub',
specs: ['spec.js']
}
So when i try to run my test im getting the error
Message:
Failed: Error while waiting for Protractor to sync with the page: "[ng:test] no injector found for element argument to getTestability\nhttp://errors.angularjs.org/1.5.0/ng/test"
Stack:
Error: Failed: Error while waiting for Protractor to sync with the page: "[ng:test] no injector found for element argument to getTestability\nhttp://errors.angularjs.org/1.5.0/ng/test"
at C:\Users\ShapeR\PycharmProjects\ratest\node_modules\jasminewd2\index.js:101:16
at Promise.invokeCallback_ (C:\Users\ShapeR\PycharmProjects\ratest\node_modules\selenium-webdriver\lib\promise.js:1329:14)
at TaskQueue.execute_ (C:\Users\ShapeR\PycharmProjects\ratest\node_modules\selenium-webdriver\lib\promise.js:2790:14)
at TaskQueue.executeNext_ (C:\Users\ShapeR\PycharmProjects\ratest\node_modules\selenium-webdriver\lib\promise.js:2773:21)
1 spec, 1 failure
I have a manual bootstrapping for body element and set the rootElement to body in config, but it didnt help. I even tried to remove manual boostraping and just add ng-app='rentapplicationApp' to body element, but it changes nothing, still same error.
So what is wrong?

The core value of Protractor is that it manages the angular loading for you, including sync, so you are very right in not wanting to use: browser.ignoreSynchronization = true.
The error message you are getting is that protractor is unable to locate angular in order to sync. This is because of a combination of two issues:
The page isn't ready, angular isn't loaded
It is unable to locate the ng-app, even once the page is loaded
Firstly, from Protractor setup page.
If your page does manual bootstrap Protractor will not be able to load your page using browser.get. Instead, use the base webdriver instance - browser.driver.get. This means that Protractor does not know when your page is fully loaded, and you may need to add a wait statement to make sure your tests avoid race conditions.
Solution 1
Add a wait statement.
Solution 2
If you don't have a good reason for manually bootstrapping, or don't want to wait:
Stop manually bootstrapping the app
Use browser.get over browser.driver.get

[ng:test] no injector found for element argument to getTestability
I suspect there is something wrong with the application itself, the way it is bootstrapped, since Protractor actually finds the root element (you can explicitly set the rootElement: "body.root" inside your config as well), but fails to setup the injector for the root element.
I'd try to figure out what is happening it step by step - first, try running the protractor test against a non-built application started directly from the source to ensure that this is not the webpack's or other part's of the build fault.
Then, I'd try upgrading to the latest 1.x Angular and Protractor (3.3.0 is the most recent version).
The most simple workaround at the moment would be to turn the sync between Protractor and Angular off, by using browser.ignoreSynchronization = true:
describe("Strange Protractor/Angular problem", function () {
beforeEach(function () {
browser.ignoreSynchronization = true;
browser.get("https://dl.dropboxusercontent.com/u/597502/vxcv/index.html");
var elm = $(".navbar-brand");
browser.wait(EC.presenceOf(elm), 5000);
});
it("should have an expected title", function () {
expect($(".navbar-brand").getText()).toEqual('RENT APPLICATION');
});
});
Of course, there are downsides to this approach - you would have to use browser.wait calls here and there to tackle the timing issue. The test flow would not be as natural and simple as it would be when sync is on.

The problem was in bootstrapping my app. For some reason it doesnt work with ng-app tag. The only working solution was to manual bootstrap it
angular.bootstrap(document, ["rentapplicationApp"]);
And first argument should be dom node, not a string, like it was in my case, although with string the app will work, but getTestability will fail.

Related

AngularJS 1.7 Module Injection For Tests Error

My AngularJS (1.7.x) application has a custom filter that I want to write tests around it, and I decided to use Jest to perform this task.
My main issue is that as I follow this tutorial by Curt, I am struggling to properly get the filter (which has no outside dependencies so I thought it was the prime target to introduce unit tests with) to load within the test harness.
For starters, here is a simplified version of the filter for the purpose of this question:
angular.module('app.module').filter('takeTheThing', () =>
function (parameter1) {
return `${parameter1} thing!`;
}
);
And, after following the tutorial above, as well as reading up on another SO question specific to testing AngularJS filters, I have attempted every conceivable version of my simple test file as follows but receive a cryptic error message from Angular about it:
require('../node_modules/angular/angular.min.js');
require('../node_modules/angular-mocks/angular-mocks.js');
//Commenting or un-commenting this, results in module-related injector errors:
//require('./takeTheThing.filter.js');
describe('The thingerizer', () => {
let $filter;
beforeEach(angular.mock.module('app.module'));
//Injecting this specifically, or _$filter_ still errors:
beforeEach(inject(takeTheThingFilter => {
$filter = takeTheThingFilter;
}));
//Injecting here instead of in the beforeEach, same issue
it('should give me something', () => {
//Calling the specific filter or thru the Angular $filter... Same
const actual = $filter(1);
expect(actual).toEqual('1 thing!');
});
});
I'm pulling my hair out, but there's something quite basic I'm missing in regards to the test setup (specifically, how to load the app "correctly" without whole-hog loading my entire application). What gives?
AngularJS: 1.7.5
Angular Mocks: 1.7.6
Jest: 23.6.0 (I am using gulp-jest but even when I directly call jest from within the bin folder, I get the exact same errors, so I omitted most of those details here)

Protractor - Giving "could not find testability for element" error when accessing element

I'm running into issue with Protractor when accessing variable that stores return value of "elements.all". I'm fairly new to Protractor, so I wasn't sure how to select elements by custom attribute. Luckily, I received a suggestion, when I posted a question in another post. I was suggested to try out - "element.all(by.css('[mycustom-id]'));". But I'm not sure if that statement works or not since I'm getting "Could not find testability for element" error. It is also possible that I'm incorrectly iterating the object. I appreciate if anyone of you can point out my mistake. Thanks.
Spec.JS
var settings = require(__dirname + '/setting.json');
describe('Protractor Demo App', function() {
var target = element.all(by.css('[mycustom-id]'));
beforeEach(function() {
browser.get(settings.url);
});
it('Test mouseover', function() {
// This does not work
target.each(function(item){
//Do some stuff here
});
// This does not work either
target.count().then(function(x){
console.log("Total--" + x);
});
});
});
index.html
<div>
<a mycustom-id="123" href=''>HELLO1</a>
<a mycustom-id="211" href=''>HELLO2</a>
</div>
I'm getting this error because I need to set useAllAngular2AppRoots to true in config file. So if anyone having similar issue, make sure you have useAllAngular2AppRoots set to True.
It's not a good practice to put things outside of Jasmine functions, i.e. outside of it(), beforeAll() etc. Protractor uses those Jasmine functions to manage the control flow.
So I'm guessing that it is trying to create those webElements way before it should be. Move your element locator inside the it() block.
it('Test mouseover', function() {
var target = element.all(by.css('[mycustom-id]'));
target.each(function(item){
//Do some stuff here
});
});

RequireJS main require call back never invoked

I've tried this post's advice to no avail. No matter what I do, RequireJS's primary callback is never fired. Here's my dependency graph:
/module/main.js
-- /module/mainController.js
--/vendor/preloadjs
--/module/itemController.js
--/module/router.js
--/vendor/crossroads.js
--/vendor/signals.js
--/vendor/hasher.js
--/vendor/signals.js
require.config({
baseUrl: "script/module",
paths: {
signals: "vendor/signals"
}
});
require(["main", function(){
console.log("main function!");
}]);
The "main" module makes use of js-signals, and actually gets invoked. In fact the entire dependency tree is loaded (confirmed via the web inspector). I have a single entry point for the application. All modules start up and actually run fine. You'd think that if the main application callback doesn't run that one or all of its dependencies would have failed.
I'm sure there is some stupid reason I'm not kicking off the primary require's callback. For the record I've tried using the requirejs() method and get the same results.
No files have code in them except for dependencies and console.logs.
Does anyone have any ideas for what I'm doing wrong?
I'll answer my own silliness. The problem is right there in the source. I'm using Angular module injection syntax, and passing the callback as part of the dependency array. Oops. It needs to be the second argument!
Long story short, the code is right, but this is the change:
require.config({
baseUrl: "script/module",
paths: {
signals: "vendor/signals"
}
});
require(["main"], function(){
console.log("main function!");
});

What are the contents of protactor.js

I was just going through the angular.js documentation HERE and saw the section called:
Multi-slot transclusion
and the following code in the protractor.js tab:
it('should have transcluded the title and the body', function() {
var titleElement = element(by.model('title'));
titleElement.clear();
titleElement.sendKeys('TITLE');
var textElement = element(by.model('text'));
textElement.clear();
textElement.sendKeys('TEXT');
expect(element(by.binding('title')).getText()).toEqual('TITLE');
expect(element(by.binding('text')).getText()).toEqual('TEXT');
});
I was just wondering if thats angular's version of jQuery
From E2E section of angular.js site:
Protractor is a Node.js program, and runs end-to-end tests that are also written in JavaScript and run with node. Protractor uses WebDriver to control browsers and simulate user actions.

How can you reset Knockout for each Jasmine test?

I have some feature tests that run with a fixture (loaded with jasmine-jquery) that has some Knockout bindings in the HTML. At the begin of each test I want to start with a viewModel in its initial state.
If I call applyBindings() in the beforeEach() with a new instance of the viewModel I get this error from Knockout
Error: You cannot apply bindings multiple times to the same element.
If I try to revert the properties of the existing viewModel to match its initial state I still get an error. I believe this is because the fixture's HTML is removed after each test - this probably breaks the bindings?
I've also tried a suggestion that came up when Googling which was to use the cleanNode function in Knockout. This isn't part of the API (it only designed to be used by Knockout internally) and no matter what I tried it didn't resolve the issue.
It feels like I'm taking the wrong approach to this. tl;dr; How does everybody else test Knockout with Jasmine?
Thanks for any help
I generally append an element in beforeEach, apply bindings to that element, and ko.removeNode on it in afterEach. Something like:
var fixture;
beforeEach(function() {
fixture = document.createElement("div");
document.body.appendChild(fixture);
});
afterEach(function() {
ko.removeNode(fixture);
});
Then use fixture as the second argument to any applyBindings calls like: ko.applyBindings(myTestViewModel, fixture);
The way I solved this was changing my js to check for jasmine e.g.:
if (!window.jasmine)
ko.applyBindings(viewModel);

Categories

Resources