1
1
import { IJupyterLabPageFixture , expect , test } from '@jupyterlab/galata' ;
2
+ import { Locator } from '@playwright/test' ;
2
3
3
4
async function closeSideTab ( page : IJupyterLabPageFixture ) : Promise < void > {
4
5
await page
@@ -7,37 +8,102 @@ async function closeSideTab(page: IJupyterLabPageFixture): Promise<void> {
7
8
. click ( ) ;
8
9
}
9
10
11
+ async function openSession (
12
+ page : IJupyterLabPageFixture ,
13
+ session : string ,
14
+ waitUntilReady = true
15
+ ) : Promise < void > {
16
+ await expect ( page . getByText ( `${ session } .glu` ) ) . toBeVisible ( ) ;
17
+ await page . getByText ( `${ session } .glu` ) . dblclick ( ) ;
18
+ if ( waitUntilReady ) {
19
+ // TODO Wait for spinner to not be visible once we have one
20
+ await page . waitForSelector ( '.bqplot' ) ;
21
+ }
22
+ }
23
+
24
+ async function createLink (
25
+ page : IJupyterLabPageFixture ,
26
+ datasets : [ string , string ] ,
27
+ attributes : [ string , string ]
28
+ ) : Promise < void > {
29
+ // Switch to link editor
30
+ await ( await page . waitForSelector ( 'text="Link Data"' ) ) . click ( ) ;
31
+
32
+ await page . click (
33
+ `.glue-LinkEditor-linkingDatasetsPanel:first-child > div:text('${ datasets [ 0 ] } ')`
34
+ ) ;
35
+ await page . click (
36
+ `.glue-LinkEditor-linkingDatasetsPanel:last-child > div:text('${ datasets [ 1 ] } ')`
37
+ ) ;
38
+
39
+ let attr = page . locator (
40
+ `.firstAttributePanel > div:text('${ attributes [ 0 ] } ')`
41
+ ) ;
42
+ if ( ! ( await attr . getAttribute ( 'class' ) ) ?. includes ( 'selected' ) ) {
43
+ await page . click ( `.firstAttributePanel > div:text('${ attributes [ 0 ] } ')` ) ;
44
+ }
45
+ attr = page . locator ( `.secondAttributePanel > div:text('${ attributes [ 1 ] } ')` ) ;
46
+ if ( ! ( await attr . getAttribute ( 'class' ) ) ?. includes ( 'selected' ) ) {
47
+ await page . click ( `.secondAttributePanel > div:text('${ attributes [ 1 ] } ')` ) ;
48
+ }
49
+
50
+ await page . click ( '.glue-LinkEditor-linkingGlueButton' ) ;
51
+ }
52
+
53
+ async function selectPlotRange (
54
+ page : IJupyterLabPageFixture ,
55
+ viewer : Locator
56
+ ) : Promise < void > {
57
+ await viewer . locator ( 'button[value="bqplot:xrange"]' ) . click ( ) ;
58
+
59
+ await page . waitForSelector ( 'g.selector.brushintsel' ) ;
60
+
61
+ const figureBox = await viewer . locator ( '.bqplot.figure' ) . boundingBox ( ) ;
62
+ await page . mouse . move (
63
+ figureBox ! . x + figureBox ! . width / 3 ,
64
+ figureBox ! . y + figureBox ! . height / 3
65
+ ) ;
66
+ await page . mouse . down ( ) ;
67
+ await page . mouse . move (
68
+ figureBox ! . x + figureBox ! . width / 2 ,
69
+ figureBox ! . y + figureBox ! . height / 2
70
+ ) ;
71
+ await page . mouse . up ( ) ;
72
+ await expect ( viewer . locator ( '.glue__subset-select' ) ) . toContainText (
73
+ ' Subset 1 '
74
+ ) ;
75
+ }
76
+
10
77
/**
11
78
* Don't load JupyterLab webpage before running the tests.
12
79
* This is required to ensure we capture all log messages.
13
80
*/
14
- test . use ( { autoGoto : false } ) ;
81
+ test . use ( {
82
+ autoGoto : false ,
83
+ mockSettings : {
84
+ '@jupyterlab/apputils-extension:notification' : {
85
+ fetchNews : 'false'
86
+ }
87
+ }
88
+ } ) ;
15
89
16
90
test ( 'should render session file' , async ( { page } ) => {
17
91
await page . goto ( ) ;
18
92
19
- await expect ( page . getByText ( 'session.glu' ) ) . toBeVisible ( ) ;
20
- await page . getByText ( 'session.glu' ) . dblclick ( ) ;
93
+ await openSession ( page , 'session' ) ;
21
94
22
95
await closeSideTab ( page ) ;
23
96
24
- // TODO Wait for spinner to not be visible once we have one
25
- await page . waitForSelector ( '.bqplot' ) ;
26
-
27
97
expect ( await page . screenshot ( ) ) . toMatchSnapshot ( 'session-tab1.png' ) ;
28
98
} ) ;
29
99
30
100
test ( 'should switch tab' , async ( { page } ) => {
31
101
await page . goto ( ) ;
32
102
33
- await expect ( page . getByText ( 'session.glu' ) ) . toBeVisible ( ) ;
34
- await page . getByText ( 'session.glu' ) . dblclick ( ) ;
103
+ await openSession ( page , 'session' ) ;
35
104
36
105
await closeSideTab ( page ) ;
37
106
38
- // TODO Wait for spinner to not be visible once we have one
39
- await page . waitForSelector ( '.bqplot' ) ;
40
-
41
107
// Switch tab
42
108
await page . getByRole ( 'tab' , { name : 'Tab 2' } ) . click ( ) ;
43
109
@@ -49,11 +115,7 @@ test('should switch tab', async ({ page }) => {
49
115
test ( 'should open link editor' , async ( { page } ) => {
50
116
await page . goto ( ) ;
51
117
52
- await expect ( page . getByText ( 'session.glu' ) ) . toBeVisible ( ) ;
53
- await page . getByText ( 'session.glu' ) . dblclick ( ) ;
54
-
55
- // TODO Wait for spinner to not be visible once we have one
56
- await page . waitForSelector ( '.bqplot' ) ;
118
+ await openSession ( page , 'session' ) ;
57
119
58
120
// Switch to link editor
59
121
await ( await page . waitForSelector ( 'text="Link Data"' ) ) . click ( ) ;
@@ -64,21 +126,17 @@ test('should open link editor', async ({ page }) => {
64
126
test ( 'should open the control panel on widget clicking' , async ( { page } ) => {
65
127
await page . goto ( ) ;
66
128
67
- await expect ( page . getByText ( 'session.glu' ) ) . toBeVisible ( ) ;
68
- await page . getByText ( 'session.glu' ) . dblclick ( ) ;
69
- await page . waitForSelector ( '.bqplot' ) ;
129
+ await openSession ( page , 'session' ) ;
70
130
await page . getByText ( 'Histogram Viewer' ) . click ( ) ;
71
- await page . getByText ( 'TAB 1 - HISTOGRAMVIEWER' ) ;
131
+ page . getByText ( 'TAB 1 - HISTOGRAMVIEWER' ) ;
72
132
73
133
expect ( await page . screenshot ( ) ) . toMatchSnapshot ( 'control-panel.png' ) ;
74
134
} ) ;
75
135
76
136
test ( 'should hide the control panel on tab switching' , async ( { page } ) => {
77
137
await page . goto ( ) ;
78
138
79
- await expect ( page . getByText ( 'session.glu' ) ) . toBeVisible ( ) ;
80
- await page . getByText ( 'session.glu' ) . dblclick ( ) ;
81
- await page . waitForSelector ( '.bqplot' ) ;
139
+ await openSession ( page , 'session' ) ;
82
140
await page . getByText ( 'Histogram Viewer' ) . click ( ) ;
83
141
await page . getByText ( 'TAB 1 - HISTOGRAMVIEWER' ) ;
84
142
@@ -90,12 +148,44 @@ test('should hide the control panel on tab switching', async ({ page }) => {
90
148
) ;
91
149
} ) ;
92
150
151
+ test ( 'should add and delete link' , async ( { page } ) => {
152
+ await page . goto ( ) ;
153
+
154
+ await openSession ( page , 'session' ) ;
155
+
156
+ let linkCreated = false ;
157
+ await createLink (
158
+ page ,
159
+ [ 'w5' , 'w5_psc' ] ,
160
+ [ 'Pixel Axis 1 [x]' , 'Pixel Axis 0 [x]' ]
161
+ ) ;
162
+
163
+ const summaries = page . locator ( '.glue-LinkEditor-summaryIdentity' ) ;
164
+ const summariesCount = await summaries . count ( ) ;
165
+
166
+ expect ( summariesCount ) . toBe ( 3 ) ;
167
+
168
+ for ( let i = 0 ; i < summariesCount ; i ++ ) {
169
+ if (
170
+ ( await summaries . nth ( i ) . innerText ( ) ) ===
171
+ 'Pixel Axis 1 [x]\nPixel Axis 0 [x]'
172
+ ) {
173
+ linkCreated = true ;
174
+ break ;
175
+ }
176
+ }
177
+
178
+ expect ( linkCreated ) . toBeTruthy ( ) ;
179
+
180
+ // Remove the last link
181
+ await page . click ( '.glue-LinkEditor-deleteButton:last-child' ) ;
182
+ expect ( await summaries . count ( ) ) . toBe ( 2 ) ;
183
+ } ) ;
184
+
93
185
test ( 'should add new dataset and create a viewer' , async ( { page } ) => {
94
186
await page . goto ( ) ;
95
187
96
- await expect ( page . getByText ( 'session.glu' ) ) . toBeVisible ( ) ;
97
- await page . getByText ( 'session.glu' ) . dblclick ( ) ;
98
- await page . waitForSelector ( '.bqplot' ) ;
188
+ await openSession ( page , 'session' ) ;
99
189
100
190
// Open the "Add Data" dialog
101
191
await page . getByText ( 'Add Data' ) . click ( ) ;
@@ -154,3 +244,111 @@ test('should add new dataset and create a viewer', async ({ page }) => {
154
244
'add-data-viewer-created.png'
155
245
) ;
156
246
} ) ;
247
+
248
+ test ( 'should display linked data' , async ( { page } ) => {
249
+ await page . goto ( ) ;
250
+
251
+ await openSession ( page , 'session3' ) ;
252
+
253
+ // Create a link between the ID of datasets
254
+ await createLink ( page , [ 'w5_psc' , 'w6_psc' ] , [ 'ID' , 'ID' ] ) ;
255
+
256
+ await page . getByRole ( 'tab' , { name : 'Tab 1' } ) . click ( ) ;
257
+ const viewers = page . locator ( '.glue-item' ) ;
258
+
259
+ // force the size of histograms for snapshot comparison
260
+ viewers
261
+ . first ( )
262
+ . locator ( '.bqplot.figure > svg.svg-figure > g > rect' )
263
+ . evaluate ( element => {
264
+ element . style . width = '571px' ;
265
+ element . style . height = '410px' ;
266
+ } ) ;
267
+
268
+ viewers
269
+ . last ( )
270
+ . locator ( '.bqplot.figure > svg.svg-figure > g > rect' )
271
+ . evaluate ( element => {
272
+ element . style . width = '571px' ;
273
+ element . style . height = '410px' ;
274
+ } ) ;
275
+
276
+ // select a range.
277
+ await selectPlotRange ( page , viewers . first ( ) ) ;
278
+
279
+ // expect the selected area and the linked one to match.
280
+ expect (
281
+ await viewers
282
+ . first ( )
283
+ . locator ( '.bqplot.figure > svg.svg-figure > g > rect' )
284
+ . screenshot ( )
285
+ ) . toMatchSnapshot ( 'histogram-selection.png' ) ;
286
+
287
+ expect (
288
+ await viewers
289
+ . last ( )
290
+ . locator ( '.bqplot.figure > svg.svg-figure > g > rect' )
291
+ . screenshot ( )
292
+ ) . toMatchSnapshot ( 'histogram-linked-selection.png' ) ;
293
+ } ) ;
294
+
295
+ test ( 'should delete and restore links' , async ( { page } ) => {
296
+ await page . goto ( ) ;
297
+
298
+ await openSession ( page , 'session3' ) ;
299
+
300
+ // remove the existing links
301
+ await ( await page . waitForSelector ( 'text="Link Data"' ) ) . click ( ) ;
302
+ const deleteButton = page . locator ( '.glue-LinkEditor-deleteButton' ) ;
303
+ while ( await deleteButton . count ( ) ) {
304
+ await deleteButton . first ( ) . click ( ) ;
305
+ }
306
+
307
+ // select attributes in viewers
308
+ await page . getByRole ( 'tab' , { name : 'Tab 1' } ) . click ( ) ;
309
+ const viewers = page . locator ( '.glue-item' ) ;
310
+
311
+ // force the size of histograms for snapshot comparison
312
+ viewers
313
+ . first ( )
314
+ . locator ( '.bqplot.figure > svg.svg-figure > g > rect' )
315
+ . evaluate ( element => {
316
+ element . style . width = '571px' ;
317
+ element . style . height = '410px' ;
318
+ } ) ;
319
+
320
+ viewers
321
+ . last ( )
322
+ . locator ( '.bqplot.figure > svg.svg-figure > g > rect' )
323
+ . evaluate ( element => {
324
+ element . style . width = '571px' ;
325
+ element . style . height = '410px' ;
326
+ } ) ;
327
+
328
+ // select a range.
329
+ await selectPlotRange ( page , viewers . first ( ) ) ;
330
+
331
+ // expect the selected area and the linked one to match
332
+ expect (
333
+ await viewers
334
+ . first ( )
335
+ . locator ( '.bqplot.figure > svg.svg-figure > g > rect' )
336
+ . screenshot ( )
337
+ ) . toMatchSnapshot ( 'histogram-selection.png' ) ;
338
+
339
+ expect (
340
+ await viewers
341
+ . last ( )
342
+ . locator ( '.bqplot.figure > svg.svg-figure > g > rect' )
343
+ . screenshot ( )
344
+ ) . toMatchSnapshot ( 'histogram-no-selection.png' ) ;
345
+
346
+ await createLink ( page , [ 'w5_psc' , 'w6_psc' ] , [ 'ID' , 'ID' ] ) ;
347
+ await page . getByRole ( 'tab' , { name : 'Tab 1' } ) . click ( ) ;
348
+ expect (
349
+ await viewers
350
+ . last ( )
351
+ . locator ( '.bqplot.figure > svg.svg-figure > g > rect' )
352
+ . screenshot ( )
353
+ ) . toMatchSnapshot ( 'histogram-linked-selection.png' ) ;
354
+ } ) ;
0 commit comments