remarkable 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +16 -0
- data/LICENSE +20 -0
- data/README +2 -0
- data/lib/remarkable/base.rb +54 -0
- data/lib/remarkable/core_ext/array.rb +19 -0
- data/lib/remarkable/dsl/assertions.rb +184 -0
- data/lib/remarkable/dsl/callbacks.rb +54 -0
- data/lib/remarkable/dsl/matches.rb +142 -0
- data/lib/remarkable/dsl/optionals.rb +142 -0
- data/lib/remarkable/dsl.rb +39 -0
- data/lib/remarkable/i18n.rb +54 -0
- data/lib/remarkable/macros.rb +48 -0
- data/lib/remarkable/matchers.rb +19 -0
- data/lib/remarkable/messages.rb +98 -0
- data/lib/remarkable/pending.rb +33 -0
- data/lib/remarkable/rspec.rb +26 -0
- data/lib/remarkable/version.rb +3 -0
- data/lib/remarkable.rb +20 -0
- data/locale/en.yml +14 -0
- data/spec/base_spec.rb +42 -0
- data/spec/dsl/assertions_spec.rb +54 -0
- data/spec/dsl/optionals_spec.rb +42 -0
- data/spec/i18n_spec.rb +41 -0
- data/spec/locale/en.yml +19 -0
- data/spec/locale/pt-BR.yml +21 -0
- data/spec/macros_spec.rb +26 -0
- data/spec/matchers/be_a_person_matcher.rb +25 -0
- data/spec/matchers/collection_contain_matcher.rb +32 -0
- data/spec/matchers/contain_matcher.rb +31 -0
- data/spec/matchers/single_contain_matcher.rb +50 -0
- data/spec/messages_spec.rb +65 -0
- data/spec/pending_spec.rb +12 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +16 -0
- metadata +105 -0
data/lib/remarkable.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# Load core files
|
2
|
+
dir = File.dirname(__FILE__)
|
3
|
+
require File.join(dir, 'remarkable', 'version')
|
4
|
+
require File.join(dir, 'remarkable', 'matchers')
|
5
|
+
require File.join(dir, 'remarkable', 'i18n')
|
6
|
+
require File.join(dir, 'remarkable', 'dsl')
|
7
|
+
require File.join(dir, 'remarkable', 'messages')
|
8
|
+
|
9
|
+
require File.join(dir, 'remarkable', 'base')
|
10
|
+
require File.join(dir, 'remarkable', 'macros')
|
11
|
+
require File.join(dir, 'remarkable', 'pending')
|
12
|
+
require File.join(dir, 'remarkable', 'core_ext', 'array')
|
13
|
+
|
14
|
+
# Loads rspec files only if spec is defined
|
15
|
+
if defined?(Spec)
|
16
|
+
require File.join(dir, 'remarkable', 'rspec')
|
17
|
+
end
|
18
|
+
|
19
|
+
# Add Remarkable default locale file
|
20
|
+
Remarkable.add_locale File.join(dir, '..', 'locale', 'en.yml')
|
data/locale/en.yml
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
en:
|
2
|
+
remarkable:
|
3
|
+
core:
|
4
|
+
not: "not"
|
5
|
+
should: "should"
|
6
|
+
should_not: "should not"
|
7
|
+
example_disabled: "Example disabled"
|
8
|
+
failure_message_for_should: "Expected {{expectation}}"
|
9
|
+
failure_message_for_should_not: "Did not expect {{expectation}}"
|
10
|
+
|
11
|
+
helpers:
|
12
|
+
words_connector: ", "
|
13
|
+
two_words_connector: " and "
|
14
|
+
last_word_connector: ", and "
|
data/spec/base_spec.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe Remarkable::Base do
|
4
|
+
subject { [1, 2, 3] }
|
5
|
+
|
6
|
+
it 'should provide default structure to matchers' do
|
7
|
+
[1, 2, 3].should contain(1)
|
8
|
+
[1, 2, 3].should contain(1, 2)
|
9
|
+
[1, 2, 3].should contain(1, 2, 3)
|
10
|
+
|
11
|
+
[1, 2, 3].should_not contain(4)
|
12
|
+
[1, 2, 3].should_not contain(1, 4)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should not change rspec matchers default behavior' do
|
16
|
+
should include(3)
|
17
|
+
[1, 2, 3].should include(3)
|
18
|
+
|
19
|
+
1.should == 1
|
20
|
+
true.should be_true
|
21
|
+
false.should be_false
|
22
|
+
proc{ 1 + '' }.should raise_error(TypeError)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should store spec instance binding' do
|
26
|
+
matcher = contain(1)
|
27
|
+
should matcher
|
28
|
+
matcher.instance_variable_get('@spec').class.ancestors.should include(Spec::Example::ExampleGroup)
|
29
|
+
end
|
30
|
+
|
31
|
+
it { should contain(1) }
|
32
|
+
it { should_not contain(10) }
|
33
|
+
|
34
|
+
class MatchersSandbox
|
35
|
+
include Remarkable::Matchers
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should allow Macros and Matchers to be added to any class' do
|
39
|
+
MatchersSandbox.new.should respond_to(:contain)
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Remarkable::DSL::Assertions do
|
4
|
+
subject { [1, 2, 3] }
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@matcher = Remarkable::Specs::Matchers::CollectionContainMatcher.new(1, 2, 3)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should provide default structure for assertions' do
|
11
|
+
should collection_contain(1)
|
12
|
+
should collection_contain(1, 2)
|
13
|
+
should collection_contain(1, 2, 3)
|
14
|
+
|
15
|
+
should_not collection_contain(4)
|
16
|
+
should_not collection_contain(1, 4)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should provide default structure for single assertions' do
|
20
|
+
should single_contain(1)
|
21
|
+
should_not single_contain(4)
|
22
|
+
nil.should_not single_contain(1)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should provide collection in description' do
|
26
|
+
@matcher.description.should == 'contain 1, 2, and 3'
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should provide value to expectation messages' do
|
30
|
+
@matcher.matches?([4])
|
31
|
+
@matcher.failure_message.should == 'Expected that 1 is included in [4]'
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should accept blocks as argument' do
|
35
|
+
should_not single_contain(4)
|
36
|
+
should single_contain(4){ |array| array << 4 }
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should provide an interface for default_options hook' do
|
40
|
+
matcher = Remarkable::Specs::Matchers::CollectionContainMatcher.new(1, :args => true)
|
41
|
+
matcher.instance_variable_get('@options').should == { :working => true, :args => true }
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should provide an interface for after_initialize hook' do
|
45
|
+
matcher = Remarkable::Specs::Matchers::CollectionContainMatcher.new(1)
|
46
|
+
matcher.instance_variable_get('@after_initialize').should be_true
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should provide an interface for before_assert hook' do
|
50
|
+
matcher = Remarkable::Specs::Matchers::CollectionContainMatcher.new(1)
|
51
|
+
[1, 2, 3].should matcher
|
52
|
+
matcher.instance_variable_get('@before_assert').should be_true
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Remarkable::DSL::Optionals do
|
4
|
+
before(:each) do
|
5
|
+
@matcher = Remarkable::Specs::Matchers::BeAPersonMatcher.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should create optional methods on the fly" do
|
9
|
+
@matcher.first_name('José')
|
10
|
+
@matcher.instance_variable_get('@options')[:first_name].should == 'José'
|
11
|
+
|
12
|
+
@matcher.last_name('Valim')
|
13
|
+
@matcher.instance_variable_get('@options')[:last_name].should == 'Valim'
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should allow defaults values" do
|
17
|
+
@matcher.age
|
18
|
+
@matcher.instance_variable_get('@options')[:age].should == 18
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should allow alias to be set" do
|
22
|
+
@matcher.family_name('Valim')
|
23
|
+
@matcher.instance_variable_get('@options')[:last_name].should == 'Valim'
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should provide a description with optionals' do
|
27
|
+
@matcher = Remarkable::Specs::Matchers::SingleContainMatcher.new(1)
|
28
|
+
@matcher.description.should == 'contain 1 not checking for blank'
|
29
|
+
|
30
|
+
@matcher.allow_blank(10)
|
31
|
+
@matcher.description.should == 'contain 1 with blank equal 10'
|
32
|
+
|
33
|
+
@matcher.allow_blank(true)
|
34
|
+
@matcher.description.should == 'contain 1 with blank equal true'
|
35
|
+
|
36
|
+
@matcher.allow_nil(true)
|
37
|
+
@matcher.description.should == 'contain 1 allowing nil and with blank equal true'
|
38
|
+
|
39
|
+
@matcher.allow_nil(false)
|
40
|
+
@matcher.description.should == 'contain 1 not allowing nil and with blank equal true'
|
41
|
+
end
|
42
|
+
end
|
data/spec/i18n_spec.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe Remarkable::I18n do
|
4
|
+
subject { [1, 2, 3] }
|
5
|
+
|
6
|
+
before(:all) do
|
7
|
+
Remarkable.locale = :"pt-BR"
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should have a locale apart from I18n' do
|
11
|
+
I18n.locale.should_not == Remarkable.locale
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should delegate translate to I18n API overwriting the default locale' do
|
15
|
+
::I18n.should_receive(:translate).with('remarkable.core.not', :locale => :"pt-BR").and_return('translated')
|
16
|
+
Remarkable.t('remarkable.core.not').should == 'translated'
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should delegate localize to I18n API overwriting the default locale' do
|
20
|
+
::I18n.should_receive(:localize).with('remarkable.core.not', :locale => :"pt-BR").and_return('localized')
|
21
|
+
Remarkable.l('remarkable.core.not').should == 'localized'
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should delegate add_locale to I18n backend' do
|
25
|
+
backend = mock(::I18n::Backend)
|
26
|
+
::I18n.should_receive(:backend).and_return(backend)
|
27
|
+
backend.should_receive(:load_translations).with('a', 'b', 'c')
|
28
|
+
|
29
|
+
Remarkable.add_locale('a', 'b', 'c')
|
30
|
+
end
|
31
|
+
|
32
|
+
after(:all) do
|
33
|
+
Remarkable.locale = :en
|
34
|
+
end
|
35
|
+
|
36
|
+
Remarkable.locale = :"pt-BR"
|
37
|
+
should_collection_contain(1)
|
38
|
+
should_not_collection_contain(4)
|
39
|
+
xshould_not_collection_contain(5)
|
40
|
+
Remarkable.locale = :en
|
41
|
+
end
|
data/spec/locale/en.yml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
en:
|
2
|
+
remarkable:
|
3
|
+
specs:
|
4
|
+
contain:
|
5
|
+
description: "contain the given values"
|
6
|
+
single_contain:
|
7
|
+
description: "contain {{value}}"
|
8
|
+
optionals:
|
9
|
+
allow_nil:
|
10
|
+
positive: "allowing nil"
|
11
|
+
negative: "not allowing nil"
|
12
|
+
allow_blank:
|
13
|
+
positive: "with blank equal {{inspect}}"
|
14
|
+
not_given: "not checking for blank"
|
15
|
+
collection_contain:
|
16
|
+
description: "contain {{values}}"
|
17
|
+
expectations:
|
18
|
+
included: "{{more}}{{value}} is included in {{subject_inspect}}"
|
19
|
+
is_array?: "subject is a array, but got {{subject_name}}"
|
@@ -0,0 +1,21 @@
|
|
1
|
+
pt-BR:
|
2
|
+
remarkable:
|
3
|
+
core:
|
4
|
+
not: não
|
5
|
+
should: deve
|
6
|
+
should_not: não deve
|
7
|
+
example_disabled: Exemplo desativado
|
8
|
+
failure_message_for_should: Esperava que {{expectation}}
|
9
|
+
failure_message_for_should_not: Não esperava que {{expectation}}
|
10
|
+
|
11
|
+
helpers:
|
12
|
+
words_connector: ', '
|
13
|
+
two_words_connector: ' e '
|
14
|
+
last_word_connector: ' e '
|
15
|
+
|
16
|
+
specs:
|
17
|
+
collection_contain:
|
18
|
+
description: "conter os valores fornecidos"
|
19
|
+
expectations:
|
20
|
+
included: "{{value}} estivesse incluso em {{subject_inspect}}"
|
21
|
+
is_array?: "valor dado é um array, mas é {{subject_name}}"
|
data/spec/macros_spec.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe Remarkable::Macros do
|
4
|
+
subject { [1, 2, 3] }
|
5
|
+
|
6
|
+
should_contain(1)
|
7
|
+
should_contain(1, 2)
|
8
|
+
should_contain(1, 2, 3)
|
9
|
+
|
10
|
+
should_not_contain(4)
|
11
|
+
should_not_contain(1, 4)
|
12
|
+
|
13
|
+
describe "with disabled examples" do
|
14
|
+
# Example disabled without parameters to ensure rescue works properly
|
15
|
+
xshould_not_single_contain
|
16
|
+
xshould_contain(5)
|
17
|
+
xshould_not_contain(1)
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "with blocks" do
|
21
|
+
subject { [1, 2, 3] }
|
22
|
+
|
23
|
+
should_not_single_contain(4)
|
24
|
+
should_single_contain(4){ |array| array << 4 }
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Remarkable
|
2
|
+
module Specs
|
3
|
+
module Matchers
|
4
|
+
class BeAPersonMatcher < Remarkable::Base
|
5
|
+
arguments
|
6
|
+
|
7
|
+
optional :first_name
|
8
|
+
optional :age, :default => 18
|
9
|
+
optional :last_name, :alias => :family_name
|
10
|
+
|
11
|
+
def description
|
12
|
+
"be a person"
|
13
|
+
end
|
14
|
+
|
15
|
+
def expectation
|
16
|
+
"is not a person"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def be_a_person(*args, &block)
|
21
|
+
BeAPersonMatcher.new(*args, &block).spec(self)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Remarkable
|
2
|
+
module Specs
|
3
|
+
module Matchers
|
4
|
+
class CollectionContainMatcher < Remarkable::Base
|
5
|
+
arguments :collection => :values, :as => :value
|
6
|
+
|
7
|
+
optional :working
|
8
|
+
default_options :working => true
|
9
|
+
|
10
|
+
assertion :is_array? do
|
11
|
+
@subject.is_a?(Array)
|
12
|
+
end
|
13
|
+
|
14
|
+
collection_assertion :included? do
|
15
|
+
return @subject.include?(@value), :more => 'that '
|
16
|
+
end
|
17
|
+
|
18
|
+
after_initialize do
|
19
|
+
@after_initialize = true
|
20
|
+
end
|
21
|
+
|
22
|
+
before_assert do
|
23
|
+
@before_assert = true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def collection_contain(*args)
|
28
|
+
CollectionContainMatcher.new(*args).spec(self)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Remarkable
|
2
|
+
module Specs
|
3
|
+
module Matchers
|
4
|
+
class ContainMatcher < Remarkable::Base
|
5
|
+
def initialize(*values)
|
6
|
+
@values = values
|
7
|
+
end
|
8
|
+
|
9
|
+
def matches?(subject)
|
10
|
+
@subject = subject
|
11
|
+
|
12
|
+
assert_matcher_for(@values) do |value|
|
13
|
+
@value = value
|
14
|
+
included?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def included?
|
19
|
+
return true if @subject.include?(@value)
|
20
|
+
|
21
|
+
@expectation = "#{@value} is included in #{@subject.inspect}"
|
22
|
+
false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def contain(*args)
|
27
|
+
ContainMatcher.new(*args).spec(self)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Remarkable
|
2
|
+
module Specs
|
3
|
+
module Matchers
|
4
|
+
class SingleContainMatcher < Remarkable::Base
|
5
|
+
arguments :value, :block => :iterator
|
6
|
+
|
7
|
+
assertions :is_array?, :included?
|
8
|
+
|
9
|
+
optional :allow_nil
|
10
|
+
optional :allow_blank
|
11
|
+
|
12
|
+
after_initialize :set_after_initialize
|
13
|
+
|
14
|
+
before_assert do
|
15
|
+
@before_assert = true
|
16
|
+
@iterator.call(@subject) if @iterator
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def included?
|
22
|
+
return true if @subject.include?(@value)
|
23
|
+
|
24
|
+
@expectation = "#{@value} is not included in #{@subject.inspect}"
|
25
|
+
false
|
26
|
+
end
|
27
|
+
|
28
|
+
def is_array?
|
29
|
+
return true if @subject.is_a?(Array)
|
30
|
+
|
31
|
+
@expectation = "subject is a #{subject_name}"
|
32
|
+
false
|
33
|
+
end
|
34
|
+
|
35
|
+
def default_options
|
36
|
+
{ :working => true }
|
37
|
+
end
|
38
|
+
|
39
|
+
def set_after_initialize
|
40
|
+
@after_initialize = true
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
def single_contain(*args, &block)
|
46
|
+
SingleContainMatcher.new(*args, &block).spec(self)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe Remarkable::Messages do
|
4
|
+
subject { [1, 2, 3] }
|
5
|
+
|
6
|
+
describe 'without I18n' do
|
7
|
+
before(:each) do
|
8
|
+
@matcher = Remarkable::Specs::Matchers::ContainMatcher.new(1, 2, 3)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should provide a description' do
|
12
|
+
@matcher.description.should == 'contain the given values'
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should provide a failure message' do
|
16
|
+
@matcher.matches?([4])
|
17
|
+
@matcher.failure_message.should == 'Expected 1 is included in [4]'
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should provide a negative failure message' do
|
21
|
+
@matcher.matches?([1])
|
22
|
+
@matcher.negative_failure_message.should == 'Did not expect 2 is included in [1]'
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should provide a not word' do
|
26
|
+
@matcher.send(:not_word).should == 'not '
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'with I18n' do
|
31
|
+
before(:all) do
|
32
|
+
Remarkable.locale = :"pt-BR"
|
33
|
+
end
|
34
|
+
|
35
|
+
before(:each) do
|
36
|
+
@matcher = Remarkable::Specs::Matchers::CollectionContainMatcher.new(1, 2, 3)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should provide a default i18n scope' do
|
40
|
+
@matcher.send(:matcher_i18n_scope).should == 'remarkable.specs.collection_contain'
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should provide a translated description' do
|
44
|
+
@matcher.description.should == 'conter os valores fornecidos'
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should provide a translated failure message' do
|
48
|
+
@matcher.matches?([4])
|
49
|
+
@matcher.failure_message.should == 'Esperava que 1 estivesse incluso em [4]'
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should provide a translated negative failure message' do
|
53
|
+
@matcher.matches?([1])
|
54
|
+
@matcher.negative_failure_message.should == 'Não esperava que 2 estivesse incluso em [1]'
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should provide an i18n not word' do
|
58
|
+
@matcher.send(:not_word).should == 'não '
|
59
|
+
end
|
60
|
+
|
61
|
+
after(:all) do
|
62
|
+
Remarkable.locale = :en
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|