From 65da4b1d685fc389dadd7035b7b54df9b079c982 Mon Sep 17 00:00:00 2001 From: Viktor Scharf Date: Thu, 4 Aug 2022 11:43:58 +0200 Subject: [PATCH] add re-share tests (#7378) --- .../integrations/reshare.ocis.feature | 54 ++++++++ tests/e2e/cucumber/steps/api.ts | 35 +++++ tests/e2e/cucumber/steps/app-files/share.ts | 28 ++++ tests/e2e/support/api/graph/index.ts | 9 +- tests/e2e/support/api/graph/user.ts | 42 ------ tests/e2e/support/api/graph/userManagement.ts | 131 ++++++++++++++++++ tests/e2e/support/api/index.ts | 2 +- .../api/{user.ts => userManagement.ts} | 58 +++++++- tests/e2e/support/environment/index.ts | 2 +- tests/e2e/support/environment/user.ts | 26 ---- .../e2e/support/environment/userManagement.ts | 48 +++++++ .../objects/app-files/share/actions.ts | 22 +++ .../support/objects/app-files/share/index.ts | 8 ++ .../objects/app-files/utils/sidebar.ts | 4 +- tests/e2e/support/store/group.ts | 25 ++++ tests/e2e/support/store/index.ts | 1 + tests/e2e/support/types.ts | 5 + 17 files changed, 426 insertions(+), 74 deletions(-) create mode 100644 tests/e2e/cucumber/features/integrations/reshare.ocis.feature delete mode 100644 tests/e2e/support/api/graph/user.ts create mode 100644 tests/e2e/support/api/graph/userManagement.ts rename tests/e2e/support/api/{user.ts => userManagement.ts} (63%) delete mode 100644 tests/e2e/support/environment/user.ts create mode 100644 tests/e2e/support/environment/userManagement.ts create mode 100644 tests/e2e/support/store/group.ts diff --git a/tests/e2e/cucumber/features/integrations/reshare.ocis.feature b/tests/e2e/cucumber/features/integrations/reshare.ocis.feature new file mode 100644 index 00000000000..fda28ed5572 --- /dev/null +++ b/tests/e2e/cucumber/features/integrations/reshare.ocis.feature @@ -0,0 +1,54 @@ +Feature: reshare + + Background: + Given "Admin" disables share auto accepting + + Scenario: re-sharing + Given "Admin" creates following users + | id | + | Alice | + | Brian | + | Carol | + And "Admin" creates following group + | id | + | sales | + | finance | + And "Admin" adds user to the group + | user | group | + | Carol | sales | + + And "Alice" logs in + And "Alice" opens the "files" app + And "Alice" navigates to the personal space page + And "Alice" creates the following resources + | resource | type | + | folder_to_shared | folder | + When "Alice" shares the following resource using the sidebar panel + | resource | user | role | + | folder_to_shared | Brian | editor | + And "Alice" logs out + + And "Brian" logs in + And "Brian" opens the "files" app + And "Brian" navigates to the shared with me page + And "Brian" accepts the following share + | name | + | folder_to_shared | + And "Brian" reshares the following resource + | resource | user | role | + | folder_to_shared | Carol | viewer | + And "Brian" logs out + + And "Carol" logs in + And "Carol" opens the "files" app + And "Carol" navigates to the shared with me page + And "Carol" accepts the following share + | name | + | folder_to_shared | + And "Carol" reshares the following resource + | resource | user | role | + | folder_to_shared | Alice | viewer | + And "Carol" logs out + + + diff --git a/tests/e2e/cucumber/steps/api.ts b/tests/e2e/cucumber/steps/api.ts index d48a4db3130..7f47e6f679b 100644 --- a/tests/e2e/cucumber/steps/api.ts +++ b/tests/e2e/cucumber/steps/api.ts @@ -65,3 +65,38 @@ Given( }) } ) + +Given( + '{string} creates following group(s)', + async function (this: World, stepUser: string, stepTable: DataTable): Promise { + const admin = this.usersEnvironment.getUser({ key: stepUser }) + + for (const info of stepTable.hashes()) { + const group = this.usersEnvironment.getGroup({ key: info.id }) + if (config.ocis) { + await api.graph.deleteGroup({ group, admin }) + await api.graph.createGroup({ group, admin }) + } else { + await api.user.deleteGroup({ group, admin }) + await api.user.createGroup({ group, admin }) + } + } + } +) + +Given( + '{string} adds user(s) to the group(s)', + async function (this: World, stepUser: string, stepTable: DataTable): Promise { + const admin = this.usersEnvironment.getUser({ key: stepUser }) + + for (const info of stepTable.hashes()) { + const group = this.usersEnvironment.getGroup({ key: info.group }) + const user = this.usersEnvironment.getUser({ key: info.user }) + if (config.ocis) { + await api.graph.addUserToGroup({ user, group, admin }) + } else { + await api.user.addUserToGroup({ user, group, admin }) + } + } + } +) diff --git a/tests/e2e/cucumber/steps/app-files/share.ts b/tests/e2e/cucumber/steps/app-files/share.ts index 3cee20a4b50..cceee4b4c64 100644 --- a/tests/e2e/cucumber/steps/app-files/share.ts +++ b/tests/e2e/cucumber/steps/app-files/share.ts @@ -37,6 +37,34 @@ When( } ) +When( + /^"([^"]*)" reshares the following (resource|resources)$/, + async function (this: World, stepUser: string, _: string, stepTable: DataTable) { + const { page } = this.actorsEnvironment.getActor({ key: stepUser }) + const shareObject = new objects.applicationFiles.Share({ page }) + const shareInfo = stepTable.hashes().reduce((acc, stepRow) => { + const { user, resource, role } = stepRow + + if (!acc[resource]) { + acc[resource] = { users: [], role: '' } + } + + acc[resource].users.push(this.usersEnvironment.getUser({ key: user })) + acc[resource].role = role + + return acc + }, {}) + + for (const folder of Object.keys(shareInfo)) { + await shareObject.createReshare({ + folder, + users: shareInfo[folder].users, + role: shareInfo[folder].role + }) + } + } +) + When( '{string} accepts the following share(s)', async function (this: World, stepUser: string, stepTable: DataTable) { diff --git a/tests/e2e/support/api/graph/index.ts b/tests/e2e/support/api/graph/index.ts index 3a8ddaaea93..17ba3fccd68 100644 --- a/tests/e2e/support/api/graph/index.ts +++ b/tests/e2e/support/api/graph/index.ts @@ -1 +1,8 @@ -export { me, createUser, deleteUser } from './user' +export { + me, + createUser, + deleteUser, + createGroup, + deleteGroup, + addUserToGroup +} from './userManagement' diff --git a/tests/e2e/support/api/graph/user.ts b/tests/e2e/support/api/graph/user.ts deleted file mode 100644 index 500023588cf..00000000000 --- a/tests/e2e/support/api/graph/user.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { checkResponseStatus, request } from '../http' -import { Me, User } from '../../types' -import join from 'join-path' - -export const me = async ({ user }: { user: User }): Promise => { - const response = await request({ - method: 'GET', - path: join('graph', 'v1.0', 'me'), - user - }) - - return await response.json() -} - -export const createUser = async ({ user, admin }: { user: User; admin: User }): Promise => { - const body = JSON.stringify({ - displayName: user.displayName, - mail: user.email, - onPremisesSamAccountName: user.id, - passwordProfile: { password: user.password } - }) - - const response = await request({ - method: 'POST', - path: join('graph', 'v1.0', 'users'), - body, - user: admin - }) - - checkResponseStatus(response, 'Failed while creating user') - return user -} - -export const deleteUser = async ({ user, admin }: { user: User; admin: User }): Promise => { - await request({ - method: 'DELETE', - path: join('graph', 'v1.0', 'users', user.id), - user: admin - }) - - return user -} diff --git a/tests/e2e/support/api/graph/userManagement.ts b/tests/e2e/support/api/graph/userManagement.ts new file mode 100644 index 00000000000..69a1521693b --- /dev/null +++ b/tests/e2e/support/api/graph/userManagement.ts @@ -0,0 +1,131 @@ +import { checkResponseStatus, request } from '../http' +import { Group, Me, User } from '../../types' +import join from 'join-path' +import { config } from '../../../config' + +export const me = async ({ user }: { user: User }): Promise => { + const response = await request({ + method: 'GET', + path: join('graph', 'v1.0', 'me'), + user + }) + + return await response.json() +} + +export const createUser = async ({ user, admin }: { user: User; admin: User }): Promise => { + const body = JSON.stringify({ + displayName: user.displayName, + mail: user.email, + onPremisesSamAccountName: user.id, + passwordProfile: { password: user.password } + }) + + const response = await request({ + method: 'POST', + path: join('graph', 'v1.0', 'users'), + body, + user: admin + }) + + checkResponseStatus(response, 'Failed while creating user') + return user +} + +export const deleteUser = async ({ user, admin }: { user: User; admin: User }): Promise => { + await request({ + method: 'DELETE', + path: join('graph', 'v1.0', 'users', user.id), + user: admin + }) + + return user +} + +const getUserId = async ({ user, admin }: { user: User; admin: User }): Promise => { + let userId = '' + const response = await request({ + method: 'GET', + path: join('graph', 'v1.0', 'users', user.id), + user: admin + }) + if (response.ok) { + userId = (await response.json()).id + } + return userId +} + +export const createGroup = async ({ + group, + admin +}: { + group: Group + admin: User +}): Promise => { + const body = JSON.stringify({ + displayName: group.displayName + }) + + const response = await request({ + method: 'POST', + path: join('graph', 'v1.0', 'groups'), + body, + user: admin + }) + + checkResponseStatus(response, 'Failed while creating group') + return group +} + +const getGroupId = async ({ group, admin }: { group: Group; admin: User }): Promise => { + let groupId = '' + const response = await request({ + method: 'GET', + path: join('graph', 'v1.0', 'groups', group.displayName), + user: admin + }) + if (response.ok) { + groupId = (await response.json()).id + } + return groupId +} + +export const deleteGroup = async ({ + group, + admin +}: { + group: Group + admin: User +}): Promise => { + const groupId = await getGroupId({ group, admin }) + await request({ + method: 'DELETE', + path: join('graph', 'v1.0', 'groups', groupId), + user: admin + }) + return group +} + +export const addUserToGroup = async ({ + user, + group, + admin +}: { + user: User + group: Group + admin: User +}): Promise => { + const groupId = await getGroupId({ group, admin }) + const userId = await getUserId({ user, admin }) + const body = JSON.stringify({ + '@odata.id': join(config.backendUrl, 'graph', 'v1.0', 'users', userId) + }) + + const response = await request({ + method: 'POST', + path: join('graph', 'v1.0', 'groups', groupId, 'members', '$ref'), + body: body, + user: admin + }) + checkResponseStatus(response, 'Failed while adding an user to the group') +} diff --git a/tests/e2e/support/api/index.ts b/tests/e2e/support/api/index.ts index 98b321c6e20..120555af468 100644 --- a/tests/e2e/support/api/index.ts +++ b/tests/e2e/support/api/index.ts @@ -1,5 +1,5 @@ export * as http from './http' -export * as user from './user' +export * as user from './userManagement' export * as config from './config' export * as settings from './settings' export * as graph from './graph' diff --git a/tests/e2e/support/api/user.ts b/tests/e2e/support/api/userManagement.ts similarity index 63% rename from tests/e2e/support/api/user.ts rename to tests/e2e/support/api/userManagement.ts index 92c3ba88c99..6b919c9c06a 100644 --- a/tests/e2e/support/api/user.ts +++ b/tests/e2e/support/api/userManagement.ts @@ -1,5 +1,5 @@ import { checkResponseStatus, checkOCJsonStatus, request } from './http' -import { User } from '../types' +import { Group, User } from '../types' import { URLSearchParams } from 'url' import join from 'join-path' @@ -68,3 +68,59 @@ export const getUser = async ({ user }: { user: User }): Promise => { return user } + +export const createGroup = async ({ + group, + admin +}: { + group: Group + admin: User +}): Promise => { + const body = new URLSearchParams() + body.append('groupid', group.id) + const response = await request({ + method: 'POST', + path: join('ocs', 'v2.php', 'cloud', 'groups'), + body: body, + user: admin + }) + checkResponseStatus(response, 'Failed while creating group') + return group +} + +export const deleteGroup = async ({ + group, + admin +}: { + group: Group + admin: User +}): Promise => { + await request({ + method: 'DELETE', + path: join('ocs', 'v2.php', 'cloud', 'groups', encodeURIComponent(group.id)), + user: admin + }) + + return group +} + +export const addUserToGroup = async ({ + user, + group, + admin +}: { + user: User + group: Group + admin: User +}): Promise => { + const body = new URLSearchParams() + body.append('groupid', group.id) + const response = await request({ + method: 'POST', + path: join('ocs', 'v2.php', 'cloud', 'users', user.id, 'groups'), + body: body, + user: admin + }) + checkResponseStatus(response, 'Failed while adding an user to the group') + return group +} diff --git a/tests/e2e/support/environment/index.ts b/tests/e2e/support/environment/index.ts index 0c67f494591..eaa48f5a0bc 100644 --- a/tests/e2e/support/environment/index.ts +++ b/tests/e2e/support/environment/index.ts @@ -2,4 +2,4 @@ export { ActorsEnvironment } from './actor' export { FilesEnvironment } from './file' export { LinksEnvironment } from './link' export { SpacesEnvironment } from './space' -export { UsersEnvironment } from './user' +export { UsersEnvironment } from './userManagement' diff --git a/tests/e2e/support/environment/user.ts b/tests/e2e/support/environment/user.ts deleted file mode 100644 index cc483a1e63f..00000000000 --- a/tests/e2e/support/environment/user.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { User } from '../types' -import { userStore } from '../store' - -export class UsersEnvironment { - getUser({ key }: { key: string }): User { - const uniqueKey = key.toLowerCase() - - if (!userStore.has(uniqueKey)) { - throw new Error(`user with key '${uniqueKey}' not found`) - } - - return userStore.get(uniqueKey) - } - - createUser({ key, user }: { key: string; user: User }): User { - const uniqueKey = key.toLowerCase() - - if (userStore.has(uniqueKey)) { - throw new Error(`user with key '${uniqueKey}' already exists`) - } - - userStore.set(uniqueKey, user) - - return user - } -} diff --git a/tests/e2e/support/environment/userManagement.ts b/tests/e2e/support/environment/userManagement.ts new file mode 100644 index 00000000000..698721b1173 --- /dev/null +++ b/tests/e2e/support/environment/userManagement.ts @@ -0,0 +1,48 @@ +import { Group, User } from '../types' +import { userStore, groupStore } from '../store' + +export class UsersEnvironment { + getUser({ key }: { key: string }): User { + const uniqueKey = key.toLowerCase() + + if (!userStore.has(uniqueKey)) { + throw new Error(`user with key '${uniqueKey}' not found`) + } + + return userStore.get(uniqueKey) + } + + createUser({ key, user }: { key: string; user: User }): User { + const uniqueKey = key.toLowerCase() + + if (userStore.has(uniqueKey)) { + throw new Error(`user with key '${uniqueKey}' already exists`) + } + + userStore.set(uniqueKey, user) + + return user + } + + getGroup({ key }: { key: string }): Group { + const uniqueKey = key.toLowerCase() + + if (!groupStore.has(uniqueKey)) { + throw new Error(`group with key '${uniqueKey}' not found`) + } + + return groupStore.get(uniqueKey) + } + + createGroup({ key, group }: { key: string; group: Group }): Group { + const uniqueKey = key.toLowerCase() + + if (userStore.has(uniqueKey)) { + throw new Error(`group with key '${uniqueKey}' already exists`) + } + + groupStore.set(uniqueKey, group) + + return group + } +} diff --git a/tests/e2e/support/objects/app-files/share/actions.ts b/tests/e2e/support/objects/app-files/share/actions.ts index 2d165c80d09..997ff82a0d1 100644 --- a/tests/e2e/support/objects/app-files/share/actions.ts +++ b/tests/e2e/support/objects/app-files/share/actions.ts @@ -50,6 +50,28 @@ export const createShare = async (args: createShareArgs): Promise => { await sidebar.close({ page: page }) } +export interface createReshareArgs { + page: Page + folder: string + users: User[] + role: string +} + +export const createReshare = async (args: createReshareArgs): Promise => { + const { page, folder, users, role } = args + const folderPaths = folder.split('/') + const folderName = folderPaths.pop() + + if (folderPaths.length) { + await clickResource({ page: page, path: folderPaths.join('/') }) + } + await sidebar.open({ page: page, resource: folderName }) + await sidebar.openPanel({ page: page, name: 'sharing' }) + + await inviteMembers({ page, users, role }) + await sidebar.close({ page: page }) +} + export interface inviteMembersArgs { page: Page users: User[] diff --git a/tests/e2e/support/objects/app-files/share/index.ts b/tests/e2e/support/objects/app-files/share/index.ts index a0f012c5be1..3566ef8be3e 100644 --- a/tests/e2e/support/objects/app-files/share/index.ts +++ b/tests/e2e/support/objects/app-files/share/index.ts @@ -2,6 +2,8 @@ import { Page } from 'playwright' import { createShare, createShareArgs, + createReshare, + createReshareArgs, acceptShare, changeShareeRole, changeShareeRoleArgs, @@ -27,6 +29,12 @@ export class Share { await this.#page.locator('body').click() } + async createReshare(args: Omit): Promise { + const startUrl = this.#page.url() + await createReshare({ ...args, page: this.#page }) + await this.#page.goto(startUrl) + } + async accept(args: Omit): Promise { await acceptShare({ ...args, page: this.#page }) } diff --git a/tests/e2e/support/objects/app-files/utils/sidebar.ts b/tests/e2e/support/objects/app-files/utils/sidebar.ts index 9e717c6c8a8..fe6b33163b8 100644 --- a/tests/e2e/support/objects/app-files/utils/sidebar.ts +++ b/tests/e2e/support/objects/app-files/utils/sidebar.ts @@ -46,9 +46,9 @@ export const openPanel = async ({ page, name }: { page: Page; name: string }): P await backButton.click() await locatorUtils.waitForEvent(currentPanel, 'transitionend') } - const panelSelector = page.locator(`#sidebar-panel-${name}-item-select`) const nextPanel = page.locator(`#sidebar-panel-${name}-item`) - await Promise.all([locatorUtils.waitForEvent(nextPanel, 'transitionend'), panelSelector.click()]) + await panelSelector.click() + await locatorUtils.waitForEvent(nextPanel, 'transitionend') } diff --git a/tests/e2e/support/store/group.ts b/tests/e2e/support/store/group.ts new file mode 100644 index 00000000000..7d9173257bf --- /dev/null +++ b/tests/e2e/support/store/group.ts @@ -0,0 +1,25 @@ +import { Group } from '../types' + +export const groupStore = new Map([ + [ + 'security', + { + id: 'security', + displayName: 'security department' + } + ], + [ + 'sales', + { + id: 'sales', + displayName: 'sales department' + } + ], + [ + 'finance', + { + id: 'finance', + displayName: 'finance department' + } + ] +]) diff --git a/tests/e2e/support/store/index.ts b/tests/e2e/support/store/index.ts index fdd523fe952..d7065d4b8e3 100644 --- a/tests/e2e/support/store/index.ts +++ b/tests/e2e/support/store/index.ts @@ -2,3 +2,4 @@ export { actorStore } from './actor' export { linkStore } from './link' export { spaceStore } from './space' export { userStore } from './user' +export { groupStore } from './group' diff --git a/tests/e2e/support/types.ts b/tests/e2e/support/types.ts index 773aeb73b93..9c314099f60 100644 --- a/tests/e2e/support/types.ts +++ b/tests/e2e/support/types.ts @@ -32,3 +32,8 @@ export interface File { export interface Me { id: string } + +export interface Group { + id: string + displayName: string +}