CakePHP with NightwatchJS on Travis CI

After the release of Headless Chrome browser (v59+) most of the automation tools slowly started reducing the usage of Selenium, by replacing it with the combination of chromedriver + chrome/chromium pre-installed browser (like Travis CI does on their images).

As a replacement, I’ve tried playing around with the combination of Karma/Chai to test JavaScript functionality of certain projects we have in Qobo, which went well, but it only introduced the unit test approach towards the code base. What I wanted was user automation, emulating browsers Page Object Model (POM). The choice fell on NightwatchJS library that works with headless Chrome and needs only minor tweaking.

Setting up NightwatchJS

I’ve used a combination of NightwatchJS with Mocha test framework, but Nightwatch itself has a good support of assertion methods to do some basic checks on the browser requests, but first things first.

We start with package.json for Yarn/NPM.

{
  "devDependencies": {
    "chromedriver": "^2.31.0",
    "mocha": "^3.5.0",
    "nightwatch": "^0.9.16"
  },
  "scripts": {
    "test": "./node_modules/nightwatch/bin/nightwatch"
  }
}

yarn install and proceeding with nightwatch configurations:

const chromedriver = require('chromedriver');

module.exports = {
  before: function(done) {
    chromedriver.start();

    done();
  },

  after: function(done) {
    chromedriver.stop();

    done();
  }
};

After we explained the library how to handle chromedriver, we set the configurations for nightwatch.json:

{
  "src_folders": ["tests/Frontend"], 
  "output_folder": "build/coverage/",
  "custom_commands_path": "",
  "custom_assertions_path": "",
  "page_objects_path": "",
  "globals_path": "globals.js",
  "selenium": {
    "start_process": false
  },
  "test_runner": {
    "type": "mocha",
    "options": {
        "ui": "bdd",
        "reporter": "list"
    }
  },
  "test_settings": {
    "default": {
      "selenium_port": 9515,
      "selenium_host": "localhost",
      "default_path_prefix" : "",

      "desiredCapabilities": {
        "browserName": "chrome",
        "chromeOptions" : {
          "args" : ["--no-sandbox", "--headless", "--disable-gpu"]
        },
        "acceptSslCerts": true
      }
    }
  }
}

