Corda Automation Testing with Nightwatch.js and CircleCI

I was researching a way how to test our new supported blockchain protocol — Corda on Chainstack platform. Also, this is my first-ever blockchain blogpost. I will share how I carried out end-to-end continuous Corda integration with Nightwatch.js and CircleCI.
🍄 Originally published on January 7, 2020 at https://chainstack.com/corda-automation-testing-with-nightwatch-js-and-circleci/
The code in Corda is written using Kotlin, a programming language from JetBrains, and Nightwatch.js is a Node.js powered end-to-end testing framework. My challenges are to connect to a node, initiate a flow, and have it signed by relevant parties using JavaScript.
I have a few ideas to do this:
- Run a Corda web server in my Docker image, and write JavaScript to interact to the CorDapp.
- Set up GraalVM (a high-performance polyglot VM) in my Docker image, write a Java function in Nightwatch.js.
- Interact with Corda Standalone Shell client by executing shell script in Node.js, then verify the output of shell script.
The first two ideas seem possible, but I need to include CorDapp source code in the test, which is non-optimal and inconvenient. Eventually, the last one is better and simpler.
I use No ticket scalping CorDapp for my test. You may want to explore it before moving to details.
Technology stack
These are the details of programming languages, tools, and frameworks I used in the test:
- Nightwatch.js 1.3.2 / Node.js 11 / shell script;
- Docker;
- CircleCI 2.0;
- OpenJDK-8;
- Corda Standalone Shell client 4.3;
- No ticket scalping CorDapp installed on two Corda nodes, running on Chainstack.
I assume that you are familiar with the Nightwatch.js framework, so I won’t focus on the structure as well as the test case code.
Besides the Corda Standalone Shell client, Chainstack also provides Chainstack standalone shell, which is a containerized version of Corda Standalone Shell, and which helps you interact with the CorDapps. You can learn more about it in our official documentation.

Install OpenJDK-8 in Docker image
You need to install OpenJDK-8 to run Corda Standalone Shell client; add these lines into your Docker file.
# Install OpenJDK-8
RUN apt-get update && \
apt-get install -y openjdk-8-jdk && \
apt-get install -y ant && \
apt-get clean;# Fix certificate issues
RUN apt-get update && \
apt-get install ca-certificates-java && \
apt-get clean && \
update-ca-certificates -f;# Setup JAVA_HOME -- useful for docker commandline
ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64/
RUN export JAVA_HOME
You may need to build your Docker image again.
docker build .
Write shell script to interact with No ticket scalping CorDapp
You can learn the prerequisites to run Corda Standalone Shell client at: https://docs.chainstack.com/operations/corda/tools#corda-standalone-shell
The below script will do the following things:
- Connect to Corda Node 1.
- Print out all flows in Node 1.
- Start
noScalpFlow
flow to distribute 99 tickets of event Chainstack live concert from Node 1 to Node 2. - Verify the transaction by executing
vaultQuery
command. - Exit the Corda Standalone Shell client.
# location of binary files
CORDA_CLI="corda-tools-shell-cli-4.3-all.jar"
CORDAPP_DIR="../my-cordapps/"# node 1 credentials
NODE1_HOST="nd-255-728-694.rg-837-380.int.chainstack.com"
NODE1_PORT="10201"
NODE1_USER="vibrant_ptolemy"
NODE1_PASS="*****"# node 2 legal name
NODE2_LEGALNAME="OU=Chainstack-ND-026-270-261, O=Chainstack, L=Singapore, C=SG"# command to connect to Corda node 1
START_CORDAPP="java -jar $CORDA_CLI --host=$NODE1_HOST --port=$NODE1_PORT --user=$NODE1_USER --password=$NODE1_PASS --cordapp-directory=$CORDAPP_DIR"# launch the Corda Standalone Shell client and run flow commands
{
echo "flow list"
echo "start noScalpFlow eventName: 'Chainstack live concert', ticketQuantity: 99, toDistributor: '$NODE2_LEGALNAME'"
echo "run vaultQuery contractStateType: com.noScalpDapp.states.noScalpState"
echo "bye"
} | $START_CORDAPP
Save as start_cordapp.sh
file, and run it in terminal.

Checking the output, there should be a transaction. You can use this information to verify whether the test passed or not.
Flow completed with result: SignedTransaction(id=C98A2B49358B9FC6C1C8EEBAA99DF36238E9E4F97CF492905C2A1EF25B1B9639)
Execute the shell script by Node.js and verify the output
In the below code, I write a function to start the noScalpFlow
flow, print out, and verify its result. In Node.js, thechild_process
module provides the ability to spawn child processes.
Then, I combine child_process.exe()
and util.promisify()
to create an async function which returns a boolean Promise.
// Nodejs utils to execute shell script asynchronously
const { promisify } = require('util');
const exec = promisify(require('child_process').exec);
/**
* Run noScalpFlow flow and verify the result
* @param {Object} node1 First node
* @param {Object} node2 Second node
*/
async function verifyFlow(node1, node2) {
const CORDA_CLI = 'corda-tools-shell-cli-4.3-all.jar';
const CORDAPP_DIR = '../my-cordapps/';
const START_CORDAPP = `java -jar ${CORDA_CLI} --host=${node1.host} --port=${node1.port} --user=${node1.user} --password=${node1.pass} --cordapp-directory=${CORDAPP_DIR}`; // launch the Corda Shell client and run flow commands
const { stdout } = await exec(`
START_CORDAPP="${START_CORDAPP}"
{
echo "flow list"
echo "start noScalpFlow eventName: 'Chainstack live concert', ticketQuantity: 99, toDistributor: '${node2.legalName}'"
echo "run vaultQuery contractStateType: com.noScalpDapp.states.noScalpState"
echo "bye"
} | $START_CORDAPP
`); // Print out the output
console.log(stdout); // Verify the output
return stdout.includes('Flow completed with result: SignedTransaction');
}
After that, you need a test scenario using the Nightwatch.js framework.
// Node 1 credentials
const node1 = {
host: 'nd-255-728-694.rg-837-380.int.chainstack.com',
port: '10201',
user: 'vibrant_ptolemy',
pass: 'frisk-lapdog-uneasy-amid-slate-flaky',
};// Node 2 legal name
const node2 = {
legalName: 'OU=Chainstack-ND-026-270-261, O=Chainstack, L=Singapore, C=SG',
};module.exports = {
'@tags': ['runCorDappFlow'], 'Run CorDapp flow'(browser) {
const { page } = browser;
const corda = page.nodes.corda(); // Run flow and verify result
browser.perform(async () => {
await corda.verifyFlow(node1, node2);
}); browser.end();
},
};
Commit your code and run the workflow in CircleCI; it will take a few minutes to complete. In my scenario, I get the credentials of Node 1 and Node 2, run noScalpFlow flow, and verify the output. You can see results in the below screenshot.

Before writing this post, I have done a lot of researching works to find the best solution for Corda automation testing as most of the resources from the Internet focus on building CorDapps. I believe this post will help your team to test, speed up, and secure your Corda applications like what the Chainstack team is doing.
You can try Chainstack for free at: https://console.chainstack.com.