Accessing Elements on electron webview using spectron - webdriver

I am trying to automate a electron app which loads its content on to an webview. I am using spectron and webdriverio for it.
here is the code i am using.
it('should assess webview', function() {
var self = this;
return this.app.client.waitUntilWindowLoaded()
.windowHandles().then(function(session) {
self.app.client.switchTab(session.value[1])
.click("#my-id")
.then(console.log.bind(console))
.catch(console.log.bind(console));
});
});
This doesn't seem to work. i am not sure where i am going wrong. But i used
it('should assess webview', function() {
var self = this;
return this.app.client.waitUntilWindowLoaded()
.windowHandles().then(function(session) {
self.app.client.switchTab(session.value[1])
.getSource()
.then(console.log.bind(console))
.catch(console.log.bind(console));
});
});
the above code to ensure whether the webview window handle is correct. And it is. Kindly help. Thanks

I have checked the code, using spectron and running webview inside simulating this behaviour, your code works fine. Re-written the codes. Hope this helps.
it('should assess webview', function() {
var self = this;
return this.app.client.waitUntilWindowLoaded()
.windowHandles().then(function(session) {
// Need to return the promise back, if promise is
// it would wait for the state or else app will exit.
return self.app.client.switchTab(session.value[1])
.click("#my-id") // check whether selector is present in DOM
.then(console.log.bind(console))
.catch(console.log.bind(console));
});
});
or
it('should assess webview', function() {
var self = this;
return this.app.client.waitUntilWindowLoaded()
.windowHandles()
.then(function(session) {
// switchTab & window will both focus
// window or tab which is active
return this.window(session.value[1])
})
.click("#my-id") // check whether selector is present in DOM
.then(console.log.bind(console))
.catch(console.log.bind(console));;
});

Related

Promise.all not waiting for the array of promises to resolve using Firebase database [duplicate]

