Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save egobude/762f94b8ae7736d10ed60274694cea0f to your computer and use it in GitHub Desktop.
Save egobude/762f94b8ae7736d10ed60274694cea0f to your computer and use it in GitHub Desktop.
Codeception, Laravel, and PhantomJS

You can use Codeception to test Javascript, like DOM manipulations and Ajax requests. Out of the box it can manipulate DOM elements but can't execute Javascript code, like most testing frameworks. But it gives you the option to use a WebDriver, to connect to a headless browser, and mimic a user browsing your website. It gives you some options: Selenium2, ZombieJS and, the easiest to configure, PhantomJS.

This article covers the installation and usage of PhantomJS, and assumes you are using Laravel Homestead, but it will work on any relatively new Debian based distro, like Ubuntu 14.04.

###Install PhantomJS

Just run those commands to install it:

sudo apt-get update
sudo apt-get install --yes phantomjs

If you are not using Homestead, make sure you are installing PhantomJS 1.8+, because the WebDriver Wire Protocol is not available on versions below this one. You can check PhantomJS version by executing:

phantomjs -v

###Execute PhantomJS GhostDriver

While testing, Codeception will try to connect to a headless browser on port 4444, so you'll need to keep PhantomJS running. To do that open a new terminal window, execute the command below and keep that window open:

phantomjs --webdriver=4444

###Configure your Test Suite

You basically have to add the WebDriver module to your test suite:

enabled: [..., WebDriver]

And rebuild your actor classes:

vendor/bin/codecept build

You need to add some other items to properly configure the WebDriver, here's a suite with everything set:

class_name: FunctionalTester
modules:
    enabled: [Filesystem, FunctionalHelper, Laravel4, Asserts, WebDriver]
    config:
          WebDriver:
             url: 'http://application.dev/'
             browser: phantomjs
             capabilities:
                          webStorageEnabled: true

The url item was a tricky one to me, because, when you access Homestead from your physical machine (browse), you use port 8000, but inside the Homestead virtual machine you would have to use it without that port (eg: http://localhost/), but this didn't worked for me so I had to add the host name to my Homestead VM's hosts file:

127.0.0.1 application.dev

###Setting up database access

In order to use the correct database for acceptance/functional tests: First, configure the database in the main codeception.yml file

modules:
    config:
        Db:
            dsn: 'mysql:host=localhost;dbname=acceptance_test_db'
            user: 'homestead'
            password: 'secret'
            dump: tests/_data/acceptance_test_dump.sql

Only 'localhost' works. Using 127.0.0.1:33060 will not connect correctly.

Then in the functional or acceptance testing configuration, enabled and configure the Laravel4 Module.

Example for acceptance.suite.yml

    enabled:
        - WebDriver
        - AcceptanceHelper
        - Laravel4
        - Db
    config:
        WebDriver:
            url: 'http://myapp.app'
            browser: phantomjs
            capabilities:
                webStorageEnabled: true
        Laravel4:
            environment: 'codeception'
            filters: true

Note that I chose to use the environment 'codeception'. Now, when the Laravel app runs, the env will be codeception. You can setup a new folder in app/config/codeception for codeception specific settings. Also create a file in the project folder called .env.codeception.php for specific codeception environment variables.

Finally, in the terminal run codecept build to update all of the configuration changes before running at test.

###Using It

Let's say you have a page wich requires authentication to do more stuff than simply browse it, and you have some Ajax requests built to improve user experience. Here's what you can now do:

Tell Codeception to go to a "items" page:

$I->amOnPage('/items');

It must see a particular item:

$I->seeElement('.item[data-id="1"]');

Click on an ajax link, which will redirect to the login page:

$I->click('.item[data-id="1"] .item-delete');

Tell Codeception to wait 10 seconds for a login button to appear on the page, using jQuery:

$I->waitForJs("return $('input[value=\"Sign In\"]').is(':visible');", 10);

Now it should be at /login:

$I->seeCurrentUrlEquals('/login');

Tell it to sign in:

$I->signIn();

Go to the items page:

$I->amOnPage('/items');

Check if the item element is present:

$I->seeElement('.item[data-id="1"]');

Click on a delete link:

$I->click('.item[data-id="1"] .item-delete');

Wait for the item to disappear:

$I->waitForJs("return $('.item').is(':hidden');", 10);

Reload the page, to make sure it was also removed from your database:

$I->reloadPage();

And it should not see it:

$I->dontSeeElement('.item[data-id="1"]');

Enjoy Codeception!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment