async selectLocalAdmin(){
if(this.localAdmin.visible){
await t.click(this.localAdmin);
}
else{
console.log('not visible');
}
}
I was trying to add some if else statements here and i observe that even when the if statment is true the click function is not happening, any idea on why this is happening?
Without a complete sample, I can only say that the selector.visible property returns a promise (assuming localAdmin is a Selector), so you need to add await:
async selectLocalAdmin() {
if (await this.localAdmin.visible) {
await t.click(this.localAdmin);
}
else{
console.log('not visible');
}
}
If this does not fix the issue, please share the complete test code (include the URL of the tested application, which should be publicly accessible).
Related
I'm trying to save record into database, if this record is not in user's profile (he did not discover this place) but also this record exists in collection of all places.
I'm using Expo react native and I think my problem is, that if condition will execute before functions recordInUsersAccount and recordInGlobalDatabase . Is there any way how to ensure execution after these two functions are copleted? In functions I'm rewriting variables in state={}, so I can check them below. (I tried .then() and await, async but I was not succesful).
Thank you very much.
saveScannedQrCode(idOfPlace) {
this.recordInUsersAccount(idOfPlace);
this.recordInGlobalDatabase(idOfPlace);
if (!this.state.placeAlreadyScanned && this.state.placeExistInDatabase) {
// we will add this record into database
} else {
// we will NOT add this record into database
}
}
This is the code of functions:
recordInUsersAccount(idOfPlace) {
const userId = auth.currentUser.uid;
const usersRef = db
.collection("placesExploredByUsers") // default
.doc("mUJYkbcbK6OPrlNuEPzK") // default
.collection("s53sKFeF5FS0DjuI2cdO1Rp9sCS2") // uid
.doc(idOfPlace); // id of place
usersRef.get().then((docSnapshot) => {
if (docSnapshot.exists) {
this.setState({
placeAlreadyScanned: true, // place is in user's database
});
} else {
this.setState({
placeAlreadyScanned: false, // place is NOT in user's database
});
}
});
}
recordInGlobalDatabase(idOfPlace) {
const usersRef = db
.collection("databaseOfPlaces") // default
.doc(idOfPlace); // id of place
usersRef.get().then((docSnapshot) => {
if (docSnapshot.exists) {
this.setState({
placeExistInDatabase: true, // place is in global database of places
});
} else {
this.setState({
placeExistInDatabase: false, // place is NOT in global database of places
});
}
});
}
The problem with the code is that setState in React is async, and you're trying to check the values straight after executing the functions which modify the state.
Assuming that your methods work fine and do what they're supposed to do, you could do something like:
Leave your methods as they are right now, modifying the state.
Call saveScannedQRCode as your are doing now, triggering both of the helper methods.
Instead of checking the state right after calling them, you could do that in the componentDidUpdate lifecycle hook.
componentDidUpdate(prevProps, prevState) {
if (prevState.placeExistInDatabase !== this.state.placeExistInDatabase && prevState.placeAlreadyScanned !== this.state.placeAlreadyScanned) {
// do something here - at this point state is already updated and ready to use.
// you could check for the values you're waiting for to update the DB, else not do anything.
}
}
saveScannedQrCode(idOfPlace) {
this.recordInUsersAccount(idOfPlace);
this.recordInGlobalDatabase(idOfPlace);
}
One thing - be sure to reset the state (e.g. set it to null) once you've processed the update, this way your componentDidUpdate hook won't have any problems and your strict equality will be fine.
I am currently using the following code as a hook in each of my routes:
router.beforeEach(async(to, from, next) => {
/**
*
* #type {boolean}
*/
const requiresAuth = to.matched.some((record) => record.meta.requiresAuth);
if (requiresAuth) {
if (!isAuthenticated()) {
next('/login');
} else {
next();
}
} else if (isAuthenticated()) {
next('/home');
} else {
next();
}
});
My question as the title indicates is if I should use return after calling the next() method .. something like this:
...
if (requiresAuth) {
if (!isAuthenticated()) {
next('/login');
return; <--- should I use return here?
} else {
next();
return; <--- should I use return here?
}
}
I am confused on whether it is necessary to use it or not .. could you clarify my doubt please ..
Thank you very much in advance
There is no need to return, as you have an if/else and no code after that.
But someone could argue that early bail-out improves readability. So having this code:
if (requiresAuth) {
if (!isAuthenticated()) {
next('/login');
return;
}
next();
}
Can be seen as more readable than the alternative.
Another reason for returning is future proofing. If you know for a fact that you want to return this will raise a warning (if using a linter) if someone adds code in the future
if (requiresAuth) {
if (!isAuthenticated()) {
next('/login');
return;
} else {
next();
return;
}
// adding code here will trigger an unreachable code warning.
}
So even if the 2 ways are equivalent, returning from the function does bring some benefits.
Check the docs for the global before each guard. There is no need to return, your code is wrapped in if - else and will only call next() once as described on the Vue Router docs.
Am new to aurelia js. Here, i need to do callback in aurelia js .
Here is the code i tried,
file.js
this.commonFunctions.get_alrdyShrdUser(this.alrdyshardAry,function(err,result){
if(!err){
console.log("err,result",err,result);
this.sharedAlrdy = result;
}else{
}
});
commonFunctions
get_alrdyShrdUser(docids,callback){
this.httpValueConverter.call_http('sharing/users/list','POST',docids,'test')
.then(data => {
if(data.meta && data.meta.statusCode == 200) {
return callback(null,data.sharedUsers)
}
});
}
Here all works fine, callback function also returned value, but i can't assign value to a aurelia varibale(this.sharedAlrdy).It throws error, Cannot set property 'sharedAlrdy' of undefined. Is that any other way to achieve?
This has nothing to do with Aurelia. You are just having a typical JavaScript problem with this.
Since you are using Aurelia, I assume that is ES6 code and you have arrow function support. Use arrow function in function callbacks and you won't have problems with capturing this:
this.commonFunctions.get_alrdyShrdUser(this.alrdyshardAry, (err, result) => {
if (!err) {
console.log("err, result", err, result);
this.sharedAlrdy = result;
} else {
}
});
For more details on arrow functions and this, take a look at MDN.
Good Day,
I am trying to sign out an auth2 client. This process was working fine before I upgraded my router to fit in with new RC requirements. Now it seems as if the auth2 object is cleared or lost along the way from signing in to signing out.
Here is my sign out tag:
<a role="button" (click)="signOut()" style="padding-left: 30px;">Log out</a>
it simply calls a signOut() function found in navbar.component.ts (See below)
signOut() {
var auth2 = this._navigationService.getAuth2();
auth2.signOut().then(function () {
});
console.log('User signed out.');
sessionStorage.clear();
localStorage.clear();
this.router.navigate(['Login'])
window.location.reload()
}
here is the navigationService code it is calling:
import { Injectable } from '#angular/core';
#Injectable()
export class NavigationService {
onEditMode:boolean;
auth2:any;
constructor() {
this.onEditMode=true;
}
getEditMode(){
return this.onEditMode;
}
setEditMode(editMode:boolean){
this.onEditMode=editMode;
}
setAuth2(auth2:any){
this.auth2=auth2;
}
getAuth2(){
return this.auth2;
}
}
Here is my login.component.ts which sets the auth2 object seen in navigationService.ts:
onGoogleLoginSuccess = (loggedInUser) => {
this.isLoading=true;
console.log(loggedInUser)
this._navigationService.setAuth2(gapi.auth2.getAuthInstance());
console.log("Google gapi" + gapi.auth2.getAuthInstance());
sessionStorage.setItem('gapi',gapi.auth2.getAuthInstance());
this._zone.run(() => {
this.userAuthToken = loggedInUser.hg.access_token;
this.userDisplayName = loggedInUser.getBasicProfile().getName();
var strClientID = document.getElementsByTagName('meta')['google-signin-client_id'].getAttribute('content')
this.objTrimbleAuthentication.ClientID = document.getElementsByTagName('meta')['google-signin-client_id'].getAttribute('content');
this.objTrimbleAuthentication.IDToken = loggedInUser.getAuthResponse().id_token;
this._trimbleAuthenticationService.sendAndVerify(this.objTrimbleAuthentication).subscribe(data=>{
if(data.tokenIsValid==true){
sessionStorage.setItem('S_USER_EMAIL',loggedInUser.getBasicProfile().getEmail());
sessionStorage.setItem('S_USER_NAME',loggedInUser.getBasicProfile().getName());
sessionStorage.setItem('S_ID_TOKEN',this.userAuthToken);
this.objExternalBindingModel.ExternalAccessToken=this.userAuthToken;
this.objExternalBindingModel.Provider="Google";
this.objExternalBindingModel.UserName = loggedInUser.getBasicProfile().getName();
this._LoginService.obtainLocalAccessToken(this.objExternalBindingModel).subscribe(data=>{
// console.log(data);
this.isLoading=false;
this._router.navigate(['/Home']);
sessionStorage.setItem("access_token",data.access_token);
},error=>{
console.log(error);
})
}else{
this.isLoading= false;
this.showModal('#trimbleAuthError');
}
}, error=>{
})
});
}
onGoogleLoginSuccess is called from login.component.html:
<div style="margin-left:8% !important" id="{{googleLoginButtonId}}"></div>
So this process was working fine until I update my router to use the latest Angular2 Release Candidate. I am out of ideas on what could possibly be causing the following error when I click the sign out button:
Error in component.html/navbar.component.html:12:33
ORIGINAL EXCEPTION: TypeError: Cannot read property 'signOut' of undefined
if you need any other information or components please ask I hope I have given enough information. As I said it was working so keep that in mind, please.
Update
Waiting for additional info ...
In the following code, auth2:any; is undeclared. Is setAuth2 called anywhere before signOut()?
import { Injectable } from '#angular/core';
#Injectable()
export class NavigationService {
onEditMode:boolean;
auth2:any;
constructor() {
this.onEditMode=true;
}
getEditMode(){
return this.onEditMode;
}
setEditMode(editMode:boolean){
this.onEditMode=editMode;
}
setAuth2(auth2:any){
this.auth2=auth2;
}
getAuth2(){
return this.auth2;
}
}
Base on limited information and code posted, my guess is a logical bug in the logout process.
In signOut(), the window.location.reload() reload the page at the current url, which also clear all variables/objects. However, after reload, your app properly try to do signout again (due to url?).
In your navbar.component, you may need to add more logic in ngInit() to handle the situation.
Or can your code work without window.location.reload()? It seems odd to use that with angular2, especially with routing.
Right, the solution i found to the above question was that signing out using localhost will not work. So i just used this block of code when deploying the website and keep it commented out when running the website on localhost.
this is my signOut() function found in navbar.component.ts:
signOut() {
//////////////////////////////////////// Uncomment block for live deployment //////////////////////////////
// var auth2 = gapi.auth2.getAuthInstance();
// auth2.signOut().then(function () {
// console.log('User signed out.');
// });
//////////////////////////////////////////////////////////////////////////////////////////////////////////
sessionStorage.clear();
localStorage.clear();
this.router.navigate(['/']);
window.location.reload();
}
although getAuthInstance gives an error when trying to run it in localhost, deploying the web application to a server seems to work fine.
The goal: scan firebase data and delete items older than a given time.
The problem: the query generates a permissions error, though other read operations are allowed. Yet the problem seems to be the .read rule, since when it's taken out, everything works.
I authenticate using a token with "username" and "dataClass" embedded. Authentication normally works fine, and subscribed clients are receiving updates. Debugging log and examining the auth() payload show that the "username" and "dataClass" are correctly embedded in the token and correctly extracted by Firebase.
However, trying to use once() to get a subset of data older than a certain age generates a permission error. I can see the data location using ref(), however, with no error. Why does ref() work and a query doesn't? Possible basic misunderstanding: does a query return a copy of data, as it would in a SQL database, or does it return pointers to the data?
Here's the code, followed by the rules being used. Thanks mucho.
var Firebase = require('firebase');
Firebase.enableLogging(true, true);
// auth token is passed in as an argument
var token;
process.argv.forEach(function(val, index, array) {if (index==2) {token=val;} });
var oneHourAgo=(new Date).getTime() - (minutes*60000);
var fb=new Firebase("https://<mysite>.firebaseio.com/changeMessages");
connect2Firebase(fb,token);
function connect2Firebase(firebase,authToken) {
firebase.auth(authToken, function(error,payload) {
if(error) {
console.log("Login Failed!", error);
} else {
console.log("Login Succeeded!");
console.log(payload);
doSomething();
}
});
}
function doSomething() {
// THIS GIVES PERMISSION ERROR
fb.endAt(oneHourAgo).once('value', function(ss) { console.log(ss.val()); });
// THIS WORKS
//console.log(fb.endAt(oneHourAgo).ref().toString());
}
// THE RULES. Changing to ".read":true makes it work.
{
"rules": {
"changeMessages": {
"$dataClass": {
".read": "auth.dataClass == $dataClass && auth.username == 'admin'",
".write": "auth.username == 'admin'"
}
}
}
}