Skip to content

Commit

Permalink
add product device remove command
Browse files Browse the repository at this point in the history
  • Loading branch information
busticated committed Aug 1, 2020
1 parent dc65a31 commit e396c9f
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 12 deletions.
10 changes: 10 additions & 0 deletions src/cli/product.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,15 @@ module.exports = ({ commandProcessor, root }) => {
}
});

commandProcessor.createCommand(device, 'remove', 'Removes a device from a Product', {
params: '<product> <deviceID>',
examples: {
'$0 $command 12345 0123456789abcdef01234567': 'Remove device id `0123456789abcdef01234567` from product `12345`',
},
handler: (args) => {
const ProdCmd = require('../cmd/product');
return new ProdCmd(args).removeDevice(args);
}
});
return product;
};
5 changes: 3 additions & 2 deletions src/cli/product.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ describe('Product Command-Line Interface', () => {
'Help: particle help product device <command>',
'',
'Commands:',
' list List all devices that are part of a product',
' add Adds one or more devices into a Product',
' list List all devices that are part of a product',
' add Adds one or more devices into a Product',
' remove Removes a device from a Product',
''
].join(os.EOL));
});
Expand Down
21 changes: 21 additions & 0 deletions src/cmd/product.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,27 @@ module.exports = class ProductCommand extends CLICommandBase {
return this.ui.write(message.join(os.EOL));
}

removeDevice({ params: { product, deviceID } }){
if (!this.isDeviceId(deviceID)){
return this.showUsageError(`\`deviceID\` parameter must be an id - received: ${deviceID}`);
}

const msg = `Removing device ${deviceID} from product ${product}`;
const remove = createAPI()
.removeDevice(deviceID, product)
.catch(error => {
const message = 'Error removing device from product';
throw createAPIErrorResult({ error, message, json: false });
});

return this.ui.showBusySpinnerUntilResolved(msg, remove)
.then(() => this.showDeviceRemoveResult({ product, deviceID }));
}

showDeviceRemoveResult({ product, deviceID }){
return this.ui.write(`Success! Removed device ${deviceID} from product ${product}${os.EOL}`);
}

showDeviceDetail({ json, params: { product, device } }){
const msg = `Fetching device ${device} detail`;
const fetchData = createAPI().getDeviceAttributes(device, product);
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/help.e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ describe('Help & Unknown Command / Argument Handling', () => {
'library', 'list', 'login', 'logout', 'mesh create', 'mesh add',
'mesh remove', 'mesh list', 'mesh info', 'mesh scan', 'mesh', 'monitor',
'nyan', 'preprocess', 'product device list', 'product device add',
'product device', 'product', 'project create', 'project', 'publish',
'serial list', 'serial monitor', 'serial identify', 'serial wifi',
'product device remove', 'product device', 'product', 'project create',
'project', 'publish', 'serial list', 'serial monitor', 'serial identify', 'serial wifi',
'serial mac', 'serial inspect', 'serial flash', 'serial claim',
'serial', 'setup', 'subscribe', 'token list', 'token revoke',
'token create', 'token', 'udp send', 'udp listen', 'udp', 'update',
Expand Down
83 changes: 75 additions & 8 deletions test/e2e/product.e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,14 @@ describe('Product Commands', () => {
// TODO (mirande): sometimes entity includes: `pinned_build_target`
const detailedDeviceFieldNames = ['cellular', 'connected',
'current_build_target', 'default_build_target', 'denied',
'desired_firmware_version', 'development', 'firmware_product_id',
'firmware_updates_enabled', 'firmware_updates_forced',
'firmware_version', 'functions', 'groups', 'iccid', 'id', 'imei',
'last_handshake_at', 'last_heard', 'last_iccid', 'last_ip_address',
'mobile_secret', 'name', 'notes', 'online', 'owner',
'pinned_build_target', 'platform_id', 'product_id', 'quarantined',
'serial_number', 'status', 'system_firmware_version',
'targeted_firmware_release_version', 'variables'];
'development', 'firmware_product_id', 'firmware_updates_enabled',
'firmware_updates_forced', 'firmware_version', 'functions', 'groups',
'iccid', 'id', 'imei', 'last_handshake_at', 'last_heard',
'last_iccid', 'last_ip_address', 'mobile_secret', 'name', 'notes',
'online', 'owner', 'pinned_build_target', 'platform_id',
'product_id', 'quarantined', 'serial_number', 'status',
'system_firmware_version', 'targeted_firmware_release_version',
'variables'];

it('Lists devices', async () => {
const args = ['product', 'device', 'list', PRODUCT_01_ID];
Expand Down Expand Up @@ -440,6 +440,73 @@ describe('Product Commands', () => {
});
});

describe('Device Remove Subcommand', () => {
const help = [
'Removes a device from a Product',
'Usage: particle product device remove [options] <product> <deviceID>',
'',
'Global Options:',
' -v, --verbose Increases how much logging to display [count]',
' -q, --quiet Decreases how much logging to display [count]',
'',
'Examples:',
' particle product device remove 12345 0123456789abcdef01234567 Remove device id `0123456789abcdef01234567` from product `12345`'
];

before(async () => {
await cli.setTestProfileAndLogin();
});

after(async () => {
await cli.run(['product', 'device', 'add', PRODUCT_01_ID, PRODUCT_01_DEVICE_01_ID]);
});

it('Removes a device', async () => {
const args = ['product', 'device', 'remove', PRODUCT_01_ID, PRODUCT_01_DEVICE_01_ID];
const { stdout, stderr, exitCode } = await cli.run(args);

expect(stdout).to.include(`Success! Removed device ${PRODUCT_01_DEVICE_01_ID} from product ${PRODUCT_01_ID}${os.EOL}`);
expect(stderr).to.equal('');
expect(exitCode).to.equal(0);
});

it('Fails to remove a device when `deviceID` param is not provided', async () => {
const args = ['product', 'device', 'remove', PRODUCT_01_ID];
const { stdout, stderr, exitCode } = await cli.run(args);

expect(stdout).to.include('Parameter \'deviceID\' is required.');
expect(stderr.split(os.EOL)).to.include.members(help);
expect(exitCode).to.equal(1);
});

it('Fails to remove a device when `deviceID` param is not an id', async () => {
const args = ['product', 'device', 'remove', PRODUCT_01_ID, PRODUCT_01_DEVICE_01_NAME];
const { stdout, stderr, exitCode } = await cli.run(args);

expect(stdout).to.include(`\`deviceID\` parameter must be an id - received: ${PRODUCT_01_DEVICE_01_NAME}`);
expect(stderr.split(os.EOL)).to.include.members(help);
expect(exitCode).to.equal(1);
});

it('Fails to remove a device when `product` is unknown', async () => {
const args = ['product', 'device', 'remove', 'LOLWUTNOPE', PRODUCT_01_DEVICE_01_ID];
const { stdout, stderr, exitCode } = await cli.run(args);

expect(stdout).to.include('HTTP error 404');
expect(stderr).to.equal('');
expect(exitCode).to.equal(1);
});

it('Fails to remove a device when `device` is unknown', async () => {
const args = ['product', 'device', 'remove', PRODUCT_01_ID, '000000000000000000000001'];
const { stdout, stderr, exitCode } = await cli.run(args);

expect(stdout).to.include('Error removing device from product: Device not found for this product');
expect(stderr).to.equal('');
expect(exitCode).to.equal(1);
});
});

function parseAndSortDeviceList(stdout){
const json = JSON.parse(stdout);

Expand Down

0 comments on commit e396c9f

Please sign in to comment.