├── .bowerrc ├── .gitignore ├── Cakefile ├── README.md ├── app ├── assets │ ├── images │ │ └── .gitkeep │ └── index.html ├── collections │ └── .gitkeep ├── initialize.coffee ├── lib │ └── helpers.coffee ├── models │ └── .gitkeep ├── routers │ └── main.coffee └── views │ ├── index.coffee │ ├── styles │ ├── _base.styl │ └── application.styl │ └── templates │ └── .gitkeep ├── bower.json ├── brunch-config.coffee ├── generators ├── collection │ ├── collection.coffee.hbs │ └── generator.json ├── collection_test │ ├── collection_test.coffee.hbs │ └── generator.json ├── generator │ ├── generated_file.coffee.hbs │ ├── generator.json │ └── generator.json.hbs ├── model │ ├── generator.json │ └── model.coffee.hbs ├── model_test │ ├── generator.json │ └── model_test.coffee.hbs ├── module │ ├── generator.json │ └── view.coffee.hbs ├── style │ ├── generator.json │ └── style.styl.hbs ├── template │ ├── generator.json │ └── template.hbs.hbs ├── view │ ├── generator.json │ └── view.coffee.hbs └── view_test │ ├── generator.json │ └── view_test.coffee.hbs ├── package.json └── test ├── collections └── .gitkeep ├── helpers.coffee ├── karma.conf.coffee ├── models └── .gitkeep ├── routers └── main_test.coffee ├── vendor └── js │ ├── chai-backbone.js │ ├── chai-changes.js │ ├── chai-jquery.js │ ├── chai.js │ ├── sinon-chai.js │ └── sinon.js └── views └── index_test.coffee /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "bower_components" 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Numerous always-ignore extensions 2 | *.diff 3 | *.err 4 | *.orig 5 | *.log 6 | *.rej 7 | *.swo 8 | *.swp 9 | *.vi 10 | *~ 11 | *.sass-cache 12 | 13 | # OS or Editor folders 14 | .DS_Store 15 | .cache 16 | .project 17 | .settings 18 | .tmproj 19 | nbproject 20 | Thumbs.db 21 | 22 | # NPM packages folder. 23 | node_modules/ 24 | 25 | # Brunch folder for temporary files. 26 | tmp/ 27 | 28 | # Brunch output folder. 29 | public/ 30 | 31 | # Bower stuff. 32 | bower_components/ 33 | -------------------------------------------------------------------------------- /Cakefile: -------------------------------------------------------------------------------- 1 | util = require 'util' 2 | exec = (require 'child_process').exec 3 | server = (require 'karma').server 4 | 5 | task 'test', -> 6 | config = "#{__dirname}/test/karma.conf.coffee" 7 | server.start configFile: config, (exitCode) -> 8 | console.log "Karma has exited with #{exitCode}" 9 | process.exit exitCode 10 | 11 | task 'build:test', -> 12 | exec 'brunch b', (error, stdout, stderr) -> 13 | if stdout 14 | console.log stdout 15 | invoke 'test' 16 | else if stderr 17 | console.log stderr 18 | else if error 19 | console.log error 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Brunch with Hipsters 2 | 3 | ![image](http://www.latimes.com/media/photo/2011-07/63171841.jpg) 4 | 5 | Brunch with Hipsters is a rad [Brunch](http://brunch.io/) app skeleton that comes with unicorns out of the box. Take a look at [Hackerank (an example app)](https://github.com/elving/Hackerank) to see how it works. Brunch with Hipsters was awesome before awesome was awesome. 6 | 7 | ## Languages 8 | 9 | - [CoffeeScript](http://coffeescript.org/) 10 | - [Stylus](http://learnboost.github.com/stylus/) 11 | - [Handlebars](http://handlebarsjs.com/) 12 | 13 | ## Features 14 | 15 | - [jQuery](https://github.com/jquery/jquery) 16 | - [Lodash](https://github.com/bestiejs/lodash) 17 | - [Backbone](https://github.com/jashkenas/backbone) 18 | - [Swag](https://github.com/elving/swag) 19 | - [Font Awesome](https://github.com/FortAwesome/Font-Awesome) 20 | - [HTML5 Boilerplate Helpers](https://github.com/h5bp/html5-boilerplate) 21 | 22 | ## Plugins 23 | 24 | - [Brunch Auto-Reload](https://github.com/brunch/auto-reload-brunch) 25 | - [Coffeelint](https://github.com/ilkosta/coffeelint-brunch) 26 | - [imageoptimizer-brunch](https://github.com/steffenmllr/imageoptmizer-brunch) 27 | 28 | ## Getting started 29 | 30 | $ brunch new git@github.com:elving/brunch-with-hipsters.git 31 | $ brunch w -s 32 | 33 | or 34 | 35 | $ git clone git@github.com:elving/brunch-with-hipsters.git 36 | $ npm install 37 | $ bower install 38 | $ brunch w -s 39 | 40 | or 41 | 42 | $ git clone git@github.com:elving/brunch-with-hipsters.git && npm install && $ bower install && brunch w -s 43 | 44 | ## Generators 45 | 46 | First install [scaffolt](https://github.com/paulmillr/scaffolt#readme): 47 | 48 | npm install -g scaffolt 49 | 50 | Then you can use the following commands to generate files: 51 | 52 | scaffolt view 53 | → app/views/name.coffee 54 | → test/views/name_test.coffee 55 | 56 | scaffolt model 57 | → app/models/name.coffee 58 | → test/models/name_test.coffee 59 | 60 | scaffolt style 61 | → app/views/styles/name.styl 62 | 63 | scaffolt template 64 | → app/views/templates/name.hbs 65 | 66 | scaffolt collection 67 | → app/collections/name.coffee 68 | → test/collections/name_test.coffee 69 | 70 | scaffolt module 71 | → app/views/name.coffee 72 | → test/views/name_test.coffee 73 | → app/models/name.coffee 74 | → test/models/name_test.coffee 75 | → app/views/styles/name.styl 76 | → app/views/templates/name.hbs 77 | 78 | ## Testing 79 | 80 | To run your tests using [Karma](https://github.com/karma-runner) you will need to install [phantomjs](https://github.com/ariya/phantomjs): 81 | 82 | brew update && brew install phantomjs 83 | 84 | Run the tests: 85 | 86 | cake test 87 | 88 | Build and test your app: 89 | 90 | cake build:test 91 | 92 | You can change Karma's configuration by editing `test/karma.conf.coffee` and add any test helpers by editing `test/helpers.coffee`. 93 | 94 | 95 | [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/elving/brunch-with-hipsters/trend.png)](https://bitdeli.com/free "Bitdeli Badge") 96 | 97 | -------------------------------------------------------------------------------- /app/assets/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elving/brunch-with-hipsters/610eb0b21b3eaf7faa1d03174fd4b8b390de0469/app/assets/images/.gitkeep -------------------------------------------------------------------------------- /app/assets/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 |

