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

Feature/sc 124023/get refactor #704

Merged
merged 5 commits into from
Dec 21, 2023
Merged
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
1 change: 1 addition & 0 deletions src/cli/logic-function.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ module.exports = ({ commandProcessor, root }) => {
});

commandProcessor.createCommand(logicFunction, 'get', 'Downloads the logic function', {
params: '[filepath]',
options: {
'org': {
description: 'Specify the organization',
Expand Down
43 changes: 24 additions & 19 deletions src/cmd/logic-function.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,25 +47,29 @@ module.exports = class LogicFunctionsCommand extends CLICommandBase {
// We assume at least one trigger
this.ui.stdout.write(`- ${item.name} (${item.enabled ? this.ui.chalk.cyanBright('enabled') : this.ui.chalk.cyan('disabled')})${os.EOL}`);
this.ui.stdout.write(` - ID: ${item.id}${os.EOL}`);
this.ui.stdout.write(` - ${item.logic_triggers[0].type} based trigger ${os.EOL}`);
this.ui.stdout.write(` - ${item.triggers[0].type} based trigger ${os.EOL}`);
});
this.ui.stdout.write(`${os.EOL}To view a Logic Function's code, see ${this.ui.chalk.yellow('particle logic-function get')}.${os.EOL}`);
}

async get({ org, name, id }) {
async get({ org, name, id, params : { filepath } } = { params: { } }) {
this._setOrg(org);
const logicFunctions = await LogicFunction.listFromCloud({ org, api: this.api });
if (!name && !id) {
name = await this._selectLogicFunctionName(logicFunctions);
}
const logicFunction = await LogicFunction.getByIdOrName({ org, id, name, list: logicFunctions });
logicFunction.path = filepath;

await this._getLogicFunctionList();

({ name, id } = await this._getLogicFunctionIdAndName(name, id));

const logicFunctionData = await this._getLogicFunctionData(id);

const { logicFunctionConfigData, logicFunctionCode } = this._serializeLogicFunction(logicFunctionData);

const { jsonPath, jsPath } = await this._generateFiles({ logicFunctionConfigData, logicFunctionCode, name });

this._printGetOutput({ jsonPath, jsPath });
// check if the files already exists
await this._confirmOverwriteIfNeeded({
filePaths: [logicFunction.configurationPath, logicFunction.sourcePath],
});
await logicFunction.saveToDisk();
this._printGetOutput({
jsonPath: logicFunction.configurationPath,
jsPath: logicFunction.sourcePath
});
this._printGetHelperOutput();
}

Expand Down Expand Up @@ -168,9 +172,9 @@ module.exports = class LogicFunctionsCommand extends CLICommandBase {

// Prompts the user to overwrite if any files exist
// If user says no, we exit the process
async _validatePaths({ jsonPath, jsPath, _exit = () => process.exit(0) }) {
async _confirmOverwriteIfNeeded({ filePaths, _exit = () => process.exit(0) }) {
let exists = false;
const pathsToCheck = [jsonPath, jsPath];
const pathsToCheck = filePaths;
for (const p of pathsToCheck) {
if (await fs.pathExists(p)) {
exists = true;
Expand Down Expand Up @@ -452,7 +456,7 @@ module.exports = class LogicFunctionsCommand extends CLICommandBase {
async _overwriteIfLFExistsLocally(name, id) {
const { jsonPath, jsPath } = this._getLocalLFPathNames(name);

const exist = await this._validatePaths({ jsonPath, jsPath });
const exist = await this._confirmOverwriteIfNeeded({ filePaths: { jsonPath, jsPath } });

if (!exist) {
return;
Expand Down Expand Up @@ -551,7 +555,7 @@ module.exports = class LogicFunctionsCommand extends CLICommandBase {
async _generateFiles({ logicFunctionConfigData, logicFunctionCode, name }) {
const { jsonPath, jsPath } = this._getLocalLFPathNames(name);

await this._validatePaths({ jsonPath, jsPath });
await this._confirmOverwriteIfNeeded({ filePaths: { jsonPath, jsPath } });

await fs.writeFile(jsonPath, JSON.stringify(logicFunctionConfigData, null, 2));
await fs.writeFile(jsPath, logicFunctionCode);
Expand All @@ -569,7 +573,7 @@ module.exports = class LogicFunctionsCommand extends CLICommandBase {

async _getLogicFunctionIdAndName(name, id) {
if (!id && !name) {
name = await this._selectLogicFunction(this.logicFuncList);
name = await this._selectLogicFunctionName(this.logicFuncList);
id = this._getIdFromName(name, this.logicFuncList);
} else if (!id && name) {
id = this._getIdFromName(name, this.logicFuncList);
Expand All @@ -580,8 +584,9 @@ module.exports = class LogicFunctionsCommand extends CLICommandBase {
return { name, id };
}

async _selectLogicFunction(list) {
async _selectLogicFunctionName(list) {
if (list.length === 0) {
this._printListHelperOutput();
throw new Error('No logic functions found');
}
const answer = await this._prompt({
Expand Down
93 changes: 86 additions & 7 deletions src/cmd/logic-function.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,14 @@ describe('LogicFunctionCommands', () => {
});

describe('list', () => {
beforeEach(() => {
logicFunc1.logic_functions.forEach((lf) => {
lf.triggers = lf.logic_triggers;
});
});

it('lists logic functions in Sandbox account', async () => {

const logicListStub = sinon.stub(LogicFunction, 'listFromCloud').resolves(logicFunc1.logic_functions);
await logicFunctionCommands.list({});
expect(logicListStub.calledWith({ api: logicFunctionCommands.api, org: undefined })).to.be.true;
Expand Down Expand Up @@ -95,6 +102,75 @@ describe('LogicFunctionCommands', () => {

});

describe('get', () => {
let lf;

beforeEach(() => {
lf = new LogicFunction({
name: 'LF1',
description: 'Logic Function 1',
id: '0021e8f4-64ee-416d-83f3-898aa909fb1b',
});
lf.fileNames = {
sourceCode: 'code.js',
configuration: 'config.json'
};
});

it('gets a logic function with an specific name from Sandbox account', async () => {
const logicGetStub = sinon.stub(LogicFunction, 'getByIdOrName').resolves(lf);
lf.saveToDisk = sinon.stub().resolves(true);
sinon.stub(LogicFunction, 'listFromCloud').resolves(logicFunc1.logic_functions);
await logicFunctionCommands.get({ name: 'LF1', params: {} });
expect(logicGetStub.calledWith({ org: undefined, id: undefined, name: 'LF1', list: logicFunc1.logic_functions })).to.be.true;
expect(logicGetStub.calledOnce).to.be.true;
expect(lf.saveToDisk.calledOnce).to.be.true;
expect(logicFunctionCommands.ui.stdout.write.callCount).to.equal(6);
expect(logicFunctionCommands.ui.stdout.write.getCall(2).args[0]).to.equal(` - ${lf.fileNames.configuration}${os.EOL}`);
expect(logicFunctionCommands.ui.stdout.write.getCall(3).args[0]).to.equal(` - ${lf.fileNames.sourceCode}${os.EOL}`);
});
it('gets a logic function with an specific id from Sandbox account', async () => {
const logicGetStub = sinon.stub(LogicFunction, 'getByIdOrName').resolves(lf);
lf.saveToDisk = sinon.stub().resolves(true);
sinon.stub(LogicFunction, 'listFromCloud').resolves(logicFunc1.logic_functions);
await logicFunctionCommands.get({ id: '0021e8f4-64ee-416d-83f3-898aa909fb1b', params: {} });
expect(logicGetStub.calledWith({ org: undefined, id: '0021e8f4-64ee-416d-83f3-898aa909fb1b', name: undefined, list: logicFunc1.logic_functions })).to.be.true;
expect(logicGetStub.calledOnce).to.be.true;
expect(lf.saveToDisk.calledOnce).to.be.true;
expect(logicFunctionCommands.ui.stdout.write.callCount).to.equal(6);
expect(logicFunctionCommands.ui.stdout.write.getCall(2).args[0]).to.equal(` - ${lf.fileNames.configuration}${os.EOL}`);
expect(logicFunctionCommands.ui.stdout.write.getCall(3).args[0]).to.equal(` - ${lf.fileNames.sourceCode}${os.EOL}`);

});
it('shows error if logic function is not found', async () => {
const logicGetStub = sinon.stub(LogicFunction, 'getByIdOrName').rejects(new Error('Logic function not found'));
lf.saveToDisk = sinon.stub().resolves(true);
sinon.stub(LogicFunction, 'listFromCloud').resolves(logicFunc1.logic_functions);
let error;
try {
await logicFunctionCommands.get({ name: 'LF3', params: {} });
} catch (e) {
error = e;
}
expect(logicGetStub.calledWith({ org: undefined, id: undefined, name: 'LF3', list: logicFunc1.logic_functions })).to.be.true;
expect(error).to.be.an.instanceOf(Error);
expect(error.message).to.equal('Logic function not found');
});

it('gets a logic function with an specific name from an org', async () => {
const logicGetStub = sinon.stub(LogicFunction, 'getByIdOrName').resolves(lf);
lf.saveToDisk = sinon.stub().resolves(true);
sinon.stub(LogicFunction, 'listFromCloud').resolves(logicFunc1.logic_functions);
await logicFunctionCommands.get({ name: 'LF1', org: 'particle', params: {} });
expect(logicGetStub.calledWith({ org: 'particle', id: undefined, name: 'LF1', list: logicFunc1.logic_functions })).to.be.true;
expect(logicGetStub.calledOnce).to.be.true;
expect(lf.saveToDisk.calledOnce).to.be.true;
expect(logicFunctionCommands.ui.stdout.write.callCount).to.equal(6);
expect(logicFunctionCommands.ui.stdout.write.getCall(2).args[0]).to.equal(` - ${lf.fileNames.configuration}${os.EOL}`);
expect(logicFunctionCommands.ui.stdout.write.getCall(3).args[0]).to.equal(` - ${lf.fileNames.sourceCode}${os.EOL}`);
});
});

describe('_getLogicFunctionList', () => {
it('lists logic functions in Sandbox', async () => {
nock('https://api.particle.io/v1', )
Expand Down Expand Up @@ -207,7 +283,7 @@ describe('LogicFunctionCommands', () => {
const data = { logic_function : logicFunc1.logic_functions[0] };
const logicFunctionCode = data.logic_function.source.code;
const logicFunctionConfigData = data.logic_function;
sinon.stub(logicFunctionCommands, '_validatePaths').resolves(true);
sinon.stub(logicFunctionCommands, '_confirmOverwriteIfNeeded').resolves(true);
const name = 'LF1';
const slugName = slugify(name);

Expand Down Expand Up @@ -376,7 +452,10 @@ describe('LogicFunctionCommands', () => {
it('returns if paths do not exist', async () => {
sinon.stub(fs, 'pathExists').resolves(false);

const res = await logicFunctionCommands._validatePaths({ jsonPath: 'dir/path/to/file', _exit: sinon.stub() });
const res = await logicFunctionCommands._confirmOverwriteIfNeeded({
filePaths: ['dir/path/to/file'],
_exit: sinon.stub()
});

expect(res).to.eql(false);

Expand All @@ -387,7 +466,7 @@ describe('LogicFunctionCommands', () => {
sinon.stub(fs, 'pathExists').resolves(true);
sinon.stub(logicFunctionCommands, '_promptOverwrite').resolves(false);

await logicFunctionCommands._validatePaths({ jsonPath: 'dir/path/to/file', _exit: exitStub });
await logicFunctionCommands._confirmOverwriteIfNeeded({ filePaths: ['dir/path/to/file'], _exit: exitStub });

expect(logicFunctionCommands._promptOverwrite.callCount).to.eql(1);
expect(exitStub.callCount).to.eql(1);
Expand All @@ -398,7 +477,7 @@ describe('LogicFunctionCommands', () => {
sinon.stub(logicFunctionCommands, '_promptOverwrite').resolves(true);
const paths = ['dir/', 'dir/path/to/file'];

const res = await logicFunctionCommands._validatePaths({ paths });
const res = await logicFunctionCommands._confirmOverwriteIfNeeded({ filePaths: paths });

expect(res).to.eql(true);

Expand Down Expand Up @@ -555,14 +634,14 @@ describe('LogicFunctionCommands', () => {

});

describe('_selectLogicFunction', () => {
describe('_selectLogicFunctionName', () => {
it('selects logic function from a list', async () => {
const logicFunctions = ['logicFunc1', 'logicFunc2'];
const selectedLF = 'logicFunc2';
const promptStub = sinon.stub(logicFunctionCommands, '_prompt');
promptStub.resolves({ logic_function: selectedLF });

const res = await logicFunctionCommands._selectLogicFunction(logicFunctions);
const res = await logicFunctionCommands._selectLogicFunctionName(logicFunctions);

expect(res).to.eql(selectedLF);
sinon.assert.calledOnceWithExactly(promptStub, {
Expand All @@ -579,7 +658,7 @@ describe('LogicFunctionCommands', () => {

let error;
try {
await logicFunctionCommands._selectLogicFunction(logicFunctions);
await logicFunctionCommands._selectLogicFunctionName(logicFunctions);
} catch (_e) {
error = _e;
}
Expand Down
Loading