Test always times out, does not show promise output - node.js

browser.sleep(4000);
var discount_type = element(by.id("discount_type"));
var discount_value= element(by.id("discount_value"));
var grandTotal = element(by.id("grand-total"));
var subtotal = element(by.id("subtotal"));
var delivery_fee = element(by.id("delivery_fee"));
var last = protractor.promise.defer();
console.log("hallo");
subtotal.getText().then(function(sub) {
console.log("#############");
console.log(sub);
delivery_fee.getText().then(function(fee) {
console.log(fee);
var calc = parseFloat(sub) - parseFloat(fee) - parseFloat(config.promocodes.referral.discount);
console.log(calc);
last.fulfill(calc);
});
});
last.then(function(calc) {
console.log("final wait");
expect(grandTotal.getText()).toBe("$" + calc);
});
I need to calculate a value before I can be sure that my test ran ok.
In my tests, I always get to see "hallo" in the console.
Then I get a
> hallo
A Jasmine spec timed out. Resetting the WebDriver Control Flow.
> F
>
> Failures: 1) Refer a user and apply referral code should assign
> referral discount to user Message:
> Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL. Stack:
> Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
> at Timer.listOnTimeout (timers.js:92:15)
It seems the code never enters the subtotal.getText() promise! Why is that???

You never return from the promise resolution function. And, you don't have to have a deferred:
var last = subtotal.getText().then(function(sub) {
return delivery_fee.getText().then(function(fee) {
return parseFloat(sub) - parseFloat(fee) - parseFloat(config.promocodes.referral.discount);
});
});
last.then(function(calc) {
expect(grandTotal.getText()).toBe("$" + calc);
});

Related

Node.js memcached throwing unhandled promise rejection from within try/catch

I'm using a promisified version of the node.js memcached library for caching.
var get = promisify(memcached.get).bind(memcached);
var set = promisify(memcached.set).bind(memcached);
var add = promisify(memcached.add).bind(memcached);
var del = promisify(memcached.del).bind(memcached);
var incr = promisify(memcached.incr).bind(memcached);
var getMulti = promisify(memcached.getMulti).bind(memcached);
These are exposed in the exports of my connections.js file. I figured that this would be sufficient, as I expected memcached to silently fail if it had any problems, and I could just fall back to the database.
Once or twice an hour (I would guess the application gets around 30,000 requests an hour) a request fails, and the output to the log is this:
(node:28788) UnhandledPromiseRejectionWarning: Error: Item is not stored
at Socket.notstored (c:\Workspaces\DOH\Vaccines\Service\node_modules\memcached\lib\memcached.js:445:20)
at Client.rawDataReceived (c:\Workspaces\DOH\Vaccines\Service\node_modules\memcached\lib\memcached.js:744:51)
at Client.BufferBuffer (c:\Workspaces\DOH\Vaccines\Service\node_modules\memcached\lib\memcached.js:678:12)
at Socket.bowlofcurry (c:\Workspaces\DOH\Vaccines\Service\node_modules\memcached\lib\utils.js:126:15)
This seems odd to me, but I figured I would just account for that possibility by wrapping my function in a try/catch.
incr: async function (key, amount) {
key = Buffer.from(key).toString('base64')
try {
if (amount == undefined) {
amount = 1
}
var value = await get(env + key);
if (!value) {
await set(env + key, amount, 0)
} else {
await incr(env + key, amount);
}
return get(env + key)
} catch (e) {
console.log("Memcached incr error: " + e);
return 1
}
}
While I was debugging and connected to the memcached server, I saw the same error happen on a call to cache.incr(). The exception was not caught, it just failed the request and sent a 500 back to the client.
What am I missing? Does promisify not handle deep exceptions? The log is never able to trace the exception all the way back to a function call in my code; it just stops at utils.js in the memcached library. Why is that disconnect there?

Getting response before firebase transaction done

