diff --git a/packages/files-ui/cypress/support/commands.ts b/packages/files-ui/cypress/support/commands.ts index baf73539aa..693b9f9ed8 100644 --- a/packages/files-ui/cypress/support/commands.ts +++ b/packages/files-ui/cypress/support/commands.ts @@ -26,17 +26,16 @@ // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) import { authenticationPage } from "./page-objects/authenticationPage" -import { apiTestHelper } from "./utils/apiTestHelper" +import { apiTestHelper, ClearBucketType } from "./utils/apiTestHelper" import { ethers, Wallet } from "ethers" import { homePage } from "./page-objects/homePage" import { testPrivateKey, testAccountPassword, localHost } from "../fixtures/loginData" import { CustomizedBridge } from "./utils/CustomBridge" import "cypress-file-upload" import "cypress-pipe" -import { BucketType } from "@chainsafe/files-api-client" import { navigationMenu } from "./page-objects/navigationMenu" -Cypress.Commands.add("clearBucket", (bucketType: BucketType) => { +Cypress.Commands.add("clearBucket", (bucketType: ClearBucketType) => { apiTestHelper.clearBucket(bucketType) }) @@ -47,6 +46,7 @@ export interface Web3LoginOptions { clearCSFBucket?: boolean clearTrashBucket?: boolean deleteShareBucket?: boolean + withNewUser?: boolean } Cypress.Commands.add( @@ -56,7 +56,8 @@ Cypress.Commands.add( url = localHost, clearCSFBucket = false, clearTrashBucket = false, - deleteShareBucket = false + deleteShareBucket = false, + withNewUser = true }: Web3LoginOptions = {}) => { cy.on("window:before:load", (win) => { @@ -64,32 +65,49 @@ Cypress.Commands.add( "https://rinkeby.infura.io/v3/4bf032f2d38a4ed6bb975b80d6340847", 4 ) - const signer = new Wallet(testPrivateKey, provider) + const signer = withNewUser + ? Wallet.createRandom() + : new Wallet(testPrivateKey, provider) // inject ethereum object in the global window Object.defineProperty(win, "ethereum", { - get: () => new CustomizedBridge(signer as any, provider as any) + get: () => new CustomizedBridge(signer as any, signer.address, provider as any) }) }) - // with nothing in localstorage (and in session storage) - // the whole login flow should kick in - cy.session("web3login", () => { - cy.visit(url) - authenticationPage.web3Button().click() - authenticationPage.showMoreButton().click() - authenticationPage.detectedWallet().click() - authenticationPage.web3SignInButton().safeClick() - authenticationPage.loginPasswordButton().click() - authenticationPage.loginPasswordInput().type(`${testAccountPassword}{enter}`) - - if (saveBrowser) { - // this is taking forever for test accounts - authenticationPage.saveBrowserButton().click() - } else { - authenticationPage.doNotSaveBrowserButton().click() - } - homePage.appHeaderLabel().should("be.visible") - }) + if (withNewUser){ + cy.session("web3loginNewUser", () => { + cy.visit(url) + authenticationPage.web3Button().click() + authenticationPage.showMoreButton().click() + authenticationPage.detectedWallet().click() + authenticationPage.web3SignInButton().safeClick() + authenticationPage.signInExplainerContinueButton().safeClick() + // we are using the testAccount password here, but we could input anything + authenticationPage.signInSetupPasswordInput().type(`${testAccountPassword}`) + authenticationPage.signInSetupPasswordVerificationInput().type(`${testAccountPassword}{enter}`) + + homePage.appHeaderLabel().should("be.visible") + }) + } else { + cy.session("web3loginTestUser", () => { + cy.visit(url) + authenticationPage.web3Button().click() + authenticationPage.showMoreButton().click() + authenticationPage.detectedWallet().click() + authenticationPage.web3SignInButton().safeClick() + authenticationPage.loginPasswordButton().click() + authenticationPage.loginPasswordInput().type(`${testAccountPassword}{enter}`) + + if (saveBrowser) { + // this is taking forever for test accounts + authenticationPage.saveBrowserButton().click() + } else { + authenticationPage.doNotSaveBrowserButton().click() + } + homePage.appHeaderLabel().should("be.visible") + }) + } + cy.visit(url) homePage.appHeaderLabel().should("be.visible") @@ -115,7 +133,7 @@ Cypress.Commands.add( } ) -Cypress.Commands.add("safeClick", { prevSubject: "element" }, $element => { +Cypress.Commands.add("safeClick", { prevSubject: "element" }, ($element?: JQuery) => { const click = ($el: JQuery) => $el.trigger("click") return cy .wrap($element) @@ -137,9 +155,10 @@ declare global { * @param {Boolean} options.clearCSFBucket - (default: false) - whether any file in the csf bucket should be deleted. * @param {Boolean} options.clearTrashBucket - (default: false) - whether any file in the trash bucket should be deleted. * @param {Boolean} options.deleteShareBucket - (default: false) - whether any shared bucket should be deleted. + * @param {Boolean} options.withNewUser - (default: true) - whether to create a new user for this session. * @example cy.web3Login({saveBrowser: true, url: 'http://localhost:8080'}) */ - web3Login: (options?: Web3LoginOptions) => Chainable + web3Login: (options?: Web3LoginOptions) => void /** * Use this when encountering race condition issues resulting in @@ -153,8 +172,14 @@ declare global { * https://github.com/cypress-io/cypress/issues/7306 * */ - safeClick: () => Chainable + safeClick: ($element?: JQuery) => Chainable + /** + * Clear a bucket. + * @param {BucketType} - what bucket type to clear for this user. + * @example cy.clearBucket("csf") + */ + clearBucket: (bucketType: ClearBucketType) => void } } } diff --git a/packages/files-ui/cypress/support/page-objects/authenticationPage.ts b/packages/files-ui/cypress/support/page-objects/authenticationPage.ts index 2c408c7cd3..5d8e68b258 100644 --- a/packages/files-ui/cypress/support/page-objects/authenticationPage.ts +++ b/packages/files-ui/cypress/support/page-objects/authenticationPage.ts @@ -12,6 +12,10 @@ export const authenticationPage = { // sign in section elements loginPasswordButton: () => cy.get("[data-cy=login-password-button]", { timeout: 20000 }), loginPasswordInput: () => cy.get("[data-cy=login-password-input]"), + signInExplainerContinueButton: () => cy.get("[data-cy=button-sign-in-explainer-continue]", { timeout: 20000 }), + signInSetupPasswordInput: () => cy.get("[data-cy=input-sign-in-password]"), + signInSetupPasswordVerificationInput: () => cy.get("[data-cy=input-sign-in-password-verification]"), + signInSetupPasswordSubmitButton: () => cy.get("[data-cy=button-sign-in-password]"), // save browser section elements saveBrowserButton: () => cy.get("[data-cy=save-browser-button]"), diff --git a/packages/files-ui/cypress/support/utils/CustomBridge.ts b/packages/files-ui/cypress/support/utils/CustomBridge.ts index 4924ecbbff..ff1fd4c19c 100644 --- a/packages/files-ui/cypress/support/utils/CustomBridge.ts +++ b/packages/files-ui/cypress/support/utils/CustomBridge.ts @@ -1,8 +1,15 @@ import { Eip1193Bridge } from "@ethersproject/experimental/lib/eip1193-bridge" +import { ethers } from "ethers" import { toUtf8String } from "ethers/lib/utils" -import { testAddress } from "../../fixtures/loginData" export class CustomizedBridge extends Eip1193Bridge { + expectedAddress = "" + + constructor(signer: ethers.Signer, address: string, provider?: ethers.providers.Provider) { + super(signer as any, provider as any) + this.expectedAddress = address + } + async sendAsync(...args: Array) { return this.send(...args) } @@ -30,17 +37,17 @@ export class CustomizedBridge extends Eip1193Bridge { const message = params[0] if ( - (addr as string).toLowerCase() !== testAddress.toLowerCase() + (addr as string).toLowerCase() !== this.expectedAddress.toLowerCase() ) { return Promise.reject( - `Wrong address, expected ${testAddress}, but got ${addr}` + `Wrong address, expected ${this.expectedAddress}, but got ${addr}` ) } try { const sig = await this.signer.signMessage(toUtf8String(message)) return sig - } catch (e) { + } catch (e: any) { return Promise.reject( `Error in CustomizedBridge for personal_sign: ${e.message}` ) @@ -49,9 +56,9 @@ export class CustomizedBridge extends Eip1193Bridge { if (method === "eth_requestAccounts" || method === "eth_accounts") { if (isCallbackForm) { - callback({ result: [testAddress] }) + callback({ result: [this.expectedAddress] }) } else { - return Promise.resolve([testAddress]) + return Promise.resolve([this.expectedAddress]) } } diff --git a/packages/files-ui/cypress/support/utils/apiTestHelper.ts b/packages/files-ui/cypress/support/utils/apiTestHelper.ts index 50cd2e053a..4be4ea8ab8 100644 --- a/packages/files-ui/cypress/support/utils/apiTestHelper.ts +++ b/packages/files-ui/cypress/support/utils/apiTestHelper.ts @@ -7,6 +7,7 @@ import { homePage } from "../page-objects/homePage" const API_BASE_USE = "https://stage.imploy.site/api/v1" const REFRESH_TOKEN_KEY = "csf.refreshToken" +export type ClearBucketType = Exclude const getApiClient = () => { // Disable the internal Axios JSON deserialization as this is handled by the client const axiosInstance = axios.create({ transformResponse: [] }) @@ -34,7 +35,7 @@ export const apiTestHelper = { }) }) }, - clearBucket(bucketType: BucketType) { + clearBucket(bucketType: ClearBucketType) { const apiClient = getApiClient() return new Cypress.Promise(async (resolve) => { diff --git a/packages/files-ui/cypress/tests/survey-banner-spec.ts b/packages/files-ui/cypress/tests/survey-banner-spec.ts index fb66f27708..eb9c08a074 100644 --- a/packages/files-ui/cypress/tests/survey-banner-spec.ts +++ b/packages/files-ui/cypress/tests/survey-banner-spec.ts @@ -20,7 +20,7 @@ describe("Survey Banner", () => { body: { [dismissedSurveyKey]: "false" } }) - cy.web3Login() + cy.web3Login({ withNewUser: false }) homePage.surveyBanner().should("be.visible") // set up a spy for the POST response @@ -42,7 +42,7 @@ describe("Survey Banner", () => { body: { [dismissedSurveyKey]: "true" } }) - cy.web3Login() + cy.web3Login({ withNewUser: false }) homePage.surveyBanner().should("not.exist") }) @@ -51,7 +51,7 @@ describe("Survey Banner", () => { body: {} }) - cy.web3Login() + cy.web3Login({ withNewUser: false }) homePage.surveyBanner().should("be.visible") }) @@ -67,7 +67,12 @@ describe("Survey Banner", () => { body: {} }) - cy.web3Login() + cy.web3Login({ withNewUser: false }) + homePage.surveyBanner().should("not.exist") + }) + + it("A new user should not see the banner", () => { + cy.web3Login({ withNewUser: true }) homePage.surveyBanner().should("not.exist") }) }) diff --git a/packages/files-ui/src/Components/Elements/PasswordForm.tsx b/packages/files-ui/src/Components/Elements/PasswordForm.tsx index e99eeea19a..8652444779 100644 --- a/packages/files-ui/src/Components/Elements/PasswordForm.tsx +++ b/packages/files-ui/src/Components/Elements/PasswordForm.tsx @@ -104,6 +104,7 @@ const PasswordForm = ({ buttonLabel, setPassword }: Props) => { label={t`Password:`} labelClassName={classes.inputLabel} captionMessage={} + data-cy="input-sign-in-password" /> { name="confirmPassword" label={t`Confirm Password:`} labelClassName={classes.inputLabel} + data-cy="input-sign-in-password-verification" /> diff --git a/packages/files-ui/src/Components/Modules/LoginModule/ConciseExplainer.tsx b/packages/files-ui/src/Components/Modules/LoginModule/ConciseExplainer.tsx index 9ada6ef109..d18dec3849 100644 --- a/packages/files-ui/src/Components/Modules/LoginModule/ConciseExplainer.tsx +++ b/packages/files-ui/src/Components/Modules/LoginModule/ConciseExplainer.tsx @@ -178,6 +178,7 @@ const ConciseExplainer: React.FC = ({ className, onConti variant="primary" onClick={onContinue} className={classes.continue} + data-cy="button-sign-in-explainer-continue" > Continue