@@ -3,20 +3,12 @@ import path from 'path';
33import type { JupyterLab } from '@jupyterlab/application' ;
44import type { JSONObject } from '@lumino/coreutils' ;
55
6- import { SharingService } from '../../src/sharing-service' ;
7-
86declare global {
97 interface Window {
108 jupyterapp : JupyterLab ;
119 }
1210}
1311
14- declare global {
15- interface Window {
16- sharingService ?: SharingService ;
17- }
18- }
19-
2012async function runCommand ( page : Page , command : string , args : JSONObject = { } ) {
2113 await page . evaluate (
2214 async ( { command, args } ) => {
@@ -26,36 +18,71 @@ async function runCommand(page: Page, command: string, args: JSONObject = {}) {
2618 ) ;
2719}
2820
29- async function dismissKernelSelectDialog ( page : Page ) {
30- const kernelDialogHeader = page . locator ( '.jp-Dialog .jp-Dialog-header' , {
31- hasText : 'Select Kernel'
21+ const TEST_NOTEBOOK = {
22+ cells : [
23+ {
24+ cell_type : 'code' ,
25+ execution_count : null ,
26+ id : '55eb9a2d-401d-4abd-b0eb-373ded5b408d' ,
27+ outputs : [ ] ,
28+ metadata : { } ,
29+ source : [ `# This is a test notebook` ]
30+ }
31+ ] ,
32+ metadata : {
33+ kernelspec : {
34+ display_name : 'Python 3 (ipykernel)' ,
35+ language : 'python' ,
36+ name : 'python3'
37+ } ,
38+ language_info : {
39+ codemirror_mode : {
40+ name : 'ipython' ,
41+ version : 3
42+ } ,
43+ file_extension : '.py' ,
44+ mimetype : 'text/x-python' ,
45+ name : 'python' ,
46+ nbconvert_exporter : 'python' ,
47+ pygments_lexer : 'ipython3'
48+ }
49+ } ,
50+ nbformat : 4 ,
51+ nbformat_minor : 5
52+ } ;
53+
54+ async function mockTokenRoute ( page : Page ) {
55+ await page . route ( '**/api/v1/auth/issue' , async route => {
56+ const json = { token : 'test-token' } ;
57+ await route . fulfill ( { json } ) ;
3258 } ) ;
59+ }
3360
34- if ( ( await kernelDialogHeader . count ( ) ) === 0 ) {
35- return ;
36- }
37-
38- const selectButtonLabel = kernelDialogHeader . locator (
39- 'xpath=../../..//div[@aria-label="Select Kernel"]'
40- ) ;
41-
42- if ( await selectButtonLabel . count ( ) ) {
43- await selectButtonLabel . first ( ) . click ( ) ;
44- }
61+ async function mockGetSharedNotebook ( page : Page , notebookId : string ) {
62+ await page . route ( '**/api/v1/notebooks/*' , async route => {
63+ const json = {
64+ id : notebookId ,
65+ domain_id : 'domain' ,
66+ readable_id : null ,
67+ content : TEST_NOTEBOOK
68+ } ;
69+ await route . fulfill ( { json } ) ;
70+ } ) ;
4571}
4672
47- async function getSharedNotebookID ( page : Page ) {
48- return new URL ( page . url ( ) ) . searchParams . get ( 'notebook' ) ;
73+ async function mockShareNotebookResponse ( page : Page , notebookId : string ) {
74+ await page . route ( '**/api/v1/notebooks' , async route => {
75+ const json = {
76+ message : 'Shared!' ,
77+ notebook : { id : notebookId , readable_id : null }
78+ } ;
79+ await route . fulfill ( { json } ) ;
80+ } ) ;
4981}
5082
5183test . beforeEach ( async ( { page } ) => {
52- await page . goto ( 'lab/index.html?kernel=python ' ) ;
84+ await page . goto ( 'lab/index.html' ) ;
5385 await page . waitForSelector ( '.jp-LabShell' ) ;
54-
55- // Clear token before each test
56- await page . evaluate ( ( ) => {
57- window . sharingService ?. resetToken ( ) ;
58- } ) ;
5986} ) ;
6087
6188test . describe ( 'General' , ( ) => {
@@ -70,13 +97,11 @@ test.describe('General', () => {
7097 } ) ;
7198
7299 test ( 'Dialog windows should shade the notebook area only' , async ( { page } ) => {
73- await dismissKernelSelectDialog ( page ) ;
74100 const firstCell = page . locator ( '.jp-Cell' ) ;
75101 await firstCell
76102 . getByRole ( 'textbox' )
77103 . fill ( 'The shaded area should cover the notebook content, but not the toolbar.' ) ;
78104 const promise = runCommand ( page , 'notebook:restart-kernel' ) ;
79- await dismissKernelSelectDialog ( page ) ;
80105 const dialog = page . locator ( '.jp-Dialog' ) ;
81106
82107 expect (
@@ -92,13 +117,20 @@ test.describe('General', () => {
92117 } ) ;
93118
94119 test ( 'Should load a view-only notebook' , async ( { page } ) => {
95- await runCommand ( page , 'jupytereverywhere:share-notebook' ) ;
96-
97- const notebookId = await getSharedNotebookID ( page ) ;
98- expect ( notebookId ) . not . toBeNull ( ) ;
120+ await mockTokenRoute ( page ) ;
121+ const notebookId = 'e3b0c442-98fc-1fc2-9c9f-8b6d6ed08a1d' ;
122+
123+ await page . route ( '**/api/v1/notebooks/*' , async route => {
124+ const json = {
125+ id : notebookId ,
126+ domain_id : 'domain' ,
127+ readable_id : null ,
128+ content : TEST_NOTEBOOK
129+ } ;
130+ await route . fulfill ( { json } ) ;
131+ } ) ;
99132
100- await page . goto ( `lab/index.html?notebook=${ notebookId } &kernel=python` ) ;
101- dismissKernelSelectDialog ( page ) ;
133+ await page . goto ( `lab/index.html?notebook=${ notebookId } ` ) ;
102134
103135 expect (
104136 await page . locator ( '.jp-NotebookPanel' ) . screenshot ( {
@@ -110,31 +142,36 @@ test.describe('General', () => {
110142
111143 test ( 'Should open files page' , async ( { page } ) => {
112144 await page . locator ( '.jp-SideBar' ) . getByTitle ( 'Files' ) . click ( ) ;
113- await dismissKernelSelectDialog ( page ) ;
114145 expect ( await page . locator ( '#je-files' ) . screenshot ( ) ) . toMatchSnapshot ( 'files.png' ) ;
115146 } ) ;
116147} ) ;
117148
118149test . describe ( 'Sharing' , ( ) => {
119150 test ( 'Should open share dialog in interactive notebook' , async ( { page } ) => {
120- await runCommand ( page , 'jupytereverywhere:share-notebook' ) ;
151+ await mockTokenRoute ( page ) ;
152+ await mockShareNotebookResponse ( page , 'e3b0c442-98fc-1fc2-9c9f-8b6d6ed08a1d' ) ;
153+ const shareButton = page . locator ( '.jp-ToolbarButton' ) . getByTitle ( 'Share this notebook' ) ;
154+ await shareButton . click ( ) ;
121155 const dialog = page . locator ( '.jp-Dialog-content' ) ;
122156 expect ( await dialog . screenshot ( ) ) . toMatchSnapshot ( 'share-dialog.png' ) ;
123157 } ) ;
124158
125159 test ( 'Should open share dialog in view-only mode' , async ( { page } ) => {
160+ await mockTokenRoute ( page ) ;
161+
126162 // Load view-only (shared) notebook
127- await runCommand ( page , 'jupytereverywhere:share-notebook' ) ;
128- const notebookId = await getSharedNotebookID ( page ) ;
129- expect ( notebookId ) . not . toBeNull ( ) ;
163+ const notebookId = 'e3b0c442-98fc-1fc2-9c9f-8b6d6ed08a1d' ;
164+ await mockGetSharedNotebook ( page , notebookId ) ;
165+ await page . goto ( `lab/index.html?notebook= ${ notebookId } ` ) ;
130166
131- // Re-share it as a new notebook
132- await page . goto ( `lab/index.html?notebook= ${ notebookId } &kernel=python` ) ;
133- dismissKernelSelectDialog ( page ) ;
167+ // Re-Share it as a new notebook
168+ const newNotebookId = '104931f8-fd96-489e-8520-c1793cbba6ce' ;
169+ await mockShareNotebookResponse ( page , newNotebookId ) ;
134170
171+ const shareButton = page . locator ( '.jp-ToolbarButton' ) . getByTitle ( 'Share this notebook' ) ;
135172 const dialog = page . locator ( '.jp-Dialog-content' ) ;
136173 await expect ( dialog ) . toHaveCount ( 0 ) ;
137- await runCommand ( page , 'jupytereverywhere:share-notebook' ) ;
174+ await shareButton . click ( ) ;
138175 await expect ( dialog ) . toHaveCount ( 1 ) ;
139176 } ) ;
140177
@@ -158,10 +195,8 @@ test.describe('Download', () => {
158195 } ) ;
159196
160197 test ( 'Should download a notebook as IPyNB and PDF' , async ( { page, context } ) => {
161- dismissKernelSelectDialog ( page ) ;
162- await runCommand ( page , 'jupytereverywhere:share-notebook' ) ;
163- await getSharedNotebookID ( page ) ;
164- dismissKernelSelectDialog ( page ) ;
198+ await mockTokenRoute ( page ) ;
199+ await mockShareNotebookResponse ( page , 'test-download-regular-notebook' ) ;
165200
166201 const ipynbDownload = page . waitForEvent ( 'download' ) ;
167202 await runCommand ( page , 'jupytereverywhere:download-notebook' ) ;
@@ -175,36 +210,37 @@ test.describe('Download', () => {
175210 } ) ;
176211
177212 test ( 'Should download view-only notebook as IPyNB and PDF' , async ( { page } ) => {
178- await runCommand ( page , 'jupytereverywhere:share-notebook' ) ;
179- const notebookId = await getSharedNotebookID ( page ) ;
180- expect ( notebookId ) . not . toBeNull ( ) ;
213+ await mockTokenRoute ( page ) ;
181214
182- await page . goto ( `lab/index.html?notebook=${ notebookId } &kernel=python` ) ;
183- dismissKernelSelectDialog ( page ) ;
215+ const notebookId = 'e3b0c442-98fc-1fc2-9c9f-8b6d6ed08a1d' ;
216+ await mockGetSharedNotebook ( page , notebookId ) ;
217+ await mockShareNotebookResponse ( page , 'test-download-viewonly-notebook' ) ;
218+
219+ await page . goto ( `lab/index.html?notebook=${ notebookId } ` ) ;
184220
185221 // Wait until view-only notebook loads, and assert it is a view-only notebook.
186222 await page . locator ( '.jp-NotebookPanel' ) . waitFor ( ) ;
187223 await expect ( page . locator ( '.je-ViewOnlyHeader' ) ) . toBeVisible ( ) ;
188224
189225 const ipynbDownload = page . waitForEvent ( 'download' ) ;
190- await runCommand ( page , 'jupytereverywhere:download-notebook ' ) ;
226+ await runCommand ( page , 'jupytereverywhere:download-pdf ' ) ;
191227 const ipynbPath = await ( await ipynbDownload ) . path ( ) ;
192228 expect ( ipynbPath ) . not . toBeNull ( ) ;
193229
194230 const pdfDownload = page . waitForEvent ( 'download' ) ;
195231 await runCommand ( page , 'jupytereverywhere:download-pdf' ) ;
232+
196233 const pdfPath = await ( await pdfDownload ) . path ( ) ;
197234 expect ( pdfPath ) . not . toBeNull ( ) ;
198235 } ) ;
199236} ) ;
200237
201238test . describe ( 'Files' , ( ) => {
202239 test ( 'Should upload two files and display their thumbnails' , async ( { page } ) => {
203- await page . goto ( 'lab/index.html?kernel=python ' ) ;
240+ await page . goto ( 'lab/index.html' ) ;
204241 await page . waitForSelector ( '.jp-LabShell' ) ;
205242
206243 await page . locator ( '.jp-SideBar' ) . getByTitle ( 'Files' ) . click ( ) ;
207- await dismissKernelSelectDialog ( page ) ;
208244
209245 await page . locator ( '.je-FileTile' ) . first ( ) . click ( ) ; // the first tile will always be the "add new" one
210246
@@ -232,15 +268,17 @@ test.describe('Files', () => {
232268} ) ;
233269
234270test ( 'Should remove View Only banner when the Create Copy button is clicked' , async ( { page } ) => {
235- await runCommand ( page , 'jupytereverywhere:share-notebook' ) ;
236- const notebookId = await getSharedNotebookID ( page ) ;
237- expect ( notebookId ) . not . toBeNull ( ) ;
271+ await mockTokenRoute ( page ) ;
272+
273+ const notebookId = 'e3b0c442-98fc-1fc2-9c9f-8b6d6ed08a1d' ;
274+ await mockGetSharedNotebook ( page , notebookId ) ;
238275
239276 // Open view-only notebook
240- await page . goto ( `lab/index.html?notebook=${ notebookId } &kernel=python ` ) ;
277+ await page . goto ( `lab/index.html?notebook=${ notebookId } ` ) ;
241278 await expect ( page . locator ( '.je-ViewOnlyHeader' ) ) . toBeVisible ( ) ;
242279
243- await runCommand ( page , 'jupytereverywhere:create-copy-notebook' ) ;
280+ const createCopyButton = page . locator ( '.jp-ToolbarButtonComponent.je-CreateCopyButton' ) ;
281+ await createCopyButton . click ( ) ;
244282 await expect ( page . locator ( '.je-ViewOnlyHeader' ) ) . toBeHidden ( {
245283 timeout : 10000
246284 } ) ;
0 commit comments