Protractor. How to restart browser between tests? - protractor

I wrote a pack of tests and separately each of them works correctly (for each test I created separate file - it important for my case) , but when I try to run them all together I have some problems:
At the first I tried to restart browser after each test with “restartBrowserBetweenTests: true” option but as a result I receive next error:
Failed: This driver instance does not have a valid session ID (did you
call WebDriver.quit()?) and may no longer be used.
I read some advice for this situation, but nothing helped me.
Basically, I can get without restarting browser but in this case I want to close all active tabs after each test and I also don’t know ho to do it. With the help of this function:
browser.getAllWindowHandles().then((handles) => {
browser.driver.switchTo().window(handles[1]);
browser.driver.close();
browser.driver.switchTo().window(handles[0]);
});
I can close active tab and return for the previous but the function works only if I place this code in the test spec, that's not comfortable for me (copy it for each test) and if I call it from special file with functions it works incorrectly due to the
“Failed: no such window: target window already closed
from unknown error: web view not found”
errors (a consequence of a lost context).

https://www.protractortest.org/#/api?view=ProtractorBrowser.prototype.restart
use instead:
browser.restart()
also try to use await
it('Test Puppeteer screenshot', async function() {
await browser.get('https://www.google.com')
let current = await browser.getWindowHandle()
await browser.executeScript("window.open('https://www.indiatoday.com')")
handles = await browser.getAllWindowHandles()
await browser.switchTo().window(handles[1]);
await browser.close();
await browser.switchTo().window(handles[0]);
});
Note if you are using page object the nyou have to reinitialize modules:
if you are using javascript object notation for page then
https://www.npmjs.com/package/decache
const decache = require('decache');
let stage1 = require('../pageobjects/stage1.js');
beforeEach(async function () {
decache('../pageobjects/stage1.js');
stage1 = require('../pageobjects/stage1.js');
elements = stage1.elements;
});
If you are using nodejs class:
let stage1 = require('../pageobjects/stage1.js');
beforeEach(async function () {
stage1 = new PageObjects.stage1();
});
This because the reference for elements have changed you have to reinitialize them

Related

FireStore read fails silently and I have no idea why

Help is much appreciated how to trace down this issue, because I am running out of ideas.
I am calling the function getOrderCollection, below, but it aborts after the first line var myCompanyDoc = await FirebaseFirestore.instance.collection('companies').doc(myCompany).get(); Without trowing anything to the console or jumping into some library when debugging. When I click next statement it jumps back to the calling function.
I am authenticated to the database, companyCollection = FirebaseFirestore.instance.collection('companies') provides an initialized object pointing to the collection and myCompany is a constant with the document id entered by copy/paste.
If some rules for the database but I can't see successful or denied queries with the monitor.
Any ideas how I can proceed tracing down the issue?
Future<void> getOrderCollection() async {
var myCompanyDoc = await FirebaseFirestore.instance.collection('companies').doc(myCompany).get();
print("companyDoc fetched");
final myDeliveryDocRef = myCompanyDoc.data()['delivery'].toString();
orderCollection = FirebaseFirestore.instance.collection('companies').doc(myCompany).collection('features').doc(myDeliveryDocRef).collection('orders');
orderBriefDoc = FirebaseFirestore.instance.collection('companies').doc(myCompany).collection('features').doc(myDeliveryDocRef);
}
UPDATE: This is collection > document what corresponds to final String myCompany = '4U4kZKXkr3rHA6B04S5K';
As we discussed in your comments, the issue was that you forgot to await the getOrderCollection() function. Even though, as you mentioned, your caller function _deliveryRepository.initRepository() was awaited, you still had to await getOrderCollection() inside your caller method to make sure that the code is waiting for the getOrderCollection() to be executed before it proceeds to the next line.
In general, you want to have some error handling and to type the known types/classes (avoid using var).
Error handling - for async/await place the code inside a try/catch.
Typing - Dart is type safe, which is really great to prevent runtime errors.
Depending on your setup, you might be able to hover over the Firestore.instance.collection(...).doc(...) to see the return type. .doc(...).get() returns a DocumentSnapshot and .collection(...).get() returns a CollectionSnapshot.
Using the above, it should be easier to debug:
Future<void> getOrderCollection() async {
try {
DocumentSnapshot myCompanyDoc = await FirebaseFirestore.instance.collection('companies').doc(myCompany).get();
print("companyDoc fetched");
final myDeliveryDocRef = myCompanyDoc.data()['delivery'].toString();
} catch(e) {
print('Error: ' + e.toString());
}
}
Don't forget to await your other 2 Firestore queries.

