diff --git a/src/display/draw_layer.js b/src/display/draw_layer.js index 23ba3e350..3c763f443 100644 --- a/src/display/draw_layer.js +++ b/src/display/draw_layer.js @@ -24,12 +24,12 @@ import { shadow } from "../shared/util.js"; class DrawLayer { #parent = null; - #id = 0; - #mapping = new Map(); #toUpdate = new Map(); + static #id = 0; + constructor({ pageIndex }) { this.pageIndex = pageIndex; } @@ -96,7 +96,7 @@ class DrawLayer { } draw(properties, isPathUpdatable = false, hasClip = false) { - const id = this.#id++; + const id = DrawLayer.#id++; const root = this.#createSVG(); const defs = DrawLayer._svgFactory.createElement("defs"); @@ -129,7 +129,7 @@ class DrawLayer { // it composes with its parent with mix-blend-mode: multiply. // But the outline has a different mix-blend-mode, so we need to draw it in // its own SVG. - const id = this.#id++; + const id = DrawLayer.#id++; const root = this.#createSVG(); const defs = DrawLayer._svgFactory.createElement("defs"); root.append(defs); diff --git a/test/integration/ink_editor_spec.mjs b/test/integration/ink_editor_spec.mjs index 83e6b593e..672f8ae21 100644 --- a/test/integration/ink_editor_spec.mjs +++ b/test/integration/ink_editor_spec.mjs @@ -1015,4 +1015,73 @@ describe("Ink Editor", () => { ); }); }); + + describe("Draw annotations on several page, move one of them and delete it", () => { + let pages; + + beforeAll(async () => { + pages = await loadAndWait( + "tracemonkey.pdf", + ".annotationEditorLayer", + 10 + ); + }); + + afterAll(async () => { + await closePages(pages); + }); + + it("must check that the first annotation is correctly associated with its SVG", async () => { + await Promise.all( + pages.map(async ([browserName, page]) => { + await switchToInk(page); + + for (let i = 0; i < 2; i++) { + const pageSelector = `.page[data-page-number = "${i + 1}"]`; + const rect = await getRect( + page, + `${pageSelector} .annotationEditorLayer` + ); + const xStart = rect.x + 10; + const yStart = rect.y + 10; + const clickHandle = await waitForPointerUp(page); + await page.mouse.move(xStart, yStart); + await page.mouse.down(); + await page.mouse.move(xStart + 10, yStart + 10); + await page.mouse.up(); + await awaitPromise(clickHandle); + await commit(page); + } + + const pageOneSelector = `.page[data-page-number = "1"]`; + const initialRect = await getRect(page, `${pageOneSelector} svg`); + + let editorSelector = getEditorSelector(1); + await waitForSelectedEditor(page, editorSelector); + await dragAndDrop(page, editorSelector, [[0, -30]], /* steps = */ 10); + await waitForSerialized(page, 2); + await page.waitForSelector(`${editorSelector} button.delete`); + await page.click(`${editorSelector} button.delete`); + await waitForSerialized(page, 1); + await page.click("#editorUndoBarUndoButton"); + await page.waitForSelector("#editorUndoBar", { hidden: true }); + + editorSelector = getEditorSelector(0); + const editorRect = await getRect(page, editorSelector); + await page.mouse.click( + editorRect.x + editorRect.width / 2, + editorRect.y + editorRect.height / 2 + ); + await waitForSelectedEditor(page, editorSelector); + + await dragAndDrop(page, editorSelector, [[30, 30]], /* steps = */ 10); + const finalRect = await getRect(page, `${pageOneSelector} svg`); + + expect(initialRect) + .withContext(`In ${browserName}`) + .not.toEqual(finalRect); + }) + ); + }); + }); }); diff --git a/test/integration/test_utils.mjs b/test/integration/test_utils.mjs index 3d1ff5bf2..2b868ca89 100644 --- a/test/integration/test_utils.mjs +++ b/test/integration/test_utils.mjs @@ -511,14 +511,14 @@ async function serializeBitmapDimensions(page) { }); } -async function dragAndDrop(page, selector, translations) { +async function dragAndDrop(page, selector, translations, steps = 1) { const rect = await getRect(page, selector); const startX = rect.x + rect.width / 2; const startY = rect.y + rect.height / 2; await page.mouse.move(startX, startY); await page.mouse.down(); for (const [tX, tY] of translations) { - await page.mouse.move(startX + tX, startY + tY); + await page.mouse.move(startX + tX, startY + tY, { steps }); } await page.mouse.up(); await page.waitForSelector("#viewer:not(.noUserSelect)");