Tag Archives: javascript

Exploring Loopback – Part 1.

Imagen-Devecoop-Loopback

Hi, this is the first part of a series of articles related to the Loopback framework.

Loopback, as its pages says is a javascript framework based on express, so if you know express then it should be easy to understand and apply your knowledge.

LoopBack is an open source Node.js framework built on top of Express optimized for building APIs for mobile, web, and other devices. Connect to multiple data sources, write business logic in Node.js, glue on top of your existing services and data, connect using JS, iOS & Android SDKs

In my last project we choosed to use this powerful and interesting framework. Among the features we find:

  • Easy-to-use CLI wizard.
  • Built-in API Explorer.
  • Several features for creation, relationship and ACL on the models.
  • It’s isomorphic, sharing the same API between client and server side.

The best way to show you the potential is using it, so here we go…

Step 1 - Installation:

First we need to verify if we have Node and NPM installed, if you need help check this awesome post by Ale

Easy, we have a npm package, so run the following command:

$ npm install -g strongloop

(Yes, it says strongloop, that’s the company that develops loopback, it was recently acquired by IBM)

Once we have it installed, let’s get to work!

The first thing we need to do is creating a new project, as I’m someone that forgets the things that I have to do (and I have too much to do), I think that we can create something easy and productive: a TODO list.

How we do that ?, with our Easy-to-use CLI wizard:

$ slc loopback

In general the CLI wizard guides us asking questions, in this case we have the following (yes!, is a yeoman generator):

[?] Enter a directory name where to create the project: todo-app
[?] What's the name of your application? todo-app

Here we can see what we just did.

Step 2 - Creating our model

Our next step is creating our todo model, which is going to have a text field with string type and a boolean field to know if it is completed or not.

$ cd todo-app
$ slc loopback:model
? Enter the model name: todo
? Select the data-source to attach todo to: db (memory)
? Select model's base class: PersistedModel
? Expose todo via the REST API? Yes
? Custom plural form (used to build REST URL): todos
Let's add some todo properties now.

What we just chose ?:

  • Select the data-source to attach todo to: db (memory): Memory options means that when we stop the app, we will loose every saved data. On the next issues we will see how to use different datasources.
  • Select model’s base class: PersistedModel: PersistedModel is the base model of built-in models, except for Email. It provides all the standard create, read, update, and delete (CRUD) operations and exposes REST endpoints for them.
  • Expose todo via the REST API? Yes: We can use the API Explorer.

So far we created the model, now we need to add the properties that I mentioned:

Enter an empty property name when done.
? Property name: text
   invoke   loopback:property
? Property type: string
? Required? Yes
Let's add another todo property.
Enter an empty property name when done.
? Property name: completed
   invoke   loopback:property
? Property type: boolean
? Required? Yes

To finish we just use ctrl+c.

Two files were added, todo.js y todo.json. The todo.json file is where we define properties, fields, relationships, permissions, etc. And the todo.js file is where we gonna to create the remote methods, hooks and any related code of the model, etc.

This is our todo.json file:

{
  "name": "todo",
  "plural": "todos",
  "base": "PersistedModel",
  "idInjection": true,
  "options": {
    "validateUpsert": true
  },
  "properties": {
    "text": {
      "type": "string",
      "required": true
    },
    "completed": {
      "type": "boolean",
      "required": true
    }
  },
  "validations": [],
  "relations": {},
  "acls": [],
  "methods": []
}

And todo.js:

module.exports = function(Todo) {

};

Additionally the new datasource of the model was added in the model-config.json file

Here we can see what we just did.

So, what we do next ?, how about running what we just did ?, we can run the app as the following:

$ node .
Browse your REST API at http://0.0.0.0:3000/explorer
Web server listening at: http://0.0.0.0:3000/

If we go to http://0.0.0.0:3000/explorer or http://localhost:3000/explorer we will see two models, todo and Users (the exposed models are the ones that have the public property set to true).

Well now is when you guys test the API (I will only show a couple of simple examples), loopback already create the API for us, where we have the most common operations: POST, GET, PUT, find, exists, etc.

####Adding a new item:

