Skip to content

Commit f252d8f

Browse files
committed
Correct tests
1 parent c0fd1e1 commit f252d8f

9 files changed

+153
-25
lines changed

galata/src/fixtures.ts

Lines changed: 70 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright (c) Jupyter Development Team.
22
// Distributed under the terms of the Modified BSD License.
33

4-
import { Session, TerminalAPI } from '@jupyterlab/services';
4+
import { Session, TerminalAPI, Workspace } from '@jupyterlab/services';
55
import { ISettingRegistry } from '@jupyterlab/settingregistry';
66
import {
77
test as base,
@@ -49,11 +49,16 @@ export type GalataOptions = {
4949
*/
5050
serverFiles: 'on' | 'off' | 'only-on-failure';
5151
/**
52-
* Whether to mock JupyterLab state in-memory or not.
52+
* Mock JupyterLab state in-memory or not.
53+
*
54+
* Possible values are:
55+
* - true (default): JupyterLab state will be mocked on a per test basis
56+
* - false: JupyterLab state won't be mocked (Be careful it will write state in local files)
57+
* - Record<string, unknown>: Initial JupyterLab data state - Mapping (state key, value).
5358
*
5459
* By default the state is stored in-memory
5560
*/
56-
mockState: boolean; // TODO allow loading custom state
61+
mockState: boolean | Record<string, unknown>;
5762
/**
5863
* Mock JupyterLab settings in-memory or not.
5964
*
@@ -65,7 +70,7 @@ export type GalataOptions = {
6570
* By default the settings are stored in-memory. However the
6671
* they are still initialized with the hard drive values.
6772
*/
68-
mockSettings: boolean | Record<string, unknown>; // TODO test mock with record
73+
mockSettings: boolean | Record<string, unknown>;
6974
/**
7075
* Unique test temporary path created on the server.
7176
*
@@ -95,7 +100,12 @@ export const test: TestType<
95100
await use(baseURL ?? process.env.TARGET_URL ?? 'http://localhost:8888');
96101
},
97102
/**
98-
* Whether to mock JupyterLab state in-memory or not.
103+
* Mock JupyterLab state in-memory or not.
104+
*
105+
* Possible values are:
106+
* - true (default): JupyterLab state will be mocked on a per test basis
107+
* - false: JupyterLab state won't be mocked (Be careful it will write state in local files)
108+
* - Record<string, unknown>: Initial JupyterLab data state - Mapping (state key, value).
99109
*
100110
* By default the state is stored in-memory
101111
*/
@@ -105,8 +115,8 @@ export const test: TestType<
105115
*
106116
* Possible values are:
107117
* - true (default): JupyterLab settings will be mocked on a per test basis
108-
* - false: JupyterLab settings won't be mocked (Be careful it will read & write settings local files)
109-
* - Record<string, any>: Mapping {pluginId: settings} that will override default settings
118+
* - false: JupyterLab settings won't be mocked (Be careful it may write settings local files)
119+
* - Record<string, unknown>: Mapping {pluginId: settings} that will override default settings
110120
*
111121
* By default the settings are stored in-memory. However the
112122
* they are still initialized with the hard drive values.
@@ -204,8 +214,14 @@ export const test: TestType<
204214
);
205215
}
206216

207-
const workspace = { data: {}, metadata: {} };
217+
const workspace: Workspace.IWorkspace = {
218+
data: {},
219+
metadata: { id: 'default' }
220+
};
208221
if (mockState) {
222+
if (typeof mockState !== 'boolean') {
223+
workspace.data = { ...mockState } as any;
224+
}
209225
// State will be stored in-memory (after loading the initial version from disk)
210226
await Private.mockState(page, workspace);
211227
}
@@ -230,7 +246,17 @@ export const test: TestType<
230246
}
231247
});
232248

