Skip to content

Commit

Permalink
Added check for minimum supported gauge version#74 (#75)
Browse files Browse the repository at this point in the history
  • Loading branch information
Vinay Shankar Shukla authored and nehashri committed Dec 20, 2017
1 parent 78b1e3d commit 79574bb
Show file tree
Hide file tree
Showing 6 changed files with 207 additions and 71 deletions.
14 changes: 13 additions & 1 deletion src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export enum VSCodeCommands {
ShowReferences = 'editor.action.showReferences'
}

export enum GaugeCommands {
export enum GaugeVSCodeCommands {
StopExecution = 'gauge.stopExecution',
RefreshExplorer = 'gauge.specexplorer.refresh',
Execute = 'gauge.execute',
Expand All @@ -26,6 +26,18 @@ export enum GaugeCommands {
RepeatExecution = 'gauge.execute.repeat',
}

export enum GaugeCommands {
Gauge = 'gauge',
Version = '--version',
MachineReadable = '--machine-readable',
Run = 'run',
Parallel = '--parallel',
SimpleConsole = '--simple-console',
RerunFailed = '--failed',
Repeat = '--repeat',
HideSuggestion = '--hide-suggestion',
}

export enum GaugeCommandContext {
Enabled = 'gauge:enabled',
Activated = 'gauge:activated',
Expand Down
48 changes: 22 additions & 26 deletions src/execution/gaugeExecution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,30 @@ import cp = require('child_process');
import path = require('path');
import { LineBuffer } from './lineBuffer'
import { OutputChannel } from './outputChannel'
import { GaugeCommands } from '../commands';
import { GaugeVSCodeCommands, GaugeCommands } from '../commands';
import { ChildProcess } from 'child_process';

const gauge = 'gauge';
const run = 'run';
const parallel = '--parallel';
const simpleConsole = '--simple-console';
const rerunFailed = '--failed';
const repeat = '--repeat';
const hideSuggestion = '--hide-suggestion';
const outputChannelName = 'Gauge Execution';
const extensions = [".spec", ".md"];
const GAUGE_EXECUTION_CONFIG = "gauge.execution"
let outputChannel = vscode.window.createOutputChannel(outputChannelName);
let executing : boolean;
let process : ChildProcess;
let preExecute : Function[] = [];
let postExecute : Function[] = [];
let executing: boolean;
let process: ChildProcess;
let preExecute: Function[] = [];
let postExecute: Function[] = [];

export function execute(spec: string, config: any): Thenable<any> {
return new Promise((resolve, reject) => {
if(executing){
if (executing) {
reject('A Specification or Scenario is still running!');
return;
}

executing = true;
preExecute.forEach(f => f.call(null, path.relative(vscode.workspace.rootPath, config.status)))
let args = getArgs(spec, config);
let chan = new OutputChannel(outputChannel, ['Running tool:', gauge, args.join(' ')].join(' '));
process = cp.spawn(gauge, args, { cwd: vscode.workspace.rootPath });
let chan = new OutputChannel(outputChannel, ['Running tool:', GaugeCommands.Gauge, args.join(' ')].join(' '));
process = cp.spawn(GaugeCommands.Gauge, args, { cwd: vscode.workspace.rootPath });
process.stdout.on('data', chunk => chan.appendOutBuf(chunk.toString()));
process.stderr.on('data', chunk => chan.appendErrBuf(chunk.toString()));
process.on('exit', (code, signal) => {
Expand All @@ -48,41 +41,44 @@ export function execute(spec: string, config: any): Thenable<any> {
});
}

export function cancel(){
if(process && !process.killed)
export function cancel() {
if (process && !process.killed)
process.kill();
}

export function onBeforeExecute(hook : Function) {
export function onBeforeExecute(hook: Function) {
preExecute.push(hook);
}

export function onExecuted(hook : Function) {
export function onExecuted(hook: Function) {
postExecute.push(hook);
}

function getArgs(spec, config): Array<string> {
if (config.rerunFailed) {
return [run, rerunFailed];
return [GaugeCommands.Run, GaugeCommands.RerunFailed];
}
if (config.repeat) {
return [run, repeat];
return [GaugeCommands.Run, GaugeCommands.Repeat];
}
return (!config.inParallel) ? [run, spec, simpleConsole, hideSuggestion] : [run, parallel, spec, hideSuggestion];
if (config.inParallel) {
return [GaugeCommands.Run, GaugeCommands.Parallel, spec, GaugeCommands.HideSuggestion];
}
return [GaugeCommands.Run, spec, GaugeCommands.SimpleConsole, GaugeCommands.HideSuggestion];
}


export function runSpecification(all?: boolean): Thenable<any> {
if (all) {
let dirs = vscode.workspace.getConfiguration(GAUGE_EXECUTION_CONFIG).get<Array<string>>("specDirs");
return execute(dirs.join(" "), { inParallel: false , status : dirs.join(" ")});
return execute(dirs.join(" "), { inParallel: false, status: dirs.join(" ") });
}
let spec = vscode.window.activeTextEditor.document.fileName;
if (!extensions.includes(path.extname(spec))) {
vscode.window.showWarningMessage(`No specification found. Current file is not a gauge specification.`);
return Promise.reject(new Error(`No specification found. Current file is not a gauge specification.`));
}
return execute(spec, { inParallel: false , status: spec});
return execute(spec, { inParallel: false, status: spec });
};

export function runScenario(languageClient: LanguageClient, atCursor: boolean): Thenable<any> {
Expand Down Expand Up @@ -124,7 +120,7 @@ function executeOptedScenario(scenarios: any): Thenable<any> {
return vscode.window.showQuickPick<any>(getQuickPickItems(sceHeadings)).then((selected) => {
if (selected) {
let sce = scenarios.find(sce => selected.label == sce.heading);
return execute(sce.executionIdentifier, { inParallel: false , status : sce.executionIdentifier});
return execute(sce.executionIdentifier, { inParallel: false, status: sce.executionIdentifier });
}
}, (reason: any) => {
return Promise.reject(reason);
Expand All @@ -135,5 +131,5 @@ function executeAtCursor(scenarios: any): Thenable<any> {
if (scenarios instanceof Array) {
return executeOptedScenario(scenarios);
}
return execute(scenarios.executionIdentifier, { inParallel: false , status: scenarios.executionIdentifier});
return execute(scenarios.executionIdentifier, { inParallel: false, status: scenarios.executionIdentifier });
}
4 changes: 2 additions & 2 deletions src/explorer/specExplorer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';
import { LanguageClient, TextDocumentIdentifier } from 'vscode-languageclient';
import { GaugeCommands } from '../commands';
import { GaugeVSCodeCommands } from '../commands';

export class SpecNodeProvider implements vscode.TreeDataProvider<GaugeNode> {

Expand Down Expand Up @@ -60,7 +60,7 @@ export abstract class GaugeNode extends vscode.TreeItem{
) {
super(label, vscode.TreeItemCollapsibleState.Collapsed);
}
command = {title:'Open File', command: GaugeCommands.Open, arguments: [this]}
command = {title:'Open File', command: GaugeVSCodeCommands.Open, arguments: [this]}
}

class Spec extends GaugeNode {
Expand Down
90 changes: 48 additions & 42 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,80 +11,78 @@ import cp = require('child_process');
import opn = require('opn');
import copyPaste = require('copy-paste');
import { execute, runScenario, runSpecification, cancel, onBeforeExecute, onExecuted } from "./execution/gaugeExecution";
import { SpecNodeProvider, GaugeNode, Scenario} from './explorer/specExplorer'
import { VSCodeCommands, GaugeCommands, GaugeCommandContext, setCommandContext } from './commands';
import { SpecNodeProvider, GaugeNode, Scenario } from './explorer/specExplorer'
import { VSCodeCommands, GaugeVSCodeCommands, GaugeCommandContext, setCommandContext } from './commands';
import { getGaugeVersionInfo, GaugeVersionInfo } from './gaugeVersion'

const DEBUG_LOG_LEVEL_CONFIG = 'enableDebugLogs';
const GAUGE_LAUNCH_CONFIG = 'gauge.launch';
const GAUGE_EXTENSION_ID = 'getgauge.gauge';
const GAUGE_SUPPRESS_UPDATE_NOTIF = 'gauge.notification.suppressUpdateNotification';
const GAUGE_VSCODE_VERSION = 'gauge.vscode.version';

const MINIMUM_SUPPORTED_GAUGE_VERSION = '0.9.6';
let launchConfig;

export function activate(context: ExtensionContext) {
let gaugeVersion = cp.spawnSync('gauge', ['-v']);
if (gaugeVersion.error) {
vscode.window.showWarningMessage("Cannot find 'gauge' executable in PATH.", 'Install').then(selected => {
if (selected === 'Install') {
opn('https://getgauge.io/get-started.html');
}
});
let gaugeVersionInfo = getGaugeVersionInfo();
if (!gaugeVersionInfo || !gaugeVersionInfo.isGreaterOrEqual(MINIMUM_SUPPORTED_GAUGE_VERSION)) {
notifyToInstallGauge(`Cannot find 'gauge' executable or a compatible version (>=${MINIMUM_SUPPORTED_GAUGE_VERSION}) in PATH.`);
return
}

let serverOptions = {
command: 'gauge',
args: ["daemon", "--lsp", "--dir=" + vscode.workspace.rootPath],
}
};

launchConfig = vscode.workspace.getConfiguration(GAUGE_LAUNCH_CONFIG);
if (launchConfig.get(DEBUG_LOG_LEVEL_CONFIG)) {
serverOptions.args.push("-l")
serverOptions.args.push("debug")
};

let clientOptions = {
documentSelector: ['gauge'],
revealOutputChannelOn: RevealOutputChannelOn.Never,
};
let languageClient = new LanguageClient('Gauge', serverOptions, clientOptions);
let disposable = languageClient.start();

var notifyNewVersion = notifyOnNewGaugeVsCodeVersion(context,
extensions.getExtension(GAUGE_EXTENSION_ID)!.packageJSON.version);
var notifyNewVersion = notifyOnNewGaugeVsCodeVersion(context,extensions.getExtension(GAUGE_EXTENSION_ID)!.packageJSON.version);

registerStopExecution(context);
context.subscriptions.push(vscode.commands.registerCommand(GaugeCommands.Execute, (spec) => { return execute(spec, { inParallel: false, status : spec }) }));
context.subscriptions.push(vscode.commands.registerCommand(GaugeCommands.ExecuteInParallel, (spec) => { return execute(spec, { inParallel: true, status: spec }) }));
context.subscriptions.push(vscode.commands.registerCommand(GaugeCommands.ExecuteFailed, () => { return execute(null, { rerunFailed: true , status: "failed scenarios"}) }));
context.subscriptions.push(vscode.commands.registerCommand(GaugeCommands.ExecuteSpec, () => { return runSpecification() }));
context.subscriptions.push(vscode.commands.registerCommand(GaugeCommands.ExecuteAllSpecs, () => { return runSpecification(true) }));
context.subscriptions.push(vscode.commands.registerCommand(GaugeCommands.ExecuteScenario, () => { return runScenario(languageClient, true) }));
context.subscriptions.push(vscode.commands.registerCommand(GaugeCommands.ExecuteScenarios, (scn: Scenario) => {
if(scn){
return execute(scn.executionIdentifier, {inParallel: false, status: scn.executionIdentifier})
context.subscriptions.push(vscode.commands.registerCommand(GaugeVSCodeCommands.Execute, (spec) => { return execute(spec, { inParallel: false, status: spec }) }));
context.subscriptions.push(vscode.commands.registerCommand(GaugeVSCodeCommands.ExecuteInParallel, (spec) => { return execute(spec, { inParallel: true, status: spec }) }));
context.subscriptions.push(vscode.commands.registerCommand(GaugeVSCodeCommands.ExecuteFailed, () => { return execute(null, { rerunFailed: true, status: "failed scenarios" }) }));
context.subscriptions.push(vscode.commands.registerCommand(GaugeVSCodeCommands.ExecuteSpec, () => { return runSpecification() }));
context.subscriptions.push(vscode.commands.registerCommand(GaugeVSCodeCommands.ExecuteAllSpecs, () => { return runSpecification(true) }));
context.subscriptions.push(vscode.commands.registerCommand(GaugeVSCodeCommands.ExecuteScenario, () => { return runScenario(languageClient, true) }));
context.subscriptions.push(vscode.commands.registerCommand(GaugeVSCodeCommands.ExecuteScenarios, (scn: Scenario) => {
if (scn) {
return execute(scn.executionIdentifier, { inParallel: false, status: scn.executionIdentifier })
}
return runScenario(languageClient, false)
}));
context.subscriptions.push(vscode.commands.registerCommand(GaugeCommands.CopyStub, (code: string) => {
context.subscriptions.push(vscode.commands.registerCommand(GaugeVSCodeCommands.CopyStub, (code: string) => {
copyPaste.copy(code);
vscode.window.showInformationMessage("Step Implementation copied to clipboard");
}));
context.subscriptions.push(vscode.commands.registerCommand(GaugeCommands.ShowReferencesAtCursor, showStepReferencesAtCursor(languageClient)));
context.subscriptions.push(vscode.commands.registerCommand(GaugeCommands.RepeatExecution, () => { return execute(null, { repeat: true ,status: "previous run"}) }));
context.subscriptions.push(vscode.commands.registerCommand(GaugeCommands.ShowReferences, showStepReferences(languageClient)));
context.subscriptions.push(vscode.commands.registerCommand(GaugeCommands.ReportIssue, () => { reportIssue(gaugeVersion); }));
context.subscriptions.push(vscode.commands.registerCommand(GaugeCommands.Open, (node: GaugeNode) => {
return vscode.workspace.openTextDocument(node.file).then(document => {
}));
context.subscriptions.push(vscode.commands.registerCommand(GaugeVSCodeCommands.ShowReferencesAtCursor, showStepReferencesAtCursor(languageClient)));
context.subscriptions.push(vscode.commands.registerCommand(GaugeVSCodeCommands.RepeatExecution, () => { return execute(null, { repeat: true, status: "previous run" }) }));
context.subscriptions.push(vscode.commands.registerCommand(GaugeVSCodeCommands.ShowReferences, showStepReferences(languageClient)));
context.subscriptions.push(vscode.commands.registerCommand(GaugeVSCodeCommands.ReportIssue, () => { reportIssue(gaugeVersionInfo); }));
context.subscriptions.push(vscode.commands.registerCommand(GaugeVSCodeCommands.Open, (node: GaugeNode) => {
return vscode.workspace.openTextDocument(node.file).then(document => {
if (node instanceof Scenario) {
let scenarioNode: Scenario = node
let options: TextDocumentShowOptions = {
selection: new Range(new Position(scenarioNode.lineNo-1, 0), new Position(scenarioNode.lineNo-1, 0))
selection: new Range(new Position(scenarioNode.lineNo - 1, 0), new Position(scenarioNode.lineNo - 1, 0))
}
return vscode.window.showTextDocument(document, options)
}
return vscode.window.showTextDocument(document);
});
}));
return vscode.window.showTextDocument(document);
});
}));

context.subscriptions.push(onConfigurationChange());
context.subscriptions.push(disposable);
Expand All @@ -94,10 +92,10 @@ export function activate(context: ExtensionContext) {
languageClient.onReady().then(
() => {
let specExplorerConfig = workspace.getConfiguration('gauge.specExplorer');
if(specExplorerConfig && specExplorerConfig.get<boolean>('enabled')){
if (specExplorerConfig && specExplorerConfig.get<boolean>('enabled')) {
let provider = new SpecNodeProvider(vscode.workspace.rootPath, languageClient);
let treeDataProvider = vscode.window.registerTreeDataProvider(GaugeCommandContext.GaugeSpecExplorer, provider);
context.subscriptions.push(vscode.commands.registerCommand(GaugeCommands.RefreshExplorer, () => provider.refresh()));
let treeDataProvider = vscode.window.registerTreeDataProvider(GaugeCommandContext.GaugeSpecExplorer, provider);
context.subscriptions.push(vscode.commands.registerCommand(GaugeVSCodeCommands.RefreshExplorer, () => provider.refresh()));
context.subscriptions.push(treeDataProvider);
setTimeout(setCommandContext, 1000, GaugeCommandContext.Activated, true);
}
Expand All @@ -107,24 +105,32 @@ export function activate(context: ExtensionContext) {

function registerStopExecution(context: ExtensionContext) {
let stopExecution = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 2);
stopExecution.command = GaugeCommands.StopExecution;
stopExecution.command = GaugeVSCodeCommands.StopExecution;
stopExecution.tooltip = 'Click to Stop Run';
context.subscriptions.push(stopExecution);
onBeforeExecute((s) => {
stopExecution.text = `$(primitive-square) Running ${s}`;
stopExecution.show();
});
onExecuted(() => stopExecution.hide());
context.subscriptions.push(vscode.commands.registerCommand(GaugeCommands.StopExecution, () => { cancel(); }));
context.subscriptions.push(vscode.commands.registerCommand(GaugeVSCodeCommands.StopExecution, () => { cancel(); }));
}

function notifyToInstallGauge(message: string) {
vscode.window.showWarningMessage(message, 'Install').then(selected => {
if (selected === 'Install') {
opn('https://getgauge.io/get-started.html');
}
});
}

function reportIssue(gaugeVersion: cp.SpawnSyncReturns<string>) {
function reportIssue(gaugeVersion: GaugeVersionInfo) {
let extVersion = extensions.getExtension("getgauge.gauge").packageJSON.version;
let issueTemplate = `\`\`\`
VS-Code version: ${vscode.version}
Gauge Extension Version: ${extVersion}
${gaugeVersion.stdout.toString()}
${gaugeVersion.toString()}
\`\`\``;

return opn(`https://github.com/getgauge/gauge-vscode/issues/new?body=${escape(issueTemplate)}`).then(() => { }, (err) => {
Expand Down Expand Up @@ -188,7 +194,7 @@ function notifyOnNewGaugeVsCodeVersion(context: ExtensionContext, latestVersion:
}

function showUpdateMessage(version: string) {
vscode.window.showInformationMessage("Gauge updated to version " + version, 'Show Release Notes','Do not show this again').then(selected => {
vscode.window.showInformationMessage("Gauge updated to version " + version, 'Show Release Notes', 'Do not show this again').then(selected => {
if (selected === 'Show Release Notes') {
opn('https://github.com/getgauge/gauge-vscode/releases/tag/v' + version);
}
Expand Down
42 changes: 42 additions & 0 deletions src/gaugeVersion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { spawnSync } from 'child_process';
import { GaugeCommands } from './commands';

export class GaugeVersionInfo {
public version: string;
public commitHash: string
public plugins: Array<Object>;

public constructor(v: string, commitHash: string, plugins: Array<Object>) {
this.version = v;
this.commitHash = commitHash;
this.plugins = plugins;
}

isGreaterOrEqual(version: string): boolean {
return this.version >= version;
}

getVersion(): string {
return this.version
}

toString(): string {
let v = `Gauge version: ${this.version}`;
let cm = this.commitHash && `Commit Hash: ${this.commitHash}` || '';
let plugins = this.plugins
.map((p: any) => p.name + ' (' + p.version + ')')
.join('\n');
plugins = `Plugins\n-------\n${plugins}`;
return `${v}\n${cm}\n\n${plugins}`;
}

}

export function getGaugeVersionInfo() {
let gv = spawnSync(GaugeCommands.Gauge, [GaugeCommands.Version, GaugeCommands.MachineReadable]);
if (gv.error) {
return null;
}
let m = JSON.parse(gv.stdout.toString());
return new GaugeVersionInfo(m.version, m.commitHash, m.plugins)
}
Loading

0 comments on commit 79574bb

Please sign in to comment.