Corda Automation Testing with Nightwatch.js and CircleCI

Phap Duong
5 min readApr 14, 2020

--

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:

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.

Node details and credentials in Chainstack.

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.

Interact with CorDapp 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.

Running CorDapp flow in CircleCI.

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.

Sign up to discover human stories that deepen your understanding of the world.

--

--

Phap Duong
Phap Duong

No responses yet

Write a response