Skip to content

Commit b9f020a

Browse files
committed
test: convert groups.feature test to playwright
1 parent 4a3cf4d commit b9f020a

11 files changed

Lines changed: 433 additions & 77 deletions

File tree

.drone.star

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,6 @@ config = {
146146
"cucumber/features/admin-settings/users.feature:131",
147147
"cucumber/features/admin-settings/users.feature:185",
148148
"cucumber/features/admin-settings/spaces.feature",
149-
"cucumber/features/keycloak",
150149
],
151150
"extraServerEnvironment": {
152151
"PROXY_AUTOPROVISION_ACCOUNTS": "true",
@@ -212,6 +211,27 @@ config = {
212211
"IDP_ACCESS_TOKEN_EXPIRATION": 30,
213212
},
214213
},
214+
"keycloak": {
215+
"earlyFail": True,
216+
"skip": False,
217+
"suites": [
218+
"keycloak",
219+
],
220+
"extraServerEnvironment": {
221+
"PROXY_AUTOPROVISION_ACCOUNTS": "true",
222+
"PROXY_ROLE_ASSIGNMENT_DRIVER": "oidc",
223+
"OCIS_OIDC_ISSUER": "https://keycloak:8443/realms/oCIS",
224+
"PROXY_OIDC_REWRITE_WELLKNOWN": "true",
225+
"WEB_OIDC_CLIENT_ID": "web",
226+
"PROXY_USER_OIDC_CLAIM": "preferred_username",
227+
"PROXY_USER_CS3_CLAIM": "username",
228+
"OCIS_ADMIN_USER_ID": "",
229+
"OCIS_EXCLUDE_RUN_SERVICES": "idp",
230+
"GRAPH_ASSIGN_DEFAULT_USER_ROLE": "false",
231+
"GRAPH_USERNAME_MATCH": "none",
232+
"KEYCLOAK_DOMAIN": "keycloak:8443",
233+
},
234+
},
215235
},
216236
"build": True,
217237
}
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
import { test } from '@playwright/test'
2+
import { config } from '../../../e2e/config.js'
3+
import { ActorsEnvironment, UsersEnvironment } from '../../../e2e/support/environment/index.js'
4+
import { setAccessAndRefreshToken } from '../../helpers/setAccessAndRefreshToken.js'
5+
import * as api from '../../steps/api/api.js'
6+
import * as ui from '../../steps/ui/index'
7+
import { editor } from '../../../e2e/support/objects/app-files/utils/index.js'
8+
9+
test.describe('groups management', () => {
10+
let actorsEnvironment
11+
const usersEnvironment = new UsersEnvironment()
12+
13+
test.beforeEach(async ({ browser }) => {
14+
actorsEnvironment = new ActorsEnvironment({
15+
context: {
16+
acceptDownloads: config.acceptDownloads,
17+
reportDir: config.reportDir,
18+
tracingReportDir: config.tracingReportDir,
19+
reportHar: config.reportHar,
20+
reportTracing: config.reportTracing,
21+
reportVideo: config.reportVideo,
22+
failOnUncaughtConsoleError: config.failOnUncaughtConsoleError
23+
},
24+
browser: browser
25+
})
26+
27+
await setAccessAndRefreshToken(usersEnvironment)
28+
})
29+
30+
test.afterEach(async () => {})
31+
32+
test('keycloak group sync with oCIS', async () => {
33+
// Given "Admin" creates following user using API
34+
// | id |
35+
// | Alice |
36+
// | Brian |
37+
await api.userHasBeenCreated({ usersEnvironment, stepUser: 'Admin', userToBeCreated: 'Alice' })
38+
await api.userHasBeenCreated({ usersEnvironment, stepUser: 'Admin', userToBeCreated: 'Brian' })
39+
40+
// And "Alice" creates the following files into personal space using API
41+
// | pathToFile | content |
42+
// | shareToSales.txt | Keycloak group share |
43+
// | shareToSecurity.txt | Keycloak group share |
44+
await api.userHasCreatedFile({
45+
usersEnvironment,
46+
stepUser: 'Alice',
47+
filename: 'shareToSales.txt',
48+
content: 'Keycloak group share'
49+
})
50+
await api.userHasCreatedFile({
51+
usersEnvironment,
52+
stepUser: 'Alice',
53+
filename: 'shareToSecurity.txt',
54+
content: 'Keycloak group share'
55+
})
56+
// When "Admin" logs in
57+
await ui.logInUser({ usersEnvironment, actorsEnvironment, stepUser: 'Admin' })
58+
59+
// And "Admin" opens the "admin-settings" app
60+
await ui.userOpensApplication({ actorsEnvironment, stepUser: 'Admin', name: 'admin-settings' })
61+
62+
// And "Admin" navigates to the groups management page
63+
await ui.userNavigatesToGroupsManagementPage({ actorsEnvironment, stepUser: 'Admin' })
64+
65+
// When "Admin" creates the following groups
66+
// | id |
67+
// | security |
68+
// | sales |
69+
await ui.userCreatesGroup({ actorsEnvironment, stepUser: 'Admin', group: 'security' })
70+
await ui.userCreatesGroup({ actorsEnvironment, stepUser: 'Admin', group: 'sales' })
71+
72+
// Then "Admin" should see the following group
73+
// | group |
74+
// | security |
75+
// | keycloak sales |
76+
// | keycloak finance |
77+
expect(
78+
await ui.checkGroupsPresenceById({
79+
actorsEnvironment,
80+
stepUser: 'Admin',
81+
expectedGroupIds: ['sales']
82+
})
83+
).toBeTruthy()
84+
85+
// When "Admin" navigates to the users management page
86+
await ui.userNavigatesToUserManagementPage({ actorsEnvironment, stepUser: 'Admin' })
87+
// And "Admin" adds the user "Brian" to the groups "security,keycloak sales" using the sidebar panel
88+
await ui.userAddsUserToGroup({
89+
actorsEnvironment,
90+
stepUser: 'Admin',
91+
action: 'adds',
92+
groups: ['security', 'keycloak sales'],
93+
user: 'Brian'
94+
})
95+
96+
// And "Admin" logs out
97+
await ui.logOutUser({ actorsEnvironment, stepUser: 'Admin' })
98+
// And "Alice" logs in
99+
await ui.logInUser({ usersEnvironment, actorsEnvironment, stepUser: 'Alice' })
100+
101+
// And "Alice" shares the following resource using the sidebar panel
102+
// | resource | recipient | type | role | resourceType |
103+
// | shareToSales.txt | keycloak sales | group | Can edit without versions | file |
104+
// | shareToSecurity.txt | security | group | Can edit without versions | file |
105+
await ui.shareResource({
106+
actorsEnvironment,
107+
usersEnvironment,
108+
stepUser: 'Alice',
109+
actionType: 'SIDEBAR_PANEL',
110+
resource: 'shareToSales.txt',
111+
recipient: 'keycloak sales',
112+
type: 'group',
113+
role: 'Can edit without versions',
114+
resourceType: 'file'
115+
})
116+
117+
await ui.shareResource({
118+
actorsEnvironment,
119+
usersEnvironment,
120+
stepUser: 'Alice',
121+
actionType: 'SIDEBAR_PANEL',
122+
resource: 'shareToSales.txt',
123+
recipient: 'security',
124+
type: 'group',
125+
role: 'Can edit without versions',
126+
resourceType: 'file'
127+
})
128+
129+
// And "Alice" logs out
130+
await ui.logOutUser({ actorsEnvironment, stepUser: 'Alice' })
131+
132+
// And "Brian" logs in
133+
await ui.logInUser({ usersEnvironment, actorsEnvironment, stepUser: 'Brian' })
134+
// And "Brian" navigates to the shared with me page
135+
await ui.navigateToSharedWithMePage({ actorsEnvironment, stepUser: 'Brian' })
136+
137+
// # user should have access to unsynced shares
138+
// When "Brian" opens the following file in texteditor
139+
// | resource |
140+
// | shareToSales.txt |
141+
await ui.userOpensFileInViewer({
142+
actorsEnvironment,
143+
stepUser: 'Brian',
144+
resource: 'shareToSales.txt',
145+
actionType: 'texteditor'
146+
})
147+
// And "Brian" closes the file viewer
148+
const { page } = actorsEnvironment.getActor({ key: 'Brian' })
149+
await editor.close(page)
150+
// And "Brian" edits the following resources
151+
// | resource | content |
152+
// | shareToSecurity.txt | new content |
153+
await ui.userEditsFile({
154+
actorsEnvironment,
155+
stepUser: 'Brian',
156+
resource: 'shareToSecurity.txt',
157+
content: 'new content'
158+
})
159+
// And "Brian" logs out
160+
await ui.logOutUser({ actorsEnvironment, stepUser: 'Brian' })
161+
162+
// When "Admin" logs in
163+
await ui.logInUser({ usersEnvironment, actorsEnvironment, stepUser: 'Admin' })
164+
165+
// And "Admin" opens the "admin-settings" app
166+
await ui.userOpensApplication({ actorsEnvironment, stepUser: 'Admin', name: 'admin-settings' })
167+
168+
// And "Admin" navigates to the groups management page
169+
await ui.userNavigatesToGroupsManagementPage({ actorsEnvironment, stepUser: 'Admin' })
170+
171+
// # Renaming a Keycloak group results in the creation of a new group on the oCIS server (see https://github.com/owncloud/ocis/issues/10445).
172+
// # After renaming a group, it may take up to 5 minutes for the changes to sync, so avoid using the renamed group in the subsequent steps.
173+
// And "Admin" changes displayName to "a renamed group" for group "keycloak finance" using the sidebar panel
174+
await ui.userRenamesGroup({
175+
actorsEnvironment,
176+
stepUser: 'Admin',
177+
attribute: 'displayName',
178+
value: 'a renamed group',
179+
user: 'keycloak finance'
180+
})
181+
182+
// When "Admin" deletes the following group using the context menu
183+
// | group |
184+
// | sales |
185+
await ui.userDeletesGroup({
186+
actorsEnvironment,
187+
stepUser: 'Admin',
188+
actionType: 'contex menu',
189+
group: 'sales'
190+
})
191+
// Then "Admin" should not see the following group
192+
// | group |
193+
// | sales |
194+
expect(
195+
await ui.checkGroupsPresenceById({
196+
actorsEnvironment,
197+
stepUser: 'Admin',
198+
expectedGroupIds: ['sales']
199+
})
200+
).toBeFalsy()
201+
// And "Admin" logs out
202+
await ui.logOutUser({ actorsEnvironment, stepUser: 'Admin' })
203+
})
204+
})
File renamed without changes.

