1
+ import {
2
+ getUIMode ,
3
+ test ,
4
+ WebViewerInstance ,
5
+ setupWebViewer ,
6
+ waitForWVEvent ,
7
+ evaluateAndWaitForEvent ,
8
+ } from '../../playwright-utility-setup' ;
9
+ import { expect , Frame , Page } from '@playwright/test' ;
10
+
11
+ test . describe ( 'Accessible Mode Tests' , ( ) => {
12
+ let iframe : Frame | Page ;
13
+ let instance : WebViewerInstance ;
14
+
15
+ const isAROModeEnabled = async ( iframe : Frame | Page ) => {
16
+ return iframe . evaluate ( ( ) => {
17
+ return window . instance . Core . documentViewer . getAccessibleReadingOrderManager ( ) . isInAccessibleReadingOrderMode ( ) ;
18
+ } ) ;
19
+ } ;
20
+
21
+ test . describe ( 'Loading a XOD file' , ( ) => {
22
+ test . beforeEach ( async ( { page } ) => {
23
+ const {
24
+ iframe : iframeRef ,
25
+ instance : instanceWebViewer ,
26
+ } = await setupWebViewer ( {
27
+ page,
28
+ samplePath : 'advanced/accessibility' ,
29
+ } ) ;
30
+
31
+ iframe = iframeRef ;
32
+ instance = instanceWebViewer ;
33
+
34
+ await expect ( async ( ) => {
35
+ await evaluateAndWaitForEvent (
36
+ iframe ,
37
+ async ( ) => window . instance . Core . documentViewer . loadDocument ( '/test-files/demo-annotated.xod' ) ,
38
+ 'AccessibleReadingOrderManager.accessibleReadingOrderModeNoStructure' ,
39
+ ) ;
40
+ } ) . toPass ( ) ;
41
+
42
+ const loadingModal = iframe . locator ( '[data-element="loadingModal"]' ) ;
43
+ await expect ( async ( ) => {
44
+ await expect ( loadingModal ) . toHaveCount ( 0 ) ;
45
+ } ) . toPass ( ) ;
46
+ } ) ;
47
+
48
+ // Flaky test: https://app.circleci.com/pipelines/github/XodoDocs/webviewer/123371/workflows/e28c18bd-f750-4335-b6f1-22752562fbcc/jobs/151298/tests
49
+ // Jira ticket: https://apryse.atlassian.net/browse/WVR-7712
50
+ test . skip ( 'Should tab into the current page from outside of the document' , async ( { page, browserName } , testInfo ) => {
51
+ test . skip ( testInfo . project . use . webComponent , 'TODO: This test is failing when using with web component' ) ;
52
+ test . skip ( browserName === 'webkit' , 'TODO: investigate why this test is flaky on webkit' ) ;
53
+
54
+ await iframe . evaluate ( async ( ) => {
55
+ window . instance . Core . documentViewer . setCurrentPage ( 2 ) ;
56
+ } ) ;
57
+
58
+ await waitForWVEvent ( iframe , 'pageComplete' ) ;
59
+
60
+ let currentPageNumber = await iframe . evaluate ( async ( ) => {
61
+ return instance . Core . documentViewer . getCurrentPage ( ) ;
62
+ } ) ;
63
+ expect ( currentPageNumber ) . toBe ( 2 ) ;
64
+
65
+ await instance ( 'closeElements' , [ 'loadingModal' ] ) ;
66
+
67
+ const notesPanelButtonSelector = ( getUIMode ( ) === 'default' ) ? 'notesPanelToggle' : 'toggleNotesButton' ;
68
+ await iframe . locator ( `[data-element="${ notesPanelButtonSelector } "]` ) . click ( ) ;
69
+
70
+ await page . keyboard . press ( 'Tab' ) ;
71
+
72
+ currentPageNumber = await iframe . evaluate ( async ( ) => {
73
+ return instance . Core . documentViewer . getCurrentPage ( ) ;
74
+ } ) ;
75
+ expect ( currentPageNumber ) . toBe ( 2 ) ;
76
+ } ) ;
77
+
78
+ test . skip ( 'Should go to the correct page when pressing the document button in accessibility popup' , async ( { page, browserName } ) => {
79
+ test . skip ( browserName === 'webkit' , 'TODO: investigate why this test is flaky on webkit' ) ;
80
+
81
+ await iframe . evaluate ( async ( ) => {
82
+ window . instance . Core . documentViewer . setCurrentPage ( 9 ) ;
83
+ } ) ;
84
+
85
+ await waitForWVEvent ( iframe , 'pageComplete' ) ;
86
+
87
+ let currentPageNumber = await iframe . evaluate ( async ( ) => {
88
+ return instance . Core . documentViewer . getCurrentPage ( ) ;
89
+ } ) ;
90
+ expect ( currentPageNumber ) . toBe ( 9 ) ;
91
+
92
+ await page . locator ( '#play' ) . click ( ) ;
93
+
94
+ // press tab 6 times to get to the accessibility popup
95
+ // timeout of 200 used to make test more consistent
96
+ await page . keyboard . press ( 'Tab' ) ;
97
+ // eslint-disable-next-line playwright/no-wait-for-timeout
98
+ await page . waitForTimeout ( 200 ) ;
99
+ await page . keyboard . press ( 'Tab' ) ;
100
+ // eslint-disable-next-line playwright/no-wait-for-timeout
101
+ await page . waitForTimeout ( 200 ) ;
102
+ await page . keyboard . press ( 'Tab' ) ;
103
+ // eslint-disable-next-line playwright/no-wait-for-timeout
104
+ await page . waitForTimeout ( 200 ) ;
105
+ await page . keyboard . press ( 'Tab' ) ;
106
+ // eslint-disable-next-line playwright/no-wait-for-timeout
107
+ await page . waitForTimeout ( 200 ) ;
108
+ await page . keyboard . press ( 'Tab' ) ;
109
+ // eslint-disable-next-line playwright/no-wait-for-timeout
110
+ await page . waitForTimeout ( 200 ) ;
111
+ await page . keyboard . press ( 'Tab' ) ;
112
+ // eslint-disable-next-line playwright/no-wait-for-timeout
113
+ await page . waitForTimeout ( 200 ) ;
114
+
115
+ await page . keyboard . press ( 'Enter' ) ;
116
+ // eslint-disable-next-line playwright/no-wait-for-timeout
117
+ await page . waitForTimeout ( 200 ) ;
118
+
119
+ currentPageNumber = await iframe . evaluate ( async ( ) => {
120
+ return instance . Core . documentViewer . getCurrentPage ( ) ;
121
+ } ) ;
122
+ expect ( currentPageNumber ) . toBe ( 9 ) ;
123
+ } ) ;
124
+
125
+ test ( 'Tabs correctly through pages and links' , async ( { page, browserName } , testInfo ) => {
126
+ test . skip ( testInfo . project . use . webComponent , 'TODO: This test is failing when using with web component' ) ;
127
+ test . skip ( browserName === 'firefox' || browserName === 'webkit' , 'TODO: investigate why this test fails on webkit and firefox' ) ;
128
+
129
+ // add a link
130
+ await evaluateAndWaitForEvent (
131
+ iframe ,
132
+ async ( ) => {
133
+ const core = window . instance . Core ;
134
+
135
+ const annot = new core . Annotations . RectangleAnnotation ( {
136
+ PageNumber : 1 ,
137
+ X : 50 ,
138
+ Y : 100 ,
139
+ Width : 150 ,
140
+ Height : 100 ,
141
+ } ) ;
142
+
143
+ core . annotationManager . addAnnotation ( annot ) ;
144
+ core . annotationManager . redrawAnnotation ( annot ) ;
145
+
146
+ const annotations = core . annotationManager . getAnnotationsList ( ) ;
147
+ const targetAnnotation = annotations [ 0 ] ;
148
+
149
+ const newLink = new core . Annotations . Link ( ) ;
150
+ newLink . PageNumber = targetAnnotation . PageNumber ;
151
+ newLink . X = targetAnnotation . X ;
152
+ newLink . Y = targetAnnotation . Y ;
153
+ newLink . Width = targetAnnotation . Width ;
154
+ newLink . Height = targetAnnotation . Height ;
155
+
156
+ newLink . addAction (
157
+ 'U' ,
158
+ new core . Actions . URI ( {
159
+ uri : 'https://www.apryse.com' ,
160
+ } ) ,
161
+ ) ;
162
+
163
+ core . annotationManager . addAnnotation ( newLink ) ;
164
+ core . annotationManager . groupAnnotations ( targetAnnotation , [ newLink ] ) ;
165
+ core . annotationManager . drawAnnotationsFromList ( newLink ) ;
166
+ } ,
167
+ 'annotManager.annotationsDrawn'
168
+ ) ;
169
+
170
+ await page . locator ( '#play' ) . click ( ) ;
171
+
172
+ // press the document button in the accessibility popup
173
+ // timeout of 200 used to make test more consistent
174
+ await page . keyboard . press ( 'Tab' ) ;
175
+ // eslint-disable-next-line playwright/no-wait-for-timeout
176
+ await page . waitForTimeout ( 200 ) ;
177
+ await page . keyboard . press ( 'Tab' ) ;
178
+ // eslint-disable-next-line playwright/no-wait-for-timeout
179
+ await page . waitForTimeout ( 200 ) ;
180
+ await page . keyboard . press ( 'Tab' ) ;
181
+ // eslint-disable-next-line playwright/no-wait-for-timeout
182
+ await page . waitForTimeout ( 200 ) ;
183
+ await page . keyboard . press ( 'Tab' ) ;
184
+ // eslint-disable-next-line playwright/no-wait-for-timeout
185
+ await page . waitForTimeout ( 200 ) ;
186
+ await page . keyboard . press ( 'Tab' ) ;
187
+ // eslint-disable-next-line playwright/no-wait-for-timeout
188
+ await page . waitForTimeout ( 200 ) ;
189
+ await page . keyboard . press ( 'Tab' ) ;
190
+ // eslint-disable-next-line playwright/no-wait-for-timeout
191
+ await page . waitForTimeout ( 200 ) ;
192
+
193
+ await page . keyboard . press ( 'Enter' ) ;
194
+ // eslint-disable-next-line playwright/no-wait-for-timeout
195
+ await page . waitForTimeout ( 200 ) ;
196
+
197
+ // should be on page 1
198
+ let currentPageNumber = await iframe . evaluate ( async ( ) => {
199
+ return instance . Core . documentViewer . getCurrentPage ( ) ;
200
+ } ) ;
201
+ expect ( currentPageNumber ) . toBe ( 1 ) ;
202
+
203
+ // first tab on page 1 should go to link
204
+ await page . keyboard . press ( 'Tab' ) ;
205
+ // eslint-disable-next-line playwright/no-wait-for-timeout
206
+ await page . waitForTimeout ( 200 ) ;
207
+ // second tab should go to page 2
208
+ await page . keyboard . press ( 'Tab' ) ;
209
+ // eslint-disable-next-line playwright/no-wait-for-timeout
210
+ await page . waitForTimeout ( 200 ) ;
211
+
212
+ currentPageNumber = await iframe . evaluate ( async ( ) => {
213
+ return instance . Core . documentViewer . getCurrentPage ( ) ;
214
+ } ) ;
215
+ expect ( currentPageNumber ) . toBe ( 2 ) ;
216
+ } ) ;
217
+
218
+ test ( 'Should be able to toggle a11y mode ON and OFF with the preset button' , async ( ) => {
219
+ test . skip ( getUIMode ( ) !== 'default' , 'Test only works in Modular UI' ) ;
220
+
221
+ // Customize header by adding a button to it
222
+ await iframe . evaluate ( ( ) => {
223
+ const toggleA11yModeButton = {
224
+ 'dataElement' : 'toggleAccessibilityModePresetButton' ,
225
+ 'type' : 'presetButton' ,
226
+ 'buttonType' : 'toggleAccessibilityModeButton' ,
227
+ } ;
228
+
229
+ const mainHeader = window . instance . UI . getModularHeader ( 'default-top-header' ) ;
230
+ const updatedItems = [ ...mainHeader . items , toggleA11yModeButton ] ;
231
+ mainHeader . setItems ( updatedItems ) ;
232
+ } ) ;
233
+
234
+ const toggleA11yModeButton = iframe . getByRole ( 'button' , { name : / A c c e s s i b i l i t y M o d e / i } ) ;
235
+ await expect ( toggleA11yModeButton ) . toBeVisible ( ) ;
236
+ expect ( await isAROModeEnabled ( iframe ) ) . toBe ( true ) ;
237
+ await toggleA11yModeButton . click ( ) ;
238
+ expect ( await isAROModeEnabled ( iframe ) ) . toBe ( false ) ;
239
+ } ) ;
240
+
241
+ test ( 'Should turn the ARO mode on, add the accessible mode content and be able to turn the mode off via UI' , async ( ) => {
242
+ test . skip ( getUIMode ( ) !== 'default' , 'Test only works in Modular UI' ) ;
243
+ expect ( await isAROModeEnabled ( iframe ) ) . toBe ( true ) ;
244
+
245
+ // ARO mode content should not be added
246
+ const a11yContentBoxes = iframe . locator ( '[data-element^="a11y-reader-content"]' ) ;
247
+ await expect ( a11yContentBoxes ) . toHaveCount ( 0 ) ;
248
+
249
+ // Legacy Accessible mode content should be added
250
+ const accessibleModeContent = iframe . locator ( '[id^="pageText"]' ) ;
251
+ await expect ( accessibleModeContent ) . toHaveCount ( 2 ) ;
252
+
253
+
254
+ await iframe . getByRole ( 'button' , { name : / V i e w C o n t r o l s / i } ) . click ( ) ;
255
+ await iframe . getByRole ( 'button' , { name : / A c c e s s i b i l i t y M o d e / i } ) . click ( ) ;
256
+ expect ( await isAROModeEnabled ( iframe ) ) . toBe ( false ) ;
257
+
258
+ // Legacy Accessible mode content should be removed
259
+ const accessibleModeContentAfterDisableMode = iframe . locator ( '[id^="pageText"]' ) ;
260
+ await expect ( accessibleModeContentAfterDisableMode ) . toHaveCount ( 0 ) ;
261
+ } ) ;
262
+ } ) ;
263
+
264
+ test . describe ( 'Loading a PDF file' , ( ) => {
265
+ test . beforeEach ( async ( { page } ) => {
266
+ const {
267
+ iframe : iframeRef ,
268
+ } = await setupWebViewer (
269
+ {
270
+ page,
271
+ samplePath : 'advanced/accessibility' ,
272
+ } ,
273
+ ) ;
274
+ iframe = iframeRef ;
275
+ await expect ( async ( ) => {
276
+ expect ( await isAROModeEnabled ( iframe ) ) . toBe ( true ) ;
277
+ } ) . toPass ( ) ;
278
+
279
+ const loadingModal = iframe . locator ( '[data-element="loadingModal"]' ) ;
280
+ await expect ( async ( ) => {
281
+ await expect ( loadingModal ) . toHaveCount ( 0 ) ;
282
+ } ) . toPass ( ) ;
283
+
284
+ await expect ( async ( ) => {
285
+ await evaluateAndWaitForEvent (
286
+ iframe ,
287
+ async ( ) => window . instance . Core . documentViewer . loadDocument ( '/test-files/pdf-ua/basic-three-page-doc.pdf' ) ,
288
+ 'AccessibleReadingOrderManager.accessibleReadingOrderModeReady' ,
289
+ ) ;
290
+ } ) . toPass ( ) ;
291
+ } ) ;
292
+ test ( 'Should activate the Accessible Reading Order Mode without errors and add the appropriate a11y DOM elements' , async ( ) => {
293
+ const a11yPageContainers = iframe . locator ( '[data-element^="a11y-reader-container"]' ) ;
294
+ await expect ( a11yPageContainers ) . toHaveCount ( 3 ) ;
295
+
296
+ const a11yPage1 = a11yPageContainers . nth ( 0 ) ;
297
+ const a11yPage1Elements = a11yPage1 . locator ( '[data-element^="a11y-reader-content"]' ) ;
298
+ await expect ( a11yPage1Elements ) . toHaveCount ( 7 ) ;
299
+ } ) ;
300
+
301
+ // test doesn't pass 150 times
302
+ // https://apryse.atlassian.net/browse/WVR-9440
303
+ test . skip ( 'Should add the accessibility mode toggle option to the View controls and be able to toggle the mode ON and OFF' , async ( ) => {
304
+ test . skip ( getUIMode ( ) !== 'default' , 'Test only works in Modular UI' ) ;
305
+ expect ( await isAROModeEnabled ( iframe ) ) . toBe ( true ) ;
306
+ await iframe . getByRole ( 'button' , { name : / V i e w C o n t r o l s / i } ) . click ( ) ;
307
+ await iframe . getByRole ( 'button' , { name : / A c c e s s i b i l i t y M o d e / i } ) . click ( ) ;
308
+ expect ( await isAROModeEnabled ( iframe ) ) . toBe ( false ) ;
309
+ const a11yPageContainers = iframe . locator ( '[data-element^="a11y-reader-container"]' ) ;
310
+ await expect ( a11yPageContainers ) . toHaveCount ( 0 ) ;
311
+ await iframe . getByRole ( 'button' , { name : / A c c e s s i b i l i t y M o d e / i } ) . click ( ) ;
312
+ expect ( await isAROModeEnabled ( iframe ) ) . toBe ( true ) ;
313
+ const a11yPageContainersAfterEnablingAgain = iframe . locator ( '[data-element^="a11y-reader-container"]' ) ;
314
+ await expect ( a11yPageContainersAfterEnablingAgain ) . toHaveCount ( 3 ) ;
315
+ } ) ;
316
+
317
+ test ( 'should update the accessibility DOM based on whether the opened file is structured or unstructured' , async ( ) => {
318
+ // The PDF file loaded is structured so the a11y content should be added
319
+ await expect ( iframe . locator ( '[data-element^="a11y-reader-container"]' ) ) . toHaveCount ( 3 ) ;
320
+
321
+ await evaluateAndWaitForEvent (
322
+ iframe ,
323
+ async ( ) => window . instance . Core . documentViewer . loadDocument ( '/test-files/demo-annotated.pdf' ) ,
324
+ 'AccessibleReadingOrderManager.accessibleReadingOrderModeNoStructure' ,
325
+ ) ;
326
+
327
+ // After loading a non-structured file, the a11y content should be removed
328
+ await expect ( iframe . locator ( '[data-element^="a11y-reader-container"]' ) ) . toHaveCount ( 0 ) ;
329
+ // And the legacy accessible content should be added
330
+ await expect ( iframe . locator ( '[id^="pageText"]' ) ) . toHaveCount ( 9 ) ;
331
+
332
+ await evaluateAndWaitForEvent (
333
+ iframe ,
334
+ async ( ) => window . instance . Core . documentViewer . loadDocument ( '/test-files/pdf-ua/PDFUA-Ref-2-02_Invoice.pdf' ) ,
335
+ 'AccessibleReadingOrderManager.accessibleReadingOrderModeReady'
336
+ ) ;
337
+ // Opening a structured PDF file again and should add the a11y content and remove the legacy accessible content
338
+ await expect ( iframe . locator ( '[data-element^="a11y-reader-container"]' ) ) . toHaveCount ( 1 ) ;
339
+ await expect ( iframe . locator ( '[id^="pageText"]' ) ) . toHaveCount ( 0 ) ;
340
+ } ) ;
341
+
342
+ test ( 'should load the legacy accessibility content when the file is incorrectly tagged' , async ( ) => {
343
+ expect ( await isAROModeEnabled ( iframe ) ) . toBe ( true ) ;
344
+ await evaluateAndWaitForEvent (
345
+ iframe ,
346
+ async ( ) => window . instance . Core . documentViewer . loadDocument ( '/test-files/incorrectly-tagged.pdf' ) ,
347
+ 'AccessibleReadingOrderManager.accessibleReadingOrderModeNoStructure' ,
348
+ ) ;
349
+
350
+ const accessibleModeContent = iframe . locator ( '[id^="pageText"]' ) ;
351
+ await expect ( accessibleModeContent ) . toHaveCount ( 3 ) ;
352
+ } ) ;
353
+ } ) ;
354
+
355
+
356
+ test . describe ( 'Accessible mode and Full API OFF' , ( ) => {
357
+ test ( 'should log a warning when the user tries to enable accessibility mode using the preset button' , async ( { page } ) => {
358
+ test . skip ( getUIMode ( ) !== 'default' , 'Test only works in Modular UI' ) ;
359
+ const { iframe, consoleLogs } = await setupWebViewer ( {
360
+ page,
361
+ samplePath : 'viewing/viewing' ,
362
+ } ) ;
363
+
364
+ const isAROModeEnabled = async ( ) => {
365
+ return iframe . evaluate ( ( ) => {
366
+ return window . instance . Core . documentViewer . getAccessibleReadingOrderManager ( ) . isInAccessibleReadingOrderMode ( ) ;
367
+ } ) ;
368
+ } ;
369
+
370
+ expect ( await isAROModeEnabled ( ) ) . toBe ( false ) ;
371
+
372
+ await iframe . evaluate ( ( ) => {
373
+ const toggleA11yModeButton = {
374
+ 'dataElement' : 'toggleAccessibilityModePresetButton' ,
375
+ 'type' : 'presetButton' ,
376
+ 'buttonType' : 'toggleAccessibilityModeButton' ,
377
+ } ;
378
+
379
+ const mainHeader = window . instance . UI . getModularHeader ( 'default-top-header' ) ;
380
+ const updatedItems = [ ...mainHeader . items , toggleA11yModeButton ] ;
381
+ mainHeader . setItems ( updatedItems ) ;
382
+ } ) ;
383
+
384
+ const toggleA11yModeButton = iframe . getByRole ( 'button' , { name : / A c c e s s i b i l i t y M o d e / i } ) ;
385
+ await expect ( toggleA11yModeButton ) . toBeVisible ( ) ;
386
+ await toggleA11yModeButton . click ( ) ;
387
+ expect ( await isAROModeEnabled ( iframe ) ) . toBe ( false ) ;
388
+ expect ( consoleLogs ) . toContain ( 'FullAPI is required to use accessibility mode' ) ;
389
+ } ) ;
390
+ } ) ;
391
+ } ) ;
0 commit comments