Skip to content

Commit

Permalink
Basic unit test for workspace viewer (#1305)
Browse files Browse the repository at this point in the history
- Introduces basic unit testing for the workspace viewer
- Proposes unit testing through mocking the vscode API via the sinon library
  • Loading branch information
ElianHugh authored Feb 17, 2023
1 parent 0e49417 commit db11fa0
Show file tree
Hide file tree
Showing 9 changed files with 3,020 additions and 2,627 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2011,6 +2011,7 @@
"@types/mocha": "^8.2.2",
"@types/node": "^16.11.7",
"@types/node-fetch": "^2.5.10",
"@types/sinon": "^10.0.13",
"@types/vscode": "^1.67.0",
"@types/winreg": "^1.2.31",
"@typescript-eslint/eslint-plugin": "^5.30.0",
Expand All @@ -2021,6 +2022,7 @@
"eslint": "^7.28.0",
"eslint-plugin-jsdoc": "^35.1.3",
"mocha": "^9.1.0",
"sinon": "^15.0.1",
"ts-loader": "^9.3.1",
"typescript": "^4.7.2",
"webpack": "^5.38.1",
Expand Down
2 changes: 1 addition & 1 deletion src/rmarkdown/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ export abstract class RMarkdownManager {
let childProcess: DisposableProcess | undefined = undefined;
await util.doWithProgress(
(async (
token: vscode.CancellationToken | undefined,
token: vscode.CancellationToken | undefined,
progress: vscode.Progress<{
message?: string | undefined;
increment?: number | undefined;
Expand Down
1 change: 1 addition & 0 deletions src/test/common/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './mockvscode';
37 changes: 37 additions & 0 deletions src/test/common/mockvscode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import * as vscode from 'vscode';
import sinon = require('sinon');
import path = require('path');
import * as ext from '../../extension';

export function mockActiveTextEditor(document: vscode.TextDocument, sandbox: sinon.SinonSandbox) {
return sandbox.stub(vscode.window, 'activeTextEditor').value({
document
});
}

export function mockExtensionContext(extension_root: string, sandbox: sinon.SinonSandbox) {
const mockExtensionContext = {
environmentVariableCollection: sandbox.stub(),
extension: sandbox.stub(),
extensionMode: sandbox.stub(),
extensionPath: sandbox.stub(),
extensionUri: sandbox.stub(),
globalState: {
get: sinon.stub(),
set: sinon.stub()
},
globalStorageUri: sandbox.stub(),
logUri: sandbox.stub(),
secrets: sandbox.stub(),
storageUri: sandbox.stub(),
subscriptions: [],
workspaceState: {
get: sinon.stub(),
update: sinon.stub()
},
asAbsolutePath: (relativePath: string) => {
return path.join(extension_root, relativePath);
}
};
return sandbox.stub(ext, 'extensionContext').value(mockExtensionContext);
}
55 changes: 55 additions & 0 deletions src/test/suite/sesson.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import vscode = require('vscode');
import sinon = require('sinon');
import path = require('path');
import * as assert from 'assert';
import * as fs from 'fs-extra';

import { mockExtensionContext } from '../common';
import * as session from '../../session';
import * as workspace from '../../workspaceViewer';

const extension_root: string = path.join(__dirname, '..', '..', '..');
const workspaceFile = path.join(extension_root, 'test', 'rFiles', 'session', 'workspace.json');

function mockWorkspaceData(sandbox: sinon.SinonSandbox) {
const content = fs.readFileSync(workspaceFile, 'utf8');
const workspaceData = JSON.parse(content) as session.WorkspaceData;
return sandbox.stub(session, 'workspaceData').value(workspaceData);
}

suite('Workspace Viewer', () => {
let sandbox: sinon.SinonSandbox;
let workspaceViewer: workspace.WorkspaceDataProvider;
let nodes: vscode.TreeItem[];

setup(() => {
sandbox = sinon.createSandbox();
});
teardown(() => {
sandbox.restore();
});

test('has 3 nodes', async () => {
mockExtensionContext(extension_root, sandbox);
mockWorkspaceData(sandbox);
workspaceViewer = new workspace.WorkspaceDataProvider();
workspaceViewer.refresh();
nodes = await workspaceViewer.getChildren();
assert.strictEqual(nodes.length, 3);
});

test('search node', async () => {
const search = await workspaceViewer.getChildren(nodes[0]);
assert.strictEqual(search.length, 10);
});

test('attached node', async () => {
const attached = await workspaceViewer.getChildren(nodes[1]);
assert.strictEqual(attached.length, 14);
});

test('env node', async () => {
const env: workspace.GlobalEnvItem[] = await workspaceViewer.getChildren(nodes[2]) as workspace.GlobalEnvItem[];
assert.strictEqual(env.length, 9);
});
});
22 changes: 11 additions & 11 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ export async function spawnAsync(command: string, args?: ReadonlyArray<string>,
status: null,
signal: null
};

try {
const childProcess = spawn(command, args, options, onDisposed);
if (childProcess.pid !== undefined) {
Expand Down Expand Up @@ -536,7 +536,7 @@ export async function promptToInstallRPackage(name: string, section: string, cwd

/**
* Create temporary directory. Will avoid name clashes. Caller must delete directory after use.
*
*
* @param root Parent folder.
* @param hidden If set to true, directory will be prefixed with a '.' (ignored on windows).
* @returns Path to the temporary directory.
Expand All @@ -551,18 +551,18 @@ export function createTempDir(root: string, hidden?: boolean): string {

/**
* Utility function for converting 'unknown' types to errors.
*
*
* Usage:
*
*
* ```ts
* try { ... }
* catch (e) {
* const err: Error = catchAsError(e);
* try { ... }
* catch (e) {
* const err: Error = catchAsError(e);
* }
* ```
* @param err
* @param fallbackMessage
* @returns
* @param err
* @param fallbackMessage
* @returns
*/
export function catchAsError(err: unknown, fallbackMessage?: string): Error {
return (err instanceof Error) ? err : Error(fallbackMessage ?? 'Unknown error');
Expand Down Expand Up @@ -623,7 +623,7 @@ export function statSyncSafe(path: fs.PathLike): fs.Stats | undefined {
try {
return fs.statSync(path);
} catch (e) {

}
}

Expand Down
5 changes: 5 additions & 0 deletions test/rFiles/rmarkdown/basic.rmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
title: Hello World
---

Hello world
147 changes: 147 additions & 0 deletions test/rFiles/session/workspace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
{
"search": [
"tools:vscode",
"package:stats",
"package:graphics",
"package:grDevices",
"package:datasets",
"tools:custom",
"package:utils",
"package:methods",
"Autoloads",
"package:base"
],
"loaded_namespaces": [
"compiler",
"cli",
"graphics",
"tools",
"utils",
"grDevices",
"crayon",
"stats",
"datasets",
"methods",
"jsonlite",
"rlang",
"base",
"pak"
],
"globalenv": {
"a": {
"class": [
"character"
],
"type": "character",
"length": 1,
"size": 112,
"str": "chr \"a\""
},
"b": {
"class": [
"integer"
],
"type": "integer",
"length": 1,
"size": 56,
"str": "int 1"
},
"c": {
"class": [
"numeric"
],
"type": "double",
"length": 1,
"size": 56,
"str": "num 1.5"
},
"d": {
"class": [
"complex"
],
"type": "complex",
"length": 1,
"size": 64,
"str": "cplx 0+0i"
},
"e": {
"class": [
"logical"
],
"type": "logical",
"length": 1,
"size": 56,
"str": "logi TRUE"
},
"f": {
"class": [
"function"
],
"type": "closure",
"length": 1,
"size": 1240,
"str": "function (x, ...)"
},
"g": {
"class": [
"environment"
],
"type": "environment",
"length": 11,
"size": 56,
"str": "<environment: R_GlobalEnv>",
"names": [
"a",
"b",
"c",
"d",
"e",
"f",
".local.name",
"g",
".local",
"h",
"i"
]
},
"h": {
"class": [
"list"
],
"type": "list",
"length": 2,
"size": 520,
"str": "List of 2\n $ a: num 1\n $ b: chr \"foo\"",
"names": [
"a",
"b"
]
},
"i": {
"class": [
"data.frame"
],
"type": "list",
"length": 11,
"size": 7208,
"str": "'data.frame':\t32 obs. of 11 variables:\n $ mpg : num 21 21 ...\n $ cyl : num 6 6 ...\n $ disp: num 160 160 ...\n $ hp : num 110 110 ...\n $ drat: num 3.9 3.9 ...\n $ wt : num 2.62 ...\n $ qsec: num 16.5 ...\n $ vs : num 0 0 ...\n $ am : num 1 1 ...\n $ gear: num 4 4 ...\n $ carb: num 4 4 ...",
"names": [
"mpg",
"cyl",
"disp",
"hp",
"drat",
"wt",
"qsec",
"vs",
"am",
"gear",
"carb"
],
"dim": [
32,
11
]
}
}
}
Loading

0 comments on commit db11fa0

Please sign in to comment.