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.
Related
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)
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.
I am currently using Webdriver IO, Chimp JS and Cucumber JS, and I'm having a bit of a hard time dragging an element to another element that's inside of an iframe. I've been able to locate the element I want to move, as well as the element in the iframe after using client.frame(0); however I haven't found a way to click on the element, switch to the iframe to locate the element I want to move to, then move the element.
To make it easier, here's a picture. I want to move element 1 to element 2. But element 2 is in an iframe:
Looking through the docs, I see a lot of potentially helpful actions like hold, release ext. But I am working on desktop, and so I can't use any of the mobile actions.
With this limitation, it looks like the only drag and drop function available to me is dragAndDrop, but there doesn't seem to be a way to drag and drop an object into an element in an iframe in the javascript version of Webdriver. Am I correct in thinking this? Is there someway to do this solely using Cucumber JS? I feel like I'm missing something huge here, but I can't seem to figure it out :\
The selenium standalone driver I used is selenium-server-standalone-2.50.0.jar(selenium-release.storage.googleapis.com/index.html?path=2.50/) and chrome driver I used is ChromeDriver 2.29 (https://sites.google.com/a/chromium.org/chromedriver/downloads)
var webdriverio = require('webdriverio'),
dragAndDrop = require('html-dnd').codeForSelectors,
should = require('should');
// a test script block or suite
describe('Title Test for Web Driver IO - Tutorial Test Page Website', function() {
// set timeout to 10 seconds
this.timeout(10000);
var driver = {};
// hook to run before tests
before( function () {
// load the driver for browser
driver = webdriverio.remote({ desiredCapabilities: {browserName: 'chrome'} });
return driver.init();
});
// a test spec - "specification"
it('should be load correct page and title', function () {
var sectionId = "";
// load page, then call function()
return driver
.url('http://localhost:9000') //your url
.pause(7000)
.moveToObject('#element1')
.buttonDown()
.moveToObject('#element2')
.buttonUp()
.pause(2000)
.end()
});
// a "hook" to run after all tests in this block
after(function() {
return driver.end();
});
});
I am trying to add jQuery selector controls to a phantomJS headless browser for testing purposes.
Is it possible?
To this point we have been overwriting the check to see if the control exists and haven't made any attempts to manipulate values and test onChange events.
The test I am wanting to run is this:
//arrange
//OnChange results in values being stored in cookies
$('#TestControl').val(cookieValue).trigger('change');
//act
var result = $.cookie(cookieName);
//assert
expect(result).toBe(cookieValue);
The problem is that I don't know how to actually create $('#TestControl')
For creating DOM elements in phantomJS/jasmine, you could do the following:
var TestControl = $('<input id="TestControl"/>');
$(document.body).append(TestControl);
However, it is better to define the markup in html. The fixture module of jasmine-jquery allows you to load HTML content to be used by your tests. The overall workflow is as follows:
In myfixture.html file:
<div id="my-fixture"><input id="TestControl"/></div>
Inside your test:
loadFixtures('myfixture.html')
$('#TestControl').val(cookieValue).trigger('change')
expect($('#my-fixture')).to...
I'm trying to TDD a purely front-end project based on a single HTML page using Jasmine and Karma to unit test.
The document of Jasmine tells nothing about DOM manipulations, which is one of the most important things I'm trying to test.
The question is simple, how do I examine the DOM changes and the content changes of a HTML page?
For example, say if I have code like below:
HTML file
Say Hello
JS file:
// Router
App.Router = Backbone.Router.extend({
routes: {
'': 'home',
'say_hello': 'sayHello'
}
});
var router = new App.Router();
router.on('route:sayHello', function(){
$("body").append("Hello World");
});
Backbone.history.start();
How do I test such behavior:
If someone clicks "Say Hello" link, the text in the html body will contain "Hello World"
And even more, how do I check the CSS changes or simulate HTML events (mouseover, focus, change, load, etc...)? Is that possible with Jasmine and Karma?
Thanks
TDD is to unit testing - unit - small methods with mocks, stubs and spies. Manipulation on the DOM should be done by methods and you want to tests those methods.
Instead of testing jQuery engine selector and method 'append' call some method. In the test create spy that will be expecting that your methods was called.
To check DOM manipulation you can use Jasmine jQuery matcher -https://github.com/velesin/jasmine-jquery
If you need to test small html snippets you should add them programatically to your test.
var fixture = '<h1>My HTML fragment</h1>';
document.body.insertAdjacentHTML(
'afterbegin',
fixture);
You can also manage to link stylesheets
var fixture = '<link rel="stylesheet" media="all" \
href="https://www.npmjs.com/static/css/index.css?last-changed=10d466883fa405391313dc8294e783fd">\
<header><div class="header-item header-nav-menu-container">\
<h1 style="color:#FFF">My HTML fragment</h1></div></header>';
document.body.insertAdjacentHTML(
'afterbegin',
fixture);
Also to serve the stylesheets with karma you should add the to the list of files and link them like this