I just want to know that whether this approach is good or not while using chai-as-promised with mocha and protractor?
let options = customers.all(by.tagName('option'));
options.then(function (items){
for(let i=0 ; i<items.length ; i++){
items[i].getText().then(function(txt:any){
if(txt == "ABC XYZ"){
items[i].click();
}
})
}
});
First of all you should learn more about chai plugin chai-as-promise. Visit This url to know more about this plugin.
Second you need to understand that this plugin is meant for handling assertion statement that has dependency on some promise. It is not meant for dealing all the promises. If you are new then you should learn using async/await with protractor.
Refer this post for more details
first source
second source
Related
Firstly, Karate UI automation is really awesome tool. I am kind of enjoying it while writing the UI tests using Karate. I ran into a situation where in, i was trying to fetch the shadowRoot elements. I read few similar posts related to javascript executor with karate and learnt that it is already answered. it is recommended to use driver.eval. But in Karate 0.9.5 there is no eval, it has script() or scriptAll(). I have gone through documentation couple of times to figure out how i can fetch element inside an element but no luck.
Using traditional selenium+java, we can fetch shadowRoot like this way:
something like shadowRoot which sits inside a parent element like div or body.
//downloads-manager is the tagname and under that downloads-manager, a shadowRoot element exists
The HTML looks like this. it is from chrome://downloads.
<downloads-manager>
#shadow-root(open)
</download-manager>
WebElement downloadManager =driver.findElement(By.tagName("downloads-manager");
WebElement shadowRoot= (WebElement)((JavaScriptExecutor)driver)
.executeScript("return arguments[0].shadowRoot",downloadManager);
So i tried the following in Karate UI
script("downloads-manager","return _.shadowRoot"); //js injection error
script('downloads-manager', "function(e){ return e.shadowRoot;}"); // same injection error as mentioned above.
def shadowRoot = locate("downloads-manager").script("function(e){return e.shadowRoot};"); //returns an empty string.
I bet there is a way to get this shadowRoot element using Karate UI but i am kind of running out of options and not able to figure out this.
Can someone please look into this & help me?
-San
Can you switch to XPath and see if that helps:
* def temp = script('//downloads-manager', '_.innerHTML')
Else please submit a sample in this format so we can debug: https://github.com/intuit/karate/tree/develop/examples/ui-test
EDIT: after you posted the link to that hangouts example in the comments, I figured out the JS that would work:
* driver 'http://html5-demos.appspot.com/hangouts'
* waitFor('#hangouts')
* def heading = script('hangout-module', "_.shadowRoot.querySelector('h1').textContent")
* match heading == 'Paul Irish'
It took some trial and error and fiddling with the DevTools console to figure this out. So the good news is that it is possible, you can use any JS you need, and you do need to know which HTML element to call .shadowRoot on.
EDIT: for other examples of JS in Karate: https://stackoverflow.com/a/60800181/143475
defineSupportCode(({Given, When,Then})=>{
When('click on search button', async () =>{
await browser.actions().sendKeys(protractor.Key.ENTER).perform();
await browser.sleep(3000)
await browser.actions().sendKeys(protractor.Key.ENTER).perform();
await browser.sleep(3000)
let element1 = element(by.xpath("//h3[text()='Selenium - Web Browser Automation']"))
await expect(element1.isDisplayed()).to.eventually.be.false;
});
Then('it should show search result', async () =>{
let element2 = element(by.xpath("//h3[text()='Downloads - Selenium']"))
await expect(element2.isDisplayed()).to.eventually.be.true;
});
})
My last then block was skipped.But I want to continue my all test steps even if it is pass or fail (then definitely i think i have to use soft assert).In testng we have a class called softassert. Is there something available here as well similar to that one. I am using chai package for assertion purpose
TIA
Background:
This is not a protractor or cucumber issue, it is actually chai(well it looks like you are using chai from your code snippet but feel free to correct me if I'm wrong).
Issue:
After reviewing chai docs https://www.chaijs.com/api/assert/ it looks like they do not support the concept of soft asserts like some other assertion frameworks.
Solution 1:
The only workaround I can think of is to wrap your assertion in a try catch and store the error received from the assertion in your world instance, then in your after hook throw the errors.
Solution 2:
Use a library that does support soft asserts. From a quick search, I see https://www.npmjs.com/package/soft-assert but FYI I have not tried this library
Notes:
One bad thing about this is that screenshots may capture incorrect information.
I am writing a protractor test, where I need to read a span/div with id='mylabel' using getText(). I then need to pass the value to an input (id='myinput') using sendKeys().
So, I do this:
var value;
element(by.id('mylabel')).getText().then(function(txt){
value = txt;
element(by.id('myinput')).sendKeys(value);
// do "other protractor tasks" with 'value'.
})
But, is there a way I can avoid the nesting, by asking protractor to perform sendKeys and subsequent actions only after the value variable is set?
The above is a simple case, but I soon find code getting into multiple nesting because of the waiting for promises to be resolved. Also, I observed that protractor does not provide a stacktrace if "other protractor tasks" throws an error due to an error somewhere down the line (it just hangs and times out).
I am using Protractor 2.1.0 and I am working with Angular JS pages.
I am specifically interested to know if it is a known issue to have silent errors in nested tasks with Protractor and is there anyway to solve it?
Protractor handle at least one level of promises without the need of then function. That way you can expect synchronous flow.
If you are looking for event based action like watching a value to update then you can setup something like this:
function waitForTextToUpdate(elm, defaultText, timeout) {
if (typeof(timeout) === 'undefined') {
timeout = 10000;
}
return browser.driver.wait(function() {
return elm.getText().then(function(value) {
return !(value.indexOf(defaultText) > -1);
});
}, timeout, "Expectation error (waitForTextToUpdate): Timed out waiting for element state to change.");
}
Promises are inevitable in protractor. There is no way to avoid handling promises, but if you want to avoid nesting it can be done easily using .then() chaining functionality. Here's an example -
var value = '';
element(by.id('mylabel')).getText()
.then(function(txt){
value = txt;
})
.then(function(){
element(by.id('myinput')).sendKeys(value);
// do "other protractor tasks" with 'value'.
});
There's also an npm package available for this feature. Q npm package. It works similar to the above example but is more extended.
Hope this helps.
I want to provide a way to use an on-event handler from the outside of a plugin. Problem is, that the trigger will not fired if I provide them in wrong order.
For example, this works:
$(window).on('foo:bar', function(){
alert(true);
});
$(window).trigger('foo:bar');
...this, however does not:
$(window).trigger('foo:bar');
$(window).on('foo:bar', function(){
alert(true);
});
Any ideas how the second approach can work?
Update
Here it works: http://www.benplum.com/projects/rubberband/
You cannot. You want to eat cake before baking it.
UPD: You're misinterpreting the code at http://www.benplum.com/projects/rubberband/
Here is a jsfiddle with proof that it doesn't work like you're thinking: jsfiddle.net/zerkms/z5Mya/
Note about code: I've forked the library and added trivial console.log here: https://github.com/zerkms/Rubberband/blob/master/jquery.bp.rubberband.js#L77
Due to some caching issues, I need to explicitly bypass the cache, for a specific module, if certain URL parameters are present. The workaround I've arrived at is to hack the render() function in libraries/joomla/document/html/renderer/module.php, along the lines of:
function render( $module, $params = array(), $content = null )
{
// Existing code:
$mod_params = new JParameter( $module->params );
// My hack:
if ($module->module == 'mod_foo')
{
if (certain URL parameters are present)
{
$mod_params->set('cache', 0);
}
}
...
}
Of course, hacking the core joomla code is a terrible idea, one which I'd like to avoid if at all possible. So, is there an appropriate hook I can plugin to in order to achieve the same? I don't think I can do anything at the module level, since it won't even be inspected if the renderer has already decided to fetch it from cache.
To answer the first question no there isn't a module render event, here's the plugin doc's and the list of events in Joomla!
Turn off caching for your module.
See this article on The Art Of Joomla, additional articles you could look at:
Using Cache to Speed Up your code
JCache API