tests/e2e-playwright/steps/ui/adminSettings.ts

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,3 +161,117 @@ export async function userChangesGroup({
161161
action
162162
})
163163
}
164+
165+
export async function userNavigatesToUserManagementPage({
166+
actorsEnvironment,
167+
stepUser
168+
}: {
169+
actorsEnvironment: ActorsEnvironment
170+
stepUser: string
171+
}): Promise<void> {
172+
const { page } = actorsEnvironment.getActor({ key: stepUser })
173+
const pageObject = new objects.applicationAdminSettings.page.Users({ page })
174+
await pageObject.navigate()
175+
}
176+
177+
export async function userDeletesGroup({
178+
actorsEnvironment,
179+
stepUser,
180+
actionType,
181+
group
182+
}: {
183+
actorsEnvironment: ActorsEnvironment
184+
stepUser: string
185+
actionType: string
186+
group: string
187+
}): Promise<void> {
188+
const { page } = actorsEnvironment.getActor({ key: stepUser })
189+
const groupsObject = new objects.applicationAdminSettings.Groups({ page })
190+
const groupIds = []
191+
192+
switch (actionType) {
193+
case 'batch actions':
194+
groupIds.push(groupsObject.getUUID({ key: group }))
195+
await groupsObject.selectGroup({ key: group })
196+
await groupsObject.deleteGroupUsingBatchAction({ groupIds })
197+
break
198+
case 'context menu':
199+
await groupsObject.deleteGroupUsingContextMenu({ key: group })
200+
break
201+
default:
202+
throw new Error(`'${actionType}' not implemented`)
203+
}
204+
}
205+
206+
export async function userRenamesGroup({
207+
actorsEnvironment,
208+
stepUser,
209+
attribute,
210+
value,
211+
user
212+
}: {
213+
actorsEnvironment: ActorsEnvironment
214+
stepUser: string
215+
attribute: string
216+
value: string
217+
user: string
218+
}): Promise<void> {
219+
const { page } = actorsEnvironment.getActor({ key: stepUser })
220+
const groupsObject = new objects.applicationAdminSettings.Groups({ page })
221+
222+
await groupsObject.changeGroup({
223+
key: user,
224+
attribute: attribute,
225+
value: value,
226+
action: 'context-menu'
227+
})
228+
}
229+
230+
export async function userAddsUserToGroup({
231+
actorsEnvironment,
232+
stepUser,
233+
action,
234+
groups,
235+
user
236+
}: {
237+
actorsEnvironment: ActorsEnvironment
238+
stepUser: string
239+
action: string
240+
groups: string[]
241+
user: string
242+
}): Promise<void> {
243+
const { page } = actorsEnvironment.getActor({ key: stepUser })
244+
const usersObject = new objects.applicationAdminSettings.Users({ page })
245+
switch (action) {
246+
case 'adds':
247+
await usersObject.addToGroups({
248+
key: user,
249+
groups,
250+
action: 'context-menu'
251+
})
252+
break
253+
case 'removes':
254+
await usersObject.removeFromGroups({
255+
key: user,
256+
groups,
257+
action: 'context-menu'
258+
})
259+
break
260+
default:
261+
throw new Error(`'${action}' not implemented`)
262+
}
263+
}
264+
265+
export async function userCreatesGroup({
266+
actorsEnvironment,
267+
stepUser,
268+
group
269+
}: {
270+
actorsEnvironment: ActorsEnvironment
271+
stepUser: string
272+
group: string
273+
}): Promise<void> {
274+
const { page } = actorsEnvironment.getActor({ key: stepUser })
275+
const groupsObject = new objects.applicationAdminSettings.Groups({ page })
276+
await groupsObject.createGroup({ key: group })
277+
}

0 commit comments

Comments
 (0)