Blog

Jon Clausen

August 05, 2016

Spread the word


Share your thoughts

An incredibly powerful feature of ContentBox 3 is the increasing availability of open source themes to jump start your custom development.   For those wishing to contribute back to the community, creating your own theme is as simple as cloning one of our boilerplate themes, creating a new GitHub repo for your customizations, and publishing your theme on Forgebox.  

Inevitably, if your theme becomes popular one, others will want to contribute to the community.  Managing the process of pull requests and releases of your theme is greatly simplified with your own continuous integration pipeline.  Today we're going to look at how to set up Travis CI integration for your theme development, to ensure new commits and pull requests to your branches are fully vetted for quality.

In this case, we'll use the existing Asymmetry theme and set it up for travis testing.   In testing your theme, there are two critical areas we need to ensure are verified:

  1. The asset pipeline - using ColdBox Elixr or standalone Grunt or Gulp compilations.
  2. Your custom theme templates and layouts.

Preparing your Theme for Testing

In the case of the asset pipeline, this is as easy as installing NPM and running your compilation.  For the templates and layouts, you'll need to create a test site which utilizes each of those layouts and templates. First though, let's set up our directory structure:

  1. Create a workbench directory in your theme root (the actual name is up to you, but this is a convention we use regularly at Ortus so we'll use that here). We'll use this directory to store items we may need for the build, such as SQL scripts
  2. Create a tests directory for your suites in the theme root (you can place them anywhere, but the root makes it easy for CommandBox to scaffold them out)
  3. Create a TestProxy.cfc file and place it in the workbench directory, to allow your tests to extend the core application settings. We'll copy this later during the build to where it needs to go.  The contents of this file are simply:
    component extends="Application"{}
  4. Create a Travis build file (.travis.yml) in the root of  your project
  5. Copy your working ContentBox test Application.cfc to workbench/Application.cfc.txt, which will be used to auto-configure your Travis ContentBox build.

Create a Demo Site in ContentBox

The most time-consuming step of this process is creating a ContentBox test site which allows you to demo all of your layouts.  Once you've set up this site, simply export a backup of the database to your workbench folder, which we'll use during the build process going forward.  Don't forget to update this file as you develop new features for your theme.  From the root of your theme, to export a MySQL database, simply run:

mysqldump -u[YOUR USER NAME] -p[YOUR PASSWORD] -d [YOUR DATABASE NAME] > workbench/test-db.sql

Create Your Test Harness

First we'll need to create our runner.cfm and Application.cfc (AKA - Our test harness) within your tests directory.  You can grab a boilerplate copy of those files from any of the Coldbox Modules.  To keep things simple, here are the basic contents of those files:

Application.cfc:

component extends="TestProxy"{
    this.name = "ASYMMETRY-THEME-TESTHARNESS-" & hash( getCurrentTemplatePath() );
    this.sessionManagement = true;
    this.whiteSpaceManagement = "smart";

    // any mappings go here, we create one that points to the root called test.
    this.mappings[ "/tests" ] = getDirectoryFromPath( getCurrentTemplatePath() );
    rootPath = REReplaceNoCase( this.mappings[ "/tests" ], "/tests(\\|/)", "" );
    this.mappings[ "/root" ]   = rootPath;

    COLDBOX_APP_ROOT_PATH = rootPath & "/";
    // The web server mapping to this application. Used for remote purposes or static purposes
    COLDBOX_APP_MAPPING   = "/";
    COLDBOX_CONFIG_FILE      = "config.Coldbox";
    COLDBOX_APP_KEY          = "ASYMMETRY-THEME-TESTHARNESS";

    public boolean function onRequestStart( String targetPage ){
        return true;
    }
}

runner.cfm:

<cfsetting showDebugOutput="false">
<!--- Executes all tests in the 'specs' folder with simple reporter by default --->
<cfparam name="url.reporter"         default="simple">
<cfparam name="url.directory"         default="tests.specs">
<cfparam name="url.recurse"         default="true" type="boolean">
<cfparam name="url.bundles"         default="">
<cfparam name="url.labels"             default="">
<cfparam name="url.reportpath"         default="#expandPath( "/tests/results" )#">
<cfparam name="url.propertiesFilename"     default="TEST.properties">
<cfparam name="url.propertiesSummary"     default="false" type="boolean">

<!--- Include the TestBox HTML Runner --->
<cfinclude template="/testbox/system/runners/HTMLRunner.cfm" >

When preparing tests, you may choose to put all your tests in one file or, optimally, create a test spec for each template or layout.  To keep it simple, we'll use CommandBox to create one test spec for page layouts and one test spec for blogs, which we will use to test those layout groups.  We're using our integration test template, since we'll be running actual events to test our layout:

box coldbox create integration-test handler=BlogLayout directory=workbench/tests/specs/integration/layout
box coldbox create integration-test handler=PageLayout directory=workbench/tests/specs/integration/layout

 

No let's add a simple test for one of our pages.  Open your PageLayoutTest.cfc and replace the boilerplate describe() block with the following:

describe( "Performs tests on the page layout objects", function(){

    beforeEach(function( currentSpec ){
        // Setup as a new ColdBox request for this suite, VERY IMPORTANT. ELSE EVERYTHING LOOKS LIKE THE SAME REQUEST.
        setup();
    });

    it( "Tests the standard page layout", function(){
        URL.pageSlug="mypage";
        var event = execute( "page.index" );
        var rc = event.getCollection();
        expect( rc )
            .toBeStruct()
            .toHaveKey( "pageSlug" );
        expect( rc.pageSlug ).toBe( URL.pageSlug );
        structDelete( URL, "pageSlug" );

    });

});

No that we have at least one test to run, let's set up our Travis build so that we can perform these tests.

Create your Travis Build File

We're going to walk you through the process of some key steps in the build, omitting some of the basics.  If you haven't set up Travis integration previously, use this tutorial to get started.   For a completed build file, see here.

Travis Install Block:

We're going to test our asset pipeline and our layouts, so we'll need both CommandBox and NPM installed, along with all of our dependencies  Please make note of all of code comments in the script below:

install:
  # Commandbox and NPM Installation - Do this before we move our files so we can test compilation
  - sudo apt-get update && sudo apt-get --assume-yes install zip unzip commandbox nodejs npm
  - sudo npm install -g bower

  # Move our working root to a theme directory
  - mkdir asymmetry
  - mv !(asymmetry) asymmetry/
  # Make sure to copy our Git directory
  - mv .git asymmetry/
  # Copy our workbench directory up to the root
  - cp -ar asymmetry/workbench ./
  # Move our TestProxy up to the root
  - mv workbench/TestProxy.cfc ./

  # Dependency Setup
  - box install
  - box install contentbox
  - box install testbox
  # Move our pre-configured App.cfc up to the root of the site, replacing our install version
  - mv workbench/Application.cfc.txt ./Application.cfc
  # Move our theme files in to our ContentBox module
  - mv asymmetry ./modules/contentbox/themes/
  # Install our test database
  - mysql -u root -e 'create database contentbox;'
  # import database
  - mysql -u root contentbox < workbench/test-db.sql

  # Start up Commandbox
  - box server start port=49616 rewritesEnable=true openBrowser=false

If all goes according to plan, your ContentBox server will start up and your index page will be available to confirm your installation is up and running.

Travis Script Blocks:

Travis basically runs until it receives an exit code of greater than zero.  To test our build we simply run all of our standard scripts, using some regex goodness to check the output of our testbox results:

before_script:

  - curl http://localhost:49616/

script: > 
    cd ./modules/contentbox/themes/asymmetry && npm install;
    cd ./modules/contentbox/themes/asymmetry && bower install;
    cd ./modules/contentbox/themes/asymmetry && grunt --completion=bash;
    testResults="echo $(box testbox run runner=http://localhost:49616/workbench/tests/runner.cfm)";
    echo "$testResults";
    if grep -i "\[Failures: [1-9][0-9]\?[0-9]\?\]\|\[Errors: [1-9][0-9]\?[0-9]\?\]\|]*>\|]*>" <<< $testResults;  then exit 1; fi

 

That's it.  Once you publish your .travis.yml file, along with your setup files, you can configure Travis CI to run your builds on pushes to specific branches, pull request, and tags.

Auto Publishing

Remember how we make sure to copy the .git directory along with our module?  We can use this, along with CommandBox to publish new releases of your theme.  We'll save this for another post that discusses the use of SSH keys and different deployment options available.   Happy coding!

Add Your Comment

Recent Entries

ColdBox 7.2.0 Released

ColdBox 7.2.0 Released

ColdBox, a widely used development platform for ColdFusion (CFML), has unveiled version 7.2. Packed with compelling new features, bug fixes, and enhancements, this release is designed to empower developers by boosting productivity, refining scheduled task capabilities, and enhancing the overall reliability and efficiency of application development. This article will delve into the key highlights of ColdBox 7.2 and elucidate how these advancements can positively impact developers in their daily coding endeavors.

Luis Majano
Luis Majano
November 20, 2023
Into the Box 2023 Series on CFCast

Into the Box 2023 Series on CFCast

Excitement is in the air as we unleash the highly anticipated ITB 2023 series exclusively for our valued CFCast subscribers – and the best part? It's FREE for CFCast members! Now is the perfect time if you haven't joined the CFCast community yet. Plus, we've got an incredible End-of-Year deal that's too good to miss

Maria Jose Herrera
Maria Jose Herrera
November 20, 2023
Ortus Deals are Finally Here!

Ortus Deals are Finally Here!

The much-anticipated Ortus End-of-the-Year Sale has arrived, and it's time to elevate your development experience! Whether you're a seasoned developer, a tech enthusiast, or someone on the lookout for top-notch projects, Ortus has something special in store for you. Brace yourself for incredible discounts across a wide array of products and services, including Ortus annual events, books, cutting-edge services, and more.

Maria Jose Herrera
Maria Jose Herrera
November 15, 2023