pyper_rb 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/Gemfile +24 -0
- data/LICENSE.txt +22 -0
- data/README.md +178 -0
- data/Rakefile +10 -0
- data/lib/pyper/all.rb +4 -0
- data/lib/pyper/pipeline.rb +63 -0
- data/lib/pyper/pipes/cassandra/all_items_reader.rb +40 -0
- data/lib/pyper/pipes/cassandra/deleter.rb +19 -0
- data/lib/pyper/pipes/cassandra/mod_key.rb +32 -0
- data/lib/pyper/pipes/cassandra/mod_key_reader.rb +41 -0
- data/lib/pyper/pipes/cassandra/pagination_decoding.rb +22 -0
- data/lib/pyper/pipes/cassandra/pagination_encoding.rb +17 -0
- data/lib/pyper/pipes/cassandra/reader.rb +35 -0
- data/lib/pyper/pipes/cassandra/writer.rb +24 -0
- data/lib/pyper/pipes/cassandra.rb +8 -0
- data/lib/pyper/pipes/content/fetch.rb +30 -0
- data/lib/pyper/pipes/content/store.rb +36 -0
- data/lib/pyper/pipes/content.rb +2 -0
- data/lib/pyper/pipes/default_values.rb +15 -0
- data/lib/pyper/pipes/field_rename.rb +23 -0
- data/lib/pyper/pipes/force_enumerator.rb +13 -0
- data/lib/pyper/pipes/model/attribute_deserializer.rb +27 -0
- data/lib/pyper/pipes/model/attribute_serializer.rb +34 -0
- data/lib/pyper/pipes/model/attribute_validation.rb +57 -0
- data/lib/pyper/pipes/model/virtus_deserializer.rb +39 -0
- data/lib/pyper/pipes/model/virtus_parser.rb +13 -0
- data/lib/pyper/pipes/model.rb +5 -0
- data/lib/pyper/pipes/no_op.rb +15 -0
- data/lib/pyper/pipes/pry.rb +9 -0
- data/lib/pyper/pipes/remove_fields.rb +22 -0
- data/lib/pyper/pipes.rb +8 -0
- data/lib/pyper/version.rb +3 -0
- data/lib/pyper.rb +4 -0
- data/pyper_rb.gemspec +22 -0
- data/test/fixtures/cass_schema_config.yml +6 -0
- data/test/fixtures/test_datastore/schema.cql +23 -0
- data/test/test_helper.rb +34 -0
- data/test/unit/pyper/pipeline_test.rb +81 -0
- data/test/unit/pyper/pipes/cassandra/all_items_reader_test.rb +47 -0
- data/test/unit/pyper/pipes/cassandra/deleter_test.rb +37 -0
- data/test/unit/pyper/pipes/cassandra/mod_key_reader_test.rb +47 -0
- data/test/unit/pyper/pipes/cassandra/pagination_decoding_test.rb +29 -0
- data/test/unit/pyper/pipes/cassandra/pagination_encoding_test.rb +29 -0
- data/test/unit/pyper/pipes/cassandra/reader_test.rb +79 -0
- data/test/unit/pyper/pipes/cassandra/writer_test.rb +51 -0
- data/test/unit/pyper/pipes/content/fetch_test.rb +38 -0
- data/test/unit/pyper/pipes/content/store_test.rb +49 -0
- data/test/unit/pyper/pipes/field_rename_test.rb +24 -0
- data/test/unit/pyper/pipes/model/attribute_deserializer_test.rb +69 -0
- data/test/unit/pyper/pipes/model/attribute_serializer_test.rb +60 -0
- data/test/unit/pyper/pipes/model/attribute_validation_test.rb +96 -0
- data/test/unit/pyper/pipes/model/virtus_deserializer_test.rb +75 -0
- data/test/unit/pyper/pipes/no_op_test.rb +12 -0
- data/test/unit/pyper/pipes/remove_fields_test.rb +24 -0
- 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
|