refactor(vue): share generated test id helpers

This commit is contained in:
Danila Poyarkov 2026-05-15 13:10:44 +03:00
parent 6b406002dd
commit 698bcde00b
8 changed files with 68 additions and 21 deletions

View file

@ -47,7 +47,15 @@ export { useToolbarState } from '#vue/primitives/Toolbar/useToolbarState'
export { useNodeFontStatus } from '#vue/shared/font-status/use'
export { usePropScrub } from '#vue/controls/prop-scrub/use'
export { toolCursor } from '#vue/editor/tool-cursor'
export { testId, testIdSelector } from '#vue/testing/test-id'
export {
acpPermissionOptionTestId,
testId,
testIdSelector,
toolbarFlyoutItemTestId,
toolbarFlyoutTestId,
toolbarToolTestId,
variablesAddTestId
} from '#vue/testing/test-id'
export { vTestId } from '#vue/testing/v-test-id'
export type {
RequiredTestIdProps,

View file

@ -22,6 +22,26 @@ export function testIdSelector(id: TestId): string {
return `[data-test-id="${cssEscape(id)}"]`
}
export function toolbarToolTestId(tool: string, mobile = false): TestId {
return `${mobile ? 'mobile-' : ''}toolbar-tool-${tool.toLowerCase()}`
}
export function toolbarFlyoutTestId(tool: string, mobile = false): TestId {
return `${mobile ? 'mobile-' : ''}toolbar-flyout-${tool.toLowerCase()}`
}
export function toolbarFlyoutItemTestId(tool: string, mobile = false): TestId {
return `${mobile ? 'mobile-' : ''}toolbar-flyout-item-${tool.toLowerCase()}`
}
export function variablesAddTestId(type: string): TestId {
return `variables-add-${type.toLowerCase()}`
}
export function acpPermissionOptionTestId(kind: string): TestId {
return `acp-permission-option-${kind}`
}
function cssEscape(value: string): string {
return CSS.escape(value)
}

View file

@ -11,7 +11,13 @@ import IconChevronDown from '~icons/lucide/chevron-down'
import { menu } from '@/components/ui/menu'
import ToolButton from '@/components/Toolbar/ToolButton.vue'
import { vTestId, ToolbarItem } from '@open-pencil/vue'
import {
toolbarFlyoutItemTestId,
toolbarFlyoutTestId,
toolbarToolTestId,
vTestId,
ToolbarItem
} from '@open-pencil/vue'
import type { Tool } from '@open-pencil/vue'
import type { EditorToolDef } from '@open-pencil/core/editor'
@ -58,7 +64,7 @@ function activeKeyForTool() {
<div class="flex items-center">
<slot :label="`${toolLabels[activeKeyForTool()]} (${tool.shortcut})`">
<ToolButton
:test-id="`${mobile ? 'mobile-' : ''}toolbar-tool-${activeKeyForTool().toLowerCase()}`"
:test-id="toolbarToolTestId(activeKeyForTool(), mobile)"
:icon="toolIcons[activeKeyForTool()]"
:active="isActiveTool(activeKeyForTool())"
:mobile="mobile"
@ -69,7 +75,7 @@ function activeKeyForTool() {
<DropdownMenuRoot>
<DropdownMenuTrigger as-child>
<button
v-test-id="`${mobile ? 'mobile-' : ''}toolbar-flyout-${tool.key.toLowerCase()}`"
v-test-id="toolbarFlyoutTestId(tool.key, mobile)"
class="flex h-8 w-3 cursor-pointer items-center justify-center border-none transition-colors"
:class="[
mobile ? 'rounded-[6px] select-none' : 'rounded-lg',
@ -93,7 +99,7 @@ function activeKeyForTool() {
:tool="sub"
>
<DropdownMenuItem
v-test-id="`${mobile ? 'mobile-' : ''}toolbar-flyout-item-${sub.toLowerCase()}`"
v-test-id="toolbarFlyoutItemTestId(sub, mobile)"
:class="menu().item({ class: subActive ? 'bg-accent text-white' : undefined })"
@select="actions.select"
>

View file

@ -27,7 +27,7 @@ import {
} from 'reka-ui'
import { FlexRender } from '@tanstack/vue-table'
import { vTestId, useI18n, useVariablesEditor } from '@open-pencil/vue'
import { variablesAddTestId, vTestId, useI18n, useVariablesEditor } from '@open-pencil/vue'
import IconHash from '~icons/lucide/hash'
import IconPalette from '~icons/lucide/palette'
@ -390,7 +390,7 @@ function modeId(columnId: string): string {
v-for="item in variableTypes"
:key="item.type"
:class="menuCls.item"
v-test-id="`variables-add-${item.type.toLowerCase()}`"
v-test-id="variablesAddTestId(item.type)"
@select="ctx.addVariable(item.type)"
>
<component :is="variableTypeIcons[item.type]" :class="menuCls.icon" />

View file

@ -10,7 +10,7 @@ import {
AlertDialogTitle
} from 'reka-ui'
import { computed } from 'vue'
import { vTestId } from '@open-pencil/vue'
import { acpPermissionOptionTestId, vTestId } from '@open-pencil/vue'
import {
currentPermission,
@ -86,7 +86,7 @@ function handleDismiss() {
<AlertDialogAction
v-for="opt in allowOptions"
:key="opt.optionId"
v-test-id="`acp-permission-option-${opt.kind}`"
v-test-id="acpPermissionOptionTestId(opt.kind)"
class="w-full rounded bg-accent px-3 py-1.5 text-xs font-medium text-white hover:bg-accent/90"
@click="respondToPermission(opt.optionId)"
>
@ -96,7 +96,7 @@ function handleDismiss() {
<AlertDialogCancel
v-for="opt in rejectOptions"
:key="opt.optionId"
v-test-id="`acp-permission-option-${opt.kind}`"
v-test-id="acpPermissionOptionTestId(opt.kind)"
class="w-full rounded border border-border bg-canvas px-3 py-1.5 text-xs text-muted hover:bg-hover hover:text-surface"
@click="respondToPermission(opt.optionId)"
>

View file

@ -2,6 +2,7 @@ import { test, expect, type Page } from '@playwright/test'
import { CanvasHelper } from '#tests/helpers/canvas'
import { getPageChildren } from '#tests/helpers/store'
import { toolbarFlyoutItemTestId, toolbarFlyoutTestId } from '#tests/helpers/test-ids'
let page: Page
let canvas: CanvasHelper
@ -20,13 +21,13 @@ test.afterAll(async () => {
})
test('shapes flyout opens', async () => {
await page.getByTestId('toolbar-flyout-rectangle').click()
await expect(page.getByTestId('toolbar-flyout-item-polygon')).toBeVisible()
await page.getByTestId(toolbarFlyoutTestId('RECTANGLE')).click()
await expect(page.getByTestId(toolbarFlyoutItemTestId('POLYGON'))).toBeVisible()
canvas.assertNoErrors()
})
test('Polygon tool creates POLYGON node', async () => {
await page.getByTestId('toolbar-flyout-item-polygon').click()
await page.getByTestId(toolbarFlyoutItemTestId('POLYGON')).click()
await canvas.drag(300, 200, 400, 300)
await canvas.waitForRender()
@ -36,8 +37,8 @@ test('Polygon tool creates POLYGON node', async () => {
})
test('Star tool creates STAR node', async () => {
await page.getByTestId('toolbar-flyout-rectangle').click()
await page.getByTestId('toolbar-flyout-item-star').click()
await page.getByTestId(toolbarFlyoutTestId('RECTANGLE')).click()
await page.getByTestId(toolbarFlyoutItemTestId('STAR')).click()
await canvas.drag(150, 150, 250, 250)
await canvas.waitForRender()
@ -105,8 +106,8 @@ test('Pen close path creates VECTOR with closed region', async () => {
})
test('Frame flyout shows Frame and Section items', async () => {
await page.getByTestId('toolbar-flyout-frame').click()
await expect(page.getByTestId('toolbar-flyout-item-frame')).toBeVisible()
await expect(page.getByTestId('toolbar-flyout-item-section')).toBeVisible()
await page.getByTestId(toolbarFlyoutTestId('FRAME')).click()
await expect(page.getByTestId(toolbarFlyoutItemTestId('FRAME'))).toBeVisible()
await expect(page.getByTestId(toolbarFlyoutItemTestId('SECTION'))).toBeVisible()
canvas.assertNoErrors()
})

View file

@ -1,6 +1,7 @@
import { test, expect, type Page } from '@playwright/test'
import { CanvasHelper } from '#tests/helpers/canvas'
import { variablesAddTestId } from '#tests/helpers/test-ids'
let page: Page
let canvas: CanvasHelper
@ -64,19 +65,19 @@ test('add variable menu creates non-color variable types', async () => {
await canvas.waitForRender()
await page.getByTestId('variables-add-variable').click()
await page.getByTestId('variables-add-float').click()
await page.getByTestId(variablesAddTestId('FLOAT')).click()
await expect(
page.getByTestId('variable-row').filter({ hasText: 'New number' })
).toHaveCount(1)
await page.getByTestId('variables-add-variable').click()
await page.getByTestId('variables-add-string').click()
await page.getByTestId(variablesAddTestId('STRING')).click()
await expect(
page.getByTestId('variable-row').filter({ hasText: 'New text' })
).toHaveCount(1)
await page.getByTestId('variables-add-variable').click()
await page.getByTestId('variables-add-boolean').click()
await page.getByTestId(variablesAddTestId('BOOLEAN')).click()
await expect(
page.getByTestId('variable-row').filter({ hasText: 'New boolean' })
).toHaveCount(1)

11
tests/helpers/test-ids.ts Normal file
View file

@ -0,0 +1,11 @@
export function toolbarFlyoutTestId(tool: string, mobile = false) {
return `${mobile ? 'mobile-' : ''}toolbar-flyout-${tool.toLowerCase()}`
}
export function toolbarFlyoutItemTestId(tool: string, mobile = false) {
return `${mobile ? 'mobile-' : ''}toolbar-flyout-item-${tool.toLowerCase()}`
}
export function variablesAddTestId(type: string) {
return `variables-add-${type.toLowerCase()}`
}