Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bruin CLI commands #1

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 136 additions & 3 deletions extension.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,154 @@
// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
const child_process = require('child_process');
const vscode = require('vscode');

// This method is called when your extension is activated
// Your extension is activated the very first time the command is executed

const BRUIN_WHICH_COMMAND = "which bruin"
const BRUIN_HELP_COMMAND_ID = "bruin.help"
const BRUIN_HELP_COMMAND = "bruin --help"
const BRUIN_RENDER_COMMAND = "bruin render"
const BRUIN_RENDER_COMMAND_ID = "bruin.renderSql"

/**
* @param {vscode.ExtensionContext} context
*/
function activate(context) {
//
if (checkBruinBinary()) {
vscode.window.showErrorMessage('Bruin executable not found');
return;
}

let panel = undefined;

let bruinHelpDisposable = vscode.commands.registerCommand(BRUIN_HELP_COMMAND_ID, async () => {

if (isEditorActive() && isFileExtensionSQL()) {
const outputCommand = await commandExcution(BRUIN_HELP_COMMAND);
vscode.window.showInformationMessage(outputCommand.stdout);
vscode.window.showErrorMessage(outputCommand.stderr)
} else {
vscode.window.showErrorMessage('Please trigger Bruin for SQL files');
}
})

let bruinRenderDisposable = vscode.commands.registerCommand(BRUIN_RENDER_COMMAND_ID, async () => {
const columnToShowIn = vscode.window.activeTextEditor
? vscode.ViewColumn.Beside
: undefined;

if (isEditorActive() && isFileExtensionSQL()) {
const sqlAssetPath = vscode.window.activeTextEditor.document.fileName;
const outputCommand = await commandExcution(`${BRUIN_RENDER_COMMAND} ${sqlAssetPath}`);

if (panel) {
panel.reveal(columnToShowIn || vscode.window.activeTextEditor.viewColumn)
}
else {
panel = vscode.window.createWebviewPanel(
'bruin', // Identifies the type of the webview. Used internally
'Render single SQL assset', // Title of the panel displayed to the user
columnToShowIn || vscode.window.activeTextEditor.viewColumn, // Editor column to show the new webview panel in.
{} // Webview options. More on these later.
);

panel.onDidDispose(
() => {
panel = undefined;
},
null,
context.subscriptions
);
}
panel.webview.html = getWebviewContent(outputCommand.stdout, sqlAssetPath);

vscode.window.showErrorMessage(outputCommand.stderr)
} else {
vscode.window.showErrorMessage('Please trigger Bruin for SQL files');
}
});

context.subscriptions.push(bruinHelpDisposable);
context.subscriptions.push(bruinRenderDisposable);
console.log("Bruin extension successfully activated")
}

// This method is called when your extension is deactivated
function deactivate() {}
function deactivate() {
// Left empty intentionally
}

function isEditorActive() {
return vscode.window.activeTextEditor
}

function isFileExtensionSQL() {
let fileName = vscode.window.activeTextEditor.document.fileName.toLocaleLowerCase();
let fileExtension = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length)
if (fileExtension === 'sql') return true
}
function commandExcution(cliCommand) {
return new Promise((resolve) => {
child_process.exec(cliCommand, (error, stdout) => {
if (error) {
return resolve({ stderr: error.message });
}
return resolve({ stdout });
});
})
}

