Files
Imhotep/packages/imhotep-playwright/src/presets.ts
T

89 lines
2.8 KiB
TypeScript
Raw Normal View History

import { lowerToCanonical, type CanonicalClauseDescriptor } from 'imhotep-dsl'
import type { FluentRelation } from 'imhotep-dsl'
import type { ImhotepUi } from './public.js'
export interface PresetResult {
assertions: FluentRelation[]
clauses: CanonicalClauseDescriptor[]
}
function toPresetResult(assertions: FluentRelation[]): PresetResult {
const clauses: CanonicalClauseDescriptor[] = []
for (const assertion of assertions) {
clauses.push(...lowerToCanonical(assertion.toAst()))
}
return { assertions, clauses }
}
export function touchTarget(
ui: ImhotepUi,
selector: string,
options: { minSize?: number } = {},
): PresetResult {
const minSize = options.minSize ?? 44
const assertions = [
ui.expect(selector).to.be.atLeast(minSize, 'width'),
ui.expect(selector).to.be.atLeast(minSize, 'height'),
]
return toPresetResult(assertions)
}
export function toolbarAlignment(
ui: ImhotepUi,
selectors: string[],
options: { minGap?: number; axis?: 'centerY' | 'centerX' } = {},
): PresetResult {
const minGap = options.minGap ?? 8
const axis = options.axis ?? 'centerY'
const assertions: FluentRelation[] = []
for (let i = 0; i < selectors.length - 1; i++) {
assertions.push(ui.expect(selectors[i]).to.be.leftOf(selectors[i + 1], { minGap }))
assertions.push(ui.expect(selectors[i]).to.be.alignedWith(selectors[i + 1], { axis }))
}
return toPresetResult(assertions)
}
export function cardSpacing(
ui: ImhotepUi,
cardSelector: string,
nextCardSelector: string,
options: { minGap?: number } = {},
): PresetResult {
const minGap = options.minGap ?? 16
const assertions = [
ui.expect(cardSelector).to.be.leftOf(nextCardSelector, { minGap }),
ui.expect(cardSelector).to.be.alignedWith(nextCardSelector, { axis: 'top' }),
]
return toPresetResult(assertions)
}
export function formLabelAlignment(
ui: ImhotepUi,
labelSelector: string,
inputSelector: string,
options: { labelAbove?: boolean; maxGap?: number } = {},
): PresetResult {
const labelAbove = options.labelAbove ?? true
const maxGap = options.maxGap ?? 16
const assertions: FluentRelation[] = []
if (labelAbove) {
assertions.push(ui.expect(labelSelector).to.be.above(inputSelector, { maxGap }))
assertions.push(ui.expect(labelSelector).to.be.alignedWith(inputSelector, { axis: 'left' }))
} else {
assertions.push(ui.expect(labelSelector).to.be.leftOf(inputSelector, { maxGap }))
assertions.push(ui.expect(labelSelector).to.be.alignedWith(inputSelector, { axis: 'centerY' }))
}
return toPresetResult(assertions)
}
export function modalContainment(
ui: ImhotepUi,
modalSelector: string,
): PresetResult {
const assertions = [
ui.expect(modalSelector).to.be.inside('body'),
ui.expect(modalSelector).to.be.centeredWithin('body'),
]
return toPresetResult(assertions)
}