miércoles, 22 de junio de 2016

writing selenium in javascript node with webdriverio - instructions for impatients

The following is what you need to do in order to write a javascript program that will command your browser through selenium using webdriver.io node library.

 First is about installing and running the selenium server. Second is a little webdriverio example. 

Installing the selenium server

The following instructions are give in a shell script that was tested on mac:
#install java

# download selenium server: 

curl -O http://selenium-release.storage.googleapis.com/2.53/selenium-server-standalone-2.53.0.jar

#download googlechrome selenium drivers: 

curl -O http://chromedriver.storage.googleapis.com/2.22/chromedriver_mac32.zip
unzip chromedriver_mac32.zip


#Execute selenium server: 

java -Dwebdriver.chrome.driver=./chromedriver -jar selenium-server-standalone-2.53.0.jar


The Program

From here the instructions are the same as in http://webdriver.io/guide.html - just execute ```npm install webdriverio``` in your node project and execute the following file. In this simple program that will navigate to google and when is ready print the document title in the console:
var webdriverio = require('webdriverio');
var options = {
    desiredCapabilities: {
        browserName: 'chrome'
    }
};
webdriverio
    .remote(options)
    .init()
    .url('http://www.google.com')
    .getTitle().then(function(title) {
        console.log('Title was: ' + title);
    })
    .end();

Appendix: Technologies used

  • http://www.seleniumhq.org/ - the infrastructure that talks to browsers (java) 
  • http://webdriver.io/guide.html - the selenium javascript api 
  • http://chromedriver.storage.googleapis.com/index.html - selenium driver to manage chrome browser.
  • java and node

jueves, 19 de mayo de 2016

Minify JavaScript code with esprima and escodegen


var esprima = require('esprima'), 
escodegen = require('escodegen');

function doUglify(s)
{
 try
 {
  var ast = esprima.parse(s);
  s = escodegen.generate(ast, {format: escodegen.FORMAT_MINIFY}) || s;
 }
 catch(ex)
 {
  console.log(ex);
 }
 return s;
}

lunes, 18 de enero de 2016

first steps with postgresql for inpatients

The following is a bash script that show easy steps for getting started with postgresql and verified in a arch linux distribution. There are also some comments for explaining, ideal for inpatients:
DATA_FOLDER=.data
mkdir myproject
cd myproject

initdb -D $DATA_FOLDER

#TODO DONT DO THIS IN PRODUCTION
sudo chmod -R a+wr /run/postgresql/ 

postgres -D $DATA_FOLDER >logfile 2>&1 &

createdb mydb

sábado, 7 de noviembre de 2015

jasmine for node: execute test files and set jasmine timeout globally

When developing jasmine tests in node, I want to declare which files to run. I don't want / like the way of indicating this in a jasmine.json file and it wasn't working as expected.
Also I had some difficulties guesssing how to set the timeout interval globally. Mainly my difficuly was not to now that jasmine was creating a global 'jasmine' object when requiring it.
The following code shows both things:
var
 path = require('path')
, glob = require('glob').sync
, Jasmine = require('jasmine')

var jasmineRunner = new Jasmine();
jasmine.DEFAULT_TIMEOUT_INTERVAL = 99999999;

jasmineRunner.specFiles = glob(path.join(__dirname, '*Spec.js'));
jasmineRunner.execute();

martes, 6 de octubre de 2015

Queue based on Q promises

So just that,I'm working with promises in JavaScript and at certain point I needed a queue for executing asynchronous tasks. My promises are implemented by q library and my particular requirements are as follows. I implemented this web service client without knowing that no concurrent operations are allowed. In some cases, if you request two operations at the same moment the server will return an error. In my case, an obvious quick solution was to en-queue the method that makes the requests in my client. Something like make it synchronous (similar as java methods can be declared as 'synchronous' when multi threads access it).

I research a little and there are plenty alternatives, most appreciated was the queue utility of async, a library that also use. Nevertheless instead learning how to use it, and because I know this problem can be solved w promises wanted to try something else

I very liked the solution proposed here because is simple so I adapted to use Q promises instead jQuery's. This is the result (working example in node, but should work also in the browser)

var Q = require('q')


