Skip to content

Commit d20d532

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 d20d532

2 files changed

Lines changed: 101 additions & 6 deletions

File tree

src/test/suite/sessInstall.test.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
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+
let originalSessionWatcher: boolean | undefined;
13+
14+
setup(() => {
15+
sandbox = sinon.createSandbox();
16+
mockExtensionContext(extension_root, sandbox);
17+
originalSessionWatcher = vscode.workspace.getConfiguration('r').get<boolean>('sessionWatcher');
18+
});
19+
20+
teardown(async () => {
21+
await vscode.workspace.getConfiguration('r').update('sessionWatcher', originalSessionWatcher, vscode.ConfigurationTarget.Global);
22+
sandbox.restore();
23+
});
24+
25+
test('promptToInstallSessPackage does nothing if sessionWatcher is disabled', async () => {
26+
await vscode.workspace.getConfiguration('r').update('sessionWatcher', false, vscode.ConfigurationTarget.Global);
27+
28+
const getVersionStub = sandbox.stub(util, 'getRPackageVersion').resolves(undefined);
29+
const showMessageStub = sandbox.stub(vscode.window, 'showErrorMessage').resolves(undefined);
30+
31+
await util.promptToInstallSessPackage();
32+
33+
assert.strictEqual(getVersionStub.called, false);
34+
assert.strictEqual(showMessageStub.called, false);
35+
});
36+
37+
test('promptToInstallSessPackage prompts to install if not installed', async () => {
38+
await vscode.workspace.getConfiguration('r').update('sessionWatcher', true, vscode.ConfigurationTarget.Global);
39+
sandbox.stub(util, 'getRPackageVersion').resolves(undefined);
40+
41+
// Mock reading DESCRIPTION file
42+
sandbox.stub(util, 'readFileSyncSafe').returns('Package: sess\nVersion: 0.1.0\n');
43+
44+
const showMessageStub = sandbox.stub(vscode.window, 'showErrorMessage').resolves(undefined);
45+
46+
await util.promptToInstallSessPackage();
47+
48+
assert.strictEqual(showMessageStub.calledOnce, true);
49+
const args = showMessageStub.getCall(0).args;
50+
assert.ok(args[0].includes('required for the session watcher to work'));
51+
});
52+
53+
test('promptToInstallSessPackage prompts to update if installed version is older', async () => {
54+
await vscode.workspace.getConfiguration('r').update('sessionWatcher', true, vscode.ConfigurationTarget.Global);
55+
sandbox.stub(util, 'getRPackageVersion').resolves('0.0.9');
56+
57+
// Mock reading DESCRIPTION file with newer version
58+
sandbox.stub(util, 'readFileSyncSafe').returns('Package: sess\nVersion: 0.1.0\n');
59+
60+
const showMessageStub = sandbox.stub(vscode.window, 'showErrorMessage').resolves(undefined);
61+
62+
await util.promptToInstallSessPackage();
63+
64+
assert.strictEqual(showMessageStub.calledOnce, true);
65+
const args = showMessageStub.getCall(0).args;
66+
assert.ok(args[0].includes('A newer version of R package "sess" (0.1.0) is available'));
67+
});
68+
69+
test('promptToInstallSessPackage does not prompt if installed version is newer or equal', async () => {
70+
await vscode.workspace.getConfiguration('r').update('sessionWatcher', true, vscode.ConfigurationTarget.Global);
71+
sandbox.stub(util, 'getRPackageVersion').resolves('0.1.0');
72+
73+
sandbox.stub(util, 'readFileSyncSafe').returns('Package: sess\nVersion: 0.1.0\n');
74+
75+
const showMessageStub = sandbox.stub(vscode.window, 'showErrorMessage').resolves(undefined);
76+
77+
await util.promptToInstallSessPackage();
78+
79+
assert.strictEqual(showMessageStub.called, false);
80+
});
81+
});

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 as typeof import('./util')).config();
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 as typeof import('./util')).readFileSyncSafe(descriptionPath);
604+
const match = descriptionContent?.match(/^Version:\s*(.+)$/m);
605+
const bundledVersion = match ? match[1] : undefined;
606+
607+
const installedVersion = await (exports as typeof import('./util')).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)