pyper_rb 1.2.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.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/Gemfile +24 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +178 -0
  6. data/Rakefile +10 -0
  7. data/lib/pyper/all.rb +4 -0
  8. data/lib/pyper/pipeline.rb +63 -0
  9. data/lib/pyper/pipes/cassandra/all_items_reader.rb +40 -0
  10. data/lib/pyper/pipes/cassandra/deleter.rb +19 -0
  11. data/lib/pyper/pipes/cassandra/mod_key.rb +32 -0
  12. data/lib/pyper/pipes/cassandra/mod_key_reader.rb +41 -0
  13. data/lib/pyper/pipes/cassandra/pagination_decoding.rb +22 -0
  14. data/lib/pyper/pipes/cassandra/pagination_encoding.rb +17 -0
  15. data/lib/pyper/pipes/cassandra/reader.rb +35 -0
  16. data/lib/pyper/pipes/cassandra/writer.rb +24 -0
  17. data/lib/pyper/pipes/cassandra.rb +8 -0
  18. data/lib/pyper/pipes/content/fetch.rb +30 -0
  19. data/lib/pyper/pipes/content/store.rb +36 -0
  20. data/lib/pyper/pipes/content.rb +2 -0
  21. data/lib/pyper/pipes/default_values.rb +15 -0
  22. data/lib/pyper/pipes/field_rename.rb +23 -0
  23. data/lib/pyper/pipes/force_enumerator.rb +13 -0
  24. data/lib/pyper/pipes/model/attribute_deserializer.rb +27 -0
  25. data/lib/pyper/pipes/model/attribute_serializer.rb +34 -0
  26. data/lib/pyper/pipes/model/attribute_validation.rb +57 -0
  27. data/lib/pyper/pipes/model/virtus_deserializer.rb +39 -0
  28. data/lib/pyper/pipes/model/virtus_parser.rb +13 -0
  29. data/lib/pyper/pipes/model.rb +5 -0
  30. data/lib/pyper/pipes/no_op.rb +15 -0
  31. data/lib/pyper/pipes/pry.rb +9 -0
  32. data/lib/pyper/pipes/remove_fields.rb +22 -0
  33. data/lib/pyper/pipes.rb +8 -0
  34. data/lib/pyper/version.rb +3 -0
  35. data/lib/pyper.rb +4 -0
  36. data/pyper_rb.gemspec +22 -0
  37. data/test/fixtures/cass_schema_config.yml +6 -0
  38. data/test/fixtures/test_datastore/schema.cql +23 -0
  39. data/test/test_helper.rb +34 -0
  40. data/test/unit/pyper/pipeline_test.rb +81 -0
  41. data/test/unit/pyper/pipes/cassandra/all_items_reader_test.rb +47 -0
  42. data/test/unit/pyper/pipes/cassandra/deleter_test.rb +37 -0
  43. data/test/unit/pyper/pipes/cassandra/mod_key_reader_test.rb +47 -0
  44. data/test/unit/pyper/pipes/cassandra/pagination_decoding_test.rb +29 -0
  45. data/test/unit/pyper/pipes/cassandra/pagination_encoding_test.rb +29 -0
  46. data/test/unit/pyper/pipes/cassandra/reader_test.rb +79 -0
  47. data/test/unit/pyper/pipes/cassandra/writer_test.rb +51 -0
  48. data/test/unit/pyper/pipes/content/fetch_test.rb +38 -0
  49. data/test/unit/pyper/pipes/content/store_test.rb +49 -0
  50. data/test/unit/pyper/pipes/field_rename_test.rb +24 -0
  51. data/test/unit/pyper/pipes/model/attribute_deserializer_test.rb +69 -0
  52. data/test/unit/pyper/pipes/model/attribute_serializer_test.rb +60 -0
  53. data/test/unit/pyper/pipes/model/attribute_validation_test.rb +96 -0
  54. data/test/unit/pyper/pipes/model/virtus_deserializer_test.rb +75 -0
  55. data/test/unit/pyper/pipes/no_op_test.rb +12 -0
  56. data/test/unit/pyper/pipes/remove_fields_test.rb +24 -0
  57. metadata +147 -0
