evergreen 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -71,11 +71,30 @@ One problem often faced when writing unit tests for client side code is that cha
71
71
 
72
72
  Even more powerful than that, Evergreen allows you to create HTML templates to go along with your specs. Simply name the template the same as the spec, only with an html extension. For example:
73
73
 
74
- spec/javascripts/widget_spec.js
75
- spec/javascripts/widget_spec.html
74
+ spec/javascripts/widget_spec.js
75
+ spec/javascripts/widget_spec.html
76
76
 
77
77
  The template will be placed inside the test div, so that means it should not include html, head, body or similar tags. The template will be restored for each example, so that at the start of each example, the markup inside the test div is identical.
78
78
 
79
+ == Spec Helper
80
+
81
+ If you add a spec_helper file like so:
82
+
83
+ spec/javascripts/spec_helper.js
84
+
85
+ It will automatically be loaded. This is a great place for adding custom matchers and the like.
86
+
87
+ == CoffeeScript
88
+
89
+ Evergreen supports specs written in {CoffeeScript}[http://github.com/jashkenas/coffee-script]. Just name your spec file _spec.coffee and it will automatically be translated for you.
90
+
91
+ You can also add a CoffeeScript spec helper, but remember that CoffeeScript encloses individual files in a closure, if you need something you define in the spec helper to be available in your spec files, attach it to the window object:
92
+
93
+ # spec/javascripts/spec_helper.coffee
94
+
95
+ MyThing: "foo" # local to spec helper
96
+ window.MyThing: "foo" # global
97
+
79
98
  == License:
80
99
 
81
100
  (The MIT License)
@@ -43,6 +43,8 @@ module Evergreen
43
43
 
44
44
  get '/run/*' do |name|
45
45
  @spec = Spec.new(root, name)
46
+ @js_spec_helper = Spec.new(root, 'spec_helper.js')
47
+ @coffee_spec_helper = Spec.new(root, 'spec_helper.coffee')
46
48
  erb :spec
47
49
  end
48
50
 
@@ -1,20 +1,25 @@
1
+ if(!this.JSON){this.JSON={};}
2
+
1
3
  var Evergreen = {};
2
4
 
3
5
  Evergreen.ReflectiveReporter = function() {
4
6
  this.reportRunnerStarting = function(runner) {
5
- jasmine.results = [];
7
+ Evergreen.results = [];
6
8
  };
7
9
  this.reportSpecResults = function(spec) {
8
10
  var results = spec.results();
9
11
  var item = results.getItems()[0] || {};
10
- jasmine.results.push({
12
+ Evergreen.results.push({
11
13
  name: spec.getFullName(),
12
14
  passed: results.failedCount === 0,
13
15
  message: item.message,
14
16
  trace: item.trace
15
17
  });
16
18
  };
17
- }
19
+ };
20
+ Evergreen.getResults = function() {
21
+ return JSON.stringify(Evergreen.results);
22
+ };
18
23
 
19
24
  beforeEach(function() {
20
25
  var test = document.getElementById('test');
@@ -24,3 +29,34 @@ beforeEach(function() {
24
29
  var require = function(file) {
25
30
  document.write('<script type="text/javascript" src="' + file + '"></script>');
26
31
  };
32
+
33
+ // === JSON ===
34
+
35
+ (function(){function f(n){return n<10?'0'+n:n;}
36
+ if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+'-'+
37
+ f(this.getUTCMonth()+1)+'-'+
38
+ f(this.getUTCDate())+'T'+
39
+ f(this.getUTCHours())+':'+
40
+ f(this.getUTCMinutes())+':'+
41
+ f(this.getUTCSeconds())+'Z':null;};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf();};}
42
+ var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4);})+'"':'"'+string+'"';}
43
+ function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key);}
44
+ if(typeof rep==='function'){value=rep.call(holder,key,value);}
45
+ switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null';}
46
+ gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||'null';}
47
+ v=partial.length===0?'[]':gap?'[\n'+gap+
48
+ partial.join(',\n'+gap)+'\n'+
49
+ mind+']':'['+partial.join(',')+']';gap=mind;return v;}
50
+ if(rep&&typeof rep==='object'){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==='string'){v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}else{for(k in value){if(Object.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}
51
+ v=partial.length===0?'{}':gap?'{\n'+gap+partial.join(',\n'+gap)+'\n'+
52
+ mind+'}':'{'+partial.join(',')+'}';gap=mind;return v;}}
53
+ if(typeof JSON.stringify!=='function'){JSON.stringify=function(value,replacer,space){var i;gap='';indent='';if(typeof space==='number'){for(i=0;i<space;i+=1){indent+=' ';}}else if(typeof space==='string'){indent=space;}
54
+ rep=replacer;if(replacer&&typeof replacer!=='function'&&(typeof replacer!=='object'||typeof replacer.length!=='number')){throw new Error('JSON.stringify');}
55
+ return str('',{'':value});};}
56
+ if(typeof JSON.parse!=='function'){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==='object'){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v;}else{delete value[k];}}}}
57
+ return reviver.call(holder,key,value);}
58
+ text=String(text);cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return'\\u'+
59
+ ('0000'+a.charCodeAt(0).toString(16)).slice(-4);});}
60
+ if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){j=eval('('+text+')');return typeof reviver==='function'?walk({'':j},''):j;}
61
+ throw new SyntaxError('JSON.parse');};}}());
62
+
@@ -34,9 +34,9 @@ module Evergreen
34
34
  def failure_message
