Skip to content

Commit 12fd98f

Browse files
committed
chore: add tests
1 parent 6fe639b commit 12fd98f

File tree

2 files changed

+188
-0
lines changed

2 files changed

+188
-0
lines changed

src/notebooks/deepnote/deepnoteTreeDataProvider.unit.test.ts

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,102 @@ suite('DeepnoteTreeDataProvider', () => {
160160
});
161161
});
162162

163+
suite('loading state', () => {
164+
test('should show loading item on first getChildren call', async () => {
165+
const children = await provider.getChildren();
166+
167+
assert.isArray(children);
168+
assert.strictEqual(children.length, 1);
169+
assert.strictEqual(children[0].type, DeepnoteTreeItemType.Loading);
170+
assert.strictEqual(children[0].contextValue, 'loading');
171+
});
172+
173+
test('should create loading item with correct properties', async () => {
174+
const children = await provider.getChildren();
175+
const loadingItem = children[0];
176+
177+
assert.strictEqual(loadingItem.type, DeepnoteTreeItemType.Loading);
178+
assert.strictEqual(loadingItem.label, 'Scanning for Deepnote projects...');
179+
assert.strictEqual(loadingItem.collapsibleState, 0); // TreeItemCollapsibleState.None
180+
assert.strictEqual(loadingItem.data, null);
181+
assert.isDefined(loadingItem.iconPath);
182+
});
183+
184+
test('should not show loading item after initial scan completes', async () => {
185+
const firstChildren = await provider.getChildren();
186+
assert.strictEqual(firstChildren.length, 1);
187+
assert.strictEqual(firstChildren[0].type, DeepnoteTreeItemType.Loading);
188+
189+
// Wait for the scan to complete - give it time to finish
190+
await new Promise((resolve) => setTimeout(resolve, 100));
191+
192+
const secondChildren = await provider.getChildren();
193+
assert.isArray(secondChildren);
194+
195+
if (secondChildren.length > 0) {
196+
assert.notStrictEqual(secondChildren[0].type, DeepnoteTreeItemType.Loading);
197+
}
198+
});
199+
200+
test('should reset loading state on refresh', async () => {
201+
const firstChildren = await provider.getChildren();
202+
assert.strictEqual(firstChildren[0].type, DeepnoteTreeItemType.Loading);
203+
204+
await new Promise((resolve) => setTimeout(resolve, 100));
205+
206+
const afterScan = await provider.getChildren();
207+
if (afterScan.length > 0) {
208+
assert.notStrictEqual(afterScan[0].type, DeepnoteTreeItemType.Loading);
209+
}
210+
211+
// Call refresh to reset state, should show loading again
212+
provider.refresh();
213+
const afterRefresh = await provider.getChildren();
214+
assert.isArray(afterRefresh);
215+
assert.strictEqual(afterRefresh.length, 1);
216+
assert.strictEqual(afterRefresh[0].type, DeepnoteTreeItemType.Loading);
217+
});
218+
219+
test('should handle multiple concurrent getChildren calls during initial scan', async () => {
220+
const promise1 = provider.getChildren();
221+
const promise2 = provider.getChildren();
222+
const promise3 = provider.getChildren();
223+
224+
const [children1, children2, children3] = await Promise.all([promise1, promise2, promise3]);
225+
226+
// All should return loading item
227+
assert.strictEqual(children1.length, 1);
228+
assert.strictEqual(children1[0].type, DeepnoteTreeItemType.Loading);
229+
230+
assert.strictEqual(children2.length, 1);
231+
assert.strictEqual(children2[0].type, DeepnoteTreeItemType.Loading);
232+
233+
assert.strictEqual(children3.length, 1);
234+
assert.strictEqual(children3[0].type, DeepnoteTreeItemType.Loading);
235+
});
236+
237+
test('should not show loading item when called with parent element', async () => {
238+
const mockProjectItem = new DeepnoteTreeItem(
239+
DeepnoteTreeItemType.ProjectFile,
240+
{
241+
filePath: '/workspace/project.deepnote',
242+
projectId: 'project-123'
243+
},
244+
mockProject,
245+
1 // TreeItemCollapsibleState.Collapsed
246+
);
247+
248+
// Even during initial scan, should not show loading for children of a project
249+
const children = await provider.getChildren(mockProjectItem);
250+
251+
assert.isArray(children);
252+
253+
children.forEach((child) => {
254+
assert.notStrictEqual(child.type, DeepnoteTreeItemType.Loading);
255+
});
256+
});
257+
});
258+
163259
suite('integration scenarios', () => {
164260
test('should maintain independence between multiple providers', () => {
165261
const provider1 = new DeepnoteTreeDataProvider();

src/notebooks/deepnote/deepnoteTreeItem.unit.test.ts

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,98 @@ suite('DeepnoteTreeItem', () => {
579579
});
580580
});
581581

582+
suite('Loading type', () => {
583+
test('should create loading item with null data', () => {
584+
const context: DeepnoteTreeItemContext = {
585+
filePath: '',
586+
projectId: ''
587+
};
588+
589+
const item = new DeepnoteTreeItem(
590+
DeepnoteTreeItemType.Loading,
591+
context,
592+
null,
593+
TreeItemCollapsibleState.None
594+
);
595+
596+
assert.strictEqual(item.type, DeepnoteTreeItemType.Loading);
597+
assert.strictEqual(item.data, null);
598+
assert.strictEqual(item.collapsibleState, TreeItemCollapsibleState.None);
599+
assert.strictEqual(item.contextValue, 'loading');
600+
});
601+
602+
test('should not initialize label/tooltip/icon for loading items', () => {
603+
const context: DeepnoteTreeItemContext = {
604+
filePath: '',
605+
projectId: ''
606+
};
607+
608+
const item = new DeepnoteTreeItem(
609+
DeepnoteTreeItemType.Loading,
610+
context,
611+
null,
612+
TreeItemCollapsibleState.None
613+
);
614+
615+
// Label, iconPath, tooltip should be undefined or empty until manually set
616+
// (they are not initialized in constructor for loading items)
617+
assert.strictEqual(item.label, '');
618+
});
619+
620+
test('should allow manual label and icon assignment for loading items', () => {
621+
const context: DeepnoteTreeItemContext = {
622+
filePath: '',
623+
projectId: ''
624+
};
625+
626+
const item = new DeepnoteTreeItem(
627+
DeepnoteTreeItemType.Loading,
628+
context,
629+
null,
630+
TreeItemCollapsibleState.None
631+
);
632+
633+
item.label = 'Scanning for Deepnote projects...';
634+
item.iconPath = new ThemeIcon('loading~spin');
635+
636+
assert.strictEqual(item.label, 'Scanning for Deepnote projects...');
637+
assert.instanceOf(item.iconPath, ThemeIcon);
638+
assert.strictEqual((item.iconPath as ThemeIcon).id, 'loading~spin');
639+
});
640+
641+
test('should not have command for loading items', () => {
642+
const context: DeepnoteTreeItemContext = {
643+
filePath: '',
644+
projectId: ''
645+
};
646+
647+
const item = new DeepnoteTreeItem(
648+
DeepnoteTreeItemType.Loading,
649+
context,
650+
null,
651+
TreeItemCollapsibleState.None
652+
);
653+
654+
assert.isUndefined(item.command);
655+
});
656+
657+
test('should not have resourceUri for loading items', () => {
658+
const context: DeepnoteTreeItemContext = {
659+
filePath: '',
660+
projectId: ''
661+
};
662+
663+
const item = new DeepnoteTreeItem(
664+
DeepnoteTreeItemType.Loading,
665+
context,
666+
null,
667+
TreeItemCollapsibleState.None
668+
);
669+
670+
assert.isUndefined(item.resourceUri);
671+
});
672+
});
673+
582674
suite('integration scenarios', () => {
583675
test('should create valid tree structure hierarchy', () => {
584676
// Create parent project file

0 commit comments

Comments
 (0)