@@ -0,0 +1,79 @@
1
+ require 'test_helper'
2
+
3
+ module Pyper::Pipes::Cassandra
4
+ class ReaderTest < Minitest::Should::TestCase
5
+ context 'a cassandra reader pipe' do
6
+
7
+ setup do
8
+ setup_cass_schema
9
+
10
+ @client = create_cass_client('test_datastore')
11
+ @pipe = Reader.new(:test, @client)
12
+
13
+ # populate some test data
14
+ @client.insert(:test, {id: 'id', a: '1', b: 'b'})
15
+ @client.insert(:test, {id: 'id', a: '2', b: 'b'})
16
+ end
17
+
18
+ teardown do
19
+ teardown_cass_schema
20
+ end
21
+
22
+ should 'read items from the cassandra table' do
23
+ out = @pipe.pipe(id: 'id').to_a
24
+ assert_equal 2, out.count
25
+ assert_equal({ "id" => "id", "a" => "1", "b" => "b" }, out.first)
26
+ end
27
+
28
+ should 'return items in ascending order' do
29
+ out = @pipe.pipe(id: 'id').to_a
30
+ assert_equal %w(1 2), out.map { |i| i['a'] }
31
+ end
32
+
33
+ should 'limit results if limit arg provided' do
34
+ out = @pipe.pipe(id: 'id', :limit => 1).to_a
35
+ assert_equal 1, out.count
36
+ end
37
+
38
+ should 'order results by field and direction if order pair provided' do
39
+ out = @pipe.pipe(id: 'id', :order => [:a, :desc]).to_a
40
+ assert_equal %w(2 1), out.map { |i| i['a'] }
41
+ end
42
+
43
+ should 'save page state and last_page in status' do
44
+ status = {}
45
+ out = @pipe.pipe({id: 'id', :page_size => 1}, status).to_a
46
+ assert_equal 1, out.count
47
+ assert_equal '1', out.first['a']
48
+ assert status[:paging_state]
49
+ assert_equal false, status[:last_page]
50
+ end
51
+
52
+ should 'page through results if :page_size and/or :paging_state provided' do
53
+ status = {}
54
+ out = @pipe.pipe({id: 'id', :page_size => 1}, status).to_a
55
+ assert_equal 1, out.count
56
+ assert_equal '1', out.first['a']
57
+ paging_state = status[:paging_state]
58
+
59
+ out = @pipe.pipe({id: 'id', :page_size => 1, :paging_state => paging_state}, status).to_a
60
+ assert_equal 1, out.count
61
+ assert_equal '2', out.first['a']
62
+ assert_equal false, status[:last_page]
63
+ end
64
+
65
+ context "columns selecting" do
66
+ should "only select given columns from columns argument" do
67
+ out = @pipe.pipe({id: 'id', :columns => [:a]}).to_a
68
+ assert_equal({'a' => '1'}, out.first)
69
+ assert_equal({'a' => '2'}, out.last)
70
+ end
71
+
72
+ should "select all columns when columns argument not given" do
73
+ out = @pipe.pipe({id: 'id'}).to_a
74
+ assert_equal({ "id" => "id", "a" => "1", "b" => "b" }, out.first)
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,51 @@
1
+ require 'test_helper'
2
+
3
+ module Pyper::Pipes::Cassandra
4
+ class WriterTest < Minitest::Should::TestCase
5
+ context 'a cassandra writer pipe' do
6
+
7
+ setup do
8
+ setup_cass_schema
9
+
10
+ @client = create_cass_client('test_datastore')
11
+ @writer = Writer.new(:test, @client)
12
+ end
13
+
14
+ teardown do
15
+ teardown_cass_schema
16
+ end
17
+
18
+ should 'write to the specified cassandra table' do
19
+ attributes = {id: 'id', a: 'a', b: 'b'}
20
+ @writer.pipe(attributes)
21
+ row = @client.select(:test).execute.first
22
+
23
+ attributes.keys.each do |key|
24
+ assert_equal attributes[key], row[key.to_s]
25
+ end
26
+ end
27
+
28
+ should 'raise an error if required attributes are not provided' do
29
+ attributes = {a: 'a', b: 'b'}
30
+ assert_raises(Cassandra::Errors::InvalidError) { @writer.pipe(attributes) }
31
+ end
32
+
33
+ should 'return the original attributes if the write succeeds' do
34
+ attributes = {id: 'id', a: 'a', b: 'b'}
35
+ assert_equal attributes, @writer.pipe(attributes)
36
+ end
37
+
38
+ should 'raise an error if too many attributes are provided' do
39
+ attributes = {id: 'id', a: 'a', b: 'b', not_an_attribute: 'x'}
40
+ assert_raises(Cassandra::Errors::InvalidError) { @writer.pipe(attributes) }
41
+ end
42
+
43
+ should 'filter attributes if a filter set is given, returning the original attributes' do
44
+ attributes = {id: 'id', a: 'a', b: 'b', not_an_attribute: 'x'}
45
+ filter = [:id, :a, :b]
46
+ writer = Writer.new(:test, @client, filter)
47
+ assert_equal attributes, writer.pipe(attributes)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,38 @@
1
+ require 'test_helper'
2
+
3
+ module Pyper::Pipes::Content
4
+ class FetchTest < Minitest::Should::TestCase
5
+ context 'the content fetch pipe' do
6
+
7
+ setup do
8
+ @dir = Dir.mktmpdir
9
+ @storage_builder = lambda do |item|
10
+ StorageStrategy.get("#{@dir}/content",
11
+ filters: [:size, :checksum],
12
+ size: { metadata_key: :raw_size },
13
+ checksum: {
14
+ digest: :sha256,
15
+ hash_type: :hex,
16
+ metadata_key: :raw_sha256
17
+ })
18
+ end
19
+
20
+ @pipe = Fetch.new(:content, &@storage_builder)
21
+ @strategy = @storage_builder.call({})
22
+ end
23
+
24
+ should 'fetch content using the provided storage builder' do
25
+ content = 'asdf'
26
+ @strategy.write(content)
27
+
28
+ attributes = @pipe.pipe([{}])
29
+ assert_equal content, attributes.first[:content]
30
+ end
31
+
32
+ should 'add nothing if there is no content to store' do
33
+ attributes = @pipe.pipe([{}])
34
+ refute @content, attributes.first[:content]
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,49 @@
1
+ require 'test_helper'
2
+
3
+ module Pyper::Pipes::Content
4
+ class StoreTest < Minitest::Should::TestCase
5
+ context 'the content storage pipe' do
6
+
7
+ setup do
8
+ @dir = Dir.mktmpdir
9
+ @storage_builder = lambda do |attributes|
10
+ StorageStrategy.get("#{@dir}/metadata",
11
+ filters: [:size, :checksum],
12
+ size: { metadata_key: :raw_size },
13
+ checksum: {
14
+ digest: :sha256,
15
+ hash_type: :hex,
16
+ metadata_key: :raw_sha256
17
+ })
18
+ end
19
+
20
+ @pipe = Store.new(:content, &@storage_builder)
21
+ @strategy = @storage_builder.call({})
22
+ end
23
+
24
+ should 'store content using the provided storage builder' do
25
+ content = 'asdf'
26
+ @pipe.pipe(:content => content)
27
+
28
+ assert_equal content, @strategy.read
29
+ end
30
+
31
+
32
+ should 'store size and checksum metadata' do
33
+ content = 'asdf'
34
+ @pipe.pipe(:content => content)
35
+
36
+ assert_equal '4', @strategy.metadata[:raw_size]
37
+ assert @strategy.metadata[:raw_sha256]
38
+ end
39
+
40
+ should 'remove content from attributes adding new metadata fields' do
41
+ content = 'asdf'
42
+ attributes = @pipe.pipe(:content => content)
43
+
44
+ assert_equal '4', attributes[:raw_size]
45
+ assert attributes[:raw_sha256]
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,24 @@
1
+ require 'test_helper'
2
+
3
+ module Pyper::Pipes
4
+ class FieldRenameTest < Minitest::Should::TestCase
5
+ context 'the field rename pipe' do
6
+
7
+ setup do
8
+ @pipe = FieldRename.new(:a => :b, "c" => "d")
9
+ end
10
+
11
+ should 'rename provided symbols as symbols' do
12
+ assert_equal({ :b => 1, :d => 1}, @pipe.pipe(:a => 1, :c => 1))
13
+ end
14
+
15
+ should 'rename provided strings as strings' do
16
+ assert_equal({ "b" => 1, "d" => 1}, @pipe.pipe("a" => 1, "c" => 1))
17
+ end
18
+
19
+ should 'rename nil values' do
20
+ assert_equal({ :b => nil, "d" => nil}, @pipe.pipe(:a => nil, "c" => nil))
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,69 @@
1
+ require 'test_helper'
2
+ require 'json'
3
+
4
+ module Pyper::Pipes::Model
5
+ class AttributeDeserializerTest < Minitest::Should::TestCase
6
+ setup do
7
+ type_mapping = {
8
+ :array => Array,
9
+ :hash => Hash,
10
+ :int => Integer,
11
+ :float => Float,
12
+ :other => String
13
+ }
14
+ @pipe = AttributeDeserializer.new(type_mapping)
15
+ end
16
+
17
+ should 'deserialize json arrays' do
18
+ value = [1,2,3]
19
+ item = { :array => JSON.generate(value) }
20
+ out = @pipe.pipe([item])
21
+ assert_equal 1, out.count
22
+ assert_equal value, out.first[:array]
23
+ end
24
+
25
+ should 'deserialize json hashes' do
26
+ value = {'a' => 1}
27
+ item = { :hash => JSON.generate(value) }
28
+ out = @pipe.pipe([item])
29
+ assert_equal 1, out.count
30
+ assert_equal value, out.first[:hash]
31
+ end
32
+
33
+ should 'deserialize ints' do
34
+ value = 1
35
+ item = { :int => value.to_s }
36
+ out = @pipe.pipe([item])
37
+ assert_equal 1, out.count
38
+ assert_equal value, out.first[:int]
39
+ end
40
+
41
+ should 'deserialize fixnums' do
42
+ value = 1.5
43
+ item = { :float => value.to_s }
44
+ out = @pipe.pipe([item])
45
+ assert_equal 1, out.count
46
+ assert_equal value, out.first[:float]
47
+ end
48
+
49
+ should 'not deserialize other fields' do
50
+ value = 'asdf'
51
+ item = { :other => value }
52
+ out = @pipe.pipe([item])
53
+ assert_equal 1, out.count
54
+ assert_equal value, out.first[:other]
55
+ end
56
+
57
+ should 'not modify original values when deserializng' do
58
+ value = [1,2,3]
59
+ item = { :array => JSON.generate(value) }
60
+ out = @pipe.pipe([item])
61
+ assert_equal 1, out.count
62
+ assert_equal value, out.first[:array]
63
+
64
+ # This throws an error if we have modified the original values
65
+ out = @pipe.pipe([item])
66
+ assert_equal value, out.first[:array]
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,60 @@
1
+ require 'test_helper'
2
+ require 'json'
3
+
4
+ module Pyper::Pipes::Model
5
+ class AttributeSerializerTest < Minitest::Should::TestCase
6
+ setup do
7
+ @pipe = AttributeSerializer.new
8
+ end
9
+
10
+ should 'serialize arrays to JSON' do
11
+ value = [1,2,3]
12
+ attributes = { :array => value }
13
+ out = @pipe.pipe(attributes)
14
+ assert_equal 1, out.count
15
+ assert_equal JSON.generate(value), out[:array]
16
+ end
17
+
18
+ should 'serialize hashes to JSON' do
19
+ value = {'a' => 1}
20
+ attributes = { :hash => value }
21
+ out = @pipe.pipe(attributes)
22
+ assert_equal 1, out.count
23
+ assert_equal JSON.generate(value), out[:hash]
24
+ end
25
+
26
+ should 'serialize datetimes to times' do
27
+ value = DateTime.now
28
+ attributes = { :datetime => value }
29
+ out = @pipe.pipe(attributes)
30
+ assert_equal 1, out.count
31
+ assert_equal value.to_time, out[:datetime]
32
+ end
33
+
34
+ should 'encode strings to utf-8' do
35
+ value = 'str'.force_encoding('ascii-8bit')
36
+ attributes = { :string => value }
37
+ out = @pipe.pipe(attributes)
38
+ assert_equal 1, out.count
39
+ assert_equal Encoding::UTF_8, out[:string].encoding
40
+ end
41
+
42
+ should 'be able to serialize collections containing strings with non-UTF8 characters to JSON' do
43
+ ascii = "\xC2\xA0".force_encoding('ascii-8bit')
44
+ time = DateTime.now
45
+ ascii_values = { :array => [ascii], :datetime => time, :fixnum => 1, :string => ascii }
46
+ utf8_values = { :array => [ascii.force_encoding("UTF-8")], :datetime => time, :fixnum => 1, :string => ascii.force_encoding("UTF-8") }
47
+ out = @pipe.pipe({ :hash => ascii_values })
48
+ assert_equal 1, out.count
49
+ assert_equal JSON.generate(utf8_values), out[:hash]
50
+ end
51
+
52
+ should 'not serialize other fields' do
53
+ value = 1.5
54
+ attributes = { :fixnum => value }
55
+ out = @pipe.pipe(attributes)
56
+ assert_equal 1, out.count
57
+ assert_equal value, out[:fixnum]
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,96 @@
1
+ require 'test_helper'
2
+
3
+ module Pyper::Pipes::Model
4
+ class AttributeValidationTest < Minitest::Should::TestCase
5
+ context "pipe" do
6
+ context "with required attributes" do
7
+ setup do
8
+ @opts = { :required => [:foo, :bar] }
9
+ @pipe = AttributeValidation.new(@opts)
10
+ end
11
+
12
+ should "raise when missing required attribute" do
13
+ error_1 = assert_raises(AttributeValidation::Failure) do
14
+ @pipe.pipe({})
15
+ end
16
+ assert_equal "Missing required attribute foo.", error_1.message
17
+
18
+ error_2 = assert_raises(AttributeValidation::Failure) do
19
+ @pipe.pipe({ :foo => "bar" })
20
+ end
21
+ assert_equal "Missing required attribute bar.", error_2.message
22
+
23
+ # Nothing should be raised now.
24
+ @pipe.pipe({ :foo => "bar", :bar => "qux" })
25
+ end
26
+
27
+ should "raise when required attribute is nil" do
28
+ error = assert_raises(AttributeValidation::Failure) do
29
+ @pipe.pipe({ :foo => nil, :bar => "qux"})
30
+ end
31
+ assert_equal "Missing required attribute foo.", error.message
32
+ end
33
+ end
34
+
35
+ context "with allowed attributes" do
36
+ setup do
37
+ @opts = { :allowed => [:foo, :bar] }
38
+ @pipe = AttributeValidation.new(@opts)
39
+ end
40
+
41
+ should "raise when attribute is not included in the whitelist" do
42
+ error = assert_raises(AttributeValidation::Failure) do
43
+ @pipe.pipe({ :foo => "foo", :bar => "bar", :baz => "baz" })
44
+ end
45
+ assert_equal "Attribute baz is not allowed.", error.message
46
+
47
+ # Nothing should be raised now.
48
+ @pipe.pipe({ :foo => "foo", :bar => "bar" })
49
+ end
50
+
51
+ should "allow all attributes when allowed option is not set" do
52
+ pipe = AttributeValidation.new
53
+
54
+ # Nothing should be raised now.
55
+ pipe.pipe({ :foo => "foo", :bar => "bar", :baz => "baz" })
56
+ end
57
+ end
58
+
59
+
60
+ context "with restricted attributes" do
61
+ setup do
62
+ @opts = {
63
+ :restricted => {
64
+ :bar => lambda { |value| ["qux", "bazqux"].include?(value) }
65
+ }
66
+ }
67
+ @pipe = AttributeValidation.new(@opts)
68
+ end
69
+
70
+ should "raise when lambda returns false" do
71
+ error = assert_raises(AttributeValidation::Failure) do
72
+ @pipe.pipe({ :bar => "foo"})
73
+ end
74
+ assert_equal "Invalid value for attribute bar.", error.message
75
+
76
+ # Nothing should be raised now.
77
+ @pipe.pipe({ :bar => "qux" })
78
+ @pipe.pipe({ :bar => "bazqux" })
79
+ end
80
+ end
81
+
82
+ should "return attributes hash when all is well" do
83
+ opts = {
84
+ :allowed => [:foo, :bar],
85
+ :required => [:foo],
86
+ :restricted => {
87
+ :bar => lambda { |value| ["bar", "foobar"].include?(value) }
88
+ }
89
+ }
90
+ pipe = AttributeValidation.new(opts)
91
+ attributes = { :foo => "bar", :bar => "foobar" }
92
+ assert_equal attributes, pipe.pipe(attributes)
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,75 @@
1
+ require 'test_helper'
2
+ require 'json'
3
+ require 'virtus'
4
+
5
+ module Pyper::Pipes::Model
6
+ class VirtusDeserializerTest < Minitest::Should::TestCase
7
+
8
+ class TestVirtus
9
+ include ::Virtus.model
10
+
11
+ attribute :array, Array[String]
12
+ attribute :hash, Hash
13
+ attribute :int, Integer
14
+ attribute :float, Float
15
+ attribute :other, String
16
+ end
17
+
18
+ setup do
19
+ @pipe = VirtusDeserializer.new(TestVirtus.attribute_set)
20
+ end
21
+
22
+ should 'deserialize json arrays' do
23
+ value = [1,2,3]
24
+ item = { 'array' => JSON.generate(value) }
25
+ out = @pipe.pipe([item])
26
+ assert_equal 1, out.count
27
+
28
+ assert_equal value, out.first['array']
29
+ end
30
+
31
+ should 'deserialize json hashes' do
32
+ value = {'a' => 1}
33
+ item = { 'hash' => JSON.generate(value) }
34
+ out = @pipe.pipe([item])
35
+ assert_equal 1, out.count
36
+ assert_equal value, out.first['hash']
37
+ end
38
+
39
+ should 'deserialize ints' do
40
+ value = 1
41
+ item = { 'int' => value.to_s }
42
+ out = @pipe.pipe([item])
43
+ assert_equal 1, out.count
44
+ assert_equal value, out.first['int']
45
+ end
46
+
47
+ should 'deserialize floats' do
48
+ value = 1.5
49
+ item = { 'float' => value.to_s }
50
+ out = @pipe.pipe([item])
51
+ assert_equal 1, out.count
52
+ assert_equal value, out.first['float']
53
+ end
54
+
55
+ should 'not deserialize other fields' do
56
+ value = 'asdf'
57
+ item = { 'other' => value }
58
+ out = @pipe.pipe([item])
59
+ assert_equal 1, out.count
60
+ assert_equal value, out.first['other']
61
+ end
62
+
63
+ should 'not modify original values when deserializng' do
64
+ value = [1,2,3]
65
+ item = { 'array' => JSON.generate(value) }
66
+ out = @pipe.pipe([item])
67
+ assert_equal 1, out.count
68
+ assert_equal value, out.first['array']
69
+
70
+ # This throws an error if we have modified the original values
71
+ out = @pipe.pipe([item])
72
+ assert_equal value, out.first['array']
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,12 @@
1
+ require 'test_helper'
2
+
3
+ module Pyper::Pipes
4
+ class NoOpTest < Minitest::Should::TestCase
5
+ context 'NoOp pipe' do
6
+ should 'perform no operation' do
7
+ pipe_input = { :pipe_var => "this is a string" }
8
+ assert_equal pipe_input, NoOp.pipe(pipe_input)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,24 @@
1
+ require 'test_helper'
2
+
3
+ module Pyper::Pipes
4
+ class RemoveFieldsTest < Minitest::Should::TestCase
5
+ context 'the remove fields pipe' do
6
+
7
+ should "accept a symbol" do
8
+ pipe = RemoveFields.new(:a)
9
+ assert_equal({ :b => 2 }, pipe.pipe(:a => 1, :b => 2))
10
+ end
11
+
12
+ should "accept an array of symbol" do
13
+ pipe = RemoveFields.new([:a])
14
+ assert_equal({ :b => 2 }, pipe.pipe(:a => 1, :b => 2))
15
+ end
16
+
17
+ should 'remove fields provided an array of symbols' do
18
+ pipe = RemoveFields.new([:a])
19
+ assert_equal({ :b => 2 }, pipe.pipe(:a => 1, :b => 2))
20
+ end
21
+
22
+ end
23
+ end
24
+ end