Skip to content

Commit

Permalink
Merge pull request #763 from particle-iot/feature/device-protection-d…
Browse files Browse the repository at this point in the history
…evice-selector

Add option to filter device with `particle device-protection` commands
  • Loading branch information
keeramis authored Aug 28, 2024
2 parents fb91a2c + ee13660 commit f0703f2
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 8 deletions.
25 changes: 20 additions & 5 deletions src/cli/device-protection.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,31 @@ module.exports = ({ commandProcessor, root }) => {
const deviceProtection = commandProcessor.createCategory(root, 'device-protection', 'Manage Device Protection');

commandProcessor.createCommand(deviceProtection, 'status', 'Gets the current Device Protection status', {
handler: () => {
options: {
device: {
description: 'Device ID or name',
alias: 'd'
}
},
handler: (args) => {
const DeviceProtectionCommands = require('../cmd/device-protection');
return new DeviceProtectionCommands().getStatus();
return new DeviceProtectionCommands().getStatus(args);
},
examples: {
'$0 $command': 'Gets the current Device Protection status'
}
});

commandProcessor.createCommand(deviceProtection, 'disable', 'Disables Device Protection', {

handler: () => {
options: {
d: {
description: 'Device ID or name',
alias: 'device'
}
},
handler: (args) => {
const DeviceProtectionCommands = require('../cmd/device-protection');
return new DeviceProtectionCommands().disableProtection();
return new DeviceProtectionCommands().disableProtection(args);
},
examples: {
'$0 $command': 'Puts a Protected Device to Service Mode',
Expand All @@ -27,6 +38,10 @@ module.exports = ({ commandProcessor, root }) => {
options: {
file: {
description: 'File to use for Device Protection'
},
d: {
description: 'Device ID or name',
alias: 'device'
}
},
handler: (args) => {
Expand Down
153 changes: 153 additions & 0 deletions src/cli/device-protection.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
const { expect } = require('../../test/setup');
const commandProcessor = require('../app/command-processor');
const deviceProtection = require('./device-protection');

describe('Device Protection Command-Line Interface', () => {
let root;

beforeEach(() => {
root = commandProcessor.createAppCategory();
deviceProtection({ root, commandProcessor });
});

describe('`Device Protection` Namespace', () => {
it('Handles `device-protection` command', () => {
const argv = commandProcessor.parse(root, ['device-protection']);
expect(argv.clierror).to.equal(undefined);
expect(argv.params).to.equal(undefined);
});

it('Includes help', () => {
const termWidth = null; // don't right-align option type labels so testing is easier
commandProcessor.parse(root, ['device-protection', '--help'], termWidth);
commandProcessor.showHelp((helpText) => {
expect(helpText).to.equal([
'Manage Device Protection',
'Usage: particle device-protection <command>',
'Help: particle help device-protection <command>',
'',
'Commands:',
' status Gets the current Device Protection status',
' disable Disables Device Protection',
' enable Enables Device Protection',
''
].join('\n'));
});
});

describe('`device-protection status` command', () => {
it('Handles `status` command', () => {
const argv = commandProcessor.parse(root, ['device-protection', 'status']);
expect(argv.clierror).to.equal(undefined);
expect(argv.params).to.eql({});
});

it('Handles `status` command with a device', () => {
const argv = commandProcessor.parse(root, ['device-protection', 'status', '--device', '0123456789abcdef']);
expect(argv.clierror).to.equal(undefined);
expect(argv.device).to.eql('0123456789abcdef');
});

it('Includes help', () => {
const termWidth = null; // don't right-align option type labels so testing is easier
commandProcessor.parse(root, ['device-protection', 'status', '--help'], termWidth);
commandProcessor.showHelp((helpText) => {
expect(helpText).to.equal([
'Gets the current Device Protection status',
'Usage: particle device-protection status [options]',
'',
'Options:',
' --device, -d Device ID or name [string]',
'',
'Examples:',
' particle device-protection status Gets the current Device Protection status',
''
].join('\n'));
});
});
});

describe('`device-protection disable` command', () => {
it('Handles `disable` command', () => {
const argv = commandProcessor.parse(root, ['device-protection', 'disable']);
expect(argv.clierror).to.equal(undefined);
expect(argv.device).to.eql(undefined);
});

it('Handles `disable` command with a device', () => {
const argv = commandProcessor.parse(root, ['device-protection', 'disable', '-d', '0123456789abcdef']);
expect(argv.clierror).to.equal(undefined);
expect(argv.device).to.eql('0123456789abcdef');
});

it('Includes help', () => {
const termWidth = null; // don't right-align option type labels so testing is easier
commandProcessor.parse(root, ['device-protection', 'disable', '--help'], termWidth);
commandProcessor.showHelp((helpText) => {
expect(helpText).to.equal([
'Disables Device Protection',
'Usage: particle device-protection disable [options]',
'',
'Options:',
' -d, --device Device ID or name [string]',
'',
'Examples:',
' particle device-protection disable Puts a Protected Device to Service Mode',
'',
'A Protected Device in Service Mode allows any command to be performed on it that can be performed on an Open Device like flashing firmware or serial monitor.',
''
].join('\n'));
});
});
});

describe('`device-protection enable` command', () => {
it('Handles `enable` command', () => {
const argv = commandProcessor.parse(root, ['device-protection', 'enable']);
expect(argv.clierror).to.equal(undefined);
expect(argv.device).to.eql(undefined);
});

it('Handles `enable` command with a device', () => {
const argv = commandProcessor.parse(root, ['device-protection', 'enable', '-d', '0123456789abcdef']);
expect(argv.clierror).to.equal(undefined);
expect(argv.device).to.eql('0123456789abcdef');
expect(argv.file).to.eql(undefined);
});

it('Handles `enable` command with a filename', () => {
const argv = commandProcessor.parse(root, ['device-protection', 'enable', '--file', 'file.txt']);
expect(argv.clierror).to.equal(undefined);
expect(argv.device).to.eql(undefined);
expect(argv.file).to.eql('file.txt');
});

it('Handles `enable` command with a device and a filename', () => {
const argv = commandProcessor.parse(root, ['device-protection', 'enable', '-d', '0123456789abcdef', '--file', 'file.txt']);
expect(argv.clierror).to.equal(undefined);
expect(argv.device).to.eql('0123456789abcdef');
expect(argv.file).to.eql('file.txt');
});

it('Includes help', () => {
const termWidth = null; // don't right-align option type labels so testing is easier
commandProcessor.parse(root, ['device-protection', 'enable', '--help'], termWidth);
commandProcessor.showHelp((helpText) => {
expect(helpText).to.equal([
'Enables Device Protection',
'Usage: particle device-protection enable [options]',
'',
'Options:',
' --file File to use for Device Protection [string]',
' -d, --device Device ID or name [string]',
'',
'Examples:',
' particle device-protection enable Turns an Open Device into a Protected Device',
''
].join('\n'));
});
});
});
});
});

9 changes: 6 additions & 3 deletions src/cmd/device-protection.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ module.exports = class DeviceProtectionCommands extends CLICommandBase {
* @returns {Promise<Object>} The protection state of the device.
* @throws {Error} Throws an error if any of the async operations fail.
*/
async getStatus() {
async getStatus({ device } = {}) {
this.deviceId = device;
let addToOutput = [];
let s;
try {
Expand Down Expand Up @@ -87,7 +88,8 @@ module.exports = class DeviceProtectionCommands extends CLICommandBase {
* @returns {Promise<void>}
* @throws {Error} - Throws an error if any of the async operations fail.
*/
async disableProtection() {
async disableProtection({ device } = {}) {
this.deviceId = device;
let addToOutput = [];
try {
await this._withDevice({ spinner: 'Disabling Device Protection' }, async () => {
Expand Down Expand Up @@ -132,7 +134,8 @@ module.exports = class DeviceProtectionCommands extends CLICommandBase {
* @returns {Promise<void>}
* @throws {Error} Throws an error if any of the asynchronous operations fail.
*/
async enableProtection({ file } = {}) {
async enableProtection({ file, device } = {}) {
this.deviceId = device;
let addToOutput = [];
try {
await this._withDevice({ spinner: 'Enabling Device Protection' }, async () => {
Expand Down

0 comments on commit f0703f2

Please sign in to comment.