opal-rspec 0.0.1.beta1
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/.gitignore +3 -0
- data/Gemfile +15 -0
- data/README.md +78 -0
- data/Rakefile +46 -0
- data/app/rspec-builder.rb +10 -0
- data/app/rspec/core.rb +202 -0
- data/app/rspec/core/configuration.rb +1070 -0
- data/app/rspec/core/example_group.rb +573 -0
- data/app/rspec/core/project_initializer.rb +0 -0
- data/app/rspec/core/shared_example_group.rb +146 -0
- data/app/rspec/core/shared_example_group/collection.rb +27 -0
- data/app/rspec/matchers/built_in/have.rb +0 -0
- data/config.ru +10 -0
- data/lib/opal-rspec.rb +2 -0
- data/lib/opal/rspec.rb +6 -0
- data/lib/opal/rspec/rake_task.rb +44 -0
- data/lib/opal/rspec/version.rb +6 -0
- data/opal-rspec.gemspec +23 -0
- data/opal/opal-rspec.rb +1 -0
- data/opal/opal/rspec.rb +21 -0
- data/opal/opal/rspec/browser_formatter.rb +194 -0
- data/opal/opal/rspec/fixes.rb +62 -0
- data/opal/opal/rspec/runner.rb +52 -0
- data/opal/opal/rspec/sprockets_runner.rb.erb +11 -0
- data/opal/opal/rspec/text_formatter.rb +74 -0
- data/spec/example_spec.rb +143 -0
- data/spec/matchers_spec.rb +181 -0
- data/vendor/spec_runner.js +41 -0
- metadata +113 -0
@@ -0,0 +1,62 @@
|
|
1
|
+
# String#<< is not supported by Opal
|
2
|
+
module RSpec::Expectations
|
3
|
+
def self.fail_with(message, expected = nil, actual = nil)
|
4
|
+
if !message
|
5
|
+
raise ArgumentError, "Failure message is nil. Does your matcher define the " +
|
6
|
+
"appropriate failure_message_for_* method to return a string?"
|
7
|
+
end
|
8
|
+
|
9
|
+
raise RSpec::Expectations::ExpectationNotMetError.new(message)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# Opal does not support mutable strings
|
14
|
+
module RSpec::Matchers::Pretty
|
15
|
+
def underscore(camel_cased_word)
|
16
|
+
word = camel_cased_word.to_s.dup
|
17
|
+
word = word.gsub(/([A-Z]+)([A-Z][a-z])/,'$1_$2')
|
18
|
+
word = word.gsub(/([a-z\d])([A-Z])/,'$1_$2')
|
19
|
+
word = word.tr("-", "_")
|
20
|
+
word = word.downcase
|
21
|
+
word
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Opal does not yet support $1..$9 backrefs
|
26
|
+
class RSpec::Matchers::BuiltIn::BePredicate
|
27
|
+
def prefix_and_expected(symbol)
|
28
|
+
symbol.to_s =~ /^(be_(an?_)?)(.*)/
|
29
|
+
return $~[1], $~[3]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
module RSpec::ExampleGroups
|
34
|
+
def self.base_name_for(group)
|
35
|
+
return "Anonymous" if group.description.empty?
|
36
|
+
|
37
|
+
# convert to CamelCase
|
38
|
+
name = ' ' + group.description
|
39
|
+
name = name.gsub(/[^0-9a-zA-Z]+([0-9a-zA-Z])/) { |m| m[1].upcase }
|
40
|
+
|
41
|
+
name = name.lstrip # Remove leading whitespace
|
42
|
+
name = name.gsub(/\W/, '') # JRuby, RBX and others don't like non-ascii in const names
|
43
|
+
|
44
|
+
# Ruby requires first const letter to be A-Z. Use `Nested`
|
45
|
+
# as necessary to enforce that.
|
46
|
+
name = name.gsub(/\A([^A-Z]|\z)/, 'Nested$1')
|
47
|
+
|
48
|
+
name
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.disambiguate(name, const_scope)
|
52
|
+
return name unless const_scope.const_defined?(name)
|
53
|
+
|
54
|
+
# Add a trailing number if needed to disambiguate from an existing constant.
|
55
|
+
name = name + "_2"
|
56
|
+
while const_scope.const_defined?(name)
|
57
|
+
name = name.next
|
58
|
+
end
|
59
|
+
|
60
|
+
name
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Opal
|
2
|
+
module RSpec
|
3
|
+
class Runner
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def browser?
|
7
|
+
`typeof(document) !== "undefined"`
|
8
|
+
end
|
9
|
+
|
10
|
+
def phantom?
|
11
|
+
`typeof(phantom) !== 'undefined' || typeof(OPAL_SPEC_PHANTOM) !== 'undefined'`
|
12
|
+
end
|
13
|
+
|
14
|
+
def default_formatter
|
15
|
+
if phantom?
|
16
|
+
TextFormatter
|
17
|
+
else # browser
|
18
|
+
BrowserFormatter
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def autorun
|
23
|
+
if browser?
|
24
|
+
`setTimeout(function() { #{Runner.new.run} }, 0)`
|
25
|
+
else # phantom
|
26
|
+
Runner.new.run
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def initialize(options={}, configuration=::RSpec::configuration, world=::RSpec::world)
|
32
|
+
@options = options
|
33
|
+
@configuration = configuration
|
34
|
+
@world = world
|
35
|
+
end
|
36
|
+
|
37
|
+
def run(err=$stdout, out=$stdout)
|
38
|
+
@configuration.error_stream = err
|
39
|
+
@configuration.output_stream ||= out
|
40
|
+
|
41
|
+
@configuration.reporter.report(@world.example_count) do |reporter|
|
42
|
+
begin
|
43
|
+
@configuration.run_hook(:before, :suite)
|
44
|
+
@world.example_groups.map {|g| g.run(reporter) }.all? ? 0 : @configuration.failure_exit_code
|
45
|
+
ensure
|
46
|
+
@configuration.run_hook(:after, :suite)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# This file is used by Opal::Server to basically load all spec files that
|
2
|
+
# can be found in the spec/ directory.
|
3
|
+
|
4
|
+
<% require_asset 'opal' %>
|
5
|
+
<% require_asset 'opal-rspec' %>
|
6
|
+
|
7
|
+
<% Dir.glob('spec/**/*_spec.{rb,opal}').each do |s| %>
|
8
|
+
<% require_asset s.sub(/^spec\//, '').sub(/\.(rb|opal)$/, '') %>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
Opal::RSpec::Runner.autorun
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Opal
|
2
|
+
module RSpec
|
3
|
+
class TextFormatter < ::RSpec::Core::Formatters::BaseFormatter
|
4
|
+
|
5
|
+
def dump_failures
|
6
|
+
if failed_examples.empty?
|
7
|
+
puts "\nFinished"
|
8
|
+
else
|
9
|
+
puts "\nFailures:"
|
10
|
+
failed_examples.each_with_index do |example, index|
|
11
|
+
puts "\n"
|
12
|
+
dump_failure(example, index)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def dump_failure(example, index)
|
18
|
+
puts "#{short_padding}#{index.next}) #{example.full_description}"
|
19
|
+
dump_failure_info(example)
|
20
|
+
end
|
21
|
+
|
22
|
+
def dump_failure_info(example)
|
23
|
+
exception = example.execution_result[:exception]
|
24
|
+
exception_class_name = exception.class.name.to_s
|
25
|
+
red "#{long_padding}#{exception_class_name}:"
|
26
|
+
exception.message.to_s.split("\n").each { |line| red "#{long_padding} #{line}" }
|
27
|
+
end
|
28
|
+
|
29
|
+
def dump_summary(duration, example_count, failure_count, pending_count)
|
30
|
+
@duration = duration
|
31
|
+
@example_count = example_count
|
32
|
+
@failure_count = failure_count
|
33
|
+
@pending_count = pending_count
|
34
|
+
|
35
|
+
msg = "\n#{example_count} examples, #{failure_count} failures (time taken: #{duration})"
|
36
|
+
|
37
|
+
if failure_count == 0
|
38
|
+
green msg
|
39
|
+
finish_with_code(0)
|
40
|
+
else
|
41
|
+
red msg
|
42
|
+
finish_with_code(1)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def finish_with_code(code)
|
47
|
+
%x{
|
48
|
+
if (typeof(phantom) !== "undefined") {
|
49
|
+
phantom.exit(code);
|
50
|
+
}
|
51
|
+
else {
|
52
|
+
Opal.global.OPAL_SPEC_CODE = code;
|
53
|
+
}
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
def green(str)
|
58
|
+
`console.log('\\033[32m' + str + '\\033[0m')`
|
59
|
+
end
|
60
|
+
|
61
|
+
def red(str)
|
62
|
+
`console.log('\\033[31m' + str + '\\033[0m')`
|
63
|
+
end
|
64
|
+
|
65
|
+
def short_padding
|
66
|
+
' '
|
67
|
+
end
|
68
|
+
|
69
|
+
def long_padding
|
70
|
+
' '
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
module SomeHelpers
|
2
|
+
def opal_rspec_helper
|
3
|
+
let(:defined_opal_helper) { :it_works }
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
module SomeMoreHelpers
|
8
|
+
def opal_rspec_include_helper
|
9
|
+
42
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
RSpec.configure do |c|
|
14
|
+
c.extend SomeHelpers
|
15
|
+
c.include SomeMoreHelpers
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "RSpec include and extend" do
|
19
|
+
opal_rspec_helper
|
20
|
+
|
21
|
+
it "works for extend" do
|
22
|
+
defined_opal_helper.should == :it_works
|
23
|
+
end
|
24
|
+
|
25
|
+
it "works for include" do
|
26
|
+
opal_rspec_include_helper.should == 42
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
$count = 0
|
31
|
+
|
32
|
+
describe "let" do
|
33
|
+
let(:count) { $count += 1 }
|
34
|
+
|
35
|
+
it "memoizes the value" do
|
36
|
+
count.should eq(1)
|
37
|
+
count.should eq(1)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "is not cached across examples" do
|
41
|
+
count.should eq(2)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "helper methods" do
|
46
|
+
def some_helper
|
47
|
+
:present
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should be available" do
|
51
|
+
some_helper.should eq(:present)
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "nested group" do
|
55
|
+
it "should work in nested groups" do
|
56
|
+
some_helper.should eq(:present)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "nested describes" do
|
62
|
+
it "works in multiple places" do
|
63
|
+
1.should eq(1)
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "nested" do
|
67
|
+
it "and here" do
|
68
|
+
1.should_not eq(2)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "subject" do
|
74
|
+
subject { [1, 2, 3] }
|
75
|
+
|
76
|
+
it "a new instance should be the subject" do
|
77
|
+
subject.should be_kind_of(Array)
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "nested subjects" do
|
81
|
+
before { subject << 4 }
|
82
|
+
|
83
|
+
it "should work with before and example" do
|
84
|
+
subject.should == [1, 2, 3, 4]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe Hash do
|
90
|
+
it "should create a new instance of subject for classes" do
|
91
|
+
subject.should == {}
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "Simple expectations" do
|
96
|
+
before do
|
97
|
+
@bar = 200
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should eat" do
|
101
|
+
@bar.should == 200
|
102
|
+
end
|
103
|
+
|
104
|
+
after do
|
105
|
+
@bar.class
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe "should syntax" do
|
110
|
+
it "should work for positive" do
|
111
|
+
[1, 2, 3].should == [1, 2, 3]
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should work for negative" do
|
115
|
+
[1, 2, 3].should_not == [4, 5, 6]
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "expect syntax" do
|
120
|
+
it "positive expectation" do
|
121
|
+
expect(100).to eq(100)
|
122
|
+
end
|
123
|
+
|
124
|
+
it "negative expectation" do
|
125
|
+
expect(100).to_not eq(300)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe "Normal errors" do
|
130
|
+
it "should still work" do
|
131
|
+
lambda { raise "wtf son" }.should raise_error(Exception)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe "let on an inner scope" do
|
136
|
+
describe "inner context" do
|
137
|
+
let(:foo) { :bar }
|
138
|
+
|
139
|
+
it "should still work" do
|
140
|
+
foo.should eq(:bar)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
describe "be_truthy" do
|
2
|
+
it "passes with truthy values" do
|
3
|
+
expect(true).to be_truthy
|
4
|
+
expect(1.0).to be_truthy
|
5
|
+
expect([]).to be_truthy
|
6
|
+
end
|
7
|
+
|
8
|
+
it "fails with falsey values" do
|
9
|
+
expect {
|
10
|
+
expect(false).to be_truthy
|
11
|
+
}.to raise_error(Exception)
|
12
|
+
|
13
|
+
expect {
|
14
|
+
expect(nil).to be_truthy
|
15
|
+
}.to raise_error(Exception)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "be_falsey" do
|
20
|
+
it "passes with falsey values" do
|
21
|
+
expect(false).to be_falsey
|
22
|
+
expect(nil).to be_falsey
|
23
|
+
end
|
24
|
+
|
25
|
+
it "fails with truthy values" do
|
26
|
+
expect {
|
27
|
+
expect(true).to be_falsey
|
28
|
+
}.to raise_error(Exception)
|
29
|
+
|
30
|
+
expect {
|
31
|
+
expect({}).to be_falsey
|
32
|
+
}.to raise_error(Exception)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "be_nil" do
|
37
|
+
it "passes when object is nil" do
|
38
|
+
expect(nil).to be_nil
|
39
|
+
end
|
40
|
+
|
41
|
+
it "fails with any other object" do
|
42
|
+
expect {
|
43
|
+
expect(false).to be_nil
|
44
|
+
}.to raise_error(Exception)
|
45
|
+
|
46
|
+
expect {
|
47
|
+
expect(:foo).to be_nil
|
48
|
+
}.to raise_error(Exception)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "be_kind_of" do
|
53
|
+
it "passes if actual is kind of expected class" do
|
54
|
+
expect("foo").to be_kind_of(String)
|
55
|
+
expect("foo").to_not be_kind_of(Numeric)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "passes if actual is kind of superclass of expected class" do
|
59
|
+
expect([]).to be_kind_of(Object)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "fails if expected is not a kind of expected" do
|
63
|
+
expect {
|
64
|
+
expect("foo").to be_kind_of(Integer)
|
65
|
+
}.to raise_error(Exception)
|
66
|
+
|
67
|
+
expect {
|
68
|
+
expect("foo").to_not be_kind_of(String)
|
69
|
+
}.to raise_error(Exception)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "eq" do
|
74
|
+
it "matches when actual == expected" do
|
75
|
+
expect(:foo).to eq(:foo)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "does not match when actual != expected" do
|
79
|
+
expect(:foo).not_to eq(42)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "fails if matcher does not match" do
|
83
|
+
expect {
|
84
|
+
expect(:foo).to eq(42)
|
85
|
+
}.to raise_error(Exception)
|
86
|
+
|
87
|
+
expect {
|
88
|
+
expect(:foo).not_to eq(:foo)
|
89
|
+
}.to raise_error(Exception)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "eql" do
|
94
|
+
it "matches when expected.eql?(actual)" do
|
95
|
+
expect(1).to eql(1)
|
96
|
+
end
|
97
|
+
|
98
|
+
it "does not match when !expected.eql?(actual)" do
|
99
|
+
expect(1).to_not eql(:foo)
|
100
|
+
end
|
101
|
+
|
102
|
+
it "fails if matcher does not match" do
|
103
|
+
expect {
|
104
|
+
expect(1).to eql(:bar)
|
105
|
+
}.to raise_error(Exception)
|
106
|
+
|
107
|
+
expect {
|
108
|
+
expect(2).to_not eql(2)
|
109
|
+
}.to raise_error(Exception)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe "include" do
|
114
|
+
it "matches if actual includes expected" do
|
115
|
+
expect("foo").to include("f")
|
116
|
+
expect([:foo, :bar, :baz]).to include(:baz)
|
117
|
+
expect({ :yellow => 'lorry' }).to include(:yellow)
|
118
|
+
end
|
119
|
+
|
120
|
+
it "does not match if actual does not inlcude expected" do
|
121
|
+
expect("foo").to_not include("b")
|
122
|
+
expect([:foo, :bar, :baz]).to_not include(:kapow)
|
123
|
+
expect({ :yellow => 'lorry' }).to_not include(:red)
|
124
|
+
end
|
125
|
+
|
126
|
+
it "fails if matcher does not match" do
|
127
|
+
expect {
|
128
|
+
expect("bar").to include("z")
|
129
|
+
}.to raise_error(Exception)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe "respond_to" do
|
134
|
+
it "matches if actual responds to sym" do
|
135
|
+
expect("foo").to respond_to(:upcase)
|
136
|
+
end
|
137
|
+
|
138
|
+
it "does not match if actual does not respond to sym" do
|
139
|
+
expect(Object.new).to_not respond_to(:upcase)
|
140
|
+
end
|
141
|
+
|
142
|
+
it "fails if actual does not respond to sym" do
|
143
|
+
expect {
|
144
|
+
expect(Object.new).to respond_to(:upcase)
|
145
|
+
}.to raise_error(Exception)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe "match" do
|
150
|
+
it "matches if actual matches expected" do
|
151
|
+
expect("foobar").to match(/ar/)
|
152
|
+
expect("foobar").to match("oob")
|
153
|
+
end
|
154
|
+
|
155
|
+
it "does not match if actual does not match expected" do
|
156
|
+
expect("foobar").to_not match(/baz/)
|
157
|
+
expect("foobar").to_not match("woosh")
|
158
|
+
end
|
159
|
+
|
160
|
+
it "fails unless matcher matches" do
|
161
|
+
expect {
|
162
|
+
exprct("hello").to match(/world/)
|
163
|
+
}.to raise_error(Exception)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
describe "operator ==" do
|
168
|
+
it "matches if actual == expected" do
|
169
|
+
"hello".should == "hello"
|
170
|
+
end
|
171
|
+
|
172
|
+
it "does not match when actual does not == expected" do
|
173
|
+
"hello".should_not == "world"
|
174
|
+
end
|
175
|
+
|
176
|
+
it "fails unless matcher matches" do
|
177
|
+
expect {
|
178
|
+
"hello".should == "world"
|
179
|
+
}.to raise_error(Exception)
|
180
|
+
end
|
181
|
+
end
|