2022-07-22 12:13:47 +02:00
/ * C o p y r i g h t 2 0 2 2 M o z i l l a F o u n d a t i o n
*
* Licensed under the Apache License , Version 2.0 ( the "License" ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an "AS IS" BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
* /
2023-10-12 13:16:58 +02:00
import {
2023-12-06 15:27:31 +01:00
awaitPromise ,
2025-02-23 18:52:19 +01:00
clearEditors ,
2022-07-22 12:13:47 +02:00
closePages ,
2024-12-09 16:07:39 +01:00
dragAndDrop ,
2024-12-01 21:15:57 +01:00
getAnnotationSelector ,
getEditors ,
2023-12-04 23:13:31 +01:00
getEditorSelector ,
2024-05-23 17:53:58 +02:00
getRect ,
2024-12-01 21:15:57 +01:00
getSerialized ,
2025-03-06 14:59:04 +01:00
isCanvasMonochrome ,
2023-10-26 22:42:41 +02:00
kbRedo ,
kbUndo ,
2022-07-22 12:13:47 +02:00
loadAndWait ,
2025-02-22 15:19:10 +01:00
moveEditor ,
2023-12-04 13:27:30 +01:00
scrollIntoView ,
2025-01-18 19:21:55 +01:00
selectEditor ,
2025-02-23 18:49:14 +01:00
selectEditors ,
2024-05-24 19:11:37 +02:00
switchToEditor ,
2024-12-04 17:57:17 +01:00
waitForAnnotationModeChanged ,
2024-11-29 16:22:44 +01:00
waitForNoElement ,
2025-02-18 15:24:01 +01:00
waitForPointerUp ,
2024-12-01 21:15:57 +01:00
waitForSelectedEditor ,
2024-03-22 19:30:56 +01:00
waitForSerialized ,
2023-09-29 15:01:52 +02:00
waitForStorageEntries ,
2024-12-01 21:15:57 +01:00
waitForTimeout ,
2023-10-12 13:16:58 +02:00
} from "./test_utils.mjs" ;
2022-07-22 12:13:47 +02:00
2025-02-23 18:49:14 +01:00
const selectAll = selectEditors . bind ( null , "ink" ) ;
2023-09-29 15:01:52 +02:00
2025-02-23 18:52:19 +01:00
const clearAll = clearEditors . bind ( null , "ink" ) ;
2023-09-29 15:01:52 +02:00
const commit = async page => {
await page . keyboard . press ( "Escape" ) ;
await page . waitForSelector ( ".inkEditor.selectedEditor.draggable.disabled" ) ;
} ;
2024-05-24 19:11:37 +02:00
const switchToInk = switchToEditor . bind ( null , "Ink" ) ;
2023-04-16 21:36:26 +02:00
describe ( "Ink Editor" , ( ) => {
describe ( "Basic operations" , ( ) => {
2022-07-22 12:13:47 +02:00
let pages ;
2025-02-09 16:35:55 +01:00
beforeEach ( async ( ) => {
2022-07-27 14:11:29 +02:00
pages = await loadAndWait ( "aboutstacks.pdf" , ".annotationEditorLayer" ) ;
2022-07-22 12:13:47 +02:00
} ) ;
2025-02-09 16:35:55 +01:00
afterEach ( async ( ) => {
2022-07-22 12:13:47 +02:00
await closePages ( pages ) ;
} ) ;
it ( "must draw, undo a deletion and check that the editors are not selected" , async ( ) => {
await Promise . all (
pages . map ( async ( [ browserName , page ] ) => {
2024-05-24 19:11:37 +02:00
await switchToInk ( page ) ;
2022-07-22 12:13:47 +02:00
2024-05-23 17:53:58 +02:00
const rect = await getRect ( page , ".annotationEditorLayer" ) ;
2022-07-22 12:13:47 +02:00
for ( let i = 0 ; i < 3 ; i ++ ) {
const x = rect . x + 100 + i * 100 ;
const y = rect . y + 100 + i * 100 ;
2023-12-06 15:27:31 +01:00
const clickHandle = await waitForPointerUp ( page ) ;
2022-07-22 12:13:47 +02:00
await page . mouse . move ( x , y ) ;
await page . mouse . down ( ) ;
await page . mouse . move ( x + 50 , y + 50 ) ;
await page . mouse . up ( ) ;
2023-12-06 15:27:31 +01:00
await awaitPromise ( clickHandle ) ;
2022-07-22 12:13:47 +02:00
2023-09-29 15:01:52 +02:00
await commit ( page ) ;
2022-07-22 12:13:47 +02:00
}
2023-09-29 15:01:52 +02:00
await clearAll ( page ) ;
2022-07-22 12:13:47 +02:00
2023-10-26 22:42:41 +02:00
await kbUndo ( page ) ;
2023-09-29 15:01:52 +02:00
await waitForStorageEntries ( page , 3 ) ;
2022-07-22 12:13:47 +02:00
2024-12-22 18:28:50 +01:00
expect ( await getEditors ( page , "selected" ) )
2022-07-22 12:13:47 +02:00
. withContext ( ` In ${ browserName } ` )
. toEqual ( [ ] ) ;
} )
) ;
} ) ;
2022-07-29 16:53:03 +02:00
it ( "must draw, undo/redo and check that the editor don't move" , async ( ) => {
await Promise . all (
pages . map ( async ( [ browserName , page ] ) => {
2025-02-09 16:27:16 +01:00
await switchToInk ( page ) ;
2024-05-23 17:53:58 +02:00
const rect = await getRect ( page , ".annotationEditorLayer" ) ;
2022-07-29 16:53:03 +02:00
const xStart = rect . x + 300 ;
const yStart = rect . y + 300 ;
2023-12-06 15:27:31 +01:00
const clickHandle = await waitForPointerUp ( page ) ;
2022-07-29 16:53:03 +02:00
await page . mouse . move ( xStart , yStart ) ;
await page . mouse . down ( ) ;
await page . mouse . move ( xStart + 50 , yStart + 50 ) ;
await page . mouse . up ( ) ;
2023-12-06 15:27:31 +01:00
await awaitPromise ( clickHandle ) ;
2022-07-29 16:53:03 +02:00
2023-09-29 15:01:52 +02:00
await commit ( page ) ;
2022-07-29 16:53:03 +02:00
2024-11-20 22:26:38 +01:00
const rectBefore = await getRect ( page , ".canvasWrapper .draw" ) ;
2022-07-29 16:53:03 +02:00
for ( let i = 0 ; i < 30 ; i ++ ) {
2023-10-26 22:42:41 +02:00
await kbUndo ( page ) ;
2023-09-29 15:01:52 +02:00
await waitForStorageEntries ( page , 0 ) ;
2023-10-26 22:42:41 +02:00
await kbRedo ( page ) ;
2023-09-29 15:01:52 +02:00
await waitForStorageEntries ( page , 1 ) ;
2022-07-29 16:53:03 +02:00
}
2024-11-20 22:26:38 +01:00
const rectAfter = await getRect ( page , ".canvasWrapper .draw" ) ;
2022-07-29 16:53:03 +02:00
expect ( Math . round ( rectBefore . x ) )
. withContext ( ` In ${ browserName } ` )
. toEqual ( Math . round ( rectAfter . x ) ) ;
expect ( Math . round ( rectBefore . y ) )
. withContext ( ` In ${ browserName } ` )
. toEqual ( Math . round ( rectAfter . y ) ) ;
} )
) ;
} ) ;
2025-02-22 15:19:10 +01:00
it ( "must draw and move with the keyboard" , async ( ) => {
await Promise . all (
pages . map ( async ( [ browserName , page ] ) => {
await switchToInk ( page ) ;
const rect = await getRect ( page , ".annotationEditorLayer" ) ;
const x = rect . x + 100 ;
const y = rect . y + 100 ;
const clickHandle = await waitForPointerUp ( page ) ;
await page . mouse . move ( x , y ) ;
await page . mouse . down ( ) ;
await page . mouse . move ( x + 50 , y + 50 ) ;
await page . mouse . up ( ) ;
await awaitPromise ( clickHandle ) ;
await commit ( page ) ;
const editorSelector = getEditorSelector ( 0 ) ;
await page . waitForSelector ( editorSelector ) ;
const rectBefore = ( await getSerialized ( page , s => s . rect ) ) [ 0 ] ;
const N = 20 ;
await moveEditor ( page , editorSelector , N , ( ) =>
page . keyboard . press ( "ArrowDown" )
) ;
const rectAfter = ( await getSerialized ( page , s => s . rect ) ) [ 0 ] ;
expect ( Math . abs ( rectBefore [ 0 ] - rectAfter [ 0 ] ) )
. withContext ( ` In ${ browserName } ` )
. toBeLessThan ( 1e-2 ) ;
expect ( Math . abs ( rectBefore [ 1 ] - N - rectAfter [ 1 ] ) )
. withContext ( ` In ${ browserName } ` )
. toBeLessThan ( 1e-2 ) ;
expect ( Math . abs ( rectBefore [ 2 ] - rectAfter [ 2 ] ) )
. withContext ( ` In ${ browserName } ` )
. toBeLessThan ( 1e-2 ) ;
expect ( Math . abs ( rectBefore [ 3 ] - N - rectAfter [ 3 ] ) )
. withContext ( ` In ${ browserName } ` )
. toBeLessThan ( 1e-2 ) ;
} )
) ;
} ) ;
2022-07-22 12:13:47 +02:00
} ) ;
2023-04-16 21:36:26 +02:00
describe ( "with a rotated pdf" , ( ) => {
let pages ;
2025-02-09 16:35:55 +01:00
beforeEach ( async ( ) => {
2023-04-16 21:36:26 +02:00
pages = await loadAndWait ( "issue16278.pdf" , ".annotationEditorLayer" ) ;
} ) ;
2025-02-09 16:35:55 +01:00
afterEach ( async ( ) => {
2023-04-16 21:36:26 +02:00
await closePages ( pages ) ;
} ) ;
it ( "must draw something" , async ( ) => {
await Promise . all (
pages . map ( async ( [ browserName , page ] ) => {
2024-05-24 19:11:37 +02:00
await switchToInk ( page ) ;
2023-04-16 21:36:26 +02:00
2024-05-23 17:53:58 +02:00
const rect = await getRect ( page , ".annotationEditorLayer" ) ;
2023-04-16 21:36:26 +02:00
const x = rect . x + 20 ;
const y = rect . y + 20 ;
2023-12-06 15:27:31 +01:00
const clickHandle = await waitForPointerUp ( page ) ;
2023-04-16 21:36:26 +02:00
await page . mouse . move ( x , y ) ;
await page . mouse . down ( ) ;
await page . mouse . move ( x + 50 , y + 50 ) ;
await page . mouse . up ( ) ;
2023-12-06 15:27:31 +01:00
await awaitPromise ( clickHandle ) ;
2023-04-16 21:36:26 +02:00
2023-09-29 15:01:52 +02:00
await commit ( page ) ;
2023-04-16 21:36:26 +02:00
2023-09-29 15:01:52 +02:00
await selectAll ( page ) ;
2023-04-16 21:36:26 +02:00
2024-12-22 18:28:50 +01:00
expect ( await getEditors ( page , "selected" ) )
2023-04-16 21:36:26 +02:00
. withContext ( ` In ${ browserName } ` )
. toEqual ( [ 0 ] ) ;
} )
) ;
} ) ;
} ) ;
2023-12-04 13:27:30 +01:00
describe ( "Invisible layers must be disabled" , ( ) => {
let pages ;
2025-02-09 16:35:55 +01:00
beforeEach ( async ( ) => {
2023-12-04 13:27:30 +01:00
pages = await loadAndWait ( "tracemonkey.pdf" , ".annotationEditorLayer" ) ;
} ) ;
2025-02-09 16:35:55 +01:00
afterEach ( async ( ) => {
2023-12-04 13:27:30 +01:00
await closePages ( pages ) ;
} ) ;
it ( "must check that the editor layer is disabled" , async ( ) => {
await Promise . all (
pages . map ( async ( [ browserName , page ] ) => {
2024-05-24 19:11:37 +02:00
await switchToInk ( page ) ;
2023-12-04 13:27:30 +01:00
2024-05-23 17:53:58 +02:00
const rect = await getRect ( page , ".annotationEditorLayer" ) ;
2023-12-04 13:27:30 +01:00
const x = rect . x + 20 ;
const y = rect . y + 20 ;
2023-12-06 15:27:31 +01:00
const clickHandle = await waitForPointerUp ( page ) ;
2023-12-04 13:27:30 +01:00
await page . mouse . move ( x , y ) ;
await page . mouse . down ( ) ;
await page . mouse . move ( x + 50 , y + 50 ) ;
await page . mouse . up ( ) ;
2023-12-06 15:27:31 +01:00
await awaitPromise ( clickHandle ) ;
2023-12-04 13:27:30 +01:00
await commit ( page ) ;
const oneToFourteen = Array . from ( new Array ( 13 ) . keys ( ) , n => n + 2 ) ;
for ( const pageNumber of oneToFourteen ) {
await scrollIntoView (
page ,
` .page[data-page-number = " ${ pageNumber } "] `
) ;
}
2024-05-24 19:11:37 +02:00
await switchToInk ( page , /* disable */ true ) ;
2023-12-04 13:27:30 +01:00
const fourteenToOne = Array . from ( new Array ( 13 ) . keys ( ) , n => 13 - n ) ;
for ( const pageNumber of fourteenToOne ) {
await scrollIntoView (
page ,
` .page[data-page-number = " ${ pageNumber } "] `
) ;
}
await page . waitForSelector (
` .page[data-page-number = "1"] .annotationEditorLayer.disabled:not(.inkEditing) `
) ;
} )
) ;
} ) ;
} ) ;
2023-12-04 23:13:31 +01:00
describe ( "Ink editor must be committed when blurred" , ( ) => {
let pages ;
2025-02-09 16:35:55 +01:00
beforeEach ( async ( ) => {
2023-12-04 23:13:31 +01:00
pages = await loadAndWait ( "tracemonkey.pdf" , ".annotationEditorLayer" ) ;
} ) ;
2025-02-09 16:35:55 +01:00
afterEach ( async ( ) => {
2023-12-04 23:13:31 +01:00
await closePages ( pages ) ;
} ) ;
it ( "must check that the ink editor is committed" , async ( ) => {
await Promise . all (
pages . map ( async ( [ browserName , page ] ) => {
2024-05-24 19:11:37 +02:00
await switchToInk ( page ) ;
2023-12-04 23:13:31 +01:00
2024-05-23 17:53:58 +02:00
const rect = await getRect ( page , ".annotationEditorLayer" ) ;
2023-12-04 23:13:31 +01:00
const x = rect . x + 20 ;
const y = rect . y + 20 ;
2023-12-06 15:27:31 +01:00
const clickHandle = await waitForPointerUp ( page ) ;
2023-12-04 23:13:31 +01:00
await page . mouse . move ( x , y ) ;
await page . mouse . down ( ) ;
await page . mouse . move ( x + 50 , y + 50 ) ;
await page . mouse . up ( ) ;
2023-12-06 15:27:31 +01:00
await awaitPromise ( clickHandle ) ;
2023-12-04 23:13:31 +01:00
page . mouse . click ( rect . x - 10 , rect . y + 10 ) ;
await page . waitForSelector ( ` ${ getEditorSelector ( 0 ) } .disabled ` ) ;
} )
) ;
} ) ;
} ) ;
2024-03-22 19:30:56 +01:00
describe ( "Undo a draw" , ( ) => {
let pages ;
2025-02-09 16:35:55 +01:00
beforeEach ( async ( ) => {
2024-03-22 19:30:56 +01:00
pages = await loadAndWait ( "tracemonkey.pdf" , ".annotationEditorLayer" ) ;
} ) ;
2025-02-09 16:35:55 +01:00
afterEach ( async ( ) => {
2024-03-22 19:30:56 +01:00
await closePages ( pages ) ;
} ) ;
it ( "must check that a draw can be undone" , async ( ) => {
await Promise . all (
pages . map ( async ( [ browserName , page ] ) => {
2024-05-24 19:11:37 +02:00
await switchToInk ( page ) ;
2024-03-22 19:30:56 +01:00
2024-05-23 17:53:58 +02:00
const rect = await getRect ( page , ".annotationEditorLayer" ) ;
2024-03-22 19:30:56 +01:00
const xStart = rect . x + 300 ;
const yStart = rect . y + 300 ;
const clickHandle = await waitForPointerUp ( page ) ;
await page . mouse . move ( xStart , yStart ) ;
await page . mouse . down ( ) ;
await page . mouse . move ( xStart + 50 , yStart + 50 ) ;
await page . mouse . up ( ) ;
await awaitPromise ( clickHandle ) ;
await commit ( page ) ;
2025-01-19 19:46:50 +01:00
const editorSelector = getEditorSelector ( 0 ) ;
await page . waitForSelector ( editorSelector ) ;
2024-03-22 19:30:56 +01:00
await waitForSerialized ( page , 1 ) ;
2025-01-19 19:46:50 +01:00
await page . waitForSelector ( ` ${ editorSelector } button.delete ` ) ;
await page . click ( ` ${ editorSelector } button.delete ` ) ;
2024-03-22 19:30:56 +01:00
await waitForSerialized ( page , 0 ) ;
await kbUndo ( page ) ;
await waitForSerialized ( page , 1 ) ;
2025-01-19 19:46:50 +01:00
await page . waitForSelector ( editorSelector ) ;
2024-03-22 19:30:56 +01:00
} )
) ;
} ) ;
} ) ;
describe ( "Delete a draw and undo it on another page" , ( ) => {
let pages ;
2025-02-09 16:35:55 +01:00
beforeEach ( async ( ) => {
2024-03-22 19:30:56 +01:00
pages = await loadAndWait ( "tracemonkey.pdf" , ".annotationEditorLayer" ) ;
} ) ;
2025-02-09 16:35:55 +01:00
afterEach ( async ( ) => {
2024-03-22 19:30:56 +01:00
await closePages ( pages ) ;
} ) ;
it ( "must check that a draw can be undone" , async ( ) => {
await Promise . all (
pages . map ( async ( [ browserName , page ] ) => {
2024-05-24 19:11:37 +02:00
await switchToInk ( page ) ;
2024-03-22 19:30:56 +01:00
2024-05-23 17:53:58 +02:00
const rect = await getRect ( page , ".annotationEditorLayer" ) ;
2024-03-22 19:30:56 +01:00
const xStart = rect . x + 300 ;
const yStart = rect . y + 300 ;
const clickHandle = await waitForPointerUp ( page ) ;
await page . mouse . move ( xStart , yStart ) ;
await page . mouse . down ( ) ;
await page . mouse . move ( xStart + 50 , yStart + 50 ) ;
await page . mouse . up ( ) ;
await awaitPromise ( clickHandle ) ;
await commit ( page ) ;
2025-01-19 19:46:50 +01:00
const editorSelector = getEditorSelector ( 0 ) ;
await page . waitForSelector ( editorSelector ) ;
2024-03-22 19:30:56 +01:00
await waitForSerialized ( page , 1 ) ;
2025-01-19 19:46:50 +01:00
await page . waitForSelector ( ` ${ editorSelector } button.delete ` ) ;
await page . click ( ` ${ editorSelector } button.delete ` ) ;
2024-03-22 19:30:56 +01:00
await waitForSerialized ( page , 0 ) ;
const twoToFourteen = Array . from ( new Array ( 13 ) . keys ( ) , n => n + 2 ) ;
for ( const pageNumber of twoToFourteen ) {
const pageSelector = ` .page[data-page-number = " ${ pageNumber } "] ` ;
await scrollIntoView ( page , pageSelector ) ;
}
await kbUndo ( page ) ;
await waitForSerialized ( page , 1 ) ;
const thirteenToOne = Array . from ( new Array ( 13 ) . keys ( ) , n => 13 - n ) ;
for ( const pageNumber of thirteenToOne ) {
const pageSelector = ` .page[data-page-number = " ${ pageNumber } "] ` ;
await scrollIntoView ( page , pageSelector ) ;
}
2025-01-19 19:46:50 +01:00
await page . waitForSelector ( editorSelector ) ;
2024-03-22 19:30:56 +01:00
} )
) ;
} ) ;
} ) ;
describe ( "Delete a draw, scroll and undo it" , ( ) => {
let pages ;
2025-02-09 16:35:55 +01:00
beforeEach ( async ( ) => {
2024-03-22 19:30:56 +01:00
pages = await loadAndWait ( "tracemonkey.pdf" , ".annotationEditorLayer" ) ;
} ) ;
2025-02-09 16:35:55 +01:00
afterEach ( async ( ) => {
2024-03-22 19:30:56 +01:00
await closePages ( pages ) ;
} ) ;
it ( "must check that a draw can be undone" , async ( ) => {
await Promise . all (
pages . map ( async ( [ browserName , page ] ) => {
2024-05-24 19:11:37 +02:00
await switchToInk ( page ) ;
2024-03-22 19:30:56 +01:00
2024-05-23 17:53:58 +02:00
const rect = await getRect ( page , ".annotationEditorLayer" ) ;
2024-03-22 19:30:56 +01:00
const xStart = rect . x + 300 ;
const yStart = rect . y + 300 ;
const clickHandle = await waitForPointerUp ( page ) ;
await page . mouse . move ( xStart , yStart ) ;
await page . mouse . down ( ) ;
await page . mouse . move ( xStart + 50 , yStart + 50 ) ;
await page . mouse . up ( ) ;
await awaitPromise ( clickHandle ) ;
await commit ( page ) ;
2025-01-19 19:46:50 +01:00
const editorSelector = getEditorSelector ( 0 ) ;
await page . waitForSelector ( editorSelector ) ;
2024-03-22 19:30:56 +01:00
await waitForSerialized ( page , 1 ) ;
2025-01-19 19:46:50 +01:00
await page . waitForSelector ( ` ${ editorSelector } button.delete ` ) ;
await page . click ( ` ${ editorSelector } button.delete ` ) ;
2024-03-22 19:30:56 +01:00
await waitForSerialized ( page , 0 ) ;
const twoToOne = Array . from ( new Array ( 13 ) . keys ( ) , n => n + 2 ) . concat (
Array . from ( new Array ( 13 ) . keys ( ) , n => 13 - n )
) ;
for ( const pageNumber of twoToOne ) {
const pageSelector = ` .page[data-page-number = " ${ pageNumber } "] ` ;
await scrollIntoView ( page , pageSelector ) ;
}
await kbUndo ( page ) ;
await waitForSerialized ( page , 1 ) ;
2025-01-19 19:46:50 +01:00
await page . waitForSelector ( editorSelector ) ;
2024-03-22 19:30:56 +01:00
} )
) ;
} ) ;
} ) ;
2024-04-08 18:07:34 +02:00
describe ( "Draw several times in the same editor" , ( ) => {
let pages ;
2025-02-09 16:35:55 +01:00
beforeEach ( async ( ) => {
2024-04-08 18:07:34 +02:00
pages = await loadAndWait ( "empty.pdf" , ".annotationEditorLayer" ) ;
} ) ;
2025-02-09 16:35:55 +01:00
afterEach ( async ( ) => {
2024-04-08 18:07:34 +02:00
await closePages ( pages ) ;
} ) ;
it ( "must check that we can draw several times on the same canvas" , async ( ) => {
await Promise . all (
pages . map ( async ( [ browserName , page ] ) => {
2024-05-24 19:11:37 +02:00
await switchToInk ( page ) ;
2024-05-23 17:53:58 +02:00
const rect = await getRect ( page , ".annotationEditorLayer" ) ;
2024-04-08 18:07:34 +02:00
let xStart = rect . x + 10 ;
const yStart = rect . y + 10 ;
for ( let i = 0 ; i < 5 ; i ++ ) {
const clickHandle = await waitForPointerUp ( page ) ;
await page . mouse . move ( xStart , yStart ) ;
await page . mouse . down ( ) ;
await page . mouse . move ( xStart + 50 , yStart + 50 ) ;
await page . mouse . up ( ) ;
await awaitPromise ( clickHandle ) ;
xStart += 70 ;
}
await commit ( page ) ;
await page . waitForSelector ( getEditorSelector ( 0 ) ) ;
} )
) ;
} ) ;
} ) ;
2024-11-20 22:26:38 +01:00
describe ( "Drawing must unselect all" , ( ) => {
let pages ;
2025-02-09 16:35:55 +01:00
beforeEach ( async ( ) => {
2024-11-20 22:26:38 +01:00
pages = await loadAndWait ( "empty.pdf" , ".annotationEditorLayer" ) ;
} ) ;
2025-02-09 16:35:55 +01:00
afterEach ( async ( ) => {
2024-11-20 22:26:38 +01:00
await closePages ( pages ) ;
} ) ;
it ( "must check that when we start to draw then the editors are unselected" , async ( ) => {
await Promise . all (
pages . map ( async ( [ browserName , page ] ) => {
await switchToInk ( page ) ;
const rect = await getRect ( page , ".annotationEditorLayer" ) ;
let xStart = rect . x + 10 ;
const yStart = rect . y + 10 ;
for ( let i = 0 ; i < 2 ; i ++ ) {
const clickHandle = await waitForPointerUp ( page ) ;
await page . mouse . move ( xStart , yStart ) ;
await page . mouse . down ( ) ;
if ( i === 1 ) {
2024-12-22 18:28:50 +01:00
expect ( await getEditors ( page , "selected" ) )
2024-11-20 22:26:38 +01:00
. withContext ( ` In ${ browserName } ` )
. toEqual ( [ ] ) ;
}
await page . mouse . move ( xStart + 50 , yStart + 50 ) ;
await page . mouse . up ( ) ;
await awaitPromise ( clickHandle ) ;
await commit ( page ) ;
xStart += 70 ;
}
} )
) ;
} ) ;
} ) ;
describe ( "Selected editor must be updated even if the page has been destroyed" , ( ) => {
let pages ;
2025-02-09 16:35:55 +01:00
beforeEach ( async ( ) => {
2024-11-20 22:26:38 +01:00
pages = await loadAndWait ( "tracemonkey.pdf" , ".annotationEditorLayer" ) ;
} ) ;
2025-02-09 16:35:55 +01:00
afterEach ( async ( ) => {
2024-11-20 22:26:38 +01:00
await closePages ( pages ) ;
} ) ;
it ( "must check that the color has been changed" , async ( ) => {
await Promise . all (
pages . map ( async ( [ browserName , page ] ) => {
await switchToInk ( page ) ;
const rect = await getRect ( page , ".annotationEditorLayer" ) ;
const x = rect . x + 20 ;
const y = rect . y + 20 ;
const clickHandle = await waitForPointerUp ( page ) ;
await page . mouse . move ( x , y ) ;
await page . mouse . down ( ) ;
await page . mouse . move ( x + 50 , y + 50 ) ;
await page . mouse . up ( ) ;
await awaitPromise ( clickHandle ) ;
await commit ( page ) ;
const drawSelector = ` .page[data-page-number = "1"] .canvasWrapper .draw ` ;
await page . waitForSelector ( drawSelector , { visible : true } ) ;
let color = await page . evaluate ( sel => {
const el = document . querySelector ( sel ) ;
return el . getAttribute ( "stroke" ) ;
} , drawSelector ) ;
expect ( color ) . toEqual ( "#000000" ) ;
const oneToFourteen = Array . from ( new Array ( 13 ) . keys ( ) , n => n + 2 ) ;
for ( const pageNumber of oneToFourteen ) {
await scrollIntoView (
page ,
` .page[data-page-number = " ${ pageNumber } "] `
) ;
}
const red = "#ff0000" ;
page . evaluate ( value => {
window . PDFViewerApplication . eventBus . dispatch (
"switchannotationeditorparams" ,
{
source : null ,
type : window . pdfjsLib . AnnotationEditorParamsType . INK _COLOR ,
value ,
}
) ;
} , red ) ;
const fourteenToOne = Array . from ( new Array ( 13 ) . keys ( ) , n => 13 - n ) ;
for ( const pageNumber of fourteenToOne ) {
await scrollIntoView (
page ,
` .page[data-page-number = " ${ pageNumber } "] `
) ;
}
await page . waitForSelector ( drawSelector , { visible : true } ) ;
color = await page . evaluate ( sel => {
const el = document . querySelector ( sel ) ;
return el . getAttribute ( "stroke" ) ;
} , drawSelector ) ;
expect ( color ) . toEqual ( red ) ;
} )
) ;
} ) ;
} ) ;
2024-11-29 16:22:44 +01:00
describe ( "Can delete the drawing in progress and undo the deletion" , ( ) => {
let pages ;
2025-02-09 16:35:55 +01:00
beforeEach ( async ( ) => {
2024-11-29 16:22:44 +01:00
pages = await loadAndWait ( "empty.pdf" , ".annotationEditorLayer" ) ;
} ) ;
2025-02-09 16:35:55 +01:00
afterEach ( async ( ) => {
2024-11-29 16:22:44 +01:00
await closePages ( pages ) ;
} ) ;
2024-12-01 21:15:57 +01:00
it ( "must check that the deletion has been undid" , async ( ) => {
2024-11-29 16:22:44 +01:00
await Promise . all (
pages . map ( async ( [ browserName , page ] ) => {
await switchToInk ( page ) ;
const rect = await getRect ( page , ".annotationEditorLayer" ) ;
const x = rect . x + 20 ;
const y = rect . y + 20 ;
const clickHandle = await waitForPointerUp ( page ) ;
await page . mouse . move ( x , y ) ;
await page . mouse . down ( ) ;
await page . mouse . move ( x + 50 , y + 50 ) ;
await page . mouse . up ( ) ;
await awaitPromise ( clickHandle ) ;
const drawSelector = ` .canvasWrapper svg.draw path[d]:not([d=""]) ` ;
await page . waitForSelector ( drawSelector ) ;
await page . keyboard . press ( "Backspace" ) ;
const editorSelector = getEditorSelector ( 0 ) ;
await waitForNoElement ( page , drawSelector ) ;
await waitForNoElement ( page , editorSelector ) ;
await kbUndo ( page ) ;
await page . waitForSelector ( editorSelector , { visible : true } ) ;
await page . waitForSelector ( drawSelector ) ;
} )
) ;
} ) ;
} ) ;
2024-12-02 11:06:13 +01:00
describe ( "Annotation mustn't take focus if it isn't visible" , ( ) => {
let pages ;
2025-02-09 16:35:55 +01:00
beforeEach ( async ( ) => {
2024-12-02 11:06:13 +01:00
pages = await loadAndWait ( "tracemonkey.pdf" , ".annotationEditorLayer" ) ;
} ) ;
2025-02-09 16:35:55 +01:00
afterEach ( async ( ) => {
2024-12-02 11:06:13 +01:00
await closePages ( pages ) ;
} ) ;
it ( "must check that the focus isn't taken" , async ( ) => {
await Promise . all (
pages . map ( async ( [ browserName , page ] ) => {
await switchToInk ( page ) ;
const rect = await getRect ( page , ".annotationEditorLayer" ) ;
const x = rect . x + 20 ;
const y = rect . y + 20 ;
const clickHandle = await waitForPointerUp ( page ) ;
await page . mouse . move ( x , y ) ;
await page . mouse . down ( ) ;
await page . mouse . move ( x + 50 , y + 50 ) ;
await page . mouse . up ( ) ;
await awaitPromise ( clickHandle ) ;
await page . evaluate ( ( ) => {
window . focusedIds = [ ] ;
window . focusCallback = e => {
window . focusedIds . push ( e . target . id ) ;
} ;
window . addEventListener ( "focusin" , window . focusCallback ) ;
} ) ;
const oneToFourteen = Array . from ( new Array ( 13 ) . keys ( ) , n => n + 2 ) ;
for ( const pageNumber of oneToFourteen ) {
await scrollIntoView (
page ,
` .page[data-page-number = " ${ pageNumber } "] `
) ;
}
const ids = await page . evaluate ( ( ) => {
const { focusedIds , focusCallback } = window ;
window . removeEventListener ( "focusin" , focusCallback ) ;
delete window . focusCallback ;
delete window . focusedIds ;
return focusedIds ;
} ) ;
expect ( ids ) . withContext ( ` In ${ browserName } ` ) . toEqual ( [ ] ) ;
} )
) ;
} ) ;
} ) ;
2024-12-01 21:15:57 +01:00
describe ( "Ink (update existing)" , ( ) => {
let pages ;
2025-02-09 16:35:55 +01:00
beforeEach ( async ( ) => {
2024-12-01 21:15:57 +01:00
pages = await loadAndWait ( "inks.pdf" , ".annotationEditorLayer" ) ;
} ) ;
2025-02-09 16:35:55 +01:00
afterEach ( async ( ) => {
2024-12-01 21:15:57 +01:00
await closePages ( pages ) ;
} ) ;
it ( "must update an existing annotation" , async ( ) => {
await Promise . all (
pages . map ( async ( [ browserName , page ] ) => {
const annotationsRect = await page . evaluate ( ( ) => {
let xm = Infinity ,
xM = - Infinity ,
ym = Infinity ,
yM = - Infinity ;
for ( const el of document . querySelectorAll (
"section.inkAnnotation"
) ) {
const { x , y , width , height } = el . getBoundingClientRect ( ) ;
xm = Math . min ( xm , x ) ;
xM = Math . max ( xM , x + width ) ;
ym = Math . min ( ym , y ) ;
yM = Math . max ( yM , y + height ) ;
}
return { x : xm , y : ym , width : xM - xm , height : yM - ym } ;
} ) ;
await switchToInk ( page ) ;
// The page has been re-rendered but with no ink annotations.
2025-03-06 14:59:04 +01:00
let isWhite = await isCanvasMonochrome (
page ,
1 ,
annotationsRect ,
0xffffffff
) ;
2024-12-01 21:15:57 +01:00
expect ( isWhite ) . withContext ( ` In ${ browserName } ` ) . toBeTrue ( ) ;
let editorIds = await getEditors ( page , "ink" ) ;
expect ( editorIds . length ) . withContext ( ` In ${ browserName } ` ) . toEqual ( 15 ) ;
const pdfjsA = getEditorSelector ( 0 ) ;
const editorRect = await getRect ( page , pdfjsA ) ;
2025-01-18 19:21:55 +01:00
await selectEditor ( page , pdfjsA ) ;
2024-12-01 21:15:57 +01:00
const red = "#ff0000" ;
page . evaluate ( value => {
window . PDFViewerApplication . eventBus . dispatch (
"switchannotationeditorparams" ,
{
source : null ,
type : window . pdfjsLib . AnnotationEditorParamsType . INK _COLOR ,
value ,
}
) ;
} , red ) ;
const serialized = await getSerialized ( page ) ;
expect ( serialized . length ) . withContext ( ` In ${ browserName } ` ) . toEqual ( 1 ) ;
expect ( serialized [ 0 ] . color ) . toEqual ( [ 255 , 0 , 0 ] ) ;
// Disable editing mode.
await switchToInk ( page , /* disable = */ true ) ;
// We want to check that the editor is displayed but not the original
// canvas.
editorIds = await getEditors ( page , "ink" ) ;
expect ( editorIds . length ) . withContext ( ` In ${ browserName } ` ) . toEqual ( 1 ) ;
2025-03-06 14:59:04 +01:00
isWhite = await isCanvasMonochrome ( page , 1 , editorRect , 0xffffffff ) ;
2024-12-01 21:15:57 +01:00
expect ( isWhite ) . withContext ( ` In ${ browserName } ` ) . toBeTrue ( ) ;
// Check we've now a svg with a red stroke.
await page . waitForSelector ( "svg[stroke = '#ff0000']" , {
visible : true ,
} ) ;
// Re-enable editing mode.
await switchToInk ( page ) ;
await page . focus ( ".annotationEditorLayer" ) ;
await kbUndo ( page ) ;
await waitForSerialized ( page , 0 ) ;
editorIds = await getEditors ( page , "ink" ) ;
expect ( editorIds . length ) . withContext ( ` In ${ browserName } ` ) . toEqual ( 15 ) ;
// Undo again.
await kbUndo ( page ) ;
// Nothing should happen, it's why we can't wait for something
// specific!
// eslint-disable-next-line no-restricted-syntax
await waitForTimeout ( 200 ) ;
// We check that the editor hasn't been removed.
editorIds = await getEditors ( page , "ink" ) ;
expect ( editorIds . length ) . withContext ( ` In ${ browserName } ` ) . toEqual ( 15 ) ;
} )
) ;
} ) ;
} ) ;
describe ( "Ink (move existing)" , ( ) => {
let pages ;
2025-02-09 16:35:55 +01:00
beforeEach ( async ( ) => {
2024-12-01 21:15:57 +01:00
pages = await loadAndWait ( "inks.pdf" , getAnnotationSelector ( "277R" ) ) ;
} ) ;
2025-02-09 16:35:55 +01:00
afterEach ( async ( ) => {
2024-12-01 21:15:57 +01:00
await closePages ( pages ) ;
} ) ;
it ( "must move an annotation" , async ( ) => {
await Promise . all (
pages . map ( async ( [ browserName , page ] ) => {
2024-12-04 17:57:17 +01:00
const modeChangedHandle = await waitForAnnotationModeChanged ( page ) ;
const inkRect = await getRect ( page , getAnnotationSelector ( "277R" ) ) ;
await page . mouse . click (
inkRect . x + inkRect . width / 2 ,
inkRect . y + inkRect . height / 2 ,
{ count : 2 }
) ;
await awaitPromise ( modeChangedHandle ) ;
2024-12-01 21:15:57 +01:00
const edgeB = getEditorSelector ( 10 ) ;
await waitForSelectedEditor ( page , edgeB ) ;
const editorIds = await getEditors ( page , "ink" ) ;
expect ( editorIds . length ) . withContext ( ` In ${ browserName } ` ) . toEqual ( 15 ) ;
// All the current annotations should be serialized as null objects
// because they haven't been edited yet.
const serialized = await getSerialized ( page ) ;
expect ( serialized ) . withContext ( ` In ${ browserName } ` ) . toEqual ( [ ] ) ;
// Select the annotation we want to move.
2025-01-18 19:21:55 +01:00
await selectEditor ( page , edgeB ) ;
2024-12-01 21:15:57 +01:00
2024-12-09 16:07:39 +01:00
await dragAndDrop ( page , edgeB , [ [ 100 , 100 ] ] ) ;
2024-12-01 21:15:57 +01:00
await waitForSerialized ( page , 1 ) ;
} )
) ;
} ) ;
} ) ;
2024-10-19 02:19:46 +05:30
describe ( "Undo deletion popup has the expected behaviour" , ( ) => {
let pages ;
const editorSelector = getEditorSelector ( 0 ) ;
beforeEach ( async ( ) => {
pages = await loadAndWait ( "tracemonkey.pdf" , ".annotationEditorLayer" ) ;
} ) ;
afterEach ( async ( ) => {
await closePages ( pages ) ;
} ) ;
it ( "must check that deleting a drawing can be undone using the undo button" , async ( ) => {
await Promise . all (
pages . map ( async ( [ browserName , page ] ) => {
await switchToInk ( page ) ;
const rect = await getRect ( page , ".annotationEditorLayer" ) ;
const xStart = rect . x + 300 ;
const yStart = rect . y + 300 ;
const clickHandle = await waitForPointerUp ( page ) ;
await page . mouse . move ( xStart , yStart ) ;
await page . mouse . down ( ) ;
await page . mouse . move ( xStart + 50 , yStart + 50 ) ;
await page . mouse . up ( ) ;
await awaitPromise ( clickHandle ) ;
await commit ( page ) ;
await page . waitForSelector ( editorSelector ) ;
await waitForSerialized ( page , 1 ) ;
await page . waitForSelector ( ` ${ editorSelector } button.delete ` ) ;
await page . click ( ` ${ editorSelector } button.delete ` ) ;
await waitForSerialized ( page , 0 ) ;
await page . waitForSelector ( "#editorUndoBar:not([hidden])" ) ;
await page . click ( "#editorUndoBarUndoButton" ) ;
await waitForSerialized ( page , 1 ) ;
await page . waitForSelector ( editorSelector ) ;
} )
) ;
} ) ;
it ( "must check that the undo deletion popup displays the correct message" , async ( ) => {
await Promise . all (
pages . map ( async ( [ browserName , page ] ) => {
await switchToInk ( page ) ;
const rect = await getRect ( page , ".annotationEditorLayer" ) ;
const xStart = rect . x + 300 ;
const yStart = rect . y + 300 ;
const clickHandle = await waitForPointerUp ( page ) ;
await page . mouse . move ( xStart , yStart ) ;
await page . mouse . down ( ) ;
await page . mouse . move ( xStart + 50 , yStart + 50 ) ;
await page . mouse . up ( ) ;
await awaitPromise ( clickHandle ) ;
await commit ( page ) ;
await page . waitForSelector ( editorSelector ) ;
await waitForSerialized ( page , 1 ) ;
await page . waitForSelector ( ` ${ editorSelector } button.delete ` ) ;
await page . click ( ` ${ editorSelector } button.delete ` ) ;
await waitForSerialized ( page , 0 ) ;
await page . waitForFunction ( ( ) => {
const messageElement = document . querySelector (
"#editorUndoBarMessage"
) ;
return messageElement && messageElement . textContent . trim ( ) !== "" ;
} ) ;
const message = await page . waitForSelector ( "#editorUndoBarMessage" ) ;
const messageText = await page . evaluate (
el => el . textContent ,
message
) ;
expect ( messageText ) . toContain ( "Drawing removed" ) ;
} )
) ;
} ) ;
it ( "must check that the popup disappears when a new drawing is created" , async ( ) => {
await Promise . all (
pages . map ( async ( [ browserName , page ] ) => {
await switchToInk ( page ) ;
const rect = await getRect ( page , ".annotationEditorLayer" ) ;
const xStart = rect . x + 300 ;
const yStart = rect . y + 300 ;
const clickHandle = await waitForPointerUp ( page ) ;
await page . mouse . move ( xStart , yStart ) ;
await page . mouse . down ( ) ;
await page . mouse . move ( xStart + 50 , yStart + 50 ) ;
await page . mouse . up ( ) ;
await awaitPromise ( clickHandle ) ;
await commit ( page ) ;
await page . waitForSelector ( editorSelector ) ;
await waitForSerialized ( page , 1 ) ;
await page . waitForSelector ( ` ${ editorSelector } button.delete ` ) ;
await page . click ( ` ${ editorSelector } button.delete ` ) ;
await waitForSerialized ( page , 0 ) ;
await page . waitForSelector ( "#editorUndoBar:not([hidden])" ) ;
const newRect = await getRect ( page , ".annotationEditorLayer" ) ;
const newXStart = newRect . x + 300 ;
const newYStart = newRect . y + 300 ;
const newClickHandle = await waitForPointerUp ( page ) ;
await page . mouse . move ( newXStart , newYStart ) ;
await page . mouse . down ( ) ;
await page . mouse . move ( newXStart + 50 , newYStart + 50 ) ;
await page . mouse . up ( ) ;
await awaitPromise ( newClickHandle ) ;
await commit ( page ) ;
await page . waitForSelector ( getEditorSelector ( 1 ) ) ;
await waitForSerialized ( page , 1 ) ;
await page . waitForSelector ( "#editorUndoBar" , { hidden : true } ) ;
} )
) ;
} ) ;
} ) ;
2024-12-05 14:22:00 +01:00
describe ( "Ink must update its stroke width when not the current active layer" , ( ) => {
let pages ;
2025-02-09 16:35:55 +01:00
beforeEach ( async ( ) => {
2024-12-05 14:22:00 +01:00
pages = await loadAndWait ( "tracemonkey.pdf" , ".annotationEditorLayer" ) ;
} ) ;
2025-02-09 16:35:55 +01:00
afterEach ( async ( ) => {
2024-12-05 14:22:00 +01:00
await closePages ( pages ) ;
} ) ;
it ( "must check that the stroke width has been updated after zooming" , async ( ) => {
await Promise . all (
pages . map ( async ( [ browserName , page ] ) => {
await switchToInk ( page ) ;
const rect = await getRect ( page , ".annotationEditorLayer" ) ;
const x = rect . x + 20 ;
const y = rect . y + 20 ;
const clickHandle = await waitForPointerUp ( page ) ;
await page . mouse . move ( x , y ) ;
await page . mouse . down ( ) ;
await page . mouse . move ( x + 50 , y + 50 ) ;
await page . mouse . up ( ) ;
await awaitPromise ( clickHandle ) ;
const svgSelector = ".canvasWrapper svg.draw" ;
const strokeWidth = await page . $eval ( svgSelector , el =>
parseFloat ( el . getAttribute ( "stroke-width" ) )
) ;
await scrollIntoView ( page , ` .page[data-page-number = "2"] ` ) ;
const rectPageTwo = await getRect (
page ,
` .page[data-page-number = "2"] .annotationEditorLayer `
) ;
const originX = rectPageTwo . x + rectPageTwo . width / 2 ;
const originY = rectPageTwo . y + rectPageTwo . height / 2 ;
await page . evaluate (
origin => {
window . PDFViewerApplication . pdfViewer . increaseScale ( {
scaleFactor : 1.5 ,
origin ,
} ) ;
} ,
[ originX , originY ]
) ;
const newStrokeWidth = await page . $eval ( svgSelector , el =>
parseFloat ( el . getAttribute ( "stroke-width" ) )
) ;
expect ( newStrokeWidth )
. withContext ( ` In ${ browserName } ` )
. not . toEqual ( strokeWidth ) ;
} )
) ;
} ) ;
} ) ;
2025-01-08 20:44:11 +01:00
describe ( "Draw annotations on several page, move one of them and delete it" , ( ) => {
let pages ;
2025-02-09 16:35:55 +01:00
beforeEach ( async ( ) => {
2025-01-08 20:44:11 +01:00
pages = await loadAndWait (
"tracemonkey.pdf" ,
".annotationEditorLayer" ,
10
) ;
} ) ;
2025-02-09 16:35:55 +01:00
afterEach ( async ( ) => {
2025-01-08 20:44:11 +01:00
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 ) ;
2025-01-18 19:21:55 +01:00
await selectEditor ( page , editorSelector ) ;
2025-01-08 20:44:11 +01:00
await dragAndDrop ( page , editorSelector , [ [ 30 , 30 ] ] , /* steps = */ 10 ) ;
const finalRect = await getRect ( page , ` ${ pageOneSelector } svg ` ) ;
expect ( initialRect )
. withContext ( ` In ${ browserName } ` )
. not . toEqual ( finalRect ) ;
} )
) ;
} ) ;
} ) ;
2025-01-17 13:45:22 +01:00
describe ( "Page position should remain unchanged after drawing" , ( ) => {
let pages ;
2025-02-09 16:35:55 +01:00
beforeEach ( async ( ) => {
2025-01-17 13:45:22 +01:00
pages = await loadAndWait ( "tracemonkey.pdf" , ".annotationEditorLayer" ) ;
} ) ;
2025-02-09 16:35:55 +01:00
afterEach ( async ( ) => {
2025-01-17 13:45:22 +01:00
await closePages ( pages ) ;
} ) ;
it ( "must check that the page position remains the same after drawing" , async ( ) => {
await Promise . all (
pages . map ( async ( [ browserName , page ] ) => {
const pageInitialPosition = await getRect (
page ,
".page[data-page-number='1']"
) ;
await switchToInk ( page ) ;
const editorLayerRect = await getRect ( page , ".annotationEditorLayer" ) ;
const drawStartX = editorLayerRect . x + 100 ;
const drawStartY = editorLayerRect . y + 100 ;
const clickHandle = await waitForPointerUp ( page ) ;
await page . mouse . move ( drawStartX , drawStartY ) ;
await page . mouse . down ( ) ;
await page . mouse . move ( drawStartX + 50 , drawStartY + 50 ) ;
await page . mouse . up ( ) ;
await awaitPromise ( clickHandle ) ;
await commit ( page ) ;
const pageFinalPosition = await getRect (
page ,
".page[data-page-number='1']"
) ;
expect ( pageInitialPosition . x )
. withContext ( ` In ${ browserName } ` )
. toEqual ( pageFinalPosition . x ) ;
expect ( pageInitialPosition . y )
. withContext ( ` In ${ browserName } ` )
. toEqual ( pageFinalPosition . y ) ;
} )
) ;
} ) ;
} ) ;
2022-07-22 12:13:47 +02:00
} ) ;
2025-01-23 17:47:29 +02:00
describe ( "The pen-drawn shape must maintain correct curvature regardless of the page it is drawn on or whether the curve's endpoint lies within or beyond the page boundaries" , ( ) => {
let pages ;
2025-02-09 16:35:55 +01:00
beforeEach ( async ( ) => {
2025-01-23 17:47:29 +02:00
pages = await loadAndWait ( "tracemonkey.pdf" , ".annotationEditorLayer" ) ;
} ) ;
2025-02-09 16:35:55 +01:00
afterEach ( async ( ) => {
2025-01-23 17:47:29 +02:00
await closePages ( pages ) ;
} ) ;
const getCurveOnPage = async ( { pageNumber = 1 , page } ) => {
const clickHandle = await waitForPointerUp ( page ) ;
const pageSelector = ` .page[data-page-number = " ${ pageNumber } "] ` ;
await scrollIntoView ( page , pageSelector ) ;
await page . waitForSelector ( pageSelector ) ;
const rect = await getRect ( page , ` ${ pageSelector } .annotationEditorLayer ` ) ;
const x = rect . x + 100 ;
const y = rect . y + 200 ;
await page . mouse . move ( x , y ) ;
await page . mouse . down ( ) ;
// Create a reference curve on first page.
await page . mouse . move ( x - 100 , y ) ;
if ( page !== 1 ) {
// Add a move to create a curve that extends beyond the page boundary.
await page . mouse . move ( x - 200 , y ) ;
}
await page . mouse . up ( ) ;
await awaitPromise ( clickHandle ) ;
const d = await page . $eval (
` ${ pageSelector } .canvasWrapper svg.draw path[d]:not([d=""]) ` ,
el => el . getAttribute ( "d" )
) ;
return d ;
} ;
it ( "must retain correct curvature regardless of the page or the curve's endpoint location" , async ( ) => {
await Promise . all (
pages . map ( async ( [ browserName , page ] ) => {
await switchToInk ( page ) ;
// Creating a reference curve on the first page with end
// within the page boundaries.
const d1 = await getCurveOnPage ( { pageNumber : 1 , page } ) ;
// Creating a curve on the second page with end
// beyond the page boundaries.
const d2 = await getCurveOnPage ( { pageNumber : 2 , page } ) ;
// Expect that the endpoint beyond the boundaries is ignored,
// ensuring both curves have the same shape on both pages.
expect ( d1 ) . withContext ( ` In ${ browserName } ` ) . toEqual ( d2 ) ;
} )
) ;
} ) ;
} ) ;