From 9274fc4ad6322081d889a67a58de0b2dcb0b5314 Mon Sep 17 00:00:00 2001 From: amrita Date: Tue, 10 Jan 2023 12:02:07 +0545 Subject: [PATCH 1/4] Add e2e tests related to internal link in personal space --- .../features/smoke/internalLink.ocis.feature | 38 +++++++++++ .../e2e/cucumber/features/smoke/link.feature | 10 +-- tests/e2e/cucumber/steps/ui/links.ts | 13 +++- tests/e2e/cucumber/steps/ui/public.ts | 18 +++++ tests/e2e/cucumber/steps/ui/resources.ts | 58 ++++++++++++++++ tests/e2e/cucumber/steps/ui/shares.ts | 9 +++ tests/e2e/support/environment/actor/actor.ts | 6 ++ .../support/objects/app-files/link/actions.ts | 67 +++++++++++++++++++ .../support/objects/app-files/link/index.ts | 13 ++++ .../objects/app-files/page/shares/withMe.ts | 13 +++- tests/e2e/support/objects/runtime/session.ts | 6 +- tests/e2e/support/types.ts | 1 + 12 files changed, 244 insertions(+), 8 deletions(-) create mode 100644 tests/e2e/cucumber/features/smoke/internalLink.ocis.feature diff --git a/tests/e2e/cucumber/features/smoke/internalLink.ocis.feature b/tests/e2e/cucumber/features/smoke/internalLink.ocis.feature new file mode 100644 index 00000000000..accffed7188 --- /dev/null +++ b/tests/e2e/cucumber/features/smoke/internalLink.ocis.feature @@ -0,0 +1,38 @@ +Feature: internal link + + Scenario: link with internal permission + Given "Admin" creates following users + | id | + | Alice | + | Brian | + And "Alice" creates the following folder in personal space using API + | name | + | folderPublic | + And "Alice" logs in + And "Alice" opens the "files" app + And "Alice" uploads the following resources + | resource | to | + | lorem.txt | folderPublic | + When "Alice" shares the following resource using the sidebar panel + | resource | recipient | type | role | + | folderPublic | Brian | user | editor | + And "Alice" creates a public link using sidebar panel + | resource | name | role | expireDate | + | folderPublic | myPublicLink | internal | +5 days | + And "Brian" opens the public link "myPublicLink" + And "Brian" logs in the internal link + And "Brian" opens shared-with-me page + And "Brian" accepts the following share + | name | + | folderPublic | + And "Brian" uploads the following resource + | resource | to | + | simple.pdf | folderPublic | + And "Alice" updates following sharee role + | resource | recipient | type | role | + | folderPublic | Brian | user | custom_permissions:read | + And "Alice" logs out +# Then "Brian" should not able to edit the following resources +# | resource | +# | folderPublic | + And "Brian" logs out diff --git a/tests/e2e/cucumber/features/smoke/link.feature b/tests/e2e/cucumber/features/smoke/link.feature index 7154284797c..a00c0061e60 100644 --- a/tests/e2e/cucumber/features/smoke/link.feature +++ b/tests/e2e/cucumber/features/smoke/link.feature @@ -4,17 +4,17 @@ Feature: link Given "Admin" creates following users | id | | Alice | - When "Alice" logs in + And "Alice" creates the following folder in personal space using API + | name | + | folderPublic | + And "Alice" logs in And "Alice" opens the "files" app - And "Alice" creates the following resources - | resource | type | - | folderPublic | folder | And "Alice" uploads the following resources | resource | to | | lorem.txt | folderPublic | #Then "Alice" should see the following resource # | folderPublic/lorem.txt | - And "Alice" creates a public link for the resource "folderPublic" using the sidebar panel + When "Alice" creates a public link for the resource "folderPublic" using the sidebar panel And "Alice" renames the most recently created public link of resource "folderPublic" to "myPublicLink" And "Alice" edits the public link named "myPublicLink" of resource "folderPublic" changing role to "uploader" And "Alice" sets the expiration date of the public link named "myPublicLink" of resource "folderPublic" to "+5 days" diff --git a/tests/e2e/cucumber/steps/ui/links.ts b/tests/e2e/cucumber/steps/ui/links.ts index b6e5acf3ee1..4ec1e9c6558 100644 --- a/tests/e2e/cucumber/steps/ui/links.ts +++ b/tests/e2e/cucumber/steps/ui/links.ts @@ -1,4 +1,4 @@ -import { Then, When } from '@cucumber/cucumber' +import { DataTable, Then, When } from '@cucumber/cucumber' import { expect } from '@playwright/test' import { World } from '../../environment' import { objects } from '../../../support' @@ -143,3 +143,14 @@ When( expect(role).toBe(newPermission.toLowerCase()) } ) + +When( + '{string} creates a public link using sidebar panel', + async function (this: World, stepUser: string, stepTable: DataTable): Promise { + const { page } = this.actorsEnvironment.getActor({ key: stepUser }) + const linkObject = new objects.applicationFiles.Link({ page }) + for (const info of stepTable.hashes()) { + await linkObject.createPublicLink(info) + } + } +) diff --git a/tests/e2e/cucumber/steps/ui/public.ts b/tests/e2e/cucumber/steps/ui/public.ts index 46a9f45bb0d..3619ce23cbc 100644 --- a/tests/e2e/cucumber/steps/ui/public.ts +++ b/tests/e2e/cucumber/steps/ui/public.ts @@ -137,3 +137,21 @@ When( } } ) + +When( + '{string} logs in the internal link', + async function (this: World, stepUser: string): Promise { + let user + try { + user = this.usersEnvironment.getUser({ key: stepUser }) + } catch (e) {} + const { page } = await this.actorsEnvironment.createActor({ + key: stepUser, + namespace: kebabCase( + [this.feature.name, stepUser, DateTime.now().toFormat('yyyy-M-d-hh-mm-ss')].join('-') + ) + }) + const sessionObject = new objects.runtime.Session({ page }) + await sessionObject.internalLinkLogin({ user }) + } +) diff --git a/tests/e2e/cucumber/steps/ui/resources.ts b/tests/e2e/cucumber/steps/ui/resources.ts index ef8654863b5..42e27981fa1 100644 --- a/tests/e2e/cucumber/steps/ui/resources.ts +++ b/tests/e2e/cucumber/steps/ui/resources.ts @@ -361,3 +361,61 @@ When( } } ) + +Then( + 'the following resource(s) should contain the following tag(s) in the files list for user {string}', + async function (this: World, stepUser: string, stepTable: DataTable): Promise { + const { page } = this.actorsEnvironment.getActor({ key: stepUser }) + const resourceObject = new objects.applicationFiles.Resource({ page }) + for (const { resource, tags } of stepTable.hashes()) { + const isVisible = await resourceObject.areTagsVisibleForResourceInFilesTable({ + resource, + tags: tags.split(',').map((tag) => tag.trim().toLowerCase()) + }) + expect(isVisible).toBe(true) + } + } +) + +Then( + 'the following resource(s) should contain the following tag(s) in the details panel for user {string}', + async function (this: World, stepUser: string, stepTable: DataTable): Promise { + const { page } = this.actorsEnvironment.getActor({ key: stepUser }) + const resourceObject = new objects.applicationFiles.Resource({ page }) + for (const { resource, tags } of stepTable.hashes()) { + const isVisible = await resourceObject.areTagsVisibleForResourceInDetailsPanel({ + resource, + tags: tags.split(',').map((tag) => tag.trim().toLowerCase()) + }) + expect(isVisible).toBe(true) + } + } +) + +When( + '{string} adds the following tag(s) for the following resource(s) using the sidebar panel', + async function (this: World, stepUser: string, stepTable: DataTable) { + const { page } = this.actorsEnvironment.getActor({ key: stepUser }) + const resourceObject = new objects.applicationFiles.Resource({ page }) + for (const { resource, tags } of stepTable.hashes()) { + await resourceObject.addTags({ + resource, + tags: tags.split(',').map((tag) => tag.trim().toLowerCase()) + }) + } + } +) + +When( + '{string} removes the following tag(s) for the following resource(s) using the sidebar panel', + async function (this: World, stepUser: string, stepTable: DataTable) { + const { page } = this.actorsEnvironment.getActor({ key: stepUser }) + const resourceObject = new objects.applicationFiles.Resource({ page }) + for (const { resource, tags } of stepTable.hashes()) { + await resourceObject.removeTags({ + resource, + tags: tags.split(',').map((tag) => tag.trim().toLowerCase()) + }) + } + } +) diff --git a/tests/e2e/cucumber/steps/ui/shares.ts b/tests/e2e/cucumber/steps/ui/shares.ts index 8a7127aef44..afda7e0a2db 100644 --- a/tests/e2e/cucumber/steps/ui/shares.ts +++ b/tests/e2e/cucumber/steps/ui/shares.ts @@ -223,3 +223,12 @@ Then( } } ) + +When( + '{string} opens shared-with-me page', + async function (this: World, stepUser: string): Promise { + const actor = this.actorsEnvironment.getActor({ key: stepUser }) + const pageObject = new objects.applicationFiles.page.shares.WithMe({ page: actor.page }) + await pageObject.openShareWithMeFromInternalLink(actor) + } +) diff --git a/tests/e2e/support/environment/actor/actor.ts b/tests/e2e/support/environment/actor/actor.ts index 40328a2dcd0..71a3b751fc6 100644 --- a/tests/e2e/support/environment/actor/actor.ts +++ b/tests/e2e/support/environment/actor/actor.ts @@ -28,6 +28,12 @@ export class ActorEnvironment extends EventEmitter implements Actor { this.page = await this.context.newPage() } + public async updatePage(newPage: Page): Promise { + await this.page.close() + this.page = newPage + return this.page + } + async close(): Promise { if (this.options.context.reportTracing) { await this.context?.tracing.stop({ diff --git a/tests/e2e/support/objects/app-files/link/actions.ts b/tests/e2e/support/objects/app-files/link/actions.ts index 95973849f47..b1ed24af24c 100644 --- a/tests/e2e/support/objects/app-files/link/actions.ts +++ b/tests/e2e/support/objects/app-files/link/actions.ts @@ -5,6 +5,14 @@ import { sidebar } from '../utils' import { getActualExpiryDate } from '../../../utils/datePicker' import { clickResource } from '../resource/actions' +export interface createLinkAllArgs { + page: Page + resource: string + name?: string + expireDate?: string + role?: string + password?: string +} export interface createLinkArgs { page: Page resource?: string @@ -87,6 +95,65 @@ const deleteLinkButton = `//ancestor::li//div[contains(@class, "details-buttons")]//button/span[text()="Delete link"]` const confirmDeleteButton = `//button[contains(@class,"oc-modal-body-actions-confirm") and text()="Delete"]` +export const createLinkWithArgs = async (args: createLinkAllArgs): Promise => { + const { page, resource, name, expireDate, role, password } = args + let linkName, createdLink + const resourcePaths = resource.split('/') + const resourceName = resourcePaths.pop() + if (resourcePaths.length) { + await clickResource({ page: page, path: resourcePaths.join('/') }) + } + await sidebar.open({ page: page, resource: resourceName }) + await sidebar.openPanel({ page: page, name: 'sharing' }) + + await page.locator(addPublicLinkButton).click() + await waitForPopupNotPresent(page) + createdLink = await page.locator(util.format(publicLink, 'Link')).textContent() + + if (name) { + await page.locator(util.format(editPublicLinkButton, 'Link')).click() + await page.locator(editPublicLinkRenameButton).click() + await page.locator(editPublicLinkInput).fill(name) + await page.locator(editPublicLinkRenameConfirm).click() + const message = await page.locator(linkUpdateDialog).textContent() + expect(message.trim()).toBe('Link was updated successfully') + linkName = await page.locator(getMostRecentLink + '//h4').textContent() + } + if (role) { + await page.waitForSelector(linkUpdateDialog, { state: 'detached', strict: false }) + await page.locator(util.format(publicLinkEditRoleButton, linkName)).click() + await page.locator(util.format(publicLinkSetRoleButton, role.toLowerCase())).click() + const message = await page.locator(linkUpdateDialog).textContent() + expect(message.trim()).toBe('Link was updated successfully') + } + if (expireDate) { + await page.locator(util.format(editPublicLinkButton, linkName)).click() + await page.locator(editPublicLinkSetExpirationButton).click() + + const newExpiryDate = getActualExpiryDate( + expireDate.toLowerCase().match(/[dayrmonthwek]+/)[0] as any, + expireDate + ) + + await page.locator(linkExpiryDatepicker).evaluate( + (datePicker: any, { newExpiryDate }): any => { + datePicker?.__vueParentComponent?.refs?.calendar.move(newExpiryDate) + }, + { newExpiryDate } + ) + await page.locator(linkExpiryDatepicker).click() + } + if (password) { + await page.waitForSelector(linkUpdateDialog, { state: 'detached', strict: false }) + await page.locator(editPublicLinkAddPasswordButton).click() + await page.locator(editPublicLinkInput).fill(password) + await page.locator(editPublicLinkRenameConfirm).click() + const message = await page.locator(linkUpdateDialog).textContent() + expect(message.trim()).toBe('Link was updated successfully') + } + return [createdLink, linkName] +} + export const createLink = async (args: createLinkArgs): Promise => { const { space, page, resource } = args if (!space) { diff --git a/tests/e2e/support/objects/app-files/link/index.ts b/tests/e2e/support/objects/app-files/link/index.ts index be048734994..3746bca967f 100644 --- a/tests/e2e/support/objects/app-files/link/index.ts +++ b/tests/e2e/support/objects/app-files/link/index.ts @@ -8,7 +8,9 @@ import { changeNameArgs, changeRole, changeRoleArgs, + createLinkWithArgs, createLink, + createLinkAllArgs, createLinkArgs, deleteLink, deleteLinkArgs, @@ -27,6 +29,17 @@ export class Link { this.#linksEnvironment = new LinksEnvironment() } + async createPublicLink(args: Omit): Promise { + const startUrl = this.#page.url() + const linkArgs = await createLinkWithArgs({ ...args, page: this.#page }) + const [url, name] = linkArgs + this.#linksEnvironment.createLink({ + key: name, + link: { name, url } + }) + await this.#page.goto(startUrl) + } + async create(args: Omit): Promise { const startUrl = this.#page.url() const url = await createLink({ ...args, page: this.#page }) diff --git a/tests/e2e/support/objects/app-files/page/shares/withMe.ts b/tests/e2e/support/objects/app-files/page/shares/withMe.ts index e259d7d6faf..78041ef5dcb 100644 --- a/tests/e2e/support/objects/app-files/page/shares/withMe.ts +++ b/tests/e2e/support/objects/app-files/page/shares/withMe.ts @@ -1,6 +1,8 @@ import { Page } from 'playwright' +import { Actor } from '../../../../../support/types' -const sharesNavSelector = '//a[@data-nav-name="files-shares-with-me"]' +const sharesNavSelector = '//a[@data-nav-name="files-shares"]' +const shareWithMeNavButton = `//a/span[text()='Open "Shared with me"']` export class WithMe { #page: Page @@ -12,4 +14,13 @@ export class WithMe { async navigate(): Promise { await this.#page.locator(sharesNavSelector).click() } + + async openShareWithMeFromInternalLink(actor: Actor): Promise { + const [newTab] = await Promise.all([ + this.#page.waitForEvent('popup'), + this.#page.locator(shareWithMeNavButton).click() + ]) + await newTab.waitForSelector('#shares-navigation') + await actor.updatePage(newTab) + } } diff --git a/tests/e2e/support/objects/runtime/session.ts b/tests/e2e/support/objects/runtime/session.ts index 81031e5bc73..bbba0a6c97f 100644 --- a/tests/e2e/support/objects/runtime/session.ts +++ b/tests/e2e/support/objects/runtime/session.ts @@ -15,7 +15,6 @@ class Ocis implements LoginAdapter { async login({ user }: { user: User }): Promise { const { id, password } = user - await this.#page.locator('#oc-login-username').fill(id) await this.#page.locator('#oc-login-password').fill(password) await this.#page.locator('button[type="submit"]').click() @@ -62,4 +61,9 @@ export class Session { await this.#page.locator('#_userMenuButton').click() await this.#page.locator('#oc-topbar-account-logout').click() } + + async internalLinkLogin({ user }: { user: User }): Promise { + await this.#adapter.login({ user }) + await this.#page.waitForSelector('#web-content-main') + } } diff --git a/tests/e2e/support/types.ts b/tests/e2e/support/types.ts index 9c314099f60..e2f42fcadb1 100644 --- a/tests/e2e/support/types.ts +++ b/tests/e2e/support/types.ts @@ -15,6 +15,7 @@ export interface Actor { context: BrowserContext page: Page close(): Promise + updatePage(page: Page): Promise } export interface User { From 94e0ec1f76a6a936ba6f9213435bac08af6c0aa5 Mon Sep 17 00:00:00 2001 From: Saw-jan Date: Mon, 23 Jan 2023 11:55:44 +0545 Subject: [PATCH 2/4] refactor re-use the steps --- .../features/smoke/internalLink.ocis.feature | 17 +++-- .../e2e/cucumber/features/smoke/link.feature | 10 +-- tests/e2e/cucumber/steps/ui/links.ts | 16 ++--- tests/e2e/cucumber/steps/ui/public.ts | 18 ----- tests/e2e/cucumber/steps/ui/session.ts | 23 +++++-- tests/e2e/cucumber/steps/ui/shares.ts | 9 --- tests/e2e/support/environment/actor/actor.ts | 4 +- .../support/objects/app-files/link/actions.ts | 67 ------------------- .../support/objects/app-files/link/index.ts | 13 ---- .../objects/app-files/page/shares/withMe.ts | 2 +- tests/e2e/support/objects/runtime/session.ts | 5 -- tests/e2e/support/types.ts | 2 +- 12 files changed, 44 insertions(+), 142 deletions(-) diff --git a/tests/e2e/cucumber/features/smoke/internalLink.ocis.feature b/tests/e2e/cucumber/features/smoke/internalLink.ocis.feature index accffed7188..274cdcfb0fd 100644 --- a/tests/e2e/cucumber/features/smoke/internalLink.ocis.feature +++ b/tests/e2e/cucumber/features/smoke/internalLink.ocis.feature @@ -1,6 +1,6 @@ -Feature: internal link +Feature: internal link share - Scenario: link with internal permission + Scenario: link share as an internal role Given "Admin" creates following users | id | | Alice | @@ -13,15 +13,14 @@ Feature: internal link And "Alice" uploads the following resources | resource | to | | lorem.txt | folderPublic | - When "Alice" shares the following resource using the sidebar panel + And "Alice" shares the following resource using the sidebar panel | resource | recipient | type | role | | folderPublic | Brian | user | editor | - And "Alice" creates a public link using sidebar panel - | resource | name | role | expireDate | - | folderPublic | myPublicLink | internal | +5 days | - And "Brian" opens the public link "myPublicLink" - And "Brian" logs in the internal link - And "Brian" opens shared-with-me page + And "Alice" creates a public link for the resource "folderPublic" using the sidebar panel + When "Alice" edits the public link named "Link" of resource "folderPublic" changing role to "internal" + And "Brian" opens the public link "Link" + And "Brian" logs in from the internal link + And "Brian" opens shared-with-me page from the internal link And "Brian" accepts the following share | name | | folderPublic | diff --git a/tests/e2e/cucumber/features/smoke/link.feature b/tests/e2e/cucumber/features/smoke/link.feature index a00c0061e60..7154284797c 100644 --- a/tests/e2e/cucumber/features/smoke/link.feature +++ b/tests/e2e/cucumber/features/smoke/link.feature @@ -4,17 +4,17 @@ Feature: link Given "Admin" creates following users | id | | Alice | - And "Alice" creates the following folder in personal space using API - | name | - | folderPublic | - And "Alice" logs in + When "Alice" logs in And "Alice" opens the "files" app + And "Alice" creates the following resources + | resource | type | + | folderPublic | folder | And "Alice" uploads the following resources | resource | to | | lorem.txt | folderPublic | #Then "Alice" should see the following resource # | folderPublic/lorem.txt | - When "Alice" creates a public link for the resource "folderPublic" using the sidebar panel + And "Alice" creates a public link for the resource "folderPublic" using the sidebar panel And "Alice" renames the most recently created public link of resource "folderPublic" to "myPublicLink" And "Alice" edits the public link named "myPublicLink" of resource "folderPublic" changing role to "uploader" And "Alice" sets the expiration date of the public link named "myPublicLink" of resource "folderPublic" to "+5 days" diff --git a/tests/e2e/cucumber/steps/ui/links.ts b/tests/e2e/cucumber/steps/ui/links.ts index 4ec1e9c6558..80a939275db 100644 --- a/tests/e2e/cucumber/steps/ui/links.ts +++ b/tests/e2e/cucumber/steps/ui/links.ts @@ -1,7 +1,9 @@ -import { DataTable, Then, When } from '@cucumber/cucumber' +import { Then, When } from '@cucumber/cucumber' import { expect } from '@playwright/test' import { World } from '../../environment' import { objects } from '../../../support' +import { kebabCase } from 'lodash' +import { DateTime } from 'luxon' When( '{string} creates a public link for the resource {string} using the sidebar panel', @@ -145,12 +147,10 @@ When( ) When( - '{string} creates a public link using sidebar panel', - async function (this: World, stepUser: string, stepTable: DataTable): Promise { - const { page } = this.actorsEnvironment.getActor({ key: stepUser }) - const linkObject = new objects.applicationFiles.Link({ page }) - for (const info of stepTable.hashes()) { - await linkObject.createPublicLink(info) - } + '{string} opens shared-with-me page from the internal link', + async function (this: World, stepUser: string): Promise { + const actor = this.actorsEnvironment.getActor({ key: stepUser }) + const pageObject = new objects.applicationFiles.page.shares.WithMe({ page: actor.page }) + await pageObject.openShareWithMeFromInternalLink(actor) } ) diff --git a/tests/e2e/cucumber/steps/ui/public.ts b/tests/e2e/cucumber/steps/ui/public.ts index 3619ce23cbc..46a9f45bb0d 100644 --- a/tests/e2e/cucumber/steps/ui/public.ts +++ b/tests/e2e/cucumber/steps/ui/public.ts @@ -137,21 +137,3 @@ When( } } ) - -When( - '{string} logs in the internal link', - async function (this: World, stepUser: string): Promise { - let user - try { - user = this.usersEnvironment.getUser({ key: stepUser }) - } catch (e) {} - const { page } = await this.actorsEnvironment.createActor({ - key: stepUser, - namespace: kebabCase( - [this.feature.name, stepUser, DateTime.now().toFormat('yyyy-M-d-hh-mm-ss')].join('-') - ) - }) - const sessionObject = new objects.runtime.Session({ page }) - await sessionObject.internalLinkLogin({ user }) - } -) diff --git a/tests/e2e/cucumber/steps/ui/session.ts b/tests/e2e/cucumber/steps/ui/session.ts index 7409ec042d5..06a771e3c9d 100644 --- a/tests/e2e/cucumber/steps/ui/session.ts +++ b/tests/e2e/cucumber/steps/ui/session.ts @@ -5,16 +5,20 @@ import { DateTime } from 'luxon' import { kebabCase } from 'lodash' import { objects } from '../../../support' -async function LogInUser(this: World, stepUser: string): Promise { - const user = this.usersEnvironment.getUser({ key: stepUser }) - const { page } = await this.actorsEnvironment.createActor({ +async function createNewSession(world: World, stepUser: string) { + const { page } = await world.actorsEnvironment.createActor({ key: stepUser, namespace: kebabCase( - [this.feature.name, stepUser, DateTime.now().toFormat('yyyy-M-d-hh-mm-ss')].join('-') + [world.feature.name, stepUser, DateTime.now().toFormat('yyyy-M-d-hh-mm-ss')].join('-') ) }) - const sessionObject = new objects.runtime.Session({ page }) + return new objects.runtime.Session({ page }) +} +async function LogInUser(this: World, stepUser: string): Promise { + const sessionObject = await createNewSession(this, stepUser) + const { page } = this.actorsEnvironment.getActor({ key: stepUser }) + const user = this.usersEnvironment.getUser({ key: stepUser }) await page.goto(config.frontendUrl) await sessionObject.login({ user }) } @@ -35,3 +39,12 @@ async function LogOutUser(this: World, stepUser: string): Promise { Given('{string} has logged out', LogOutUser) When('{string} logs out', LogOutUser) + +When( + '{string} logs in from the internal link', + async function (this: World, stepUser: string): Promise { + const sessionObject = await createNewSession(this, stepUser) + const user = this.usersEnvironment.getUser({ key: stepUser }) + await sessionObject.login({ user }) + } +) diff --git a/tests/e2e/cucumber/steps/ui/shares.ts b/tests/e2e/cucumber/steps/ui/shares.ts index afda7e0a2db..8a7127aef44 100644 --- a/tests/e2e/cucumber/steps/ui/shares.ts +++ b/tests/e2e/cucumber/steps/ui/shares.ts @@ -223,12 +223,3 @@ Then( } } ) - -When( - '{string} opens shared-with-me page', - async function (this: World, stepUser: string): Promise { - const actor = this.actorsEnvironment.getActor({ key: stepUser }) - const pageObject = new objects.applicationFiles.page.shares.WithMe({ page: actor.page }) - await pageObject.openShareWithMeFromInternalLink(actor) - } -) diff --git a/tests/e2e/support/environment/actor/actor.ts b/tests/e2e/support/environment/actor/actor.ts index 71a3b751fc6..8e2622f987e 100644 --- a/tests/e2e/support/environment/actor/actor.ts +++ b/tests/e2e/support/environment/actor/actor.ts @@ -28,8 +28,10 @@ export class ActorEnvironment extends EventEmitter implements Actor { this.page = await this.context.newPage() } - public async updatePage(newPage: Page): Promise { + public async newPage(newPage: Page): Promise { + // close the old page await this.page.close() + // set the new page this.page = newPage return this.page } diff --git a/tests/e2e/support/objects/app-files/link/actions.ts b/tests/e2e/support/objects/app-files/link/actions.ts index b1ed24af24c..95973849f47 100644 --- a/tests/e2e/support/objects/app-files/link/actions.ts +++ b/tests/e2e/support/objects/app-files/link/actions.ts @@ -5,14 +5,6 @@ import { sidebar } from '../utils' import { getActualExpiryDate } from '../../../utils/datePicker' import { clickResource } from '../resource/actions' -export interface createLinkAllArgs { - page: Page - resource: string - name?: string - expireDate?: string - role?: string - password?: string -} export interface createLinkArgs { page: Page resource?: string @@ -95,65 +87,6 @@ const deleteLinkButton = `//ancestor::li//div[contains(@class, "details-buttons")]//button/span[text()="Delete link"]` const confirmDeleteButton = `//button[contains(@class,"oc-modal-body-actions-confirm") and text()="Delete"]` -export const createLinkWithArgs = async (args: createLinkAllArgs): Promise => { - const { page, resource, name, expireDate, role, password } = args - let linkName, createdLink - const resourcePaths = resource.split('/') - const resourceName = resourcePaths.pop() - if (resourcePaths.length) { - await clickResource({ page: page, path: resourcePaths.join('/') }) - } - await sidebar.open({ page: page, resource: resourceName }) - await sidebar.openPanel({ page: page, name: 'sharing' }) - - await page.locator(addPublicLinkButton).click() - await waitForPopupNotPresent(page) - createdLink = await page.locator(util.format(publicLink, 'Link')).textContent() - - if (name) { - await page.locator(util.format(editPublicLinkButton, 'Link')).click() - await page.locator(editPublicLinkRenameButton).click() - await page.locator(editPublicLinkInput).fill(name) - await page.locator(editPublicLinkRenameConfirm).click() - const message = await page.locator(linkUpdateDialog).textContent() - expect(message.trim()).toBe('Link was updated successfully') - linkName = await page.locator(getMostRecentLink + '//h4').textContent() - } - if (role) { - await page.waitForSelector(linkUpdateDialog, { state: 'detached', strict: false }) - await page.locator(util.format(publicLinkEditRoleButton, linkName)).click() - await page.locator(util.format(publicLinkSetRoleButton, role.toLowerCase())).click() - const message = await page.locator(linkUpdateDialog).textContent() - expect(message.trim()).toBe('Link was updated successfully') - } - if (expireDate) { - await page.locator(util.format(editPublicLinkButton, linkName)).click() - await page.locator(editPublicLinkSetExpirationButton).click() - - const newExpiryDate = getActualExpiryDate( - expireDate.toLowerCase().match(/[dayrmonthwek]+/)[0] as any, - expireDate - ) - - await page.locator(linkExpiryDatepicker).evaluate( - (datePicker: any, { newExpiryDate }): any => { - datePicker?.__vueParentComponent?.refs?.calendar.move(newExpiryDate) - }, - { newExpiryDate } - ) - await page.locator(linkExpiryDatepicker).click() - } - if (password) { - await page.waitForSelector(linkUpdateDialog, { state: 'detached', strict: false }) - await page.locator(editPublicLinkAddPasswordButton).click() - await page.locator(editPublicLinkInput).fill(password) - await page.locator(editPublicLinkRenameConfirm).click() - const message = await page.locator(linkUpdateDialog).textContent() - expect(message.trim()).toBe('Link was updated successfully') - } - return [createdLink, linkName] -} - export const createLink = async (args: createLinkArgs): Promise => { const { space, page, resource } = args if (!space) { diff --git a/tests/e2e/support/objects/app-files/link/index.ts b/tests/e2e/support/objects/app-files/link/index.ts index 3746bca967f..be048734994 100644 --- a/tests/e2e/support/objects/app-files/link/index.ts +++ b/tests/e2e/support/objects/app-files/link/index.ts @@ -8,9 +8,7 @@ import { changeNameArgs, changeRole, changeRoleArgs, - createLinkWithArgs, createLink, - createLinkAllArgs, createLinkArgs, deleteLink, deleteLinkArgs, @@ -29,17 +27,6 @@ export class Link { this.#linksEnvironment = new LinksEnvironment() } - async createPublicLink(args: Omit): Promise { - const startUrl = this.#page.url() - const linkArgs = await createLinkWithArgs({ ...args, page: this.#page }) - const [url, name] = linkArgs - this.#linksEnvironment.createLink({ - key: name, - link: { name, url } - }) - await this.#page.goto(startUrl) - } - async create(args: Omit): Promise { const startUrl = this.#page.url() const url = await createLink({ ...args, page: this.#page }) diff --git a/tests/e2e/support/objects/app-files/page/shares/withMe.ts b/tests/e2e/support/objects/app-files/page/shares/withMe.ts index 78041ef5dcb..67be1753033 100644 --- a/tests/e2e/support/objects/app-files/page/shares/withMe.ts +++ b/tests/e2e/support/objects/app-files/page/shares/withMe.ts @@ -21,6 +21,6 @@ export class WithMe { this.#page.locator(shareWithMeNavButton).click() ]) await newTab.waitForSelector('#shares-navigation') - await actor.updatePage(newTab) + await actor.newPage(newTab) } } diff --git a/tests/e2e/support/objects/runtime/session.ts b/tests/e2e/support/objects/runtime/session.ts index bbba0a6c97f..75258824fe7 100644 --- a/tests/e2e/support/objects/runtime/session.ts +++ b/tests/e2e/support/objects/runtime/session.ts @@ -61,9 +61,4 @@ export class Session { await this.#page.locator('#_userMenuButton').click() await this.#page.locator('#oc-topbar-account-logout').click() } - - async internalLinkLogin({ user }: { user: User }): Promise { - await this.#adapter.login({ user }) - await this.#page.waitForSelector('#web-content-main') - } } diff --git a/tests/e2e/support/types.ts b/tests/e2e/support/types.ts index e2f42fcadb1..2cb07a16b9a 100644 --- a/tests/e2e/support/types.ts +++ b/tests/e2e/support/types.ts @@ -15,7 +15,7 @@ export interface Actor { context: BrowserContext page: Page close(): Promise - updatePage(page: Page): Promise + newPage(page: Page): Promise } export interface User { From 74dfca6851d43ee31da5410929aaeb8fc3f2644b Mon Sep 17 00:00:00 2001 From: Saw-jan Date: Mon, 23 Jan 2023 14:29:01 +0545 Subject: [PATCH 3/4] refactor share via api for link share address reviews --- .../features/smoke/internalLink.ocis.feature | 37 ++++++------ tests/e2e/cucumber/steps/api.ts | 5 +- tests/e2e/cucumber/steps/ui/links.ts | 2 - tests/e2e/cucumber/steps/ui/resources.ts | 58 ------------------- tests/e2e/support/api/share/share.ts | 9 ++- .../objects/app-files/page/shares/withMe.ts | 9 +-- tests/e2e/support/objects/runtime/session.ts | 1 + 7 files changed, 32 insertions(+), 89 deletions(-) diff --git a/tests/e2e/cucumber/features/smoke/internalLink.ocis.feature b/tests/e2e/cucumber/features/smoke/internalLink.ocis.feature index 274cdcfb0fd..51f314c7d02 100644 --- a/tests/e2e/cucumber/features/smoke/internalLink.ocis.feature +++ b/tests/e2e/cucumber/features/smoke/internalLink.ocis.feature @@ -1,37 +1,34 @@ Feature: internal link share - Scenario: link share as an internal role + Scenario: share a link with internal role Given "Admin" creates following users | id | | Alice | | Brian | And "Alice" creates the following folder in personal space using API - | name | - | folderPublic | + | name | + | myfolder | + And "Alice" shares the following resource using API + | resource | recipient | type | role | + | myfolder | Brian | user | editor | And "Alice" logs in And "Alice" opens the "files" app - And "Alice" uploads the following resources - | resource | to | - | lorem.txt | folderPublic | - And "Alice" shares the following resource using the sidebar panel - | resource | recipient | type | role | - | folderPublic | Brian | user | editor | - And "Alice" creates a public link for the resource "folderPublic" using the sidebar panel - When "Alice" edits the public link named "Link" of resource "folderPublic" changing role to "internal" + And "Alice" creates a public link for the resource "myfolder" using the sidebar panel + When "Alice" edits the public link named "Link" of resource "myfolder" changing role to "internal" And "Brian" opens the public link "Link" And "Brian" logs in from the internal link And "Brian" opens shared-with-me page from the internal link And "Brian" accepts the following share - | name | - | folderPublic | + | name | + | myfolder | And "Brian" uploads the following resource - | resource | to | - | simple.pdf | folderPublic | + | resource | to | + | simple.pdf | myfolder | And "Alice" updates following sharee role - | resource | recipient | type | role | - | folderPublic | Brian | user | custom_permissions:read | + | resource | recipient | type | role | + | myfolder | Brian | user | custom_permissions:read | And "Alice" logs out -# Then "Brian" should not able to edit the following resources -# | resource | -# | folderPublic | + Then "Brian" should not be able to reshare the following resource + | resource | + | myfolder | And "Brian" logs out diff --git a/tests/e2e/cucumber/steps/api.ts b/tests/e2e/cucumber/steps/api.ts index 85d1d8739d8..dbc924eac82 100644 --- a/tests/e2e/cucumber/steps/api.ts +++ b/tests/e2e/cucumber/steps/api.ts @@ -120,9 +120,10 @@ Given( await api.share.createShare({ user, path: info.resource, - shareWith: info.recipient, shareType: info.type, - role: info.role + shareWith: info.recipient, + role: info.role, + name: info.name }) } } diff --git a/tests/e2e/cucumber/steps/ui/links.ts b/tests/e2e/cucumber/steps/ui/links.ts index 80a939275db..f6c23591759 100644 --- a/tests/e2e/cucumber/steps/ui/links.ts +++ b/tests/e2e/cucumber/steps/ui/links.ts @@ -2,8 +2,6 @@ import { Then, When } from '@cucumber/cucumber' import { expect } from '@playwright/test' import { World } from '../../environment' import { objects } from '../../../support' -import { kebabCase } from 'lodash' -import { DateTime } from 'luxon' When( '{string} creates a public link for the resource {string} using the sidebar panel', diff --git a/tests/e2e/cucumber/steps/ui/resources.ts b/tests/e2e/cucumber/steps/ui/resources.ts index 42e27981fa1..ef8654863b5 100644 --- a/tests/e2e/cucumber/steps/ui/resources.ts +++ b/tests/e2e/cucumber/steps/ui/resources.ts @@ -361,61 +361,3 @@ When( } } ) - -Then( - 'the following resource(s) should contain the following tag(s) in the files list for user {string}', - async function (this: World, stepUser: string, stepTable: DataTable): Promise { - const { page } = this.actorsEnvironment.getActor({ key: stepUser }) - const resourceObject = new objects.applicationFiles.Resource({ page }) - for (const { resource, tags } of stepTable.hashes()) { - const isVisible = await resourceObject.areTagsVisibleForResourceInFilesTable({ - resource, - tags: tags.split(',').map((tag) => tag.trim().toLowerCase()) - }) - expect(isVisible).toBe(true) - } - } -) - -Then( - 'the following resource(s) should contain the following tag(s) in the details panel for user {string}', - async function (this: World, stepUser: string, stepTable: DataTable): Promise { - const { page } = this.actorsEnvironment.getActor({ key: stepUser }) - const resourceObject = new objects.applicationFiles.Resource({ page }) - for (const { resource, tags } of stepTable.hashes()) { - const isVisible = await resourceObject.areTagsVisibleForResourceInDetailsPanel({ - resource, - tags: tags.split(',').map((tag) => tag.trim().toLowerCase()) - }) - expect(isVisible).toBe(true) - } - } -) - -When( - '{string} adds the following tag(s) for the following resource(s) using the sidebar panel', - async function (this: World, stepUser: string, stepTable: DataTable) { - const { page } = this.actorsEnvironment.getActor({ key: stepUser }) - const resourceObject = new objects.applicationFiles.Resource({ page }) - for (const { resource, tags } of stepTable.hashes()) { - await resourceObject.addTags({ - resource, - tags: tags.split(',').map((tag) => tag.trim().toLowerCase()) - }) - } - } -) - -When( - '{string} removes the following tag(s) for the following resource(s) using the sidebar panel', - async function (this: World, stepUser: string, stepTable: DataTable) { - const { page } = this.actorsEnvironment.getActor({ key: stepUser }) - const resourceObject = new objects.applicationFiles.Resource({ page }) - for (const { resource, tags } of stepTable.hashes()) { - await resourceObject.removeTags({ - resource, - tags: tags.split(',').map((tag) => tag.trim().toLowerCase()) - }) - } - } -) diff --git a/tests/e2e/support/api/share/share.ts b/tests/e2e/support/api/share/share.ts index a3c97182698..d038afdcaf9 100644 --- a/tests/e2e/support/api/share/share.ts +++ b/tests/e2e/support/api/share/share.ts @@ -21,19 +21,22 @@ export const createShare = async ({ path, shareWith, shareType, - role + role, + name }: { user: User path: string - shareWith: string shareType: string - role: string + shareWith?: string + role?: string + name?: string }): Promise => { const body = new URLSearchParams() body.append('path', path) body.append('shareWith', shareWith) body.append('shareType', shareTypes[shareType]) body.append('role', role) + body.append('name', name) const response = await request({ method: 'POST', diff --git a/tests/e2e/support/objects/app-files/page/shares/withMe.ts b/tests/e2e/support/objects/app-files/page/shares/withMe.ts index 67be1753033..e39a78ca056 100644 --- a/tests/e2e/support/objects/app-files/page/shares/withMe.ts +++ b/tests/e2e/support/objects/app-files/page/shares/withMe.ts @@ -1,8 +1,9 @@ import { Page } from 'playwright' import { Actor } from '../../../../../support/types' -const sharesNavSelector = '//a[@data-nav-name="files-shares"]' -const shareWithMeNavButton = `//a/span[text()='Open "Shared with me"']` +const sharesNavSelector = '//a[@data-nav-name="files-shares-with-me"]' +const openShareWithMeButton = `//a/span[text()='Open "Shared with me"']` +const shareWithMeNavSelector = '//a/span[text()="Shared with me"]' export class WithMe { #page: Page @@ -18,9 +19,9 @@ export class WithMe { async openShareWithMeFromInternalLink(actor: Actor): Promise { const [newTab] = await Promise.all([ this.#page.waitForEvent('popup'), - this.#page.locator(shareWithMeNavButton).click() + this.#page.locator(openShareWithMeButton).click() ]) - await newTab.waitForSelector('#shares-navigation') + await newTab.waitForSelector(shareWithMeNavSelector) await actor.newPage(newTab) } } diff --git a/tests/e2e/support/objects/runtime/session.ts b/tests/e2e/support/objects/runtime/session.ts index 75258824fe7..81031e5bc73 100644 --- a/tests/e2e/support/objects/runtime/session.ts +++ b/tests/e2e/support/objects/runtime/session.ts @@ -15,6 +15,7 @@ class Ocis implements LoginAdapter { async login({ user }: { user: User }): Promise { const { id, password } = user + await this.#page.locator('#oc-login-username').fill(id) await this.#page.locator('#oc-login-password').fill(password) await this.#page.locator('button[type="submit"]').click() From dc4283ea820afaf98dec5726e9aab37f435ba0ee Mon Sep 17 00:00:00 2001 From: Saw-jan Date: Wed, 1 Feb 2023 16:11:09 +0545 Subject: [PATCH 4/4] check if can edit the share --- tests/e2e/cucumber/features/smoke/internalLink.ocis.feature | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/e2e/cucumber/features/smoke/internalLink.ocis.feature b/tests/e2e/cucumber/features/smoke/internalLink.ocis.feature index 51f314c7d02..b25841829a1 100644 --- a/tests/e2e/cucumber/features/smoke/internalLink.ocis.feature +++ b/tests/e2e/cucumber/features/smoke/internalLink.ocis.feature @@ -28,7 +28,5 @@ Feature: internal link share | resource | recipient | type | role | | myfolder | Brian | user | custom_permissions:read | And "Alice" logs out - Then "Brian" should not be able to reshare the following resource - | resource | - | myfolder | + Then "Brian" should see folder "myfolder" but should not be able to edit And "Brian" logs out