Fist we open the accordeon in POST /todos (http://localhost:3000/explorer/#!/todos/create)

We have three separated groups in there: Response Class, Parameters, Response Messages.

Response class has two visualizations options: Model: shows us how the properties are defined (type, required, not required, etc) and Model Schema: a json with default values.

In Parameters we have a textarea called value, in there we can add the item that we want (create the json by hand or click on the Model Schema on the Data Type column on the right to set as parameter value)

In both cases we can set the content type too.

At last, we have the Response Messages, which show us where the request from and some data of the response like the body, the code and the headers.

Imagen-Making-POST

In this example we add one item, “Clean the kitchen” :(. After we click on “Try it out!”, we have the following response:

Imagen-POST-RESPONSE

To see all added items we can do the same steps but with GET option, in addition we can use filter here, but we will leave this for later.

Imagen-GET

That was the first look on what Loopback offers, we create an API REST without adding a single line of code.

In the next part we will see how to integrate the client and connect with a database.

E2E tests with django-casper

We often need to test our "javascript rich" Django application and the infamous TestClient provided with Django is not enough on this cases. Here is when django-casper comes to the rescue

First a brief introduction. Javascript has a great package named PhantomJs. PhantomJs is a headless webkit browser (yeap no need to open FF/Chrome for testing ala selenium!). CasperJS is a library on top of that to ease the testing from CasperJS website:

CasperJS is an open source navigation scripting &testing utility written in >Javascript for the PhantomJS WebKit headless browser and SlimerJS (Gecko).It >eases the process of defining a full navigationscenario and provides useful >high-level functions,methods & syntactic sugar for doing common tasks such as:

  • defining & ordering browsing navigation steps
  • filling & submitting forms
  • clicking & following links
  • capturing screenshots of a page (or part of it)
  • testing remote DOM
  • logging events
  • downloading resources, including binary ones
  • writing functional test suites, saving results as JUnit XML
  • scraping Web contents

django-casper is a sort of wrapper for casperjs, allowing us to run javacript/casper tests from Django's built-in test command, this is great, not only to facilitate the development process, but to take advantage of Django's own test runner to create mocks, stubs, fixtures, etc. for our front end testing.

Installation:

We will need a running python and node instance with django and casperjs installed respectively. If you don't have it already on your box here is a quick howto for GNU/Linux

Node

Install nvm

$ curl https://raw.github.com/creationix/nvm/v0.4.0/install.sh | sh

From nvm, install latest node version

$ nvm install latest

then open a new terminal or source ~/.zshrc or ~/.bashrc or whatever rc file for the shell you are using

Create virtualenv

Create a new virtualenv instance if you don't have virtualenv installed please refer to the official documentation http://virtualenv.readthedocs.org/en/latest/virtualenv.html Note: You can skip this step and install Django globally, but is not recommended

$ virtualenv django-casper && source django-casper/bin/activate

Now we are ready to install casperjs and django

Installing django

$ pip install django

Installing casperjs

$ npm install -g casperjs

Installing django-casper

It is possible to install django-casper from pip (pip install django-casper), but we are going to use the following method, in order to get the example code for tests.

$ git clone git@github.com:dobarkod/django-casper.git $ cd django-casper $ python setup.py install

Using it

Django-casper comes with a testproject that implements some test tests.

$ cd testproject $ python manage.py test testapp

This should run all the test included in the application.

Where are my tests?!!

Tests are divided in two parts, the django part where the backend stuff is prepared (fixture, backend mocks, etc) and the casper part where the actual tests are written. Lets see an example:

$ vim testapp/tests.py

from casper.tests import CasperTestCase
import os.path

from django.contrib.auth.models import User


class CasperTestTestCase(CasperTestCase):

    def test_that_casper_integration_works(self):
        self.assertTrue(self.casper(
            os.path.join(os.path.dirname(__file__),
            'casper-tests/test.js')))

On this file we have one test that in turn calls the casper library passing the test casper should run on this case casper-tests/test.js. Inside this django test, we could add new data to the database, and test the result on the casper-tests/test.js test.

Lets see the content of the casper-tests/test.js test file

 casper.test.comment('Casper+Django integration example');
 var helper = require('../../../casper/jslib/djangocasper.js');

 helper.scenario('/',
function() {
   this.test.assertSelectorHasText('em', 'django-casper',
 "There's a mention of django-casper on the page");
},
function() {
  this.click('a');
   this.test.assertSelectorHasText('#messages p', 'Good times!',
 "When the link is clicked, a message is added to the page");
}
 );

helper.run();

We can observe, that the test is opening the root "/" page (helper.scenario('/'.... ), and then asserting the content of the page on the first function. The second function, clicks on a link on the page, and asserts that a message is added to the page.

These are basic tests, I encourage you to give it a try. Also take a look a Django dynamic fixture, a library to create dynamic test data for your django tests.

Happy Testing!

Useful links

django-casper: https://github.com/dobarkod/django-casper

django-dynamic-fixture: https://github.com/paulocheque/django-dynamic-fixture

casperjs: http://casperjs.org/

virtualenv: http://www.virtualenv.org/en/latest/

nvm: https://github.com/creationix/nvm

Creating a Backbone, RequireJs and Compass application from scratch with Yeoman

This guide will show you how to scaffold a Backbone + RequireJs + Compass application completely from scratch.

In the way, we are going to cover how to install Node, NPM, RVM, Ruby, Compass and Yeoman (yo, Grunt, Bower). We will cover some of the common pitfalls and how to solve them. This guide assumes you are using a GNU/Linux based operative system and it was tested on Ubuntu 12.04 64 bits.

1. Node.js and NPM

First we install Node.js and Node Package Manager (NPM). It is important to NOT use SUDO when doing this. Using sudo will get you into some nasty permission conflicts. Installing Node and NPM can present some difficulties depending on your machine's setup (firewall, users, etc.) I have found that this Gist has the right solution for most cases. Right now we are going to use the first solution.

We install Node:

echo 'export PATH=$HOME/local/bin:$PATH' >> ~/.bashrc
. ~/.bashrc
mkdir ~/local
mkdir ~/node-latest-install
cd ~/node-latest-install
curl http://nodejs.org/dist/node-latest.tar.gz | tar xz --strip-components=1
./configure --prefix=~/local
make install

Then we install NPM:

curl https://www.npmjs.org/install.sh | sh

To verify:

node -v
npm -v

Node should be v0.10.26 or larger, NPM should be 1.4.3 or larger.

2. Compass

With Node and NPM in place, we need to install Compass.

"Compass is an open-source CSS authoring framework which uses the Sass stylesheet language to make writing stylesheets powerful and easy."

To install Compass, we will need Ruby.

If you already have Ruby installed, verify you have the latest version with

ruby -v

And update your ruby gems with

gem update --system

If you don't, we are going to install Ruby (the latest version being 2.1.1). There are different ways to do so, in this case we choose to do it through Ruby Version Manager (RVM).

"RVM is a command-line tool which allows you to easily install, manage, and work with multiple ruby environments from interpreters to sets of gems."

curl -L https://get.rvm.io | bash -s stable
source ~/.rvm/scripts/rvm
rvm install 2.1.1
gem install compass

verify:

ruby -v
compass -v

Open a new console, and try ruby -v again. If you don't have the ruby command anymore, you have to enable "Run command as a login shell" on your console's settings. Why this is so is explained in this article.

3. Yeoman

To setup our application, we are going to use the Backbone generator for Yeoman. It will handle most of the hard work for us.

Yeoman is a great tool by Addy Osmani (same guy from the Backbone Fundamentals book) and others, that will help you

"by scaffolding workflows for creating modern webapps, while at the same time mixing in many of the best practices that have evolved within the industry.""

It gives you three tools: yo, for new apps scaffolding, Grunt, to build, preview, test and any other task in your workflow, and Bower, for managing packages and their dependencies.

We install Yeoman (using the -g flag to indicate NPM that the module should be available globally):

Note we don't use SUDO at all when installing with npm!

npm install -g yo

If you see the following output when installing Yeoman:

[Yeoman Doctor] Uh oh, I found potential errors on your machine

[Error] NPM root value is not in your NODE_PATH [info] NODE_PATH = /usr/lib/nodejs:/usr/lib/node_modules:/usr/share/javascript NPM root = ~/local/lib/node_modules

[Fix] Append the NPM root value to your NODE_PATH variable Add this line to your .bashrc export NODE_PATH=$NODE_PATH:~/local/lib/node_modules Or run this command echo "export NODE_PATH=$NODE_PATH:~/local/lib/node_modules" >> ~/.bashrc && source ~/.bashrc

Just follow the instructions in the [Fix] section (if only all CLIs were this helpful!), adding the NPM root to your NODE_PATH.

For scaffolding our Backbone app, we need a Yeoman generator that knows how to do it. Let's install it:

npm install -g generator-backbone

To verify the installation, run

yo -h

You should see a list of generators under the message "Please choose a generator below." Backbone should be there. If it isn't listed, try

echo "export NODE_PATH=$NODE_PATH:~/local/lib/node_modules" >> ~/.bashrc && source ~/.bashrc

Scaffolding our application

We are almost ready. Create a directory for your application, and generate the Backbone app inside it:

mkdir <my-app-name>
cd <my-app-name>
yo backbone

When asked, select Bootstrap for Sass and RequireJs.

[?] What more would you like? 
 ⬢ Bootstrap for Sass
 ⬡ Use CoffeeScript
‣⬢ Use RequireJs

Next we install the project's dependecies:

npm install
bower install

Running our application

Our application is setup. To try it out, run Grunt with the "serve" task:

grunt serve

Our default browser should open at http://localhost:9000/, showing the scaffolded app.

You can see in the console output the different tasks Grunt performed for us (tasks are defined in Gruntfile.js), to get the app up and running. You can see a "connect:livereload" task was run, and a "watch" task is running. This means you can, thanks to LiveReload edit your index.html at /app and the browser will automatically refresh the page with your changes! A huge time-saver.

You can get to work on your Backbone app! The Yeoman generator not only created the app scaffold for us, we can use it to create the basic parts of any Backbone app (models, views, etc.), for instance the router:

yo backbone:router ''

Happy coding!