NightwatchJS still uses selenium_` naming options in the configurations (for backward compatibility reasons), so don’t get scared by the naming.

And the final touch, testing login action:

describe('Testing login UsersController::login() method', () => {
    var loginUrl = 'http://localhost:8000/login';

    before(function(browser, done) {
      done();
    });

    after(function(browser, done) {
      browser.end(function() {
        done();
      });
    });

    afterEach(function(browser, done) {
      done();
    });

    beforeEach(function(browser, done) {
      done();
    });

    it('gets [login] page', (browser) => {

        browser
            .url(loginUrl)
            .waitForElementVisible('.login-box').present;
    });

    it('trying to [login]', (browser) => {
        browser
            .url(loginUrl)
            .waitForElementVisible('.login-box', 2000)
            .assert.elementPresent('input#username')
            .setValue('input#username', 'username')
            .assert.elementPresent('input#password')
            .setValue('input#password', 'password')
            .submitForm('form')
            .pause(2000)
            .assert.elementPresent('nav');
    });
});

Running yarn test you should get something like this:

running nightwatchjs with yarn

NightwatchJS on Travis CI

Last but not the least – configuring Travis CI to run NightwatchJS on a PHP distro image. The config is partially pasted from project-template-cakephp , (pull request #340 with NightWatchJS).

sudo: true
dist: trusty

language: php

php:
    - 5.6
    - 7.0
    - 7.1
    - nightly

#enabling NodeJS
node_js:
  - "7"

#setting up stable Chrome, which has headless support 
#out of the box
addons:
  chrome: stable

#caching Yarn and its node_modules
cache:
  yarn: true
  directories:
    - node_modules

# installing JS packages and starting up the server
before_script:
    - yarn install
    - ./bin/phpserv >/dev/null 2>&1 &
    - sleep 5

# once you're done with PHPUnit/PHPCS,
# it's time to check the UI with `yarn test`
script:
  - ./vendor/bin/phpunit --group example
  - ./vendor/bin/phpunit --exclude-group example
  - ./vendor/bin/phpcs
  - yarn test

 

ES2015: Refresher on modern JavaScript

A quick lookup on modern JavaScript and whole Babel thing. This will be a start of a small research on splitting frontend and backend implementation for CakePHP framework and its plugin.

CakePHP: Interview with Larry E. Masters

Interesting interview with one of the core members of CakePHP community – Larry E. Masters.

Throughout the interview Larry covers CakePHP Framework history, as well as covering major milestones of CakePHP 3.x version. If you’re still into 2.x – it’s time to upgrade, as it brings some nice perks, more flexible code, and massive performance boost.

 

PHP: Testing protected methods in CakePHP3

One of the things I recently had to deal with – unit testing protected methods of the class. Few seconds of checking StackOverflow brought a nice and elegant way of checking protected methods using ReflectionClasses. Sebastian Bergmann has a complete guide on how to check non-public functionality of the classes in his archieves.

Here’s a short sample of the code using CakePHP3:

<?php

 use Search\Model\Table\SaveSearchTable;
 use Cake\TestSuite\TestCase;
 
 class SaveSearchTableTest extends TestCase
 {
    public function setUp()
    {
        $this->SavedSearches = \Cake\ORM\TableRegistry::get('SavedSearches');
    }
    
    public function testProtectedMethod()
    {
        $methodName = 'protectedMethod';
        
        $reflectionClass =  new \ReflectionClass('\Search\Model\Table\SaveSearchesTable');
        
        $method = $reflectionClass->getMethod($methodName);
        
        $methodResult = $method->invokeArgs( $this->SavedSearches, [
            'arg1',
            ['arg2']
        ]);
        
        $this->assertNotEmpty($methodResult);
    }
 }

 

CakeDC upgrades users plugin with Google Authenticator

Few days of work, and almost a month of waiting, but it was totally worth it. Yesterday noon, CakeDC community upgraded one of its major plugins, with our Qobo patch, that allows users to enable Google Authenticator functionality I wrote about previously. There’s no need anymore to use ‘dev-develop’ branches in composer.

 

Google Authenticator in CakePHP3.x

Google Authenticator gets a new wave of interest from the web community, trying to put an extra layer on top of user authentication process. There’s a plethora of plugins and components that let you authenticate with Google, but most of them aim to OAuth and Google+ integration. Two-step auth gets aside.

I took few hours on research for the simple 2FA library available on the net and found TwoFactorAuth that already support Google URI QR-codes, that can be easily embedded into any framework/application running on PHP.

CakePHP3.x Integration

With few minor modifications it nicely got integrated into CakePHP 3.x framework. If you’re using CakePHP 3.x, you can install ‘develop’ branch, of CakeDC/Users plugin, and enable two-factor authentication with few minor modifications.

 <?php
 //config/app.php or any other config file that suites your app
 Configure::write('GoogleAuthenticator.login', true);
 /*
 some other custom configs you might need
 'GoogleAuthenticator' => [
            //enable Google Authenticator
            'login' => false,
            'issuer' => null,
            // The number of digits the resulting codes will be
            'digits' => 6,
            // The number of seconds a code will be valid
            'period' => 30,
            // The algorithm used
            'algorithm' => 'sha1',
            // QR-code provider (more on this later)
            'qrcodeprovider' => null,
            // Random Number Generator provider (more on this later)
            'rngprovider' => null,
            // Key used for encrypting the user credentials, leave this false to use Security.salt
            'encryptionKey' => false
        ],
*/
?>

When you enable it the CakeDC/Users Google Authenticator feature, upon ‘/login’ you will ll be redirected to ‘/verify’, where you should insert your verification code from the mobile app (Google Authenticator for Android).

If you’re already sharing a secret key with the website/app, you won’t have to synchronize an app with it. Otherwise, you’ll have to scan it first, as it’s described in the documentation. QR-code will appear on the ‘/verify’ action of the app.

UPD: CakeDC/Users has upgraded the plugin to 4.x version, which enables Google Authenticator in the master repo.

Qobo: first month benchmark

It’s been already one month since I moved to Qobo Ltd, as a backend developer, so it’s about time to do some benchmarks on the work done.

Open-Source

The level of open source involvement of Qobo is enormous. All the projects I’ve been involved in before were always about open-source: it was either based on open-source, or using open-source solutions into some extend. Every time it ends up locking down the solutions for indoor use. It was either features the company didn’t want to share with the open-source community, or key business aspects that were crucial for competitive advantage. The story repeats over and over – the level of feedback to open source was minimal.

Contrarily, Qobo’s approach towards open-source is different. I didn’t do the exact measures, but it’s approximately 70-80% of code that goes to public repositories. Apart of advocating open-source within the company, we participate in other development communities, which helps us get things better. What’s the point of getting stuck with yet another closed-source plugin/module/library that others troubleshooted/patched and use everywhere. Examples? Well, it’s CakeDC community, CakePHP framework, WordPress, Bootstrap, and many others.

Side-effects of it:

  • You write better code (if you want to get things accepted in pull requests)
  • You stand on the shoulders of giants (community helps. Always)
  • Self-development (you’re not stuck with repetitive tasks)
Teams

Q: how many programmers does it take to change a light bulb?

A: none, that’s a hardware problem (c)

Small teams, dedicated to certain projects or split by the expertise in certain technology or business aspects. Mind blowing speed of deployment & accuracy. The most appropriate way of describing the social system and involvement in the projects would be meritocracy – “We do it, because we can”.

 

CakePHP 3 adopts PSR-2

Recently read this article from James Watts:

By adopting PSR-2 we can remove or reduce the code we maintain related to enforcing coding standards – as there are common tools, used by the rest of the community, to validate and revise CS issues, without requiring exceptions.

Looks like it’s time to re-write our internal modules with PSR-2 standards in mind, if we want to share them with open-source community.

Cakephp 2.x: failing Phing using CakePHP testsuites

Digging todays deployment scripts on CI (Continuous integration) machine, I’ve noted that no matter how many Unit tests fail, phing still thought that builds were successful. Teetering on the brink of a heart attack, I’ve started checking stage machines, and production systems, to get the prove of concept. Thankfully, the number of failed tests wasn’t too big, and patches were added shortly, but the issue remained.

It appeared that ExecTask of Phing (no matter how the script is ran), will return success, unless you start comparing the values outside of it. Solution was pretty obvious, but took some time to go through the documentation of Phing/PHPUnit/CakePHP: