Skip to content

Commit 1facfa0

Browse files
committed
test: replace cucumber with playwright for internalLink.feature
Signed-off-by: Ashim Shrestha <[email protected]>
1 parent b8e01de commit 1facfa0

File tree

12 files changed

+528
-1
lines changed

12 files changed

+528
-1
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
"browserslist-useragent-regexp": "^4.0.0",
6161
"commander": "14.0.0",
6262
"debug": "^4.4.1",
63+
"dotenv": "^17.2.1",
6364
"ejs": "3.1.10",
6465
"eslint": "9.29.0",
6566
"git-repo-info": "2.1.1",

playwright.config.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { defineConfig, devices } from '@playwright/test'
2+
import dotenv from 'dotenv'
3+
import path from 'path'
4+
import { fileURLToPath } from 'url'
5+
import { dirname } from 'path'
6+
7+
/**
8+
* Read environment variables from file.
9+
* https://github.com/motdotla/dotenv
10+
*/
11+
const __filename = fileURLToPath(import.meta.url)
12+
const __dirname = dirname(__filename)
13+
dotenv.config({ path: path.resolve(__dirname, 'e2e', '.env'), override: true })
14+
15+
/**
16+
* See https://playwright.dev/docs/test-configuration.
17+
*/
18+
export default defineConfig({
19+
// Look for test files in the "tests" directory, relative to this configuration file.
20+
testDir: 'tests/spec',
21+
22+
// Run all tests in parallel.
23+
fullyParallel: true,
24+
25+
// Fail the build on CI if you accidentally left test.only in the source code.
26+
forbidOnly: !!process.env.CI,
27+
28+
// Retry on CI only.
29+
retries: process.env.CI ? 2 : 0,
30+
31+
// Opt out of parallel tests on CI.
32+
workers: process.env.CI ? 1 : undefined,
33+
34+
// Reporter to use
35+
reporter: 'html',
36+
37+
use: {
38+
// Collect trace when retrying the failed test.
39+
trace: 'on-first-retry'
40+
},
41+
// Configure projects for major browsers.
42+
projects: [
43+
{
44+
name: 'chromium',
45+
use: {
46+
...devices['Desktop Chrome'],
47+
launchOptions: {
48+
args: [
49+
'--allow-insecure-localhost',
50+
'--ignore-certificate-errors' // Note: This flag is deprecated as of Chrome 119
51+
]
52+
}
53+
}
54+
},
55+
{
56+
name: 'firefox',
57+
use: { ...devices['Desktop Firefox'] }
58+
},
59+
{
60+
name: 'webkit',
61+
use: { ...devices['Desktop Safari'] }
62+
}
63+
]
64+
// // Run your local dev server before starting the tests.
65+
// webServer: {
66+
// command: 'npm run start',
67+
// url: 'http://localhost:3000',
68+
// reuseExistingServer: !process.env.CI,
69+
// },
70+
})

pnpm-lock.yaml

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/e2e/helper/api.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { config } from '../config'
2+
import { UsersEnvironment } from '../support/environment'
3+
import { api } from '../support'
4+
import { ResourceType } from '../support/api/share/share'
5+
6+
export async function createUserUsingAPI(
7+
usersEnvironment: UsersEnvironment,
8+
stepUser: string,
9+
userToBeCreated: string
10+
): Promise<void> {
11+
const admin = usersEnvironment.getUser({ key: stepUser })
12+
const user = usersEnvironment.getUser({ key: userToBeCreated })
13+
// do not try to create users when using predefined users
14+
if (!config.predefinedUsers) {
15+
await api.provision.createUser({ user, admin })
16+
}
17+
}
18+
19+
export async function createFolderInPersonalSpaceUsingAPI(
20+
usersEnvironment: UsersEnvironment,
21+
stepUser: string,
22+
folderName: string
23+
): Promise<void> {
24+
const user = usersEnvironment.getUser({ key: stepUser })
25+
await api.dav.createFolderInsidePersonalSpace({ user, folder: folderName })
26+
}
27+
28+
export async function shareResourceUsingAPI(
29+
usersEnvironment: UsersEnvironment,
30+
stepUser: string,
31+
resource: string,
32+
recipient: string,
33+
type: string,
34+
role: string,
35+
resourceType: ResourceType
36+
): Promise<void> {
37+
const user = usersEnvironment.getUser({ key: stepUser })
38+
await api.share.createShare({
39+
user,
40+
path: resource,
41+
shareType: type,
42+
shareWith: recipient,
43+
role: role,
44+
resourceType: resourceType as ResourceType
45+
})
46+
}
47+
48+
export async function createPublicLinkOfResourceUsingAPI(
49+
usersEnvironment: UsersEnvironment,
50+
stepUser: string,
51+
resource: string,
52+
role: string,
53+
name?: string,
54+
password?: undefined,
55+
space?: 'Personal'
56+
) {
57+
const user = usersEnvironment.getUser({ key: stepUser })
58+
59+
await api.share.createLinkShare({
60+
user,
61+
path: resource,
62+
password: password,
63+
name: name ? name : 'Unnamed link',
64+
role: role,
65+
spaceName: space
66+
})
67+
}

