remarkable 3.0.0
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.
- 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
|