Xolvio Cucumber - Getting errors in console yet all tests are passing - meteor

I have the following code. It seems like my tests pass, but I get tons of errors in my console. What's going on? Are my tests non-deterministic and being re-run? If so how do I prevent the errors?
login.feature:
Feature: User authentication
As a user
I want to be able to login
So that I can have all the good stuff that comes with user accounts
Background:
Given I am signed out
Scenario: A user can sign up with valid information
Given I am on the home page
When I open the sign up modal
And I enter my desired authentication information
Then I should be logged in
step_definitions.js
this.When(/^I open the sign up modal$/, function (callback) {
// Write code here that turns the phrase above into concrete actions
helper.world.browser.
click('[data-ion-modal="signup"]').
waitForVisible('.#signup-form', 2000).
call(callback);
});
this.When(/^I enter my desired authentication information$/, function (callback) {
// Write code here that turns the phrase above into concrete actions
helper.world.browser.
waitForExist('#signup-form', 2000).
waitForVisible('#signup-form').
setValue('#signup-email', 'newuser#test.com').
setValue('#signup-password', 'password').
submitForm('#signup-form').
call(callback);
});
this.Then(/^I should be logged in$/, function (callback) {
// Write code here that turns the phrase above into concrete actions
helper.world.browser.
waitForExist('.tabs', 2000).
waitForVisible('.tabs').
call(callback);
});

This looks like a meteor-cucumber regression. I'm in the process of rewriting cucumber, expect this problem to go away in the next release.

Related

Amplify Reset Password Hangs

I used amplify's withAuthenticator as shown below for my /mainPage path. But when I tried to reset password, supply the confirmation code and submit it, the page hangs. It should refresh my /mainPage page.
import { withAuthenticator } from "#aws-amplify/ui-react";
import "#aws-amplify/ui-react/styles.css";
function MainPage({ signOut, user }) {
return (
<>
<h1>Hello {user.username}</h1>
<button onClick={signOut}>Sign out</button>
</>
);
}
export default withAuthenticator(MainPage);
Lots of missing information here but.. here's go nothing
page hangs == there was an error which can be viewed and inspected by your browser's developer tools - you should attach the error here in order to help others to assist (next time of course)
do you use the default reset password flow or make something custom?
in any case - why do you use the signOut method for this process? the user is not signed in (forgot password) so there is no point to sign out
The only scenerio I can think of is if the user is forced to change password (e.g. - getting kicked off with the signOut method, change password and sign in again). Even for that use-case - the signOut method alone (as present in your code) is only the first phase of this process (and not the entire process)
With that being said, I'll try to suggest a process that will simplify things for you (as the name Amplify applies) - reset one's password by using the build-in mechanism already provided with the library (please read the docs)
Long story short, the process would be:
User need to change password (forgot or forced to perform this action)
An email with temporary code is then send to user's email (this code is only valid for one hour - please generate it only when user is able to actually change current password)
User copy the code from email to your form, and then enter the new password
After confirmation - password changed. It's up to you to decide if you want to enter user into your app of force re-entry (e.g. typing the new password in the login screen in order to sign-in)
And you can use the forgotPassword and forgotPasswordSubmit methods in order to fulfill that process (more information in the link provided above) . In any other case (you have a custom flow) - please share more details
One last technical note:
In react this form of event handling
<button onClick={asyncFunc} >I am a button!</button>
Is the short way of wrtiting
<button onClick={async () => { await asyncFunc1(); await asyncFunc2() } }>
I am a button!
</button>
So either write your own custom async function and use the short way (preferred) or use the long way and use several functions in order to materialize your async process steps
Good luck 😊

How to run Cypress BDD Feature using TAGS in the Terminal without closing the test/browser for each Feature

