11/* eslint-disable @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */
22import { assert } from 'chai' ;
3- import { Uri , workspace } from 'vscode' ;
3+ import { Uri , workspace , NotebookDocument } from 'vscode' ;
44import { IDisposable } from '../../../platform/common/types' ;
5- import { captureScreenShot , IExtensionTestApi } from '../../common.node' ;
5+ import { captureScreenShot , IExtensionTestApi , waitForCondition } from '../../common.node' ;
66import { EXTENSION_ROOT_DIR_FOR_TESTS , initialize } from '../../initialize.node' ;
7- import { closeNotebooksAndCleanUpAfterTests } from './helper.node' ;
7+ import { closeNotebooksAndCleanUpAfterTests , startJupyterServer , getDefaultKernelConnection } from './helper.node' ;
88import { logger } from '../../../platform/logging' ;
99import { IDeepnoteNotebookManager } from '../../../notebooks/types' ;
10+ import { IKernel , IKernelProvider , INotebookKernelExecution } from '../../../kernels/types' ;
11+ import { createKernelController } from './executionHelper' ;
1012
1113/* eslint-disable @typescript-eslint/no-explicit-any, no-invalid-this */
1214suite ( 'Deepnote Integration Tests @kernelCore' , function ( ) {
@@ -20,13 +22,36 @@ suite('Deepnote Integration Tests @kernelCore', function () {
2022 'notebook' ,
2123 'test.deepnote'
2224 ) ;
25+ let nbDocument : NotebookDocument ;
26+ let kernel : IKernel ;
27+ let kernelExecution : INotebookKernelExecution ;
2328 this . timeout ( 240_000 ) ;
2429
2530 suiteSetup ( async function ( ) {
2631 logger . info ( 'Suite Setup VS Code Notebook - Deepnote Integration' ) ;
2732 this . timeout ( 240_000 ) ;
2833 try {
2934 api = await initialize ( ) ;
35+ logger . info ( 'After initialize' ) ;
36+
37+ await startJupyterServer ( ) ;
38+ logger . info ( 'After starting Jupyter' ) ;
39+
40+ const notebookManager = api . serviceContainer . get < IDeepnoteNotebookManager > ( IDeepnoteNotebookManager ) ;
41+ notebookManager . selectNotebookForProject ( 'test-project-id' , 'main-notebook-id' ) ;
42+
43+ nbDocument = await workspace . openNotebookDocument ( deepnoteFilePath ) ;
44+ logger . info ( `Opened notebook with ${ nbDocument . cellCount } cells` ) ;
45+
46+ const kernelProvider = api . serviceContainer . get < IKernelProvider > ( IKernelProvider ) ;
47+ const metadata = await getDefaultKernelConnection ( ) ;
48+ const controller = createKernelController ( ) ;
49+ kernel = kernelProvider . getOrCreate ( nbDocument , { metadata, resourceUri : nbDocument . uri , controller } ) ;
50+ logger . info ( 'Before starting kernel' ) ;
51+ await kernel . start ( ) ;
52+ logger . info ( 'After starting kernel' ) ;
53+ kernelExecution = kernelProvider . getKernelExecution ( kernel ) ;
54+
3055 logger . info ( 'Suite Setup (completed)' ) ;
3156 } catch ( e ) {
3257 logger . error ( 'Suite Setup (failed) - Deepnote Integration' , e ) ;
@@ -51,30 +76,91 @@ suite('Deepnote Integration Tests @kernelCore', function () {
5176 test ( 'Load .deepnote file' , async function ( ) {
5277 logger . debug ( 'Test: Load .deepnote file - starting' ) ;
5378
54- const notebookManager = api . serviceContainer . get < IDeepnoteNotebookManager > ( IDeepnoteNotebookManager ) ;
55- assert . isOk ( notebookManager , 'Notebook manager should be available' ) ;
56-
57- notebookManager . selectNotebookForProject ( 'test-project-id' , 'main-notebook-id' ) ;
58-
59- const nbDocument = await workspace . openNotebookDocument ( deepnoteFilePath ) ;
60-
61- logger . debug ( `Opened notebook with type: ${ nbDocument . notebookType } , cells: ${ nbDocument . cellCount } ` ) ;
62-
6379 assert . equal ( nbDocument . notebookType , 'deepnote' , 'Notebook type should be deepnote' ) ;
6480 assert . equal ( nbDocument . cellCount , 3 , 'Notebook should have 3 cells' ) ;
65-
6681 assert . equal ( nbDocument . metadata ?. deepnoteProjectId , 'test-project-id' , 'Project ID should match' ) ;
6782 assert . equal ( nbDocument . metadata ?. deepnoteNotebookId , 'main-notebook-id' , 'Notebook ID should match' ) ;
6883
6984 logger . debug ( 'Test: Load .deepnote file - completed' ) ;
7085 } ) ;
7186
72- test ( 'Extension services are available' , async function ( ) {
73- logger . debug ( 'Test: Extension services are available - starting' ) ;
87+ test ( 'Execute code cell and verify output' , async function ( ) {
88+ logger . debug ( 'Test: Execute code cell - starting' ) ;
89+
90+ const cell = nbDocument . cellAt ( 0 ) ;
91+ assert . equal ( cell . kind , 1 , 'First cell should be a code cell' ) ;
92+
93+ await kernelExecution . executeCell ( cell ) ;
94+
95+ await waitForCondition (
96+ async ( ) => cell . executionSummary ?. success === true ,
97+ 30_000 ,
98+ 'Cell execution did not complete successfully'
99+ ) ;
100+
101+ assert . isAtLeast ( cell . executionSummary ?. executionOrder || 0 , 1 , 'Cell should have execution order' ) ;
102+ assert . isTrue ( cell . executionSummary ?. success , 'Cell execution should succeed' ) ;
103+ assert . isAtLeast ( cell . outputs . length , 1 , 'Cell should have at least one output' ) ;
104+
105+ const outputText = new TextDecoder ( ) . decode ( cell . outputs [ 0 ] . items [ 0 ] . data ) . toString ( ) ;
106+ assert . include ( outputText , 'Hello World' , 'Output should contain "Hello World"' ) ;
107+
108+ logger . debug ( 'Test: Execute code cell - completed' ) ;
109+ } ) ;
110+
111+ test ( 'Execute multiple code cells with shared state' , async function ( ) {
112+ logger . debug ( 'Test: Execute multiple code cells - starting' ) ;
113+
114+ const cell1 = nbDocument . cellAt ( 0 ) ;
115+ const cell2 = nbDocument . cellAt ( 1 ) ;
116+
117+ await kernelExecution . executeCell ( cell1 ) ;
118+ await waitForCondition (
119+ async ( ) => cell1 . executionSummary ?. success === true ,
120+ 30_000 ,
121+ 'First cell execution did not complete'
122+ ) ;
123+
124+ await kernelExecution . executeCell ( cell2 ) ;
125+ await waitForCondition (
126+ async ( ) => cell2 . executionSummary ?. success === true ,
127+ 30_000 ,
128+ 'Second cell execution did not complete'
129+ ) ;
130+
131+ assert . isTrue ( cell2 . executionSummary ?. success , 'Second cell should execute successfully' ) ;
132+ assert . isAtLeast ( cell2 . outputs . length , 1 , 'Second cell should have output' ) ;
133+
134+ const outputText = new TextDecoder ( ) . decode ( cell2 . outputs [ 0 ] . items [ 0 ] . data ) . toString ( ) ;
135+ assert . include ( outputText , '42' , 'Output should contain the value 42' ) ;
136+
137+ logger . debug ( 'Test: Execute multiple code cells - completed' ) ;
138+ } ) ;
139+
140+ test ( 'Init notebook executes automatically' , async function ( ) {
141+ logger . debug ( 'Test: Init notebook execution - starting' ) ;
74142
75143 const notebookManager = api . serviceContainer . get < IDeepnoteNotebookManager > ( IDeepnoteNotebookManager ) ;
76- assert . isOk ( notebookManager , 'Notebook manager should be available' ) ;
77144
78- logger . debug ( 'Test: Extension services are available - completed' ) ;
145+ await waitForCondition (
146+ async ( ) => notebookManager . hasInitNotebookBeenRun ( 'test-project-id' ) ,
147+ 60_000 ,
148+ 'Init notebook did not execute within timeout'
149+ ) ;
150+
151+ assert . isTrue (
152+ notebookManager . hasInitNotebookBeenRun ( 'test-project-id' ) ,
153+ 'Init notebook should have been marked as run'
154+ ) ;
155+
156+ const cell = nbDocument . cellAt ( 0 ) ;
157+ await kernelExecution . executeCell ( cell ) ;
158+ await waitForCondition (
159+ async ( ) => cell . executionSummary ?. success === true ,
160+ 30_000 ,
161+ 'Cell execution did not complete'
162+ ) ;
163+
164+ logger . debug ( 'Test: Init notebook execution - completed' ) ;
79165 } ) ;
80166} ) ;
0 commit comments