Data return from axios cant be written to variable

I want to get an data attribute from my axios post and write it to an local variable to reuse it.
If i console.log it inside the axios .then, tha data is set, if i write it to my variable and want to use it after, it is empty.
export default {
data(){
return {
post:{},
projectId: '',
existingProjects: []
}
},
methods: {
addPost(){
//check if project exists else create
let uriProj = 'http://localhost:4000/projects/add';
this.axios.post(uriProj, {
projectName: this.post.project,
}).then(response => this.projectId = response.data.data);
console.log("project_id: "+this.projectId)
}
}
What am i doing wrong?
Another Question:
Is this the right way if i want to reuse the id in another method?
My Goal is to first create a project if it is not already in my db, then i want to reuse the id of the created or returned project model to create a new customer in my db, if the customer already has the project with the id of this project, it shouldnt be added, if it is a new one it should be added.
Has this to be done in multiple requests or is there a simple method for doing this?
I believe the issue you are seeing has to do with the asynchronous nature of network calls. When axios submits the post request it returns a Promise then the addPost function continues executing. So the projectId gets logged after it the initial value gets set, but before the network request completes. Everything inside the then() function executes once the network request has been completed so you can test by moving the console.log to be executed once the request is done. You could also output the value in the template so you can see it update {{ projectId }}
this.axios.post(uriProj, {
projectName: this.post.project,
}).then(response => {
this.projectId = response.data.data
console.log("project_id: "+this.projectId)
});
I would ideally recommend using the VueJS dev tools browser extension because it allows you to inspect the state of your Vue components without having to use console.log or add random echos to your template markup.
#jfadich is correct. I recommend using async/await instead of then, it's more intuitive to read.
async addPost(){
//check if project exists else create
let uriProj = 'http://localhost:4000/projects/add';
let resp = await this.axios.post(uriProj, {
projectName: this.post.project,
})
this.projectId = resp.data.data
console.log("project_id: "+this.projectId)
}

Loopback Operation hook receives options as empty

I'll try to explain this weird situation as simple as I can.
I've created an operation hook "before save" and make it in a mixin to add it to some models.
this mixin uses context.options to get current userId to do something.
this mixin is working perfectly if I call the operation directly (like POST /Accounts for example).
But if I call it inside a remote method, the context.options is empty, for example, if we have a method called POST /Accounts/Signup, and inside it, we call Account.create(...), the "before save" hook receives the options as empty object {}
A sandbox project has been hosted here
https://github.com/mustafamagdy/loopback-sandbox-issue
the mixin code snippet is as follows:
module.exports = function(Model, options) {
Model.observe("before save", async function(ctx) {
if (ctx.instance.id) return;
const userId = ctx.options && ctx.options.accessToken && ctx.options.accessToken.userId;
if (userId) {
//... do stuff
}
else
{
console.error("Failed to scope " + Model.name + " to user (null)");
}
});
};
After the investigation, I found this issue that talks about similar behaviour, however, the comments are very destractive. So I thoughlt to write the conclusion here for anyone who are facing the same issue.
Loopback require you to pass the options you declared from the remote method to the model method(s) if you want to receive it on operation hook, so I ended up doing so.
module.exports = function(Note) {
Note.makeNew = makeNew;
async function makeNew(options) {
await Note.create(obj, options);
}
};

How to query firestore with the Dialogflow inline editor to get information

I am using the inline editor within Dialogflow with the aim of making queries to the database I have created within Firestore.
In short, the user requests a list of courses, I'd like the chatbot to then grab that information form the db and display that back to the user.
Below I have tried to create a function that will do this, I want to take the user input, say "Art Courses" and have my db return those results.
So far, I have created a function that is triggered when the intent is matched, like so;
function getCourses(agent){
let courseRequest = agent.parameters.courseRequest;
if (getCourses){
console.log('Here is the list you requested for ${getCourses}' + parameters.courseRequest);
return admin.firestore().collection('Course_Information').doc.where('CoureTypes').get();
}
}
Are there any notable things I need to add to my function to perform what I wish to achieve?
Thank you.
UPDATE
This code deploys fine, but when I communicate with my bot and trigger the CourseEnquiry intent, cloud Functions shows this error:
admin.collection is not a function
Whilst this seems self explanatory I can't make sure of what it means, I thought declaring const admin = require('firebase-admin');enables me to use admin.collection
// See https://github.com/dialogflow/dialogflow-fulfillment-nodejs
// for Dialogflow fulfillment library docs, samples, and to report issues
'use strict';
const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const {Card, Suggestion} = require('dialogflow-fulfillment');
const admin = require('firebase-admin');
process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });
console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
console.log('Dialogflow Request body: ' + JSON.stringify(request.body));
function getDate(agent){
var today = new Date();
}
function welcome(agent) {
agent.add(`Welcome to my agent!`);
}
function test(agent){
agent.add("The test is successful");
}
function getCourses(agent){
// Get the database collection and document
const getCourseDoc = admin.collection('Course_Information').doc('Course_Types');
return getCourseDoc.get()
.then(doc => {
if (!doc.exists) {
agent.add('No data found in the database!');
} else {
agent.add(doc.data().entry);
}
return Promise.resolve('Here is the information you wanted');
}).catch(() => {
agent.add('Error reading entry from the Firestore database.');
});
}
function getSubmissionDateSep(agent){
agent.add('Your next submission date is for coursework 1 is');
}
let intentMap = new Map();
intentMap.set('Default Welcome Intent', welcome);
intentMap.set('Test_Test', test);
intentMap.set('CourseEnquiry', getCourses);
intentMap.set('Submission_Dates - sept', getSubmissionDateSep);
agent.handleRequest(intentMap);
});
UPDATE #2
Hey guys, still not got anywhere with this, I have tried adding:
admin.initializeApp(functions.config().firebase);
const db = admin.firestore();
According to this document but I get this error when deploying:
The deployment of your Cloud Function failed:
Function load error: Code in file index.js can't be loaded.
Is there a syntax error in your code?
Detailed stack trace: Error: Firebase config variables are not available. Please use the latest version of the Firebase CLI to deploy this function.
You don't show how you're responding to the user with your results, but you'll want to make sure you handle that as part of the then() clause in a Promise. Since the get() in the firestore collection returns a Promise, and you are returning it from your function, you need to make sure that the calling function treats it as a Promise, has a then() clause, and sends back the result as part of something inside this clause.

