Skip to content

Commit b6bbb3a

Browse files
Add comprehensive test coverage for core transformation functions
- Add tests for convert-deepnote-block-type-to-jupyter.ts (100% coverage) - Add tests for convert-deepnote-block-to-jupyter-cell.ts (100% coverage) - Add tests for transform-deepnote-yaml-to-notebook-content.ts (100% coverage) This increases overall test coverage from 26.57% to 55.94%, providing comprehensive testing for the core Deepnote-to-Jupyter transformation logic.
1 parent ef0931b commit b6bbb3a

File tree

3 files changed

+747
-0
lines changed

3 files changed

+747
-0
lines changed
Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
// Copyright (c) Deepnote
2+
// Distributed under the terms of the Modified BSD License.
3+
4+
import { convertDeepnoteBlockToJupyterCell } from '../convert-deepnote-block-to-jupyter-cell';
5+
import { DeepnoteBlock } from '@deepnote/blocks';
6+
7+
jest.mock('@deepnote/blocks', () => ({
8+
createPythonCode: jest.fn((block: any) => block.source || 'print("test")'),
9+
createMarkdown: jest.fn((block: any) => block.source || '# Test')
10+
}));
11+
12+
jest.mock('../convert-deepnote-block-type-to-jupyter', () => ({
13+
convertDeepnoteBlockTypeToJupyter: jest.fn((type: string) => {
14+
if (
15+
[
16+
'code',
17+
'sql',
18+
'notebook-function',
19+
'big-number',
20+
'visualization',
21+
'input-text',
22+
'input-checkbox',
23+
'input-textarea',
24+
'input-file',
25+
'input-select',
26+
'input-date-range',
27+
'input-date',
28+
'input-slider'
29+
].includes(type)
30+
) {
31+
return 'code';
32+
}
33+
return 'markdown';
34+
})
35+
}));
36+
37+
describe('convertDeepnoteBlockToJupyterCell', () => {
38+
describe('code cells', () => {
39+
it('should convert a basic code block to a Jupyter code cell', () => {
40+
const block: DeepnoteBlock = {
41+
id: 'block-1',
42+
type: 'code',
43+
source: 'print("hello")',
44+
metadata: { foo: 'bar' }
45+
} as any;
46+
47+
const result = convertDeepnoteBlockToJupyterCell(block);
48+
49+
expect(result.cell_type).toBe('code');
50+
expect(result.metadata).toEqual({ foo: 'bar', cell_id: 'block-1' });
51+
expect(result.source).toBe('print("hello")');
52+
expect(result.execution_count).toBeNull();
53+
expect(result.outputs).toEqual([]);
54+
});
55+
56+
it('should include execution count if present', () => {
57+
const block: DeepnoteBlock = {
58+
id: 'block-2',
59+
type: 'code',
60+
source: 'x = 1',
61+
metadata: {},
62+
executionCount: 5
63+
} as any;
64+
65+
const result = convertDeepnoteBlockToJupyterCell(block);
66+
67+
expect(result.cell_type).toBe('code');
68+
expect(result.execution_count).toBe(5);
69+
});
70+
71+
it('should include outputs if present', () => {
72+
const blockOutputs = [
73+
{
74+
output_type: 'stream',
75+
name: 'stdout',
76+
text: 'hello\n'
77+
}
78+
];
79+
80+
const block: DeepnoteBlock = {
81+
id: 'block-3',
82+
type: 'code',
83+
source: 'print("hello")',
84+
metadata: {},
85+
outputs: blockOutputs
86+
} as any;
87+
88+
const result = convertDeepnoteBlockToJupyterCell(block);
89+
90+
expect(result.cell_type).toBe('code');
91+
expect(result.outputs).toEqual(blockOutputs);
92+
});
93+
94+
it('should remove truncated property from outputs', () => {
95+
const blockOutputs = [
96+
{
97+
output_type: 'stream',
98+
name: 'stdout',
99+
text: 'hello\n',
100+
truncated: true
101+
}
102+
];
103+
104+
const block: DeepnoteBlock = {
105+
id: 'block-4',
106+
type: 'code',
107+
source: 'print("hello")',
108+
metadata: {},
109+
outputs: blockOutputs
110+
} as any;
111+
112+
const result = convertDeepnoteBlockToJupyterCell(block);
113+
114+
expect(result.cell_type).toBe('code');
115+
expect(result.outputs).toHaveLength(1);
116+
const resultOutputs = result.outputs as any[];
117+
expect(resultOutputs[0]).not.toHaveProperty('truncated');
118+
expect(resultOutputs[0]).toEqual({
119+
output_type: 'stream',
120+
name: 'stdout',
121+
text: 'hello\n'
122+
});
123+
});
124+
125+
it('should handle multiple outputs with truncated properties', () => {
126+
const blockOutputs = [
127+
{
128+
output_type: 'stream',
129+
name: 'stdout',
130+
text: 'line1\n',
131+
truncated: true
132+
},
133+
{
134+
output_type: 'stream',
135+
name: 'stdout',
136+
text: 'line2\n',
137+
truncated: false
138+
}
139+
];
140+
141+
const block: DeepnoteBlock = {
142+
id: 'block-5',
143+
type: 'code',
144+
source: 'print("test")',
145+
metadata: {},
146+
outputs: blockOutputs
147+
} as any;
148+
149+
const result = convertDeepnoteBlockToJupyterCell(block);
150+
151+
expect(result.cell_type).toBe('code');
152+
expect(result.outputs).toHaveLength(2);
153+
const resultOutputs = result.outputs as any[];
154+
expect(resultOutputs[0]).not.toHaveProperty('truncated');
155+
expect(resultOutputs[1]).not.toHaveProperty('truncated');
156+
});
157+
158+
it('should not mutate the original block', () => {
159+
const blockOutputs = [
160+
{
161+
output_type: 'stream',
162+
name: 'stdout',
163+
text: 'hello\n',
164+
truncated: true
165+
}
166+
];
167+
168+
const block: DeepnoteBlock = {
169+
id: 'block-6',
170+
type: 'code',
171+
source: 'print("hello")',
172+
metadata: { test: 'value' },
173+
outputs: blockOutputs
174+
} as any;
175+
176+
convertDeepnoteBlockToJupyterCell(block);
177+
178+
expect(block.outputs![0]).toHaveProperty('truncated');
179+
expect(block.metadata).toEqual({ test: 'value' });
180+
});
181+
});
182+
183+
describe('markdown cells', () => {
184+
it('should convert a basic markdown block to a Jupyter markdown cell', () => {
185+
const block: DeepnoteBlock = {
186+
id: 'block-7',
187+
type: 'markdown',
188+
source: '# Hello',
189+
metadata: { foo: 'bar' }
190+
} as any;
191+
192+
const result = convertDeepnoteBlockToJupyterCell(block);
193+
194+
expect(result.cell_type).toBe('markdown');
195+
expect(result.metadata).toEqual({});
196+
expect(result.source).toBe('# Hello');
197+
});
198+
199+
it('should convert text-cell-h1 to markdown cell', () => {
200+
const block: DeepnoteBlock = {
201+
id: 'block-8',
202+
type: 'text-cell-h1',
203+
source: 'Heading 1',
204+
metadata: {}
205+
} as any;
206+
207+
const result = convertDeepnoteBlockToJupyterCell(block);
208+
209+
expect(result.cell_type).toBe('markdown');
210+
});
211+
212+
it('should convert image block to markdown cell', () => {
213+
const block: DeepnoteBlock = {
214+
id: 'block-9',
215+
type: 'image',
216+
source: '![alt](url)',
217+
metadata: {}
218+
} as any;
219+
220+
const result = convertDeepnoteBlockToJupyterCell(block);
221+
222+
expect(result.cell_type).toBe('markdown');
223+
});
224+
225+
it('should not include metadata from Deepnote block in markdown cells', () => {
226+
const block: DeepnoteBlock = {
227+
id: 'block-10',
228+
type: 'markdown',
229+
source: 'Text',
230+
metadata: { deepnoteMetadata: 'should not appear' }
231+
} as any;
232+
233+
const result = convertDeepnoteBlockToJupyterCell(block);
234+
235+
expect(result.cell_type).toBe('markdown');
236+
expect(result.metadata).toEqual({});
237+
});
238+
});
239+
240+
describe('special block types', () => {
241+
it('should convert sql block to code cell', () => {
242+
const block: DeepnoteBlock = {
243+
id: 'block-11',
244+
type: 'sql',
245+
source: 'SELECT * FROM table',
246+
metadata: {}
247+
} as any;
248+
249+
const result = convertDeepnoteBlockToJupyterCell(block);
250+
251+
expect(result.cell_type).toBe('code');
252+
});
253+
254+
it('should convert visualization block to code cell', () => {
255+
const block: DeepnoteBlock = {
256+
id: 'block-12',
257+
type: 'visualization',
258+
source: 'chart_data',
259+
metadata: {}
260+
} as any;
261+
262+
const result = convertDeepnoteBlockToJupyterCell(block);
263+
264+
expect(result.cell_type).toBe('code');
265+
});
266+
267+
it('should convert input blocks to code cells', () => {
268+
const inputTypes = [
269+
'input-text',
270+
'input-checkbox',
271+
'input-textarea',
272+
'input-file',
273+
'input-select',
274+
'input-date-range',
275+
'input-date',
276+
'input-slider'
277+
];
278+
279+
inputTypes.forEach(type => {
280+
const block: DeepnoteBlock = {
281+
id: `block-${type}`,
282+
type,
283+
source: 'input_value',
284+
metadata: {}
285+
} as any;
286+
287+
const result = convertDeepnoteBlockToJupyterCell(block);
288+
289+
expect(result.cell_type).toBe('code');
290+
});
291+
});
292+
});
293+
});

0 commit comments

Comments
 (0)