I'm trying to retrieve all the child then when there's match display.
I print the value in the console and my code work well there after few second, but when I print it in the agent as a message it show not available before the response because it does not wait.
Here is my code:
function retrieveContact(agent) {
var query = admin.database().ref("/contacts").orderByKey();
query.once("value")
.then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var key = childSnapshot.key;
var childName = childSnapshot.child('name').val();
if (agent.parameters.name == childName) {
console.log('find ' + childName);
agent.add('The email address for ' + childName + ' is ' + childSnapshot.child('email').val());
}
// console.log('testMode'+childName);
}); //// .then
}); //// .once }
SO, how can I wait my response then let the agent show the result?
How can I include the promise concept in my code ?
You don't show your entire Handler function, but if you're doing async operations (such as reading from the firebase db) you must return the Promise. This is how the Handler Dispatcher knows to wait for the Promise to complete before returning a response to the user.
In your case, it is probably as simple as
return query.once("value")
// etc

Call a generator function inside setInterval()

I am trying to call a generator function inside setInterval() method. The objective of this code is it will query a particular server for some data periodically, until it gets a non zero response. Upon getting the response it will call storeAddress() which is a generator function defined in the same file.
The below code is giving me an error like this:
SyntaxError: yield is a reserved word (248:6)
NOTE: I am using react-boilerplate to build my app. The above error is thrown by babel, as far as I can tell through searching internet.
I have tried const query = yeild call (setInterval, function(){magic code}, 10000). This does not give the error, but magic code never gets executed.
I have tried const query = setInterval(function* () {magic code}, 10000) with the same effect as above.
I have tried const query = setInterval(yield call(function(){magic code}, 10000) with same effect as above.
I have tried const query = yield call (setInterval, function(){magic code}, 10000) with same effect as above.
I have tried storeAddress(action.payload, balance).next() inside setInterval(). The control does flow inside storeAddress(), but that function also have generator calls inside, which never gets invoked. In fact nothing after the first generator call inside storeAddress() gets executed in this case.
function* callSaveNewAddress(action){
const selectedNetwork = yield select(selectNetworkId());
let count = 1;
let balance = 0;
const query = setInterval(function () {
getAddressBalance(action.payload, selectedNetwork).then(res =>
{return balance = res.data.mempool_balance});
if(balance > 0) {
yield call (storeAddress, action.payload, balance);
clearInterval(query);
} else if(count == 90) {
clearInterval(query);
console.log("Nothing received in 15 minutes");
}
}, 10000);
}
So how am I suppose to call storeAddress(), which is a generator function, inside a normal function like setInterval()?
const query= function * () {
const runner = yield call(setInterval, () => {
getAddressBalance(action.payload, selectedNetwork).then(res =>
{return balance = res.data.mempool_balance});
if(balance > 0) {
yield call (storeAddress, action.payload, balance);
clearInterval(query);
} else if(count == 90) {
clearInterval(query);
console.log("Nothing received in 15 minutes");
}
}, 1000);
}
try to use the setInterval within a call, passing through parameters the function you want to execute within it.

protractor timed out only when ignoreSynchronization is set to false

I couldn't figure out why protractor timed out when it reach to the code with ignoreSynchronization set to false;
this.countSubscribers = function () {
this.subscriberCount().then(function (count) {
totalSubscribers = count;
});
};
the method works correctly and totalSubscribers variable is getting correct value when
ignoreSynchronization = true;
Code below is a sample of my spec page:
describe("subscriber page test", function () {
"use strict";
var selectedCount = 10;
var subscriberCount;
describe("This test script selects no. of subscribers to be displayed on subscriber page", function () {
/**
* Step-1#Select number of items to be displayed
* Step-2#Get the count of subscribers displayed
* Step-3#check whether the number of subscribers displayed is equal to 10
*/
it("should select the no. of items to displayed and get the count", function () {
browser.ignoreSynchronization = false;
subscriber_page.selectItems(selectedCount);
subscriber_page.countSubscribers();
});
it("should check whether the selected no. of subscribers are displayed", function () {
expect(subscriber_page.getSubscribers()).toBe(10);
});
});
});
and the code below is a sample of my page object:
var SubscriberPage = function () {
"use strict";
this.subscriberCount = function() { return element...};
this.selectOption = function(count) {return element...};
var totalSubscribers;
/**
* This method selects items in list box
*/
this.selectItems = function (count) {
this.selectOption(count).click(); //selects the items from list box
};
/**
* This method sets the number of subscribers listed
*/
this.countSubscribers = function () {
this.subscriberCount().count().then(function (count) {
totalSubscribers = count;
});
};
/**
* This method returns the subscriber count
*/
this.getSubscribers = function () {
return totalSubscribers;//returns the count of subscribers.
};
};
module.exports = new SubscriberPage();
The code select items successfully, but it makes long pause afterward then produce
following error message:
Failed: Timed out waiting for Protractor to synchronize with the page after 5 seconds. Please see https://github.com/angular/protractor/blob/master/docs/faq.md
While waiting for element with locator - Locator: By(css selector, ...)
What I found out so far:
If I comment out following line from spec page countSubscribers method rather works correctly:
subscriber_page.selectItems(selectedCount);
or if I temporarily flip the ignoreSynchronization variable to true before countSubscribers method is executed, it works fine.
Can anyone explain what the protractor is doing at this point and what the best solution is while browser.ignoreSynchronization is set to false?
Keep a reference of "this" before your function. And then call it whenever you want.
Also if you do element.all(...) You'll be able to use the native .count() which will resolve the promise for you.
//Reference to this
var self = this;
//element.all with .count()
this.subscriberCount = function() { return element.all(...).Count()};
//This method returns the number of subscribers listed
this.countSubscribers = function () {
return self.subscriberCount();
});

