Skip to content

Commit

Permalink
Optimize tests (#1027)
Browse files Browse the repository at this point in the history
* get started

* wip

* it is working

* cleanup

* lint and cleanup

* navigate to setting on pc and phone (different views)

* more settings test, remove Sharedtransfermodal

* Update packages/files-ui/cypress/integration/settings.ts

* Update packages/files-ui/cypress/support/commands.ts

Co-authored-by: Michael Yankelev <12774278+FSM1@users.noreply.github.com>

Co-authored-by: Thibaut Sardan <hi@thib.top>
Co-authored-by: Michael Yankelev <12774278+FSM1@users.noreply.github.com>
  • Loading branch information
3 people authored May 13, 2021
1 parent ffe435e commit dcfd3d8
Show file tree
Hide file tree
Showing 14 changed files with 155 additions and 58 deletions.
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ jobs:
REACT_APP_BLOCKNATIVE_ID: ${{ secrets.GH_REACT_APP_BLOCKNATIVE_ID }}
REACT_APP_FILES_VERIFIER_NAME: ${{ secrets.GH_REACT_APP_FILES_VERIFIER_NAME }}
REACT_APP_FILES_UUID_VERIFIER_NAME: 'chainsafe-uuid-testnet'
REACT_APP_TEST: 'true'
with:
start: yarn start:files-ui
# quote the url to be safe against YML parsing surprises
Expand Down
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,9 @@ storybook-static
.vscode
.idea
.env
.DS_Store
.DS_Store

# test artifacts
packages/files-ui/cypress/screenshots
packages/files-ui/cypress/videos
packages/files-ui/cypress/fixtures/storage
6 changes: 4 additions & 2 deletions packages/common-components/src/Tabs/Tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ const Tabs: React.FC<ITabsProps> = ({ className, children, activeKey, injectedCl
clsx(
elem.props.tabKey === activeKey && "selected",
classes.tabBar,
injectedClass?.tabBar
injectedClass?.tabBar,
elem.props.tabKey
)}
onClick={() => onTabSelect(elem.props.tabKey)}
>
Expand All @@ -87,7 +88,8 @@ const Tabs: React.FC<ITabsProps> = ({ className, children, activeKey, injectedCl
clsx(
children.props.tabKey === activeKey && "selected",
classes.tabBar,
injectedClass?.tabBar
injectedClass?.tabBar,
children.props.tabKey
)}
onClick={() => onTabSelect(children.props.tabKey)}
>
Expand Down
1 change: 1 addition & 0 deletions packages/files-ui/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ REACT_APP_FILES_UUID_VERIFIER_NAME=chainsafe-uuid-testnet
# Set to `mainnet` if required
REACT_APP_DIRECT_AUTH_NETWORK=testnet
SENTRY_AUTH_TOKEN=
REACT_APP_TEST=true
24 changes: 0 additions & 24 deletions packages/files-ui/cypress/integration/login.ts

This file was deleted.

30 changes: 30 additions & 0 deletions packages/files-ui/cypress/integration/settings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
describe("Settings", () => {
it("can navigate to the settings profile page", () => {
cy.web3Login()
cy.get("[data-cy=settings-nav]").click()
cy.get("[data-cy=settings-profile-header").should("be.visible")
cy.url().should("include", "/settings")
cy.get(".profile").click()
cy.url().should("include", "/settings/profile")
cy.get("[data-cy=settings-profile-header]").should("be.visible")
cy.get(".security").click()
cy.url().should("include", "/settings/security")
cy.get("[data-cy=settings-security-header").should("be.visible")
})

it("can navigate to the settings security page on a phone", () => {
cy.viewport("iphone-6")
cy.web3Login()
cy.get(".hamburger-menu").click()
cy.get("[data-cy=settings-nav]").click()
cy.get("[data-cy=settings-profile-header]").should("not.exist")
cy.url().should("include", "/settings")
cy.get(".profile").click()
cy.url().should("include", "/settings/profile")
cy.get("[data-cy=settings-profile-header").should("be.visible")
cy.go("back")
cy.get(".security").click()
cy.url().should("include", "/settings/security")
cy.get("[data-cy=settings-security-header").should("be.visible")
})
})
17 changes: 13 additions & 4 deletions packages/files-ui/cypress/plugins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,26 @@
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
import { existsSync, readFileSync } from "fs"

// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)

/**
* @type {Cypress.PluginConfig}
*/
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export default (on, config) => {

export default (on: any) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config

on("task", {
readFileMaybe(filename: string) {
if (existsSync(filename)) {
return readFileSync(filename, "utf8")
}

return null
}
})
}
104 changes: 84 additions & 20 deletions packages/files-ui/cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,37 +29,101 @@ import { ethers, Wallet } from "ethers"
import { testPrivateKey, testAccountPassword, localHost } from "../fixtures/loginData"
import { CustomizedBridge } from "./utils/CustomBridge"

export type Storage = Record<string, string>[]

export interface Web3LoginOptions {
url?: string
saveBrowser?: boolean
useLocalAndSessionStorage?: boolean
}

Cypress.Commands.add("web3Login", ({ saveBrowser = false, url = localHost }: Web3LoginOptions = {}) => {
const SESSION_FILE = "cypress/fixtures/storage/sessionStorage.json"
const LOCAL_FILE = "cypress/fixtures/storage/localStorage.json"

Cypress.Commands.add("web3Login", ({ saveBrowser = false, url = localHost, useLocalAndSessionStorage = true }: Web3LoginOptions = {}) => {
let session: Storage = []
let local: Storage = []

cy.task<string | null>("readFileMaybe", SESSION_FILE)
.then((unparsedSession) => {
session = unparsedSession && JSON.parse(unparsedSession) || []
})

cy.task<string | null>("readFileMaybe", LOCAL_FILE)
.then((unparsedLocal) => {
local = unparsedLocal && JSON.parse(unparsedLocal) || []
})

cy.on("window:before:load", (win) => {
const provider = new ethers.providers.JsonRpcProvider("https://rinkeby.infura.io/v3/4bf032f2d38a4ed6bb975b80d6340847", 4)
const signer = new Wallet(testPrivateKey, provider)

// inject ethereum object in the global window
Object.defineProperty(win, "ethereum", {
get: () => new CustomizedBridge(signer as any, provider as any)
})

// clear session storage in any case, if previous session storage should be
// kept will be decided after.
// Note that Cypress keep the session storage between test but clears localStorage
win.sessionStorage.clear()
win.localStorage.clear()

if (useLocalAndSessionStorage){
session.forEach(({ key, value }) => {
win.sessionStorage.setItem(key, value)
})

local.forEach(({ key, value }) => {
win.localStorage.setItem(key, value)
})
}
})

cy.visit(url)
cy.get("[data-cy=web3]").click()
cy.get(".bn-onboard-modal-select-wallets > :nth-child(1) > .bn-onboard-custom").click()
cy.get("[data-cy=sign-in-with-web3-button]").click()
cy.get("[data-cy=login-password-button]", { timeout: 10000 }).click()
cy.get("[data-cy=login-password-input]").type(`${testAccountPassword}{enter}`)

if(saveBrowser){
cy.get("[data-cy=save-browser-button]").click()
} else {
cy.get("[data-cy=do-not-save-browser-button]").click()
}

cy.get("[data-cy=files-app-header", { timeout: 30000 }).should("be.visible")
// with nothing in localstorage (and in session storage)
// the whole login flow should kick in
cy.then(() => {
cy.log("Logging in", !!local.length && "there is something in session storage ---> direct login")

if(local.length === 0){
cy.log("nothing in session storage, --> click on web3 button")
cy.get("[data-cy=web3]").click()
cy.get(".bn-onboard-modal-select-wallets > :nth-child(1) > .bn-onboard-custom").click()
cy.get("[data-cy=sign-in-with-web3-button]").click()
cy.get("[data-cy=login-password-button]", { timeout: 20000 }).click()
cy.get("[data-cy=login-password-input]").type(`${testAccountPassword}{enter}`)

if(saveBrowser){
// this is taking forever for test accounts
cy.get("[data-cy=save-browser-button]").click()
} else {
cy.get("[data-cy=do-not-save-browser-button]").click()
}
}
})

cy.get("[data-cy=files-app-header", { timeout: 20000 }).should("be.visible")

// save local and session storage in files
cy.window().then((win) => {
const newLocal: Array<Record<string, string>> = []
const newSession: Array<Record<string, string>> = []

Object.keys(win.localStorage).forEach((key) => {
newLocal.push({ key, value: localStorage.getItem(key) || "" })
})

Object.keys(win.sessionStorage).forEach((key) => {
newSession.push({ key, value: sessionStorage.getItem(key) || "" })
})

const newLocalString = JSON.stringify(newLocal)
const newSessionString = JSON.stringify(newSession)

cy.writeFile(SESSION_FILE, newSessionString)
cy.writeFile(LOCAL_FILE, newLocalString)
})
})

// Must be declared global to be detected by typescript (allows import/export)
Expand All @@ -68,16 +132,16 @@ declare global {
namespace Cypress {
interface Chainable {
/**
* Login using Metamask to an instance of files running on localhost:3000.
* @param {Object} options
* @param {string} options.saveBrowser - save the browser to localstorage (default: false).
* @param {string} options.url - what url to visit (default: "http://localhost:3000").
* @example cy.web3Login({saveBrowser: true})
* Login using Metamask to an instance of Files.
* @param {String} options.url - (default: "http://localhost:3000") - what url to visit.
* @param {Boolean} options.saveBrowser - (default: false) - save the browser to localstorage.
* @param {Boolean} options.useLocalAndSessionStorage - (default: true) - use what could have been stored before to speedup login
* @example cy.web3Login({saveBrowser: true, url: 'http://localhost:8080'})
*/
web3Login: (options?: Web3LoginOptions) => Chainable
}
}
}

// Convert this to a module instead of script (allows import/export)
export {}
export {}
2 changes: 1 addition & 1 deletion packages/files-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
"extract": "lingui extract",
"compile": "lingui compile",
"lingui-version": "lingui --version",
"lint": "eslint './src/**/*.{js,jsx,ts,tsx}'"
"lint": "eslint './{src, cypress}/**/*.{js,jsx,ts,tsx}'"
},
"browserslist": {
"production": [
Expand Down
2 changes: 1 addition & 1 deletion packages/files-ui/src/Components/Layouts/AppHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ const AppHeader = ({ navOpen, setNavOpen }: IAppHeader) => {
<HamburgerMenu
onClick={() => setNavOpen(!navOpen)}
variant={navOpen ? "active" : "default"}
className={classes.hamburgerMenu}
className={clsx(classes.hamburgerMenu, "hamburger-menu")}
/>
<Link
className={classes.logo}
Expand Down
1 change: 1 addition & 0 deletions packages/files-ui/src/Components/Layouts/AppNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ const AppNav: React.FC<IAppNav> = ({ navOpen, setNavOpen }: IAppNav) => {
>
<SettingSvg />
<Typography
data-cy="settings-nav"
variant="h5"
className={classes.navItemText}
>
Expand Down
11 changes: 8 additions & 3 deletions packages/files-ui/src/Components/Modules/Settings/Profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,10 @@ const ProfileView = () => {
>
<Form>
{profile?.publicAddress ? (
<div className={classes.boxContainer}>
<div
className={classes.boxContainer}
data-cy="settings-profile-header"
>
<div className={classes.walletAddressContainer}>
<Typography
variant="body1"
Expand Down Expand Up @@ -320,8 +323,10 @@ const ProfileView = () => {
</div>
</div> */}
<div>
<Typography variant='h4'
component='h4'>
<Typography
variant='h4'
component='h4'
>
<Trans>Display Settings</Trans>
</Typography>
<Typography
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,10 @@ const Security = ({ className }: SecurityProps) => {

return (
<div className={clsx(classes.root, className)}>
<div id="security">
<div
id="security"
data-cy="settings-security-header"
>
<Typography
variant="h4"
component="h4"
Expand Down
2 changes: 1 addition & 1 deletion packages/files-ui/src/Contexts/ThresholdKeyContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -825,7 +825,7 @@ const ThresholdKeyProvider = ({ children, network = "mainnet", enableLogging = f
loggedinAs
}}
>
{!isNewDevice && pendingShareTransferRequests.length > 0 && (
{!isNewDevice && pendingShareTransferRequests.length > 0 && process.env.REACT_APP_TEST !== "true" && (
<ShareTransferRequestModal
requests={pendingShareTransferRequests}
/>
Expand Down

0 comments on commit dcfd3d8

Please sign in to comment.