11import { IJupyterLabPageFixture , expect , test } from '@jupyterlab/galata' ;
2+ import { Locator } from '@playwright/test' ;
23
34async function closeSideTab ( page : IJupyterLabPageFixture ) : Promise < void > {
45 await page
@@ -7,37 +8,102 @@ async function closeSideTab(page: IJupyterLabPageFixture): Promise<void> {
78 . click ( ) ;
89}
910
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+
1077/**
1178 * Don't load JupyterLab webpage before running the tests.
1279 * This is required to ensure we capture all log messages.
1380 */
14- test . use ( { autoGoto : false } ) ;
81+ test . use ( {
82+ autoGoto : false ,
83+ mockSettings : {
84+ '@jupyterlab/apputils-extension:notification' : {
85+ fetchNews : 'false'
86+ }
87+ }
88+ } ) ;
1589
1690test ( 'should render session file' , async ( { page } ) => {
1791 await page . goto ( ) ;
1892
19- await expect ( page . getByText ( 'session.glu' ) ) . toBeVisible ( ) ;
20- await page . getByText ( 'session.glu' ) . dblclick ( ) ;
93+ await openSession ( page , 'session' ) ;
2194
2295 await closeSideTab ( page ) ;
2396
24- // TODO Wait for spinner to not be visible once we have one
25- await page . waitForSelector ( '.bqplot' ) ;
26-
2797 expect ( await page . screenshot ( ) ) . toMatchSnapshot ( 'session-tab1.png' ) ;
2898} ) ;
2999
30100test ( 'should switch tab' , async ( { page } ) => {
31101 await page . goto ( ) ;
32102
33- await expect ( page . getByText ( 'session.glu' ) ) . toBeVisible ( ) ;
34- await page . getByText ( 'session.glu' ) . dblclick ( ) ;
103+ await openSession ( page , 'session' ) ;
35104
36105 await closeSideTab ( page ) ;
37106
38- // TODO Wait for spinner to not be visible once we have one
39- await page . waitForSelector ( '.bqplot' ) ;
40-
41107 // Switch tab
42108 await page . getByRole ( 'tab' , { name : 'Tab 2' } ) . click ( ) ;
43109
@@ -49,11 +115,7 @@ test('should switch tab', async ({ page }) => {
49115test ( 'should open link editor' , async ( { page } ) => {
50116 await page . goto ( ) ;
51117
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' ) ;
57119
58120 // Switch to link editor
59121 await ( await page . waitForSelector ( 'text="Link Data"' ) ) . click ( ) ;
@@ -64,21 +126,17 @@ test('should open link editor', async ({ page }) => {
64126test ( 'should open the control panel on widget clicking' , async ( { page } ) => {
65127 await page . goto ( ) ;
66128
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' ) ;
70130 await page . getByText ( 'Histogram Viewer' ) . click ( ) ;
71- await page . getByText ( 'TAB 1 - HISTOGRAMVIEWER' ) ;
131+ page . getByText ( 'TAB 1 - HISTOGRAMVIEWER' ) ;
72132
73133 expect ( await page . screenshot ( ) ) . toMatchSnapshot ( 'control-panel.png' ) ;
74134} ) ;
75135
76136test ( 'should hide the control panel on tab switching' , async ( { page } ) => {
77137 await page . goto ( ) ;
78138
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' ) ;
82140 await page . getByText ( 'Histogram Viewer' ) . click ( ) ;
83141 await page . getByText ( 'TAB 1 - HISTOGRAMVIEWER' ) ;
84142
@@ -90,12 +148,44 @@ test('should hide the control panel on tab switching', async ({ page }) => {
90148 ) ;
91149} ) ;
92150
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+
93185test ( 'should add new dataset and create a viewer' , async ( { page } ) => {
94186 await page . goto ( ) ;
95187
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' ) ;
99189
100190 // Open the "Add Data" dialog
101191 await page . getByText ( 'Add Data' ) . click ( ) ;
@@ -154,3 +244,111 @@ test('should add new dataset and create a viewer', async ({ page }) => {
154244 'add-data-viewer-created.png'
155245 ) ;
156246} ) ;
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