35
35
  failed_examples.map do |row|
36
36
  msg = []
37
- msg << " Failed: #{row.name}"
38
- msg << " #{row.message}"
39
- msg << " in #{row.trace.fileName}:#{row.trace.lineNumber}" if row.trace.respond_to?(:fileName)
37
+ msg << " Failed: #{row['name']}"
38
+ msg << " #{row['message']}"
39
+ msg << " in #{row['trace']['fileName']}:#{row['trace']['lineNumber']}" if row['trace']
40
40
  msg.join("\n")
41
41
  end.join("\n\n")
42
42
  end
@@ -44,14 +44,14 @@ module Evergreen
44
44
  protected
45
45
 
46
46
  def failed_examples
47
- results.select { |row| !row.passed }
47
+ results.select { |row| !row['passed'] }
48
48
  end
49
49
 
50
50
  def results
51
51
  @results ||= begin
52
52
  session = Capybara::Session.new(:envjs, Evergreen.application(spec.root))
53
53
  session.visit(spec.url)
54
- session.evaluate_script('jasmine.results')
54
+ JSON.parse(session.evaluate_script('Evergreen.getResults()'))
55
55
  end
56
56
  end
57
57
 
@@ -2,7 +2,7 @@ module Evergreen
2
2
  class Spec
3
3
 
4
4
  def self.all(root)
5
- Dir.glob(File.join(root, 'spec/javascripts', '*_spec.js')).map do |path|
5
+ Dir.glob(File.join(root, 'spec/javascripts', '*_spec.{js,coffee}')).map do |path|
6
6
  new(root, File.basename(path))
7
7
  end
8
8
  end
@@ -27,7 +27,11 @@ module Evergreen
27
27
  end
28
28
 
29
29
  def read
30
- File.read(full_path)
30
+ if full_path =~ /\.coffee$/
31
+ %x(coffee -p #{full_path})
32
+ else
33
+ File.read(full_path)
34
+ end
31
35
  end
32
36
  alias_method :contents, :read
33
37
 
@@ -35,5 +39,9 @@ module Evergreen
35
39
  "/run/#{name}"
36
40
  end
37
41
 
42
+ def exist?
43
+ File.exist?(full_path)
44
+ end
45
+
38
46
  end
39
47
  end
@@ -1,3 +1,3 @@
1
1
  module Evergreen
2
- VERSION = '0.2.1'
2
+ VERSION = '0.2.2'
3
3
  end
@@ -1,6 +1,67 @@
1
- <h1>JS Specs</h1>
1
+ <!doctype html>
2
2
 
3
- <% @specs.each do |spec| %>
4
- <p><a href="<%= url(spec.url) %>"><%= spec.name %></a></p>
5
- <% end %>
3
+ <html>
4
+ <head>
5
+ <title>Evergreen</title>
6
+ <style type="text/css">
7
+ * { margin: 0; padding: 0; }
8
+ body {
9
+ font-family: 'Lucida grande', 'sans-serif';
10
+ background: #f0f0f0;
11
+ }
12
+ a {
13
+ color: #00A500;
14
+ }
6
15
 
16
+ #page {
17
+ width: 800px;
18
+ background: white;
19
+ -moz-border-radius: 3px;
20
+ padding: 20px;
21
+ margin: 50px auto 30px;
22
+ border: 1px solid #ddd
23
+ }
24
+
25
+ #page h1 {
26
+ margin: 0 0 30px;
27
+ }
28
+
29
+ #page ul li {
30
+ list-style: none;
31
+ border: 1px solid #ddd;
32
+ -moz-border-radius: 3px;
33
+ margin: 10px 0;
34
+ background: #f5f5f5;
35
+ }
36
+
37
+ #page ul li a {
38
+ padding: 7px 10px;
39
+ display: block;
40
+ text-decoration: none;
41
+ }
42
+
43
+ #footer {
44
+ margin: 0 auto 30px;
45
+ width: 600px;
46
+ text-align: center;
47
+ font-size: 13px;
48
+ color: #aaa;
49
+ }
50
+ </style>
51
+ </head>
52
+ <body>
53
+ <div id="page">
54
+ <h1>Evergreen</h1>
55
+
56
+ <ul id="specs">
57
+ <% @specs.each do |spec| %>
58
+ <li><a href="<%= url(spec.url) %>"><%= spec.name %></a></li>
59
+ <% end %>
60
+ </ul>
61
+ </div>
62
+ <div id="footer">
63
+ Powered by <a href="http://github.com/jnicklas/evergreen">Evergreen</a>.
64
+ Evergreen is sponsored by <a href="http://elabs.se">Elabs</a>.
65
+ </div>
66
+ </body>
67
+ </html>
@@ -7,10 +7,54 @@
7
7
  <script type="text/javascript" src="<%= url("/lib/jasmine-html.js") %>"></script>
