Skip to content

Commit 507508e

Browse files
committed
test: Add test for DeepnoteRequirementsHelper
Signed-off-by: Tomas Kislan <[email protected]>
1 parent 31be353 commit 507508e

File tree

1 file changed

+93
-0
lines changed

1 file changed

+93
-0
lines changed
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import { assert } from 'chai';
2+
import * as sinon from 'sinon';
3+
import { instance, mock, when } from 'ts-mockito';
4+
import { CancellationToken, Uri, WorkspaceFolder } from 'vscode';
5+
import * as fs from 'fs';
6+
7+
import { DeepnoteRequirementsHelper } from './deepnoteRequirementsHelper.node';
8+
import type { DeepnoteProject } from '../../platform/deepnote/deepnoteTypes';
9+
import { ILogger } from '../../platform/logging/types';
10+
import { IPersistentStateFactory } from '../../platform/common/types';
11+
import { mockedVSCodeNamespaces, resetVSCodeMocks } from '../../test/vscode-mock';
12+
13+
suite('DeepnoteRequirementsHelper', () => {
14+
let helper: DeepnoteRequirementsHelper;
15+
let mockLogger: ILogger;
16+
let mockPersistentStateFactory: IPersistentStateFactory;
17+
let mockCancellationToken: CancellationToken;
18+
let sandbox: sinon.SinonSandbox;
19+
20+
setup(() => {
21+
resetVSCodeMocks();
22+
sandbox = sinon.createSandbox();
23+
24+
// Create mocks
25+
mockLogger = mock<ILogger>();
26+
mockPersistentStateFactory = mock<IPersistentStateFactory>();
27+
mockCancellationToken = mock<CancellationToken>();
28+
29+
// Setup default behavior for cancellation token
30+
when(mockCancellationToken.isCancellationRequested).thenReturn(false);
31+
32+
// Create the helper with mocked dependencies
33+
helper = new DeepnoteRequirementsHelper(instance(mockLogger), instance(mockPersistentStateFactory));
34+
});
35+
36+
teardown(() => {
37+
sandbox.restore();
38+
});
39+
40+
test('should create requirements.txt file with valid requirements', async () => {
41+
// Arrange
42+
const workspaceUri = Uri.file('/test/workspace');
43+
const mockWorkspaceFolder: WorkspaceFolder = {
44+
uri: workspaceUri,
45+
name: 'test-workspace',
46+
index: 0
47+
};
48+
49+
when(mockedVSCodeNamespaces.workspace.workspaceFolders).thenReturn([mockWorkspaceFolder]);
50+
51+
const project: DeepnoteProject = {
52+
metadata: {
53+
createdAt: '2024-01-01T00:00:00Z'
54+
},
55+
version: '1',
56+
project: {
57+
id: 'test-project-id',
58+
name: 'Test Project',
59+
notebooks: [],
60+
settings: {
61+
requirements: ['numpy>=1.20.0', 'pandas==1.3.0', 'matplotlib']
62+
}
63+
}
64+
};
65+
66+
// Mock fs.promises to check file doesn't exist
67+
const fsAccessStub = sandbox.stub(fs.promises, 'access');
68+
fsAccessStub.rejects(new Error('File not found'));
69+
70+
// Mock fs.promises.writeFile to capture what's written
71+
let writtenContent = '';
72+
let writtenPath = '';
73+
const fsWriteFileStub = sandbox.stub(fs.promises, 'writeFile');
74+
fsWriteFileStub.callsFake(async (path, content) => {
75+
writtenPath = path.toString();
76+
writtenContent = content.toString();
77+
});
78+
79+
// Act
80+
await helper.createRequirementsFile(project, instance(mockCancellationToken));
81+
82+
// Assert
83+
assert.isTrue(fsWriteFileStub.calledOnce, 'writeFile should be called once');
84+
assert.include(writtenPath, 'requirements.txt', 'Should write to requirements.txt');
85+
assert.include(writtenContent, 'numpy>=1.20.0', 'Should include numpy requirement');
86+
assert.include(writtenContent, 'pandas==1.3.0', 'Should include pandas requirement');
87+
assert.include(writtenContent, 'matplotlib', 'Should include matplotlib requirement');
88+
89+
// Verify content format (should have LF line endings)
90+
const expectedContent = 'numpy>=1.20.0\npandas==1.3.0\nmatplotlib\n';
91+
assert.strictEqual(writtenContent, expectedContent, 'Content should match expected format');
92+
});
93+
});

0 commit comments

Comments
 (0)