diff --git a/e2e/tests/controls/polygon-controls/index.spec.ts b/e2e/tests/controls/polygon-controls/index.spec.ts index 7b79b96c96a..d29fd711dbd 100644 --- a/e2e/tests/controls/polygon-controls/index.spec.ts +++ b/e2e/tests/controls/polygon-controls/index.spec.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import type { Polygon } from '../../../..'; +import type { Polygon } from 'fabric'; import setup from '../../../setup'; import { CanvasUtil } from '../../../utils/CanvasUtil'; import { ObjectUtil } from '../../../utils/ObjectUtil'; @@ -30,31 +30,58 @@ for (const exact of [true, false]) { name: toSnapshotName('initial', exact), }); - const p2ControlPoint = await starUtil.getObjectControlPoint('p2'); + const modifyPoly = ( + title: string, + controlName: string, + delta: { x: number; y: number } + ) => + test.step(title, async () => { + const eventStreamHandle = + await test.step('subscribe to poly events', () => + starUtil.evaluateHandle((object) => { + const events: { action: string; corner: string }[] = []; + const disposer = object.on( + 'modifyPoly', + ({ transform: { action, corner } }) => + events.push({ action, corner }) + ); + object.once('modified', ({ transform: { action, corner } }) => { + disposer(); + events.push({ action, corner }); + }); + return events; + })); - await test.step('drag the p2 control', async () => { - await page.mouse.move(p2ControlPoint.x, p2ControlPoint.y); - await page.mouse.down(); - await page.mouse.move(p2ControlPoint.x + 300, p2ControlPoint.y + 100, { - steps: 40, - }); - await page.mouse.up(); - expect(await canvasUtil.screenshot()).toMatchSnapshot({ - name: toSnapshotName('moved_controls_p2', exact), - }); - }); + const controlPoint = await starUtil.getObjectControlPoint(controlName); + await page.mouse.move(controlPoint.x, controlPoint.y); + await page.mouse.down(); + await page.mouse.move( + controlPoint.x + delta.x, + controlPoint.y + delta.y, + { + steps: 40, + } + ); + await page.mouse.up(); - await test.step('drag in the opposite direction', async () => { - const p4ControlPoint = await starUtil.getObjectControlPoint('p4'); - await page.mouse.move(p4ControlPoint.x, p4ControlPoint.y); - await page.mouse.down(); - await page.mouse.move(p4ControlPoint.x - 300, p4ControlPoint.y - 100, { - steps: 40, - }); - await page.mouse.up(); - expect(await canvasUtil.screenshot()).toMatchSnapshot({ - name: toSnapshotName('moved_controls_p4', exact), + expect(await canvasUtil.screenshot()).toMatchSnapshot({ + name: toSnapshotName(`moved_controls_${controlName}`, exact), + }); + + const events = await eventStreamHandle.jsonValue(); + expect(events.length).toBeGreaterThan(0); + expect(events).toMatchObject( + new Array(events.length).fill({ + action: 'modifyPoly', + corner: controlName, + }) + ); }); + + await modifyPoly('drag the p2 control', 'p2', { x: 300, y: 100 }); + await modifyPoly('drag in the p4 control in the opposite direction', 'p4', { + x: -300, + y: -100, }); }); } diff --git a/e2e/utils/CanvasUtil.ts b/e2e/utils/CanvasUtil.ts index 3d2057682bc..b940b0e1eb1 100644 --- a/e2e/utils/CanvasUtil.ts +++ b/e2e/utils/CanvasUtil.ts @@ -1,3 +1,4 @@ +import type { JSHandle } from '@playwright/test'; import { type LocatorScreenshotOptions, type Page } from '@playwright/test'; import type { Canvas } from 'fabric'; import os from 'node:os'; @@ -31,15 +32,24 @@ export class CanvasUtil { .screenshot({ omitBackground: true, ...options }); } + evaluateSelf() { + return this.page.evaluateHandle( + ([selector]) => canvasMap.get(document.querySelector(selector)), + [this.selector] + ); + } + async executeInBrowser( runInBrowser: (canvas: Canvas, context: C) => R, context?: C ): Promise { - return ( - await this.page.evaluateHandle( - ([selector]) => canvasMap.get(document.querySelector(selector)), - [this.selector] - ) - ).evaluate(runInBrowser, context); + return (await this.evaluateSelf()).evaluate(runInBrowser, context); + } + + async evaluateHandle( + runInBrowser: (canvas: Canvas, context: C) => R, + context?: C + ): Promise> { + return (await this.evaluateSelf()).evaluateHandle(runInBrowser, context); } } diff --git a/e2e/utils/ObjectUtil.ts b/e2e/utils/ObjectUtil.ts index db58a5c9980..99a32e905fd 100644 --- a/e2e/utils/ObjectUtil.ts +++ b/e2e/utils/ObjectUtil.ts @@ -1,9 +1,9 @@ -import type { Page } from '@playwright/test'; +import type { JSHandle, Page } from '@playwright/test'; import { expect } from '@playwright/test'; -import type { Object as FabricObject } from 'fabric'; +import type { FabricObject } from 'fabric'; import type { before, beforeAll } from 'test'; -export class ObjectUtil { +export class ObjectUtil { constructor( readonly page: Page, /** @@ -12,16 +12,25 @@ export class ObjectUtil { readonly objectId: string ) {} + evaluateSelf() { + return this.page.evaluateHandle( + ([objectId]) => objectMap.get(objectId), + [this.objectId] + ); + } + async executeInBrowser( runInBrowser: (object: T, context: C) => R, context?: C ): Promise { - return ( - await this.page.evaluateHandle( - ([objectId]) => objectMap.get(objectId), - [this.objectId] - ) - ).evaluate(runInBrowser, context); + return (await this.evaluateSelf()).evaluate(runInBrowser, context); + } + + async evaluateHandle( + runInBrowser: (object: T, context: C) => R, + context?: C + ): Promise> { + return (await this.evaluateSelf()).evaluateHandle(runInBrowser, context); } getObjectCenter() { diff --git a/src/EventTypeDefs.ts b/src/EventTypeDefs.ts index 767a59f64bc..fe51d4b4106 100644 --- a/src/EventTypeDefs.ts +++ b/src/EventTypeDefs.ts @@ -53,7 +53,7 @@ export type Transform = { target: FabricObject; action: string; actionHandler?: TransformActionHandler; - corner: string | 0; + corner: string; scaleX: number; scaleY: number; skewX: number;