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.
- checksums.yaml +7 -0
- data/Gemfile +1 -5
- data/README.md +33 -41
- data/config.ru +5 -2
- data/example/Gemfile +4 -0
- data/example/README.md +8 -0
- data/example/Rakefile +10 -0
- data/example/opal/stack.rb +2 -0
- data/example/spec/spec_helper.rb +2 -0
- data/example/spec/stack_spec.rb +17 -0
- data/lib/opal/spec/rake_task.rb +17 -24
- data/lib/opal/spec/version.rb +1 -1
- data/lib/opal/spec.rb +1 -7
- data/opal/opal/spec/browser_formatter.rb +218 -0
- data/opal/opal/spec/expectations.rb +128 -0
- data/opal/opal/spec/matchers.rb +61 -0
- data/opal/opal/spec/object.rb +21 -0
- data/{lib/assets/javascripts → opal}/opal/spec/phantom_formatter.rb +6 -6
- data/{lib/assets/javascripts → opal}/opal/spec/runner.rb +6 -21
- data/opal/opal/spec/spec.rb +185 -0
- data/{lib/assets/javascripts → opal}/opal/spec/sprockets_runner.rb.erb +3 -3
- data/{lib/assets/javascripts → opal}/opal/spec.rb +3 -5
- data/opal-spec.gemspec +5 -0
- data/spec/matchers/be_empty_spec.rb +9 -0
- data/spec/matchers/respond_to_spec.rb +15 -0
- data/spec/specs_spec.rb +149 -0
- metadata +69 -25
- data/lib/assets/javascripts/opal/spec/browser_formatter.rb +0 -192
- data/lib/assets/javascripts/opal/spec/example.rb +0 -76
- data/lib/assets/javascripts/opal/spec/example_group.rb +0 -92
- data/lib/assets/javascripts/opal/spec/expectations.rb +0 -54
- data/lib/assets/javascripts/opal/spec/kernel.rb +0 -9
- data/lib/assets/javascripts/opal/spec/matchers.rb +0 -104
- data/lib/assets/javascripts/opal/spec/scratch_pad.rb +0 -17
- data/lib/opal/spec/server.rb +0 -63
- data/spec/specs.rb +0 -73
- data/vendor/spec_runner.html.erb +0 -9
- /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
data/README.md
CHANGED
|
@@ -23,14 +23,29 @@ describe MyClass do
|
|
|
23
23
|
end
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
###
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
data/example/Gemfile
ADDED
data/example/README.md
ADDED
data/example/Rakefile
ADDED
|
@@ -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
|
+
|
data/lib/opal/spec/rake_task.rb
CHANGED
|
@@ -1,30 +1,35 @@
|
|
|
1
1
|
require 'opal/spec'
|
|
2
|
-
require 'opal
|
|
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
|
-
|
|
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:
|
|
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
|
|
15
|
+
task name do
|
|
19
16
|
require 'rack'
|
|
20
17
|
require 'webrick'
|
|
21
18
|
|
|
22
19
|
server = fork do
|
|
23
|
-
|
|
24
|
-
|
|
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 #{
|
|
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
|
data/lib/opal/spec/version.rb
CHANGED
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.
|
|
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(/</, '<').gsub(/>/, '>')
|
|
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
|