opal-spec 0.2.10 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +1 -5
  3. data/README.md +33 -41
  4. data/config.ru +5 -2
  5. data/example/Gemfile +4 -0
  6. data/example/README.md +8 -0
  7. data/example/Rakefile +10 -0
  8. data/example/opal/stack.rb +2 -0
  9. data/example/spec/spec_helper.rb +2 -0
  10. data/example/spec/stack_spec.rb +17 -0
  11. data/lib/opal/spec/rake_task.rb +17 -24
  12. data/lib/opal/spec/version.rb +1 -1
  13. data/lib/opal/spec.rb +1 -7
  14. data/opal/opal/spec/browser_formatter.rb +218 -0
  15. data/opal/opal/spec/expectations.rb +128 -0
  16. data/opal/opal/spec/matchers.rb +61 -0
  17. data/opal/opal/spec/object.rb +21 -0
  18. data/{lib/assets/javascripts → opal}/opal/spec/phantom_formatter.rb +6 -6
  19. data/{lib/assets/javascripts → opal}/opal/spec/runner.rb +6 -21
  20. data/opal/opal/spec/spec.rb +185 -0
  21. data/{lib/assets/javascripts → opal}/opal/spec/sprockets_runner.rb.erb +3 -3
  22. data/{lib/assets/javascripts → opal}/opal/spec.rb +3 -5
  23. data/opal-spec.gemspec +5 -0
  24. data/spec/matchers/be_empty_spec.rb +9 -0
  25. data/spec/matchers/respond_to_spec.rb +15 -0
  26. data/spec/specs_spec.rb +149 -0
  27. metadata +69 -25
  28. data/lib/assets/javascripts/opal/spec/browser_formatter.rb +0 -192
  29. data/lib/assets/javascripts/opal/spec/example.rb +0 -76
  30. data/lib/assets/javascripts/opal/spec/example_group.rb +0 -92
  31. data/lib/assets/javascripts/opal/spec/expectations.rb +0 -54
  32. data/lib/assets/javascripts/opal/spec/kernel.rb +0 -9
  33. data/lib/assets/javascripts/opal/spec/matchers.rb +0 -104
  34. data/lib/assets/javascripts/opal/spec/scratch_pad.rb +0 -17
  35. data/lib/opal/spec/server.rb +0 -63
  36. data/spec/specs.rb +0 -73
  37. data/vendor/spec_runner.html.erb +0 -9
  38. /data/{lib/assets/javascripts → opal}/opal-spec.rb +0 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f1c0478a579f30dd1260e1eac1f4e7fc7ec7de64
4
+ data.tar.gz: 4d1bd16512841732a1dbb24c9af3094b380b7a4f
5
+ SHA512:
6
+ metadata.gz: a537c224a1e36c6c37ceb5dfc17efb60665fd14188a7d48f0052c449f1312e5caf97248371a1ea0d0d265ed2fad2bb1bd5210682cdd0eb56e396323662616e02
7
+ data.tar.gz: bd4212cc0da890c8036c7640f48c94282a5c82f90723d39cc2c0453d085f11cfef58dfc28869dc98de6b4902ebef0b566f5cde40b41ccb1541c8e3685fd626c0
data/Gemfile CHANGED
@@ -1,6 +1,2 @@
1
- source :rubygems
1
+ source 'https://rubygems.org'
2
2
  gemspec
3
-
4
- gem 'rake'
5
- gem 'opal'
6
- gem 'sprockets'
data/README.md CHANGED
@@ -23,14 +23,29 @@ describe MyClass do
23
23
  end
24
24
  ```
25
25
 
26
- ### Running specs
27
-
28
- Loading these specs in a browser won't just work. You need to run them.
29
- The best place to do this is inside `spec/spec_helper.rb`, and with a
30
- simple call:
31
-
32
- ```ruby
33
- Opal::Spec::Runner.autorun
26
+ ### Supported notations
27
+
28
+ ````
29
+ * describe "foo" do ... end
30
+ * it "should foo" do ... end
31
+ * before do ... end
32
+ * after do ... end
33
+ * let(:foo) { ... }
34
+ * async # see below
35
+
36
+ * obj.should == other
37
+ * obj.should != other
38
+ * obj.should be_nil
39
+ * obj.should be_true
40
+ * obj.should be_false
41
+ * obj.should be_kind_of(klass)
42
+ * obj.should eq(other) # compare with :==
43
+ * obj.should equal(other) # compare with :equal?
44
+ * obj.should raise_error
45
+ * obj.should be_empty
46
+ * obj.should respond_to(method)
47
+
48
+ * obj.should_not xxx
34
49
  ```
35
50
 
36
51
  ### Async examples
@@ -38,17 +53,17 @@ Opal::Spec::Runner.autorun
38
53
  Examples can be async, and need to be defined as so:
39
54
 
40
55
  ```ruby
