Chapter 1 - Introduction and Overview
By John Lenz. 2016.
The full stack of client, server, testing, and deployment code all lives in a single repository. The following is a list of the pieces that make up this repository; each piece will be described in a future chapter. The overall design is influnced by the 12 factor app.
domain-data subdirectory contains a cabal library which is shared between the client and server. It contains the type definitions for the domain and business data, various pure data transformation code, and the Servant API. It is compiled both by GHC for the server and GHCJS for the client, so has minimal dependencies. It also has a small unit test suite written using hspec. This is described in Chapter 2.
datastorage subdirectory contains a cabal library for database operations and authorization. It is used only by the server and contains all the queries and database code for the server, as well as the checks that a user has permission to access the resources (authentication is handled elseware, the datastorage library just does authorization). The reason it is split out into its own library rather than as part of the server is that it has an extensive unit test suite written using hspec. The database and authorization is the one part of the server which requires extensive testing to make sure the queries work and permissions are properly granted and denied. Separating this into a library allows focused unit testing. This library is described in Chapter 2.
server subdirectory contains a cabal library and executable for the server. It implements the servant server, authentication, settings, and logging. The server has a small unit test built using hspec and hspec-wai. The server is described in Chapter 3.
domain-data library to share data types with the server. This library does not have a unit test; most complex business logic is moved to the
domain-data library and tested there, while DOM manipulation is better tested as part of the acceptance tests. The client is described as part of Chapter 4.
client build, including it as part of the static site. The result of the metalsmith build is a collection of static files which are served to the client at the main URL for the web application. The metalsmith site is described in Chapter 5.
A typical continuous delivery/deployment pipeline for web applications is
build -> unit test -> integrate -> acceptance test -> deploy
Acceptance testing is black-box testing where the tests interact with the full program/web site exactly as a user does. Acceptance testing will run the production build of the server and load the metalsmith static site into a real web browser such as Firefox and Chrome. The acceptance tests then click elements on the page, send keys, and make sure the DOM is as expected. Importantly, the only interaction the acceptance test has is via the browser.
Using the great tools webdriver and selenium, this is suprisingly easy. In only a few lines of code, you can open a page in real browsers, find elements on the page, click on them, and check their properties. In Haskell, this is via the webdriver and hspec-webdriver packages.
acceptance-test subdirectory contains a cabal executable project using
hspec-webdriver. Importantly, it does not depend on any other libraries so that it treats the website as a black box. The acceptance testing is described in Chapter 6.
A key principle of DevOps is that "Infrastructre is Code"; everything needed to build, unit test, integrate, acceptance test, and deploy is part of the source repository. The DevOps files include the