function getWebviewContent(renderedSql, filePath) {
return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Render SQL File</title>
<style>
pre {
border: solid 1px;
padding: 10px;
}
.sql-header {
text-align: center;
font-weight: bold;
margin-top: 20px;
margin-bottom: 10px;
}
</style>
</head>
<body>
<pre class="sql-header">SQL File: ${filePath}</pre>
<pre>${renderedSql}</pre>
</body>
</html>`;
}

/**
* Checks if the Bruin executable is available.
* @returns {Boolean}
*/
function checkBruinBinary() {
try {
let output = child_process.execSync(BRUIN_WHICH_COMMAND);
if (!output) {
throw new Error("Bruin does not exists")
}
} catch (error) {
console.error(error);
return true;
}
return false;
}

module.exports = {
activate,
deactivate
deactivate,
commandExcution,
checkBruinBinary,
getWebviewContent
}

41 changes: 37 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"vscode": "^1.83.0"
},
"categories": [
"Data Science", "Formatters"
"Data Science",
"Formatters"
],
"icon": "images/bruin-logo-sm128.png",
"activationEvents": [],
Expand All @@ -26,6 +27,35 @@
"source.sql"
]
}
],
"menus": {
"editor/title": [
{
"command": "bruin.help",
"when": "resourceExtname == .sql",
"group": "navigation"
},
{
"command": "bruin.renderSql",
"when": "resourceExtname == .sql",
"group": "navigation"
}
]
},
"commands": [
{
"command": "bruin.help",
"title": "Help",
"category": "Bruin",
"icon":"$(lightbulb)"
},
{
"command": "bruin.renderSql",
"title": "Render single SQL asset",
"shortTitle": "Render SQL",
"category": "Bruin",
"icon":"$(rocket)"
}
]
},
"scripts": {
Expand All @@ -34,13 +64,16 @@
"test": "node ./test/runTest.js"
},
"devDependencies": {
"@types/vscode": "^1.83.0",
"@types/mocha": "^10.0.2",
"@types/node": "18.x",
"@types/vscode": "^1.83.0",
"@vscode/test-electron": "^2.3.4",
"eslint": "^8.50.0",
"glob": "^10.3.3",
"mocha": "^10.2.0",
"typescript": "^5.2.2",
"@vscode/test-electron": "^2.3.4"
"typescript": "^5.2.2"
},
"dependencies": {
"bruin": "^0.1.4"
}
}
53 changes: 48 additions & 5 deletions test/suite/extension.test.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,58 @@
const assert = require('assert');
const child_process = require('child_process');

// You can import and use all API from the 'vscode' module
// as well as import your extension to test it
const vscode = require('vscode');
// const myExtension = require('../extension');
const bruinExtension = require('../../extension');

suite('Extension Test Suite', () => {
suite('Bruin Test Suite', () => {
vscode.window.showInformationMessage('Start all tests.');

test('Sample test', () => {
assert.strictEqual(-1, [1, 2, 3].indexOf(5));
assert.strictEqual(-1, [1, 2, 3].indexOf(0));
test('should return an object with stdout property', async () => {
const outputCommand = await bruinExtension.commandExcution('bruin --help');
assert.ok(outputCommand.hasOwnProperty('stdout'));
});

test('should return an object with stdout containing the output of the bruin --help command', async () => {
const expectedOutput = `bruin - The CLI used for managing Bruin-powered data pipelines`;
const outputCommand = await bruinExtension.commandExcution('bruin --help');
assert.ok(outputCommand.stdout.includes(expectedOutput));
});

test('should return an error message if the command fails', async () => {
const errorCommand = await bruinExtension.commandExcution('bruin render null');
assert.ok(errorCommand.stderr.includes("Command failed"));
});

test('should return an error message if the command does not exist', async () => {
const errorCommand = await bruinExtension.commandExcution('command-not-found');
assert.ok(errorCommand.stderr.includes("command not found"));
});

test('should generate correct HTML content for webview', () => {
const renderedSql = 'SELECT 1 as one;';
const filePath = '/path/to/file.sql';
const htmlContent = bruinExtension.getWebviewContent(renderedSql, filePath);

assert.ok(htmlContent.includes('<pre class="sql-header">SQL File: /path/to/file.sql</pre>'));
assert.ok(htmlContent.includes(`<pre>${renderedSql}</pre>`));
});


test('should return an error message if Bruin binary does not exist', () => {
// Mock the child_process.execSync to simulate the absence of Bruin binary
const originalExecSync = child_process.execSync;
child_process.execSync = () => { throw new Error('Bruin does not exists'); };

const bruinNotInPath = bruinExtension.checkBruinBinary();

// Restore the original function after the test
child_process.execSync = originalExecSync;

assert.strictEqual(bruinNotInPath, true);
});



});