With the implementation of cards in v0.15, previous versions of test routines which used profiles (obviously) won't work. However, I cannot find an SDK approach to create the necessary cards to run tests. The 'before' section of code up through v0.14 for my tests has looked like the following, which uses an embedded profile, creates a temporary instance of the network and runs the tests:
describe('Finance Network', () => {
// let adminConnection;
let businessNetworkConnection;
before(() => {
BrowserFS.initialize(new BrowserFS.FileSystem.InMemory());
const adminConnection = new AdminConnection({ fs: bfs_fs });
return adminConnection.createProfile('defaultProfile', {
type: 'embedded'
})
.then(() => {
return adminConnection.connect('defaultProfile', adminID, adminPW);
})
.then(() => {
return BusinessNetworkDefinition.fromDirectory(path.resolve(__dirname, '..'));
})
.then((businessNetworkDefinition) => {
return adminConnection.deploy(businessNetworkDefinition);
})
.then(() => {
businessNetworkConnection = new BusinessNetworkConnection({ fs: bfs_fs });
return businessNetworkConnection.connect('defaultProfile', network, adminID, adminPW);
});
});
What I'm trying to find (and haven't yet) in the nodejs documentation is how to create the necessary cards to make this work, while using this same approach.
I expect to replace the following lines of code with something that creates the necessary cards:
return adminConnection.createProfile('defaultProfile', {
type: 'embedded'
})
.then(() => {
return adminConnection.connect('defaultProfile', adminID, adminPW);
})
The only place where I see card creation is in composer-client Participant Registry, but it's a Catch-22 situation where I have to be connected to create the card, but I need a card to get connected. What is the recommended approach for writing mocha-based testing as we have been doing for the past umpteen releases of Hyperledger-Composer?
Thanks!
I guess subject to some refinement as the card-based API is established, but you should be looking at something like this using only the API:
// Embedded connection used for local testing
const connectionProfile = {
name: 'embedded',
type: 'embedded'
};
// Embedded connection does not need real credentials
const credentials = {
certificate: 'FAKE CERTIFICATE',
privateKey: 'FAKE PRIVATE KEY'
};
// PeerAdmin identity used with the admin connection to deploy business networks
const deployerMetadata = {
version: 1,
userName: 'PeerAdmin',
roles: [ 'PeerAdmin', 'ChannelAdmin' ]
};
const deployerCard = new IdCard(deployerMetadata, connectionProfile);
deployerCard.setCredentials(credentials);
// In-memory card store for testing so cards are not persisted to the file system
const cardStore = new MemoryCardStore();
const adminConnection = new AdminConnection({ cardStore: cardStore });
const deployerCardName = 'PeerAdmin';
const adminUserName = 'admin';
let adminCardName;
let businessNetworkDefinition;
return adminConnection.importCard(deployerCardName, deployerCard).then(() => {
return adminConnection.connect(deployerCardName);
}).then(() => {
return BusinessNetworkDefinition.fromDirectory(path.resolve(__dirname, '..'));
}).then(definition => {
businessNetworkDefinition = definition;
// Install the Composer runtime for the new business network
return adminConnection.install(businessNetworkDefinition.getName());
}).then(() => {
// Start the business network and configure an network admin identity
const startOptions = {
networkAdmins: [
{
userName: adminUserName,
enrollmentSecret: adminSecret
}
]
};
return adminConnection.start(businessNetworkDefinition, startOptions);
}).then(adminCards => {
// Import the network admin identity for us to use
adminCardName = 'admin@' + businessNetworkDefinition.getName();
return adminConnection.importCard(adminCardName, adminCards.get(adminUserName));
}).then(() => {
// Connect to the business network using the network admin identity
businessNetworkConnection = new BusinessNetworkConnection({ cardStore: cardStore });
return businessNetworkConnection.connect(adminCardName);
});
The caveat to this is that the network admin cards being returned from the call to AdminConnection.start()
is (as I type) in the process of being added in this issue: hyperledger/composer#2753
The CLI commands already register the network admin identity and output a card for this admin that you can import if you want to use it rather than give to somebody else.
After a couple of days of experimenting, I've found a way to solve this problem. The following code sequence uses the PeerAdmin card created as part of the v0.15 release. I import that card and, after adminConnect, update the businessNetwork element in the card's metadata and then, after re-importing the card, deploy and connect to the business network.
describe('Finance Network', function () {
this.timeout(_timeout);
let businessNetworkConnection;
let peerName = 'PeerAdmin@hlfv1';
before(function () {
const adminConnection = new AdminConnection();
let idPeer;
return hlc_idCard.fromDirectory(_home+'/.composer/cards/'+peerName)
.then ((_idPeer) => {
idPeer = _idPeer;
return adminConnection.importCard(peerName, idPeer);
})
.then(() => {
return adminConnection.connect(peerName);
})
.then(() => {
return BusinessNetworkDefinition.fromDirectory(path.resolve(__dirname, '..'));
})
.then((businessNetworkDefinition) => {
idPeer.metadata.businessNetwork = network;
return adminConnection.importCard(peerName, idPeer)
.then(() => {
return adminConnection.deploy(businessNetworkDefinition,{'card': idPeer});
});
})
.then(() => {
businessNetworkConnection = new BusinessNetworkConnection();
return businessNetworkConnection.connect(peerName);
});
});