Skip to content

Commit 38d4300

Browse files
Add tests to NotebookPicker
Signed-off-by: Andy Jakubowski <[email protected]>
1 parent 05f7a51 commit 38d4300

File tree

2 files changed

+114
-2
lines changed

2 files changed

+114
-2
lines changed

jest.config.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ const jestJupyterLab = require('@jupyterlab/testutils/lib/jest-config');
22

33
const esModules = [
44
'@codemirror',
5-
'@jupyter/ydoc',
6-
'@jupyterlab/',
5+
'@jupyter',
6+
'@microsoft',
7+
'exenv-es6',
78
'lib0',
89
'nanoid',
910
'vscode-ws-jsonrpc',
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// Copyright (c) Deepnote
2+
// Distributed under the terms of the Modified BSD License.
3+
4+
import { NotebookPicker } from '../../src/components/NotebookPicker';
5+
import { framePromise } from '@jupyterlab/testing';
6+
import { NotebookPanel } from '@jupyterlab/notebook';
7+
import { INotebookModel } from '@jupyterlab/notebook';
8+
import { Widget } from '@lumino/widgets';
9+
import { simulate } from 'simulate-event';
10+
11+
describe('NotebookPicker', () => {
12+
let panel: NotebookPanel;
13+
let model: INotebookModel;
14+
15+
beforeEach(async () => {
16+
// Mock model + metadata
17+
model = {
18+
fromJSON: jest.fn(),
19+
get cells() {
20+
return [];
21+
},
22+
dirty: true
23+
} as any;
24+
25+
panel = {
26+
context: {
27+
ready: Promise.resolve(),
28+
model: {
29+
getMetadata: jest.fn().mockReturnValue({
30+
notebooks: {
31+
nb1: { id: 'nb1', name: 'nb1', cells: [{ source: 'code' }] },
32+
nb2: { id: 'nb2', name: 'nb2', cells: [] }
33+
},
34+
notebook_names: ['nb1', 'nb2']
35+
})
36+
}
37+
},
38+
model
39+
} as any;
40+
41+
// Attach to DOM
42+
const widget = new NotebookPicker(panel);
43+
// Override onAfterAttach to avoid errors from this.parent being null
44+
(widget as any).onAfterAttach = jest.fn();
45+
Widget.attach(widget, document.body);
46+
await framePromise();
47+
});
48+
49+
afterEach(() => {
50+
document.body.innerHTML = '';
51+
jest.restoreAllMocks();
52+
});
53+
54+
it('should render a select element', async () => {
55+
await framePromise(); // wait for rendering
56+
const select = document.querySelector('select') as HTMLSelectElement;
57+
expect(select).not.toBeNull();
58+
expect(select.options.length).toBe(2);
59+
expect(select.options[0] && select.options[0].value).toBe('nb1');
60+
});
61+
62+
it('should call fromJSON when selecting a notebook', async () => {
63+
const select = document.querySelector('select') as HTMLSelectElement;
64+
simulate(select, 'change', { target: { value: 'nb2' } });
65+
await framePromise();
66+
expect(model.fromJSON).toHaveBeenCalledWith(
67+
expect.objectContaining({
68+
cells: expect.any(Array),
69+
metadata: expect.objectContaining({
70+
deepnote: expect.objectContaining({
71+
notebooks: expect.any(Object)
72+
})
73+
})
74+
})
75+
);
76+
});
77+
78+
it('should not call fromJSON if selected notebook is invalid', async () => {
79+
const getMetadata = panel.context.model.getMetadata as jest.Mock;
80+
getMetadata.mockReturnValue({ notebooks: {} });
81+
82+
const select = document.querySelector('select') as HTMLSelectElement;
83+
simulate(select, 'change', { target: { value: 'nonexistent' } });
84+
await framePromise();
85+
expect(model.fromJSON).not.toHaveBeenCalled();
86+
});
87+
88+
it('should update UI after selection', async () => {
89+
const select = document.querySelector('select') as HTMLSelectElement;
90+
select.value = 'nb2';
91+
simulate(select, 'change');
92+
await framePromise();
93+
expect(select.value).toBe('nb2');
94+
});
95+
96+
it('should handle empty metadata gracefully', async () => {
97+
const getMetadata = panel.context.model.getMetadata as jest.Mock;
98+
getMetadata.mockReturnValue({ notebooks: {}, notebook_names: [] });
99+
100+
document.body.innerHTML = '';
101+
const widget = new NotebookPicker(panel);
102+
// Override onAfterAttach to avoid errors from this.parent being null
103+
(widget as any).onAfterAttach = jest.fn();
104+
Widget.attach(widget, document.body);
105+
await framePromise();
106+
107+
const select = document.querySelector('select') as HTMLSelectElement;
108+
expect(select.options.length).toBeGreaterThanOrEqual(1);
109+
expect(select.options[0] && select.options[0].value).toBe('-');
110+
});
111+
});

0 commit comments

Comments
 (0)