Files
upstream-mirror a774ac673a
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
snapshot of https://github.com/tldraw/tldraw.git (main, 2026-09-23; blobs > 131072B omitted)
2026-09-23 16:12:52 +05:00

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())
}
}