Adding a single E2E test per menu (#2954)
A basic test for each of the menu areas fixes TLD-2251 - [x] `tests` — Changes to any test code only[^2] ### Release Notes - Add a brief release note for your PR here. --------- Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
This commit is contained in:
parent
c0d849e8b5
commit
5db4e9a491
27 changed files with 395 additions and 20 deletions
30
apps/examples/e2e/tests/fixtures/fixtures.ts
vendored
30
apps/examples/e2e/tests/fixtures/fixtures.ts
vendored
|
@ -1,10 +1,20 @@
|
||||||
import { test as base } from '@playwright/test'
|
import { test as base } from '@playwright/test'
|
||||||
|
import { ActionsMenu } from './menus/ActionsMenu'
|
||||||
|
import { HelpMenu } from './menus/HelpMenu'
|
||||||
|
import { MainMenu } from './menus/MainMenu'
|
||||||
|
import { NavigationPanel } from './menus/NavigationPanel'
|
||||||
|
import { PageMenu } from './menus/PageMenu'
|
||||||
import { StylePanel } from './menus/StylePanel'
|
import { StylePanel } from './menus/StylePanel'
|
||||||
import { Toolbar } from './menus/Toolbar'
|
import { Toolbar } from './menus/Toolbar'
|
||||||
|
|
||||||
type Fixtures = {
|
type Fixtures = {
|
||||||
toolbar: Toolbar
|
toolbar: Toolbar
|
||||||
stylePanel: StylePanel
|
stylePanel: StylePanel
|
||||||
|
actionsMenu: ActionsMenu
|
||||||
|
helpMenu: HelpMenu
|
||||||
|
mainMenu: MainMenu
|
||||||
|
pageMenu: PageMenu
|
||||||
|
navigationPanel: NavigationPanel
|
||||||
}
|
}
|
||||||
|
|
||||||
const test = base.extend<Fixtures>({
|
const test = base.extend<Fixtures>({
|
||||||
|
@ -16,6 +26,26 @@ const test = base.extend<Fixtures>({
|
||||||
const stylePanel = new StylePanel(page)
|
const stylePanel = new StylePanel(page)
|
||||||
await use(stylePanel)
|
await use(stylePanel)
|
||||||
},
|
},
|
||||||
|
actionsMenu: async ({ page }, use) => {
|
||||||
|
const actionsMenu = new ActionsMenu(page)
|
||||||
|
await use(actionsMenu)
|
||||||
|
},
|
||||||
|
helpMenu: async ({ page }, use) => {
|
||||||
|
const helpMenu = new HelpMenu(page)
|
||||||
|
await use(helpMenu)
|
||||||
|
},
|
||||||
|
mainMenu: async ({ page }, use) => {
|
||||||
|
const mainMenu = new MainMenu(page)
|
||||||
|
await use(mainMenu)
|
||||||
|
},
|
||||||
|
pageMenu: async ({ page }, use) => {
|
||||||
|
const pagemenu = new PageMenu(page)
|
||||||
|
await use(pagemenu)
|
||||||
|
},
|
||||||
|
navigationPanel: async ({ page }, use) => {
|
||||||
|
const navigationPanel = new NavigationPanel(page)
|
||||||
|
await use(navigationPanel)
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
export default test
|
export default test
|
||||||
|
|
42
apps/examples/e2e/tests/fixtures/menus/ActionsMenu.ts
vendored
Normal file
42
apps/examples/e2e/tests/fixtures/menus/ActionsMenu.ts
vendored
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
import { Locator, Page } from '@playwright/test'
|
||||||
|
|
||||||
|
export class ActionsMenu {
|
||||||
|
readonly quickActions: { [key: string]: Locator }
|
||||||
|
readonly mainActions: { [key: string]: Locator }
|
||||||
|
readonly actionsMenuButton: Locator
|
||||||
|
readonly actionsMenuContent: Locator
|
||||||
|
|
||||||
|
constructor(public readonly page: Page) {
|
||||||
|
this.page = page
|
||||||
|
this.actionsMenuButton = this.page.getByTestId('actions-menu.button')
|
||||||
|
this.actionsMenuContent = this.page.getByTestId('actions-menu.content')
|
||||||
|
this.quickActions = {
|
||||||
|
undo: this.page.getByTestId('quick-actions.undo'),
|
||||||
|
redo: this.page.getByTestId('quick-actions.redo'),
|
||||||
|
delete: this.page.getByTestId('quick-actions.delete'),
|
||||||
|
duplicate: this.page.getByTestId('quick-actions.duplicate'),
|
||||||
|
}
|
||||||
|
this.mainActions = {
|
||||||
|
alignLeft: this.page.getByTestId('actions-menu.align-left'),
|
||||||
|
alignCenterHorizontal: this.page.getByTestId('actions-menu.align-center-horizontal'),
|
||||||
|
alignRight: this.page.getByTestId('actions-menu.align-right'),
|
||||||
|
stretchHorizontal: this.page.getByTestId('actions-menu.stretch-horizontal'),
|
||||||
|
alignTop: this.page.getByTestId('actions-menu.align-top'),
|
||||||
|
alignCenterVertical: this.page.getByTestId('actions-menu.align-center-vertical'),
|
||||||
|
alignBottom: this.page.getByTestId('actions-menu.align-bottom'),
|
||||||
|
stretchVertical: this.page.getByTestId('actions-menu.stretch-vertical'),
|
||||||
|
distributeHorizontal: this.page.getByTestId('actions-menu.distribute-horizontal'),
|
||||||
|
distributeVertical: this.page.getByTestId('actions-menu.distribute-vertical'),
|
||||||
|
stackHorizontal: this.page.getByTestId('actions-menu.stack-horizontal'),
|
||||||
|
stackVertical: this.page.getByTestId('actions-menu.stack-vertical'),
|
||||||
|
sendToBack: this.page.getByTestId('actions-menu.send-to-back'),
|
||||||
|
sendBackward: this.page.getByTestId('actions-menu.send-backward'),
|
||||||
|
bringForward: this.page.getByTestId('actions-menu.bring-forward'),
|
||||||
|
bringToFront: this.page.getByTestId('actions-menu.bring-to-front'),
|
||||||
|
rotateCCW: this.page.getByTestId('actions-menu.rotate-ccw'),
|
||||||
|
rotateCW: this.page.getByTestId('actions-menu.rotate-cw'),
|
||||||
|
editLink: this.page.getByTestId('actions-menu.edit-link'),
|
||||||
|
group: this.page.getByTestId('actions-menu.group'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
34
apps/examples/e2e/tests/fixtures/menus/HelpMenu.ts
vendored
Normal file
34
apps/examples/e2e/tests/fixtures/menus/HelpMenu.ts
vendored
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
import { Locator, Page } from '@playwright/test'
|
||||||
|
|
||||||
|
export class HelpMenu {
|
||||||
|
readonly helpMenuButton: Locator
|
||||||
|
readonly languagesButton: Locator
|
||||||
|
readonly languagesContent: Locator
|
||||||
|
readonly keyboardShortcutsMenu: KeyboardShortcutsMenu
|
||||||
|
readonly linkGroup: { [key: string]: Locator }
|
||||||
|
|
||||||
|
constructor(public readonly page: Page) {
|
||||||
|
this.page = page
|
||||||
|
this.helpMenuButton = this.page.getByTestId('help-menu.button')
|
||||||
|
this.languagesButton = this.page.getByTestId('help-menu-sub.language-button')
|
||||||
|
this.languagesContent = this.page.getByTestId('help-menu-sub.language-content')
|
||||||
|
this.keyboardShortcutsMenu = new KeyboardShortcutsMenu(this.page)
|
||||||
|
this.linkGroup = {
|
||||||
|
github: this.page.getByTestId('help-menu.github'),
|
||||||
|
twitter: this.page.getByTestId('help-menu.twitter'),
|
||||||
|
discord: this.page.getByTestId('help-menu.discord'),
|
||||||
|
about: this.page.getByTestId('help-menu.about'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class KeyboardShortcutsMenu {
|
||||||
|
readonly heading: Locator
|
||||||
|
readonly button: Locator
|
||||||
|
readonly closeButton: Locator
|
||||||
|
|
||||||
|
constructor(private readonly page: Page) {
|
||||||
|
this.heading = this.page.getByRole('dialog').getByText('Keyboard shortcuts')
|
||||||
|
this.button = this.page.getByTestId('help-menu.keyboard-shortcuts-button')
|
||||||
|
this.closeButton = this.page.getByRole('dialog').getByTestId('dialog.close')
|
||||||
|
}
|
||||||
|
}
|
63
apps/examples/e2e/tests/fixtures/menus/MainMenu.ts
vendored
Normal file
63
apps/examples/e2e/tests/fixtures/menus/MainMenu.ts
vendored
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
import { Locator, Page } from '@playwright/test'
|
||||||
|
|
||||||
|
export class MainMenu {
|
||||||
|
readonly mainMenuButton: Locator
|
||||||
|
readonly buttons: { [key: string]: Locator }
|
||||||
|
readonly subMenus: { [key: string]: Locator[] }
|
||||||
|
constructor(public readonly page: Page) {
|
||||||
|
this.page = page
|
||||||
|
this.mainMenuButton = this.page.getByTestId('main-menu.button')
|
||||||
|
this.buttons = {
|
||||||
|
edit: this.page.getByRole('menuitem').getByText('Edit'),
|
||||||
|
object: this.page.getByRole('menuitem').getByText('Object'),
|
||||||
|
view: this.page.getByRole('menuitem').getByText('View'),
|
||||||
|
insertEmbed: this.page.getByRole('menuitem').getByText('Insert Embed'),
|
||||||
|
uploadMedia: this.page.getByRole('menuitem').getByText('Upload Media'),
|
||||||
|
preferences: this.page.getByRole('menuitem').getByText('Preferences'),
|
||||||
|
}
|
||||||
|
this.subMenus = {
|
||||||
|
editSubmenu: [
|
||||||
|
this.page.getByTestId('main-menu-sub.edit-content').getByText('Undo'),
|
||||||
|
this.page.getByTestId('main-menu-sub.edit-content').getByText('Redo'),
|
||||||
|
this.page.getByTestId('main-menu-sub.edit-content').getByText('Cut'),
|
||||||
|
this.page.getByTestId('main-menu-sub.edit-content').getByText('Copy'),
|
||||||
|
this.page.getByTestId('main-menu-sub.edit-content').getByText('Copy as'),
|
||||||
|
this.page.getByTestId('main-menu-sub.edit-content').getByText('Duplicate'),
|
||||||
|
this.page.getByTestId('main-menu-sub.edit-content').getByText('Paste'),
|
||||||
|
this.page.getByTestId('main-menu-sub.edit-content').getByText('Delete'),
|
||||||
|
this.page.getByTestId('main-menu-sub.edit-content').getByText('Select all'),
|
||||||
|
],
|
||||||
|
objectSubmenu: [
|
||||||
|
this.page.getByRole('menuitem').getByText('Export as'),
|
||||||
|
this.page.getByRole('menuitem').getByText('Group'),
|
||||||
|
this.page.getByRole('menuitem').getByText('Ungroup'),
|
||||||
|
this.page.getByRole('menuitem').getByText('Remove frame'),
|
||||||
|
this.page.getByRole('menuitem').getByText('Fit to content'),
|
||||||
|
this.page.getByRole('menuitem').getByText('Toggle auto size'),
|
||||||
|
this.page.getByRole('menuitem').getByText('Edit link'),
|
||||||
|
this.page.getByRole('menuitem').getByText('Convert to Bookmark'),
|
||||||
|
this.page.getByRole('menuitem').getByText('Convert to Embed'),
|
||||||
|
this.page.getByRole('menuitem').getByText('Toggle locked'),
|
||||||
|
this.page.getByRole('menuitem').getByText('Unlock all'),
|
||||||
|
],
|
||||||
|
viewSubmenu: [
|
||||||
|
this.page.getByTestId('main-menu-sub.view-content').getByText('Zoom in'),
|
||||||
|
this.page.getByTestId('main-menu-sub.view-content').getByText('Zoom out'),
|
||||||
|
this.page.getByTestId('main-menu-sub.view-content').getByText('Zoom to 100%'),
|
||||||
|
this.page.getByTestId('main-menu-sub.view-content').getByText('Zoom to fit'),
|
||||||
|
this.page.getByTestId('main-menu-sub.view-content').getByText('Zoom to selection'),
|
||||||
|
],
|
||||||
|
preferencesSubmenu: [
|
||||||
|
this.page.getByTestId('main-menu-sub.preferences-content').getByText('Always snap'),
|
||||||
|
this.page.getByTestId('main-menu-sub.preferences-content').getByText('Tool lock'),
|
||||||
|
this.page.getByTestId('main-menu-sub.preferences-content').getByText('Show grid'),
|
||||||
|
this.page.getByTestId('main-menu-sub.preferences-content').getByText('Dark mode'),
|
||||||
|
this.page.getByTestId('main-menu-sub.preferences-content').getByText('Focus mode'),
|
||||||
|
this.page.getByTestId('main-menu-sub.preferences-content').getByText('Edge scrolling'),
|
||||||
|
this.page.getByTestId('main-menu-sub.preferences-content').getByText('Reduce motion'),
|
||||||
|
this.page.getByTestId('main-menu-sub.preferences-content').getByText('Debug mode'),
|
||||||
|
this.page.getByTestId('main-menu-sub.preferences-content').getByText('Language'),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
apps/examples/e2e/tests/fixtures/menus/NavigationPanel.ts
vendored
Normal file
21
apps/examples/e2e/tests/fixtures/menus/NavigationPanel.ts
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import { Locator, Page } from '@playwright/test'
|
||||||
|
|
||||||
|
export class NavigationPanel {
|
||||||
|
readonly minimap: Locator
|
||||||
|
readonly zoomMenuButton: Locator
|
||||||
|
readonly toggleButton: Locator
|
||||||
|
readonly zoomMenuItems: { [key: string]: Locator }
|
||||||
|
constructor(private readonly page: Page) {
|
||||||
|
this.page = page
|
||||||
|
this.minimap = page.getByLabel('minimap')
|
||||||
|
this.zoomMenuButton = page.getByTestId('minimap.zoom-menu-button')
|
||||||
|
this.toggleButton = page.getByTestId('minimap.toggle-button')
|
||||||
|
this.zoomMenuItems = {
|
||||||
|
zoomIn: page.getByRole('menuitem').getByText('Zoom in'),
|
||||||
|
zoomOut: page.getByRole('menuitem').getByText('Zoom out'),
|
||||||
|
zoomToHundred: page.getByRole('menuitem').getByText('Zoom to 100%'),
|
||||||
|
zoomToFit: page.getByRole('menuitem').getByText('Zoom to fit'),
|
||||||
|
zoomToSelection: page.getByRole('menuitem').getByText('Zoom to selection'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
apps/examples/e2e/tests/fixtures/menus/PageMenu.ts
vendored
Normal file
12
apps/examples/e2e/tests/fixtures/menus/PageMenu.ts
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { Locator, Page } from '@playwright/test'
|
||||||
|
|
||||||
|
export class PageMenu {
|
||||||
|
readonly pagemenuButton: Locator
|
||||||
|
readonly header: Locator
|
||||||
|
|
||||||
|
constructor(public readonly page: Page) {
|
||||||
|
this.page = page
|
||||||
|
this.pagemenuButton = this.page.getByTestId('page-menu.button')
|
||||||
|
this.header = this.page.getByRole('dialog').getByText('Pages')
|
||||||
|
}
|
||||||
|
}
|
20
apps/examples/e2e/tests/test-actions-menu.spec.ts
Normal file
20
apps/examples/e2e/tests/test-actions-menu.spec.ts
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import { expect } from '@playwright/test'
|
||||||
|
import { setup } from '../shared-e2e'
|
||||||
|
import test from './fixtures/fixtures'
|
||||||
|
|
||||||
|
test.describe('actions menu', () => {
|
||||||
|
test.beforeEach(setup)
|
||||||
|
|
||||||
|
test('you can open and close the actions menu', async ({ actionsMenu }) => {
|
||||||
|
const { actionsMenuButton, actionsMenuContent } = actionsMenu
|
||||||
|
await expect(actionsMenuContent).toBeHidden()
|
||||||
|
await actionsMenuButton.click()
|
||||||
|
await expect(actionsMenuContent).toBeVisible()
|
||||||
|
await actionsMenuButton.click()
|
||||||
|
await expect(actionsMenuContent).toBeHidden()
|
||||||
|
})
|
||||||
|
|
||||||
|
// ...
|
||||||
|
// More tests here
|
||||||
|
// ...
|
||||||
|
})
|
|
@ -45,11 +45,11 @@ test.describe.skip('clipboard tests', () => {
|
||||||
expect(await page.evaluate(() => editor.getCurrentPageShapes().length)).toBe(1)
|
expect(await page.evaluate(() => editor.getCurrentPageShapes().length)).toBe(1)
|
||||||
expect(await page.evaluate(() => editor.getSelectedShapes().length)).toBe(1)
|
expect(await page.evaluate(() => editor.getSelectedShapes().length)).toBe(1)
|
||||||
|
|
||||||
await page.getByTestId('main.menu').click()
|
await page.getByTestId('main-menu.button').click()
|
||||||
await page.getByTestId('main-menu-sub-trigger.edit').click()
|
await page.getByTestId('main-menu-sub-trigger.edit').click()
|
||||||
await page.getByTestId('main-menu.copy').click()
|
await page.getByTestId('main-menu.copy').click()
|
||||||
await sleep(100)
|
await sleep(100)
|
||||||
await page.getByTestId('main.menu').click()
|
await page.getByTestId('main-menu.button').click()
|
||||||
await page.getByTestId('main-menu-sub-trigger.edit').click()
|
await page.getByTestId('main-menu-sub-trigger.edit').click()
|
||||||
await page.getByTestId('main-menu.paste').click()
|
await page.getByTestId('main-menu.paste').click()
|
||||||
|
|
||||||
|
|
41
apps/examples/e2e/tests/test-help-menu.spec.ts
Normal file
41
apps/examples/e2e/tests/test-help-menu.spec.ts
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
import { expect } from '@playwright/test'
|
||||||
|
import { setup } from '../shared-e2e'
|
||||||
|
import test from './fixtures/fixtures'
|
||||||
|
|
||||||
|
test.describe('help menu', () => {
|
||||||
|
test.beforeEach(setup)
|
||||||
|
|
||||||
|
test('you can open and close the menus', async ({ helpMenu, isMobile }) => {
|
||||||
|
// No help menu on mobile
|
||||||
|
|
||||||
|
const { helpMenuButton, languagesButton, keyboardShortcutsMenu, languagesContent } = helpMenu
|
||||||
|
|
||||||
|
test.skip(isMobile, 'only run on desktop')
|
||||||
|
await test.step('open help menu', async () => {
|
||||||
|
await expect(languagesButton).toBeHidden()
|
||||||
|
await expect(keyboardShortcutsMenu.button).toBeHidden()
|
||||||
|
await helpMenuButton.click()
|
||||||
|
await expect(languagesButton).toBeVisible()
|
||||||
|
await expect(keyboardShortcutsMenu.button).toBeVisible()
|
||||||
|
})
|
||||||
|
await test.step('hover languages submenu', async () => {
|
||||||
|
await expect(languagesContent).toBeHidden()
|
||||||
|
await languagesButton.hover()
|
||||||
|
await expect(languagesContent).toBeVisible()
|
||||||
|
})
|
||||||
|
await test.step('open the keyboard shortcuts menu', async () => {
|
||||||
|
await expect(keyboardShortcutsMenu.heading).toBeHidden()
|
||||||
|
await keyboardShortcutsMenu.button.click()
|
||||||
|
await expect(keyboardShortcutsMenu.heading).toBeVisible()
|
||||||
|
})
|
||||||
|
await test.step('close the keyboard shortcuts menu', async () => {
|
||||||
|
await keyboardShortcutsMenu.closeButton.click()
|
||||||
|
await expect(keyboardShortcutsMenu.heading).toBeHidden()
|
||||||
|
await expect(languagesButton).toBeHidden()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// ...
|
||||||
|
// More tests here
|
||||||
|
// ...
|
||||||
|
})
|
44
apps/examples/e2e/tests/test-main-menu.spec.ts
Normal file
44
apps/examples/e2e/tests/test-main-menu.spec.ts
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
import { expect } from '@playwright/test'
|
||||||
|
import { setup } from '../shared-e2e'
|
||||||
|
import test from './fixtures/fixtures'
|
||||||
|
|
||||||
|
test.describe('help menu', () => {
|
||||||
|
test.beforeEach(setup)
|
||||||
|
|
||||||
|
test('you can open and close the menu', async ({ mainMenu, page }) => {
|
||||||
|
const { mainMenuButton, buttons } = mainMenu
|
||||||
|
const { editSubmenu, viewSubmenu, preferencesSubmenu } = mainMenu.subMenus
|
||||||
|
const submenus = [
|
||||||
|
{ name: 'preferences', submenu: preferencesSubmenu, button: buttons.preferences },
|
||||||
|
{ name: 'view', submenu: viewSubmenu, button: buttons.view },
|
||||||
|
{ name: 'edit', submenu: editSubmenu, button: buttons.edit },
|
||||||
|
]
|
||||||
|
|
||||||
|
await test.step('open main menu', async () => {
|
||||||
|
await expect(buttons.edit).toBeHidden()
|
||||||
|
await mainMenuButton.click()
|
||||||
|
await expect(buttons.edit).toBeVisible()
|
||||||
|
})
|
||||||
|
for (const submenu of submenus) {
|
||||||
|
await test.step(`hovering opens ${submenu.name} submenu`, async () => {
|
||||||
|
await expect(submenu.submenu[0]).toBeHidden()
|
||||||
|
await submenu.button.hover()
|
||||||
|
await expect(submenu.submenu[0]).toBeVisible()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
await test.step('close main menu', async () => {
|
||||||
|
// close the menu by clicking the main menu button again
|
||||||
|
await mainMenuButton.click()
|
||||||
|
await expect(buttons.edit).toBeHidden()
|
||||||
|
// open the menu again
|
||||||
|
await mainMenuButton.click()
|
||||||
|
// click somewhere on the canvas to close the menu
|
||||||
|
await page.mouse.click(250, 150)
|
||||||
|
await expect(buttons.edit).toBeHidden()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// ...
|
||||||
|
// More tests here
|
||||||
|
// ...
|
||||||
|
})
|
33
apps/examples/e2e/tests/test-navigation-panel.spec.ts
Normal file
33
apps/examples/e2e/tests/test-navigation-panel.spec.ts
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import { expect } from '@playwright/test'
|
||||||
|
import { setup } from '../shared-e2e'
|
||||||
|
import test from './fixtures/fixtures'
|
||||||
|
|
||||||
|
test.describe('navigationPanel', () => {
|
||||||
|
test.beforeEach(setup)
|
||||||
|
|
||||||
|
test('you can open and close the zoom menu', async ({ navigationPanel, isMobile }) => {
|
||||||
|
// no navigationPanel on mobile
|
||||||
|
test.skip(isMobile)
|
||||||
|
const { zoomMenuButton } = navigationPanel
|
||||||
|
const { zoomIn } = navigationPanel.zoomMenuItems
|
||||||
|
await expect(zoomIn).toBeHidden()
|
||||||
|
await zoomMenuButton.click()
|
||||||
|
await expect(zoomIn).toBeVisible()
|
||||||
|
await zoomMenuButton.click()
|
||||||
|
await expect(zoomIn).toBeHidden()
|
||||||
|
})
|
||||||
|
test('you can toggle the minimap', async ({ navigationPanel, isMobile }) => {
|
||||||
|
// no navigationPanel on mobile
|
||||||
|
test.skip(isMobile)
|
||||||
|
const { minimap, toggleButton } = navigationPanel
|
||||||
|
await expect(minimap).toBeHidden()
|
||||||
|
await toggleButton.click()
|
||||||
|
await expect(minimap).toBeVisible()
|
||||||
|
await toggleButton.click()
|
||||||
|
await expect(minimap).toBeHidden()
|
||||||
|
})
|
||||||
|
|
||||||
|
// ...
|
||||||
|
// More tests here
|
||||||
|
// ...
|
||||||
|
})
|
20
apps/examples/e2e/tests/test-page-menu.spec.ts
Normal file
20
apps/examples/e2e/tests/test-page-menu.spec.ts
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import { expect } from '@playwright/test'
|
||||||
|
import { setup } from '../shared-e2e'
|
||||||
|
import test from './fixtures/fixtures'
|
||||||
|
|
||||||
|
test.describe('page menu', () => {
|
||||||
|
test.beforeEach(setup)
|
||||||
|
|
||||||
|
test('you can open and close the page menu', async ({ pageMenu }) => {
|
||||||
|
const { pagemenuButton, header } = pageMenu
|
||||||
|
await expect(header).toBeHidden()
|
||||||
|
await pagemenuButton.click()
|
||||||
|
await expect(header).toBeVisible()
|
||||||
|
await pagemenuButton.click()
|
||||||
|
await expect(header).toBeHidden()
|
||||||
|
})
|
||||||
|
|
||||||
|
// ...
|
||||||
|
// More tests here
|
||||||
|
// ...
|
||||||
|
})
|
|
@ -1479,7 +1479,7 @@ export function TldrawUiDropdownMenuRoot({ id, children, modal, debugOpen, }: TL
|
||||||
export function TldrawUiDropdownMenuSub({ id, children }: TLUiDropdownMenuSubProps): JSX_2.Element;
|
export function TldrawUiDropdownMenuSub({ id, children }: TLUiDropdownMenuSubProps): JSX_2.Element;
|
||||||
|
|
||||||
// @public (undocumented)
|
// @public (undocumented)
|
||||||
export function TldrawUiDropdownMenuSubTrigger({ label, title, disabled, }: TLUiDropdownMenuSubTriggerProps): JSX_2.Element;
|
export function TldrawUiDropdownMenuSubTrigger({ id, label, title, disabled, }: TLUiDropdownMenuSubTriggerProps): JSX_2.Element;
|
||||||
|
|
||||||
// @public (undocumented)
|
// @public (undocumented)
|
||||||
export function TldrawUiDropdownMenuTrigger({ children, ...rest }: TLUiDropdownMenuTriggerProps): JSX_2.Element;
|
export function TldrawUiDropdownMenuTrigger({ children, ...rest }: TLUiDropdownMenuTriggerProps): JSX_2.Element;
|
||||||
|
@ -1910,7 +1910,7 @@ export interface TLUiEventMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
// @public (undocumented)
|
// @public (undocumented)
|
||||||
export type TLUiEventSource = 'actions-menu' | 'context-menu' | 'debug-panel' | 'dialog' | 'document-name' | 'export-menu' | 'help-menu' | 'helper-buttons' | 'kbd' | 'menu' | 'navigation-zone' | 'page-menu' | 'people-menu' | 'quick-actions' | 'share-menu' | 'style-panel' | 'toolbar' | 'unknown' | 'zoom-menu';
|
export type TLUiEventSource = 'actions-menu' | 'context-menu' | 'debug-panel' | 'dialog' | 'document-name' | 'export-menu' | 'help-menu' | 'helper-buttons' | 'kbd' | 'main-menu' | 'menu' | 'navigation-zone' | 'page-menu' | 'people-menu' | 'quick-actions' | 'share-menu' | 'style-panel' | 'toolbar' | 'unknown' | 'zoom-menu';
|
||||||
|
|
||||||
// @public (undocumented)
|
// @public (undocumented)
|
||||||
export type TLUiHelperButtonsProps = {
|
export type TLUiHelperButtonsProps = {
|
||||||
|
|
|
@ -17517,7 +17517,7 @@
|
||||||
"excerptTokens": [
|
"excerptTokens": [
|
||||||
{
|
{
|
||||||
"kind": "Content",
|
"kind": "Content",
|
||||||
"text": "export declare function TldrawUiDropdownMenuSubTrigger({ label, title, disabled, }: "
|
"text": "export declare function TldrawUiDropdownMenuSubTrigger({ id, label, title, disabled, }: "
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": "Reference",
|
"kind": "Reference",
|
||||||
|
@ -17551,7 +17551,7 @@
|
||||||
"overloadIndex": 1,
|
"overloadIndex": 1,
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"parameterName": "{ label, title, disabled, }",
|
"parameterName": "{ id, label, title, disabled, }",
|
||||||
"parameterTypeTokenRange": {
|
"parameterTypeTokenRange": {
|
||||||
"startIndex": 1,
|
"startIndex": 1,
|
||||||
"endIndex": 2
|
"endIndex": 2
|
||||||
|
@ -22024,7 +22024,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": "Content",
|
"kind": "Content",
|
||||||
"text": "'actions-menu' | 'context-menu' | 'debug-panel' | 'dialog' | 'document-name' | 'export-menu' | 'help-menu' | 'helper-buttons' | 'kbd' | 'menu' | 'navigation-zone' | 'page-menu' | 'people-menu' | 'quick-actions' | 'share-menu' | 'style-panel' | 'toolbar' | 'unknown' | 'zoom-menu'"
|
"text": "'actions-menu' | 'context-menu' | 'debug-panel' | 'dialog' | 'document-name' | 'export-menu' | 'help-menu' | 'helper-buttons' | 'kbd' | 'main-menu' | 'menu' | 'navigation-zone' | 'page-menu' | 'people-menu' | 'quick-actions' | 'share-menu' | 'style-panel' | 'toolbar' | 'unknown' | 'zoom-menu'"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": "Content",
|
"kind": "Content",
|
||||||
|
|
|
@ -47,7 +47,7 @@ export const DefaultActionsMenu = memo(function DefaultActionsMenu({
|
||||||
<TldrawUiPopoverTrigger>
|
<TldrawUiPopoverTrigger>
|
||||||
<TldrawUiButton
|
<TldrawUiButton
|
||||||
type="icon"
|
type="icon"
|
||||||
data-testid="main.action-menu"
|
data-testid="actions-menu.button"
|
||||||
title={msg('actions-menu.title')}
|
title={msg('actions-menu.title')}
|
||||||
>
|
>
|
||||||
<TldrawUiButtonIcon icon="dots-vertical" small />
|
<TldrawUiButtonIcon icon="dots-vertical" small />
|
||||||
|
@ -57,7 +57,7 @@ export const DefaultActionsMenu = memo(function DefaultActionsMenu({
|
||||||
side={breakpoint >= PORTRAIT_BREAKPOINT.TABLET ? 'bottom' : 'top'}
|
side={breakpoint >= PORTRAIT_BREAKPOINT.TABLET ? 'bottom' : 'top'}
|
||||||
sideOffset={6}
|
sideOffset={6}
|
||||||
>
|
>
|
||||||
<div className="tlui-actions-menu tlui-buttons__grid">
|
<div className="tlui-actions-menu tlui-buttons__grid" data-testid="actions-menu.content">
|
||||||
<TldrawUiMenuContextProvider type="icons" sourceId="actions-menu">
|
<TldrawUiMenuContextProvider type="icons" sourceId="actions-menu">
|
||||||
{content}
|
{content}
|
||||||
</TldrawUiMenuContextProvider>
|
</TldrawUiMenuContextProvider>
|
||||||
|
|
|
@ -33,7 +33,7 @@ export const DefaultHelpMenu = memo(function DefaultHelpMenu({ children }: TLUiH
|
||||||
<div className="tlui-help-menu">
|
<div className="tlui-help-menu">
|
||||||
<TldrawUiDropdownMenuRoot id="help menu">
|
<TldrawUiDropdownMenuRoot id="help menu">
|
||||||
<TldrawUiDropdownMenuTrigger>
|
<TldrawUiDropdownMenuTrigger>
|
||||||
<TldrawUiButton type="help" title={msg('help-menu.title')}>
|
<TldrawUiButton type="help" title={msg('help-menu.title')} data-testid="help-menu.button">
|
||||||
<TldrawUiButtonIcon icon="question-mark" small />
|
<TldrawUiButtonIcon icon="question-mark" small />
|
||||||
</TldrawUiButton>
|
</TldrawUiButton>
|
||||||
</TldrawUiDropdownMenuTrigger>
|
</TldrawUiDropdownMenuTrigger>
|
||||||
|
|
|
@ -21,7 +21,7 @@ export function KeyboardShortcutsMenuItem() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TldrawUiMenuItem
|
<TldrawUiMenuItem
|
||||||
id="keyboard-shortcuts"
|
id="keyboard-shortcuts-button"
|
||||||
label="help-menu.keyboard-shortcuts"
|
label="help-menu.keyboard-shortcuts"
|
||||||
readonlyOk
|
readonlyOk
|
||||||
onSelect={() => {
|
onSelect={() => {
|
||||||
|
|
|
@ -27,7 +27,7 @@ export const DefaultMainMenu = memo(function DefaultMainMenu({ children }: TLUiM
|
||||||
return (
|
return (
|
||||||
<_Dropdown.Root dir="ltr" open={isOpen} onOpenChange={onOpenChange} modal={false}>
|
<_Dropdown.Root dir="ltr" open={isOpen} onOpenChange={onOpenChange} modal={false}>
|
||||||
<_Dropdown.Trigger asChild dir="ltr">
|
<_Dropdown.Trigger asChild dir="ltr">
|
||||||
<TldrawUiButton type="icon" data-testid="main.menu" title={msg('menu.title')}>
|
<TldrawUiButton type="icon" data-testid="main-menu.button" title={msg('menu.title')}>
|
||||||
<TldrawUiButtonIcon icon="menu" small />
|
<TldrawUiButtonIcon icon="menu" small />
|
||||||
</TldrawUiButton>
|
</TldrawUiButton>
|
||||||
</_Dropdown.Trigger>
|
</_Dropdown.Trigger>
|
||||||
|
@ -40,7 +40,7 @@ export const DefaultMainMenu = memo(function DefaultMainMenu({ children }: TLUiM
|
||||||
alignOffset={0}
|
alignOffset={0}
|
||||||
sideOffset={6}
|
sideOffset={6}
|
||||||
>
|
>
|
||||||
<TldrawUiMenuContextProvider type="menu" sourceId="menu">
|
<TldrawUiMenuContextProvider type="menu" sourceId="main-menu">
|
||||||
{content}
|
{content}
|
||||||
</TldrawUiMenuContextProvider>
|
</TldrawUiMenuContextProvider>
|
||||||
</_Dropdown.Content>
|
</_Dropdown.Content>
|
||||||
|
|
|
@ -221,6 +221,8 @@ export function DefaultMinimap() {
|
||||||
return (
|
return (
|
||||||
<div className="tlui-minimap">
|
<div className="tlui-minimap">
|
||||||
<canvas
|
<canvas
|
||||||
|
role="img"
|
||||||
|
aria-label="minimap"
|
||||||
ref={rCanvas}
|
ref={rCanvas}
|
||||||
className="tlui-minimap__canvas"
|
className="tlui-minimap__canvas"
|
||||||
onDoubleClick={onDoubleClick}
|
onDoubleClick={onDoubleClick}
|
||||||
|
|
|
@ -38,7 +38,7 @@ export const DefaultNavigationPanel = memo(function DefaultNavigationPanel() {
|
||||||
{Minimap && (
|
{Minimap && (
|
||||||
<TldrawUiButton
|
<TldrawUiButton
|
||||||
type="icon"
|
type="icon"
|
||||||
data-testid="minimap.toggle"
|
data-testid="minimap.toggle-button"
|
||||||
title={msg('navigation-zone.toggle-minimap')}
|
title={msg('navigation-zone.toggle-minimap')}
|
||||||
className="tlui-navigation-panel__toggle"
|
className="tlui-navigation-panel__toggle"
|
||||||
onClick={toggleMinimap}
|
onClick={toggleMinimap}
|
||||||
|
@ -69,7 +69,7 @@ export const DefaultNavigationPanel = memo(function DefaultNavigationPanel() {
|
||||||
{Minimap && (
|
{Minimap && (
|
||||||
<TldrawUiButton
|
<TldrawUiButton
|
||||||
type="icon"
|
type="icon"
|
||||||
data-testid="minimap.toggle"
|
data-testid="minimap.toggle-button"
|
||||||
title={msg('navigation-zone.toggle-minimap')}
|
title={msg('navigation-zone.toggle-minimap')}
|
||||||
className="tlui-navigation-panel__toggle"
|
className="tlui-navigation-panel__toggle"
|
||||||
onClick={toggleMinimap}
|
onClick={toggleMinimap}
|
||||||
|
|
|
@ -263,7 +263,12 @@ export const DefaultPageMenu = memo(function DefaultPageMenu() {
|
||||||
return (
|
return (
|
||||||
<TldrawUiPopover id="pages" onOpenChange={onOpenChange} open={isOpen}>
|
<TldrawUiPopover id="pages" onOpenChange={onOpenChange} open={isOpen}>
|
||||||
<TldrawUiPopoverTrigger data-testid="main.page-menu">
|
<TldrawUiPopoverTrigger data-testid="main.page-menu">
|
||||||
<TldrawUiButton type="menu" title={currentPage.name} className="tlui-page-menu__trigger">
|
<TldrawUiButton
|
||||||
|
type="menu"
|
||||||
|
title={currentPage.name}
|
||||||
|
data-testid="page-menu.button"
|
||||||
|
className="tlui-page-menu__trigger"
|
||||||
|
>
|
||||||
<div className="tlui-page-menu__name">{currentPage.name}</div>
|
<div className="tlui-page-menu__name">{currentPage.name}</div>
|
||||||
<TldrawUiButtonIcon icon="chevron-down" small />
|
<TldrawUiButtonIcon icon="chevron-down" small />
|
||||||
</TldrawUiButton>
|
</TldrawUiButton>
|
||||||
|
|
|
@ -64,7 +64,7 @@ const ZoomTriggerButton = forwardRef<HTMLButtonElement, any>(
|
||||||
{...props}
|
{...props}
|
||||||
type="icon"
|
type="icon"
|
||||||
title={`${msg('navigation-zone.zoom')}`}
|
title={`${msg('navigation-zone.zoom')}`}
|
||||||
data-testid="minimap.zoom-menu"
|
data-testid="minimap.zoom-menu-button"
|
||||||
className={
|
className={
|
||||||
breakpoint < PORTRAIT_BREAKPOINT.TABLET_SM
|
breakpoint < PORTRAIT_BREAKPOINT.TABLET_SM
|
||||||
? 'tlui-zoom-menu__button'
|
? 'tlui-zoom-menu__button'
|
||||||
|
|
|
@ -115,6 +115,7 @@ export type TLUiDropdownMenuSubTriggerProps = {
|
||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
export function TldrawUiDropdownMenuSubTrigger({
|
export function TldrawUiDropdownMenuSubTrigger({
|
||||||
|
id,
|
||||||
label,
|
label,
|
||||||
title,
|
title,
|
||||||
disabled,
|
disabled,
|
||||||
|
@ -122,6 +123,7 @@ export function TldrawUiDropdownMenuSubTrigger({
|
||||||
return (
|
return (
|
||||||
<_DropdownMenu.SubTrigger dir="ltr" asChild disabled={disabled}>
|
<_DropdownMenu.SubTrigger dir="ltr" asChild disabled={disabled}>
|
||||||
<TldrawUiButton
|
<TldrawUiButton
|
||||||
|
data-testid={id}
|
||||||
type="menu"
|
type="menu"
|
||||||
className="tlui-menu__submenu__trigger"
|
className="tlui-menu__submenu__trigger"
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
@ -145,6 +147,7 @@ export type TLUiDropdownMenuSubContentProps = {
|
||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
export function TldrawUiDropdownMenuSubContent({
|
export function TldrawUiDropdownMenuSubContent({
|
||||||
|
id,
|
||||||
alignOffset = -1,
|
alignOffset = -1,
|
||||||
sideOffset = -4,
|
sideOffset = -4,
|
||||||
size = 'small',
|
size = 'small',
|
||||||
|
@ -154,6 +157,7 @@ export function TldrawUiDropdownMenuSubContent({
|
||||||
return (
|
return (
|
||||||
<_DropdownMenu.Portal container={container}>
|
<_DropdownMenu.Portal container={container}>
|
||||||
<_DropdownMenu.SubContent
|
<_DropdownMenu.SubContent
|
||||||
|
data-testid={id}
|
||||||
className="tlui-menu tlui-menu__submenu__content"
|
className="tlui-menu tlui-menu__submenu__content"
|
||||||
alignOffset={alignOffset}
|
alignOffset={alignOffset}
|
||||||
sideOffset={sideOffset}
|
sideOffset={sideOffset}
|
||||||
|
|
|
@ -14,7 +14,7 @@ export type TldrawUiMenuContextType =
|
||||||
const menuContext = createContext<{
|
const menuContext = createContext<{
|
||||||
type: TldrawUiMenuContextType
|
type: TldrawUiMenuContextType
|
||||||
sourceId: TLUiEventSource
|
sourceId: TLUiEventSource
|
||||||
}>({ type: 'menu', sourceId: 'menu' })
|
}>({ type: 'menu', sourceId: 'main-menu' })
|
||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
export function useTldrawUiMenuContext() {
|
export function useTldrawUiMenuContext() {
|
||||||
|
|
|
@ -50,12 +50,15 @@ export function TldrawUiMenuSubmenu<Translation extends string = string>({
|
||||||
return (
|
return (
|
||||||
<TldrawUiDropdownMenuSub id={`${sourceId}-sub.${id}`}>
|
<TldrawUiDropdownMenuSub id={`${sourceId}-sub.${id}`}>
|
||||||
<TldrawUiDropdownMenuSubTrigger
|
<TldrawUiDropdownMenuSubTrigger
|
||||||
id={`${sourceId}-sub.${id}`}
|
id={`${sourceId}-sub.${labelStr ? labelStr.toLowerCase() + '-button' : ''}`}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
label={labelStr!}
|
label={labelStr!}
|
||||||
title={labelStr!}
|
title={labelStr!}
|
||||||
/>
|
/>
|
||||||
<TldrawUiDropdownMenuSubContent id={`${sourceId}-sub-content.${id}`} size={size}>
|
<TldrawUiDropdownMenuSubContent
|
||||||
|
id={`${sourceId}-sub.${labelStr ? labelStr.toLowerCase() + '-content' : ''}`}
|
||||||
|
size={size}
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</TldrawUiDropdownMenuSubContent>
|
</TldrawUiDropdownMenuSubContent>
|
||||||
</TldrawUiDropdownMenuSub>
|
</TldrawUiDropdownMenuSub>
|
||||||
|
|
|
@ -3,6 +3,7 @@ import * as React from 'react'
|
||||||
/** @public */
|
/** @public */
|
||||||
export type TLUiEventSource =
|
export type TLUiEventSource =
|
||||||
| 'menu'
|
| 'menu'
|
||||||
|
| 'main-menu'
|
||||||
| 'context-menu'
|
| 'context-menu'
|
||||||
| 'zoom-menu'
|
| 'zoom-menu'
|
||||||
| 'document-name'
|
| 'document-name'
|
||||||
|
|
Loading…
Reference in a new issue