var Queue = function () 
{
    var lastPromise = null;

    this.add = function (obj, method, args, context) 
    {
        var methodDeferred = Q.defer(); 
        var queueDeferred = this.setup();
        if(context === undefined) { context = obj; }

        // execute next queue method
        queueDeferred.done(function () 
        {
            // call actual method and wrap output in deferred
            setTimeout(function () 
            {
                obj[method].apply(context, args);
                methodDeferred.resolve();
            }, 100);
        });
        lastPromise = methodDeferred.promise;
    };

    this.setup = function () 
    {
        var queueDeferred = Q.defer(); 

        // when the previous method returns, resolve this one
        if(!lastPromise)
        {
            lastPromise = Q.defer(); 
            lastPromise.resolve();
            lastPromise = lastPromise.promise;
        }
        lastPromise.done(function () 
        {
            queueDeferred.resolve();
        });

        return queueDeferred.promise;
    }
};



var queue = new Queue();
queue.add(console, 'log', ['one']);
queue.add(console, 'log', ['two']);
queue.add(console, 'log', ['three']);
setTimeout(function ()
{
    queue.add(console, 'log', ['four']);
}, 2000);

martes, 24 de marzo de 2015

console.timing() - measure multiple calls of a code block

The following is an utility, similar to console.time / console.timeEnd to measure how long a code block takes to execute but it will take in account sevaral times and report the total calling time and average. Very useful wile profiling code blocks execution time.


console.timing = function(key)
{
 this.timings = this.timings || {}; 
 this.timings[key] = this.timings[key] || []; 
 this.timings[key].push(performance.now()); 
};

console.timingEnd = function(key)
{
 var t0 = this.timings[key][this.timings[key].length-1]; 
 this.timings[key][this.timings[key].length-1] = performance.now() - t0;
}; 

console.timingReport = function(key)
{
 var times = this.timings[key]; 
 var sum = 0;
 for (var i = 0; i < times.length; i++) 
 {
  sum += times[i]; 
 }
 var average = sum / times.length;
 console.log(key + ': times: ' + times.length + ', sum: ' + sum + ', average: ' + average);  
};

console.timingReset = function(key)
{
 this.timings[key] = []; 
}; 

domingo, 22 de febrero de 2015

Writing unit tests for command line tools using jasmine and shelljs

So this is the situation, I have a project using gulp and the build tasks are increasingly getting complex and hard to maintain. These command line tools are written by me in JavaScript and I want a way of testing their command line API, similarly of how I write other source code unit test.

Before proceed, all the source code explained in this document is  maintained here https://github.com/cancerberoSgx/javascript-sample-projects/tree/master/gulp-test-setup-shelljs-jasmine

In particular, I want to write jasmine code with specs that call the command line tools and then assert if folders/files are created, etc. So I will use jasmine as the unit test framework and shelljs for easy filesystem operations & assertations.

So suppose you have a project with build system written with gulp or grunt, npm (or whatever) and you want to write a jasmine unit test that runs these tasks and make assertations. Then users can launch unit tests calling npm test on your app.

First we install jasmine and shelljs in your project:

npm install jasmine --save-dev
npm install shelljs --save-dev
Now let's generate the jasmine unit tests with the following command. This will generate the folder spec in which we will store our tests:

node node_modules/jasmine/bin/jasmine.js init
Now let's create the file specs/buildSpec.js with the following content.

require('shelljs/global');

describe("test the build", function() 
{
 it("npm install", function() 
 {
  rm('-rf', 'node_modules'); 
  expect(test('-d', 'node_modules')).toBe(false); 
  expect(exec('npm install', {silent:true}).code).toBe(0); 
  expect(test('-d', 'node_modules')).toBe(true); 
 }); 

 it("gulp sass", function() 
 {
  rm('-rf', 'dist'); 
  expect(test('-d', 'dist')).toBe(false); 
  expect(exec('gulp sass', {silent:true}).code).toBe(0); 
  expect(test('-f', 'dist/main.css')).toBe(true); 
 }); 

 it("gulp src", function() 
 {
  rm('-rf', 'dist'); 
  expect(test('-d', 'dist')).toBe(false); 
  expect(exec('gulp src', {silent:true}).code).toBe(0); 
  expect(test('-f', 'dist/all.js')).toBe(true); 
 }); 
});
This test only make sense in my application, you should write your own. I will use it only as an example.

