matcha 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/.gitignore +19 -0
  2. data/Gemfile +7 -0
  3. data/LICENSE +90 -0
  4. data/README.md +194 -0
  5. data/Rakefile +8 -0
  6. data/app/controllers/matcha/specs_controller.rb +22 -0
  7. data/app/models/matcha/spec.rb +25 -0
  8. data/app/views/layouts/matcha/specs.html.erb +31 -0
  9. data/app/views/matcha/specs/index.html.erb +1 -0
  10. data/app/views/matcha/specs/show.html.erb +1 -0
  11. data/config/routes.rb +4 -0
  12. data/lib/matcha.rb +41 -0
  13. data/lib/matcha/engine.rb +31 -0
  14. data/lib/matcha/runner.rb +151 -0
  15. data/lib/matcha/server.rb +7 -0
  16. data/lib/tasks/matcha.rake +11 -0
  17. data/matcha.gemspec +30 -0
  18. data/spec/controllers/specs_controller_spec.rb +46 -0
  19. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  20. data/spec/dummy/app/assets/javascripts/array_sum.js.coffee +4 -0
  21. data/spec/dummy/config.ru +4 -0
  22. data/spec/dummy/config/application.rb +17 -0
  23. data/spec/dummy/config/boot.rb +6 -0
  24. data/spec/dummy/config/environment.rb +5 -0
  25. data/spec/dummy/config/environments/test.rb +29 -0
  26. data/spec/dummy/config/initializers/matcha.rb +3 -0
  27. data/spec/dummy/spec/javascripts/array_sum_cs_spec.js.coffee +8 -0
  28. data/spec/dummy/spec/javascripts/array_sum_js_spec.js +11 -0
  29. data/spec/dummy/spec/javascripts/assert_spec.js.coffee +9 -0
  30. data/spec/dummy/spec/javascripts/failing_spec.js +5 -0
  31. data/spec/dummy/spec/javascripts/spec_helper.js +3 -0
  32. data/spec/dummy/spec/javascripts/spec_helper_spec.js +7 -0
  33. data/spec/dummy/spec/javascripts/subdirectory/subdirectory_spec.js +5 -0
  34. data/spec/dummy/spec/javascripts/templates/hello.jst.ejs +1 -0
  35. data/spec/dummy/spec/javascripts/templating_spec.js +8 -0
  36. data/spec/dummy/spec/javascripts/transactions_spec.js.coffee +7 -0
  37. data/spec/matcha_spec.rb +40 -0
  38. data/spec/models/spec_spec.rb +45 -0
  39. data/spec/runner_spec.rb +36 -0
  40. data/spec/server_spec.rb +41 -0
  41. data/spec/spec_helper.rb +18 -0
  42. data/spec/views/specs/index.html.erb_spec.rb +12 -0
  43. data/spec/views/specs/show.html.erb_spec.rb +10 -0
  44. data/spec/views/specs/specs.html.erb_spec.rb +15 -0
  45. data/vendor/assets/javascripts/chai.js +2007 -0
  46. data/vendor/assets/javascripts/matcha/runner.js +70 -0
  47. data/vendor/assets/javascripts/matcha/server.js +0 -0
  48. data/vendor/assets/javascripts/mocha.js +3290 -0
  49. data/vendor/assets/stylesheets/mocha.css +133 -0
  50. metadata +202 -0
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ node_modules
19
+ spec/dummy/log
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+
4
+ # This is a runtime dependency in the gemspec, so it shouldn't be necessary to
5
+ # specify it again, but bundler is buggy:
6
+ # https://github.com/carlhuda/bundler/issues/1041
7
+ gem "jquery-rails"
data/LICENSE ADDED
@@ -0,0 +1,90 @@
1
+ Copyright (c) 2012 John Firebaugh
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ Portions derived from Evergreen (https://github.com/jnicklas/evergreen):
25
+
26
+ Copyright (c) 2009 Jonas Nicklas
27
+
28
+ Permission is hereby granted, free of charge, to any person obtaining
29
+ a copy of this software and associated documentation files (the
30
+ 'Software'), to deal in the Software without restriction, including
31
+ without limitation the rights to use, copy, modify, merge, publish,
32
+ distribute, sublicense, and/or sell copies of the Software, and to
33
+ permit persons to whom the Software is furnished to do so, subject to
34
+ the following conditions:
35
+
36
+ The above copyright notice and this permission notice shall be
37
+ included in all copies or substantial portions of the Software.
38
+
39
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
40
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
41
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
42
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
43
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
44
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
45
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
46
+
47
+ Portions derived from Mocha (https://github.com/visionmedia/mocha)
48
+
49
+ Copyright (c) 20011-2012 TJ Holowaychuk <tj@vision-media.ca>
50
+
51
+ Permission is hereby granted, free of charge, to any person obtaining
52
+ a copy of this software and associated documentation files (the
53
+ 'Software'), to deal in the Software without restriction, including
54
+ without limitation the rights to use, copy, modify, merge, publish,
55
+ distribute, sublicense, and/or sell copies of the Software, and to
56
+ permit persons to whom the Software is furnished to do so, subject to
57
+ the following conditions:
58
+
59
+ The above copyright notice and this permission notice shall be
60
+ included in all copies or substantial portions of the Software.
61
+
62
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
63
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
64
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
65
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
66
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
67
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
68
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
69
+
70
+ Portions derived from Chai (https://github.com/logicalparadox/chai)
71
+
72
+ Copyright (c) 2011 Jake Luer <jake@alogicalparadox.com>
73
+
74
+ Permission is hereby granted, free of charge, to any person obtaining a copy
75
+ of this software and associated documentation files (the "Software"), to deal
76
+ in the Software without restriction, including without limitation the rights
77
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
78
+ copies of the Software, and to permit persons to whom the Software is
79
+ furnished to do so, subject to the following conditions:
80
+
81
+ The above copyright notice and this permission notice shall be included in
82
+ all copies or substantial portions of the Software.
83
+
84
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
85
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
86
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
87
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
88
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
89
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
90
+ THE SOFTWARE.
@@ -0,0 +1,194 @@
1
+ # Matcha
2
+
3
+ Matcha is a Rails engine that allows you to test your JavaScript with the
4
+ [mocha](http://visionmedia.github.com/mocha/) test framework and [chai](http://chaijs.com/)
5
+ assertion library.
6
+
7
+ It is similar to [Jasmine](https://github.com/pivotal/jasmine-gem) and
8
+ [Evergreen](https://github.com/jnicklas/evergreen), but does not attempt to be framework
9
+ agnostic. By sticking with Rails, Matcha can take full advantage of features such as
10
+ the asset pipeline and engines.
11
+
12
+ ## Installation
13
+
14
+ Add matcha to the `:test` and `:development` groups in the Gemfile:
15
+
16
+ group :test, :development do
17
+ gem "matcha"
18
+ end
19
+
20
+ And then execute:
21
+
22
+ $ bundle
23
+
24
+ Or install it yourself as:
25
+
26
+ $ gem install matcha
27
+
28
+ ## Usage
29
+
30
+ Create a `spec/javascripts` directory and name the files in it with a `_spec` suffix.
31
+ You can write the specs in either JavaScript or CoffeeScript, using a `.js` or
32
+ `.js.coffee` extension respectively, like you would any other script asset.
33
+
34
+ Require the assets under test and any other dependencies using Sprockets directives.
35
+ For example, suppose you wanted to test your cool JavaScript `Array#sum` method, which
36
+ you placed in `app/assets/javascripts/array_sum.js`. Write the specs in JavaScript in
37
+ the file `spec/javascripts/array_sum_spec.js`:
38
+
39
+ //= require array_sum
40
+
41
+ describe("Array#sum", function(){
42
+ it("returns 0 when the Array is empty", function(){
43
+ [].sum().should.equal(0);
44
+ });
45
+
46
+ it("returns the sum of numeric elements", function(){
47
+ [1,2,3].sum().should.equal(6);
48
+ });
49
+ });
50
+
51
+ Or, if you prefer CoffeeScript, in `spec/javascripts/array_sum_spec.js.coffee`:
52
+
53
+ #= require array_sum
54
+
55
+ describe "Array#sum", ->
56
+ it "returns 0 when the Array is empty", ->
57
+ [].sum().should.equal(0)
58
+
59
+ it "returns the sum of numeric elements", ->
60
+ [1,2,3].sum().should.equal(6)
61
+
62
+ The `matcha:server` rake task starts a server for your tests. You can go to the root
63
+ page to run all specs (e.g. `http://localhost:8888/`), or a sub page to run an individual
64
+ spec file (e.g. `http://localhost:8888/array_sum_spec`).
65
+
66
+ Alternatively, you can run the specs headlessly with the `matcha:ci` task.
67
+
68
+ ## Spec Helper
69
+
70
+ Since Matcha integrates with the asset pipeline, using setup helpers in your specs is
71
+ easy. Just create a `spec_helper.js` or `spec_helper.js.coffee` file in `specs/javascripts`
72
+ and require it in your tests:
73
+
74
+ //= require spec_helper
75
+ //= require array_sum
76
+
77
+ describe("Array#sum", function(){
78
+ ...
79
+ });
80
+
81
+ ## Directives and Asset Bundling
82
+
83
+ We suggest that you explicitly require just the assets necessary for each spec. In CI
84
+ mode, Matcha will run each spec in isolation, and requiring things explicitly will help
85
+ ensure your scripts don't accumulate hidden dependencies and tight coupling.
86
+
87
+ However, you are free to ignore this advice and require the entire application.js asset
88
+ bundle in your specs or spec helper, or a bundled subset of assets. Requiring bundled
89
+ assets works like it does in Rails development mode -- Matcha will detect the complete
90
+ set of dependencies and generate a separate script tag for each one. You won't have to
91
+ search through a many thousand line application.js bundle to debug a spec failure.
92
+
93
+ ## Configuration
94
+
95
+ Matcha can be configured in an initializer, e.g. `config/initializers/matcha.rb`:
96
+
97
+ Matcha.configure do |config|
98
+ config.spec_dir = "spec/javascripts"
99
+ config.interface = :bdd
100
+ config.driver = :selenium
101
+ end if defined?(Matcha)
102
+
103
+ The `defined?` check is necessary to avoid a dependency on Matcha in the production
104
+ environment.
105
+
106
+ The `spec_dir` option tells Matcha where to find JavaScript specs. The `interface`
107
+ option specifies the test interface used by Mocha (see below). `driver` names a
108
+ Capybara driver used for the CI task (try `:webkit`, after installing
109
+ [capybara-webkit](https://github.com/thoughtbot/capybara-webkit)).
110
+
111
+ The values above are the defaults.
112
+
113
+ ## Test Interface and Assertions
114
+
115
+ Matcha includes a vendored copy of mocha.js and the [chai](http://chaijs.com/)
116
+ assertion libraries.
117
+
118
+ By default, it will assume that you want to use Mocha's "BDD" test interface, which
119
+ provides `describe()`, `it()`, `before()`, `after()`, `beforeEach()`, and `afterEach()`.
120
+ If you want to use the TDD, Exports, or QUnit interfaces instead, set the `interface`
121
+ configuration option in an initializer:
122
+
123
+ Matcha.configure do |config|
124
+ config.interface = :tdd # Or :exports or :qunit
125
+ end if defined?(Matcha)
126
+
127
+ Matcha will make all three of chai's assertion styles available to you: `expect`,
128
+ `should`, and `assert`. See the chai documentation for the details.
129
+
130
+ If you use jQuery, you may want to check out [chai-jquery](https://github.com/jfirebaugh/chai-jquery)
131
+ for some jQuery-specific assertions.
132
+
133
+ ## Transactions
134
+
135
+ One problem often faced when writing unit tests for client side code is that changes
136
+ to the page are not reverted for the next example, so that successive examples become
137
+ dependent on each other. Matcha adds a special div to your page with an id of `test`.
138
+ This div is automatically emptied before each example. You should avoid appending markup
139
+ to the page body and instead append it to this test div:
140
+
141
+ describe "transactions", ->
142
+ it "should add stuff in one test...", ->
143
+ $('#test').append('<h1 id="added">New Stuff</h1>')
144
+ $('#test h1#added').length.should.equal(1)
145
+
146
+ it "... should have been removed before the next starts", ->
147
+ $('#test h1#added').length.should.equal(0)
148
+
149
+ Note: this functionality is available only for the "BDD" (default) and "TDD" mocha interfaces,
150
+ and not for the "exports" or "QUnit" interfaces.
151
+
152
+ ## Templates / Fixtures
153
+
154
+ Matcha has no template (a.k.a. HTML fixture) support of its own. Instead, we suggest you use
155
+ Sprocket's built in support for JavaScript template (`.jst`) files. Add a `spec/javascripts/templates`
156
+ directory, place template files there (using any JS template language supported by Sprockets),
157
+ require them in your spec or spec_helper, and render them into the `#test` div.
158
+
159
+ For example, in `spec/javascripts/templates/hello.jst.ejs`:
160
+
161
+ <h1>Hello Matcha!</h1>
162
+
163
+ In `spec_helper.js`:
164
+
165
+ //= require_tree ./templates
166
+
167
+ And your spec:
168
+
169
+ //= require spec_helper
170
+
171
+ describe("templating", function(){
172
+ it("is built in to Sprockets", function(){
173
+ $('#test').html(JST['templates/hello']());
174
+ $('#test h1').text().should.equal('Hello Matcha!');
175
+ });
176
+ });
177
+
178
+ ## Contributing
179
+
180
+ 1. Fork it
181
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
182
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
183
+ 4. Push to the branch (`git push origin my-new-feature`)
184
+ 5. Create new Pull Request
185
+
186
+ ## License
187
+
188
+ Copyright (c) 2012 John Firebaugh
189
+
190
+ MIT License (see the LICENSE file)
191
+
192
+ Portions: Copyright (c) 2009 Jonas Nicklas, Copyright (c) 20011-2012 TJ Holowaychuk
193
+ <tj@vision-media.ca>, Copyright (c) 2011 Jake Luer <jake@alogicalparadox.com>. See
194
+ LICENSE file for details.
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env rake
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new :spec
7
+
8
+ task :default => :spec
@@ -0,0 +1,22 @@
1
+ module Matcha
2
+ class SpecsController < ActionController::Base
3
+ before_filter :set_interface, :set_mode
4
+
5
+ def set_interface
6
+ @interface = Matcha.interface
7
+ end
8
+
9
+ def set_mode
10
+ @mode = Matcha.mode
11
+ end
12
+
13
+ def index
14
+ @specs = Matcha::Spec.all
15
+ end
16
+
17
+ def show
18
+ @spec = Matcha::Spec.find(params[:spec])
19
+ @spec or render :text => "Not Found", :status => 404
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,25 @@
1
+ module Matcha
2
+ class Spec
3
+ def self.all
4
+ Matcha.spec_paths.map { |path| new(path) }
5
+ end
6
+
7
+ def self.find(basename)
8
+ all.find { |spec| spec.basename == basename }
9
+ end
10
+
11
+ attr_accessor :path
12
+
13
+ def initialize(path)
14
+ @path = path
15
+ end
16
+
17
+ def url
18
+ "/#{basename}"
19
+ end
20
+
21
+ def basename
22
+ path[/.*(?=\.js.*$)/]
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,31 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="content-type" content="text/html;charset=utf-8" />
5
+ <title>Mocha Tests</title>
6
+ <%= stylesheet_link_tag "mocha" %>
7
+ <%= javascript_include_tag "jquery", "mocha", "chai", "matcha/#{@mode}" %>
8
+ <script>
9
+ mocha.setup(<%= raw @interface.to_json %>);
10
+ var expect = chai.expect,
11
+ should = chai.should(),
12
+ assert = chai.assert;
13
+ window.onload = mocha.run;
14
+
15
+ <% if @interface == :bdd %>
16
+ beforeEach(function() {
17
+ document.getElementById('test').innerHTML = "";
18
+ });
19
+ <% elsif @interface == :tdd %>
20
+ setup(function() {
21
+ document.getElementById('test').innerHTML = "";
22
+ });
23
+ <% end %>
24
+ </script>
25
+ <%= yield %>
26
+ </head>
27
+ <body>
28
+ <div id="mocha"></div>
29
+ <div id="test"></div>
30
+ </body>
31
+ </html>
@@ -0,0 +1 @@
1
+ <%= javascript_include_tag *@specs.map(&:basename) %>
@@ -0,0 +1 @@
1
+ <%= javascript_include_tag @spec.basename %>
@@ -0,0 +1,4 @@
1
+ Matcha::Engine.routes.draw do
2
+ match "/" => "matcha/specs#index"
3
+ match "/*spec" => "matcha/specs#show"
4
+ end
@@ -0,0 +1,41 @@
1
+ require "matcha/engine"
2
+ require "matcha/runner"
3
+ require "matcha/server"
4
+
5
+ module Matcha
6
+ class << self
7
+ attr_accessor :mode
8
+
9
+ def serve
10
+ puts "your tests are here:"
11
+ puts " http://localhost:#{port}/"
12
+ self.mode = :server
13
+ Matcha::Server.start
14
+ end
15
+
16
+ def run
17
+ self.mode = :runner
18
+ Matcha::Runner.start
19
+ end
20
+
21
+ def config
22
+ Matcha::Engine.config.matcha
23
+ end
24
+
25
+ def configure
26
+ yield config
27
+ end
28
+
29
+ delegate :port, :spec_dir, :interface, :application, :driver, :to => :config
30
+
31
+ def spec_root
32
+ File.join(Rails.root, config.spec_dir)
33
+ end
34
+
35
+ def spec_paths
36
+ Dir[File.join(spec_root, "**/*_spec.*")].map do |path|
37
+ path.gsub(File.join(spec_root, ''), '')
38
+ end
39
+ end
40
+ end
41
+ end