Some checks failed
Deploy analytics worker / Deploy analytics worker to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
i18n upload strings / Upload latest strings (push) Failing after 1s
Deploy bemo / Deploy bemo to ${{ (github.ref == 'refs/heads/bemo-production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
Deploy grafana resources / ${{ github.event_name == 'push' && 'Deploy grafana resources' || 'Validate grafana resources (dry run)' }} (push) Failing after 0s
End to end tests (dotcom) / Check for relevant changes (push) Failing after 0s
End to end tests (examples) / Check for relevant changes (push) Failing after 0s
End to end tests (mermaid readability) / Check for relevant changes (push) Failing after 1s
End to end tests (perf) / Check for relevant changes (push) Failing after 0s
Publish editor extensions / Publish editor extensions (push) Failing after 1s
Publish SDK packages / Remove the publish-packages label (push) Has been skipped
Checks / Tests & checks (push) Has been cancelled
Checks / Build all projects (push) Has been cancelled
Deploy templates / Deploy templates (push) Has been cancelled
End to end tests (dotcom) / End to end tests (dotcom) (push) Has been cancelled
End to end tests (mermaid readability) / End to end tests (mermaid readability) (push) Has been cancelled
End to end tests (perf) / End to end tests (perf) (push) Has been cancelled
Deploy .com / Deploy dotcom to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Has been cancelled
End to end tests (examples) / End to end tests (examples) (push) Has been cancelled
Publish SDK packages / Publish SDK packages (push) Has been cancelled
Publish SDK packages / Tell user released version (push) Has been cancelled
Publish SDK packages / Publishes code templates to separate repositories (push) Has been cancelled
Publish SDK packages / Deploys the template demos with the new SDK version (push) Has been cancelled
170 lines
4.7 KiB
TypeScript
170 lines
4.7 KiB
TypeScript
import type { Locator, Page } from '@playwright/test'
|
|
import { expect, step } from './tla-test'
|
|
|
|
type ShareMenuTab = 'invite' | 'export' | 'publish'
|
|
|
|
export class ShareMenu {
|
|
public readonly shareButton: Locator
|
|
|
|
public readonly exportTabButton: Locator
|
|
public readonly inviteTabButton: Locator
|
|
public readonly publishTabButton: Locator
|
|
public readonly anonShareTabButton: Locator
|
|
|
|
public readonly exportTabPage: Locator
|
|
public readonly inviteTabPage: Locator
|
|
public readonly publishTabPage: Locator
|
|
public readonly anonShareTabPage: Locator
|
|
|
|
public readonly publishChangesButton: Locator
|
|
|
|
public readonly copyLinkButton: Locator
|
|
public readonly exportImageButton: Locator
|
|
public readonly tabs: { anonShare: Locator; invite: Locator; export: Locator; publish: Locator }
|
|
|
|
constructor(public readonly page: Page) {
|
|
this.shareButton = this.page.getByTestId('tla-share-button')
|
|
this.exportTabButton = this.page.getByTestId('tla-share-tab-button-export')
|
|
this.inviteTabButton = this.page.getByTestId('tla-share-tab-button-share')
|
|
this.publishTabButton = this.page.getByTestId('tla-share-tab-button-publish')
|
|
this.anonShareTabButton = this.page.getByTestId('tla-share-tab-button-anon-share')
|
|
|
|
this.exportTabPage = this.page.getByTestId('tla-share-tab-page-export')
|
|
this.inviteTabPage = this.page.getByTestId('tla-share-tab-page-share')
|
|
this.publishTabPage = this.page.getByTestId('tla-share-tab-page-publish')
|
|
this.anonShareTabPage = this.page.getByTestId('tla-share-tab-page-anon-share')
|
|
|
|
this.publishChangesButton = this.page.getByRole('button', {
|
|
name: 'Publish changes',
|
|
exact: true,
|
|
})
|
|
this.copyLinkButton = this.page.getByRole('button', { name: 'Copy link' })
|
|
this.exportImageButton = this.page.getByRole('button', { name: 'Export image' })
|
|
this.tabs = {
|
|
anonShare: this.anonShareTabButton,
|
|
invite: this.inviteTabButton,
|
|
export: this.exportTabButton,
|
|
publish: this.publishTabButton,
|
|
}
|
|
this.shareFile = this.shareFile.bind(this)
|
|
this.unshareFile = this.unshareFile.bind(this)
|
|
this.publishFile = this.publishFile.bind(this)
|
|
this.unpublishFile = this.unpublishFile.bind(this)
|
|
}
|
|
|
|
async open() {
|
|
await this.shareButton.click()
|
|
}
|
|
|
|
async isInviteButtonVisible() {
|
|
return await this.inviteTabButton.isVisible()
|
|
}
|
|
|
|
async share(tab: ShareMenuTab) {
|
|
await this.ensureTabSelected(tab)
|
|
if (!(await this.isToggleChecked())) {
|
|
await this.page.getByRole('switch').check()
|
|
}
|
|
}
|
|
|
|
async unshare(tab: ShareMenuTab) {
|
|
await this.ensureTabSelected(tab)
|
|
if (await this.isToggleChecked()) {
|
|
await this.page.getByRole('switch').uncheck()
|
|
}
|
|
}
|
|
|
|
@step
|
|
async shareFile() {
|
|
await this.share('invite')
|
|
}
|
|
|
|
@step
|
|
async unshareFile() {
|
|
await this.unshare('invite')
|
|
}
|
|
|
|
@step
|
|
async publishFile() {
|
|
await this.share('publish')
|
|
}
|
|
|
|
@step
|
|
async unpublishFile() {
|
|
await this.unshare('publish')
|
|
}
|
|
|
|
async isToggleChecked() {
|
|
return await this.page.getByRole('switch').isChecked()
|
|
}
|
|
|
|
@step
|
|
async copyLink() {
|
|
const sentinel = `__copy_link_pending_${Date.now()}__`
|
|
await this.page.evaluate(async (value) => {
|
|
await navigator.clipboard.writeText(value)
|
|
}, sentinel)
|
|
|
|
await this.copyLinkButton.click()
|
|
|
|
let url = ''
|
|
await expect(async () => {
|
|
url = await this.page.evaluate(async () => await navigator.clipboard.readText())
|
|
expect(url).not.toBe(sentinel)
|
|
expect(url).toBeTruthy()
|
|
const parsed = new URL(url)
|
|
expect(parsed.origin).toBe('http://localhost:3000')
|
|
// Share menu links should point to file/publish routes, not group invite routes.
|
|
expect(parsed.pathname.startsWith('/f/') || parsed.pathname.startsWith('/p/')).toBe(true)
|
|
}).toPass({ timeout: 5000 })
|
|
return url
|
|
}
|
|
|
|
@step
|
|
async openShareMenuAndCopyInviteLink() {
|
|
await this.open()
|
|
await this.inviteTabButton.click()
|
|
await this.ensureTabSelected('invite')
|
|
return await this.copyLink()
|
|
}
|
|
|
|
@step
|
|
async openShareMenuAndCopyPublishedLink() {
|
|
await this.open()
|
|
await this.publishTabButton.click()
|
|
await this.ensureTabSelected('publish')
|
|
return await this.copyLink()
|
|
}
|
|
|
|
@step
|
|
async exportFile() {
|
|
await this.ensureTabSelected('export')
|
|
await this.exportImageButton.click()
|
|
}
|
|
|
|
@step
|
|
async isTabSelected(tab: ShareMenuTab) {
|
|
const attr = await this.tabs[tab].getAttribute('data-active')
|
|
return attr === 'true'
|
|
}
|
|
|
|
@step
|
|
async ensureTabSelected(tab: ShareMenuTab) {
|
|
if (await this.isTabSelected(tab)) return
|
|
const locator = this.tabs[tab]
|
|
await locator.click()
|
|
}
|
|
|
|
@step
|
|
async publishChanges() {
|
|
await this.ensureTabSelected('publish')
|
|
await this.publishChangesButton.click()
|
|
}
|
|
|
|
async getShareType() {
|
|
return (await this.page.waitForSelector('[data-testid="shared-link-type-select"]'))
|
|
.textContent()
|
|
.then((text) => text?.trim())
|
|
}
|
|
}
|