Autopublish removed but why can I still retrieve data from db?

I have a simple Meteor/MongoDB project using the 'roles' package where I optain data from the db to the client. The roles package seems to work fine and the browser shows the right data depending on who is logged in, just like it should do. Then when running 'meteor remove autopublish' in the terminal inside my applications directory I get 'autopublish removed' just like it should. Still I can retrieve data from the server just as before(!?)
I have all of my db calls from the client/client.js.
The server/server.js does nothing (I do have publish/subscribe code but uncomment for now) and same goes for the common js file in main directory.
How can this be? Am I perhaps retrieving data from minimongo somehow? I have also removed insecure even if I don't think that matters in this case(?) Thanks in advance.
EDIT: Here's the code:
client.js:
//when uncomment the subscribe's you should not get access to the server/db, but 'data' that holds all the inlogg info still shows. The 'movies' on the other hand doesn't, just like it shouldn't.
//Meteor.subscribe('data');
//Meteor.subscribe('movies');
/*############# Get User Data ###############*/
Template.userLoggedIn.id = function () {
return Meteor.userId();
};
Template.userLoggedIn.email = function () {
var email = Meteor.users.findOne({_id: Meteor.userId()});
return email.emails[0].address;
};
Template.userLoggedIn.profile = function () {
var profile = Meteor.users.findOne({_id: Meteor.userId()});
return profile.profile.name;
};
Template.userLoggedIn.role = function () {
var role = Meteor.users.findOne({_id: Meteor.userId()});
return role.roles[0];
};
/*############# ###############*/
Template.movies.movies = function() {
var movies = Movies.find().fetch();
return movies;
}
server.js:
Meteor.publish('data', function () {
return Meteor.users.find();
});
Meteor.publish('movies', function() {
return Movies.find();
});
Thanks for providing the code - I see how this could be confusing. The users section of the docs should be written to explicitly say this, but what's happening is the current user is always published. So even if you don't write a publish function for users (or your have your subscribe commented out), you should expect to see the current user on the client. Because your template code only looks for Meteor.userId(), I would expect it to still work.
Assuming you have other users in the database, you can quickly check that they are not being published by running: Meteor.users.find().count() in your browser console. If it returns 1 then you are only publishing the current user (or 0 if you are logged out).