diff --git a/packages/files-ui/cypress/fixtures/filesTestData.ts b/packages/files-ui/cypress/fixtures/filesTestData.ts new file mode 100644 index 0000000000..792eecd885 --- /dev/null +++ b/packages/files-ui/cypress/fixtures/filesTestData.ts @@ -0,0 +1 @@ +export const folderName = "Testing" \ No newline at end of file diff --git a/packages/files-ui/cypress/support/commands.ts b/packages/files-ui/cypress/support/commands.ts index ba719f728f..74fd24c95a 100644 --- a/packages/files-ui/cypress/support/commands.ts +++ b/packages/files-ui/cypress/support/commands.ts @@ -32,6 +32,7 @@ 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" export type Storage = Record[]; @@ -146,7 +147,7 @@ Cypress.Commands.add( authenticationPage.web3Button().click() authenticationPage.showMoreButton().click() authenticationPage.detectedWallet().click() - authenticationPage.web3SignInButton().click() + authenticationPage.web3SignInButton().safeClick() authenticationPage.loginPasswordButton().click() authenticationPage.loginPasswordInput().type(`${testAccountPassword}{enter}`) @@ -172,12 +173,33 @@ Cypress.Commands.add( } if(clearTrashBucket || clearCSFBucket){ - cy.reload() + cy.reload({ timeout: 50000 }).then(() => { + if (local.length === 0) { + // Temp work around for local storage being cleared after the reload. See issue in #1381 + cy.log("nothing in local storage after reload, --> click on web3 button") + authenticationPage.web3Button().click() + authenticationPage.showMoreButton().click() + authenticationPage.detectedWallet().click() + authenticationPage.web3SignInButton().safeClick() + authenticationPage.loginPasswordButton().click() + authenticationPage.loginPasswordInput().type(`${testAccountPassword}{enter}`) + authenticationPage.doNotSaveBrowserButton().click() + } + }) homePage.appHeaderLabel().should("be.visible") } } ) +Cypress.Commands.add("safeClick", { prevSubject: "element" }, $element => { + const click = ($el: JQuery) => $el.trigger("click") + return cy + .wrap($element) + .should("be.visible") + .pipe(click) + .should($el => expect($el).to.not.be.visible) +}) + // Must be declared global to be detected by typescript (allows import/export) // eslint-disable @typescript/interface-name declare global { @@ -207,6 +229,21 @@ declare global { * @example cy.saveLocalAndSession() */ saveLocalAndSession: () => Chainable + + /** + * Use this when encountering race condition issues resulting in + * cypress "detached from DOM" issues or clicking before an event + * listener has been registered + * + * Temporary solution until cypress improve this issue + * further info + * https://www.cypress.io/blog/2019/01/22/when-can-the-test-click/ + * https://github.com/testing-library/cypress-testing-library/issues/153#issuecomment-692386444 + * https://github.com/cypress-io/cypress/issues/7306 + * + */ + safeClick: () => Chainable + } } } diff --git a/packages/files-ui/cypress/support/page-objects/homePage.ts b/packages/files-ui/cypress/support/page-objects/homePage.ts index 6d5138f6f1..eb18cee55f 100644 --- a/packages/files-ui/cypress/support/page-objects/homePage.ts +++ b/packages/files-ui/cypress/support/page-objects/homePage.ts @@ -1,4 +1,5 @@ import { basePage } from "./basePage" +import { folderName } from "../../fixtures/filesTestData" export const click = ($el: JQuery) => $el.trigger("click") @@ -6,7 +7,8 @@ export const homePage = { ...basePage, // main file browser elements - uploadButton: () => cy.get("[data-cy=upload-modal-button]"), + newFolderButton: () => cy.get("[data-cy=button-new-folder]"), + uploadButton: () => cy.get("[data-cy=button-upload-file]"), uploadFileForm: () => cy.get("[data-cy=upload-file-form] input", { timeout: 20000 }), moveSelectedButton: () => cy.get("[data-testId=button-move-selected-file]"), deleteSelectedButton: () => cy.get("[data-testId=button-delete-selected-file]"), @@ -23,6 +25,12 @@ export const homePage = { fileRenameErrorLabel: () => cy.get("[data-cy=rename-form] span.minimal.error"), fileItemKebabButton: () => cy.get("[data-testid=dropdown-title-fileDropdown]"), + // create folder modal elements + createFolderModal: () => cy.get("[data-cy=modal-create-folder]", { timeout: 10000 }), + folderNameInput: () => cy.get("[data-cy=input-folder-name]"), + cancelButton: () => cy.get("[data-cy=button-cancel-create-folder]"), + createButton: () => cy.get("[data-cy=button-create-folder]"), + // upload modal elements startUploadButton: () => cy.get("[data-testId=button-start-upload]"), uploadCancelButton: () => cy.get("[data-testId=button-cancel-upload]"), @@ -38,26 +46,25 @@ export const homePage = { moveMenuOption: () => cy.get("[data-cy=menu-move]"), deleteMenuOption: () => cy.get("[data-cy=menu-delete]"), - clickUploadButton: () => homePage.startUploadButton() - .should("not.be.disabled") - // this pipe is needed to prevent https://github.com/ChainSafe/ui-monorepo/issues/1146 - // as described https://www.cypress.io/blog/2019/01/22/when-can-the-test-click/ - .pipe(click) - .should(($el: JQuery) => { - expect($el).to.not.be.visible - }), - // helpers and convenience functions uploadFile(filePath: string) { this.uploadButton().click() this.uploadFileForm().attachFile(filePath) this.fileUploadList().should("have.length", 1) this.fileListRemoveButton().should("be.visible") - this.clickUploadButton() + this.startUploadButton().safeClick() // ensure upload is complete before proceeding this.uploadFileForm().should("not.exist") this.uploadStatusToast().should("not.exist") + }, + + createFolder(name: string = folderName) { + this.newFolderButton().click() + this.folderNameInput().type(name) + this.createButton().safeClick() + this.createFolderModal().should("not.exist") + this.fileItemName().contains(name) } } diff --git a/packages/files-ui/cypress/tests/file-management-spec.ts b/packages/files-ui/cypress/tests/file-management-spec.ts index c08e2fb7e3..b55b2f6cdc 100644 --- a/packages/files-ui/cypress/tests/file-management-spec.ts +++ b/packages/files-ui/cypress/tests/file-management-spec.ts @@ -1,13 +1,30 @@ import { binPage } from "../support/page-objects/binPage" import { homePage } from "../support/page-objects/homePage" import { navigationMenu } from "../support/page-objects/navigationMenu" +import { folderName } from "../fixtures/filesTestData" import "cypress-pipe" describe("File management", () => { context("desktop", () => { - it("can add files and cancel", () => { + it("can create folders and cancel modal", () => { + cy.web3Login({ clearCSFBucket: true }) + + // create a folder and see it in the file list + homePage.newFolderButton().click() + homePage.folderNameInput().type(folderName) + homePage.createButton().safeClick() + homePage.createFolderModal().should("not.exist") + homePage.fileItemName().contains(folderName) + + // cancel and ensure that the create folder modal is dismissed + homePage.newFolderButton().click() + homePage.cancelButton().click() + homePage.createFolderModal().should("not.exist") + }) + + it("can add files and cancel modal", () => { cy.web3Login() // upload a file and see it in the file list @@ -39,7 +56,7 @@ describe("File management", () => { homePage.uploadFileForm().attachFile("../fixtures/uploadedFiles/text-file.txt") homePage.fileUploadList().should("have.length", 2) homePage.fileListRemoveButton().should("have.length", 2) - homePage.clickUploadButton() + homePage.startUploadButton().safeClick() homePage.uploadFileForm().should("not.exist") homePage.fileItemRow().should("have.length", 2) }) @@ -103,12 +120,33 @@ describe("File management", () => { homePage.fileItemRow().should("have.length", 1) // retrieve the deleted file's name, store as a cypress alias - binPage.fileItemName().invoke("text").as("deletedFile") + binPage.fileItemName().invoke("text").as("binFile") // ensure file in bin matches the name of the deleted file cy.get("@originalFile").then(($originalFile) => { - cy.get("@deletedFile").should("equals", $originalFile) + cy.get("@binFile").should("equals", $originalFile) }) }) + + it("can delete a folder", () => { + cy.web3Login({ clearCSFBucket: true, clearTrashBucket: true }) + + // create a folder + homePage.createFolder(folderName) + homePage.fileItemRow().should("have.length", 1) + + // delete the folder via the menu option + homePage.fileItemKebabButton().first().click() + homePage.deleteMenuOption().click() + homePage.deleteFileDialog().should("be.visible") + homePage.deleteFileConfirmButton().click() + homePage.deleteFileDialog().should("not.exist") + homePage.fileItemRow().should("not.exist") + + // confirm the deleted folder is moved to the bin + navigationMenu.binNavButton().click() + binPage.fileItemRow().should("have.length", 1) + binPage.fileItemName().should("have.text", folderName) + }) }) -}) +}) \ No newline at end of file diff --git a/packages/files-ui/src/Components/Modules/FileBrowsers/CreateFolderModal.tsx b/packages/files-ui/src/Components/Modules/FileBrowsers/CreateFolderModal.tsx index 27195e4d30..64604d4404 100644 --- a/packages/files-ui/src/Components/Modules/FileBrowsers/CreateFolderModal.tsx +++ b/packages/files-ui/src/Components/Modules/FileBrowsers/CreateFolderModal.tsx @@ -132,7 +132,10 @@ const CreateFolderModal: React.FC = ({ }} >
-
+
{!desktop && ( = ({ className={classes.input} > = ({ justifyContent="flex-end" > close()} size="medium" className={classes.cancelButton} @@ -178,6 +183,7 @@ const CreateFolderModal: React.FC = ({ Cancel