As you can see it is a jasmine spec with three it(), the first checks if the command 'npm install' works, the second if the task 'gulp sass' works and the third if 'gulp src' works.

npm install: here the test first removes the folder node_module, then executes the command 'npm install' and then checks that the folder node_modules exists.

gulp sass: here the test removes the 'dist' folder, then executes the command 'gulp sass' and then makes sure the file dist/main.css was generated. gulp src is very similar.

Appendix: asserting if a server is turned on.

In my application, there is a command 'gulp connect' that will start a local server hosting the application. For testing this I use the following code.

It basically perform the following checks:

  1. check that the port 8080 is free 
  2. run the command 'gulp connect' asynchronously.
  3. wait for two seconds (time to start),
  4. check that the http port 8080 is used, 
  5. kill the server 6) and then checks that the port 8080 is free. Before killing a handler optionally given by the user is called so he can do some assertations over served resources (in my case using curl())
I tried to define a reusable and jasmine-agnostic function for testing all this automatically and assert something before killing the server. Unfortunately there are some hardcoded timeouts and have a asynchronous syntax so it might be hard to understand.

Notice how I have handcrafted an utility assertCommandOpenPort that performs all these work and a curl() function to assert on url resources. 


require('shelljs/global');

describe('gulp connect', function() 
{
 it('gulp connect should serve index at 8080', function(done) 
 {
  console.log('gulp connect should serve index at 8080'); 
  assertCommandOpenPort({
   cmd: 'gulp connect'
  , port:8080
  , timeout:2000
  , predicate: function(val, msg)
   { 
    if(!val)
    {
     expect('gulp connect fail: '+msg).toBe(false); 
    }
   }
  , testBeforeKill: function(done)
   {
    curl({
     host: 'localhost'
    , port: 8080
    , path: '/'
    , dataHandler: function(data, res)
     {
      expect(data.indexOf('</html>') !== -1).toBe(true); 
      done();
     }
    , errorHandler: function()
     {
      expect('html served').toBe(true); 
      done();
     }
    });     
   }
  , done: done
  }); 
 });  
});


// general utility for testing that a executing a command open a certain port. What it does: 
// 0) assert port is free 1) assert port is unused 2) run the command 3) assert port is used 4) kill the command 5) assert the port is free.
// I promise I tried to write the async part the easier I could....
function assertCommandOpenPort(config)
{
 var port = config.port
 , predicate = config.predicate
 , timeout = config.timeout || 2000; 
 isPortTaken(port, function(isUsed)
 {
  predicate(!isUsed, 'step 1 port taken initially'); 
 }); 
 var childProcess = exec(config.cmd, {silent: true, async: true});
 setTimeout(function()
 {
  isPortTaken(port, function(isUsed)
  {
   predicate(isUsed, 'step 2 port not taken'); 
   config.testBeforeKill(function()
   {
    childProcess.kill();
    setTimeout(function() // hack: give some time to the killing
    {
     isPortTaken(port, function(isUsed)
     {
      predicate(!isUsed, 'step 3 port not free');
      config.done();
     });
    }, 50); 
   });
      
  }); 
 }, timeout); // ugly hack: wait until server is up
}

// Utility used by assertCommandOpenPort to know if a port is currently used. Used by assertCommandOpenPort. 
// Usage: isPortTaken(8080, function(isUsed){})
function isPortTaken(port, fn) 
{
 var net = require('net')
 var tester = net.createServer()
 .once('error', function (err) 
 {
  if (err.code != 'EADDRINUSE') 
  {
   return fn(false); 
  }
  fn(true);  
 })
 .once('listening', function() 
 {
  tester.once('close', function() { fn(false);  })
  .close()
 })
 .listen(port)
}

function curl(config)
{
 var http = require('http');

 var options = {
     host: config.host
 ,   path: config.path || '/'
 , port: config.port || 80
 }; 
 var request = http.request(options, function (res) 
 {
  var data = '';
  res.on('data', function (chunk) 
  {
   data += chunk;
  });
  res.on('end', function () 
  {
   config.dataHandler && config.dataHandler(data, res);
  });
 });
 request.on('error', function (e) 
 {
  config.errorHandler && config.errorHandler(e);
 });
 request.end();
}