Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test file upload #1035

Merged
merged 11 commits into from
May 20, 2021
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This is the text inside the text-file.txt file.
26 changes: 26 additions & 0 deletions packages/files-ui/cypress/integration/file-management.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
describe("File management", () => {
it("can add files and cancel", () => {
cy.web3Login()
cy.get("[data-cy=upload-modal-button").click()
cy.get("[data-cy=upload-file-form] input").attachFile("../fixtures/uploadedFiles/text-file.txt")
cy.get(".scrollbar li").should("have.length", 1)
cy.get("[data-cy=upload-cancel-button").click()
cy.get("[data-cy=files-app-header").should("be.visible")
})

it("can add/remove files and upload", () => {
cy.web3Login({ clearCSFBucket: true })
cy.get("[data-cy=upload-modal-button").click()
cy.get("[data-cy=upload-file-form] input").attachFile("../fixtures/uploadedFiles/text-file.txt")
cy.get(".scrollbar li").should("have.length", 1)
cy.get("[data-cy=upload-file-form] input").attachFile("../fixtures/uploadedFiles/logo.png")
cy.get(".scrollbar li").should("have.length", 2)
cy.get(".removeFileIcon").first().click()
cy.get(".scrollbar li").should("have.length", 1)
cy.get("[data-cy=upload-file-form] input").attachFile("../fixtures/uploadedFiles/text-file.txt")
cy.get(".scrollbar li").should("have.length", 2)
cy.get("[data-cy=upload-ok-button").click()
cy.get("[data-cy=files-app-header").should("be.visible")
cy.get("[data-cy=file-item-row]").should("have.length", 2)
})
})
110 changes: 85 additions & 25 deletions packages/files-ui/cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,78 @@
import { ethers, Wallet } from "ethers"
import { testPrivateKey, testAccountPassword, localHost } from "../fixtures/loginData"
import { CustomizedBridge } from "./utils/CustomBridge"
import "cypress-file-upload"

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

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

const SESSION_FILE = "cypress/fixtures/storage/sessionStorage.json"
const LOCAL_FILE = "cypress/fixtures/storage/localStorage.json"
const REFRESH_TOKEN_KEY = "csf.refreshToken"

