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,31 @@
1
+ module Matcha
2
+ class Engine < Rails::Engine
3
+ config.matcha = ActiveSupport::OrderedOptions.new
4
+
5
+ def self.application(app)
6
+ Rack::Builder.app do
7
+ map app.config.assets.prefix do
8
+ run app.assets
9
+ end
10
+
11
+ run Matcha::Engine
12
+ end
13
+ end
14
+
15
+ initializer "matcha.environment" do |app|
16
+ unless app.config.assets.enabled
17
+ raise RuntimeError, "matcha requires the asset pipeline to be enabled"
18
+ end
19
+
20
+ options = app.config.matcha
21
+
22
+ options.spec_dir ||= "spec/javascripts"
23
+ options.port ||= 8888
24
+ options.interface ||= :bdd
25
+ options.application ||= self.class.application(app)
26
+ options.driver ||= :selenium
27
+
28
+ app.config.assets.paths << app.root.join(options.spec_dir).to_s
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,151 @@
1
+ module Matcha
2
+ class Runner
3
+ def self.start
4
+ new.run
5
+ end
6
+
7
+ class Example
8
+ def initialize(row)
9
+ @row = row
10
+ end
11
+
12
+ def passed?
13
+ @row['passed']
14
+ end
15
+
16
+ def failure_message
17
+ unless passed?
18
+ msg = []
19
+ msg << " Failed: #{@row['name']}"
20
+ msg << " #{@row['message']}"
21
+ msg << " in #{@row['trace']['fileName']}:#{@row['trace']['lineNumber']}" if @row['trace']
22
+ msg.join("\n")
23
+ end
24
+ end
25
+ end
26
+
27
+ class SpecRunner
28
+ attr_reader :runner, :spec
29
+
30
+ def initialize(runner, spec)
31
+ @runner = runner
32
+ @spec = spec
33
+ end
34
+
35
+ def session
36
+ runner.session
37
+ end
38
+
39
+ def io
40
+ runner.io
41
+ end
42
+
43
+ def run
44
+ io.puts dots
45
+ io.puts failure_messages
46
+ io.puts "\n#{examples.size} examples, #{failed_examples.size} failures"
47
+ passed?
48
+ end
49
+
50
+ def examples
51
+ @results ||= begin
52
+ session.visit(spec.url)
53
+
54
+ previous_results = ""
55
+
56
+ session.wait_until(300) do
57
+ dots = session.evaluate_script('Matcha.dots')
58
+ io.print dots.sub(/^#{Regexp.escape(previous_results)}/, '')
59
+ io.flush
60
+ previous_results = dots
61
+ session.evaluate_script('Matcha.done')
62
+ end
63
+
64
+ dots = session.evaluate_script('Matcha.dots')
65
+ io.print dots.sub(/^#{Regexp.escape(previous_results)}/, '')
66
+
67
+ JSON.parse(session.evaluate_script('Matcha.getResults()')).map do |row|
68
+ Example.new(row)
69
+ end
70
+ end
71
+ end
72
+
73
+ def failed_examples
74
+ examples.select { |example| not example.passed? }
75
+ end
76
+
77
+ def passed?
78
+ examples.all? { |example| example.passed? }
79
+ end
80
+
81
+ def dots
82
+ examples; ""
83
+ end
84
+
85
+ def failure_messages
86
+ unless passed?
87
+ examples.map { |example| example.failure_message }.compact.join("\n\n")
88
+ end
89
+ end
90
+ end
91
+
92
+ attr_reader :suite, :io
93
+
94
+ def initialize(options = {})
95
+ @io = options[:output] || STDOUT
96
+ end
97
+
98
+ def spec_runner(spec)
99
+ SpecRunner.new(self, spec)
100
+ end
101
+
102
+ def run
103
+ before = Time.now
104
+
105
+ io.puts ""
106
+ io.puts dots.to_s
107
+ io.puts ""
108
+ if failure_messages
109
+ io.puts failure_messages
110
+ io.puts ""
111
+ end
112
+
113
+ seconds = "%.2f" % (Time.now - before)
114
+ io.puts "Finished in #{seconds} seconds"
115
+ io.puts "#{examples.size} examples, #{failed_examples.size} failures"
116
+ passed?
117
+ end
118
+
119
+ def examples
120
+ spec_runners.map { |spec_runner| spec_runner.examples }.flatten
121
+ end
122
+
123
+ def failed_examples
124
+ examples.select { |example| not example.passed? }
125
+ end
126
+
127
+ def passed?
128
+ spec_runners.all? { |spec_runner| spec_runner.passed? }
129
+ end
130
+
131
+ def dots
132
+ spec_runners.map { |spec_runner| spec_runner.dots }.join
133
+ end
134
+
135
+ def failure_messages
136
+ unless passed?
137
+ spec_runners.map { |spec_runner| spec_runner.failure_messages }.compact.join("\n\n")
138
+ end
139
+ end
140
+
141
+ def session
142
+ @session ||= Capybara::Session.new(Matcha.driver, Matcha.application)
143
+ end
144
+
145
+ protected
146
+
147
+ def spec_runners
148
+ @spec_runners ||= Matcha::Spec.all.map { |spec| SpecRunner.new(self, spec) }
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,7 @@
1
+ module Matcha
2
+ class Server
3
+ def self.start
4
+ Rack::Server.start(:app => Matcha.application, :Port => Matcha.port, :AccessLog => [])
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ namespace :matcha do
2
+ desc "Run JavaScript specs interactively"
3
+ task :server => :environment do
4
+ Matcha.serve
5
+ end
6
+
7
+ desc "Run JavaScript specs non-interactively"
8
+ task :ci => :environment do
9
+ Matcha.run
10
+ end
11
+ end
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.authors = ["John Firebaugh"]
5
+ gem.email = ["john.firebaugh@gmail.com"]
6
+ gem.description = %q{Unit test your Rails JavaScript with the mocha test framework and chai assertion library}
7
+ gem.summary = %q{Matcha is a Rails engine that allows you to test your JavaScript with the
8
+ mocha test framework and chai assertion library.
9
+
10
+ It is similar to Jasmine and Evergreen, but does not attempt to be framework
11
+ agnostic. By sticking with Rails, Matcha can take full advantage of features such as
12
+ the asset pipeline and engines.}
13
+ gem.homepage = "http://github.com/jfirebaugh/matcha"
14
+
15
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
+ gem.files = `git ls-files`.split("\n")
17
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ gem.name = "matcha"
19
+ gem.require_paths = ["lib"]
20
+ gem.version = "0.9.0"
21
+
22
+ gem.add_dependency "jquery-rails"
23
+ gem.add_dependency "rails", "~> 3.1"
24
+ gem.add_dependency "capybara"
25
+
26
+ gem.add_development_dependency "rspec-rails"
27
+ gem.add_development_dependency "capybara-firebug", "~> 1.1"
28
+ gem.add_development_dependency "coffee-script"
29
+ gem.add_development_dependency "ejs"
30
+ end
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ describe Matcha::SpecsController do
4
+ before do
5
+ @routes = Matcha::Engine.routes
6
+ end
7
+
8
+ describe "#set_interface" do
9
+ it "assigns Matcha.interface to @interface" do
10
+ Matcha.should_receive(:interface) { :tdd }
11
+ subject.set_interface
12
+ assigns[:interface].should == :tdd
13
+ end
14
+ end
15
+
16
+ describe "#set_mode" do
17
+ it "assigns Matcha.mode to @mode" do
18
+ Matcha.should_receive(:mode) { :runner }
19
+ subject.set_mode
20
+ assigns[:mode].should == :runner
21
+ end
22
+ end
23
+
24
+ describe "#index" do
25
+ it "assigns Matcha::Spec.all to @specs" do
26
+ Matcha::Spec.should_receive(:all) { :all }
27
+ get :index
28
+ assigns[:specs].should == :all
29
+ end
30
+ end
31
+
32
+ describe "#show" do
33
+ it "finds the spec with the given basename and assigns it to @spec" do
34
+ Matcha::Spec.should_receive(:find).with("array_spec") { :spec }
35
+ get :show, :spec => "array_spec"
36
+ assigns[:spec].should == :spec
37
+ end
38
+
39
+ it "404s if there is no spec with the given basename" do
40
+ Matcha::Spec.should_receive(:find).with("array_spec") { nil }
41
+ get :show, :spec => "array_spec"
42
+ response.status.should == 404
43
+ response.should_not render_template("matcha/specs/show")
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,15 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // the compiled file.
9
+ //
10
+ // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
11
+ // GO AFTER THE REQUIRES BELOW.
12
+ //
13
+ //= require jquery
14
+ //= require jquery_ujs
15
+ //= require_tree .
@@ -0,0 +1,4 @@
1
+ Array.prototype.sum = ->
2
+ sum = 0
3
+ sum += i for i in this
4
+ sum
@@ -0,0 +1,4 @@
1
+ # This file is used by Rack-based servers to start the application.
2
+
3
+ require ::File.expand_path('../config/environment', __FILE__)
4
+ run Dummy::Application
@@ -0,0 +1,17 @@
1
+ require File.expand_path('../boot', __FILE__)
2
+
3
+ require "action_controller/railtie"
4
+ require "action_view/railtie"
5
+ require "sprockets/railtie"
6
+
7
+ if defined?(Bundler)
8
+ Bundler.require(*Rails.groups(:assets => %w(development test)))
9
+ end
10
+
11
+ module Dummy
12
+ class Application < Rails::Application
13
+ config.encoding = "utf-8"
14
+ config.assets.enabled = true
15
+ config.assets.version = '1.0'
16
+ end
17
+ end
@@ -0,0 +1,6 @@
1
+ require 'rubygems'
2
+
3
+ # Set up gems listed in the Gemfile.
4
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../../Gemfile', __FILE__)
5
+
6
+ require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
@@ -0,0 +1,5 @@
1
+ # Load the rails application
2
+ require File.expand_path('../application', __FILE__)
3
+
4
+ # Initialize the rails application
5
+ Dummy::Application.initialize!
@@ -0,0 +1,29 @@
1
+ Dummy::Application.configure do
2
+ # Settings specified here will take precedence over those in config/application.rb
3
+
4
+ # The test environment is used exclusively to run your application's
5
+ # test suite. You never need to work with it otherwise. Remember that
6
+ # your test database is "scratch space" for the test suite and is wiped
7
+ # and recreated between test runs. Don't rely on the data there!
8
+ config.cache_classes = true
9
+
10
+ # Configure static asset server for tests with Cache-Control for performance
11
+ config.serve_static_assets = true
12
+ config.static_cache_control = "public, max-age=3600"
13
+
14
+ # Log error messages when you accidentally call methods on nil
15
+ config.whiny_nils = true
16
+
17
+ # Show full error reports and disable caching
18
+ config.consider_all_requests_local = true
19
+ config.action_controller.perform_caching = false
20
+
21
+ # Raise exceptions instead of rendering exception templates
22
+ config.action_dispatch.show_exceptions = false
23
+
24
+ # Disable request forgery protection in test environment
25
+ config.action_controller.allow_forgery_protection = false
26
+
27
+ # Print deprecation notices to the stderr
28
+ config.active_support.deprecation = :stderr
29
+ end
@@ -0,0 +1,3 @@
1
+ Matcha.configure do |config|
2
+ config.configured = true
3
+ end if defined?(Matcha)
@@ -0,0 +1,8 @@
1
+ #= require array_sum
2
+
3
+ describe "Array#sum (cs)", ->
4
+ it "returns 0 when the Array is empty", ->
5
+ [].sum().should.equal(0);
6
+
7
+ it "returns the sum of numeric elements", ->
8
+ [1,2,3].sum().should.equal(6);
@@ -0,0 +1,11 @@
1
+ //= require array_sum
2
+
3
+ describe("Array#sum (js)", function(){
4
+ it("returns 0 when the Array is empty", function(){
5
+ [].sum().should.equal(0);
6
+ });
7
+
8
+ it("returns the sum of numeric elements", function(){
9
+ [1,2,3].sum().should.equal(6);
10
+ });
11
+ });
@@ -0,0 +1,9 @@
1
+ describe "assert styles", ->
2
+ it "supports expect style", ->
3
+ expect(2 + 2).to.equal(4)
4
+
5
+ it "supports should style", ->
6
+ (2 + 2).should.equal(4)
7
+
8
+ it "supports assert style", ->
9
+ assert.equal(2 + 2, 4)
@@ -0,0 +1,5 @@
1
+ describe("failure", function(){
2
+ it("fails", function(){
3
+ (2 + 2).should.equal(5);
4
+ });
5
+ });
@@ -0,0 +1,3 @@
1
+ //= require_tree ./templates
2
+
3
+ var two_plus_two = function () { return 2 + 2; };
@@ -0,0 +1,7 @@
1
+ //= require spec_helper
2
+
3
+ describe("two_plus_two", function(){
4
+ it("equals four", function(){
5
+ two_plus_two().should.equal(4);
6
+ })
7
+ });
@@ -0,0 +1,5 @@
1
+ describe("spec in subdirectory", function(){
2
+ it("passes", function(){
3
+ (2 + 2).should.equal(4);
4
+ });
5
+ });
@@ -0,0 +1 @@
1
+ <h1>Hello Matcha!</h1>
@@ -0,0 +1,8 @@
1
+ //= require spec_helper
2
+
3
+ describe("templating", function(){
4
+ it("is built in to Sprockets", function(){
5
+ $('#test').html(JST['templates/hello']());
6
+ $('#test h1').text().should.equal('Hello Matcha!');
7
+ });
8
+ });