I have a few feature files in my project and I need to execute only the specific cucumber tags (#Regression) from the feature file using Terminal. I could able to run the feature file using the tags. But the test/Browser window gets closed and open for each feature file. In this case, I have to write a login script in all the feature files to avoid this problem.
Expectation: Test/Browser should not be closed each time and Login should happen only at the beginning of the script execution.
Can someone help me to overcome this problem?
Explanation
That you have to run the login for each Scenario in your Feature respectively is the expected behavior, since each test should be as independent as possible in itself.
In order not to have to add a login step for each Scenario again and again, there are so-called Backgrounds in Cucumber. Backgrounds describe steps that apply as a precondition for all Scenarios in a Feature.
Backgrounds behave like normal Scenarios, so for example you can create a Background in each of your Features with a Given step for the login so that it is automatically executed before each scenario.
Example
Each Feature would receive the following Background, which is then automatically executed once before each Scenario:
#SomeTag
Feature: Some Feature
Background: User is logged in
Given the user is logged in
Scenario: Some first scenario
Given ...
When ...
Then ...
Scenario: Some second scenario
Given ...
When ...
Then ...
The implementation of the step definition is then the same as for steps for your normal Scenarios and can be reused in all Features:
import { defineStep, Given } from 'cypress-cucumber-preprocessor/steps';
Given('the user is logged in', () => {
// logic for login
});
// or more generic using defineStep
defineStep('the user is logged in', () => {
// logic for login
});
Regarding the logic for the login it is often suitable to use Cypress Custom Commands (Example Login for Azure AD)

Firebase Authentication. General Query

I am currently creating a react-native app and testing it using exp on a physical Pixel 2. When I load my app up, I have the following in componentDidMount:
componentDidMount = () => {
firebase.auth().onAuthStateChanged((user)=>{
if (user) {
//this.setState({userid: user.uid}); //I added this to see if it was the below slowing things down (it is not)
firebase.database().ref('/Users/'+user.uid+'/Public/').once('value')
.catch(err=>{console.log(err)})
.then(snapshot=>{
let username = snapshot.child('Username').val();
this.setState({username: username, userid: user.uid});
});
} else {
this.setState({ user: null, username: null});
}
});}
My aim is to direct the user to the log-in page if they are not authenticated. Otherwise, dive straight into the inner pages. My code sort-of-works and this does actually take place (hurray!).
However, when I load my app up is takes a number of seconds (maybe 10 seconds), for the app to realise that I am already signed in. This means it shows the log-in page for 10 seconds and then starts to display the inner pages. Has anyone got any idea of why it takes so long for .onAuthStateChanged to register that I am in fact still signed in from my last session? And is there any way for me to know whether I am at the login page because I am not logged in at all or because the app doesn't yet realise that I am logged in? It is very awkward for the user having to sign in every time and then mid way through typing their details in, being logged in lol!
As always, all help is much appreciated.

Google reCAPTCHA response success: false, no error codes

UPDATE: Google has recently updated their error message with an additional error code possibility: "timeout-or-duplicate".
This new error code seems to cover 99% of our previously mentioned mysterious
cases.
We are still left wondering why we get that many validation requests that are either timeouts or duplicates. Determinining this with certainty is likely to be impossible, but now I am just hoping that someone else has experienced something like it.
Disclaimer: I cross posted this to Google Groups, so apologies for spamming the ether for the ones of you who frequent both sites.
I am currently working on a page as part of a ASP.Net MVC application with a form that uses reCAPTCHA validation. The page currently has many daily users.
In my server side validation** of a reCAPTCHA response, for a while now, I have seen the case of the reCAPTCHA response having its success property set to false, but with an accompanying empty error code array.
Most of the requests pass validation, but some keep exhibiting this pattern.
So after doing some research online, I explored the two possible scenarios I could think of:
The validation has timed out and is no longer valid.
The user has already been validated using the response value, so they are rejected the second time.
After collecting data for a while, I have found that all cases of "Success: false, error codes: []" have either had the validation be rather old (ranging from 5 minutes to 10 days(!)), or it has been a case of a re-used response value, or sometimes a combination of the two.
Even after implementing client side prevention of double-clicking my submit-form button, a lot of double submits still seem to get through to the server side Google reCAPTCHA validation logic.
My data tells me that 1.6% (28) of all requests (1760) have failed with at least one of the above scenarios being true ("timeout" or "double submission").
Meanwhile, not a single request of the 1760 has failed where the error code array was not empty.
I just have a hard time imagining a practical use case where a ChallengeTimeStamp gets issued, and then after 10 days validation is attempted, server side.
My question is:
What could be the reason for a non-negligible percentage of all Google reCAPTCHA server side validation attempts to be either very old or a case of double submission?
**By "server side validation" I mean logic that looks like this:
public bool IsVerifiedUser(string captchaResponse, string endUserIp)
{
string apiUrl = ConfigurationManager.AppSettings["Google_Captcha_API"];
string secret = ConfigurationManager.AppSettings["Google_Captcha_SecretKey"];
using (var client = new HttpClient())
{
var parameters = new Dictionary<string, string>
{
{ "secret", secret },
{ "response", captchaResponse },
{ "remoteip", endUserIp },
};
var content = new FormUrlEncodedContent(parameters);
var response = client.PostAsync(apiUrl, content).Result;
var responseContent = response.Content.ReadAsStringAsync().Result;
GoogleCaptchaResponse googleCaptchaResponse = JsonConvert.DeserializeObject<GoogleCaptchaResponse>(responseContent);
if (googleCaptchaResponse.Success)
{
_dal.LogGoogleRecaptchaResponse(endUserIp, captchaResponse);
return true;
}
else
{
//Actual code ommitted
//Try to determine the cause of failure
//Look at googleCaptchaResponse.ErrorCodes array (this has been empty in all of the 28 cases of "success: false")
//Measure time between googleCaptchaResponse.ChallengeTimeStamp (which is UTC) and DateTime.UtcNow
//Check reCAPTCHAresponse against local database of previously used reCAPTCHAresponses to detect cases of double submission
return false;
}
}
}
Thank you in advance to anyone who has a clue and can perhaps shed some light on the subject.
You will get timeout-or-duplicate problem if your captcha is validated twice.
Save logs in a file in append mode and check if you are validating a Captcha twice.
Here is an example
$verifyResponse = file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret='.$secret.'&response='.$_POST['g-recaptcha-response'])
file_put_contents( "logfile", $verifyResponse, FILE_APPEND );
Now read the content of logfile created above and check if captcha is verified twice
This is an interesting question, but it's going to be impossible to answer with any sort of certainly. I can give an educated guess about what's occurring.
As far as the old submissions go, that could simply be users leaving the page open in the browser and coming back later to finally submit. You can handle this scenario in a few different ways:
Set a meta refresh for the page, such that it will update itself after a defined period of time, and hopefully either get a new ReCAPTCHA validation code or at least prompt the user to verify the CAPTCHA again. However, this is less than ideal as it increases requests to your server and will blow out any work the user has done on the form. It's also very brute-force: it will simply refresh after a certain amount of time, regardless of whether the user is currently actively using the page or not.
Use a JavaScript timer to notify the user about the page timing out and then refresh. This is like #1, but with much more finesse. You can pop a warning dialog telling the user that they've left the page sitting too long and it will soon need to be refreshed, giving them time to finish up if they're actively using it. You can also check for user activity via events like onmousemove. If the user's not moving the mouse, it's very likely they aren't on the page.
Handle it server-side, by catching this scenario. I actually prefer this method the most as it's the most fluid, and honestly the easiest to achieve. When you get back success: false with no error codes, simply send the user back to the page, as if they had made a validation error in the form. Provide a message telling them that their CAPTCHA validation expired and they need to verify again. Then, all they have to do is verify and resubmit.
The double-submit issue is a perennial one that plagues all web developers. User behavior studies have shown that the vast majority occur because users have been trained to double-click icons, and as a result, think they need to double-click submit buttons as well. Some of it is impatience if something doesn't happen immediately on click. Regardless, the best thing you can do is implement JavaScript that disables the button on click, preventing a second click.

Secure way to store pending user's password in Meteor

For my Meteor application, I would like to have the following signup process:
User registers username, email and password. (He's not able to log in yet.)
Confirmation email sent [Accounts.sendEnrollmentEmail]
User confirms email [Accounts.onEnrollmentLink]
User is created. [Accounts.createUser] (He's able to log in.)
In order to achieve this, I feel like I would have to store the plain text password in a table of temporary users (step 1) in order to create the actual user later (step 3). Obviously this is a horrible idea.
I could of course only ask for the password as of step 3 and create the user at once - but it's not the behavior I would like to achieve.
So: Is there a proper way to store the password securely to later pass it to the user creation? Or is there a way to create a not-loginable users?
There is not much you have to do yourself as Meteor brings everything you need for save password storage when you create a user with the built in methods. So you should use these methods from the beginning (Your step 1: Accounts.createUser, step 2: Accounts.sendVerificationEmail, step 3: Accounts.verifyEmail, step 4 isn't necessary anymore).
Now to get where you want to be you can use an approach like David Weldon suggested but use Accounts.validateLoginAttempt on the sever side. That is a little easier and the login isn't allowed in the first place.
For example you could have this code server side:
Accounts.validateLoginAttempt(function(loginAttempt){
if (!loginAttempt.allowed) {
// Only tell the user that something went wrong but not what to enhance security
throw new Meteor.Error(901, 'Your login credentials are wrong. Try again.');
} else {
// In some cases this method isn't invoked with a correct user object...
if (!loginAttempt.user) {
throw new Meteor.Error(902, 'No valid user object. Make sure to validate your email address first.');
}
// If email verification is required check if the user has a valid email address and don't allow the login if he has none
if (!loginAttempt.user.emails[0].verified) {
throw new Meteor.Error(902, 'Your email address has to be verified first.');
}
// We have a correct login!
return true;
}
});
And now on the client side you can use a logic like this for the login
Meteor.loginWithPassword(email, password, function(callback) {
if (callback === undefined) {
// Your login logic
} else if (callback.error == 902) {
// Your "not verfied" logic
} else {
// Your other login errors logic
}
}
Note that you may have to adjust the registration process a little bit, too, as Meteor per default tries to login users directly after registration but this will not be possible anymore.
Also note that you may use Accounts.validateLoginAttempt for more than just that. For example you also could implement a logic here to only allow a certain amount of bad login attempts from the same IP.
We've used a slightly different pattern in our app based on the accounts package
User registers
User is logged in normally
Out main site template conditions content with
<template name="main">
{{#if currentUser}}
{{#if verified }}
...
{{else}}
Notice to user to look for their verification email
{{/if}}
{{/if}}
</template>
Based on a helper function
Template.main.helpers({
verified: function() { return Meteor.user().emails[0].verified; }
});
This meets the requirement that the user can't do much if anything until they have been verified yet uses the accounts package in a simple and secure way.
I could see taking a related approach using iron:router as well.

Resources