Cypress.Commands.add("web3Login", ({ saveBrowser = false, url = localHost, useLocalAndSessionStorage = true }: Web3LoginOptions = {}) => {
Cypress.Commands.add("clearCsfBucket", (apiUrlBase: string) => {
cy.window().then((win) => {
cy.request("POST", `${apiUrlBase}/user/refresh`, { "refresh": win.sessionStorage.getItem(REFRESH_TOKEN_KEY) })
.then((res) => res.body.access_token.token)
.then((accessToken) => {
cy.request({
method: "POST",
url: `${apiUrlBase}/files/ls`,
body: { "path": "/", "source": { "type": "csf" } },
auth: { "bearer": accessToken }
}).then((res) => {
const toDelete = res.body.map(({ name }: { name: string }) => `/${name}`)
cy.request({
method: "POST",
url: `${apiUrlBase}/files/rm`,
body: { "paths": toDelete, "source": { "type": "csf" } },
auth: { "bearer": accessToken }
}).then(res => {
if(!res.isOkStatusCode){
throw new Error(`unexpected answer when deleting files: ${JSON.stringify(res, null, 2)}`)
}
})
})
})
})
})

Cypress.Commands.add("saveLocalAndSession", () => {
// save local and session storage in files
cy.window().then((win) => {
const newLocal: Storage = []
const newSession: Storage = []

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

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

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

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

Cypress.Commands.add("web3Login", ({
saveBrowser = false,
url = localHost,
apiUrlBase = "https://stage.imploy.site/api/v1",
useLocalAndSessionStorage = true,
clearCSFBucket = false
}: Web3LoginOptions = {}) => {
let session: Storage = []
let local: Storage = []

Expand Down Expand Up @@ -68,7 +127,7 @@ Cypress.Commands.add("web3Login", ({ saveBrowser = false, url = localHost, useLo
win.sessionStorage.clear()
win.localStorage.clear()

if (useLocalAndSessionStorage){
if (useLocalAndSessionStorage) {
session.forEach(({ key, value }) => {
win.sessionStorage.setItem(key, value)
})
Expand All @@ -84,18 +143,18 @@ Cypress.Commands.add("web3Login", ({ saveBrowser = false, url = localHost, useLo
// 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")
cy.log("Logging in", local.length > 0 && "there is something in session storage ---> direct login")

if(local.length === 0){
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
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()
Expand All @@ -105,25 +164,11 @@ Cypress.Commands.add("web3Login", ({ saveBrowser = false, url = localHost, useLo

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.saveLocalAndSession()

cy.writeFile(SESSION_FILE, newSessionString)
cy.writeFile(LOCAL_FILE, newLocalString)
})
if (clearCSFBucket) {
cy.clearCsfBucket(apiUrlBase)
}
})

// Must be declared global to be detected by typescript (allows import/export)
Expand All @@ -134,14 +179,29 @@ declare global {
/**
* Login using Metamask to an instance of Files.
* @param {String} options.url - (default: "http://localhost:3000") - what url to visit.
* @param {String} apiUrlBase - (default: "https://stage.imploy.site/api/v1") - what url to call for the api.
* @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
* @param {Boolean} options.clearCSFBucket - (default: false) - whether any file in the csf bucket should be deleted.
* @example cy.web3Login({saveBrowser: true, url: 'http://localhost:8080'})
*/
web3Login: (options?: Web3LoginOptions) => Chainable

/**
* Removed any file or folder at the root
* @param {String} apiUrlBase - what url to call for the api.
* @example cy.clearCsfBucket("https://stage.imploy.site/api/v1")
*/
clearCsfBucket: (apiUrlBase: string) => Chainable

/**
* Save loval and session storage to local files
Tbaut marked this conversation as resolved.
Show resolved Hide resolved
* @example cy.saveLocalAndSession()
*/
saveLocalAndSession: () => Chainable
}
}
}

// Convert this to a module instead of script (allows import/export)
export {}
export { }
11 changes: 11 additions & 0 deletions packages/files-ui/cypress/support/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,16 @@
// Import commands.js using ES2015 syntax:
import "./commands"

// the following gets rid of the exception "ResizeObserver loop limit exceeded"
// which someone on the internet says we can safely ignore
// source https://stackoverflow.com/questions/49384120/resizeobserver-loop-limit-exceeded
const resizeObserverLoopErrRe = /^[^(ResizeObserver loop limit exceeded)]/
Cypress.on("uncaught:exception", (err) => {
/* returning false here prevents Cypress from failing the test */
if (resizeObserverLoopErrRe.test(err.message)) {
return false
}
})

// Alternatively you can use CommonJS syntax:
// require('./commands')
2 changes: 1 addition & 1 deletion packages/files-ui/cypress/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"target": "es5",
"jsx": "react",
"lib": ["es5", "dom"],
"types": ["cypress"]
"types": ["cypress", "cypress-file-upload"]
},
"include": ["**/*.ts"]
}
5 changes: 3 additions & 2 deletions packages/files-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,9 @@
"@types/yup": "^0.29.9",
"@types/zxcvbn": "^4.4.0",
"babel-plugin-macros": "^2.8.0",
"cypress": "^7.2.0",
"eslint-plugin-cypress": "^2.11.2"
"cypress": "^7.3.0",
"cypress-file-upload": "^5.0.7",
"eslint-plugin-cypress": "^2.11.3"
},
"scripts": {
"postinstall": "yarn compile",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ const FileSystemTableItem = React.forwardRef(

return (
<TableRow
data-cy="file-item-row"
className={clsx(classes.tableRow, {
droppable: isFolder && (isOverMove || isOverUpload)
})}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,7 @@ const FilesTableView = () => {
</span>
</Button>
<Button
data-cy="upload-modal-button"
onClick={() => setIsUploadModalOpen(true)}
variant="outline"
size="large"
Expand Down
9 changes: 7 additions & 2 deletions packages/files-ui/src/Components/Modules/UploadFileModule.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,15 @@ const UploadFileModule = ({ modalOpen, close }: IUploadFileModuleProps) => {
validationSchema={UploadSchema}
onSubmit={onSubmit}
>
<Form className={classes.root}>
<Form
data-cy="upload-file-form"
className={classes.root}
>
<FileInput
multiple={true}
className={classes.input}
classNames={{
closeIcon: classes.closeIcon,
closeIcon: clsx(classes.closeIcon, "removeFileIcon"),
filelist: classes.fileList,
item: classes.item,
addFiles: classes.addFiles
Expand All @@ -135,6 +138,7 @@ const UploadFileModule = ({ modalOpen, close }: IUploadFileModuleProps) => {
/>
<footer className={classes.footer}>
<Button
data-cy="upload-cancel-button"
onClick={close}
size="medium"
className={classes.cancelButton}
Expand All @@ -144,6 +148,7 @@ const UploadFileModule = ({ modalOpen, close }: IUploadFileModuleProps) => {
<Trans>Cancel</Trans>
</Button>
<Button
data-cy="upload-ok-button"
size="medium"
type="submit"
variant="primary"
Expand Down
21 changes: 13 additions & 8 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9123,10 +9123,15 @@ cyclist@^1.0.1:
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=

cypress@^7.2.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/cypress/-/cypress-7.2.0.tgz#6a3364e18972f898fff1fb12c1ff747939e45ddc"
integrity sha512-lHHGay+YsffDn4M0bkkwezylBVHUpwwhtqte4LNPrFRCHy77X38+1PUe3neFb3glVTM+rbILtTN6FhO2djcOuQ==
cypress-file-upload@^5.0.7:
version "5.0.7"
resolved "https://registry.yarnpkg.com/cypress-file-upload/-/cypress-file-upload-5.0.7.tgz#acf24fe08a92b2d0c892a58b56811fb933d34ea9"
integrity sha512-cgWsWx7igxjyyVm9/VJ9ukdy69jL00I7z0lrwUWtXXLPvX4neO+8JAZ054Ax8Xf+mdV9OerenXzb9nqRoafjHA==

cypress@^7.3.0:
version "7.3.0"
resolved "https://registry.yarnpkg.com/cypress/-/cypress-7.3.0.tgz#17345b8d18681c120f033e7d8fd0f0271e9d0d51"
integrity sha512-aseRCH1tRVCrM6oEfja6fR/bo5l6e4SkHRRSATh27UeN4f/ANC8U7tGIulmrISJVy9xuOkOdbYKbUb2MNM+nrw==
dependencies:
"@cypress/listr-verbose-renderer" "^0.4.1"
"@cypress/request" "^2.88.5"
Expand Down Expand Up @@ -10155,10 +10160,10 @@ eslint-module-utils@^2.4.1:
debug "^2.6.9"
pkg-dir "^2.0.0"

eslint-plugin-cypress@^2.11.2:
version "2.11.2"
resolved "https://registry.yarnpkg.com/eslint-plugin-cypress/-/eslint-plugin-cypress-2.11.2.tgz#a8f3fe7ec840f55e4cea37671f93293e6c3e76a0"
integrity sha512-1SergF1sGbVhsf7MYfOLiBhdOg6wqyeV9pXUAIDIffYTGMN3dTBQS9nFAzhLsHhO+Bn0GaVM1Ecm71XUidQ7VA==
eslint-plugin-cypress@^2.11.3:
version "2.11.3"
resolved "https://registry.yarnpkg.com/eslint-plugin-cypress/-/eslint-plugin-cypress-2.11.3.tgz#54ee4067aa8192aa62810cd35080eb577e191ab7"
integrity sha512-hOoAid+XNFtpvOzZSNWP5LDrQBEJwbZwjib4XJ1KcRYKjeVj0mAmPmucG4Egli4j/aruv+Ow/acacoloWWCl9Q==
dependencies:
globals "^11.12.0"

Expand Down