Brunch with Hipsters

27 |
28 | 29 | 30 | 31 | 32 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /app/collections/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elving/brunch-with-hipsters/610eb0b21b3eaf7faa1d03174fd4b8b390de0469/app/collections/.gitkeep -------------------------------------------------------------------------------- /app/initialize.coffee: -------------------------------------------------------------------------------- 1 | # Load App Helpers 2 | require 'lib/helpers' 3 | 4 | # Initialize Router 5 | require 'routers/main' 6 | 7 | $ -> 8 | # Initialize Backbone History 9 | Backbone.history.start pushState: yes 10 | -------------------------------------------------------------------------------- /app/lib/helpers.coffee: -------------------------------------------------------------------------------- 1 | # Tell Swag where to look for partials 2 | Swag.Config.partialsPath = '../views/templates/' 3 | Swag.registerHelpers() 4 | 5 | # Put your handlebars.js helpers here. 6 | -------------------------------------------------------------------------------- /app/models/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elving/brunch-with-hipsters/610eb0b21b3eaf7faa1d03174fd4b8b390de0469/app/models/.gitkeep -------------------------------------------------------------------------------- /app/routers/main.coffee: -------------------------------------------------------------------------------- 1 | class MainRouter extends Backbone.Router 2 | routes: 3 | '': 'index' 4 | 5 | index: -> 6 | IndexView = require 'views/index' 7 | index = new IndexView() 8 | 9 | main = new MainRouter() 10 | module.exports = main 11 | -------------------------------------------------------------------------------- /app/views/index.coffee: -------------------------------------------------------------------------------- 1 | module.exports = class IndexView extends Backbone.View 2 | initialize: -> console.log 'Index View' 3 | -------------------------------------------------------------------------------- /app/views/styles/_base.styl: -------------------------------------------------------------------------------- 1 | // http://paulirish.com/2012/box-sizing-border-box-ftw/ 2 | * { box-sizing: border-box; } 3 | 4 | html, 5 | body 6 | height 100% 7 | width 100% 8 | 9 | body, 10 | input 11 | font-family "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", sans-serif 12 | font-weight 300 13 | text-rendering optimizeLegibility 14 | -------------------------------------------------------------------------------- /app/views/styles/application.styl: -------------------------------------------------------------------------------- 1 | @import 'nib' 2 | @import '_base' 3 | 4 | -------------------------------------------------------------------------------- /app/views/templates/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elving/brunch-with-hipsters/610eb0b21b3eaf7faa1d03174fd4b8b390de0469/app/views/templates/.gitkeep -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-app", 3 | "version": "0.1.0", 4 | "main": "public/javascripts/app.js", 5 | "ignore": [ 6 | "**/.*", 7 | "node_modules", 8 | "bower_components" 9 | ], 10 | "dependencies": { 11 | "swag": "~0.5.0", 12 | "lodash": "~2", 13 | "jquery": "~2", 14 | "backbone": "~1", 15 | "normalize-css": "~2", 16 | "h5bp-helpers": "~0.1", 17 | "font-awesome": "~4" 18 | }, 19 | "overrides": { 20 | "backbone": { 21 | "main": "backbone.js", 22 | "dependencies": { 23 | "lodash": "*", 24 | "jquery": "*" 25 | } 26 | }, 27 | "font-awesome": { 28 | "main": ["fonts", "css"] 29 | }, 30 | "swag": { 31 | "dependencies": {} 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /brunch-config.coffee: -------------------------------------------------------------------------------- 1 | exports.config = 2 | files: 3 | javascripts: 4 | joinTo: 5 | 'js/app.js': /^(vendor|bower_components|app)/ 6 | 7 | order: 8 | after: ['bower_components/swag/lib/swag.js'] 9 | 10 | pluginHelpers: 'js/app.js' 11 | 12 | stylesheets: 13 | joinTo: 14 | 'css/app.css': /^(vendor|bower_components|app)/ 15 | 16 | templates: 17 | joinTo: 'js/app.js' 18 | 19 | plugins: 20 | autoReload: 21 | enabled: 22 | js: on 23 | css: on 24 | assets: off 25 | 26 | imageoptimizer: 27 | path: 'images' 28 | smushit: no 29 | 30 | coffeelint: 31 | pattern: /^app\/.*\.coffee$/ 32 | 33 | options: 34 | indentation: 35 | value: 4 36 | level: "warn" 37 | 38 | max_line_length: 39 | level: "ignore" 40 | 41 | conventions: 42 | assets: /(assets|vendor\/assets|font)/ 43 | -------------------------------------------------------------------------------- /generators/collection/collection.coffee.hbs: -------------------------------------------------------------------------------- 1 | module.exports = class {{#camelize}}{{pluralName}}{{/camelize}}Collection extends Backbone.Collection 2 | model: require 'models/{{name}}' 3 | -------------------------------------------------------------------------------- /generators/collection/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "collection.coffee.hbs", 4 | "to": "app/collections/{{pluralName}}.coffee" 5 | }], 6 | "dependencies": [{ 7 | "name": "collection_test", 8 | "params": "{{pluralName}}" 9 | }] 10 | } 11 | -------------------------------------------------------------------------------- /generators/collection_test/collection_test.coffee.hbs: -------------------------------------------------------------------------------- 1 | {{#camelize}}{{pluralName}}{{/camelize}}Collection = require 'collections/{{pluralName}}' 2 | 3 | describe '{{#camelize}}{{pluralName}}{{/camelize}}Collection', -> 4 | beforeEach -> 5 | @collection = new {{#camelize}}{{pluralName}}{{/camelize}}Collection() 6 | 7 | it 'should exist', -> 8 | expect(@collection).to.be.ok 9 | -------------------------------------------------------------------------------- /generators/collection_test/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "collection_test.coffee.hbs", 4 | "to": "test/collections/{{pluralName}}_test.coffee" 5 | }], 6 | 7 | "dependencies": [] 8 | } 9 | -------------------------------------------------------------------------------- /generators/generator/generated_file.coffee.hbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elving/brunch-with-hipsters/610eb0b21b3eaf7faa1d03174fd4b8b390de0469/generators/generator/generated_file.coffee.hbs -------------------------------------------------------------------------------- /generators/generator/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "generator.json.hbs", 4 | "to": "generators/{{name}}/generator.json" 5 | }, 6 | { 7 | "from": "generated_file.coffee.hbs", 8 | "to": "generators/{{name}}/{{name}}.coffee.hbs" 9 | }], 10 | 11 | "dependencies": [] 12 | } 13 | -------------------------------------------------------------------------------- /generators/generator/generator.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "{{name}}.coffee.hbs", 4 | "to": "app/file.coffee" 5 | }], 6 | 7 | "dependencies": [] 8 | } 9 | -------------------------------------------------------------------------------- /generators/model/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "model.coffee.hbs", 4 | "to": "app/models/{{name}}.coffee" 5 | }], 6 | 7 | "dependencies": [{ 8 | "name": "model_test", 9 | "params": "{{name}}" 10 | }] 11 | } 12 | -------------------------------------------------------------------------------- /generators/model/model.coffee.hbs: -------------------------------------------------------------------------------- 1 | module.exports = class {{#camelize}}{{name}}{{/camelize}}Model extends Backbone.Model 2 | -------------------------------------------------------------------------------- /generators/model_test/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "model_test.coffee.hbs", 4 | "to": "test/models/{{name}}_test.coffee" 5 | }], 6 | 7 | "dependencies": [] 8 | } 9 | -------------------------------------------------------------------------------- /generators/model_test/model_test.coffee.hbs: -------------------------------------------------------------------------------- 1 | {{#camelize}}{{name}}{{/camelize}}Model = require 'models/{{name}}' 2 | 3 | describe '{{#camelize}}{{name}}{{/camelize}}Model', -> 4 | beforeEach -> 5 | @model = new {{#camelize}}{{name}}{{/camelize}}Model() 6 | 7 | it 'should exist', -> 8 | expect(@model).to.be.ok 9 | -------------------------------------------------------------------------------- /generators/module/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "view.coffee.hbs", 4 | "to": "app/views/{{name}}.coffee" 5 | }], 6 | 7 | "dependencies": [{ 8 | "name": "model", 9 | "params": "{{name}}" 10 | }, { 11 | "name": "view_test", 12 | "params": "{{name}}" 13 | }, { 14 | "name": "style", 15 | "params": "{{name}}" 16 | }, { 17 | "name": "template", 18 | "params": "{{name}}" 19 | }] 20 | } 21 | -------------------------------------------------------------------------------- /generators/module/view.coffee.hbs: -------------------------------------------------------------------------------- 1 | {{#camelize}}{{name}}{{/camelize}}Model = require '../models/{{name}}' 2 | 3 | module.exports = class {{#camelize}}{{name}}{{/camelize}}View extends Backbone.View 4 | model: new {{#camelize}}{{name}}{{/camelize}}Model() 5 | -------------------------------------------------------------------------------- /generators/style/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "style.styl.hbs", 4 | "to": "app/views/styles/_{{name}}.styl" 5 | }], 6 | 7 | "dependencies": [] 8 | } 9 | -------------------------------------------------------------------------------- /generators/style/style.styl.hbs: -------------------------------------------------------------------------------- 1 | // {{#camelize}}{{name}}{{/camelize}} 2 | 3 | .{{name}} 4 | -------------------------------------------------------------------------------- /generators/template/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "template.hbs.hbs", 4 | "to": "app/views/templates/{{name}}.hbs" 5 | }], 6 | 7 | "dependencies": [] 8 | } 9 | -------------------------------------------------------------------------------- /generators/template/template.hbs.hbs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /generators/view/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "view.coffee.hbs", 4 | "to": "app/views/{{name}}.coffee" 5 | }], 6 | 7 | "dependencies": [{ 8 | "name": "view_test", 9 | "params": "{{name}}" 10 | }] 11 | } 12 | -------------------------------------------------------------------------------- /generators/view/view.coffee.hbs: -------------------------------------------------------------------------------- 1 | module.exports = class {{#camelize}}{{name}}{{/camelize}}View extends Backbone.View 2 | className: '{{name}}' 3 | -------------------------------------------------------------------------------- /generators/view_test/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "view_test.coffee.hbs", 4 | "to": "test/views/{{name}}_test.coffee" 5 | }], 6 | 7 | "dependencies": [] 8 | } 9 | -------------------------------------------------------------------------------- /generators/view_test/view_test.coffee.hbs: -------------------------------------------------------------------------------- 1 | {{#camelize}}{{name}}{{/camelize}}View = require 'views/{{name}}' 2 | 3 | describe '{{#camelize}}{{name}}{{/camelize}}View', -> 4 | beforeEach -> 5 | @view = new {{#camelize}}{{name}}{{/camelize}}View() 6 | 7 | it 'should exist', -> 8 | expect(@view).to.be.ok 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Your Name", 3 | "name": "package-name", 4 | "description": "Package description", 5 | "version": "0.0.1", 6 | "homepage": "", 7 | "repository": { 8 | "type": "git", 9 | "url": "" 10 | }, 11 | "engines": { 12 | "node": "0.8 || 0.9 || 0.10" 13 | }, 14 | "scripts": { 15 | "test": "cake build:test", 16 | "start": "brunch watch --server" 17 | }, 18 | "dependencies": { 19 | "javascript-brunch": ">= 1.0 < 1.8", 20 | "coffee-script-brunch": ">= 1.0 < 1.8", 21 | 22 | "css-brunch": ">= 1.0 < 1.8", 23 | "stylus-brunch": ">= 1.0 < 1.8", 24 | 25 | "handlebars-brunch": ">= 1.0 < 1.8", 26 | 27 | "uglify-js-brunch": ">= 1.0 < 1.8", 28 | "clean-css-brunch": ">= 1.0 < 1.8", 29 | 30 | "coffeelint-brunch": ">= 1.0 < 1.8", 31 | "imageoptmizer-brunch": "~0.0.3", 32 | "auto-reload-brunch": ">= 1.0 < 1.8" 33 | }, 34 | "devDependencies": { 35 | "karma": "~0.10", 36 | "karma-mocha": "~0.1", 37 | "karma-safari-launcher": "~0.1", 38 | "karma-chrome-launcher": "~0.1", 39 | "karma-firefox-launcher": "~0.1", 40 | "karma-phantomjs-launcher": "~0.1", 41 | "karma-coffee-preprocessor": "~0.1" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /test/collections/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elving/brunch-with-hipsters/610eb0b21b3eaf7faa1d03174fd4b8b390de0469/test/collections/.gitkeep -------------------------------------------------------------------------------- /test/helpers.coffee: -------------------------------------------------------------------------------- 1 | # Create `window.describe` etc. for our BDD-like tests. 2 | mocha.setup ui: 'bdd' 3 | 4 | # Create another global variable for simpler syntax. 5 | window.expect = chai.expect 6 | -------------------------------------------------------------------------------- /test/karma.conf.coffee: -------------------------------------------------------------------------------- 1 | # Karma configuration 2 | 3 | module.exports = (config) -> 4 | config.set 5 | # base path, that will be used to resolve files and exclude 6 | basePath: '../' 7 | 8 | # list of files / patterns to load in the browser 9 | files: [ 10 | 'public/js/vendor.js' 11 | 'public/js/app.js' 12 | 13 | 'test/vendor/js/chai.js' 14 | 'test/vendor/js/sinon.js' 15 | 16 | 'test/vendor/js/chai-jquery.js' 17 | 'test/vendor/js/chai-changes.js' 18 | 'test/vendor/js/chai-backbone.js' 19 | 'test/vendor/js/sinon-chai.js' 20 | 21 | 'test/helpers.coffee' 22 | 'test/**/*_test.coffee' 23 | ] 24 | 25 | # web server port 26 | port: 8080 27 | 28 | # cli runner port 29 | runnerPort: 9100 30 | 31 | # enable / disable colors in the output (reporters and logs) 32 | colors: yes 33 | 34 | # level of logging 35 | # possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG 36 | logLevel: config.LOG_INFO 37 | 38 | # enable / disable watching file and executing tests whenever any file changes 39 | autoWatch: no 40 | 41 | # Start these browsers, currently available: 42 | # - Chrome 43 | # - ChromeCanary 44 | # - Firefox 45 | # - Opera 46 | # - Safari 47 | # - PhantomJS 48 | browsers: ['PhantomJS'] 49 | 50 | # Continuous Integration mode 51 | # if true, it capture browsers, run tests and exit 52 | singleRun: yes 53 | 54 | # compile coffee scripts 55 | preprocessors: '**/*.coffee': 'coffee' 56 | 57 | frameworks: ['mocha'] 58 | 59 | plugins: [ 60 | 'karma-mocha', 61 | 'karma-coffee-preprocessor', 62 | 'karma-phantomjs-launcher', 63 | 'karma-chrome-launcher', 64 | 'karma-firefox-launcher', 65 | 'karma-safari-launcher' 66 | ] 67 | -------------------------------------------------------------------------------- /test/models/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elving/brunch-with-hipsters/610eb0b21b3eaf7faa1d03174fd4b8b390de0469/test/models/.gitkeep -------------------------------------------------------------------------------- /test/routers/main_test.coffee: -------------------------------------------------------------------------------- 1 | describe 'Main', -> 2 | before -> 3 | @main = require 'routers/main' 4 | 5 | it 'should exist', -> 6 | expect(@main).to.be.ok 7 | 8 | it 'should route to `index` when navigating to /', -> 9 | expect('/').to.route.to @main, 'index', arguments: [] 10 | -------------------------------------------------------------------------------- /test/vendor/js/chai-backbone.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.4.0 2 | (function() { 3 | 4 | (function(chaiBackbone) { 5 | if (typeof require === "function" && typeof exports === "object" && typeof module === "object") { 6 | return module.exports = chaiBackbone; 7 | } else if (typeof define === "function" && define.amd) { 8 | return define(function() { 9 | return chaiBackbone; 10 | }); 11 | } else { 12 | return chai.use(chaiBackbone); 13 | } 14 | })(function(chai, utils) { 15 | var flag, inspect, routeTo; 16 | inspect = utils.inspect; 17 | flag = utils.flag; 18 | chai.Assertion.addMethod('trigger', function(trigger, options) { 19 | var definedActions; 20 | if (options == null) { 21 | options = {}; 22 | } 23 | definedActions = flag(this, 'whenActions') || []; 24 | definedActions.push({ 25 | negate: flag(this, 'negate'), 26 | before: function(context) { 27 | this.callback = sinon.spy(); 28 | return flag(context, 'object').on(trigger, this.callback); 29 | }, 30 | after: function(context) { 31 | var negate, _ref; 32 | negate = flag(context, 'negate'); 33 | flag(context, 'negate', this.negate); 34 | context.assert(this.callback.called, "expected to trigger " + trigger, "expected not to trigger " + trigger); 35 | if (options["with"] != null) { 36 | context.assert((_ref = this.callback).calledWith.apply(_ref, options["with"]), "expected trigger to be called with " + (inspect(options["with"])) + ", but was called with " + (inspect(this.callback.args[0])) + ".", "expected trigger not to be called with " + (inspect(options["with"])) + ", but was"); 37 | } 38 | return flag(context, 'negate', negate); 39 | } 40 | }); 41 | return flag(this, 'whenActions', definedActions); 42 | }); 43 | chai.Assertion.addProperty('route', function() { 44 | return flag(this, 'routing', true); 45 | }); 46 | routeTo = function(router, methodName, options) { 47 | var consideredRouter, current_history, route, stub, _i, _len, _ref; 48 | if (options == null) { 49 | options = {}; 50 | } 51 | if (!((typeof router === 'object') && (router instanceof Backbone.Router))) { 52 | throw new TypeError('provided router is not a Backbone.Router'); 53 | } 54 | current_history = Backbone.history; 55 | Backbone.history = new Backbone.History; 56 | stub = sinon.stub(router, methodName); 57 | router._bindRoutes(); 58 | if (options.considering != null) { 59 | _ref = options.considering; 60 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 61 | consideredRouter = _ref[_i]; 62 | consideredRouter._bindRoutes(); 63 | } 64 | } 65 | Backbone.history.options = { 66 | root: '/' 67 | }; 68 | route = flag(this, 'object'); 69 | Backbone.history.loadUrl(route); 70 | Backbone.history = current_history; 71 | router[methodName].restore(); 72 | this.assert(stub.calledOnce, "expected `" + route + "` to route to " + methodName, "expected `" + route + "` not to route to " + methodName); 73 | if (options["arguments"] != null) { 74 | return this.assert(stub.calledWith.apply(stub, options["arguments"]), "expected `" + methodName + "` to be called with " + (inspect(options["arguments"])) + ", but was called with " + (inspect(stub.args[0])) + " instead", "expected `" + methodName + "` not to be called with " + (inspect(options["arguments"])) + ", but was"); 75 | } 76 | }; 77 | chai.Assertion.overwriteProperty('to', function(_super) { 78 | return function() { 79 | if (flag(this, 'routing')) { 80 | return routeTo; 81 | } else { 82 | return _super.apply(this, arguments); 83 | } 84 | }; 85 | }); 86 | return chai.Assertion.addMethod('call', function(methodName) { 87 | var definedActions, object; 88 | object = flag(this, 'object'); 89 | definedActions = flag(this, 'whenActions') || []; 90 | definedActions.push({ 91 | negate: flag(this, 'negate'), 92 | before: function(context) { 93 | this.originalMethod = object[methodName]; 94 | this.spy = sinon.spy(); 95 | object[methodName] = this.spy; 96 | return typeof object.delegateEvents === "function" ? object.delegateEvents() : void 0; 97 | }, 98 | after: function(context) { 99 | object[methodName] = this.originalMethod; 100 | if (typeof object.delegateEvents === "function") { 101 | object.delegateEvents(); 102 | } 103 | return context.assert(this.spy.callCount > 0, this.spy.printf("expected %n to have been called at least once"), this.spy.printf("expected %n to not have been called")); 104 | } 105 | }); 106 | return flag(this, 'whenActions', definedActions); 107 | }); 108 | }); 109 | 110 | }).call(this); 111 | -------------------------------------------------------------------------------- /test/vendor/js/chai-changes.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.3.3 2 | (function() { 3 | 4 | (function(chaiChanges) { 5 | if (typeof require === "function" && typeof exports === "object" && typeof module === "object") { 6 | return module.exports = chaiChanges; 7 | } else if (typeof define === "function" && define.amd) { 8 | return define(function() { 9 | return chaiChanges; 10 | }); 11 | } else { 12 | return chai.use(chaiChanges); 13 | } 14 | })(function(chai, utils) { 15 | var byAtLeast, byAtMost, changeBy, changeByAssert, changeFrom, changeFromAssert, changeFromBeginAssert, changeTo, changeToAssert, changeToBeginAssert, flag, formatFunction, inspect, noChangeAssert; 16 | inspect = utils.inspect; 17 | flag = utils.flag; 18 | chai.Assertion.addMethod('when', function(val, options) { 19 | var action, definedActions, done, isPromise, newPromise, object, promiseCallback, result, _i, _j, _len, _len1, 20 | _this = this; 21 | if (options == null) { 22 | options = {}; 23 | } 24 | definedActions = flag(this, 'whenActions') || []; 25 | object = flag(this, 'object'); 26 | flag(this, 'whenObject', object); 27 | for (_i = 0, _len = definedActions.length; _i < _len; _i++) { 28 | action = definedActions[_i]; 29 | if (typeof action.before === "function") { 30 | action.before(this); 31 | } 32 | } 33 | result = val(); 34 | isPromise = (typeof result === 'object') && (typeof result.then === 'function'); 35 | if (isPromise) { 36 | done = options != null ? options.notify : void 0; 37 | if (done == null) { 38 | done = function() {}; 39 | } 40 | promiseCallback = function() { 41 | var _j, _len1; 42 | try { 43 | for (_j = 0, _len1 = definedActions.length; _j < _len1; _j++) { 44 | action = definedActions[_j]; 45 | if (typeof action.after === "function") { 46 | action.after(_this); 47 | } 48 | } 49 | return done(); 50 | } catch (error) { 51 | done(error); 52 | throw error; 53 | } 54 | }; 55 | newPromise = result.then(promiseCallback, promiseCallback); 56 | return newPromise; 57 | } else { 58 | for (_j = 0, _len1 = definedActions.length; _j < _len1; _j++) { 59 | action = definedActions[_j]; 60 | if (typeof action.after === "function") { 61 | action.after(this); 62 | } 63 | } 64 | } 65 | return this; 66 | }); 67 | noChangeAssert = function(context) { 68 | var endValue, negate, object, relevant, result, startValue; 69 | relevant = flag(context, 'no-change'); 70 | if (!relevant) { 71 | return; 72 | } 73 | negate = flag(context, 'negate'); 74 | flag(context, 'negate', this.negate); 75 | object = flag(context, 'whenObject'); 76 | startValue = flag(context, 'changeStart'); 77 | endValue = object(); 78 | result = !utils.eql(endValue, startValue); 79 | context.assert(result, "expected `" + (formatFunction(object)) + "` to change, but it stayed " + (utils.inspect(startValue)), "expected `" + (formatFunction(object)) + "` not to change, but it changed from " + (utils.inspect(startValue)) + " to " + (utils.inspect(endValue))); 80 | return flag(context, 'negate', negate); 81 | }; 82 | changeByAssert = function(context) { 83 | var actualDelta, endValue, negate, object, startValue; 84 | negate = flag(context, 'negate'); 85 | flag(context, 'negate', this.negate); 86 | object = flag(context, 'whenObject'); 87 | startValue = flag(context, 'changeStart'); 88 | endValue = object(); 89 | actualDelta = endValue - startValue; 90 | context.assert(this.expectedDelta === actualDelta, "expected `" + (formatFunction(object)) + "` to change by " + this.expectedDelta + ", but it changed by " + actualDelta, "expected `" + (formatFunction(object)) + "` not to change by " + this.expectedDelta + ", but it did"); 91 | return flag(context, 'negate', negate); 92 | }; 93 | changeToBeginAssert = function(context) { 94 | var negate, object, result, startValue; 95 | negate = flag(context, 'negate'); 96 | flag(context, 'negate', this.negate); 97 | object = flag(context, 'whenObject'); 98 | startValue = object(); 99 | flag(context, 'changeToStart', startValue); 100 | result = !utils.eql(startValue, this.expectedEndValue); 101 | if (negate) { 102 | result = !result; 103 | } 104 | context.assert(result, "expected `" + (formatFunction(object)) + "` to change to " + (utils.inspect(this.expectedEndValue)) + ", but it was already " + (utils.inspect(startValue)), "not supported"); 105 | return flag(context, 'negate', negate); 106 | }; 107 | changeToAssert = function(context) { 108 | var changed, endValue, negate, object, result, startValue; 109 | negate = flag(context, 'negate'); 110 | flag(context, 'negate', this.negate); 111 | object = flag(context, 'whenObject'); 112 | startValue = flag(context, 'changeToStart'); 113 | endValue = object(); 114 | if (!negate) { 115 | changed = !utils.eql(startValue, endValue); 116 | context.assert(changed, "expected `" + (formatFunction(object)) + "` to change to " + (utils.inspect(this.expectedEndValue)) + ", but it did not change from " + (utils.inspect(startValue)), "not supported"); 117 | } 118 | result = utils.eql(endValue, this.expectedEndValue); 119 | context.assert(result, "expected `" + (formatFunction(object)) + "` to change to " + (utils.inspect(this.expectedEndValue)) + ", but it changed to " + (utils.inspect(endValue)), "expected `" + (formatFunction(object)) + "` not to change to " + (utils.inspect(this.expectedEndValue)) + ", but it did"); 120 | return flag(context, 'negate', negate); 121 | }; 122 | changeFromBeginAssert = function(context) { 123 | var negate, object, result, startValue; 124 | negate = flag(context, 'negate'); 125 | flag(context, 'negate', this.negate); 126 | object = flag(context, 'whenObject'); 127 | startValue = object(); 128 | result = utils.eql(startValue, this.expectedStartValue); 129 | context.assert(result, "expected the change of `" + (formatFunction(object)) + "` to start from " + (utils.inspect(this.expectedStartValue)) + ", but it started from " + (utils.inspect(startValue)), "expected the change of `" + (formatFunction(object)) + "` not to start from " + (utils.inspect(this.expectedStartValue)) + ", but it did"); 130 | return flag(context, 'negate', negate); 131 | }; 132 | changeFromAssert = function(context) { 133 | var endValue, negate, object, result, startValue; 134 | negate = flag(context, 'negate'); 135 | flag(context, 'negate', this.negate); 136 | object = flag(context, 'whenObject'); 137 | startValue = flag(context, 'changeStart'); 138 | endValue = object(); 139 | result = !utils.eql(startValue, endValue); 140 | if (negate) { 141 | result = !result; 142 | } 143 | context.assert(result, "expected `" + (formatFunction(object)) + "` to change from " + (utils.inspect(this.expectedStartValue)) + ", but it did not change", "not supported"); 144 | return flag(context, 'negate', negate); 145 | }; 146 | chai.Assertion.addProperty('change', function() { 147 | var definedActions; 148 | flag(this, 'no-change', true); 149 | definedActions = flag(this, 'whenActions') || []; 150 | definedActions.push({ 151 | negate: flag(this, 'negate'), 152 | before: function(context) { 153 | var startValue; 154 | startValue = flag(context, 'whenObject')(); 155 | return flag(context, 'changeStart', startValue); 156 | }, 157 | after: noChangeAssert 158 | }); 159 | return flag(this, 'whenActions', definedActions); 160 | }); 161 | chai.Assertion.addProperty('increase', function() { 162 | var definedActions; 163 | definedActions = flag(this, 'whenActions') || []; 164 | definedActions.push({ 165 | negate: flag(this, 'negate'), 166 | before: function(context) { 167 | var startValue; 168 | startValue = flag(context, 'whenObject')(); 169 | return flag(context, 'increaseStart', startValue); 170 | }, 171 | after: function(context) { 172 | var endValue, negate, object, startValue; 173 | object = flag(context, 'whenObject'); 174 | endValue = object(); 175 | startValue = flag(context, 'increaseStart'); 176 | negate = flag(context, 'negate'); 177 | flag(context, 'negate', this.negate); 178 | if (!negate) { 179 | context.assert(startValue !== endValue, "expected `" + (formatFunction(object)) + "` to increase, but it did not change", "not supported"); 180 | } 181 | context.assert(startValue < endValue, "expected `" + (formatFunction(object)) + "` to increase, but it decreased by " + (startValue - endValue), "expected `" + (formatFunction(object)) + "` not to increase, but it increased by " + (endValue - startValue)); 182 | return flag(context, 'negate', negate); 183 | } 184 | }); 185 | return flag(this, 'whenActions', definedActions); 186 | }); 187 | chai.Assertion.addProperty('decrease', function() { 188 | var definedActions; 189 | definedActions = flag(this, 'whenActions') || []; 190 | definedActions.push({ 191 | negate: flag(this, 'negate'), 192 | before: function(context) { 193 | var startValue; 194 | startValue = flag(context, 'whenObject')(); 195 | return flag(context, 'decreaseStart', startValue); 196 | }, 197 | after: function(context) { 198 | var endValue, negate, object, startValue; 199 | object = flag(context, 'whenObject'); 200 | endValue = object(); 201 | startValue = flag(context, 'decreaseStart'); 202 | negate = flag(context, 'negate'); 203 | flag(context, 'negate', this.negate); 204 | if (!negate) { 205 | context.assert(startValue !== endValue, "expected `" + (formatFunction(object)) + "` to decrease, but it did not change", "not supported"); 206 | } 207 | context.assert(startValue > endValue, "expected `" + (formatFunction(object)) + "` to decrease, but it increased by " + (endValue - startValue), "expected `" + (formatFunction(object)) + "` not to decrease, but it decreased by " + (startValue - endValue)); 208 | return flag(context, 'negate', negate); 209 | } 210 | }); 211 | return flag(this, 'whenActions', definedActions); 212 | }); 213 | byAtLeast = function(amount) { 214 | var definedActions; 215 | definedActions = flag(this, 'whenActions') || []; 216 | definedActions.push({ 217 | negate: flag(this, 'negate'), 218 | before: function(context) { 219 | var startValue; 220 | startValue = flag(context, 'whenObject')(); 221 | return flag(context, 'atLeastStart', startValue); 222 | }, 223 | after: function(context) { 224 | var difference, endValue, negate, object, startValue; 225 | object = flag(context, 'whenObject'); 226 | endValue = object(); 227 | startValue = flag(context, 'atLeastStart'); 228 | negate = flag(context, 'negate'); 229 | flag(context, 'negate', this.negate); 230 | difference = Math.abs(endValue - startValue); 231 | context.assert(difference >= amount, "expected `" + (formatFunction(object)) + "` to change by at least " + amount + ", but changed by " + difference, "not supported"); 232 | return flag(context, 'negate', negate); 233 | } 234 | }); 235 | return flag(this, 'whenActions', definedActions); 236 | }; 237 | chai.Assertion.addChainableMethod('atLeast', byAtLeast, function() { 238 | return this; 239 | }); 240 | byAtMost = function(amount) { 241 | var definedActions; 242 | definedActions = flag(this, 'whenActions') || []; 243 | definedActions.push({ 244 | negate: flag(this, 'negate'), 245 | before: function(context) { 246 | var startValue; 247 | startValue = flag(context, 'whenObject')(); 248 | return flag(context, 'atMostStart', startValue); 249 | }, 250 | after: function(context) { 251 | var difference, endValue, negate, object, startValue; 252 | object = flag(context, 'whenObject'); 253 | endValue = object(); 254 | startValue = flag(context, 'atMostStart'); 255 | negate = flag(context, 'negate'); 256 | flag(context, 'negate', this.negate); 257 | difference = Math.abs(endValue - startValue); 258 | context.assert(difference <= amount, "expected `" + (formatFunction(object)) + "` to change by at most " + amount + ", but changed by " + difference, "not supported"); 259 | return flag(context, 'negate', negate); 260 | } 261 | }); 262 | return flag(this, 'whenActions', definedActions); 263 | }; 264 | chai.Assertion.addChainableMethod('atMost', byAtMost, function() { 265 | return this; 266 | }); 267 | formatFunction = function(func) { 268 | return func.toString().replace(/^\s*function \(\) {\s*/, '').replace(/\s+}$/, '').replace(/\s*return\s*/, ''); 269 | }; 270 | changeBy = function(delta) { 271 | var definedActions; 272 | flag(this, 'no-change', false); 273 | definedActions = flag(this, 'whenActions') || []; 274 | definedActions.push({ 275 | negate: flag(this, 'negate'), 276 | expectedDelta: delta, 277 | after: changeByAssert 278 | }); 279 | return flag(this, 'whenActions', definedActions); 280 | }; 281 | chai.Assertion.addChainableMethod('by', changeBy, function() { 282 | return this; 283 | }); 284 | changeTo = function(endValue) { 285 | var definedActions; 286 | flag(this, 'no-change', false); 287 | definedActions = flag(this, 'whenActions') || []; 288 | definedActions.push({ 289 | negate: flag(this, 'negate'), 290 | expectedEndValue: endValue, 291 | before: changeToBeginAssert, 292 | after: changeToAssert 293 | }); 294 | return flag(this, 'whenActions', definedActions); 295 | }; 296 | chai.Assertion.addChainableMethod('to', changeTo, function() { 297 | return this; 298 | }); 299 | changeFrom = function(startValue) { 300 | var definedActions; 301 | flag(this, 'no-change', false); 302 | definedActions = flag(this, 'whenActions') || []; 303 | definedActions.push({ 304 | negate: flag(this, 'negate'), 305 | expectedStartValue: startValue, 306 | before: changeFromBeginAssert, 307 | after: changeFromAssert 308 | }); 309 | return flag(this, 'whenActions', definedActions); 310 | }; 311 | return chai.Assertion.addChainableMethod('from', changeFrom, function() { 312 | return this; 313 | }); 314 | }); 315 | 316 | }).call(this); 317 | -------------------------------------------------------------------------------- /test/vendor/js/chai-jquery.js: -------------------------------------------------------------------------------- 1 | (function (chaiJquery) { 2 | // Module systems magic dance. 3 | if (typeof require === "function" && typeof exports === "object" && typeof module === "object") { 4 | // NodeJS 5 | module.exports = chaiJquery; 6 | } else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(['jquery'], function ($) { 9 | return function (chai, utils) { 10 | return chaiJquery(chai, utils, $); 11 | }; 12 | }); 13 | } else { 14 | // Other environment (usually