forked from hyperledger-archives/composer
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add integration tests for transaction return types and commit flag (c…
…ontributes to #4165, #4224) (hyperledger-archives#4228) Signed-off-by: Simon Stone <[email protected]>
- Loading branch information
Simon Stone
authored
Jul 4, 2018
1 parent
4d73e16
commit b9edd1f
Showing
13 changed files
with
687 additions
and
145 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,50 +14,50 @@ | |
|
||
'use strict'; | ||
|
||
const Client = require('composer-client'); | ||
const Admin = require('composer-admin'); | ||
const Common = require('composer-common'); | ||
const BusinessNetworkConnection = Client.BusinessNetworkConnection; | ||
const BusinessNetworkDefinition = Admin.BusinessNetworkDefinition; | ||
const Serializer = Common.Serializer; | ||
const Resource = Common.Resource; | ||
|
||
const Submit = require('../../lib/cmds/transaction/submitCommand.js'); | ||
const { BusinessNetworkConnection } = require('composer-client'); | ||
const { BusinessNetworkDefinition } = require('composer-common'); | ||
const CmdUtil = require('../../lib/cmds/utils/cmdutils.js'); | ||
const Pretty = require('prettyjson'); | ||
const Submit = require('../../lib/cmds/transaction/submitCommand.js'); | ||
|
||
const chai = require('chai'); | ||
const sinon = require('sinon'); | ||
|
||
chai.should(); | ||
chai.use(require('chai-things')); | ||
chai.use(require('chai-as-promised')); | ||
const sinon = require('sinon'); | ||
|
||
const NAMESPACE = 'net.biz.TestNetwork'; | ||
const ENROLL_SECRET = 'SuccessKidWin'; | ||
|
||
|
||
|
||
describe('composer transaction submit CLI unit tests', () => { | ||
let sandbox; | ||
let mockBusinessNetworkConnection; | ||
let mockBusinessNetwork; | ||
let mockSerializer; | ||
let mockResource; | ||
let businessNetworkDefinition; | ||
let modelManager; | ||
let factory; | ||
let spyPretty; | ||
|
||
beforeEach(() => { | ||
sandbox = sinon.sandbox.create(); | ||
|
||
businessNetworkDefinition = new BusinessNetworkDefinition('[email protected]'); | ||
modelManager = businessNetworkDefinition.getModelManager(); | ||
modelManager.addModelFile(` | ||
namespace org.acme | ||
concept MyConcept { | ||
o String value | ||
} | ||
transaction MyTransaction { | ||
o Boolean success | ||
}`); | ||
factory = businessNetworkDefinition.getFactory(); | ||
|
||
mockBusinessNetworkConnection = sinon.createStubInstance(BusinessNetworkConnection); | ||
mockBusinessNetwork = sinon.createStubInstance(BusinessNetworkDefinition); | ||
mockSerializer = sinon.createStubInstance(Serializer); | ||
mockResource = sinon.createStubInstance(Resource); | ||
mockBusinessNetworkConnection.getBusinessNetwork.returns(mockBusinessNetwork); | ||
mockBusinessNetworkConnection.getBusinessNetwork.returns(businessNetworkDefinition); | ||
mockBusinessNetworkConnection.connect.resolves(); | ||
mockBusinessNetwork.getSerializer.returns(mockSerializer); | ||
mockSerializer.fromJSON.returns(mockResource); | ||
mockResource.getIdentifier.returns('SuccessKid'); | ||
|
||
sandbox.stub(CmdUtil, 'createBusinessNetworkConnection').returns(mockBusinessNetworkConnection); | ||
sandbox.stub(process, 'exit'); | ||
spyPretty = sandbox.spy(Pretty, 'render'); | ||
}); | ||
|
||
afterEach(() => { | ||
|
@@ -66,71 +66,124 @@ describe('composer transaction submit CLI unit tests', () => { | |
|
||
describe('#hander', () => { | ||
|
||
it('should not error when all requred params (card based) are specified', () => { | ||
it('should not error when all requred params (card based) are specified', async () => { | ||
sandbox.stub(CmdUtil, 'prompt').resolves(ENROLL_SECRET); | ||
|
||
let argv = { | ||
card: 'cardname', | ||
data: '{"$class": "org.acme.MyTransaction", "success": true}' | ||
}; | ||
|
||
await Submit.handler(argv); | ||
sinon.assert.calledWith(mockBusinessNetworkConnection.connect,'cardname'); | ||
}); | ||
|
||
it('should not error when the transaction returns a primitive value', async () => { | ||
mockBusinessNetworkConnection.submitTransaction.resolves('foobar'); | ||
sandbox.stub(CmdUtil, 'prompt').resolves(ENROLL_SECRET); | ||
|
||
let argv = { | ||
card: 'cardname', | ||
data: '{"$class": "org.acme.MyTransaction", "success": true}' | ||
}; | ||
|
||
await Submit.handler(argv); | ||
sinon.assert.calledWith(mockBusinessNetworkConnection.connect,'cardname'); | ||
sinon.assert.calledOnce(spyPretty); | ||
sinon.assert.calledWith(spyPretty, 'foobar'); | ||
}); | ||
|
||
it('should not error when the transaction returns an array of primitive values', async () => { | ||
mockBusinessNetworkConnection.submitTransaction.resolves(['foobar', 'doge', 'cat']); | ||
sandbox.stub(CmdUtil, 'prompt').resolves(ENROLL_SECRET); | ||
|
||
let argv = { | ||
card: 'cardname', | ||
data: '{"$class": "'+NAMESPACE+'", "success": true}' | ||
data: '{"$class": "org.acme.MyTransaction", "success": true}' | ||
}; | ||
|
||
return Submit.handler(argv) | ||
.then((res) => { | ||
sinon.assert.calledWith(mockBusinessNetworkConnection.connect,'cardname'); | ||
await Submit.handler(argv); | ||
sinon.assert.calledWith(mockBusinessNetworkConnection.connect,'cardname'); | ||
sinon.assert.calledOnce(spyPretty); | ||
sinon.assert.calledWith(spyPretty, ['foobar', 'doge', 'cat']); | ||
}); | ||
|
||
it('should not error when the transaction returns a concept value', async () => { | ||
const concept = factory.newConcept('org.acme', 'MyConcept'); | ||
concept.value = 'foobar'; | ||
mockBusinessNetworkConnection.submitTransaction.resolves(concept); | ||
sandbox.stub(CmdUtil, 'prompt').resolves(ENROLL_SECRET); | ||
|
||
let argv = { | ||
card: 'cardname', | ||
data: '{"$class": "org.acme.MyTransaction", "success": true}' | ||
}; | ||
|
||
}); | ||
await Submit.handler(argv); | ||
sinon.assert.calledWith(mockBusinessNetworkConnection.connect,'cardname'); | ||
sinon.assert.calledOnce(spyPretty); | ||
sinon.assert.calledWith(spyPretty, { $class: 'org.acme.MyConcept', value: 'foobar' }); | ||
}); | ||
|
||
it('should error when can not parse the json (card based)', () => { | ||
sandbox.stub(JSON, 'parse').throws(new Error('failure')); | ||
it('should not error when the transaction returns an array of concept values', async () => { | ||
const concept1 = factory.newConcept('org.acme', 'MyConcept'); | ||
concept1.value = 'foobar'; | ||
const concept2 = factory.newConcept('org.acme', 'MyConcept'); | ||
concept2.value = 'doge'; | ||
const concept3 = factory.newConcept('org.acme', 'MyConcept'); | ||
concept3.value = 'cat'; | ||
mockBusinessNetworkConnection.submitTransaction.resolves([concept1, concept2, concept3]); | ||
sandbox.stub(CmdUtil, 'prompt').resolves(ENROLL_SECRET); | ||
|
||
let argv = { | ||
card: 'cardname', | ||
data: '{"$class": "org.acme.MyTransaction", "success": true}' | ||
}; | ||
|
||
await Submit.handler(argv); | ||
sinon.assert.calledWith(mockBusinessNetworkConnection.connect,'cardname'); | ||
sinon.assert.calledOnce(spyPretty); | ||
sinon.assert.calledWith(spyPretty, [{ $class: 'org.acme.MyConcept', value: 'foobar' }, { $class: 'org.acme.MyConcept', value: 'doge' }, { $class: 'org.acme.MyConcept', value: 'cat' }]); | ||
}); | ||
|
||
it('should error when can not parse the json (card based)', async () => { | ||
let argv = { | ||
card: 'cardname', | ||
data: '{"$class": "'+NAMESPACE+'", "success": true}' | ||
data: '{"$class": "org.acme.MyTransaction", "success": true' | ||
}; | ||
|
||
return Submit.handler(argv).should.be.rejectedWith(/JSON error/); | ||
await Submit.handler(argv).should.be.rejectedWith(/JSON error/); | ||
}); | ||
|
||
it('should error when the transaction fails to submit', () => { | ||
it('should error when the transaction fails to submit', async () => { | ||
let argv = { | ||
card: 'cardname', | ||
data: '{"$class": "'+NAMESPACE+'", "success": true}' | ||
data: '{"$class": "org.acme.MyTransaction", "success": true}' | ||
}; | ||
|
||
mockBusinessNetworkConnection.submitTransaction.rejects(new Error('some error')); | ||
return Submit.handler(argv) | ||
.then((res) => { | ||
// sinon.assert.calledWith(process.exit, 1); | ||
}).catch((error) => { | ||
error.toString().should.equal('Error: some error'); | ||
}); | ||
await Submit.handler(argv) | ||
.should.be.rejectedWith(/some error/); | ||
}); | ||
|
||
it('should error if data is not a string', () => { | ||
it('should error if data is not a string', async () => { | ||
let argv = { | ||
card: 'cardname', | ||
data: {} | ||
}; | ||
|
||
return Submit.handler(argv) | ||
.then((res) => { | ||
}).catch((error) => { | ||
error.toString().should.equal('Error: Data must be a string'); | ||
}); | ||
await Submit.handler(argv) | ||
.should.be.rejectedWith(/Data must be a string/); | ||
}); | ||
|
||
it('should error if data class is not supplied', () => { | ||
it('should error if data class is not supplied', async () => { | ||
let argv = { | ||
card: 'cardname', | ||
data: '{"success": true}' | ||
}; | ||
|
||
return Submit.handler(argv) | ||
.then((res) => { | ||
}).catch((error) => { | ||
error.toString().should.equal('Error: $class attribute not supplied'); | ||
}); | ||
await Submit.handler(argv) | ||
.should.be.rejectedWith(/\$class attribute not supplied/); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.