I am working on angular app automation where I have written a common function which needs to called at multiple places in my tests to get the form id which is generating dynamically. This function is always returning me {[[PromiseStatus]]: "pending"}"] error.
CommonFunctions.js
var common_functions = function() {
this.getFormId = function() {
// var url = "http://localhost/test/#/submission/207/form/1976";
return browser.getCurrentUrl().then(function(url){
return url.substr(-4);
});
}
};
Now this function is being used in pageobject file to get the element locator.
PageObject file:
var general_information = function() {
this.street1 = function(field1) {
var formid = common_functions.getFormId();
var street="fieldValue.street1_".concat(formid);
element(by.model(street)).sendKeys(field1);
}
Finally when i invoke this function in my test script, I get error.
Test script:
it("Verify that user is able to fill values in general information", function(){
general_information.street1('Street Victoria');
general_information.zipCode('1004');
});
Exception appearing:
Failed: invalid element state: Failed to execute 'querySelectorAll' on 'Document': '[ng-model="fieldValue.street1_Promise::1833 {[[PromiseStatus]]: "pending"}"]' is not a valid selector.
(Session info: chrome=50.0.2661.94)
(Driver info: chromedriver=2.21.371459 (36d3d07f660ff2bc1bf28a75d1cdabed0983e7c4),platform=Windows NT 6.1 SP1 x86_64)
Can somebody help me with this where I am doing it wrong?
That's because the getFormId() function returns a promise. And, since you need a value into which a promise is resolved, you need to use .then():
this.street1 = function(field1) {
common_functions.getFormId().then(function (formid) {
var street = "fieldValue.street1_".concat(formid);
element(by.model(street)).sendKeys(field1);
});
}
Related
As the title suggests, I am trying to use promiseToFuture (function of the dart library dart:js_util) on an object deriving from the method of DART:JS which is context.callmethod (''), whose objective is to perform a JavaScript function, which identifies through the string passed as a parameter; The code below:
void onWalletConnect() {
var promiseWallet =
await promiseToFuture(js.context.callMethod('JsConnectWallet'));
// ignore: avoid_print
print(promiseWallet);
if (promiseWallet['address'].compareTo('errorAddress') != 0) {
setState(() {
walletAddress = promiseWallet['address'];
isWalletconnect = true;
});
}
}
// "`js.context.callMethod('..')` Returns an Object Promise; "
Below the import:
import 'dart:js' as js;
import 'dart:js_util';
To the execution of promisetofutures() [and I am sure that this is the function that generates error and not the js.context.callMethod()] I get the following error from the Chrome console:
"
Uncaught (in promise) TypeError: js.Promise.then in not a function
at Object.promiseToFuture (js_util.dart:275:35)
at _first._MyHomePageState.new.OnWalletConnect (_first.dart:28:1)
"
I don't understand why you generate this error and how to solve it, can anyone help me?
I have created a IndexedDB setup in my ReactJs PWA.
The following error is thrown:
NotFoundError: Failed to execute 'transaction' on 'IDBDatabase': One of the specified object stores was not found.
at line userSearchDBtx = userSearchDB.transaction("userdata","readwrite")
My function looks like this:
function Users() {
let userSearchDB,userSearchDBstore,userSearchDBtx;
let userDbrequest = window.indexedDB.open("MyTestDatabase", 1);
useEffect(()=>{
if (!window.indexedDB) {
console.log("Your browser doesn't support a stable version of IndexedDB. Such and such feature will not be available.");
}
else console.log("IndexedDB supported")
userDbrequest.onupgradeneeded = function(event) {
userSearchDB = event.target.result;
userSearchDBtx = event.target.transaction;
userSearchDBstore = userSearchDB.createObjectStore("userdata",{keyPath:"uid"})
};
userDbrequest.onerror = function(event) {
console.log("ERROR: " + event.target.errorCode)
};
userDbrequest.onsuccess = function(event) {
console.log("IndexdDb Working")
userSearchDB = event.target.result
userSearchDBtx = userSearchDB.transaction("userdata","readwrite");
userSearchDBstore = userSearchDBtx.objectStore("userdata");
};
//Here also put is unknown
userSearchDBstore.put({uid:3854238974,phone:3257777,name:"shan",email:"1#1.com"})
},[])
}
let userDbrequest = window.indexedDB.open("MyTestDatabase", 1);
Place this line in useEffect()
The code should be
let userSearchDB,userSearchDBstore,userSearchDBtx,userDbrequest;
useEffect(()=>{
userDbrequest = window.indexedDB.open("MyTestDatabase", 2);
...Conrinue your code
},[])
Also, Increment the version while doing so
You are calling userSearchDBstore.put(...) before the db connected, which means no guarantee upgrade needed callback completed, which means no guarantee store created.
You need to wait. Move the put call to within the open db request success callback so that it only runs once database is upgraded.
I found out the cause was the wrong storeNames at: const request = db .transaction(storeNames , "readwrite")
I am trying to pass a variable representing an array between describe functions and I am having no luck. I have used protractor before but never passing variables between describes before. any help would be appreciated.
I combed through the stack over flow pages and could not find a solution.
I even tried to put each describe into a function but protractor said specs not found.
describe('WFN Admin Login Test', function() {
var EC = protractor.ExpectedConditions;
it('Load WFN home page - completed', function() {
browser.get('https://wfn-iat.adp.com/public/index.htm');
expect(browser.getCurrentUrl()).toEqual('https://wfn-iat.adp.com/public/index.htm');
});
var fs = require("fs");
var text = fs.readFileSync("/Users/hoflerj/Desktop/Protractor/clients/clientids.txt").toString('utf-8');
var file = text.split("\n");
console.log(file);
var arrayClient = file;
arrayClient.forEach(function(client){
//call other describe function to pass client variable below
});
});
describe('Get_CycleStatus', function() {
var EC = protractor.ExpectedConditions;
it('Enter Client-ID ', function () {
var search1 = ($$('input[id="toolbarQuickSearch"]').get(0));
browser.wait(EC.elementToBeClickable(search1),20,000).then(function() {
search1.clear().sendKeys('midrfrate'); //----client array variable here
search1.sendKeys(protractor.Key.BACK_SPACE);
browser.sleep(2000);
});
var dropdown = element(by.linkText("midrfrate"));//----client array variable
dropdown.click();
browser.sleep(2000);
});
I will eventually do a loop so that I can input the next client name any help how to do this with protractor would be most helpful. Also after setting up this global variable how would i use a loop to send this to another describe statement?
In your describe call the desired params with browser.params.paramName (in your case browser.params.arrayClient)
For your loop use an array or an object like so:
params: {
array:[ {
glob:'arrauClient',
glob2:'blabla'
}]
then call it in your describe with browser.params.glo
I have an Angular module, validation, which is declared like so:
(function(ns){
ns.validation = angular.module("validation", []);
})(blog);
The module contains two services, validator and validationRulesProvider, which look like:
(function(module){
module
.factory("validationRulesProvider", function(){
var _getRules = function() {
return [{
isValid: function(post) {
return post.length > 0;
}
}];
};
return {
getRules: _getRules
};
});
})(blog.validation);
and
(function(module){
module
.factory("validator", ["validationRulesProvider", function(validationRulesProvider){
var _validate = function(post) {
var rules = validationRulesProvider.getRules();
for (var rule in rules) {
if (!rule.isValid(post)) {
return false;
}
}
return true;
};
return {
validate: _validate
};
}]);
})(blog.validation);
I am attempting to test (using Jasmine) that
The getRules method on validationRulesProvider is actually called from the validate method
The post parameter is run through each rule returned from said method
I have the following Jasmine test script:
describe("Validator: ", function(){
var _validator;
var _mockedValidationRulesProvider;
var _mockRule;
beforeEach(function(){
module("validation");
inject(function(validationRulesProvider){
_mockedValidationRulesProvider = validationRulesProvider;
});
_mockRule = jasmine.createSpy();
spyOn(_mockedValidationRulesProvider, "getRules")
.and
.returnValue([{
isValid: _mockRule
}]);
inject(function(validator){
_validator = validator;
});
});
describe("getRules - ", function(){
it("gets a collection of rules from the rules provider", function(){
_validator.validate("");
expect(_mockedValidationRulesProvider.getRules).toHaveBeenCalled();
});
it("should pass the post through each rule received from the rules provider", function(){
expect(_mockRule.calls.count()).toEqual(_mockedValidationRulesProvider.getRules().length);
});
});
});
So, I'm simply trying to create a fake implementation of validationRulesProvider.getRules. My trouble is that both of these tests fail. If I alter the line:
spyOn(_mockedValidationRulesProvider, "getRules")
.and
.returnValue([{
isValid: _mockRule
}]);
to simply be
spyOn(_mockedValidationRulesProvider, "getRules")
.and
.returnValue([]);
then the first of the two tests pass, as the loop in validator.validate will never be entered.
Karma gives the following output:
PhantomJS 1.9.8 (Windows 7) Validator: getRules - gets a collection of rules from the rules provider FAILED
TypeError: 'undefined' is not a function (evaluating 'rule.isValid(post)')
at C:/Users/User/JS/Angular/Learning/blogsite/scripts/validation/validator.js:8
at C:/Users/User/JS/Angular/Learning/blogsite/scripts/tests/validator.test.js:32
PhantomJS 1.9.8 (Windows 7) Validator: getRules - should pass the post through each rule received from the rules provider FAILED
Expected 0 to equal 1.
at C:/Users/User/JS/Angular/Learning/blogsite/scripts/tests/validator.test.js:37
PhantomJS 1.9.8 (Windows 7): Executed 5 of 5 (2 FAILED) (0 secs / 0.039 secs)
I'm a bit of a loss as to why the tests are failing in the first instance because it seems like what I should be returning from the spy is an array of one object which contains an "isValid" function - which is exactly what is returned from the actual implementation of that function.
What am I doing wrong?
When you want to loop an array in javascript, you need to use javascript basic 'for loop' instead of 'for-in loop'.
The code in your validator factory should be like this.
for (var i = 0; i < rules.length; i++) {
var rule = rules[i];
if (!rule.isValid(post)) {
return false;
}
}
I am trying to get the hang of using indexedDB to store data client side.
consider the following code:
function queryURL(message, sender)
{
chrome.contextMenus.removeAll();
var openRequest = indexedDB.open("Tags",1);
openRequest.onsuccess = function(event){
var queryURL = message['host'];
var db = event.target.result;
var objectStore = db.transaction("domains").objectStore("domains");
var query = objectStore.get(queryURL);
query.onsuccess = function(event){
alert(query.result);
delete query.result["domain"];
createMenuItems(query.result);
available_commands=request.result;
};
db.onerror = function(event){
console.log("an error bubbled up during a transaction.");
};
};
openRequest.onerror = function(event){
console.log("error opening DB");
};
}
I do not fully understand what should be happening in the query.
The result is the same whether or not the key that is queried for is in the database:
query.onsuccess() runs and query.result is undefined so the
code errors and exits as soon as I try to delete a key from
query.result.
If the key is not found, query.onsuccess() should not be
running, correct?
If the key is found, query.result should hold the object that
corresponds to that key, correct?
In case it helps, here is the code that I used to initialize the database:
const db_name="Tags";
var request = window.indexedDB.open(db_name, 1);
var tags = [
//codes: 0 - markdown wrap tag
// 1 - HTML wrap tag
// 2 - single tag
{ domain: "www.youtube.com",
bold:["*",0],
strikethrough:["-",0],
italic:["_",0]
},
{ domain: "www.stackoverflow.com",
bold:["<strong>",1],
italic:["<em>",1],
strikethrough:["<del>",1],
superscript:["<sup>",1],
subscript:["<sub>",1],
heading1:["<h1>",1],
heading2:["<h2>",1],
heading3:["<h3>",1],
blockquote:["<blockquote>",1],
code:["<code>",1],
newline:["<br>",2],
horizontal:["<hr>",2]
}
];
request.onerror = function(event) {
alert("Error opening the database");
};
request.onupgradeneeded = function(event) {
var db = event.target.result;
alert("I'm doing stuff!");
var objectStore = db.createObjectStore("domains", {keyPath: "domain" });
objectStore.createIndex("domain", "domain", { unique: true });
objectStore.transaction.onComplete = function(event) {
var domanStore=db.transaction("domains","readwrite").objectStore("domains");
for(var i in tags)
{
domainStore.add(tags[i]);
}
}
};
Here are some links to the resources I am using:
Using IndexedDB
IDBObjectStore
IDBRequest
Finding out that the result is empty or undefined is a successful query. So yes, you get onsuccess call with result === undefined.
onerror is only reserved for when something breaks, e.g. you supplied an invalid key.
From IDBObjectStore.get docs:
Note: This method produces the same result for: a) a record that doesn't exist in the database and b) a record that has an undefined value. To tell these situations apart, call the openCursor() method with the same key. That method provides a cursor if the record exists, and no cursor if it does not.
Yes. It is even more confusing when delete method return success, even if no record is deleted.
Since request error event is cancellable bubbling event, it is not feasible to invoke to error callback even if no record is found. If request is on error and error is not prevented, its transaction will be aborted and indexedDB.onerror will be called as well. So invoking success with undefined result is still better than invoking error.