8
8
  <script type="text/javascript" src="<%= url("/evergreen/evergreen.js") %>"></script>
9
9
  <script type="text/javascript" src="<%= url("/spec/#{@spec.name}") %>"></script>
10
+ <% if @js_spec_helper.exist? %>
11
+ <script type="text/javascript" src="<%= url("/spec/#{@js_spec_helper.name}") %>"></script>
12
+ <% end %>
13
+ <% if @coffee_spec_helper.exist? %>
14
+ <script type="text/javascript" src="<%= url("/spec/#{@coffee_spec_helper.name}") %>"></script>
15
+ <% end %>
16
+ <style>
17
+ body {
18
+ font-family: 'Lucida grande', 'sans-serif';
19
+ background: #f0f0f0;
20
+ margin: 0;
21
+ padding: 0;
22
+ }
23
+ a {
24
+ color: #00A500;
25
+ }
26
+
27
+ .jasmine_reporter {
28
+ width: 800px;
29
+ background: white;
30
+ padding: 20px;
31
+ min-height: 50px;
32
+ margin: 30px auto 30px;
33
+ border: 1px solid #ddd;
34
+ -moz-border-radius: 3px;
35
+ width: 800px;
36
+ }
37
+ #test {
38
+ width: 800px;
39
+ background: white;
40
+ -moz-border-radius: 3px;
41
+ padding: 20px;
42
+ min-height: 50px;
43
+ margin: 50px auto 30px;
44
+ border: 1px solid #ddd
45
+ }
46
+ #footer {
47
+ margin: 0 auto 30px;
48
+ width: 600px;
49
+ text-align: center;
50
+ font-size: 13px;
51
+ color: #aaa;
52
+ }
53
+ </style>
10
54
  </head>
11
55
  <body>
12
- <div id="test">
13
- </div>
56
+ <div id="test">
57
+ </div>
14
58
  <script type="text/javascript">
15
59
  (function() {
16
60
  Evergreen.template = <%= @spec.template.to_json %>;
@@ -20,5 +64,9 @@
20
64
  jasmineEnv.execute();
21
65
  })();
22
66
  </script>
67
+ <div id="footer">
68
+ Powered by <a href="http://github.com/jnicklas/evergreen">Evergreen</a>.
69
+ Evergreen is sponsored by <a href="http://elabs.se">Elabs</a>.
70
+ </div>
23
71
  </body>
24
72
  </html>
@@ -5,13 +5,19 @@ describe Evergreen, ".application" do
5
5
 
6
6
  it "should show a successful test run" do
7
7
  visit("/")
8
- click_link("testing")
8
+ click_link("testing_spec.js")
9
+ page.should have_content("2 specs, 0 failures")
10
+ end
11
+
12
+ it "should show a successful test run for a coffeescript spec" do
13
+ visit("/")
14
+ click_link("coffeescript_spec.coffee")
9
15
  page.should have_content("2 specs, 0 failures")