I'm writing my first piece of code using Promises and am getting some unexpected results. I had some code that looked like this (using jQuery):
$('.loading-spinner').show();
$('.elements').replaceWith(function() {
// Blocking code to generate and return a replacement element
});
$('.newElements').blockingFunction();
$('.loading-spinner').hide();
To prevent the page getting blocked when this code it run, I tried using setTimeout and Promises to make it asyncronous, like this:
$('.loading-spinner').show();
var promises = [];
var promises2 = [];
$('.elements').each(function(i, el){
promises[i] = new Promise(function(resolve, reject) {
setTimeout(function() {
$(el).replaceWith(function() {
// Code to generate and return a replacement element
});
resolve(true);
}, 100);
});
});
Promise.all(promises).then(function(values) {
$('.newElements').each(function(i, el) {
promises2[i] = new Promise(function(resolve, reject) {
setTimeout(function() {
$(el).blockingFunction();
resolve(true);
}, 100);
});
});
});
Promise.all(promises2).then(function(values) {
$('.loading-spinner').hide();
});
What I'm trying to achieve is that once the Promises in promises are resolved, the Promises in promises2 are instantiated. Once these are resolved, the loading spinner is hidden.
The effect I'm getting is that, while the page isn't blocked for as long, The spinner disappears as soon as the all the Promises are set up, not waiting until they're resolved.
I can see that the the promises2 Promises dont resolve until everything in promises is resolved, so I dont understand why this is happening. I guess this is down to either me not understanding Promises properly, or not understating making code asynchronous.
You're calling Promise.all on promises2 before you populate it, in fact when you call it it contains an empty array so it calls Promise.all on an empty array and thus it resolves immediately without waiting for the promises in promises.
Quick fix:
function delay(ms){ // quick promisified delay function
return new Promise(function(r){ setTimeout(r,ms);});
}
var promises = $('.elements').map(function(i, el){
return delay(100).then(function(){
$(el).replaceWith(function() {
// Code to generate and return a replacement element
});
});
Promises.all(promises).then(function(els){
var ps = $('.newElements').map(function(i, el) {
return delay(100).then(function(){
$(el).blockingFunction();
});
});
return Promise.all(ps);
}).then(function(){
$('.loading-spinner').hide();
});
We can do better though, there is no reason to fire n timeouts for n elements:
delay(100).then(function(){
$(".elements").each(function(i,el){
$(el).replaceWith(function(){ /* code to generate element */});
});
}).
then(function(){ return delay(100); }).
then(function(){
$('.newElements').each(function(i, el) { $(el).blockingFunction(); });
}).then(function(){
$('.loading-spinner').hide();
}).catch(function(err){
throw err;
});

Meteor helper doesn't refresh on Reactive var .set()

I update reactive var on autorun. The same reactive var is used in helper. But helper values doesn't refresh by autorun function. My below code will explain you clearly.
Template.home.onCreated(function () {
var self = this;
self.ITEMS_INCREMENT = 2;
self.itemsLimit = new ReactiveVar(2);
});
Template.home.onRendered(function () {
var self = this;
this.autorun(function(){
if( true ){
self.itemsLimit.set(self.itemsLimit.get()+self.ITEMS_INCREMENT);
console.log(self.itemsLimit.get()); // set values are fine
}
});
});
Template.home.helpers({
testHelper: function(){
console.log(Template.instance().itemsLimit.get()); // console returns 2 and 4 only. no more update :(
return true;
}
});
Anything wrong in handling of data or usage? How to make helpers are workable?
Well well well, I don't see where are you going to change the value of reactive variable. It gets changed only ones, when first computation runs in your tracker. So only ones you see the update. The idea of using ReactiveVar is that when you change it, it gets changed inside helper or inside autorun.
Briefly, what you can do to test it is:
Template.home.onRendered(function () {
var self = this;
Meteor.setInterval(function(){
self.itemsLimit.set(self.itemsLimit.get()+self.ITEMS_INCREMENT);
}, 500);
});

How to unit test collection methods with velocity/jasmine

I'm completely new to javascript testing and I am trying to get a grasp on how to approach testing methods that touch the database
For example, I have this method that returns true if there are any documents in the db matching the query
Payments = new Mongo.Collection('payments');
_.extend(Payments, {
hasAnyPayments: function(userId) {
var payments = Payments.find({ userId: userId });
return payments.count() > 0;
}
});
So far I have only written the structure that I think is correct, but I am pretty lost
describe('Payments', function() {
describe('#hasAnyPayments', function() {
it('should return true when user has any payments', function() {
});
});
});
Are such tests even supposed to touch the database? Any advice is much appreciated
Unless you are manually inputting data into Mongo manually (or outside of Meteor) then you don't need to test the database.
What you should be testing, are the execution paths in your code.
So for the case above, hasAnyPayments is a unit that finds all user payments and returns true if there are more than 0. So your test would look something like this:
describe('Payments', function() {
describe('#hasAnyPayments', function() {
it('should return true when user has any payments', function() {
// SETUP
Payments.find = function() { return 1; } // stub to return a positive value
// EXECUTE
var actualValue = Payments.hasAnyPayments(); // you don't really care about the suer
// VERIFY
expect(actualValue).toBe(true);
});
});
});

Implement added, changed and removed server side

Context : I am using a Collection Params to call method from the Server to a C app. The C app does its stuff and then calls the server by RPC to send me the results. With the result, I get the Params ID to delete the corresponding element.
With the deletion of the Element of Params, the C app gets a removed message. I want to prevent this behavior to avoid overloading the C app of messages.
I've thinked about implementing the removed event into the Publish method on the server to prevent the server from informing the C app. I just want the C app to be inform about added events.
On the Meteor Doc, there is an example of implementation of added and removed but I don't understand it. Can someone help me ?
I've tried this (don't work at all) :
Meteor.publish('expert_mode_parameters', function ()
{
var self = this;
var handle = Expert_Mode_Parameters.find().observeChanges({
added: function ()
{
return Expert_Mode_Parameters.find();
},
removed: function ()
{
return [];
}
});
self.ready();
self.onStop(function () {
handle.stop();
});
}
It looks like your goal is to subscribe to a data set but only receive added messages, not changed or removed.
The below code should do this:
Meteor.publish('expert_mode_parameters', function () {
var self = this;
var handle = Expert_Mode_Parameters.find().observe({
added: function (document) {
self.added("expert_mode_parameters", document._id, document);
}
});
self.ready();
self.onStop(function () {
handle.stop();
});
}
The concept is, you're watching the results of Expert_Mode_Parameters.find() and then calling self.added(document) when there is a new item. The same thing can easily be expanded to include changed.

meteor findOne or find returns undefined

I'm trying to do some validation prior to loading the main page. To do this I need to find a document that I have confirmed, exist in the Mongo Collection. Unfortunately finding the document in the client.js doesn't seem to work. In my opinion the client and server collection are not in sync. Based on similar articles i have read I made many changes without success. Here is a quick summary of what I have tried.
Option1: Try to find the record in the client side and not using auto-subscribe: record not found.
In app.js
credentialToken = "2KcNCRzpTHzyZ1111";
if (Meteor.isClient) {
Template.hello.greeting = function () {
return "Welcome to ares_sso.";
};
Meteor.startup(function () {
var results = Meteor.findrec(credentialToken);
console.log("results:",results); //results is undefined.
});
Template.hello.events({
'click input': function () {
if (typeof console !== 'undefined')
console.log("You pressed the button");
}
});
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
});
}
In /client/app.js
crs_collection = new Meteor.Collection("crs");
Meteor.subscribe("crs");
Meteor.findrec = function(credentialToken) {
target = {credentialtoken:credentialToken};
recfound = crs_collection.findOne(target);
//No luck with find either.
//recfound = crs_collection.find({credentialtoken:credentialToken}, {limit:1}).fetch()[0];
console.log("recfound:",recfound); //returns recfound is undefined.
return recfound;
}
In /server/server.js
crs_collection = new Meteor.Collection("crs");
Meteor.publish("crs", function(){
return crs_collection.find();
});
Option2: Next I did the find in the server side, using a method "server_recfind" which worked but I'm not able get the content to the client.
In app.js
credentialToken = "2KcNCRzpTHzyZ1111";
if (Meteor.isClient) {
Template.hello.greeting = function () {
return "Welcome to ares_sso.";
};
Meteor.startup(function () {
var results = Meteor.call('server_findrec',credentialToken);
console.log("results=",results); // also returns undefined
});
Template.hello.events({
'click input': function () {
if (typeof console !== 'undefined')
console.log("You pressed the button");
}
});
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
});
}
In /client/app.js
crs_collection = new Meteor.Collection("crs");
Meteor.subscribe("crs");
In /server/app.js
crs_collection = new Meteor.Collection("crs");
Meteor.publish("crs", function(){
return crs_collection.find();
});
// Using Sync which finds the record but how do I sent the content to the client?
Meteor.methods ({
'server_findrec': function(credentialToken) {
// tried unblock but didnt work
//this.unblock();
var rec = crs_collection.findOne({'credentialtoken': credentialToken});
console.log("INSIDE server findrec rec=",rec); //shows content found
// tried flush but it didn't do anything
crs_collection.flush;
return rec; //rec not returning to the client
}
})
Option3: Frustrated and since I was able to find the document record with the server method. I tried adding global variables to delivery the content to the client side. Unfortunately it didn't work
In app.js
credentialToken = "2KcNCRzpTHzyZ1111";
//added global variables
c1 = '';
c2 = '';
c3 = ''
if (Meteor.isClient) {
Template.hello.greeting = function () {
return "Welcome to ares_sso.";
};
Meteor.startup(function () {
var results = Meteor.call('server_findrec',credentialToken);
console.log("results=",results); // also returns undefined
console.log("c1=",c1);
console.log("c2=",c2);
console.log("c3=",c3);
});
Template.hello.events({
'click input': function () {
if (typeof console !== 'undefined')
console.log("You pressed the button");
}
});
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
});
}
In /client/app.js
crs_collection = new Meteor.Collection("crs");
Meteor.subscribe("crs");
In /server/app.js
crs_collection = new Meteor.Collection("crs");
Meteor.publish("crs", function(){
return crs_collection.find();
});
// Using Sync which finds the record but how do I sent the content to the client?
Meteor.methods ({
'server_findrec': function(credentialToken) {
// tried unblock but didnt work
//this.unblock();
var rec = crs_collection.findOne({'credentialtoken': credentialToken});
console.log("INSIDE server findrec rec=",rec); //shows content found
c1 = rec.cont1;
c2 = rec.cont2;
c3 = rec.cont3;
//confirm that c1,c2 and c3 have content
console.log(In server_findrec c1=",c); //shows content
console.log(In server_findrec c2=",c2); //shows content
console.log(In server_findrec c3=",c3); //shows content
// tried flush to sync to client...didn't work
crs_collection.flush;
return rec; //rec not returning to the client
}
})
There is a lot more code, so I have assembled all of the above hoping it gives you a clear picture of what I have tried and what I'm trying to do. I'm sorry if I made a mistake in the process.
Overall it will be great to know what am I doing wrong? I believe the 3 scenarios should work. Any help or recommendation will be appreciated.
I'm using Meteor Release 0.7.1.2, no CoffeeScript.
Thank you all
You're making two mistakes:
Define crs_collection once, and make sure its in a file thats executed on the client AND the server. It should be defined globally.
crs_collection must be defined before your pub/sub code. Meteor executes files in the lib directory first, so its best to put your collection code there.
That's really all there is to it. I'm happy to provide an example if needed.

Resources