Skip to content

Commit

Permalink
Add 'composer card delete' command (hyperledger-archives#2410)
Browse files Browse the repository at this point in the history
Signed-off-by: Mark S. Lewis <[email protected]>
  • Loading branch information
bestbeforetoday authored Oct 19, 2017
1 parent 9b2a3c4 commit 3b51118
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 4 deletions.
10 changes: 10 additions & 0 deletions packages/composer-admin/lib/adminconnection.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,16 @@ class AdminConnection {
return this.cardStore.getAll();
}

/**
* Delete an existing card.
* @private
* @param {String} name Name of the card to delete.
* @returns {Promise} Resolves if an existing card was deleted; rejected otherwise.
*/
deleteCard(name) {
return this.cardStore.delete(name);
}

/**
* Deletes the specified connection profile from the profile store being used by this
* AdminConnection.
Expand Down
28 changes: 24 additions & 4 deletions packages/composer-admin/test/adminconnection.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ class StubCardStore extends BusinessNetworkCardStore {
*/
delete(cardName) {
return Promise.resolve().then(() => {
this.cards.delete(cardName);
if (!this.cards.delete(cardName)) {
throw new Error('Card not found: ' + cardName);
}
});
}

Expand Down Expand Up @@ -934,12 +936,12 @@ describe('AdminConnection', () => {
});
});

describe('#getAllCards', () => {
it('should return empty map when card store contains no cards', () => {
describe('#getAllCards', function() {
it('should return empty map when card store contains no cards', function() {
return adminConnection.getAllCards().should.eventually.be.instanceOf(Map).that.is.empty;
});

it('should return map of cards when card store is not empty', () => {
it('should return map of cards when card store is not empty', function() {
const cardName = 'conga-card';
return cardStore.put(cardName, peerAdminCard).then(() => {
return adminConnection.getAllCards();
Expand All @@ -950,6 +952,24 @@ describe('AdminConnection', () => {
});
});
});

describe('#deleteCard', function() {
it('should reject for non-existent card', function() {
const cardName = 'conga-card';
return adminConnection.deleteCard(cardName).should.be.rejectedWith(cardName);
});

it('should succeed for an existing card', function() {
const cardName = 'conga-card';
return cardStore.put(cardName, peerAdminCard).then(() => {
return adminConnection.deleteCard(cardName);
}).then(() => {
return cardStore.getAll();
}).then(cardMap => {
cardMap.size.should.equal(0);
});
});
});
});

});
27 changes: 27 additions & 0 deletions packages/composer-cli/lib/cmds/card/deleteCommand.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

const Delete = require ('./lib/delete.js');

module.exports.command = 'delete [options]';
module.exports.describe = 'Delete a business network card';
module.exports.builder = {
name: { alias: 'n', required: true, describe: 'The name of the card to delete', type: 'string' }
};

module.exports.handler = (argv) => {
return argv.thePromise = Delete.handler(argv);
};
37 changes: 37 additions & 0 deletions packages/composer-cli/lib/cmds/card/lib/delete.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

const cmdUtil = require('../../utils/cmdutils');

/**
* Composer "card delete" command
* @private
*/
class Delete {
/**
* Command implementation.
* @param {Object} args argument list from composer command
* @return {Promise} promise when command complete
*/
static handler(args) {
return cmdUtil.createAdminConnection().deleteCard(args.name).then(() => {
console.log('Deleted Business Network Card: ' + args.name);
});
}

}

module.exports = Delete;
67 changes: 67 additions & 0 deletions packages/composer-cli/test/card/delete.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

const AdminConnection = require('composer-admin').AdminConnection;
const CmdUtil = require('../../lib/cmds/utils/cmdutils.js');
const DeleteCmd = require('../../lib/cmds/card/deleteCommand.js');

const chai = require('chai');
const sinon = require('sinon');
chai.should();
chai.use(require('chai-as-promised'));

describe('composer card delete CLI', function() {
const sandbox = sinon.sandbox.create();
let adminConnectionStub;
let consoleLogSpy;

beforeEach(function() {
adminConnectionStub = sinon.createStubInstance(AdminConnection);
sandbox.stub(CmdUtil, 'createAdminConnection').returns(adminConnectionStub);
consoleLogSpy = sandbox.spy(console, 'log');
sandbox.stub(process, 'exit');
});

afterEach(function() {
sandbox.restore();
});

it('should delete existing card', function() {
adminConnectionStub.deleteCard.resolves();
const cardName = 'CARD_NAME';
const args = { name: cardName };
return DeleteCmd.handler(args).then(() => {
sinon.assert.calledOnce(adminConnectionStub.deleteCard);
sinon.assert.calledWith(adminConnectionStub.deleteCard, cardName);
sinon.assert.calledWith(consoleLogSpy, sinon.match(cardName));
});
});

it('should fail deleting non-existent card', function() {
const errorText = 'ERROR_MESSAGE';
adminConnectionStub.deleteCard.rejects(new Error(errorText));
const cardName = 'CARD_NAME';
const args = { name: cardName };
return DeleteCmd.handler(args).then((result) => {
sinon.assert.fail('Expected command to fail but it succeeded');
}, (error) => {
sinon.assert.calledOnce(adminConnectionStub.deleteCard);
sinon.assert.calledWith(adminConnectionStub.deleteCard, cardName);
error.toString().should.include(errorText);
});
});

});

0 comments on commit 3b51118

Please sign in to comment.