41
- describe 'MyClass' do
42
- # normal, sync example
43
- it 'does something' do
44
- # ...
45
- end
46
-
47
- # async example
48
- async 'does something else too' do
49
- # ...
50
- end
56
+ describe 'MyClass' do
57
+ # normal, sync example
58
+ it 'does something' do
59
+ #...
60
+ end
61
+
62
+ # async example
63
+ async 'does something else too' do
64
+ #...
51
65
  end
66
+ end
52
67
  ```
53
68
 
54
69
  This just marks the example as being async. To actually handle the async
@@ -66,26 +81,3 @@ end
66
81
 
67
82
  The end of the block passed to `run_async` informs opal-spec that you are
68
83
  done with this test, so it can move on.
69
-
70
- Change Log
71
- ----------
72
-
73
- ### 0.2.7
74
-
75
- * Can be built using asset pipeline/sprockets
76
- * BrowserFormatter is now default
77
-
78
- ### 0.0.3
79
-
80
- * Allow group names to be non-strings
81
- * Nested groups now have outer group name as prefix
82
- * Nested groups should inherit `before` and `after` blocks
83
-
84
- ### 0.0.2
85
-
86
- * Added seperate BrowserFormatter class for cleaner output
87
- * Update Rake tasks to use new Opal::Builder class
88
-
89
- ### 0.0.1
90
-
91
- Initial release
data/config.ru CHANGED
@@ -1,5 +1,8 @@
1
1
  require 'bundler'
2
2
  Bundler.require
3
3
 
4
- require 'opal/spec/server'
5
- run Opal::Spec::Server.new
4
+ run Opal::Server.new { |s|
5
+ s.main = 'opal/spec/sprockets_runner'
6
+ s.append_path 'spec'
7
+ s.debug = false
8
+ }
data/example/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'opal'
4
+ gem 'opal-spec'
data/example/README.md ADDED
@@ -0,0 +1,8 @@
1
+ opal-spec example
2
+ =================
3
+
4
+ Running spec
5
+ ------------
6
+
7
+ $ bundle install
8
+ $ rake
data/example/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler'
2
+ Bundler.require
3
+
4
+ require 'opal'
5
+ # Help Opal to find your library in ./opal/
6
+ Opal.append_path File.expand_path("opal", File.dirname("__FILE__"))
7
+
8
+ require 'opal/spec/rake_task'
9
+ Opal::Spec::RakeTask.new(:default)
10
+
@@ -0,0 +1,2 @@
1
+ class Stack < Array
2
+ end
@@ -0,0 +1,2 @@
1
+ require 'opal-spec'
2
+ require 'stack'
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe Stack do
4
+ before do
5
+ @stack = Stack.new
6
+ end
7
+
8
+ it "should be initially empty" do
9
+ @stack.empty?.should be_true
10
+ end
11
+
12
+ it "can contain an object" do
13
+ @stack.push(1)
14
+ @stack.pop.should == 1
15
+ end
16
+ end
17
+
@@ -1,30 +1,35 @@
1
1
  require 'opal/spec'
2
- require 'opal/spec/server'
2
+ require 'opal-sprockets'
3
3
 
4
4
  module Opal
5
5
  module Spec
6
6
  class RakeTask
7
7
  include Rake::DSL if defined? Rake::DSL
8
8
 
9
- attr_accessor :name
9
+ RUNNER = File.expand_path('../../../../vendor/spec_runner.js', __FILE__)
10
+ PORT = 9999
11
+ URL = "http://localhost:9999/"
10
12
 
11
- def initialize(name = 'opal:spec')
12
- @name = name
13
- define_tasks
14
- end
15
-
16
- def define_tasks
13
+ def initialize(name = 'opal:test', &block)
17
14
  desc "Run opal specs in phantomjs"
18
- task @name do
15
+ task name do
19
16
  require 'rack'
20
17
  require 'webrick'
21
18
 
22
19
  server = fork do
23
- Rack::Server.start(:app => Opal::Spec::Server.new(false), :Port => port,
24
- :Logger => WEBrick::Log.new("/dev/null"), :AccessLog => [])
20
+ app = Opal::Server.new { |s|
21
+ s.main = 'opal/spec/sprockets_runner'
22
+ s.append_path 'spec'
23
+ s.debug = false
24
+
25
+ block.call s if block
26
+ }
27
+
28
+ Rack::Server.start(:app => app, :Port => PORT, :AccessLog => [],
29
+ :Logger => WEBrick::Log.new("/dev/null"))
25
30
  end
26
31
 
27
- system "phantomjs #{runner_path} \"#{url_path}\""
32
+ system "phantomjs #{RUNNER} \"#{URL}\""
28
33
  success = $?.success?
29
34
 
30
35
  Process.kill(:SIGINT, server)
@@ -33,18 +38,6 @@ module Opal
33
38
  exit 1 unless success
34
39
  end
35
40
  end
36
-
37
- def runner_path
38
- File.join(VENDOR_PATH, 'spec_runner.js')
39
- end
40
-
41
- def url_path
42
- "http://localhost:9999/"
43
- end
44
-
45
- def port
46
- 9999
47
- end
48
41
  end
49
42
  end
50
43
  end
@@ -1,5 +1,5 @@
1
1
  module Opal
2
2
  module Spec
3
- VERSION = '0.2.10'
3
+ VERSION = '0.3.2'
4
4
  end
5
5
  end
data/lib/opal/spec.rb CHANGED
@@ -1,11 +1,5 @@
1
1
  require 'opal'
2
2
  require 'opal/spec/version'
3
3
 
4
- module Opal
5
- module Spec
6
- VENDOR_PATH = File.join(File.dirname(__FILE__), '..', '..', 'vendor')
7
- end
8
- end
9
-
10
4
  # Just register our opal code path with opal build tools
11
- Opal.append_path File.join(File.dirname(__FILE__), '..', 'assets', 'javascripts')
5
+ Opal.append_path File.expand_path('../../../opal', __FILE__)
@@ -0,0 +1,218 @@
1
+ module OpalSpec
2
+ class BrowserFormatter
3
+ CSS = <<-CSS
4
+
5
+ body {
6
+ font-size: 14px;
7
+ font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
8
+ }
9
+
10
+ pre {
11
+ font-family: "Bitstream Vera Sans Mono", Monaco, "Lucida Console", monospace;
12
+ font-size: 12px;
13
+ color: #444444;
14
+ white-space: pre;
15
+ padding: 3px 0px 3px 12px;
16
+ margin: 0px 0px 8px;
17
+
18
+ background: #FAFAFA;
19
+ -webkit-box-shadow: rgba(0,0,0,0.07) 0 1px 2px inset;
20
+ -webkit-border-radius: 3px;
21
+ -moz-border-radius: 3px;
22
+ border-radius: 3px;
23
+ border: 1px solid #DDDDDD;
24
+ }
25
+
26
+ ul.example_groups {
27
+ list-style-type: none;
28
+ }
29
+
30
+ li.group.passed .group_description {
31
+ color: #597800;
32
+ font-weight: bold;
33
+ }
34
+
35
+ li.group.failed .group_description {
36
+ color: #FF000E;
37
+ font-weight: bold;
38
+ }
39
+
40
+ li.example.passed {
41
+ color: #597800;
42
+ }
43
+
44
+ li.example.failed {
45
+ color: #FF000E;
46
+ }
47
+
48
+ .examples {
49
+ list-style-type: none;
50
+ }
51
+ CSS
52
+
53
+ class Node
54
+
55
+ attr_reader :element
56
+
57
+ def self.create(tag)
58
+ new(`document.createElement(tag)`)
59
+ end
60
+
61
+ def initialize(element)
62
+ @element = element
63
+ end
64
+
65
+ def class_name=(name)
66
+ `#{ @element }.className = name`
67
+ end
68
+
69
+ def html=(html)
70
+ `#{ @element }.innerHTML = html`
71
+ end
72
+
73
+ def text=(text)
74
+ self.html = text.gsub(/</, '&lt').gsub(/>/, '&gt')
75
+ end
76
+
77
+ def type=(type)
78
+ `#{ @element }.type = type`
79
+ end
80
+
81
+ def append(child)
82
+ `#{ @element }.appendChild(#{ child.element })`
83
+ end
84
+
85
+ def css_text=(text)
86
+ %x{
87
+ if (#{ @element }.styleSheet) {
88
+ #{ @element }.styleSheet.cssText = text;
89
+ }
90
+ else {
91
+ #{ @element }.appendChild(document.createTextNode(text));
92
+ }
93
+ }
94
+ end
95
+
96
+ def style(name, value)
97
+ `#{@element}.style[name] = value`
98
+ end
99
+
100
+ def append_to_head
101
+ `document.getElementsByTagName('head')[0].appendChild(#{@element})`
102
+ end
103
+ end
104
+
105
+ def initialize
106
+ @examples = []
107
+ @failed_examples = []
108
+ end
109
+
110
+ def start
111
+ raise "Not running in browser" unless Runner.in_browser?
112
+
113
+ @summary_element = Node.create 'p'
114
+ @summary_element.class_name = "summary"
115
+ @summary_element.text = "Runner..."
116
+
117
+ @groups_element = Node.create("ul")
118
+ @groups_element.class_name = "example_groups"
119
+
120
+ target = Node.new(`document.body`)
121
+ target.append @summary_element
122
+ target.append @groups_element
123
+
124
+ styles = Node.create "style"
125
+ styles.type = "text/css"
126
+ styles.css_text = CSS
127
+ styles.append_to_head
128
+
129
+ @start_time = Time.now.to_f
130
+ end
131
+
132
+ def finish
133
+ time = Time.now.to_f - @start_time
134
+ text = "\n#{example_count} examples, #{@failed_examples.size} failures (time taken: #{time})"
135
+
136
+ @summary_element.text = text
137
+ end
138
+
139
+ def example_group_started group
140
+ @example_group = group
141
+ @example_group_failed = false
142
+
143
+ @group_element = Node.create("li")
144
+
145
+ description = Node.create("span")
146
+ description.class_name = "group_description"
147
+ description.text = group.description.to_s
148
+ @group_element.append description
149
+
150
+ @example_list = Node.create "ul"
151
+ @example_list.class_name = "examples"
152
+ @group_element.append @example_list
153
+
154
+ @groups_element.append @group_element
155
+ end
156
+
157
+ def example_group_finished group
158
+ if @example_group_failed
159
+ @group_element.class_name = "group failed"
160
+ else
161
+ @group_element.class_name = "group passed"
162
+ end
163
+ end
164
+
165
+ def example_started example
166
+ @examples << example
167
+ @example = example
168
+ end
169
+
170
+ def example_failed example
171
+ @failed_examples << example
172
+ @example_group_failed = true
173
+
174
+ exception = example.exception
175
+
176
+ case exception
177
+ when OpalSpec::ExpectationNotMetError
178
+ output = exception.message
179
+ else
180
+ output = "#{exception.class.name}: #{exception.message}\n"
181
+ output += " #{exception.backtrace.join "\n "}\n"
182
+ end
183
+
184
+ wrapper = Node.create "li"
185
+ wrapper.class_name = "example failed"
186
+
187
+ description = Node.create "span"
188
+ description.class_name = "example_description"
189
+ description.text = example.description.to_s
190
+
191
+ exception = Node.create "pre"
192
+ exception.class_name = "exception"
193
+ exception.text = output
194
+
195
+ wrapper.append description
196
+ wrapper.append exception
197
+
198
+ @example_list.append wrapper
199
+ @example_list.style :display, "list-item"
200
+ end
201
+
202
+ def example_passed example
203
+ wrapper = Node.create "li"
204
+ wrapper.class_name = "example passed"
205
+
206
+ description = Node.create "span"
207
+ description.class_name = "example_description"
208
+ description.text = example.description.to_s
209
+
210
+ wrapper.append description
211
+ @example_list.append wrapper
212
+ end
213
+
214
+ def example_count
215
+ @examples.size
216
+ end
217
+ end
218
+ end
@@ -0,0 +1,128 @@
1
+ module OpalSpec
2
+ class ExpectationNotMetError < StandardError; end
3
+
4
+ module Expectations; end
5
+
6
+ def self.matcher name, &block
7
+ klass = Class.new(Matcher, &block)
8
+
9
+ klass.define_method(:matcher_name) do
10
+ name
11
+ end
12
+
13
+ Expectations.define_method(name) do |*args|
14
+ klass.new(*args)
15
+ end
16
+ end
17
+
18
+ matcher :be_nil do
19
+ def match expected, actual
20
+ actual.nil?
21
+ end
22
+
23
+ def failure_message_for_should
24
+ "expected #{expected.inspect} to be nil."
25
+ end
26
+ end
27
+
28
+ matcher :be_true do
29
+ def match expected, actual
30
+ actual == true
31
+ end
32
+
33
+ def failure_message_for_should
34
+ "expected #{actual.inspect} to be true."
35
+ end
36
+ end
37
+
38
+ matcher :be_false do
39
+ def match expected, actual
40
+ actual == false
41
+ end
42
+
43
+ def failure_message_for_should
44
+ "expected #{actual.inspect} to be false."
45
+ end
46
+ end
47
+
48
+ matcher :be_kind_of do
49
+ def match expected, actual
50
+ actual.kind_of? expected
51
+ end
52
+
53
+ def failure_message_for_should
54
+ "expected #{actual.inspect} to be a kind of #{expected.name}, not #{actual.class.name}."
55
+ end
56
+ end
57
+
58
+ matcher :eq do
59
+ def match expected, actual
60
+ expected == actual
61
+ end
62
+
63
+ def failure_message_for_should
64
+ "expected #{expected.inspect}, got: #{actual.inspect} (using ==)."
65
+ end
66
+
67
+ def failure_message_for_should_not
68
+ "expected #{expected.inspect}, not to be: #{actual.inspect} (using ==)."
69
+ end
70
+ end
71
+
72
+ matcher :equal do
73
+ def match expected, actual
74
+ expected.equal? actual
75
+ end
76
+
77
+ def failure_message_for_should
78
+ "expected #{actual.inspect} to be the same as #{expected.inspect}."
79
+ end
80
+
81
+ def failure_message_for_should_not
82
+ "expected #{actual.inspect} to not be equal to #{expected.inspect}."
83
+ end
84
+ end
85
+
86
+ matcher :raise_error do
87
+ def initialize(&block)
88
+ @block = block
89
+ end
90
+
91
+ def match expected, actual
92
+ ok = true
93
+
94
+ begin
95
+ @block.call
96
+ ok = false
97
+ rescue => e
98
+ @error = e
99
+ end
100
+
101
+ ok
102
+ end
103
+
104
+ def failure_message_for_should
105
+ "expected #{actual} to be raised, but nothing was."
106
+ end
107
+ end
108
+
109
+ matcher :be_empty do
110
+ def match expected, actual
111
+ actual.empty?
112
+ end
113
+
114
+ def failure_message_for_should
115
+ "expected #{actual.inspect} to be empty"
116
+ end
117
+ end
118
+
119
+ matcher :respond_to do
120
+ def match expected, actual
121
+ actual.respond_to? expected
122
+ end
123
+
124
+ def failure_message_for_should
125
+ "expected #{actual.inspect} (#{actual.class}) to respond to #{expected}."
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,61 @@
1
+ module OpalSpec
2
+ class Matcher
3
+ attr_reader :actual, :expected
4
+
5
+ def initialize expected = nil
6
+ @expected = expected
7
+ end
8
+
9
+ def positive_match? actual
10
+ @actual = actual
11
+
12
+ unless match expected, actual
13
+ raise OpalSpec::ExpectationNotMetError, failure_message_for_should
14
+ end
15
+ end
16
+
17
+ def negative_match? actual
18
+ @actual = actual
19
+
20
+ if match expected, actual
21
+ raise OpalSpec::ExpectationNotMetError, failure_message_for_should_not
22
+ end
23
+ end
24
+
25
+ def failure_message_for_should
26
+ "expected: #{expected.inspect}, actual: #{actual.inspect} (#{matcher_name}) [should]."
27
+ end
28
+
29
+ def failure_message_for_should_not
30
+ "expected: #{expected.inspect}, actual: #{actual.inspect} (#{matcher_name}) [should_not]."
31
+ end
32
+ end
33
+
34
+ class PositiveOperatorMatcher < Matcher
35
+ def == actual
36
+ @actual = actual
37
+
38
+ unless expected == actual
39
+ raise Opal::Spec::ExpectationNotMetError, failure_message_for_should
40
+ end
41
+ end
42
+
43
+ def failure_message_for_should
44
+ "expected #{actual.inspect}, but got: #{expected.inspect} (using ==)."
45
+ end
46
+ end
47
+
48
+ class NegativeOperatorMatcher < Matcher
49
+ def == actual
50
+ @actual = actual
51
+
52
+ if expected == actual
53
+ raise Opal::Spec::ExpectationNotMetError, failure_message_for_should_not
54
+ end
55
+ end
56
+
57
+ def failure_message_for_should_not
58
+ "expected #{actual.inspect} not to be: #{expected.inspect} (using ==)."
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,21 @@
1
+ class Object
2
+ def describe desc, &block
3
+ OpalSpec::Example.create desc, block
4
+ end
5
+
6
+ def should matcher = nil
7
+ if matcher
8
+ matcher.positive_match? self
9
+ else
10
+ OpalSpec::PositiveOperatorMatcher.new self
11
+ end
12
+ end
13
+
14
+ def should_not matcher = nil
15
+ if matcher
16
+ matcher.negative_match? self
17
+ else
18
+ OpalSpec::NegativeOperatorMatcher.new self
19
+ end
20
+ end
21
+ end