chore: e2e tests for compound fluent assertions + clean barrel exports
- Add 2 e2e FOL solver tests for fluent .and/.or through checkAll() using a mock page with distinct geometry positions (P0-1 regression) - Remove 4 individual adapter factories from barrel index: createReactAdapter, createVueAdapter, createStorybookAdapter, createCustomAdapter (use react()/vue()/storybook()/custom() instead) - Reduce barrel from 101 to 89 lines
This commit is contained in:
@@ -484,6 +484,108 @@ describe('FOL engine integration', () => {
|
||||
assert.ok(result.diagnostics.some((d) => d.code === 'IMH_EXTRACT_PROTOCOL_ERROR'))
|
||||
})
|
||||
|
||||
it('compound .and chaining compiles through FOL solver and evaluates', async () => {
|
||||
// Elements at distinct positions:
|
||||
// .a: (10,10) — top-left
|
||||
// .b: (110,10) — to the right of .a (gap: 50 >= 8)
|
||||
// .c: (10,110) — below .a (gap: 50 >= 8)
|
||||
const page: any = {
|
||||
viewportSize: () => ({ width: 1280, height: 720 }),
|
||||
setViewportSize: async () => {},
|
||||
emulateMedia: async () => {},
|
||||
addInitScript: async () => {},
|
||||
keyboard: { press: async () => {} },
|
||||
mouse: { move: async () => {} },
|
||||
context: () => ({}),
|
||||
locator: (_selector: string) => ({ hover: async () => {}, focus: async () => {} }),
|
||||
evaluate: async (_fn: any, ...args: any[]) => {
|
||||
const payload = args[0]
|
||||
if (!payload || !Array.isArray(payload.plans)) return undefined
|
||||
const elements: Array<any> = []
|
||||
const selectorToIds: Array<[string, number[]]> = []
|
||||
const positions: Record<string, { x: number; y: number }> = {
|
||||
'.a': { x: 10, y: 10 },
|
||||
'.b': { x: 110, y: 10 },
|
||||
'.c': { x: 10, y: 110 },
|
||||
}
|
||||
for (const plan of payload.plans as Array<{ key: string; queries: string[] }>) {
|
||||
const ids: number[] = []
|
||||
const pos = positions[plan.key] || { x: 0, y: 0, width: 0, height: 0 }
|
||||
for (const _query of plan.queries) {
|
||||
const subjectId = elements.length + 1
|
||||
elements.push({
|
||||
tagName: 'div',
|
||||
rect: { x: pos.x, y: pos.y, width: 50, height: 50 },
|
||||
transform: { matrix: [1, 0, 0, 1, 0, 0], originX: 0, originY: 0 },
|
||||
})
|
||||
ids.push(subjectId)
|
||||
}
|
||||
selectorToIds.push([plan.key, ids])
|
||||
}
|
||||
return { elements, selectorToIds }
|
||||
},
|
||||
}
|
||||
const ui = await imhotep(page)
|
||||
|
||||
ui.expect('.a').to.be.leftOf('.b', { minGap: 8 }).and.above('.c', { minGap: 8 })
|
||||
|
||||
const result = await ui.checkAll()
|
||||
assert.strictEqual(result.passed, true, `Expected passed:true, got passed:${result.passed}. Diagnostics: ${JSON.stringify(result.diagnostics.map(d => d.code))}`)
|
||||
assert.strictEqual(result.clauseResults.length, 1)
|
||||
assert.strictEqual(result.clauseResults[0].status, 'pass')
|
||||
assert.ok(['true', 'determinate'].includes(result.clauseResults[0].truth), `expected true|determinate truth, got ${result.clauseResults[0].truth}`)
|
||||
})
|
||||
|
||||
it('compound .or chaining compiles through FOL solver and evaluates', async () => {
|
||||
// .a is leftOf .b (true) but NOT leftOf .c (false — same x column).
|
||||
// With .or, true clause satisfies the disjunction.
|
||||
const page: any = {
|
||||
viewportSize: () => ({ width: 1280, height: 720 }),
|
||||
setViewportSize: async () => {},
|
||||
emulateMedia: async () => {},
|
||||
addInitScript: async () => {},
|
||||
keyboard: { press: async () => {} },
|
||||
mouse: { move: async () => {} },
|
||||
context: () => ({}),
|
||||
locator: (_selector: string) => ({ hover: async () => {}, focus: async () => {} }),
|
||||
evaluate: async (_fn: any, ...args: any[]) => {
|
||||
const payload = args[0]
|
||||
if (!payload || !Array.isArray(payload.plans)) return undefined
|
||||
const elements: Array<any> = []
|
||||
const selectorToIds: Array<[string, number[]]> = []
|
||||
const positions: Record<string, { x: number; y: number }> = {
|
||||
'.a': { x: 10, y: 10 },
|
||||
'.b': { x: 110, y: 10 },
|
||||
'.c': { x: 10, y: 110 },
|
||||
}
|
||||
for (const plan of payload.plans as Array<{ key: string; queries: string[] }>) {
|
||||
const ids: number[] = []
|
||||
const pos = positions[plan.key] || { x: 0, y: 0, width: 0, height: 0 }
|
||||
for (const _query of plan.queries) {
|
||||
const subjectId = elements.length + 1
|
||||
elements.push({
|
||||
tagName: 'div',
|
||||
rect: { x: pos.x, y: pos.y, width: 50, height: 50 },
|
||||
transform: { matrix: [1, 0, 0, 1, 0, 0], originX: 0, originY: 0 },
|
||||
})
|
||||
ids.push(subjectId)
|
||||
}
|
||||
selectorToIds.push([plan.key, ids])
|
||||
}
|
||||
return { elements, selectorToIds }
|
||||
},
|
||||
}
|
||||
const ui = await imhotep(page)
|
||||
|
||||
ui.expect('.a').to.be.leftOf('.b', { minGap: 8 }).or.leftOf('.c', { minGap: 8 })
|
||||
|
||||
const result = await ui.checkAll()
|
||||
assert.strictEqual(result.passed, true, `Expected passed:true. Diagnostics: ${JSON.stringify(result.diagnostics.map(d => d.code))}`)
|
||||
assert.strictEqual(result.clauseResults.length, 1)
|
||||
assert.strictEqual(result.clauseResults[0].status, 'pass')
|
||||
assert.ok(['true', 'determinate'].includes(result.clauseResults[0].truth), `expected true|determinate truth, got ${result.clauseResults[0].truth}`)
|
||||
})
|
||||
|
||||
it('forall over elements evaluates all matches', async () => {
|
||||
const page = createMockPage()
|
||||
const ui = await imhotep(page)
|
||||
|
||||
Reference in New Issue
Block a user