249+
/**
250+
* Private methods
251+
*/
233252
namespace Private {
253+
/**
254+
* Clear all wanted sessions.
255+
*
256+
* @param baseURL Application base URL
257+
* @param sessions Set of sessions
258+
* @returns Whether the sessions were closed or not
259+
*/
234260
export async function clearSessions(
235261
baseURL: string,
236262
sessions: Set<string>
@@ -243,6 +269,13 @@ namespace Private {
243269
return responses.every(response => response.ok);
244270
}
245271

272+
/**
273+
* Clear all wanted terminals.
274+
*
275+
* @param baseURL Application base URL
276+
* @param terminals Set of terminals
277+
* @returns Whether the terminals were closed or not
278+
*/
246279
export async function clearTerminals(
247280
baseURL: string,
248281
terminals: Set<string>
@@ -255,12 +288,15 @@ namespace Private {
255288
return responses.every(response => response.ok);
256289
}
257290

291+
/**
292+
* Mock workspace route.
293+
*
294+
* @param page Page model object
295+
* @param workspace In-memory workspace
296+
*/
258297
export function mockState(
259298
page: Page,
260-
workspace: {
261-
data: Record<string, unknown>;
262-
metadata: Record<string, unknown>;
263-
}
299+
workspace: Workspace.IWorkspace
264300
): Promise<void> {
265301
return page.route(/.*\/api\/workspaces[\/\w+]+/, (route, request) => {
266302
switch (request.method()) {
@@ -281,8 +317,18 @@ namespace Private {
281317
});
282318
}
283319

320+
/**
321+
* Settings REST API endpoint
322+
*/
284323
const settingsRegex = /.*\/api\/settings(?<id>(\/[@:-\w]+)*)/;
285324

325+
/**
326+
* Mock settings route.
327+
*
328+
* @param page Page model object
329+
* @param settings In-memory settings
330+
* @param mockedSettings Test mocked settings
331+
*/
286332
export function mockSettings(
287333
page: Page,
288334
settings: ISettingRegistry.IPlugin[],
@@ -388,6 +434,12 @@ namespace Private {
388434
});
389435
}
390436

437+
/**
438+
* Track the sessions created during a test
439+
*
440+
* @param page Page model object
441+
* @param sessions Set of session ids
442+
*/
391443
export function trackSessions(
392444
page: Page,
393445
sessions: Set<string>
@@ -420,6 +472,12 @@ namespace Private {
420472
});
421473
}
422474

475+
/**
476+
* Track the terminals created during a test
477+
*
478+
* @param page Page model object
479+
* @param terminals Set of terminal names
480+
*/
423481
export function trackTerminals(
424482
page: Page,
425483
terminals: Set<string>

galata/src/jupyterlabpage.ts

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -490,15 +490,6 @@ export class JupyterLabPage implements IJupyterLabPage {
490490
if (!jlabAccessible) {
491491
throw new Error('Failed to access JupyterLab object in browser context');
492492
}
493-
494-
// TODO is this still needed?
495-
// let resourcePath = '/lab';
496-
// if (context.jlabWorkspace) {
497-
// resourcePath = `${resourcePath}/workspaces/${context.jlabWorkspace}`;
498-
// }
499-
// await this.page.evaluate(async resourcePath => {
500-
// await window.galataip.waitForLaunch(resourcePath);
501-
// }, resourcePath);
502493
}
503494

504495
/**
@@ -528,13 +519,22 @@ export class JupyterLabPage implements IJupyterLabPage {
528519
};
529520
}
530521

522+
/**
523+
* Activity helper
524+
*/
531525
class ActivityHelper {
532526
constructor(readonly page: Page) {}
533527

528+
/**
529+
* JupyterLab launcher selector
530+
*/
534531
get launcherSelector(): string {
535532
return Private.xpBuildActivityTabSelector('Launcher');
536533
}
537534

535+
/**
536+
* Close all widgets in the main area
537+
*/
538538
async closeAll(): Promise<void> {
539539
await this.page.evaluate(async (launcherSelector: string) => {
540540
const app = window.jupyterlab;
@@ -544,6 +544,12 @@ class ActivityHelper {
544544
}, this.launcherSelector);
545545
}
546546

547+
/**
548+
* Whether a tab is active or not
549+
*
550+
* @param name Activity name
551+
* @returns Active status
552+
*/
547553
async isTabActive(name: string): Promise<boolean> {
548554
const tab = await this.getTab(name);
549555
return (
@@ -555,6 +561,12 @@ class ActivityHelper {
555561
);
556562
}
557563

564+
/**
565+
* Get a handle on a tab
566+
*
567+
* @param name Activity name
568+
* @returns Handle on the tab or null if the tab is not found
569+
*/
558570
getTab(name?: string): Promise<ElementHandle<Element> | null> {
559571
const page = this.page;
560572
const tabSelector = name
@@ -563,6 +575,12 @@ class ActivityHelper {
563575
return page.$(`xpath=${tabSelector}`);
564576
}
565577

578+
/**
579+
* Get a handle on a panel
580+
*
581+
* @param name Activity name
582+
* @returns Handle on the tab or null if the tab is not found
583+
*/
566584
async getPanel(name?: string): Promise<ElementHandle<Element> | null> {
567585
const page = this.page;
568586
const tab = await this.getTab(name);
@@ -576,6 +594,12 @@ class ActivityHelper {
576594
return null;
577595
}
578596

597+
/**
598+
* Activate a tab is active
599+
*
600+
* @param name Activity name
601+
* @returns Whether the action is successful
602+
*/
579603
async activateTab(name: string): Promise<boolean> {
580604
const tab = await this.getTab(name);
581605
if (tab) {

galata/test/fixture.spec.ts

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,7 @@ test.describe('page', () => {
2323

2424
test.describe('tmpPath', () => {
2525
test('should return an unique test folder', ({ tmpPath }) => {
26-
expect(tmpPath).toEqual(
27-
'test-fixture-tmpPath-should-return-an-unique-test-folder'
28-
);
26+
expect(tmpPath).toEqual('test-fixture-should-return-an-unique-test-folder');
2927
});
3028
});
3129

@@ -53,3 +51,51 @@ test.describe('mockSettings', () => {
5351
expect(await page.theme.getTheme()).toEqual('JupyterLab Light');
5452
});
5553
});
54+
55+
test.describe('mockState', () => {
56+
// Use non-default state to have the running session panel displayed
57+
test.use({
58+
mockState: {
59+
'layout-restorer:data': {
60+
main: {
61+
dock: {
62+
type: 'tab-area',
63+
currentIndex: 0,
64+
widgets: []
65+
}
66+
},
67+
down: {
68+
size: 0,
69+
widgets: []
70+
},
71+
left: {
72+
collapsed: false,
73+
visible: true,
74+
current: 'running-sessions',
75+
widgets: [
76+
'filebrowser',
77+
'jp-property-inspector',
78+
'running-sessions',
79+
'@jupyterlab/toc:plugin',
80+
'debugger-sidebar',
81+
'extensionmanager.main-view'
82+
]
83+
},
84+
right: {
85+
collapsed: true,
86+
visible: true,
87+
widgets: []
88+
},
89+
relativeSizes: [0.4, 0.6, 0]
90+
}
91+
} as any
92+
});
93+
94+
test('should return the mocked state', async ({ page }) => {
95+
expect(
96+
await page.waitForSelector(
97+
'[aria-label="Running Sessions section"] >> text=OPEN TABS'
98+
)
99+
).toBeTruthy();
100+
});
101+
});

galata/test/jupyterlabpage.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,5 @@ playwrightTest('should not be loading galata helper', async ({ page }) => {
4040
// eslint-disable-next-line jest/no-standalone-expect
4141
expect(page['notebook']).toBeUndefined(); // no helper
4242
// eslint-disable-next-line jest/no-standalone-expect
43-
expect(page.url()).toEqual('');
43+
expect(page.url()).toEqual('about:blank');
4444
});
Loading
Loading
Loading
Loading
Loading

0 commit comments

Comments
 (0)