Karma Chai How to access DOM element - chai

I am writing test cases using Karma Mocha.
Following is my function:
fun : function()
{
if(a == 1)
$("#test").hide();
}
We set the DOM element property based on some condition.
While writing its test:
it('fun', function (){
var a = 1;
// how do I test the DOM element.
// Is it possible to access the DOM element of the source file in the test file.
})
I tried using chai-jquery but it accesses only body and not the other elements.I guess it works on DOM elements of test file.
Can anyone please help.?

I assume you have your jQuery loaded upon testing then you would select you element with $('#test') and then do you tests.
Like so:
describe('obj.fun', function (){
before(function() {
$('<div id="test"></div>').appendTo(document.body);
});
after(function() {
$('#test').remove();
});
it('should hide the element when a is 1', function() {
var $test = $('#test');
expect( $test.is(':hidden') ).to.be.false;
obj.a = 1;
obj.fun();
expect( $test.is(':hidden') ).to.be.true;
});
});

Related

CucumberJS tests passing even though it's not possible

I'm trying to convert some old ruby tests (which used cucumber, phantomjs and capybara) into JavaScript (using cucumber, phantomjs and selenium) as my project is 100% node based and I want to remove the Ruby dependency.
When I run the tests, they all pass. The problem is, I've not created the conditions for the test to pass yet so a pass is impossible. I'm not sure where I'm going wrong.
Here is my world.js file:
var {defineSupportCode} = require('cucumber');
var seleniumWebdriver = require('selenium-webdriver'),
By = seleniumWebdriver.By,
until = seleniumWebdriver.until;
function CustomWorld() {
this.driver = new seleniumWebdriver.Builder()
.withCapabilities(seleniumWebdriver.Capabilities.phantomjs())
.build()
// Returns a promise that resolves to the element
this.waitForElement = function(locator) {
var condition = seleniumWebdriver.until.elementLocated(locator);
return this.driver.wait(condition)
}
}
defineSupportCode(function({setWorldConstructor}) {
setWorldConstructor(CustomWorld)
});
And here is my step definitions file:
require('dotenv').config();
var chalk = require('chalk');
var {defineSupportCode} = require('cucumber');
var seleniumWebdriver = require('selenium-webdriver'),
By = seleniumWebdriver.By,
until = seleniumWebdriver.until;
defineSupportCode(function({ Given, When, Then }) {
Given(/^I show my environment$/, function (next) {
console.log(chalk.green("Running against:" + process.env.TARGET_URI))
next()
})
When(/^I visit "(.*?)"$/, function (url) {
return this.driver.get(url);
})
Then(/^I should be on "([^"]*)"$/, function(page_name) {
this.driver.get(process.env.TARGET_URI+'/'+page_name)
.then(function() {
return this.driver.getCurrentUrl();
})
})
Then(/^I should see "([^"]*)"$/, function (text) {
var xpath = "//*[contains(text(),'" + text + "')]";
var condition = seleniumWebdriver.until.elementLocated({xpath: xpath});
return this.driver.wait(condition, 5000);
});
})
The only possible tests that could be passing there are: When(/^I visit "(.*?)"$/... and Given(/^I show my environment$/...
For reference, here is my .feature file too:
Feature: Test the global header works as expected
Scenario: Header components should exist
Given I visit "/hello"
Then I expect to see a ".c-logo-bar" element
And I expect to see a ".c-search-bar" element
And I expect to see a ".c-main-nav-bar" element
Any ideas where I'm going wrong?

Accessing elements using $$ or elements in webdriverio

I want to access web elements using the $$ or elements command using webdriverio. I know they return array of web elements but I am facing tough time accessing them, probably because I am new to webdriverio.
I tried the below code:
var webdriverio = require('webdriverio');
var options = {
desiredCapabilities: {
browserName: 'firefox',
},
};
var client = webdriverio.remote(options);
client
.init()
.url(some url)
.isExisting(selector).then(function(isExisting)) {
if(isExisting) {
var bText = this.$$('textarea[name="message_text]') // this code onwards it is not working
bText.then(function (res) {
console.log(res.length);
console.log(res);
res.value.forEach(function (elem) {
return this.click(elem.ELEMENT)
.setValue(elem.ELEMENT,'some text')
.keys('Enter')
})
})
In the above code, I can see the array res in console but the forEach loop doesn't seem to work. I want to perform click, setValue and keys('Enter') for each of the element present in this.$$('textarea[name="message_text"]') also not able to understand why the returned elements are in a form of JSON objects?
If anyone could guide me in right direction that would help!
Use 'client' instead of 'this' to select the elements.
var bText = client.$$('textarea[name="message_text]') // this code onwards it is not working
bText.then(function (res) {
console.log(res.length);
console.log(res);
See use of runner here -
https://github.com/webdriverio/webdriverio/issues/1043
#ChristianB's suggestion worked actually,since webdriverio's standalone app is built on top of webdriverjs whose methods return promises we need to resolve them properly.I was able to do this using map & Promise.all :
var bText = this.$$('textarea[name="message_text]')
bText.then(function (res) {
console.log(res.length);
console.log(res);
var promises = res.map(function (elem) {
return client
.elementIdClick(elem.ELEMENT)
.setValue(elem.selector,'some text')
.keys('Enter')
})
return Promise.all(promises)
})

Check if image is valid and loaded with Protractor

I am writing tests using Protractor (with Cucumber.js, Chai and Chai As Promised, though I think these details don't matter). I would like to write a test that checks whether an image element is valid and loaded - i.e. that it has a src attribute and has not errored out while loading.
There are some nice-looking answers elsewhere to the question of how to check if an image is loaded from within a browser, via the DOM API. But how can I cleanly perform this check using Protractor's API?
I expect my test will look something like:
this.Then(/^I should see the "([^"]*)" image$/, function (imageId, callback) {
expect(
element(by.id(imageId))
).to.eventually.satisfy(isImageOk).notify(callback);
});
but I don't know how to implement the isImageOk function via the Protractor API.
You need to evaluate a JavaScript expression in the context of the browser, using Protractor's executeAsyncScript function.
Here is the code from my answer to a similar question:
it('should find all images', function () {
browser.executeAsyncScript(function (callback) {
var imgs = document.getElementsByTagName('img'),
loaded = 0;
for (var i = 0; i < imgs.length; i++) {
if (imgs[i].naturalWidth > 0) {
loaded = loaded + 1;
};
};
callback(imgs.length - loaded);
}).then(function (brokenImagesCount) {
expect(brokenImagesCount).toBe(0);
});
});
The function executed within the browser returns the number of non-loaded images.
Just an updated version of the previous answer - test is made to fail if there are broken images, because we expect 0
it('should check if there are broken images', function () {
browser.executeAsyncScript(function (callback: (arg0: number) => void) {
const imgs = document.getElementsByTagName("img");
let loaded = 0;
for (let i = 0; i < imgs.length; i++) {
if (imgs[i].naturalWidth > 0) {
loaded = loaded + 1;
}
}
callback(imgs.length - loaded);
})
.then(function (brokenImagesCount) {
expect(brokenImagesCount).toBe(0);
});
});

Can I use Ext's loader to load non-ext scripts/object dynamically?

In my ExtJS 4.0.7 app I have some 3rd party javascripts that I need to dynamically load to render certain panel contents (some fancy charting/visualization widgets).
I run in to the age-old problem that the script doesn't finish loading before I try to use it. I thought ExtJS might have an elegant solution for this (much like the class loader: Ext.Loader).
I've looked at both Ext.Loader and Ext.ComponentLoader, but neither seem to provide what I'm looking for. Do I have to just "roll my own" and setup a timer to wait for a marker variable to exist?
Here's an example of how it's done in ExtJS 4.1.x:
Ext.Loader.loadScript({
url: '...', // URL of script
scope: this, // scope of callbacks
onLoad: function() { // callback fn when script is loaded
// ...
},
onError: function() { // callback fn if load fails
// ...
}
});
I've looked at both Ext.Loader and Ext.ComponentLoader, but neither
seem to provide what I'm looking for
Really looks like it's true. The only thing that can help you here, I think, is Loader's injectScriptElement method (which, however, is private):
var onError = function() {
// run this code on error
};
var onLoad = function() {
// run this code when script is loaded
};
Ext.Loader.injectScriptElement('/path/to/file.js', onLoad, onError);
Seems like this method would do what you want (here is example). But the only problem is that , ... you know, the method is marked as private.
This is exactly what newest Ext.Loader.loadScript from Ext.4-1 can be used for.
See http://docs.sencha.com/ext-js/4-1/#!/api/Ext.Loader-method-loadScript
For all you googlers out there, I ended up rolling my own by borrowing some Ext code:
var injectScriptElement = function(id, url, onLoad, onError, scope) {
var script = document.createElement('script'),
documentHead = typeof document !== 'undefined' && (document.head || document.getElementsByTagName('head')[0]),
cleanupScriptElement = function(script) {
script.id = id;
script.onload = null;
script.onreadystatechange = null;
script.onerror = null;
return this;
},
onLoadFn = function() {
cleanupScriptElement(script);
onLoad.call(scope);
},
onErrorFn = function() {
cleanupScriptElement(script);
onError.call(scope);
};
// if the script is already loaded, don't load it again
if (document.getElementById(id) !== null) {
onLoadFn();
return;
}
script.type = 'text/javascript';
script.src = url;
script.onload = onLoadFn;
script.onerror = onErrorFn;
script.onreadystatechange = function() {
if (this.readyState === 'loaded' || this.readyState === 'complete') {
onLoadFn();
}
};
documentHead.appendChild(script);
return script;
}
var error = function() {
console.log('error occurred');
}
var init = function() {
console.log('should not get run till the script is fully loaded');
}
injectScriptElement('myScriptElem', 'http://www.example.com/script.js', init, error, this);
From looking at the source it seems to me that you could do it in a bit of a hackish way. Try using Ext.Loader.setPath() to map a bogus namespace to your third party javascript files, and then use Ext.Loader.require() to try to load them. It doesn't look like ExtJS actually checks if required class is defined in the file included.

looping through DOM / mootools sortables

I can't seem to get a handle on my list of sortables. They are a list of list elements, each with a
form inside, which I need to get the values from.
Sortables.implement({
serialize: function(){
var serial = [];
this.list.getChildren().each(function(el, i){
serial[i] = el.getProperty('id');
}, this);
return serial;
}
});
var sort = new Sortables('.teams', {
handle: '.drag-handle',
clone: true,
onStart: function(el) {
el.fade('hide');
},
onComplete: function(el) {
//go go gadget go
order = this.serialize();
alert(order);
for(var i=0; i<order.length;i++) {
if (order[i]) {
//alert(order[i].substr(5, order[i].length));
}
}
}
});
the sortables list is then added to a list in a loop with sort.addItems(li); . But when I try to get the sortables outside of the sortables onComplete declaration, js says this.list is undefined.
Approaching the problem from another angle:
Trying to loop through the DOM gives me equally bizarre results. Here are the firebug console results for some code:
var a = document.getElementById('teams').childNodes;
var b = document.getElementById('teams').childNodes.length;
try {
console.log('myVar: ', a);
console.log('myVar.length: ', b);
} catch(e) {
alert("error logging");
}
Hardcoding one li element into the HTML (rather than being injected via JS) changes length == 1, and allows me to access that single element, leading me to believe that accessing injected elements via the DOM is the problem (for this method)
Trying to get the objects with document.getElementById('teams').childNodes[i] returns undefined.
thank you for any help!
not sure why this would fail, i tried it in several ways and it all works
http://www.jsfiddle.net/M7zLG/ test case along with html markup
here is the source that works for local refernece, using the native built-in .serialize method as well as a custom one that walks the dom and gets a custom attribute rel, which can be your DB IDs in their new order (I tend to do that)
var order = []; // global
var sort = new Sortables('.teams', {
handle: '.drag-handle',
clone: true,
onStart: function(el) {
el.fade('hide');
},
onComplete: function(el) {
//go go gadget go
order = this.serialize();
}
});
var mySerialize = function(parentEl) {
var myIds = [];
parentEl.getElements("li").each(function(el) {
myIds.push(el.get("rel"));
});
return myIds;
};
$("saveorder").addEvents({
click: function() {
console.log(sort.serialize());
console.log(order);
console.log(mySerialize($("teams")));
}
});