XDE and React Native

Overview

Today I’ll do a quick highlight of an impressive tool to help with React Native development. Created by the group at Exponent.js, this tool helps you kick the wheels with React Native. While it is still in early development, what it provides is very promising and can help existing React Native developers.

React Native

If you are not familiar with React Native, it is a cross platform tool from Facebook to build native apps. Not hybrid apps, not web apps, but native apps for iOS and Android. Your UI are native components for the OS with your business logic code running in JavaScript Core. The main difference between a React.js app and a React Native app is your render function. You can reuse most of your code between the two platforms. Visit the official site to learn more about React Native.

React Native gotchas

You do need a Mac to build iOS apps, along with XCode. Android support is available on Windows.

Exponent XDE

The XDE is a tool from Exponent JS to help you develop React Native applications. iOS development is supported with plans for adding Android support in the future. Head on over to exponentjs.com to learn more and download the XDE. The XDE only supports Mac with plans to extend support to Windows and Linux. The XDE has a companion app to run on your iPhone. This app allows you to develop your React Native app without ever building it. If your app uses custom modules or extensions, you cannot use the XDE companion app to test your application.

The tool

The XDE provides a wide array of features to help with your development. When you create a new project a simple template that showcases some of the features of React Native. It provides the bare bones files your project needs; it does not include the whole project that React Native gives you when you use the CLI tool. This allows you to develop your project only editing the JS code. The XDE is not an “IDE”, but a helper tool for developing your React Native app. It lets you use any editor you want and piggy backs on the React Native debugging already provided. The power is the companion app and extra magic the XDE provides.

The basics

At a low level (not really), the XDE handles most of the overhead for React Native development. When you open a project it starts the React Packager for your application. This will serve up the webpack JS code for the Expononet companion application. You can serve your code via LAN, localhost, or using ngrok which is provided for you. Ngrok handles any proxy and firewall issues for you. You use the URL provided in the companion app and it will let you test outside your LAN, regardless of any settings you have.

The project management is extremely lightweight. They store global settings inside a $HOME/.exponent directory and do not clutter your project with additional files. Additionally, they will launch the terminal or a code editor of your choice. If you have Atom installed, it kicks out to that first (or it did for me) regardless of your default.

The Cloud

Exponent also provides a service called exp.host. This allows you to push your project assets up for anyone to test anywhere. Each project is stored under your account and accessible with a known URL. Projects pushed up are available in the companion app for testing. You can also send a link to email or your phone for testing on device. It will launch the companion app via the exp:// protocol handler.

The Companion app

This is a key tool to help with development. You can install it on the iOS simulator or get it from the store for your iPhone. You can pick a URL to launch inside the app which points to your JavaScript bundle from webpack. This can be your local machine from the XDE or a hosted document in the exp cloud. Anyone can install the companion app from the store, which is great when working with remote parties. You can send them a link to launch and they can run your code without having to build an IPA.

Debugging

The companion app has debugging enabled by default. Simply shake your device to bring up the React Native developer menu. This is an amazing tool for working with React Native. This feature is available in the companion app from the store; no need to build your own custom version with certificates. The React Native site goes into great detail about debugging, so head on over to the docs to learn more.

The Future

The future for the XDE and React Native look great. The team has a slack channel to interact with users and are looking for feedback. I’m anticipating their Android release to help speed up development of cross platform applications. They’ve also stated they may look into cloud build solutions, which puts the XDE and React Native against some other great tools (Phonegap Build/Intel XDK).

Welcome

Another way to test Node.js CLI tools

I’ve been writing a few CLI tools using Node.js lately. All of them require asynchronous code at some point in their calls; but some have multiple. Ideally, I’d expose each function in a module properly and test them, but I wanted to be able to test the end users experience also, where they call the CLI tool and get different results back. I could mock the HTTP requests, but I need the actual calls to execute.

Let’s test this

While chatting to a few friends, I thought why not just spawn off the call and evaluate the response. The particular tool that I was writing had multiple functions you could execute and calling each one allowed me to test the majority of my code. I chose to use Chai/Assert for my tests. Chai allows you to run asynchronous tests by passing in a “done” object into your test. When you execute that object, it will complete the test for you. Synchronous calls are tested normally as shown below.

1
2
3
4
5
6
7
8
9
10
var cli = require('../src/index')

describe("Object functions", function(){
it("should have a run function", function(){
cli.should.have.property("run");
});
it("should have a help function",function(){
cli.should.have.property("help");
});
});

Spawn to the rescue

Spawn allows us to execute the CLI code, with parameters, and capture the output to evaluate. This allowed me to closely replicate an end users experience using the CLI tool. I decided to create a known passing and failing test for each asynchronous operation. spawn allows us to capture the standard output and standard error from the CLI call. If there are any errors, we can check to see if the test should pass or fail.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
it("Should return the banner and commands",function(done){
var banner=spawn("../bin/tool",[""],{});
var buffer=null;
banner.stdout.on("data",function(data){
buffer+=data;
});

banner.stderr.on("data",function(err){
assert.ok(false,"Error "+err);
done();
});

banner.on("close",function(){
buffer.indexOf("Tool Title").should.not.equal(-1);
done();
});

});

The second parameter of spawn is an array of arguments to pass, allowing me to test each of the calls available. We buffer the standard output to compare against in the close event. In our case below, we are only looking for the string “Project Created” to let us know a new project was created.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
it("Should return the banner and commands with invalid arguments",function(done){
var banner=spawn("../bin/tool",["create","foobar"],{});
var buffer=null;
banner.stdout.on("data",function(data){
buffer+=data;
});
banner.stderr.on("data",function(err){
assert.ok(false,"Error "+err);
done();
});
//On the close event, we look at the buffer
banner.on("close",function(){
buffer.indexOf("Project Created").should.not.equal(-1);
done();
});
});

Not the end all

This is not an end all solution for testing your Node.js code. This can just be in addition to however your current testing environment is.