tests/e2e/helper/cleanUpUser.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { config } from '../config.js'
2+
import { api, environment, store } from '../support'
3+
import { User, UserState } from '../support/types'
4+
5+
const cleanupPredefinedUser = async (userKey: string, user: User) => {
6+
// delete the personal space resources
7+
const resources = await api.dav.listSpaceResources({ user, spaceType: 'personal' })
8+
for (const fileId in resources) {
9+
await api.dav.deleteSpaceResource({ user, fileId })
10+
}
11+
12+
// cleanup trashbin if resources have been deleted
13+
if (Object.keys(resources).length) {
14+
await api.dav.emptyTrashbin({ user, spaceType: 'personal' })
15+
}
16+
17+
// revert user state
18+
const usersEnvironment = new environment.UsersEnvironment()
19+
const userState: UserState = usersEnvironment.getUserState(userKey)
20+
if (userState.hasOwnProperty('autoAcceptShare')) {
21+
await api.settings.configureAutoAcceptShare({ user, state: userState.autoAcceptShare })
22+
}
23+
if (userState.hasOwnProperty('language')) {
24+
await api.settings.changeLanguage({ user, language: userState.language })
25+
}
26+
}
27+
28+
export const cleanUpUser = async (createdUserStore, adminUser: User) => {
29+
const requests: Promise<User>[] = []
30+
for (const [key, user] of createdUserStore.entries()) {
31+
console.log(`Cleanup user: ${user.id}`)
32+
if (!config.predefinedUsers) {
33+
requests.push(api.provision.deleteUser({ user, admin: adminUser }))
34+
} else {
35+
await cleanupPredefinedUser(key, user)
36+
}
37+
}
38+
await Promise.all(requests)
39+
createdUserStore.clear()
40+
store.keycloakCreatedUser.clear()
41+
}

tests/e2e/helper/public.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { objects } from '../support'
2+
import { ActorsEnvironment, LinksEnvironment } from '../support/environment'
3+
4+
export async function openPublicLink(
5+
actorsEnvironment: ActorsEnvironment,
6+
linksEnvironment: LinksEnvironment,
7+
stepUser: string,
8+
name: string
9+
): Promise<void> {
10+
const { page } = await actorsEnvironment.createActor({
11+
key: stepUser,
12+
namespace: actorsEnvironment.generateNamespace(stepUser, stepUser)
13+
})
14+
15+
const { url } = linksEnvironment.getLink({ name })
16+
const pageObject = new objects.applicationFiles.page.Public({ page })
17+
await pageObject.open({ url })
18+
}

tests/e2e/helper/resources.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { objects } from '../support'
2+
import { ActorsEnvironment, FilesEnvironment } from '../support/environment'
3+
4+
export async function uploadResource(
5+
actorsEnvironment: ActorsEnvironment,
6+
filesEnvironment: FilesEnvironment,
7+
stepUser: string,
8+
resource: string,
9+
to: string,
10+
type?: string,
11+
option?: string
12+
): Promise<void> {
13+
const { page } = actorsEnvironment.getActor({ key: stepUser })
14+
const resourceObject = new objects.applicationFiles.Resource({ page })
15+
await resourceObject.upload({
16+
to: to,
17+
resources: [filesEnvironment.getFile({ name: resource })],
18+
option: option,
19+
type: type
20+
})
21+
}
22+
23+
export async function isAbleToEditFileOrFolder(
24+
actorsEnvironment: ActorsEnvironment,
25+
stepUser: string,
26+
resource: string
27+
): Promise<boolean> {
28+
const { page } = actorsEnvironment.getActor({ key: stepUser })
29+
const resourceObject = new objects.applicationFiles.Resource({ page })
30+
const userCanEdit = await resourceObject.canManageResource({ resource })
31+
return userCanEdit
32+
}

