Skip to content

Commit 49fb1f1

Browse files
committed
feat: check sess package version and prompt for update
- Added version comparison between bundled and installed sess package. - Added unit tests in sessInstall.test.ts. - Used exports workaround in util.ts to enable stubbing of local functions in tests.
1 parent 100ed6b commit 49fb1f1

2 files changed

Lines changed: 124 additions & 6 deletions

File tree

‎src/test/suite/sessInstall.test.ts‎

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import * as assert from 'assert';
2+
import * as vscode from 'vscode';
3+
import * as sinon from 'sinon';
4+
import * as path from 'path';
5+
import * as util from '../../util';
6+
import { mockExtensionContext } from '../common/mockvscode';
7+
8+
const extension_root: string = path.join(__dirname, '..', '..', '..');
9+
10+
suite('Sess Install Test Suite', () => {
11+
let sandbox: sinon.SinonSandbox;
12+
13+
setup(() => {
14+
sandbox = sinon.createSandbox();
15+
mockExtensionContext(extension_root, sandbox);
16+
});
17+
18+
teardown(() => {
19+
sandbox.restore();
20+
});
21+
22+
test('promptToInstallSessPackage does nothing if sessionWatcher is disabled', async () => {
23+
const configStub = {
24+
get: (key: string) => {
25+
if (key === 'sessionWatcher') {
26+
return false;
27+
}
28+
return undefined;
29+
}
30+
};
31+
sandbox.stub(util, 'config').returns(configStub as unknown as vscode.WorkspaceConfiguration);
32+
33+
const getVersionStub = sandbox.stub(util, 'getRPackageVersion').resolves(undefined);
34+
const showMessageStub = sandbox.stub(vscode.window, 'showErrorMessage').resolves(undefined);
35+
36+
await util.promptToInstallSessPackage();
37+
38+
assert.strictEqual(getVersionStub.called, false);
39+
assert.strictEqual(showMessageStub.called, false);
40+
});
41+
42+
test('promptToInstallSessPackage prompts to install if not installed', async () => {
43+
const configStub = {
44+
get: (key: string) => {
45+
if (key === 'sessionWatcher') return true;
46+
return undefined;
47+
}
48+
};
49+
sandbox.stub(util, 'config').returns(configStub as unknown as vscode.WorkspaceConfiguration);
50+
sandbox.stub(util, 'getRPackageVersion').resolves(undefined);
51+
52+
// Mock reading DESCRIPTION file
53+
sandbox.stub(util, 'readFileSyncSafe').returns('Package: sess\nVersion: 0.1.0\n');
54+
55+
const showMessageStub = sandbox.stub(vscode.window, 'showErrorMessage').resolves(undefined);
56+
57+
await util.promptToInstallSessPackage();
58+
59+
assert.strictEqual(showMessageStub.calledOnce, true);
60+
const args = showMessageStub.getCall(0).args;
61+
assert.ok(args[0].includes('required for the session watcher to work'));
62+
});
63+
64+
test('promptToInstallSessPackage prompts to update if installed version is older', async () => {
65+
const configStub = {
66+
get: (key: string) => {
67+
if (key === 'sessionWatcher') return true;
68+
return undefined;
69+
}
70+
};
71+
sandbox.stub(util, 'config').returns(configStub as unknown as vscode.WorkspaceConfiguration);
72+
sandbox.stub(util, 'getRPackageVersion').resolves('0.0.9');
73+
74+
// Mock reading DESCRIPTION file with newer version
75+
sandbox.stub(util, 'readFileSyncSafe').returns('Package: sess\nVersion: 0.1.0\n');
76+
77+
const showMessageStub = sandbox.stub(vscode.window, 'showErrorMessage').resolves(undefined);
78+
79+
await util.promptToInstallSessPackage();
80+
81+
assert.strictEqual(showMessageStub.calledOnce, true);
82+
const args = showMessageStub.getCall(0).args;
83+
assert.ok(args[0].includes('A newer version of R package "sess" (0.1.0) is available'));
84+
});
85+
86+
test('promptToInstallSessPackage does not prompt if installed version is newer or equal', async () => {
87+
const configStub = {
88+
get: (key: string) => {
89+
if (key === 'sessionWatcher') return true;
90+
return undefined;
91+
}
92+
};
93+
sandbox.stub(util, 'config').returns(configStub as unknown as vscode.WorkspaceConfiguration);
94+
sandbox.stub(util, 'getRPackageVersion').resolves('0.1.0');
95+
96+
sandbox.stub(util, 'readFileSyncSafe').returns('Package: sess\nVersion: 0.1.0\n');
97+
98+
const showMessageStub = sandbox.stub(vscode.window, 'showErrorMessage').resolves(undefined);
99+
100+
await util.promptToInstallSessPackage();
101+
102+
assert.strictEqual(showMessageStub.called, false);
103+
});
104+
});

‎src/util.ts‎

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -592,19 +592,33 @@ export async function promptToInstallRPackage(name: string, section: string, cwd
592592
* Prompt to install the bundled "sess" package
593593
*/
594594
export async function promptToInstallSessPackage(cwd?: string | vscode.Uri): Promise<void> {
595-
const _config = config();
595+
const _config = exports.config() as vscode.WorkspaceConfiguration;
596596
const sessionWatcher = _config.get<boolean>('sessionWatcher');
597597
if (!sessionWatcher) {
598598
return;
599599
}
600-
const sessVersion = await getRPackageVersion('sess', cwd instanceof vscode.Uri ? cwd.fsPath : cwd);
601-
if (sessVersion) {
602-
return;
603-
}
604600

605601
const sessPath = extensionContext.asAbsolutePath('sess').replace(/\\/g, '/');
602+
const descriptionPath = path.join(sessPath, 'DESCRIPTION');
603+
const descriptionContent = exports.readFileSyncSafe(descriptionPath);
604+
const match = descriptionContent?.match(/^Version:\s*(.+)$/m);
605+
const bundledVersion = match ? match[1] : undefined;
606+
607+
const installedVersion = await exports.getRPackageVersion('sess', cwd instanceof vscode.Uri ? cwd.fsPath : cwd);
608+
609+
if (installedVersion && bundledVersion && compareVersions(installedVersion, bundledVersion) >= 0) {
610+
return; // Already up to date
611+
} else if (installedVersion && !bundledVersion) {
612+
return; // Cannot determine bundled version, assume OK
613+
}
614+
606615
const installSessScript = extensionContext.asAbsolutePath(path.join('R', 'install_sess.R')).replace(/\\/g, '/');
607-
const installMsg = 'R package "sess" (shipped with vscode-R) is required for the session watcher to work. Do you want to install it?';
616+
617+
let installMsg = 'R package "sess" (shipped with vscode-R) is required for the session watcher to work. Do you want to install it?';
618+
if (installedVersion && bundledVersion && compareVersions(installedVersion, bundledVersion) < 0) {
619+
installMsg = `A newer version of R package "sess" (${bundledVersion}) is available (installed: ${installedVersion}). Do you want to update it?`;
620+
}
621+
608622
await vscode.window.showErrorMessage(installMsg, 'Yes', 'No')
609623
.then(async function (select) {
610624
if (select === 'Yes') {

0 commit comments

Comments
 (0)