[TOC]
# Angular Example
See this [blog article](http://blog.wuzzeb.org/posts/2013-12-16-yesod-and-angular.html) for the
reasoning behind how Angular is integrated into a Yesod application using this generator. This
example application follows exactly this outline via the following.
* The view consists of the Yesod handlers plus the widget hamlet/lucius/cassius. The widget files
are located in the `templates` directory exactly like in a scaffolded application and the Yesod
handlers are in `main.hs`. Note that the widget files do not use any julius.
* The Angular code and directive templates are in the `angular-app` directory, and this directory is
managed by `StaticSettings.hs`. `StaticSettings.hs` exports a variable of type `Route
EmbeddedStatic` named `ng_modules_example_js`. All the Yesod handlers have to do is reference
this one route. This Angular code must be written in a certian style for the generator to process
it correctly. The style is explained in detail in the haddock for
`Yesod.EmbeddedStatic.AngularJavascript`. The
[README.md](https://bitbucket.org/wuzzeb/yesod-static-generators/src/tip/angular/example/angular-app/README.md)
within the `angular-app` directory explains how the example application implemented these rules.
### Compiling and running the example
To compile the application, from the directory containing the .cabal file, run
~~~
cabal build example-dev
cabal build example-production
~~~
You can then run either one by
~~~
./dist/build/example-dev/example-dev
./dist/build/example-production/example-production
~~~
Note that in development mode, each javascript file in `angular-app` is served separately to help
with debugging. During production, a single javascript file containing all the code is served.
# Testing
A major goal of Angular is to make the code easy to test (as long as the right tools are in place).
Designing the application as mentioned above fits nicely with the available testing tools. See this
[blog post](http://blog.wuzzeb.org/posts/2013-12-17-testing-yesod-and-angular.html) for an
explination of the testing tools and the various types of testing that should be done.
### Karma
The example application has some karma tests of the Angular javascript code, located in the
`tests/unit-js` directory. To run the tests, the current directory must be the `tests` directory.
First, karma and the
[karma-ng-hamlet2js-preprocessor](https://npmjs.org/package/karma-ng-hamlet2js-preprocessor) must be
installed.
~~~
cd path/to/example/tests
npm install karma karma-ng-hamlet2js-preprocessor
~~~
(Could also install globally with the `-g` flag.) Now, if you have Firefox installed, the tests can
be run by:
~~~
./node_modules/karma/bin/karma start
~~~
Karma is configured via `karma.conf.js` and the test code itself is in `tests/unit-js`. The test
code uses [jasmine](http://pivotal.github.io/jasmine/). The test code is mostly normal
Angular/jasmine test code, with only two notable changes:
* The `angular-mock.js` file defines `window.module = angular.mock.module` as a shortcut and if you
search on google for examples you will see many tests using `beforeEach(module("modname"))`.
Since we use `window.module` inside `angular-app` to hold the actual Angular module, when writing
tests you will need to use `beforeEach(angular.mock.module("modname"))` inside the test code.
* The directive hamlet is loaded by the
[karma-ng-hamlet2js-preprocessor](https://npmjs.org/package/karma-ng-hamlet2js-preprocessor) karma preprocessor, which
is configured inside `karma.conf.js`.
### yesod-test
Since Angular is separate from from the handlers and routes, testing the Yesod handlers is identical
to using `yesod-test` on any other Yesod application. Therefore, the example application does not
include any tests of the Yesod handlers and routes using `yesod-test`.
### WebDriver
The example application has a small end to end test using
[webdriver](https://hackage.haskell.org/package/webdriver),
[webdriver-angular](https://hackage.haskell.org/package/webdriver-angular), and
[hspec-webdriver](https://hackage.haskell.org/package/hspec-webdriver). The tests are in the
`tests/end2end` directory. Before running them, you will first need to download
`selenium-server-standalone-<ver>.jar` from [here](http://code.google.com/p/selenium/downloads/list)
(or use a distro package). Also you will need to install the Java JRE, OpenJDK works fine. Start
the selenium server
~~~
java -jar selenium-server-standalone-<ver>.jar
~~~
Next you need to start the yesod application, I suggest you test against the version built for
production. In a scaffolded application, this is a good use for the `Staging` section of the config
file.
~~~
./dist/build/example-production/example-production
~~~
Finally, install [webdriver](http://hackage.haskell.org/package/webdriver),
[webdriver-angular](http://hackage.haskell.org/package/webdriver-angular), and
[hspec-webdriver](http://hackage.haskell.org/package/hspec-webdriver). Since the test code does not
reference any Haskell modules or javascript code from our project, I find it easiest to run the test
code from `ghci`. You could also call the test code from a test-suite section in the cabal file.
~~~
cd tests/end2end
ghci todo.hs
> main
~~~
If you use cabal sandboxes, you will need instead
~~~
ghci -package-db path/to/sandbox/i386-linux-ghc-7.6.3-packages.conf.d todo.hs
~~~
(of course the version and architecture might be different). You could also use `cabal repl` but
that also loads all the Haskell modules which are not needed for the `todo.hs` test code.