tests/e2e/helper/session.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { config } from '../config.js'
2+
import { api, objects } from '../support'
3+
import { ActorsEnvironment, UsersEnvironment } from '../support/environment'
4+
import { User } from '../support/types'
5+
6+
async function createNewSession(actorsEnvironment: ActorsEnvironment, stepUser: string) {
7+
const { page } = await actorsEnvironment.createActor({
8+
key: stepUser,
9+
namespace: actorsEnvironment.generateNamespace(stepUser, stepUser)
10+
})
11+
return new objects.runtime.Session({ page })
12+
}
13+
14+
async function initUserStates(userKey: string, user: User, usersEnvironment: UsersEnvironment) {
15+
const userInfo = await api.graph.getMeInfo(user)
16+
usersEnvironment.storeCreatedUser(userKey, {
17+
...user,
18+
uuid: userInfo.id,
19+
email: userInfo.mail
20+
})
21+
usersEnvironment.saveUserState(userKey, {
22+
language: userInfo.preferredLanguage,
23+
autoAcceptShare: await api.settings.getAutoAcceptSharesValue(user)
24+
})
25+
}
26+
27+
export async function LogInUser(
28+
usersEnvironment: UsersEnvironment,
29+
actorsEnvironment: ActorsEnvironment,
30+
stepUser: string
31+
): Promise<void> {
32+
const sessionObject = await createNewSession(actorsEnvironment, stepUser)
33+
const { page } = actorsEnvironment.getActor({ key: stepUser })
34+
35+
let user = null
36+
if (stepUser === 'Admin' || config.predefinedUsers) {
37+
user = usersEnvironment.getUser({ key: stepUser })
38+
} else {
39+
user = usersEnvironment.getCreatedUser({ key: stepUser })
40+
}
41+
42+
await page.goto(config.baseUrl)
43+
await sessionObject.login(user)
44+
45+
await page.locator('#web-content').waitFor()
46+
47+
// initialize user states: uuid, language, auto-sync
48+
if (config.predefinedUsers) {
49+
await initUserStates(stepUser, user, usersEnvironment)
50+
// test should run with English language
51+
await api.settings.changeLanguage({ user, language: 'en' })
52+
await page.reload({ waitUntil: 'load' })
53+
}
54+
}
55+
56+
export async function LogOutUser(
57+
actorsEnvironment: ActorsEnvironment,
58+
stepUser: string
59+
): Promise<void> {
60+
const actor = actorsEnvironment.getActor({ key: stepUser })
61+
const canLogout = !!(await actor.page.locator('#_userMenuButton').count())
62+
63+
const sessionObject = new objects.runtime.Session({ page: actor.page })
64+
canLogout && (await sessionObject.logout())
65+
await actor.close()
66+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { config } from '../config.js'
2+
import { api, store } from '../support'
3+
import { User } from '../support/types'
4+
import { UsersEnvironment } from '../support/environment'
5+
6+
const storeKeycloakGroups = async (adminUser: User, usersEnvironment) => {
7+
const groups = await api.graph.getGroups(adminUser)
8+
9+
store.dummyKeycloakGroupStore.forEach((dummyGroup) => {
10+
const matchingGroup = groups.find((group) => group.displayName === dummyGroup.displayName)
11+
if (matchingGroup) {
12+
usersEnvironment.storeCreatedGroup({ group: { ...dummyGroup, uuid: matchingGroup.id } })
13+
}
14+
})
15+
}
16+
17+
export async function setAccessAndRefreshToken(usersEnvironment: UsersEnvironment) {
18+
if (!config.basicAuth && !config.predefinedUsers) {
19+
let user = usersEnvironment.getUser({ key: config.adminUsername })
20+
if (config.keycloak) {
21+
user = usersEnvironment.getUser({ key: config.keycloakAdminUser })
22+
await api.keycloak.setAccessTokenForKeycloakOcisUser(user)
23+
await api.keycloak.setAccessTokenForKeycloakUser(user)
24+
await storeKeycloakGroups(user, usersEnvironment)
25+
} else {
26+
await api.token.setAccessAndRefreshToken(user)
27+
}
28+
}
29+
}

0 commit comments

Comments
 (0)