@ -6,6 +6,7 @@ import * as fse from 'fs-extra';
import defaults = require ( 'lodash/defaults' ) ;
import { WebElement } from 'mocha-webdriver' ;
import fetch from 'node-fetch' ;
import { authenticator } from 'otplib' ;
import * as path from 'path' ;
import { WebDriver } from 'selenium-webdriver' ;
@ -46,7 +47,7 @@ export class HomeUtil {
* ( after having been created if necessary ) , so that their home api can be later
* instantiated without page loads .
* When testing against an external server , the simulated login is in fact genuine ,
* done via Cognito .
* done via the Grist login page .
* /
public async simulateLogin ( name : string , email : string , org : string = "" , options : {
loginMethod? : UserProfile [ 'loginMethod' ] ,
@ -75,26 +76,22 @@ export class HomeUtil {
}
// Make sure we revisit page in case login is changing.
await this . driver . get ( 'about:blank' ) ;
// When running against an external server, we log in through Cognito .
// When running against an external server, we log in through the Grist login page .
await this . driver . get ( this . server . getUrl ( org , "" ) ) ;
if ( ! ( await this . isOnSigninPage ( ) ) ) {
if ( ! await this . isOnLoginPage ( ) ) {
// Explicitly click sign-in link if necessary.
await this . driver . findWait ( '.test-user-signin' , 4000 ) . click ( ) ;
await this . driver . findContentWait ( '.grist-floating-menu a' , 'Sign in' , 500 ) . click ( ) ;
}
// Check if we need to switch to Cognito login from the Grist sign-up page.
if ( await this . isOnGristLoginPage ( ) ) {
await this . driver . findWait ( 'a[href*="login?"]' , 4000 ) . click ( ) ;
}
// Fill the login form (either on /test/login or Cognito ).
// Fill the login form (either test or Grist).
if ( await this . isOnTestLoginPage ( ) ) {
await this . fillTestLoginForm ( email , name ) ;
} else {
await this . fill LoginForm( email ) ;
await this . fill Grist LoginForm( email ) ;
}
if ( ! ( await this . isWelcomePage ( ) ) && ( options . freshAccount || options . isFirstLogin ) ) {
if ( ! await this . isWelcomePage ( ) && ( options . freshAccount || options . isFirstLogin ) ) {
await this . _recreateCurrentUser ( email , org , name ) ;
}
}
@ -148,29 +145,43 @@ export class HomeUtil {
await form . find ( 'input[name="signInSubmitButton"]' ) . click ( ) ;
}
// Fill up a Cognito login page. If on a signup page, switch to a login page.
// TEST_ACCOUNT_PASSWORD must be set, or a password provided. Should be on a Cognito
// login/signup page before calling this method.
public async fillLoginForm ( email : string , password? : string ) {
/ * *
* Fill up the Grist login page form , and submit . If called with a user that
* has TOTP - based 2 FA enabled , TEST_ACCOUNT_TOTP_SECRET must be set for a valid
* code to be submitted on the following form .
*
* Should be on the Grist login or sign - up page before calling this method . If
* ` password ` is not passed in , TEST_ACCOUNT_PASSWORD must be set .
* /
public async fillGristLoginForm ( email : string , password? : string ) {
if ( ! password ) {
password = process . env . TEST_ACCOUNT_PASSWORD ;
if ( ! password ) {
throw new Error ( 'TEST_ACCOUNT_PASSWORD not set' ) ;
}
}
await this . check LoginPage( ) ;
await this . check Grist LoginPage( ) ;
if ( ( await this . driver . getCurrentUrl ( ) ) . match ( /signup\?/ ) ) {
await this . driver . findWait ( 'a[href*="login?"]' , 4000 ) . click ( ) ;
}
// There are two login forms, one hidden, one shown. Pick the one that is shown.
const block =
( await this . driver . find ( 'div.modal-content-desktop' ) . isDisplayed ( ) ) ?
( await this . driver . find ( 'div.modal-content-desktop' ) ) :
( await this . driver . find ( 'div.modal-content-mobile' ) ) ;
await block . findWait ( 'input[name="username"]' , 4000 ) ;
await this . setValue ( block . findWait ( 'input[name="username"]' , 4000 ) , email ) ;
await this . setValue ( block . findWait ( 'input[name="password"]' , 4000 ) , password ) ;
await block . find ( 'input[name="signInSubmitButton"]' ) . click ( ) ;
await this . driver . findWait ( 'input[name="email"]' , 4000 ) . sendKeys ( email ) ;
await this . driver . find ( 'input[name="password"]' ) . sendKeys ( password ) ;
await this . driver . find ( '.test-lp-sign-in' ) . click ( ) ;
await this . driver . wait ( async ( ) = > ! await this . isOnGristLoginPage ( ) , 4000 ) ;
if ( ! await this . driver . findContent ( '.test-mfa-title' , 'Almost there!' ) . isPresent ( ) ) {
return ;
}
const secret = process . env . TEST_ACCOUNT_TOTP_SECRET ;
if ( ! secret ) { throw new Error ( 'TEST_ACCOUNT_TOTP_SECRET not set' ) ; }
const code = authenticator . generate ( secret ) ;
await this . driver . find ( 'input[name="verificationCode"]' ) . sendKeys ( code ) ;
await this . driver . find ( '.test-mfa-submit' ) . click ( ) ;
await this . driver . wait ( async ( ) = > {
return ! await this . driver . findContent ( '.test-mfa-title' , 'Almost there!' ) . isPresent ( ) ;
} , 4000 ) ;
}
/ * *
@ -275,18 +286,19 @@ export class HomeUtil {
}
/ * *
* Returns whether we are currently on the Cognito or test login page .
* Returns whether we are currently on any login page ( including the test page ) .
* /
public async isOnLoginPage() {
const url = await this . driver . getCurrentUrl ( ) ;
return /^https:\/\/gristlogin/ . test ( url ) || await this . isOnTestLoginPage ( ) ;
return await this . isOnGristLoginPage ( ) || await this . isOnTestLoginPage ( ) ;
}
/ * *
* Returns whether we are currently on a Grist login page .
* /
public async isOnGristLoginPage() {
return /^https:\/\/login(-s)?\.getgrist\.com/ . test ( await this . driver . getCurrentUrl ( ) ) ;
const isOnSignupPage = await this . driver . find ( '.test-sp-heading' ) . isPresent ( ) ;
const isOnLoginPage = await this . driver . find ( '.test-lp-heading' ) . isPresent ( ) ;
return isOnSignupPage || isOnLoginPage ;
}
/ * *
@ -297,14 +309,7 @@ export class HomeUtil {
}
/ * *
* Returns whether we are currently on any sign - in page ( e . g . Cognito , Grist , test ) .
* /
public async isOnSigninPage() {
return await this . isOnLoginPage ( ) || await this . isOnGristLoginPage ( ) ;
}
/ * *
* Waits for browser to navigate to the Cognito login page .
* Waits for browser to navigate to any login page ( including the test page ) .
* /
public async checkLoginPage ( waitMs : number = 2000 ) {
await this . driver . wait ( this . isOnLoginPage . bind ( this ) , waitMs ) ;
@ -317,13 +322,6 @@ export class HomeUtil {
await this . driver . wait ( this . isOnGristLoginPage . bind ( this ) , waitMs ) ;
}
/ * *
* Waits for browser to navigate to any sign - in page ( e . g . Cognito , Grist , test ) .
* /
public async checkSigninPage ( waitMs : number = 4000 ) {
await this . driver . wait ( this . isOnSigninPage . bind ( this ) , waitMs ) ;
}
/ * *
* Delete and recreate the user , via the specified org . The specified user must be
* currently logged in !
@ -335,11 +333,11 @@ export class HomeUtil {
await this . driver . findWait ( '.test-user-signin' , 4000 ) . click ( ) ;
await this . driver . findContentWait ( '.grist-floating-menu a' , 'Sign in' , 500 ) . click ( ) ;
await this . checkLoginPage ( ) ;
// Fill the login form (either on /test/login or Cognito ).
// Fill the login form (either test or Grist ).
if ( await this . isOnTestLoginPage ( ) ) {
await this . fillTestLoginForm ( email , name ) ;
} else {
await this . fill LoginForm( email ) ;
await this . fill Grist LoginForm( email ) ;
}
}