abstract_mapper 0.0.1
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/.coveralls.yml +2 -0
- data/.gitignore +9 -0
- data/.metrics +9 -0
- data/.rspec +2 -0
- data/.rubocop.yml +2 -0
- data/.travis.yml +19 -0
- data/.yardopts +3 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +9 -0
- data/Guardfile +14 -0
- data/LICENSE +21 -0
- data/README.md +239 -0
- data/Rakefile +34 -0
- data/abstract_mapper.gemspec +26 -0
- data/config/metrics/STYLEGUIDE +230 -0
- data/config/metrics/cane.yml +5 -0
- data/config/metrics/churn.yml +6 -0
- data/config/metrics/flay.yml +2 -0
- data/config/metrics/metric_fu.yml +15 -0
- data/config/metrics/reek.yml +1 -0
- data/config/metrics/roodi.yml +24 -0
- data/config/metrics/rubocop.yml +76 -0
- data/config/metrics/saikuro.yml +3 -0
- data/config/metrics/simplecov.yml +6 -0
- data/config/metrics/yardstick.yml +37 -0
- data/lib/abstract_mapper/branch.rb +110 -0
- data/lib/abstract_mapper/builder.rb +84 -0
- data/lib/abstract_mapper/commands.rb +71 -0
- data/lib/abstract_mapper/dsl.rb +62 -0
- data/lib/abstract_mapper/errors/unknown_command.rb +25 -0
- data/lib/abstract_mapper/errors/wrong_node.rb +23 -0
- data/lib/abstract_mapper/errors/wrong_rule.rb +23 -0
- data/lib/abstract_mapper/functions.rb +76 -0
- data/lib/abstract_mapper/node.rb +76 -0
- data/lib/abstract_mapper/optimizer.rb +48 -0
- data/lib/abstract_mapper/pair_rule.rb +66 -0
- data/lib/abstract_mapper/rspec.rb +7 -0
- data/lib/abstract_mapper/rule.rb +52 -0
- data/lib/abstract_mapper/rules.rb +61 -0
- data/lib/abstract_mapper/settings.rb +95 -0
- data/lib/abstract_mapper/sole_rule.rb +58 -0
- data/lib/abstract_mapper/version.rb +9 -0
- data/lib/abstract_mapper.rb +82 -0
- data/lib/rspec/functions.rb +25 -0
- data/lib/rspec/mapper.rb +40 -0
- data/lib/rspec/nodes.rb +58 -0
- data/lib/rspec/rules.rb +59 -0
- data/spec/integration/faceter.rb +62 -0
- data/spec/integration/mapper_definition_spec.rb +33 -0
- data/spec/integration/rspec_examples_spec.rb +77 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/unit/abstract_mapper/branch_spec.rb +126 -0
- data/spec/unit/abstract_mapper/builder_spec.rb +78 -0
- data/spec/unit/abstract_mapper/commands_spec.rb +105 -0
- data/spec/unit/abstract_mapper/dsl_spec.rb +82 -0
- data/spec/unit/abstract_mapper/errors/unknown_command_spec.rb +21 -0
- data/spec/unit/abstract_mapper/errors/wrong_node_spec.rb +21 -0
- data/spec/unit/abstract_mapper/errors/wrong_rule_spec.rb +23 -0
- data/spec/unit/abstract_mapper/functions/compact_spec.rb +25 -0
- data/spec/unit/abstract_mapper/functions/filter_spec.rb +26 -0
- data/spec/unit/abstract_mapper/functions/subclass_spec.rb +66 -0
- data/spec/unit/abstract_mapper/node_spec.rb +84 -0
- data/spec/unit/abstract_mapper/optimizer_spec.rb +48 -0
- data/spec/unit/abstract_mapper/pair_rule_spec.rb +59 -0
- data/spec/unit/abstract_mapper/rule_spec.rb +83 -0
- data/spec/unit/abstract_mapper/rules_spec.rb +88 -0
- data/spec/unit/abstract_mapper/settings_spec.rb +113 -0
- data/spec/unit/abstract_mapper/sole_rule_spec.rb +51 -0
- data/spec/unit/abstract_mapper_spec.rb +36 -0
- metadata +171 -0
@@ -0,0 +1,62 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
shared_context "Faceter" do
|
4
|
+
|
5
|
+
before do
|
6
|
+
module Faceter
|
7
|
+
|
8
|
+
# Transproc functions
|
9
|
+
module Functions
|
10
|
+
extend Transproc::Registry
|
11
|
+
|
12
|
+
uses :map_array, from: Transproc::ArrayTransformations
|
13
|
+
uses :rename_keys, from: Transproc::HashTransformations
|
14
|
+
end
|
15
|
+
|
16
|
+
# Nodes
|
17
|
+
class List < AbstractMapper::Branch
|
18
|
+
def transproc
|
19
|
+
Functions[:map_array, super]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Rename < AbstractMapper::Node
|
24
|
+
def initialize(old, options = {})
|
25
|
+
@old = old
|
26
|
+
@new = options.fetch(:to)
|
27
|
+
super
|
28
|
+
end
|
29
|
+
|
30
|
+
def transproc
|
31
|
+
Functions[:rename_keys, @old => @new]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Rules
|
36
|
+
class CompactLists < AbstractMapper::PairRule
|
37
|
+
def optimize?
|
38
|
+
left.is_a?(List) && right.is_a?(List)
|
39
|
+
end
|
40
|
+
|
41
|
+
def optimize
|
42
|
+
List.new { left.entries + right.entries }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Registry
|
47
|
+
class Mapper < AbstractMapper
|
48
|
+
configure do
|
49
|
+
command :list, Faceter::List
|
50
|
+
command :rename, Faceter::Rename
|
51
|
+
|
52
|
+
rule Faceter::CompactLists
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end # module Faceter
|
57
|
+
|
58
|
+
end # before
|
59
|
+
|
60
|
+
after { Object.send :remove_const, :Faceter }
|
61
|
+
|
62
|
+
end # shared context
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require_relative "faceter"
|
4
|
+
|
5
|
+
describe "mapper definition" do
|
6
|
+
|
7
|
+
include_context "Faceter"
|
8
|
+
|
9
|
+
before do
|
10
|
+
class MyMapper < Faceter::Mapper
|
11
|
+
list do
|
12
|
+
rename :foo, to: :baz
|
13
|
+
end
|
14
|
+
|
15
|
+
list do
|
16
|
+
rename :bar, to: :qux
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
let(:mapper) { MyMapper.new }
|
22
|
+
let(:input) { [{ foo: :FOO, bar: :FOO }, { foo: :BAR, bar: :BAR }] }
|
23
|
+
let(:output) { [{ baz: :FOO, qux: :FOO }, { baz: :BAR, qux: :BAR }] }
|
24
|
+
|
25
|
+
it "works" do
|
26
|
+
expect(mapper.tree.inspect)
|
27
|
+
.to eql "<Root [<List [<Rename(:foo, {:to=>:baz})>, <Rename(:bar, {:to=>:qux})>]>]>"
|
28
|
+
expect(mapper.call input).to eql output
|
29
|
+
end
|
30
|
+
|
31
|
+
after { Object.send :remove_const, :MyMapper }
|
32
|
+
|
33
|
+
end # describe mapper definition
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require_relative "faceter"
|
4
|
+
|
5
|
+
require "abstract_mapper/rspec" # examples under the test
|
6
|
+
|
7
|
+
describe "rspec examples" do
|
8
|
+
|
9
|
+
include_context "Faceter"
|
10
|
+
|
11
|
+
describe "Faceter::Functions", "#rename_keys" do
|
12
|
+
|
13
|
+
let(:described_class) { Faceter::Functions }
|
14
|
+
|
15
|
+
it_behaves_like :transforming_immutable_data do
|
16
|
+
let(:arguments) { [:rename_keys, foo: :bar] }
|
17
|
+
let(:input) { { foo: :FOO, baz: :BAZ } }
|
18
|
+
let(:output) { { bar: :FOO, baz: :BAZ } }
|
19
|
+
end
|
20
|
+
|
21
|
+
end # describe Faceter::Functions
|
22
|
+
|
23
|
+
describe "Faceter::Rename" do
|
24
|
+
|
25
|
+
let(:described_class) { Faceter::Rename }
|
26
|
+
|
27
|
+
it_behaves_like :creating_immutable_node do
|
28
|
+
let(:attributes) { [:foo, to: :bar] }
|
29
|
+
end
|
30
|
+
|
31
|
+
it_behaves_like :mapping_immutable_input do
|
32
|
+
let(:attributes) { [:foo, to: :bar] }
|
33
|
+
let(:input) { { foo: :FOO, baz: :BAZ } }
|
34
|
+
let(:output) { { bar: :FOO, baz: :BAZ } }
|
35
|
+
end
|
36
|
+
|
37
|
+
end # describe Faceter::Rename
|
38
|
+
|
39
|
+
describe "Faceter::List" do
|
40
|
+
|
41
|
+
let(:described_class) { Faceter::List }
|
42
|
+
|
43
|
+
it_behaves_like :creating_immutable_branch
|
44
|
+
|
45
|
+
end # describe Faceter::List
|
46
|
+
|
47
|
+
describe "Faceter::CompactLists" do
|
48
|
+
|
49
|
+
let(:described_class) { Faceter::CompactLists }
|
50
|
+
|
51
|
+
it_behaves_like :skipping_nodes do
|
52
|
+
let(:input) { [Faceter::Rename.new(:foo, to: :bar), Faceter::List.new] }
|
53
|
+
end
|
54
|
+
|
55
|
+
it_behaves_like :optimizing_nodes do
|
56
|
+
let(:input) { [Faceter::List.new { [1] }, Faceter::List.new { [2] }] }
|
57
|
+
let(:output) { Faceter::List.new { [1, 2] } }
|
58
|
+
end
|
59
|
+
|
60
|
+
end # describe Faceter::CompactLists
|
61
|
+
|
62
|
+
describe "Faceter::Mapper" do
|
63
|
+
|
64
|
+
let(:described_class) { Faceter::Mapper }
|
65
|
+
|
66
|
+
it_behaves_like :defining_command do
|
67
|
+
let(:name) { :list }
|
68
|
+
let(:node) { Faceter::List }
|
69
|
+
end
|
70
|
+
|
71
|
+
it_behaves_like :defining_rule do
|
72
|
+
let(:rule) { Faceter::CompactLists }
|
73
|
+
end
|
74
|
+
|
75
|
+
end # describe Faceter::Mapper
|
76
|
+
|
77
|
+
end # describe mapper definition
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
begin
|
4
|
+
require "hexx-suit"
|
5
|
+
Hexx::Suit.load_metrics_for(self)
|
6
|
+
rescue LoadError
|
7
|
+
require "hexx-rspec"
|
8
|
+
Hexx::RSpec.load_metrics_for(self)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Loads the code under test
|
12
|
+
require "abstract_mapper"
|
13
|
+
|
14
|
+
RSpec.configure do |config|
|
15
|
+
config.around do |example|
|
16
|
+
class AbstractMapper::Test; end
|
17
|
+
example.run
|
18
|
+
AbstractMapper.send :remove_const, :Test
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe AbstractMapper::Branch do
|
4
|
+
|
5
|
+
let(:branch) { test.new(:foo) { [node1, node2] } }
|
6
|
+
let(:test) { AbstractMapper::Test::Foo = Class.new(described_class) }
|
7
|
+
let(:tproc) { Transproc::Function.new -> v { "#{v}-1" }, {} }
|
8
|
+
let(:node1) { instance_double AbstractMapper::Node, transproc: tproc }
|
9
|
+
let(:node2) { instance_double AbstractMapper::Node, transproc: tproc }
|
10
|
+
let(:node3) { instance_double AbstractMapper::Node, transproc: tproc }
|
11
|
+
|
12
|
+
describe ".new" do
|
13
|
+
|
14
|
+
subject { branch }
|
15
|
+
|
16
|
+
it { is_expected.to be_kind_of Enumerable }
|
17
|
+
it { is_expected.to be_frozen }
|
18
|
+
|
19
|
+
context "without a block" do
|
20
|
+
|
21
|
+
subject { test.new(:foo).entries }
|
22
|
+
it { is_expected.to be_empty }
|
23
|
+
|
24
|
+
end # context
|
25
|
+
|
26
|
+
context "with a block" do
|
27
|
+
|
28
|
+
subject { test.new(:foo) { [node1, node2] }.entries }
|
29
|
+
it { is_expected.to eql [node1, node2] }
|
30
|
+
|
31
|
+
end # context
|
32
|
+
|
33
|
+
end # describe .new
|
34
|
+
|
35
|
+
describe "#block" do
|
36
|
+
|
37
|
+
subject { branch.block }
|
38
|
+
it { is_expected.to be_nil }
|
39
|
+
|
40
|
+
end # describe #block
|
41
|
+
|
42
|
+
describe "#rebuild" do
|
43
|
+
|
44
|
+
subject { branch.rebuild { [node2, node3] } }
|
45
|
+
|
46
|
+
it { is_expected.to be_kind_of test }
|
47
|
+
|
48
|
+
it "preserves attributes" do
|
49
|
+
expect(subject.attributes).to eql branch.attributes
|
50
|
+
end
|
51
|
+
|
52
|
+
it "assings new subnodes from a block" do
|
53
|
+
expect(subject.entries).to eql [node2, node3]
|
54
|
+
end
|
55
|
+
|
56
|
+
end # describe #rebuild
|
57
|
+
|
58
|
+
describe "#each" do
|
59
|
+
|
60
|
+
let(:subnodes) { [node1, node2] }
|
61
|
+
|
62
|
+
context "with a block" do
|
63
|
+
|
64
|
+
subject { branch.each { |item| item } }
|
65
|
+
|
66
|
+
it "looks over subnodes" do
|
67
|
+
expect(subject).to eql subnodes
|
68
|
+
end
|
69
|
+
|
70
|
+
end # context
|
71
|
+
|
72
|
+
context "without a block" do
|
73
|
+
|
74
|
+
subject { branch.each }
|
75
|
+
|
76
|
+
it "returns Enumerator for subnodes" do
|
77
|
+
expect(subject).to be_kind_of Enumerator
|
78
|
+
expect(subject.entries).to eql subnodes
|
79
|
+
end
|
80
|
+
|
81
|
+
end # context
|
82
|
+
|
83
|
+
end # describe #each
|
84
|
+
|
85
|
+
describe "#<<" do
|
86
|
+
|
87
|
+
subject { branch << node3 }
|
88
|
+
|
89
|
+
it "returns the branch with updated subnodes and the same attributes" do
|
90
|
+
expect(subject).to be_kind_of test
|
91
|
+
expect(subject.attributes).to eql branch.attributes
|
92
|
+
expect(subject.entries).to eql [node1, node2, node3]
|
93
|
+
end
|
94
|
+
|
95
|
+
end # describe #<<
|
96
|
+
|
97
|
+
describe "#transproc" do
|
98
|
+
|
99
|
+
let(:data) { "baz" }
|
100
|
+
|
101
|
+
subject { branch.transproc[data] }
|
102
|
+
it { is_expected.to eql "baz-1-1" }
|
103
|
+
|
104
|
+
end # describe #transproc
|
105
|
+
|
106
|
+
describe "#to_s" do
|
107
|
+
|
108
|
+
subject { branch.to_s }
|
109
|
+
|
110
|
+
context "of the root" do
|
111
|
+
|
112
|
+
let(:branch) { described_class.new { [node1, node2] } }
|
113
|
+
it { is_expected.to eql "Root [#{node1.inspect}, #{node2.inspect}]" }
|
114
|
+
|
115
|
+
end # context
|
116
|
+
|
117
|
+
context "of the specific node" do
|
118
|
+
|
119
|
+
let(:branch) { test.new(:foo) { [node1, node2] } }
|
120
|
+
it { is_expected.to eql "Foo(:foo) [#{node1.inspect}, #{node2.inspect}]" }
|
121
|
+
|
122
|
+
end # context
|
123
|
+
|
124
|
+
end # describe #to_s
|
125
|
+
|
126
|
+
end # describe Branch
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe AbstractMapper::Builder do
|
4
|
+
|
5
|
+
before do
|
6
|
+
AbstractMapper::Test::Builder = Class.new(described_class)
|
7
|
+
AbstractMapper::Test::Foo = Class.new(AbstractMapper::Node)
|
8
|
+
AbstractMapper::Test::Bar = Class.new(AbstractMapper::Branch)
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:builder) { test.new tree }
|
12
|
+
let(:test) { AbstractMapper::Test::Builder }
|
13
|
+
let(:commands) { AbstractMapper::Commands.new(registry) }
|
14
|
+
let(:tree) { AbstractMapper::Test::Foo.new }
|
15
|
+
let(:registry) do
|
16
|
+
{ foo: AbstractMapper::Test::Foo, bar: AbstractMapper::Test::Bar }
|
17
|
+
end
|
18
|
+
|
19
|
+
describe ".commands=" do
|
20
|
+
|
21
|
+
subject { test.commands = commands }
|
22
|
+
|
23
|
+
it "sets the commands" do
|
24
|
+
expect { subject }.to change { test.commands }.to commands
|
25
|
+
end
|
26
|
+
|
27
|
+
end # describe .commands=
|
28
|
+
|
29
|
+
describe ".update" do
|
30
|
+
|
31
|
+
before { test.commands = commands }
|
32
|
+
|
33
|
+
context "by default" do
|
34
|
+
|
35
|
+
subject { test.update }
|
36
|
+
|
37
|
+
it "is an empty branch" do
|
38
|
+
expect(subject).to be_instance_of AbstractMapper::Branch
|
39
|
+
expect(subject.entries).to be_empty
|
40
|
+
end
|
41
|
+
|
42
|
+
end # context
|
43
|
+
|
44
|
+
context "initialized" do
|
45
|
+
|
46
|
+
subject { test.update(tree) }
|
47
|
+
it { is_expected.to eql tree }
|
48
|
+
|
49
|
+
end # context
|
50
|
+
|
51
|
+
context "with a block" do
|
52
|
+
|
53
|
+
subject { test.update { bar { foo(:foo) { fail } } } }
|
54
|
+
|
55
|
+
it "is built" do
|
56
|
+
expect(subject.inspect).to eql "<Root [<Bar [<Foo(:foo)>]>]>"
|
57
|
+
expect(subject.first.first.block).not_to be_nil
|
58
|
+
end
|
59
|
+
|
60
|
+
end # context
|
61
|
+
|
62
|
+
end # describe .update
|
63
|
+
|
64
|
+
describe ".new" do
|
65
|
+
|
66
|
+
subject { builder }
|
67
|
+
it { is_expected.to be_frozen }
|
68
|
+
|
69
|
+
end # describe .new
|
70
|
+
|
71
|
+
describe "#respond_to?" do
|
72
|
+
|
73
|
+
subject { builder.respond_to? :arbitrary_method }
|
74
|
+
it { is_expected.to eql true }
|
75
|
+
|
76
|
+
end # describe #respond_to?
|
77
|
+
|
78
|
+
end # describe AbstractMapper::Builder
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe AbstractMapper::Commands do
|
4
|
+
|
5
|
+
let(:commands) { test.new }
|
6
|
+
let(:test) { Class.new(described_class) }
|
7
|
+
let(:branch) { Class.new(AbstractMapper::Branch) }
|
8
|
+
|
9
|
+
describe ".new" do
|
10
|
+
|
11
|
+
subject { commands }
|
12
|
+
it { is_expected.to be_frozen }
|
13
|
+
|
14
|
+
end # describe .new
|
15
|
+
|
16
|
+
describe "#registry" do
|
17
|
+
|
18
|
+
subject { commands.registry }
|
19
|
+
|
20
|
+
context "with a hash" do
|
21
|
+
|
22
|
+
let(:commands) { test.new(registry) }
|
23
|
+
let(:registry) { { foo: branch } }
|
24
|
+
|
25
|
+
it { is_expected.to eql registry }
|
26
|
+
it { is_expected.to be_frozen }
|
27
|
+
|
28
|
+
it "doesn't freeze the source" do
|
29
|
+
expect { subject }.not_to change { registry.frozen? }
|
30
|
+
end
|
31
|
+
|
32
|
+
end # context
|
33
|
+
|
34
|
+
context "without a hash" do
|
35
|
+
|
36
|
+
let(:commands) { test.new }
|
37
|
+
|
38
|
+
it { is_expected.to eql({}) }
|
39
|
+
it { is_expected.to be_frozen }
|
40
|
+
|
41
|
+
end # context
|
42
|
+
|
43
|
+
end # describe #builder
|
44
|
+
|
45
|
+
describe "#<<" do
|
46
|
+
|
47
|
+
let(:commands) { test.new(foo: branch) }
|
48
|
+
|
49
|
+
subject { commands << ["bar", branch] }
|
50
|
+
|
51
|
+
it "registers a command" do
|
52
|
+
expect(subject).to be_kind_of test
|
53
|
+
expect(subject.registry).to eql(foo: branch, bar: branch)
|
54
|
+
end
|
55
|
+
|
56
|
+
end # describe #<<
|
57
|
+
|
58
|
+
describe "#[]" do
|
59
|
+
|
60
|
+
let(:block) { proc { [:foo] } }
|
61
|
+
let(:args) { [:baz, qux: :QUX] }
|
62
|
+
let(:commands) do
|
63
|
+
test.new(foo: AbstractMapper::Node, bar: AbstractMapper::Branch)
|
64
|
+
end
|
65
|
+
|
66
|
+
context "simple node" do
|
67
|
+
|
68
|
+
subject { commands["foo", *args, &block] }
|
69
|
+
|
70
|
+
it "builds a node with a block" do
|
71
|
+
expect(subject).to be_kind_of AbstractMapper::Node
|
72
|
+
expect(subject.attributes).to eql args
|
73
|
+
expect(subject.block).to eql block
|
74
|
+
end
|
75
|
+
|
76
|
+
end # context
|
77
|
+
|
78
|
+
context "branch command" do
|
79
|
+
|
80
|
+
subject { commands["bar", *args, &block] }
|
81
|
+
|
82
|
+
it "builds a branch" do
|
83
|
+
expect(subject).to be_kind_of AbstractMapper::Node
|
84
|
+
expect(subject.attributes).to eql args
|
85
|
+
expect(subject.entries).to eql []
|
86
|
+
end
|
87
|
+
|
88
|
+
end # context
|
89
|
+
|
90
|
+
context "unknown command" do
|
91
|
+
|
92
|
+
subject { commands["baz"] }
|
93
|
+
|
94
|
+
it "fails" do
|
95
|
+
expect { subject }.to raise_error do |error|
|
96
|
+
expect(error).to be_kind_of AbstractMapper::Errors::UnknownCommand
|
97
|
+
expect(error.message).to include "baz"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end # context
|
102
|
+
|
103
|
+
end # describe #build
|
104
|
+
|
105
|
+
end # describe AbstractMapper::Commands
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe AbstractMapper::DSL do
|
4
|
+
|
5
|
+
let!(:bar) { AbstractMapper::Test::Bar = Class.new(AbstractMapper::Branch) }
|
6
|
+
let!(:foo) { AbstractMapper::Test::Foo = Class.new(AbstractMapper::Node) }
|
7
|
+
let!(:rule) do
|
8
|
+
AbstractMapper::Test::Rule = Class.new(AbstractMapper::PairRule) do
|
9
|
+
def optimize?
|
10
|
+
left.instance_of?(AbstractMapper::Test::Foo)
|
11
|
+
end
|
12
|
+
|
13
|
+
def optimize
|
14
|
+
AbstractMapper::Test::Foo.new(nodes.flat_map(&:attributes))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
let!(:dsl) { Class.new { extend AbstractMapper::DSL } }
|
19
|
+
|
20
|
+
let!(:config) do
|
21
|
+
dsl.configure do
|
22
|
+
command :foo, AbstractMapper::Test::Foo
|
23
|
+
command :bar, AbstractMapper::Test::Bar
|
24
|
+
rule AbstractMapper::Test::Rule
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#configure" do
|
29
|
+
|
30
|
+
subject { config }
|
31
|
+
|
32
|
+
it { is_expected.to eql dsl }
|
33
|
+
|
34
|
+
it "configures settings" do
|
35
|
+
subject
|
36
|
+
expect(dsl.settings).to be_kind_of AbstractMapper::Settings
|
37
|
+
expect(dsl.settings.rules.registry).to eql [rule]
|
38
|
+
expect(dsl.settings.commands.registry).to eql(foo: foo, bar: bar)
|
39
|
+
end
|
40
|
+
|
41
|
+
end # describe #configure
|
42
|
+
|
43
|
+
describe "#finalize" do
|
44
|
+
|
45
|
+
before do
|
46
|
+
dsl.instance_eval do
|
47
|
+
bar :baz do
|
48
|
+
foo :qux
|
49
|
+
foo :quxx
|
50
|
+
end
|
51
|
+
foo :foo
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
subject { dsl.finalize }
|
56
|
+
|
57
|
+
it { is_expected.to be_kind_of AbstractMapper::Branch }
|
58
|
+
|
59
|
+
it "is optimized" do
|
60
|
+
expect(subject.inspect)
|
61
|
+
.to eql "<Root [<Bar(:baz) [<Foo([:qux, :quxx])>]>, <Foo(:foo)>]>"
|
62
|
+
end
|
63
|
+
|
64
|
+
end # describe #finalize
|
65
|
+
|
66
|
+
describe "#respond_to?" do
|
67
|
+
|
68
|
+
subject { dsl.respond_to? :anything }
|
69
|
+
it { is_expected.to eql true }
|
70
|
+
|
71
|
+
end # describe #respond_to?
|
72
|
+
|
73
|
+
describe ".inherited" do
|
74
|
+
|
75
|
+
let(:subklass) { Class.new(dsl) }
|
76
|
+
subject { subklass.settings }
|
77
|
+
|
78
|
+
it { is_expected.to eql dsl.settings }
|
79
|
+
|
80
|
+
end # describe .inherited
|
81
|
+
|
82
|
+
end # describe AbstractMapper::DSL
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe AbstractMapper::Errors::UnknownCommand do
|
4
|
+
|
5
|
+
subject(:error) { described_class.new :foo }
|
6
|
+
|
7
|
+
describe ".new" do
|
8
|
+
|
9
|
+
it { is_expected.to be_kind_of NameError }
|
10
|
+
it { is_expected.to be_frozen }
|
11
|
+
|
12
|
+
end # describe .new
|
13
|
+
|
14
|
+
describe "#message" do
|
15
|
+
|
16
|
+
subject { error.message }
|
17
|
+
it { is_expected.to eql "'foo' is not a registered DSL command" }
|
18
|
+
|
19
|
+
end # describe #message
|
20
|
+
|
21
|
+
end # describe AbstractMapper::Errors::UnknownCommand
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe AbstractMapper::Errors::WrongNode do
|
4
|
+
|
5
|
+
subject(:error) { described_class.new Symbol }
|
6
|
+
|
7
|
+
describe ".new" do
|
8
|
+
|
9
|
+
it { is_expected.to be_kind_of TypeError }
|
10
|
+
it { is_expected.to be_frozen }
|
11
|
+
|
12
|
+
end # describe .new
|
13
|
+
|
14
|
+
describe "#message" do
|
15
|
+
|
16
|
+
subject { error.message }
|
17
|
+
it { is_expected.to eql "Symbol is not a subclass of AbstractMapper::Node" }
|
18
|
+
|
19
|
+
end # describe #message
|
20
|
+
|
21
|
+
end # describe AbstractMapper::Errors::WrongNode
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe AbstractMapper::Errors::WrongRule do
|
4
|
+
|
5
|
+
subject(:error) { described_class.new Symbol }
|
6
|
+
|
7
|
+
describe ".new" do
|
8
|
+
|
9
|
+
it { is_expected.to be_kind_of TypeError }
|
10
|
+
it { is_expected.to be_frozen }
|
11
|
+
|
12
|
+
end # describe .new
|
13
|
+
|
14
|
+
describe "#message" do
|
15
|
+
|
16
|
+
subject { error.message }
|
17
|
+
it do
|
18
|
+
is_expected.to eql "Symbol is not a subclass of AbstractMapper::SoleRule"
|
19
|
+
end
|
20
|
+
|
21
|
+
end # describe #message
|
22
|
+
|
23
|
+
end # describe AbstractMapper::Errors::WrongRule
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "abstract_mapper/rspec"
|
4
|
+
|
5
|
+
describe AbstractMapper::Functions, "#compact" do
|
6
|
+
|
7
|
+
let(:function) { -> a, b { (a == b) ? [a + b] : [a, b] } }
|
8
|
+
let(:arguments) { [:compact, function] }
|
9
|
+
|
10
|
+
it_behaves_like :transforming_immutable_data do
|
11
|
+
let(:input) { [] }
|
12
|
+
let(:output) { [] }
|
13
|
+
end
|
14
|
+
|
15
|
+
it_behaves_like :transforming_immutable_data do
|
16
|
+
let(:input) { [1] }
|
17
|
+
let(:output) { [1] }
|
18
|
+
end
|
19
|
+
|
20
|
+
it_behaves_like :transforming_immutable_data do
|
21
|
+
let(:input) { [1, 1, 2, 3, 3] }
|
22
|
+
let(:output) { [4, 6] }
|
23
|
+
end
|
24
|
+
|
25
|
+
end # describe AbstractMapper::Functions#compact
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "abstract_mapper/rspec"
|
4
|
+
|
5
|
+
describe AbstractMapper::Functions, "#filter" do
|
6
|
+
|
7
|
+
let(:arguments) { [:filter, -> v { v - 1 if v > 3 }] }
|
8
|
+
|
9
|
+
it_behaves_like :transforming_immutable_data do
|
10
|
+
let(:input) { [] }
|
11
|
+
let(:output) { [] }
|
12
|
+
end
|
13
|
+
|
14
|
+
it_behaves_like :transforming_immutable_data do
|
15
|
+
let(:input) { [1, 4, 9, 7, 2, 5] }
|
16
|
+
let(:output) { [3, 8, 6, 4] }
|
17
|
+
end
|
18
|
+
|
19
|
+
it_behaves_like :transforming_immutable_data do
|
20
|
+
let(:arguments) { [:filter, -> v { [v - 1] if v > 3 }] }
|
21
|
+
|
22
|
+
let(:input) { [1, 4, 9, 7, 2, 5] }
|
23
|
+
let(:output) { [3, 8, 6, 4] }
|
24
|
+
end
|
25
|
+
|
26
|
+
end # describe AbstractMapper::Functions#filter
|