/// context('tool tests', () => { // @TODO: make rounded tools render consistently across platforms const roundedToolsCompareOptions = { failureThreshold: 13, failureThresholdType: 'pixel' }; // beforeAll isn't a thing, and beforeEach applies also to tests declared above it, // so do this fake test + flag hack in order to execute some steps before the first test let before_first_real_test = true; it(`(fake test for setup)`, () => { cy.visit('/') cy.setResolution([800, 500]); cy.window().should('have.property', 'selected_colors'); // wait for app to be loaded before_first_real_test = false; }); beforeEach(() => { if (before_first_real_test) return; cy.window().then({ timeout: 60000 }, async (win) => { win.selected_colors.foreground = "#000"; win.selected_colors.background = "#fff"; win.brush_shape = win.default_brush_shape; win.brush_size = win.default_brush_size win.eraser_size = win.default_eraser_size; win.airbrush_size = win.default_airbrush_size; win.pencil_size = win.default_pencil_size; win.stroke_size = win.default_stroke_size; win.clear(); }); }); const simulateGesture = (win, { start, end, shift, shiftToggleChance = 0.01, secondary, secondaryToggleChance, target }) => { target = target || win.$(".main-canvas")[0]; let startWithinRect = target.getBoundingClientRect(); let canvasAreaRect = win.$(".canvas-area")[0].getBoundingClientRect(); let startMinX = Math.max(startWithinRect.left, canvasAreaRect.left); let startMaxX = Math.min(startWithinRect.right, canvasAreaRect.right); let startMinY = Math.max(startWithinRect.top, canvasAreaRect.top); let startMaxY = Math.min(startWithinRect.bottom, canvasAreaRect.bottom); let startPointX = startMinX + start.x * (startMaxX - startMinX); let startPointY = startMinY + start.y * (startMaxY - startMinY); let endPointX = startMinX + end.x * (startMaxX - startMinX); let endPointY = startMinY + end.y * (startMaxY - startMinY); const $cursor = win.$(``); $cursor.css({ position: "absolute", left: 0, top: 0, opacity: 0, zIndex: 5, // @#: z-index pointerEvents: "none", transition: "opacity 0.5s", }); $cursor.appendTo(".jspaint"); let triggerMouseEvent = (type, point) => { const clientX = point.x; const clientY = point.y; // const el_over = win.document.elementFromPoint(clientX, clientY); const do_nothing = false;//!type.match(/move/) && (!el_over || !el_over.closest(".canvas-area")); $cursor.css({ display: "block", position: "absolute", left: clientX, top: clientY, opacity: do_nothing ? 0.5 : 1, }); if (do_nothing) { return; } let event = new win.$.Event(type, { view: window, bubbles: true, cancelable: true, clientX, clientY, screenX: clientX, screenY: clientY, offsetX: point.x, offsetY: point.y, button: secondary ? 2 : 0, buttons: secondary ? 2 : 1, shiftKey: shift, }); win.$(target).trigger(event); }; let t = 0; const stepsInGesture = 3; let pointForTime = (t) => { return { x: startPointX + (endPointX - startPointX) * t, y: startPointY + (endPointY - startPointY) * Math.pow(t, 0.3), }; }; return new Promise((resolve) => { triggerMouseEvent("pointerenter", pointForTime(t)); // so dynamic cursors follow the simulation cursor triggerMouseEvent("pointerdown", pointForTime(t)); let move = () => { t += 1 / stepsInGesture; // if (seededRandom() < shiftToggleChance) { // shift = !shift; // } // if (seededRandom() < secondaryToggleChance) { // secondary = !secondary; // } if (t > 1) { triggerMouseEvent("pointerup", pointForTime(t)); $cursor.remove(); resolve(); } else { triggerMouseEvent("pointermove", pointForTime(t)); /*gestureTimeoutID =*/ setTimeout(move, 10); } }; triggerMouseEvent("pointerleave", pointForTime(t)); move(); }); }; // const gesture = (points) => { // const options = { secondary: false, shift: false }; // // @TODO: while loop // trigger("pointerenter", points[0].x, points[0].y, options); // trigger("pointerdown", points[0].x, points[0].y, options); // let i = 0; // for (; i < points.length; i++) { // trigger("pointermove", points[i].x, points[i].y, options); // } // i--; // trigger("pointerup", points[i].x, points[i].y, options); // }; // it('brush tool', () => { // cy.get(".tool[title='Brush']").click(); // // gesture([{ x: 50, y: 50 }, { x: 100, y: 100 }]); // cy.get(".swatch:nth-child(21)").rightclick(); // cy.window().then({ timeout: 8000 }, async (win) => { // for (let secondary = 0; secondary <= 1; secondary++) { // for (let b = 0; b < 12; b++) { // win.$(`.chooser > :nth-child(${b + 1})`).click(); // const start = { x: 0.05 + b * 0.05, y: 0.1 + 0.1 * secondary }; // const end = { x: start.x + 0.04, y: start.y + 0.04 }; // await simulateGesture(win, { shift: false, secondary: !!secondary, start, end }); // } // } // }); // cy.matchImageSnapshot(); // }); // @TODO: test transparent document mode it(`eraser tool`, () => { cy.get(`.tool[title='Eraser/Color Eraser']`).click(); // gesture([{ x: 50, y: 50 }, { x: 100, y: 100 }]); cy.window().then({ timeout: 60000 }, async (win) => { for (let row = 0; row < 4; row++) { const secondary = !!(row % 2); const increaseSize = row >= 2; let $options = win.$(`.chooser > *`); for (let o = 0; o < $options.length; o++) { $options[o].click(); if (increaseSize) { for (let i = 0; i < 5; i++) { win.$('body').trigger(new win.$.Event("keydown", { key: "NumpadPlus", keyCode: 107, which: 107 })); } } win.selected_colors.background = "#f0f"; const start = { x: 0.05 + o * 0.05, y: 0.1 + 0.1 * row }; const end = { x: start.x + 0.04, y: start.y + 0.04 }; await simulateGesture(win, { shift: false, secondary: false, start, end }); if (secondary) { // eslint-disable-next-line require-atomic-updates win.selected_colors.background = "#ff0"; // eslint-disable-next-line require-atomic-updates win.selected_colors.foreground = "#f0f"; const start = { x: 0.04 + o * 0.05, y: 0.11 + 0.1 * row }; const end = { x: start.x + 0.03, y: start.y + 0.02 }; await simulateGesture(win, { shift: false, secondary: true, start, end }); } } } }); cy.get(".main-canvas").matchImageSnapshot(); }); ["Brush", "Pencil", "Rectangle", "Rounded Rectangle", "Ellipse", "Line"].forEach((toolName) => { it(`${toolName.toLowerCase()} tool`, () => { cy.get(`.tool[title='${toolName}']`).click(); // gesture([{ x: 50, y: 50 }, { x: 100, y: 100 }]); cy.get(".swatch:nth-child(22)").rightclick(); cy.window().then({ timeout: 60000 }, async (win) => { for (let row = 0; row < 4; row++) { const secondary = !!(row % 2); const increaseSize = row >= 2; let $options = win.$(`.chooser > *`); // Pencil has no options if ($options.length === 0) { $options = win.$(""); } for (let o = 0; o < $options.length; o++) { $options[o].click(); if (increaseSize && (o === 0 || toolName === "Brush" || toolName === "Line")) { for (let i = 0; i < 5; i++) { win.$('body').trigger(new win.$.Event("keydown", { key: "NumpadPlus", keyCode: 107, which: 107 })); } } const start = { x: 0.05 + o * 0.05, y: 0.1 + 0.1 * row }; const end = { x: start.x + 0.04, y: start.y + 0.04 }; await simulateGesture(win, { shift: false, secondary: !!secondary, start, end }); } } }); cy.get(".main-canvas").matchImageSnapshot(toolName.match(/Rounded Rectangle|Ellipse/) ? roundedToolsCompareOptions : undefined); }); }); });