transproc 0.2.4 → 0.3.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.
@@ -1,6 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Transproc::Recursion do
4
+ let(:hashes) { Transproc::HashTransformations }
5
+
4
6
  describe '.recursion' do
5
7
  let(:original) do
6
8
  {
@@ -28,7 +30,7 @@ describe Transproc::Recursion do
28
30
 
29
31
  context 'when function is non-destructive' do
30
32
  let(:map) do
31
- t(:recursion, -> enum {
33
+ described_class.t(:recursion, -> enum {
32
34
  enum.reject { |v| v == 'baz' }
33
35
  })
34
36
  end
@@ -41,7 +43,7 @@ describe Transproc::Recursion do
41
43
 
42
44
  context 'when function is destructive' do
43
45
  let(:map) do
44
- t(:recursion, -> enum {
46
+ described_class.t(:recursion, -> enum {
45
47
  enum.reject! { |v| v == 'baz' }
46
48
  })
47
49
  end
@@ -87,7 +89,7 @@ describe Transproc::Recursion do
87
89
  end
88
90
 
89
91
  context 'when function is non-destructive' do
90
- let(:map) { t(:array_recursion, proc(&:compact)) }
92
+ let(:map) { described_class.t(:array_recursion, proc(&:compact)) }
91
93
 
92
94
  it 'applies funtions to all items recursively' do
93
95
  expect(map[input]).to eql(output)
@@ -96,7 +98,7 @@ describe Transproc::Recursion do
96
98
  end
97
99
 
98
100
  context 'when function is destructive' do
99
- let(:map) { t(:array_recursion, proc(&:compact!)) }
101
+ let(:map) { described_class.t(:array_recursion, proc(&:compact!)) }
100
102
 
101
103
  it 'applies funtions to all items recursively and destructively' do
102
104
  expect(map[input]).to eql(output)
@@ -135,7 +137,9 @@ describe Transproc::Recursion do
135
137
  end
136
138
 
137
139
  context 'when function is non-destructive' do
138
- let(:map) { t(:hash_recursion, t(:symbolize_keys)) }
140
+ let(:map) do
141
+ described_class.t(:hash_recursion, hashes.t(:symbolize_keys))
142
+ end
139
143
 
140
144
  it 'applies funtions to all values recursively' do
141
145
  expect(map[input]).to eql(output)
@@ -144,7 +148,9 @@ describe Transproc::Recursion do
144
148
  end
145
149
 
146
150
  context 'when function is destructive' do
147
- let(:map) { t(:hash_recursion, t(:symbolize_keys!)) }
151
+ let(:map) do
152
+ described_class.t(:hash_recursion, hashes.t(:symbolize_keys!))
153
+ end
148
154
 
149
155
  it 'applies funtions to all values recursively and destructively' do
150
156
  expect(map[input]).to eql(output)
@@ -1,95 +1,105 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Transproc::Registry do
4
- before do
5
- module FooModule
4
+ before { module Transproc::Test; end }
5
+ after { Transproc.send :remove_const, :Test }
6
+
7
+ let(:foo) do
8
+ Transproc::Test::Foo = Module.new do
6
9
  extend Transproc::Registry
7
10
 
8
- def foo(value, prefix)
9
- [prefix, '_', value].join
11
+ def self.prefix(value, prefix)
12
+ "#{prefix}_#{value}"
10
13
  end
11
14
  end
15
+ end
16
+ let(:bar) { Transproc::Test::Bar = Module.new { extend Transproc::Registry } }
17
+ let(:baz) { Transproc::Test::Baz = Module.new { extend Transproc::Registry } }
18
+
19
+ describe '.[]' do
20
+ subject(:transproc) { foo[fn, 'baz'] }
12
21
 
13
- module BarModule
14
- include FooModule
22
+ context 'from a method' do
23
+ let(:fn) { :prefix }
15
24
 
16
- def bar(*args)
17
- foo(*args).upcase
25
+ it 'builds a function from a method' do
26
+ expect(transproc['qux']).to eql 'baz_qux'
18
27
  end
19
28
  end
20
29
 
21
- module BazModule
22
- extend Transproc::Registry
30
+ context 'from a closure' do
31
+ let(:fn) { -> value, prefix { [prefix, '_', value].join } }
32
+
33
+ it 'builds a function from a method' do
34
+ expect(transproc['qux']).to eql 'baz_qux'
35
+ end
23
36
  end
24
37
  end
25
38
 
26
- describe '.[]' do
27
- it 'builds function from the method' do
28
- fn = ::FooModule[:foo, 'baz']
39
+ describe '.t' do
40
+ subject(:transproc) { foo.t(:prefix, 'baz') }
29
41
 
30
- expect(fn['qux']).to eql 'baz_qux'
42
+ it 'is an alias for .[]' do
43
+ expect(transproc['qux']).to eql 'baz_qux'
31
44
  end
45
+ end
32
46
 
33
- it 'builds function from the proc' do
34
- fun = -> value, prefix { [prefix, '_', value].join }
35
- fn = ::FooModule[fun, 'baz']
36
-
37
- expect(fn['qux']).to eql 'baz_qux'
38
- end
47
+ describe '.import' do
48
+ context 'a module' do
49
+ subject(:import) { bar.import foo }
39
50
 
40
- it 'builds function using methods from included modules' do
41
- fn = ::BarModule[:bar, 'baz']
51
+ it 'registers all its methods' do
52
+ import
53
+ expect(bar[:prefix, 'baz']['qux']).to eql 'baz_qux'
54
+ end
42
55
 
43
- expect(fn['qux']).to eql 'BAZ_QUX'
56
+ it 'returns itself' do
57
+ expect(import).to eq bar
58
+ end
44
59
  end
45
60
 
46
- it 'can access methods from included modules directly' do
47
- fn = ::BarModule[:foo, 'baz']
61
+ context 'a method' do
62
+ before { bar.import :prefix, from: foo }
48
63
 
49
- expect(fn['qux']).to eql 'baz_qux'
64
+ it 'registers a transproc' do
65
+ expect(bar[:prefix, 'bar']['baz']).to eql 'bar_baz'
66
+ end
50
67
  end
51
68
 
52
- it 'cannot access undefined methods' do
53
- module ::BarModule
54
- undef_method :foo
69
+ context 'an imported method' do
70
+ before do
71
+ bar.import :prefix, from: foo, as: :affix
72
+ baz.import :affix, from: bar
55
73
  end
56
74
 
57
- expect { ::BarModule[:foo, 'baz'] }.to raise_error(NameError)
75
+ it 'registers a transproc' do
76
+ expect(baz[:affix, 'bar']['baz']).to eql 'bar_baz'
77
+ end
58
78
  end
59
- end
60
79
 
61
- describe '.uses' do
62
- it 'forwards methods to another module directly' do
63
- expect { ::BazModule[:baz, 'baz'] }.to raise_error(NameError)
80
+ context 'a renamed method' do
81
+ before { bar.import :prefix, from: foo, as: :affix }
64
82
 
65
- module BazModule
66
- uses :foo, as: :ffoo, from: FooModule
67
- uses :bar, from: BarModule
83
+ it 'registers a transproc under the new name' do
84
+ expect(bar[:affix, 'bar']['baz']).to eql 'bar_baz'
68
85
  end
69
-
70
- ffoo = ::BazModule[:ffoo, 'baz']
71
- bar = ::BazModule[:bar, 'baz']
72
-
73
- expect(ffoo['qux']).to eql 'baz_qux'
74
- expect(bar['qux']).to eql 'BAZ_QUX'
75
86
  end
76
- end
77
87
 
78
- describe '#t' do
79
- it 'is an alias for .[]' do
80
- module FooModule
81
- def qux(value, *args)
82
- t(:foo, *args)[value]
88
+ context 'an unknown method' do
89
+ it 'fails' do
90
+ expect { bar.import :suffix, from: foo }.to raise_error do |error|
91
+ expect(error).to be_kind_of Transproc::FunctionNotFoundError
92
+ expect(error.message).to include 'Foo[:suffix]'
83
93
  end
84
94
  end
95
+ end
96
+ end
85
97
 
86
- fn = ::FooModule[:foo, 'baz']
98
+ describe '.uses' do
99
+ before { bar.uses foo }
87
100
 
88
- expect(fn['qux']).to eql 'baz_qux'
101
+ it 'is an alias for .import' do
102
+ expect(bar[:prefix, 'baz']['qux']).to eql 'baz_qux'
89
103
  end
90
104
  end
91
-
92
- after { Object.send :remove_const, :BazModule }
93
- after { Object.send :remove_const, :BarModule }
94
- after { Object.send :remove_const, :FooModule }
95
105
  end
@@ -0,0 +1,148 @@
1
+ # encoding: utf-8
2
+
3
+ describe Transproc::Store do
4
+ let(:store) { described_class.new methods }
5
+ let(:methods) { { foo: instance_double(Proc) } }
6
+
7
+ describe '.new' do
8
+ it 'is immutable' do
9
+ expect(store).to be_frozen
10
+ end
11
+
12
+ it 'does not freeze the source hash' do
13
+ expect { store }.not_to change { methods.frozen? }
14
+ end
15
+ end # describe .new
16
+
17
+ describe '#methods' do
18
+ it 'returns the hash from the initializer' do
19
+ expect(store.methods).to eql methods
20
+ end
21
+
22
+ it 'returns empty hash by default' do
23
+ expect(described_class.new.methods).to eql({})
24
+ end
25
+
26
+ it 'is immutable' do
27
+ expect(store.methods).to be_frozen
28
+ end
29
+ end # describe #methods
30
+
31
+ describe '#fetch' do
32
+ it 'returns a registered proc' do
33
+ expect(store.fetch(:foo)).to eql methods[:foo]
34
+ end
35
+
36
+ it 'raises KeyError if requested proc is unknown' do
37
+ expect { store.fetch(:bar) }.to raise_error KeyError
38
+ end
39
+ end # describe #fetch
40
+
41
+ describe '#import' do
42
+ before do
43
+ module Bar
44
+ def self.bar
45
+ :bar
46
+ end
47
+ end
48
+
49
+ module Baz
50
+ def self.baz
51
+ :baz
52
+ end
53
+ end
54
+
55
+ module Qux
56
+ extend Transproc::Registry
57
+
58
+ import Bar
59
+ import Baz
60
+
61
+ def self.baz
62
+ :qux_baz
63
+ end
64
+
65
+ def self.qux
66
+ :qux
67
+ end
68
+ end
69
+ end
70
+
71
+ shared_examples :importing_method do
72
+ let(:preserved) { subject.methods[:foo] }
73
+ let(:imported) { subject.methods[key] }
74
+
75
+ it '[preserves old methods]' do
76
+ expect(preserved).to eql(methods[:foo])
77
+ end
78
+
79
+ it '[registers a new method]' do
80
+ expect(imported).to be_kind_of Method
81
+ expect(imported.call).to eql(value)
82
+ end
83
+ end
84
+
85
+ context 'named method' do
86
+ subject { store.import 'qux', from: Qux }
87
+
88
+ it_behaves_like :importing_method do
89
+ let(:key) { :qux }
90
+ let(:value) { :qux }
91
+ end
92
+ end
93
+
94
+ context 'renamed method' do
95
+ subject { store.import 'qux', from: Qux, as: 'quxx' }
96
+
97
+ it_behaves_like :importing_method do
98
+ let(:key) { :quxx }
99
+ let(:value) { :qux }
100
+ end
101
+ end
102
+
103
+ context 'imported proc' do
104
+ subject { store.import 'bar', from: Qux, as: 'barr' }
105
+
106
+ it_behaves_like :importing_method do
107
+ let(:key) { :barr }
108
+ let(:value) { :bar }
109
+ end
110
+ end
111
+
112
+ context 'method that reloads imported proc' do
113
+ subject { store.import 'baz', from: Qux, as: 'bazz' }
114
+
115
+ it_behaves_like :importing_method do
116
+ let(:key) { :bazz }
117
+ let(:value) { :qux_baz }
118
+ end
119
+ end
120
+
121
+ context 'module' do
122
+ subject { store.import Qux }
123
+
124
+ it_behaves_like :importing_method do
125
+ let(:key) { :bar }
126
+ let(:value) { :bar }
127
+ end
128
+
129
+ it_behaves_like :importing_method do
130
+ let(:key) { :baz }
131
+ let(:value) { :qux_baz }
132
+ end
133
+
134
+ it_behaves_like :importing_method do
135
+ let(:key) { :qux }
136
+ let(:value) { :qux }
137
+ end
138
+
139
+ it 'skips Transproc::Registry singleton methods' do
140
+ expect(subject.methods.keys).to contain_exactly(:foo, :bar, :baz, :qux)
141
+ end
142
+ end
143
+
144
+ after do
145
+ %w(Bar Baz Qux).each { |name| Object.send :remove_const, name }
146
+ end
147
+ end # describe #import
148
+ end # describe Transproc::Store
@@ -50,6 +50,14 @@ describe Transproc do
50
50
  end
51
51
  end
52
52
 
53
+ describe 'accessing a function with args' do
54
+ it 'curries the args' do
55
+ fn = Transproc(:map_array, Transproc(:to_string))
56
+
57
+ expect(fn.args).to include(Transproc(:to_string))
58
+ end
59
+ end
60
+
53
61
  describe 'handling malformed input' do
54
62
  it 'raises a Transproc::MalformedInputError' do
55
63
  expect {
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: transproc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Solnica
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-20 00:00:00.000000000 Z
11
+ date: 2015-07-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -84,6 +84,9 @@ files:
84
84
  - lib/transproc/hash.rb
85
85
  - lib/transproc/recursion.rb
86
86
  - lib/transproc/registry.rb
87
+ - lib/transproc/rspec.rb
88
+ - lib/transproc/store.rb
89
+ - lib/transproc/support/deprecations.rb
87
90
  - lib/transproc/version.rb
88
91
  - rakelib/mutant.rake
89
92
  - rakelib/rubocop.rake
@@ -94,10 +97,12 @@ files:
94
97
  - spec/unit/coercions_spec.rb
95
98
  - spec/unit/composer_spec.rb
96
99
  - spec/unit/conditional_spec.rb
100
+ - spec/unit/function_not_found_error_spec.rb
97
101
  - spec/unit/function_spec.rb
98
102
  - spec/unit/hash_transformations_spec.rb
99
103
  - spec/unit/recursion_spec.rb
100
104
  - spec/unit/registry_spec.rb
105
+ - spec/unit/store_spec.rb
101
106
  - spec/unit/transproc_spec.rb
102
107
  - transproc.gemspec
103
108
  homepage: http://solnic.github.io/transproc/
@@ -132,8 +137,10 @@ test_files:
132
137
  - spec/unit/coercions_spec.rb
133
138
  - spec/unit/composer_spec.rb
134
139
  - spec/unit/conditional_spec.rb
140
+ - spec/unit/function_not_found_error_spec.rb
135
141
  - spec/unit/function_spec.rb
136
142
  - spec/unit/hash_transformations_spec.rb
137
143
  - spec/unit/recursion_spec.rb
138
144
  - spec/unit/registry_spec.rb
145
+ - spec/unit/store_spec.rb
139
146
  - spec/unit/transproc_spec.rb