2023-11-27 18:48:37 +03:00
|
|
|
import { type Locator, type Page } from '@playwright/test'
|
|
|
|
import cssEscape from 'css.escape'
|
|
|
|
|
|
|
|
// ==============
|
|
|
|
// === Filter ===
|
|
|
|
// ==============
|
|
|
|
|
|
|
|
class Filter {
|
|
|
|
constructor(public selector = '') {}
|
|
|
|
|
|
|
|
visible<T extends { selector: string }>(this: T): Omit<T, 'visible'> {
|
|
|
|
return new Filter(this.selector + ':visible') as any
|
|
|
|
}
|
|
|
|
|
|
|
|
first<T extends { selector: string }>(this: T): Omit<T, 'first' | 'last'> {
|
|
|
|
return new Filter(this.selector + ':first') as any
|
|
|
|
}
|
|
|
|
|
|
|
|
last<T extends { selector: string }>(this: T): Omit<T, 'first' | 'last'> {
|
|
|
|
return new Filter(this.selector + ':last') as any
|
|
|
|
}
|
|
|
|
|
|
|
|
id<T extends { selector: string }>(this: T, id: string): Omit<T, 'id'> {
|
|
|
|
return new Filter(this.selector + '#' + cssEscape(id)) as any
|
|
|
|
}
|
|
|
|
|
|
|
|
class(...classes: string[]) {
|
|
|
|
return new Filter(this.selector + '.' + classes.map(cssEscape).join('.'))
|
|
|
|
}
|
|
|
|
|
|
|
|
toString() {
|
|
|
|
return this.selector
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ================
|
|
|
|
// === Locators ===
|
|
|
|
// ================
|
|
|
|
|
|
|
|
// === Button locators ===
|
|
|
|
|
|
|
|
function or(a: (page: Locator | Page) => Locator, b: (page: Locator | Page) => Locator) {
|
|
|
|
return (page: Locator | Page) => a(page).or(b(page))
|
|
|
|
}
|
|
|
|
|
|
|
|
export function playOrOpenProjectButton(page: Locator | Page) {
|
|
|
|
return page.getByAltText('Open in editor')
|
|
|
|
}
|
|
|
|
|
|
|
|
// === Auto-evaluation ===
|
|
|
|
|
|
|
|
export function enableAutoEvaluationButton(page: Locator | Page) {
|
|
|
|
return page.getByAltText('Enable auto-evaluation')
|
|
|
|
}
|
|
|
|
|
|
|
|
export function disableAutoEvaluationButton(page: Locator | Page) {
|
|
|
|
return page.getByAltText('Disable auto-evaluation')
|
|
|
|
}
|
|
|
|
|
|
|
|
export const toggleAutoEvaluationButton = or(
|
|
|
|
enableAutoEvaluationButton,
|
|
|
|
disableAutoEvaluationButton,
|
|
|
|
)
|
|
|
|
|
|
|
|
// === Documentation ===
|
|
|
|
|
|
|
|
export function showDocumentationButton(page: Locator | Page) {
|
|
|
|
return page.getByAltText('Show documentation')
|
|
|
|
}
|
|
|
|
|
|
|
|
export function hideDocumentationButton(page: Locator | Page) {
|
|
|
|
return page.getByAltText('Hide documentation')
|
|
|
|
}
|
|
|
|
|
|
|
|
export const toggleDocumentationButton = or(showDocumentationButton, hideDocumentationButton)
|
|
|
|
|
|
|
|
// === Visualization ===
|
|
|
|
|
|
|
|
export function showVisualizationButton(page: Locator | Page) {
|
|
|
|
return page.getByAltText('Show visualization')
|
|
|
|
}
|
|
|
|
|
|
|
|
export function hideVisualizationButton(page: Locator | Page) {
|
|
|
|
return page.getByAltText('Hide visualization')
|
|
|
|
}
|
|
|
|
|
|
|
|
export const toggleVisualizationButton = or(showVisualizationButton, hideVisualizationButton)
|
|
|
|
|
|
|
|
// === Visualization selector ===
|
|
|
|
|
|
|
|
export function showVisualizationSelectorButton(page: Locator | Page) {
|
|
|
|
return page.getByAltText('Show visualization selector')
|
|
|
|
}
|
|
|
|
|
|
|
|
export function hideVisualizationSelectorButton(page: Locator | Page) {
|
|
|
|
return page.getByAltText('Hide visualization selector')
|
|
|
|
}
|
|
|
|
|
|
|
|
export const toggleVisualizationSelectorButton = or(
|
|
|
|
showVisualizationSelectorButton,
|
|
|
|
hideVisualizationSelectorButton,
|
|
|
|
)
|
|
|
|
|
|
|
|
// === Fullscreen ===
|
|
|
|
|
|
|
|
export function enterFullscreenButton(page: Locator | Page) {
|
|
|
|
return page.getByAltText('Enter fullscreen')
|
|
|
|
}
|
|
|
|
|
|
|
|
export function exitFullscreenButton(page: Locator | Page) {
|
|
|
|
return page.getByAltText('Exit fullscreen')
|
|
|
|
}
|
|
|
|
|
|
|
|
export const toggleFullscreenButton = or(enterFullscreenButton, exitFullscreenButton)
|
|
|
|
|
|
|
|
// === Data locators ===
|
|
|
|
|
|
|
|
type SanitizeClassName<T extends string> = T extends `${infer A}.${infer B}`
|
|
|
|
? SanitizeClassName<`${A}${B}`>
|
|
|
|
: T extends `${infer A} ${infer B}`
|
|
|
|
? SanitizeClassName<`${A}${B}`>
|
|
|
|
: T
|
|
|
|
|
|
|
|
function componentLocator<T extends string>(className: SanitizeClassName<T>) {
|
|
|
|
return (page: Locator | Page, filter?: (f: Filter) => { selector: string }) => {
|
|
|
|
return page.locator(`.${className}${filter?.(new Filter()) ?? ''}`)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export const graphEditor = componentLocator('GraphEditor')
|
|
|
|
export const graphNode = componentLocator('GraphNode')
|
2024-01-03 12:12:38 +03:00
|
|
|
export function graphNodeByBinding(page: Locator | Page, binding: string) {
|
|
|
|
return graphNode(page).filter({ has: page.locator('.binding').and(page.getByText(binding)) })
|
|
|
|
}
|
2023-11-27 18:48:37 +03:00
|
|
|
// @ts-expect-error
|
|
|
|
export const anyVisualization = componentLocator('GraphVisualization > *')
|
|
|
|
export const circularMenu = componentLocator('CircularMenu')
|
2024-01-03 12:12:38 +03:00
|
|
|
export const addNewNodeButton = componentLocator('PlusButton')
|
2023-11-27 18:48:37 +03:00
|
|
|
export const componentBrowser = componentLocator('ComponentBrowser')
|
2024-01-29 13:37:44 +03:00
|
|
|
export const nodeOutputPort = componentLocator('outputPortHoverArea')
|
2023-11-27 18:48:37 +03:00
|
|
|
|
|
|
|
export function componentBrowserEntry(
|
|
|
|
page: Locator | Page,
|
|
|
|
filter?: (f: Filter) => { selector: string },
|
|
|
|
) {
|
2023-12-12 17:27:40 +03:00
|
|
|
return page.locator(
|
|
|
|
`.ComponentBrowser .list-variant:not(.selected) .component${filter?.(new Filter()) ?? ''}`,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
export function componentBrowserSelectedEntry(
|
|
|
|
page: Locator | Page,
|
|
|
|
filter?: (f: Filter) => { selector: string },
|
|
|
|
) {
|
|
|
|
return page.locator(
|
|
|
|
`.ComponentBrowser .list-variant.selected .component${filter?.(new Filter()) ?? ''}`,
|
|
|
|
)
|
2023-11-27 18:48:37 +03:00
|
|
|
}
|
|
|
|
|
2024-01-03 12:12:38 +03:00
|
|
|
export function componentBrowserEntryByLabel(page: Locator | Page, label: string) {
|
|
|
|
return componentBrowserEntry(page).filter({ has: page.getByText(label) })
|
|
|
|
}
|
|
|
|
|
2024-01-18 16:45:18 +03:00
|
|
|
export const navBreadcrumb = componentLocator('NavBreadcrumb')
|
2024-01-03 12:12:38 +03:00
|
|
|
export const componentBrowserInput = componentLocator('CBInput')
|
2023-11-27 18:48:37 +03:00
|
|
|
export const jsonVisualization = componentLocator('JSONVisualization')
|
|
|
|
export const tableVisualization = componentLocator('TableVisualization')
|
|
|
|
export const scatterplotVisualization = componentLocator('ScatterplotVisualization')
|
|
|
|
export const histogramVisualization = componentLocator('HistogramVisualization')
|
|
|
|
export const heatmapVisualization = componentLocator('HeatmapVisualization')
|
|
|
|
export const sqlVisualization = componentLocator('SqlVisualization')
|
|
|
|
export const geoMapVisualization = componentLocator('GeoMapVisualization')
|
|
|
|
export const imageBase64Visualization = componentLocator('ImageBase64Visualization')
|
|
|
|
export const warningsVisualization = componentLocator('WarningsVisualization')
|