Skip to content

Commit

Permalink
Merge pull request #2025 from ChainSafe/dev
Browse files Browse the repository at this point in the history
Release - 2022-03-17
  • Loading branch information
FSM1 authored Mar 18, 2022
2 parents 03f67c5 + 36a76ac commit c4e0b7a
Show file tree
Hide file tree
Showing 38 changed files with 808 additions and 220 deletions.
8 changes: 6 additions & 2 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,9 @@ Submission checklist:
- [ ] Change looks good in the mobile web ui

#### Theme
- [ ] Components / elements inspected in light mode
- [ ] Components / elements inspected in dark mode
- [ ] Components / elements inspected in light mode
- [ ] Components / elements inspected in dark mode

#### Billing
- [ ] Change applied to both files-ui and storage-ui

2 changes: 1 addition & 1 deletion packages/common-components/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@chainsafe/common-components",
"version": "1.0.31",
"version": "1.0.32",
"description": "Chainsafe Common React Components",
"author": "Chainsafe Products Team",
"license": "GPL-3.0",
Expand Down
5 changes: 3 additions & 2 deletions packages/files-ui/cypress/fixtures/filesTestData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ export const sharingExplainerKey = "csf.dismissedSharingExplainer"
export const sharedFolderName = "Share"
export const sharedFolderEditedName = "Edited"
export const validEthAddress = "0x2eab9cfa0b5e8e82a73da026254d50567f52d3ce"
export const validUsername = "filesUserB"
export const validShareKey = "0x03b53864fc991432dd2a729ee1f876e79d20788efcbe978a4a00db3f9fb24590db"
export const validUsernameA = "filesusera"
export const validUsernameB = "filesuserb"
export const validShareKey = "0x02c62b63ef1bd5ead99deb91a74bc7db4bc60d64a6d65a68461f3cf03d8c75da40"
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ export const editSharedFolderModal = {
folderNameInput: () => cy.get("[data-cy=input-shared-folder-name]"),
updateButton: () => cy.get("[data-cy=button-update-shared-folder]", { timeout: 10000 }),
userLookupResult: () => cy.get("[data-cy=user-lookup-result]", { timeout: 10000 }),
addedUserBox: () => cy.get("[data-cy=container-added-user]"),
addedUserIcon: () => cy.get("[data-cy=container-user-icon]"),
addedUserName: () => cy.get("[data-cy=label-added-user]"),
userPermissionDropDown: () => cy.get("[data-testid=dropdown-title-user-permission]"),
userViewOnlyDropdownOption: () => cy.get("[data-testid=dropdown-user-permission-read]"),
userCanEditDropdownOption: () => cy.get("[data-testid=dropdown-user-permission-write]"),
removeUserButton: () => cy.get("[data-testid=button-remove-user-from-share]"),
// link sharing related elements
shareLink: () => cy.get("[data-cy=link-share]"),
activeShareLink: () => cy.get("[data-cy=link-active-share]"),
Expand All @@ -14,7 +21,7 @@ export const editSharedFolderModal = {
linkKebabMenu: () => cy.get("[data-testid=icon-link-kebab]"),
deleteLinkMenuOption: () => cy.get("[data-cy=menu-delete-active-link]"),
linkPermissionDropdown: () => cy.get("[data-testid=dropdown-title-link-permission]"),
viewOnlyDropdownOption: () => cy.get("[data-testid=dropdown-link-permission-read]"),
canEditDropdownOption: () => cy.get("[data-testid=dropdown-link-permission-write]"),
linkViewOnlyDropdownOption: () => cy.get("[data-testid=dropdown-link-permission-read]"),
linkCanEditDropdownOption: () => cy.get("[data-testid=dropdown-link-permission-write]"),
createLinkButton: () => cy.get("[data-cy=button-create-link]")
}
6 changes: 5 additions & 1 deletion packages/files-ui/cypress/support/page-objects/sharedPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ export const sharedPage = {
...fileBrowser,

createSharedFolderButton: () => cy.get("[data-cy=button-create-a-shared-folder]"),
sharedFolderItemName: () => cy.get("[data-cy=cell-shared-folder-item-name]"),
sharedFolderItemRow: () => cy.get("[data-cy=row-shared-folder-item]", { timeout: 20000 }),
sharedFolderIcon: () => cy.get("[data-cy=cell-shared-folder-icon]"),
sharedFolderItemName: () => cy.get("[data-cy=cell-shared-folder-item-name]"),
shareOwnerCell: () => cy.get("[data-cy=cell-share-owner]"),
sharedWithCell: () => cy.get("[data-cy=cell-shared-with]"),
sharedFolderSizeCell: () => cy.get("[data-cy=cell-shared-folder-size]"),
shareRenameInput: () => cy.get("[data-cy=input-rename-share]"),

// kebab menu elements
Expand Down
103 changes: 92 additions & 11 deletions packages/files-ui/cypress/tests/file-sharing-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { createSharedFolderModal } from "../support/page-objects/modals/createSh
import { deleteSharedFolderModal } from "../support/page-objects/modals/deleteSharedFolderModal"
import { fileUploadModal } from "../support/page-objects/modals/fileUploadModal"
import { navigationMenu } from "../support/page-objects/navigationMenu"
import { sharingExplainerKey, sharedFolderName, sharedFolderEditedName, validUsername } from "../fixtures/filesTestData"
import { sharedFolderName, sharedFolderEditedName } from "../fixtures/filesTestData"
import { sharingExplainerKey, validUsernameA, validEthAddress, validShareKey } from "../fixtures/filesTestData"
import { sharedPage } from "../support/page-objects/sharedPage"
import { uploadCompleteToast } from "../support/page-objects/toasts/uploadCompleteToast"
import { viewOnlyShareLink } from "../fixtures/linkData"
Expand All @@ -12,14 +13,16 @@ import { editSharedFolderModal } from "../support/page-objects/modals/editShared

describe("File Sharing", () => {

beforeEach(() => {
// intercept and stub the response to ensure the explainer is not displayed
cy.intercept("GET", "**/user/store", {
body: { [sharingExplainerKey]: "true" }
})
})

context("desktop", () => {

it("can create, add, delete a shared folder", () => {
// intercept and stub the response to ensure the explainer is not displayed
cy.intercept("GET", "**/user/store", {
body: { [sharingExplainerKey]: "true" }
})

cy.web3Login({ deleteShareBucket: true })

// create a shared folder
Expand All @@ -28,12 +31,21 @@ describe("File Sharing", () => {
createSharedFolderModal.body().should("be.visible")
createSharedFolderModal.folderNameInput().type(sharedFolderName)
createSharedFolderModal.createButton().safeClick()
editSharedFolderModal.editPermissionInput().type(validUsername)
editSharedFolderModal.editPermissionInput().type(validUsernameA)
editSharedFolderModal.userLookupResult().should("exist").click()
editSharedFolderModal.updateButton().safeClick()
editSharedFolderModal.body().should("not.exist")
sharedPage.sharedFolderItemRow().should("have.length", 1)

// ensure share row contains all expected elements
sharedPage.sharedFolderItemRow().within(() => {
sharedPage.sharedFolderIcon().should("be.visible")
sharedPage.sharedFolderItemName().should("be.visible")
sharedPage.shareOwnerCell().should("be.visible")
sharedPage.sharedWithCell().should("be.visible")
sharedPage.sharedFolderSizeCell().should("be.visible")
})

// upload to a shared folder
sharedPage.sharedFolderItemName().contains(sharedFolderName)
.should("be.visible")
Expand Down Expand Up @@ -67,10 +79,6 @@ describe("File Sharing", () => {
})

it("can leave a shared folder", () => {
cy.intercept("GET", "**/user/store", {
body: { [sharingExplainerKey]: "true" }
})

cy.web3Login({ deleteShareBucket: true })
cy.visit(viewOnlyShareLink)
linkSharingConfirmation.viewAccessConfirmationLabel().should("be.visible")
Expand All @@ -85,5 +93,78 @@ describe("File Sharing", () => {
// ensure the shared folder is no longer shown on the main share page
sharedPage.sharedFolderItemRow().should("have.length", 0)
})

it("can add and remove users to the share modal", () => {
cy.web3Login({ deleteShareBucket: true })

// create a shared folder
navigationMenu.sharedNavButton().click()
sharedPage.createSharedFolderButton().click()
createSharedFolderModal.body().should("be.visible")
createSharedFolderModal.folderNameInput().type(sharedFolderName)
createSharedFolderModal.createButton().safeClick()

// add to share via a username
editSharedFolderModal.editPermissionInput().type(validUsernameA)
editSharedFolderModal.userLookupResult().should("exist").click()
editSharedFolderModal.addedUserBox().should("have.length", 1)

// ensure user wrapper contains all expected elements
editSharedFolderModal.addedUserBox().within(() => {
editSharedFolderModal.addedUserIcon().should("have.length", 1)
editSharedFolderModal.addedUserName().should("have.length", 1)
editSharedFolderModal.userPermissionDropDown().should("have.length", 1)
})

// add to share via an ethereum address
editSharedFolderModal.editPermissionInput().type(validEthAddress)
editSharedFolderModal.userLookupResult().should("exist").click()
editSharedFolderModal.addedUserBox().should("have.length", 2)

// add to share via a sharekey
editSharedFolderModal.editPermissionInput().type(validShareKey)
editSharedFolderModal.userLookupResult().should("exist").click()
editSharedFolderModal.addedUserBox().should("have.length", 3)

// remove added users
editSharedFolderModal.removeUserButton().first().click()
editSharedFolderModal.addedUserBox().should("have.length", 2)
editSharedFolderModal.removeUserButton().first().click()
editSharedFolderModal.addedUserBox().should("have.length", 1)
editSharedFolderModal.removeUserButton().first().click()
editSharedFolderModal.addedUserBox().should("not.exist")
})

it("can update user permissions and save changes", () => {
cy.web3Login({ deleteShareBucket: true })

// create a shared folder
navigationMenu.sharedNavButton().click()
sharedPage.createSharedFolderButton().click()
createSharedFolderModal.body().should("be.visible")
createSharedFolderModal.folderNameInput().type(sharedFolderName)
createSharedFolderModal.createButton().safeClick()

// add a user to share
editSharedFolderModal.editPermissionInput().type(validUsernameA)
editSharedFolderModal.userLookupResult().should("exist").click()
editSharedFolderModal.addedUserBox().should("have.length", 1)

// ensure default access should be "view-only"
editSharedFolderModal.userPermissionDropDown().should("contain.text", "view")

// change access to "can-edit" and save changes
editSharedFolderModal.userPermissionDropDown().click()
editSharedFolderModal.userCanEditDropdownOption().click()
editSharedFolderModal.updateButton().safeClick()

// re-open and ensure changes were saved
sharedPage.fileItemKebabButton()
.should("be.visible")
.click()
sharedPage.manageAccessMenuOption().click()
editSharedFolderModal.body().should("be.visible")
editSharedFolderModal.userPermissionDropDown().should("contain.text", "edit")
})
})
})
12 changes: 6 additions & 6 deletions packages/files-ui/cypress/tests/link-sharing-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,29 +38,29 @@ describe("Link Sharing", () => {

// ensure "view-only" and "can-edit" options are present
editSharedFolderModal.linkPermissionDropdown().click()
editSharedFolderModal.viewOnlyDropdownOption()
editSharedFolderModal.linkViewOnlyDropdownOption()
.scrollIntoView()
.should("be.visible")
editSharedFolderModal.canEditDropdownOption()
editSharedFolderModal.linkCanEditDropdownOption()
.scrollIntoView()
.should("be.visible")

// create a "view-only" link
editSharedFolderModal.viewOnlyDropdownOption().click()
editSharedFolderModal.linkViewOnlyDropdownOption().click()
editSharedFolderModal.createLinkButton().click()
editSharedFolderModal.activeShareLink().should("have.length", 1)
editSharedFolderModal.labelPermissionType().should("have.length", 1)
editSharedFolderModal.copyLinkButton().should("have.length", 1)

// ensure only the can-edit option is present if a "view-only" link exists
editSharedFolderModal.linkPermissionDropdown().click()
editSharedFolderModal.viewOnlyDropdownOption().should("not.exist")
editSharedFolderModal.canEditDropdownOption()
editSharedFolderModal.linkViewOnlyDropdownOption().should("not.exist")
editSharedFolderModal.linkCanEditDropdownOption()
.scrollIntoView()
.should("be.visible")

// create a "can-edit" link
editSharedFolderModal.canEditDropdownOption().click()
editSharedFolderModal.linkCanEditDropdownOption().click()
editSharedFolderModal.createLinkButton().click()
editSharedFolderModal.activeShareLink().should("have.length", 2)
editSharedFolderModal.labelPermissionType().should("have.length", 2)
Expand Down
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 @@
"@types/yup": "^0.29.9",
"@types/zxcvbn": "^4.4.0",
"babel-plugin-macros": "^2.8.0",
"cypress": "^9.1.0",
"cypress": "^9.5.2",
"cypress-file-upload": "^5.0.8",
"cypress-pipe": "^2.0.0"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ const ManageSharedFolder = ({ onClose, bucketToEdit }: ICreateOrManageSharedFold
resetUsers
} = useLookupSharedFolderUser()
const [hasPermissionsChanged, setHasPermissionsChanged] = useState(false)
const [newLinkPermission, setNewLinkPermission] = useState<NonceResponsePermission>("read")
const [newUserPermission, setNewUserPermission] = useState<NonceResponsePermission>("read")
const [usernameSearch, setUsernameSearch] = useState<string | undefined>()
const [suggestedUsers, setSuggestedUsers] = useState<LookupUser[]>([])
const [loadingUsers, setLoadingUsers] = useState(false)
Expand Down Expand Up @@ -248,6 +248,14 @@ const ManageSharedFolder = ({ onClose, bucketToEdit }: ICreateOrManageSharedFold
}
})

const onSuggestedUserClick = useCallback((user: LookupUser) => {
onAddNewUser(user, newUserPermission)
setSearchActive(false)
setUsernameSearch("")
setSuggestedUsers([])
setHasPermissionsChanged(true)
}, [newUserPermission, onAddNewUser])

return (
<div className={classes.root}>
<div className={classes.iconBacking}>
Expand All @@ -274,9 +282,9 @@ const ManageSharedFolder = ({ onClose, bucketToEdit }: ICreateOrManageSharedFold
data-cy="input-edit-permission"
/>
<PermissionsDropdown
selectedPermission={newLinkPermission}
onViewPermissionClick={() => setNewLinkPermission("read")}
onEditPermissionClick={() => setNewLinkPermission("write")}
selectedPermission={newUserPermission}
onViewPermissionClick={() => setNewUserPermission("read")}
onEditPermissionClick={() => setNewUserPermission("write")}
permissions={["read", "write"]}
injectedClasses={{
root: classes.permissionsInSuggestion,
Expand All @@ -292,13 +300,7 @@ const ManageSharedFolder = ({ onClose, bucketToEdit }: ICreateOrManageSharedFold
{suggestedUsers.map((u) => <div
key={u.uuid}
className={classes.usernameBox}
onClick={() => {
onAddNewUser(u, newLinkPermission)
setSearchActive(false)
setUsernameSearch("")
setSuggestedUsers([])
setHasPermissionsChanged(true)
}}
onClick={() => {onSuggestedUserClick(u)}}
data-cy="user-lookup-result"
>
<UserName user={u}/>
Expand All @@ -313,7 +315,7 @@ const ManageSharedFolder = ({ onClose, bucketToEdit }: ICreateOrManageSharedFold
>
{loadingUsers
? <Trans>Loading...</Trans>
: <Trans>No users found</Trans>
: <Trans>No user found</Trans>
}
</Typography>
</div>
Expand All @@ -328,9 +330,13 @@ const ManageSharedFolder = ({ onClose, bucketToEdit }: ICreateOrManageSharedFold
].map((sharedFolderUser) => <div
key={sharedFolderUser.user.uuid}
className={classes.addedUserBox}
data-cy="container-added-user"
>
<div className={classes.flexContainer}>
<div className={classes.hashIcon}>
<div
className={classes.hashIcon}
data-cy="container-user-icon"
>
<Hashicon
value={sharedFolderUser.user.uuid}
size={28}
Expand All @@ -339,12 +345,14 @@ const ManageSharedFolder = ({ onClose, bucketToEdit }: ICreateOrManageSharedFold
<Typography
className={classes.addedUserLabel}
component="p"
data-cy="label-added-user"
>
<UserName user={sharedFolderUser.user}/>
</Typography>
</div>
<div className={classes.flexContainer}>
<PermissionsDropdown
testId="user-permission"
selectedPermission={sharedFolderUser.permission}
onViewPermissionClick={() => {
if (sharedFolderUser.permission === "write") {
Expand All @@ -370,6 +378,7 @@ const ManageSharedFolder = ({ onClose, bucketToEdit }: ICreateOrManageSharedFold
<Button
variant="link"
className={classes.crossButton}
testId="remove-user-from-share"
onClick={() => {
setHasPermissionsChanged(true)
if (sharedFolderUser.permission === "read") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { NonceResponse, NonceResponsePermission } from "@chainsafe/files-api-cli
import { Trans } from "@lingui/macro"
import React, { useCallback, useEffect, useMemo, useState } from "react"
import { useFilesApi } from "../../../../Contexts/FilesApiContext"
import { usePosthogContext } from "../../../../Contexts/PosthogContext"
import { CSFTheme } from "../../../../Themes/types"
import PermissionsDropdown from "./PermissionsDropdown"
import SharingLink from "./SharingLink"
Expand Down Expand Up @@ -121,6 +122,7 @@ const LinkList = ({ bucketId, bucketEncryptionKey }: Props) => {
const [isLoadingCreation, setIsLoadingCreation] = useState(false)
const hasAReadNonce = useMemo(() => !!nonces.find(n => n.permission === "read"), [nonces])
const [newLinkPermission, setNewLinkPermission] = useState<NonceResponsePermission | undefined>(undefined)
const { captureEvent } = usePosthogContext()

useEffect(() => {
if (hasAReadNonce) {
Expand Down Expand Up @@ -152,6 +154,7 @@ const LinkList = ({ bucketId, bucketEncryptionKey }: Props) => {
return
}

captureEvent("Create sharing link", { permission: newLinkPermission })
setIsLoadingCreation(true)

return filesApiClient
Expand All @@ -161,7 +164,7 @@ const LinkList = ({ bucketId, bucketEncryptionKey }: Props) => {
setIsLoadingCreation(false)
refreshNonces()
})
}, [bucketId, filesApiClient, newLinkPermission, refreshNonces])
}, [bucketId, captureEvent, filesApiClient, newLinkPermission, refreshNonces])

return (
<div className={classes.root}>
Expand Down
Loading

0 comments on commit c4e0b7a

Please sign in to comment.