10
16
  end
11
17
 
12
18
  it "should show errors for a failing spec" do
13
19
  visit("/")
14
- click_link("failing")
20
+ click_link("failing_spec.js")
15
21
  page.should have_content("2 specs, 1 failure")
16
22
  page.should have_content("Expected 'bar' to equal 'noooooo'.")
17
23
  end
@@ -0,0 +1,7 @@
1
+ describe 'coffeescript', ->
2
+
3
+ it "should pass", ->
4
+ expect('foo').toEqual('foo')
5
+
6
+ it "should also pass", ->
7
+ expect('bar').toEqual('bar')
@@ -0,0 +1 @@
1
+ window.CoffeeSpecHelper: { coffee: 'script' }
@@ -0,0 +1 @@
1
+ var SpecHelper = { spec: 'helper' };
@@ -0,0 +1,9 @@
1
+ describe('the spec helper', function() {
2
+ it("should load js file", function() {
3
+ expect(SpecHelper.spec).toEqual('helper');
4
+ });
5
+
6
+ it("should load coffee file", function() {
7
+ expect(CoffeeSpecHelper.coffee).toEqual('script');
8
+ });
9
+ });
@@ -9,6 +9,11 @@ describe Evergreen::Runner do
9
9
  it { should pass }
10
10
  end
11
11
 
12
+ context "with spec helper" do
13
+ let(:spec) { Evergreen::Spec.new(root, 'with_helper_spec.js') }
14
+ it { should pass }
15
+ end
16
+
12
17
  context "with template spec" do
13
18
  let(:spec) { Evergreen::Spec.new(root, 'templates_spec.js') }
14
19
  it { should pass }
@@ -15,7 +15,7 @@ describe Evergreen::Spec do
15
15
  subject { Evergreen::Spec.all(root) }
16
16
 
17
17
  it "should find all specs in the given root directory" do
18
- subject.map(&:name).should include('testing_spec.js', 'foo_spec.js', 'bar_spec.js')
18
+ subject.map(&:name).should include('testing_spec.js', 'foo_spec.js', 'bar_spec.js', 'coffeescript_spec.coffee')
19
19
  end
20
20
  end
21
21
 
@@ -24,7 +24,22 @@ describe Evergreen::Spec do
24
24
  its(:template) { should == %(<h1 id="from-template">This is from the template</h1>\n) }
25
25
  end
26
26
 
27
+ context "with coffeescript" do
28
+ subject { Evergreen::Spec.new(root, 'coffeescript_spec.coffee') }
29
+ its(:contents) { should =~ /describe\('coffeescript', function/ }
30
+ end
31
+
27
32
  context "without a template" do
28
33
  its(:template) { should == '' }
29
34
  end
35
+
36
+ context "with existing spec file" do
37
+ it { should exist }
38
+ end
39
+
40
+ context "with missing spec file" do
41
+ subject { Evergreen::Spec.new(root, 'does_not_exist.js') }
42
+ it { should_not exist }
43
+ end
44
+
30
45
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: evergreen
3
3
  version: !ruby/object:Gem::Version
4
- hash: 21
4
+ hash: 19
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 1
10
- version: 0.2.1
9
+ - 2
10
+ version: 0.2.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jonas Nicklas
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-07-09 00:00:00 +02:00
18
+ date: 2010-07-11 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -203,12 +203,16 @@ files:
203
203
  - spec/evergreen_spec.rb
204
204
  - spec/fixtures/public/jquery.js
205
205
  - spec/fixtures/spec/javascripts/bar_spec.js
206
+ - spec/fixtures/spec/javascripts/coffeescript_spec.coffee
206
207
  - spec/fixtures/spec/javascripts/failing_spec.js
207
208
  - spec/fixtures/spec/javascripts/foo_spec.js
209
+ - spec/fixtures/spec/javascripts/spec_helper.coffee
210
+ - spec/fixtures/spec/javascripts/spec_helper.js
208
211
  - spec/fixtures/spec/javascripts/templates_spec.html
209
212
  - spec/fixtures/spec/javascripts/templates_spec.js
210
213
  - spec/fixtures/spec/javascripts/testing_spec.js
211
214
  - spec/fixtures/spec/javascripts/transactions_spec.js
215
+ - spec/fixtures/spec/javascripts/with_helper_spec.js
212
216
  - spec/meta_spec.rb
213
217
  - spec/runner_spec.rb
214
218
  - spec/spec_helper.rb