Why does a click handler NOT run in Leadfoot?

I am trying to write functional tests using Intern framework which uses Leadfoot library to implement WebDriver API as I am using Selenium Grid setup to test my webapp on remote browsers. The app is already up and running.
The functional test I use is the following one:
define(function (require) {
var tdd = require('intern!tdd');
var assert = require('intern/chai!assert');
var url = '...';
var server = '...';
tdd.suite("Init suite",function(){
tdd.before(function () {
// executes before suite starts
});
tdd.after(function () {
// executes after suite ends
});
tdd.beforeEach(function () {
// executes before each test
});
tdd.afterEach(function () {
// executes after each test
});
tdd.test('Checking servers', function () {
var that = this.remote;
return that
.setFindTimeout(15000)
.get(url)
.findById('linkservers')
.click()
.then(function(){
console.log("Click resolved");
})
.end()
.findDisplayedByClassName('server-name-span-text')
.getVisibleText()
.then(function(texts){
var t=0;
var tlen = 0;
if (Array.isArray(texts))
{
tlen = texts.length
for (t=0;t<tlen;t++)
console.log("server["+t+"]: "+texts[t]);
assert.strictEqual(texts[0],server,"server is: "+texts[0]);
} else {
assert.strictEqual(texts,server,"server is: "+texts[0]);
}
})
.end();
});
});
});
To start my test I use the intern-runner: ./node_modules/.bin/intern-runner config=tests/intern.cfg -reporters=Runner
The nature of my issue is that findDisplayedByClassName('server-name-span-text') fails to find the class name, even though I am using findDisplayed call which waits for the element to show. The element doesn't show because for some reason the click() call doesn't trigger the event properly (guess). What I mean is that the click handler in the webapp code doesn't execute thus the element with class name server-name-span-text is not created. What I get in the end is failing findDisplayedByClassName due to timeout.
As I am running this locally I can actually observe and confirm that the click events doesn't happen. So the expected changes in my webapp do not occur.
The log from intern is the following:
Listening on 0.0.0.0:9000
Tunnel started
‣ Created session firefox on LINUX (2d94ea44-dea8-411a-8ee5-a3d7b749cc7b)
Click resolved
× firefox on LINUX - Init suite - Checking servers (15.588s)
NoSuchElement: An element could not be located on the page using the given search parameters.
at <node_modules/intern/node_modules/leadfoot/lib/findDisplayed.js:37:21>
at <node_modules/intern/node_modules/dojo/Promise.ts:393:15>
at run <node_modules/intern/node_modules/dojo/Promise.ts:237:7>
at <node_modules/intern/node_modules/dojo/nextTick.ts:44:3>
at doNTCallback0 <node.js:417:9>
at process._tickCallback <node.js:346:13>
at Command.findDisplayed <node_modules/intern/node_modules/leadfoot/Command.js:23:10>
at Command.prototype.(anonymous function) [as findDisplayedByClassName] <node_modules/intern/node_modules/leadfoot/lib/strategies.js:28:16>
at Test.test <tests/functional/loadgui.js:36:6>
at <node_modules/intern/lib/Test.js:211:24>
at <node_modules/intern/node_modules/dojo/Promise.ts:393:15>
at runCallbacks <node_modules/intern/node_modules/dojo/Promise.ts:11:11>
at <node_modules/intern/node_modules/dojo/Promise.ts:317:4>
at run <node_modules/intern/node_modules/dojo/Promise.ts:237:7>
at <node_modules/intern/node_modules/dojo/nextTick.ts:44:3>
at doNTCallback0 <node.js:417:9>
No unit test coverage for firefox on LINUX
firefox on LINUX: 1/1 tests failed
TOTAL: tested 1 platforms, 1/1 tests failed
The log of the selenium node doesn't show problems, at least on INFO level:
15:33:59.735 INFO [13] org.openqa.selenium.remote.server.DriverServlet - Executing: [find element: By.id: linkservers])
15:33:59.742 INFO [13] org.openqa.selenium.remote.server.DriverServlet - Done: [find element: By.id: linkservers]
15:33:59.750 INFO [13] org.openqa.selenium.remote.server.DriverServlet - Executing: [click: 9 [[FirefoxDriver: firefox on LINUX (84846fb0-1467-45a9-bbfe-a6333ddef515)] -> id: linkservers]])
15:33:59.811 INFO [13] org.openqa.selenium.remote.server.DriverServlet - Done: [click: 9 [[FirefoxDriver: firefox on LINUX (84846fb0-1467-45a9-bbfe-a6333ddef515)] -> id: linkservers]]
15:33:59.824 INFO [13] org.openqa.selenium.remote.server.DriverServlet - Executing: [find elements: By.className: server-name-span-text])
15:34:14.844 INFO [13] org.openqa.selenium.remote.server.DriverServlet - Done: [find elements: By.className: server-name-span-text]
15:34:14.957 INFO [192] org.openqa.selenium.remote.server.DriverServlet - Executing: [execute script: return (function getCoverageData(coverageVariable) {
var coverageData = (function () { return this; })()[coverageVariable];
return coverageData && JSON.stringify(coverageData);
}).apply(this, arguments);, [__internCoverage]])
15:34:14.970 INFO [192] org.openqa.selenium.remote.server.DriverServlet - Done: [execute script: return (function getCoverageData(coverageVariable) {
var coverageData = (function () { return this; })()[coverageVariable];
return coverageData && JSON.stringify(coverageData);
}).apply(this, arguments);, [__internCoverage]]
15:34:14.980 INFO [192] org.openqa.selenium.remote.server.DriverServlet - Executing: [delete session: 2d94ea44-dea8-411a-8ee5-a3d7b749cc7b])
15:34:15.047 INFO [192] org.openqa.selenium.remote.server.DriverServlet - Done: [delete session: 2d94ea44-dea8-411a-8ee5-a3d7b749cc7b]
How do I solve this issue?
Note:
Intern version is '3.0.6' and leadfoot is '1.6.4'.
I tried running same functional test using Selenium IDE and it runs successfully.
Couple of tips to fix this issue:
Before using findDisplayedByClassName make sure you can find the element with findByClassName
If it cannot find the element then make sure .findById('linkservers') works properly. To check you can try adding .sleep() before and after to see if it actually works and provides an element for you with the 'server-name-span-text' class.
Because the click() event was fired by the browser before the handler was attached.
The problem is between get() call and click() call:
...
.get(url)
.findById('linkservers')
.click()
...
What happened is that the browser fired the click event before the handler was attached. The handler is implemented in the app under test. This meant that at the time of firing click event there was no handler therefore the server-name-span-text element was not created hence the timeout of the findDisplayedByClassName operation. Note that I also tried findByClassName operation and in this cause I got exception NoSuchElement. The quick workaround, although very nasty, was to add a sleep() after the get() call.
Solution 1:
define(function (require) {
var tdd = require('intern!tdd');
var assert = require('intern/chai!assert');
var url = '...';
var server = '...';
tdd.suite("Init suite",function(){
tdd.before(function () {
// executes before suite starts
});
tdd.after(function () {
// executes after suite ends
});
tdd.beforeEach(function () {
// executes before each test
});
tdd.afterEach(function () {
// executes after each test
});
tdd.test('Checking servers', function () {
var that = this.remote;
return that
.setFindTimeout(15000)
.get(url)
.sleep(1000) //#Fix-1
.findById('linkservers')
.click()
.then(function(){
console.log("Click resolved");
})
.end()
.findDisplayedByClassName('server-name-span-text')
.getVisibleText()
.then(function(texts){
var t=0;
var tlen = 0;
if (Array.isArray(texts))
{
tlen = texts.length
for (t=0;t<tlen;t++)
console.log("server["+t+"]: "+texts[t]);
assert.strictEqual(texts[0],server,"server is: "+texts[0]);
} else {
assert.strictEqual(texts,server,"server is: "+texts[0]);
}
})
.end();
});
});
Update:
As explained earlier the explicit wait is a nasty solution for this kind of problem. The next solution is based on the execution of an asynchronous script at application side, executeAsync() call. This script returns a promise which has to be resolved by the application in order to end the wait on the asynchronous call. Of course the application has to cooperate with this a implemented deferred object so that it determined at which point the application has loaded. Otherwise such an approach won't work. The elegant way is presented as follows.
Solution 2:
define(function (require) {
var tdd = require('intern!tdd');
var assert = require('intern/chai!assert');
var url = '...';
var server = '...';
tdd.suite("Init suite",function(){
tdd.before(function () {
// executes before suite starts
});
tdd.after(function () {
// executes after suite ends
});
tdd.beforeEach(function () {
// executes before each test
});
tdd.afterEach(function () {
// executes after each test
});
tdd.test('Checking servers', function () {
var that = this.remote;
return that
.setFindTimeout(15000)
.get(url)
.executeAsync(function(done){
//application side.
application.loaded
.then(function(){
//at this moment the application has loaded
//so we resolve our intern side promise
done();
})
})
.findById('linkservers')
.click()
.then(function(){
console.log("Click resolved");
})
.end()
.findDisplayedByClassName('server-name-span-text')
.getVisibleText()
.then(function(texts){
var t=0;
var tlen = 0;
if (Array.isArray(texts))
{
tlen = texts.length
for (t=0;t<tlen;t++)
console.log("server["+t+"]: "+texts[t]);
assert.strictEqual(texts[0],server,"server is: "+texts[0]);
} else {
assert.strictEqual(texts,server,"server is: "+texts[0]);
}
})
.end();
});
});
If you wish you could also return some parameter to the callback which you resolve on the application side. For further information about this and more you can check out the docs.

Resources