Part 2: Getting your app in a Cordova container (Android version)

When I wrote this part of the series, I started it on a Mac. Along the way I had to write some of it on a different computer, running Linux. So I decided to change the contents a bit of this post. I will still get the App in a container, but I will show it to you for the Android platform as well as iOS. Part 2 will therefore be split in two (an Android part and and iOS part). The reason for this is that it is nearly impossible to run an iOS simulator on Linux, so here you go.

So I will start with Android. You will have to make sure your development setup for compiling Android applications is correct. You can find pointers here

We will start with the React app built in part 1. The result of git clone should be located in $HOME/tmp/blogpost.

Remember when we built this React flux example app, we created a bundled version of all javascript in a file called bundle.js. It’s located in the js/ folder of the project and was created by running the build step ‘npm start’. I am mentioning this, because if you start with a fresh copy of the flux example, this build step needs to be performed for the app to work (the bundle.js is referenced in the index.html file of the project).

Let’s continue:

To embed the React app in a Cordova container, you need Cordova, a crossplatform app container.

Install it with:

npm install -g cordova

Then create the skeleton cordova application and copy the already created React app into it.

cd $HOME/tmp

$cd blogpost

$cordova create todomvc nl.joustie.todomvc "TodoMVC"

$cp -R flux/examples/flux-todomvc/* todomvc/www/

$cd todomvc/www

I don’t use the stock Android emulators that come with the SDK because they are just … too.. slow. Better to grab a copy of Genymotion that uses a Virtualbox virtualization and offers X86 Android (I have heard that the newest emulator that is included with Android Studio is also significantly faster, but I haven’t managed to test this out)

But.. this means you will have to compile for X86 as well, and not only for ARM cpu architecture. For this I used Crosswalk plugin to let the build phase also create X86 packages.

$cordova plugin add cordova-plugin-crosswalk-webview@1.2.0 
Fetching plugin "cordova-plugin-crosswalk-webview@1.2.0" via npm
Installing "cordova-plugin-crosswalk-webview" for android
joost@joost-Studio-XPS-1645:~/tmp/todomvc$ cordova build android
Running command: /home/joost/tmp/todomvc/platforms/android/cordova/build 
ANDROID_HOME=/home/joost//android-sdk-linux
JAVA_HOME=/usr/lib/jvm/java-7-oracle
Running: /home/joost/tmp/todomvc/platforms/android/gradlew cdvBuildDebug -b /home/joost/tmp/todomvc/platforms/android/build.gradle -Dorg.gradle.daemon=true
WARNING [Project: :] Current NDK support is deprecated. Alternative will be provided in the future.
WARNING [Project: :] Current NDK support is deprecated. Alternative will be provided in the future.
WARNING [Project: :] Current NDK support is deprecated. Alternative will be provided in the future.
WARNING [Project: :] Current NDK support is deprecated. Alternative will be provided in the future.
Download https://download.01.org/crosswalk/releases/crosswalk/android/maven2/org/xwalk/xwalk_core_library_beta/13.42.319.12/xwalk_core_library_beta-13.42.319.12.pom
Download https://download.01.org/crosswalk/releases/crosswalk/android/maven2/org/xwalk/xwalk_core_library_beta/13.42.319.12/xwalk_core_library_beta-13.42.319.12.aar
:preBuild
:compileArmv7DebugNdk
:preArmv7DebugBuild
:checkArmv7DebugManifest
:preX86DebugBuild
:CordovaLib:compileLint
:CordovaLib:copyDebugLint UP-TO-DATE
:CordovaLib:mergeDebugProguardFiles UP-TO-DATE
:CordovaLib:preBuild
:CordovaLib:preDebugBuild
:CordovaLib:checkDebugManifest
:CordovaLib:prepareDebugDependencies
:CordovaLib:compileDebugAidl UP-TO-DATE
:CordovaLib:compileDebugRenderscript UP-TO-DATE
:CordovaLib:generateDebugBuildConfig UP-TO-DATE
:CordovaLib:generateDebugAssets UP-TO-DATE
:CordovaLib:mergeDebugAssets UP-TO-DATE
:CordovaLib:generateDebugResValues UP-TO-DATE
:CordovaLib:generateDebugResources UP-TO-DATE
:CordovaLib:packageDebugResources UP-TO-DATE
:CordovaLib:processDebugManifest UP-TO-DATE
:CordovaLib:processDebugResources UP-TO-DATE
:CordovaLib:generateDebugSources UP-TO-DATE
:CordovaLib:compileDebugJava UP-TO-DATE
:CordovaLib:processDebugJavaRes UP-TO-DATE
:CordovaLib:packageDebugJar UP-TO-DATE
:CordovaLib:compileDebugNdk UP-TO-DATE
:CordovaLib:packageDebugJniLibs UP-TO-DATE
:CordovaLib:packageDebugLocalJar UP-TO-DATE
:CordovaLib:packageDebugRenderscript UP-TO-DATE
:CordovaLib:bundleDebug UP-TO-DATE
:prepareAndroidCordovaLibUnspecifiedDebugLibrary UP-TO-DATE
:preArmv7ReleaseBuild
:preX86ReleaseBuild
:CordovaLib:copyReleaseLint UP-TO-DATE
:CordovaLib:mergeReleaseProguardFiles
:CordovaLib:preReleaseBuild
:CordovaLib:checkReleaseManifest
:CordovaLib:prepareReleaseDependencies
:CordovaLib:compileReleaseAidl
:CordovaLib:compileReleaseRenderscript
:CordovaLib:generateReleaseBuildConfig
:CordovaLib:generateReleaseAssets UP-TO-DATE
:CordovaLib:mergeReleaseAssets
:CordovaLib:generateReleaseResValues
:CordovaLib:generateReleaseResources
:CordovaLib:packageReleaseResources
:CordovaLib:processReleaseManifest
:CordovaLib:processReleaseResources
:CordovaLib:generateReleaseSources
:CordovaLib:compileReleaseJava
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
:CordovaLib:processReleaseJavaRes UP-TO-DATE
:CordovaLib:packageReleaseJar
:CordovaLib:compileReleaseNdk
:CordovaLib:packageReleaseJniLibs UP-TO-DATE
:CordovaLib:packageReleaseLocalJar UP-TO-DATE
:CordovaLib:packageReleaseRenderscript UP-TO-DATE
:CordovaLib:bundleRelease
:prepareOrgXwalkXwalk_core_library_beta134231912Library
:prepareArmv7DebugDependencies
:compileArmv7DebugAidl
:compileArmv7DebugRenderscript
:generateArmv7DebugBuildConfig
:generateArmv7DebugAssets UP-TO-DATE
:mergeArmv7DebugAssets
:createXwalkCommandLineFileArmv7Debug
:generateArmv7DebugResValues
:generateArmv7DebugResources
:mergeArmv7DebugResources
:processArmv7DebugManifest
:processArmv7DebugResources
:generateArmv7DebugSources
:compileArmv7DebugJava
:preDexArmv7Debug
:dexArmv7Debug
:processArmv7DebugJavaRes UP-TO-DATE
:validateDebugSigning
:packageArmv7Debug
:zipalignArmv7Debug
:assembleArmv7Debug
:compileX86DebugNdk
:checkX86DebugManifest
:prepareX86DebugDependencies
:compileX86DebugAidl
:compileX86DebugRenderscript
:generateX86DebugBuildConfig
:generateX86DebugAssets UP-TO-DATE
:mergeX86DebugAssets
:createXwalkCommandLineFileX86Debug
:generateX86DebugResValues
:generateX86DebugResources
:mergeX86DebugResources
:processX86DebugManifest
:processX86DebugResources
:generateX86DebugSources
:compileX86DebugJava
:preDexX86Debug
:dexX86Debug
:processX86DebugJavaRes UP-TO-DATE
:packageX86Debug
:zipalignX86Debug
:assembleX86Debug
:assembleDebug
:cdvBuildDebug

BUILD SUCCESSFUL

Total time: 2 mins 17.031 secs

Then start Genymotion (I used the Galaxy S5 image).

When it has started, you can install the compiled package with:

$ adb install android-x86-debug.apk
1557 KB/s (38235054 bytes in 23.980s)
pkg: /data/local/tmp/android-x86-debug.apk
Success

If things went correct, you will find the todomvc application somewhere in you Apps.
Android apps menu
When you start it:
Todomvc running on Android

Part 1: Building a React App

Everyone knows Facebook, the biggest social-networking site. It is one of the largest sites of the planet. For years they have run their site on a customized version of PHP, named Hack. Not so long ago they switched to an internal product for parts of their site. This product is called React, it is a JavaScript framework. It’s star rose quickly internally.

The crux of the product is that it is a component-based, decoupled way of developing software, which is based on the best ideas from computer science about good design.

The abstraction of the DOM (Document Object Model) is handled by using a Virtual Dom. This means that you don’t directly touch the DOM of an HTML document, but rather a virtual DOM, wherein React then determines whether it will update the real DOM. There will be a diff of the change and then React will only find an update of the change position and update.

Last year Facebook published React as Open Source Software and an active community appeared around it. Many large companies have embraced technology and an ecosystem of addons came into being.
React is pure Javascript programming but one can also utilize JSX, a form of XML which can be converted by build tools in pure Javascript. The advantage of this is that a component consists of tree structures which have attributes that can be displayed.

Flux is a design pattern that has emerged as the preferred way to handle data in you React apps. It supports the idea of one-way dataflow. Instead of two-databindings in patterns like MVC, Flux only updates the view in one way. Below is a simplification but it shows clearly the unidirectional flow.

Flux diagram

There are several examples online but let’s take the one from Facebook, the TodoMVC application. It is featured in a tutorial found here.

We are only going to build it and use part of it for a mobile app, so get the source using :

$cd $HOME/tmp
$mkdir blogpost
$cd blogpost
$git clone https://github.com/facebook/flux.git
For now that’s ok, well use the example from this source tree.
$cd flux/examples/flux-todomvc

$npm install
#lots of installing here

Let’s start the project as mentioned in the package.json and have watchify ‘watch’ the file for live changes.
$npm start
> todomvc-flux@0.0.3 start ..../www
> watchify -o js/bundle.js -v -d js/app.js

2906584 bytes written to js/bundle.js (3.05 seconds)

Fire up your browser and open the index.html located in www directory of the flux-todomvc example.

todomvc screenshot

Now open the file Header.react.js in www/js/components
render: function() { return ( <header id="header"> <h1>todos</h1> <TodoTextInput id="new-todo" placeholder="What needs to be done?" onSave={this._onSave} /> </header> ); },
and change the line that says:
placeholder="What needs to be done?"
to
placeholder="What needs to be done, Joustie?"

Now refresh the browser and you will get:
todomvcscreenshot edited

To stop watchify ‘watch’ your live changes just go back to terminal/console/xterm shell session and hit control-c to signal quit.

So now we got this basic app running and I can start writing Part 2 of Running CI end-to-end testing on Saucelabs with a React hybrid cordova app.

Goodbye Wordpress

My blog has been running on the Wordpress platform for years. During the last year my development focus has been partly learning javascript and mobile development. As such, the time has come to put that knowledge to use in my personal projects. In the last couple of weeks I have migrated the old Wordpress platform to a new platform: Ghost) It is pure javascript and is more focussed on pure publishing than Wordpress. What do you think?

Running CI end-to-end testing on Sauce Labs with a React hybrid cordova app

In the wonderful world of crossplatform App development it’s hard to do end-to-end testing and CI. We have been able to setup CI for the CHECK web application, and I wanted to use the experience to make it work for mobile as well.

Those React mobile apps generally run in a Cordova container, not as a native app. Of course there is the React Native project, which will run directly through a javascript bridge, but for now we are still using Cordova.

Today I will show you from scatch how we go about this.

This delivery process consists of the following steps:

  • Part 1
    • building the React application (with flux as example)
  • Part 2
    • embed the application in a Cordova container
    • prepare the container
    • ~~build the Cordova container into a package that ~~
  • Part 2 (Android)
    • embed the application in a Cordova container
    • prepare the container
    • build the Cordova container into a package that can run in the Genymotion Android emulator
  • Part 2 (iOS)
    • embed the application in a Cordova container
    • prepare the container
    • build the Cordova container into a package that can run in the iOS simulator
  • Part 3
    • upload the app package to Sauce labs
    • create the Appium test (with Mocha)
    • run the test on Sauce Labs

About me

So now you’re reading this trying to find out ‘who’s this guy with this weird blog!’. So that would be me then. Let me introduce myself.

I’m married and have two kids. Started working in IT in the 90’s after a failed attempt to study Public Administration. I liked it so much, I stayed in the industry.
Started as an administrator, got to developing and now I like both worlds.

Several hobby’s, but some of them: Astronomy, Photography, Gardening….

Here is my CV (click for the whole thing):
CV

Mobile testing with Appium (and later Sauce Labs)

Building a Continuous Delivery flow was not our only goal. Getting automated testing in there would be very helpful. So the first idea was to get visual testing going using Appium. That took me a day or so, but we got it working.

Appium startup screen

The tests are very simple and for now only prove that tapping or clicking works, the assertions are not finished yet. Tests are written in ‘Mocha’ style and can be executed from the command line and as a job on our Jenkins servers later on :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
it("should contain a button for logging in ", function () {
return driver
//find the login button
.elementByXPath("//UIAApplication[1]/UIAWindow[1]/UIAScrollView[2]/UIAWebView[1]/UIAButton[1]")
.should.eventually.exist
});

it("a succesful login should be followed by a list of projects", function () {
return driver
//click the login button
.elementByXPath("//UIAApplication[1]/UIAWindow[1]/UIAScrollView[2]/UIAWebView[1]/UIAButton[1]").click().sleep(1000)
//the row with a project should show up
.elementByXPath("//UIAApplication[1]/UIAWindow[1]/UIAScrollView[2]/UIAWebView[1]/UIAStaticText[10]")
.should.eventually.exist
});

it("should be able to get details of project", function () {
return driver
//click the row of the project
.elementByXPath("//UIAApplication[1]/UIAWindow[1]/UIAScrollView[2]/UIAWebView[1]/UIAStaticText[9]").click()
//the project name field should appear
.elementByXPath("//UIAApplication[1]/UIAWindow[1]/UIAScrollView[2]/UIAWebView[1]/UIAStaticText[3]")
.should.eventually.exist
});

it("should be able to set this project in edit mode and save state", function () {
return driver
//click the aanpassen area
.elementByXPath("//UIAApplication[1]/UIAWindow[1]/UIAScrollView[2]/UIAWebView[1]/UIAButton[2]").click()
//click the name input field to make it editable
.elementByXPath("//UIAApplication[1]/UIAWindow[1]/UIAScrollView[2]/UIAWebView[1]/UIATextField[1]").click()
//wait a bit for client server communication
.sleep(5000)
//click save
.elementByXPath("//UIAApplication[1]/UIAWindow[1]/UIAScrollView[2]/UIAWebView[1]/UIAButton[2]").click()
//wait a bit for client server comm
.sleep(5000)
//go back to main project list
.elementByXPath("//UIAApplication[1]/UIAWindow[1]/UIAScrollView[2]/UIAWebView[1]/UIAButton[1]").click()
.sleep(5000)
//project rows should be there
.elementByXPath("//UIAApplication[1]/UIAWindow[1]/UIAScrollView[2]/UIAWebView[1]/UIAStaticText[10]")
.should.eventually.exist
});

it("should be able logout", function () {
return driver
//click the logoutbutton
.elementByXPath("//UIAApplication[1]/UIAWindow[1]/UIAScrollView[2]/UIAWebView[1]/UIAButton[1]").click()
//.sleep(1000)
//click on yes
.elementByXPath("//UIAApplication[1]/UIAWindow[1]/UIAScrollView[2]/UIAWebView[1]/UIAButton[5]").click()
.sleep(1000)
//a row with a project should show up
.elementByXPath("//UIAApplication[1]/UIAWindow[1]/UIAScrollView[2]/UIAWebView[1]/UIAStaticText[10]").isDisplayed()
});

Below is the inspector used to find out how controls can be identified by Xpath-value.
Appium Inspector

Welcome to Ghost

You’re live! Nice. We’ve put together a little post to introduce you to the Ghost editor and get you started. You can manage your content by signing in to the admin area at <your blog URL>/ghost/. When you arrive, you can select this post from a list on the left and see a preview of it on the right. Click the little pencil icon at the top of the preview to edit this post and read the next section!

Getting Started

Ghost uses something called Markdown for writing. Essentially, it’s a shorthand way to manage your post formatting as you write!

Writing in Markdown is really easy. In the left hand panel of Ghost, you simply write as you normally would. Where appropriate, you can use shortcuts to style your content. For example, a list:

  • Item number one
  • Item number two
    • A nested item
  • A final item

or with numbers!

  1. Remember to buy some milk
  2. Drink the milk
  3. Tweet that I remembered to buy the milk, and drank it

Want to link to a source? No problem. If you paste in a URL, like http://ghost.org - it’ll automatically be linked up. But if you want to customise your anchor text, you can do that too! Here’s a link to the Ghost website. Neat.

What about Images?

Images work too! Already know the URL of the image you want to include in your article? Simply paste it in like this to make it show up:

The Ghost Logo

Not sure which image you want to use yet? That’s ok too. Leave yourself a descriptive placeholder and keep writing. Come back later and drag and drop the image in to upload:

![A bowl of bananas]

Quoting

Sometimes a link isn’t enough, you want to quote someone on what they’ve said. Perhaps you’ve started using a new blogging platform and feel the sudden urge to share their slogan? A quote might be just the way to do it!

Ghost - Just a blogging platform

Working with Code

Got a streak of geek? We’ve got you covered there, too. You can write inline <code> blocks really easily with back ticks. Want to show off something more comprehensive? 4 spaces of indentation gets you there.

.awesome-thing {
    display: block;
    width: 100%;
}

Ready for a Break?

Throw 3 or more dashes down on any new line and you’ve got yourself a fancy new divider. Aw yeah.


Advanced Usage

There’s one fantastic secret about Markdown. If you want, you can write plain old HTML and it’ll still work! Very flexible.

That should be enough to get you started. Have fun - and let us know what you think :)

2016 - the next big thing?

So now we are a day forward in the new year and I realized I’d like to say something about it. For me 2015 has been a big year: finished my studies, learning new things about javascript, cloud business, apps, Agile and DEVOPS, amazing vacationing to Portugal with my love, a couple of weeks in the U.K. with the family in the summer, getting to run 10 KM … a lot of things.

Stonehenge gathering

Thinking about the past, the future

So what will 2016 bring.. ? I hope more knowledge, challenges, love and fun and more health! All the best!

Mobile CD

This year we created Continuous Integration (CI) for CHECK, but since last month we also are in the process of creating an automated build for our mobile projects. In the DEVOPS and Agile world we call this Continuous Delivery (CD). Why would we do this? Mainly for trying to speed up delivery of applications and in shorter iterations. We noticed in the initial projects we lost a lot of time because of deployment issues, especially with all the different App Stores around.

So we tried to use our existing CI platform. This was quite a challenge, because for instance Apple devices require some specific tools on the OS X platform, and our Jenkins CI server is running on Linux. Fortunately Jenkins also works with a master-slave model, so you can setup a Mac computer as a slave to the master build server. This way we have been able to run building and signing of iOS apps on our Mac mini and storing the results in the software repository of our Configuration management system in Confluence.

Workflow diagram
Mobile Development workflow