msfl 0.0.1.pre.qa → 0.0.1.pre.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5192c432f2b0fa92fdc52f791a6d1db94e0e7273
4
- data.tar.gz: 369cf6c5d51a3b2f996b070a70894a6fd952b7f4
3
+ metadata.gz: 1433fb3fe0766b9a5a4913a5c8236bffb00e9c5e
4
+ data.tar.gz: 9307024455e4e75530f334e4c91d2a09f7da7090
5
5
  SHA512:
6
- metadata.gz: dadc0e105e90e00c982424d332a2cada2733a676cf9c26f0d65ab3c5a79e4ffe94c78b87903c493aa070ae0c80f813eb1bf6313cd81531593911fde0f0c3b1bf
7
- data.tar.gz: 86c9aac383c3a267e9344ca3f081b4b1e9fd8c461ca5e86a5962e3811476dad04ac918c521cc9dc0011811e5029caca9ec14858bd9b83ad313a8c0a1c45d6561
6
+ metadata.gz: 1a7ac56dec38d01c8dcec0521e27cb03f361d952d8309d72bfa6494e9b5b49c8e34a89d1f2e98c66742a885110519ecd41ea24d3aa05b2508b1eeb20155244e3
7
+ data.tar.gz: 8a8150eb7c2ded7f183e7f124167a2dd3de92477cdc52731ee6868599625b344308c80bb5707230e51847ba11ad6a0635129a69a77887b112d570ffc3c2df6b5
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ ### Ruby template
2
+ *.gem
3
+ *.rbc
4
+ /coverage/
5
+ /spec/reports/
6
+
7
+ ## Documentation cache and generated files:
8
+ /.yardoc/
9
+ /_yardoc/
10
+ /doc/
11
+ /rdoc/
12
+
13
+ ## Environment normalisation:
14
+ /.bundle/
15
+ /lib/bundler/man/
16
+ .idea/
17
+
18
+ ## Gemfile for development
19
+ #Gemfile
20
+ #Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+ gem 'simplecov', :require => false, :group => :test # MIT https://github.com/colszowka/simplecov/blob/master/MIT-LICENSE
3
+ gem 'yard' # MIT https://github.com/lsegal/yard/blob/master/LICENSE + Ruby license for one file from the Ruby source lib/parser/ruby/legacy/ruby_lex.rb
4
+ gem 'rspec' # MIT https://github.com/rspec/rspec/blob/master/License.txt
5
+ gem 'byebug'
data/Gemfile.lock ADDED
@@ -0,0 +1,40 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ byebug (3.5.1)
5
+ columnize (~> 0.8)
6
+ debugger-linecache (~> 1.2)
7
+ slop (~> 3.6)
8
+ columnize (0.8.9)
9
+ debugger-linecache (1.2.0)
10
+ diff-lcs (1.2.5)
11
+ docile (1.1.5)
12
+ multi_json (1.10.1)
13
+ rspec (3.1.0)
14
+ rspec-core (~> 3.1.0)
15
+ rspec-expectations (~> 3.1.0)
16
+ rspec-mocks (~> 3.1.0)
17
+ rspec-core (3.1.7)
18
+ rspec-support (~> 3.1.0)
19
+ rspec-expectations (3.1.2)
20
+ diff-lcs (>= 1.2.0, < 2.0)
21
+ rspec-support (~> 3.1.0)
22
+ rspec-mocks (3.1.3)
23
+ rspec-support (~> 3.1.0)
24
+ rspec-support (3.1.2)
25
+ simplecov (0.9.1)
26
+ docile (~> 1.1.0)
27
+ multi_json (~> 1.0)
28
+ simplecov-html (~> 0.8.0)
29
+ simplecov-html (0.8.0)
30
+ slop (3.6.0)
31
+ yard (0.8.7.6)
32
+
33
+ PLATFORMS
34
+ ruby
35
+
36
+ DEPENDENCIES
37
+ byebug
38
+ rspec
39
+ simplecov
40
+ yard
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2015 Mattermark, Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,5 @@
1
+ [![Circle CI](https://circleci.com/gh/caldwecr/msfl.svg?style=svg)](https://circleci.com/gh/caldwecr/msfl)
2
+
3
+ # Ruby Gem for the Mattermark Semantic Filter Language
4
+
5
+ Contains serializers and validators (and perhaps other) MSFL goodies
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "rake"
2
+ require 'rspec/core/rake_task'
3
+
4
+ task default: [:spec] do
5
+ ENV['RACK_ENV'] = 'test'
6
+ end
7
+
8
+ task :spec do
9
+ RSpec::Core::RakeTask.new(:spec)
10
+ end
data/circle.yml ADDED
@@ -0,0 +1,9 @@
1
+ machine:
2
+
3
+ timezone:
4
+ America/Los_Angeles # Set the timezone
5
+
6
+ # Version of ruby to use
7
+ ruby:
8
+ version:
9
+ 2.1.3
@@ -6,7 +6,9 @@ module MSFL
6
6
 
7
7
  # The descendant class MUST override this method otherwise all field validations will fail
8
8
  #
9
- # @return [Array] the fields in the dataset
9
+ # The method defines an array of symbols, indicating what fields are supported for the Dataset
10
+ #
11
+ # @return [Array<Symbol>] the fields in the dataset
10
12
  def fields
11
13
  raise NoMethodError, "Descendants of MSFL::Datasets::Base are required to implement the #fields method"
12
14
  end
@@ -14,11 +16,14 @@ module MSFL
14
16
  # The descendant class may override this method to control the operators that are supported for the dataset
15
17
  # - Note that this can only be used to reduce the number of supported operators (you can't add new operators
16
18
  # here, without first adding them to MSFL::Validators::Definitions::HashKey#hash_key_operators)
19
+ #
20
+ # @return [Array<Symbol>] the operators supported in the dataset
17
21
  def operators
18
22
  hash_key_operators
19
23
  end
20
24
 
21
- # Method not implemented at this time
25
+ # This method returns the errors argument. The errors argument is unchanged if type conformity validation passes,
26
+ # otherwise an error is added to errors.
22
27
  #
23
28
  # @param obj [Object] the object that should be type checked based on the field argument
24
29
  # @param field [Symbol] which field should the object be checked for conformity
@@ -30,11 +35,14 @@ module MSFL
30
35
  # # because the type of total_funding must be an integer
31
36
  #
32
37
  def validate_type_conforms(obj, field, errors)
38
+ errors << "Dataset type conformity validation failed for obj: #{obj} against field: #{field}" unless type_conforms?(obj, field)
33
39
  errors
34
40
  end
35
41
 
36
42
  # Method not implemented at this time
37
43
  # Returns true if the object conforms to the types supported by the indicated field
44
+ # While not currently implemented the intent is that the descendant Dataset would specify a hash of supported
45
+ # types for each field and this method would then cross reference that list.
38
46
  #
39
47
  # @param obj [Object] the object that should be type checked based on the field argument
40
48
  # @param field [Symbol] which field should the object be checked for conformity
@@ -42,19 +50,33 @@ module MSFL
42
50
  true
43
51
  end
44
52
 
45
- # Method not implemented at this time
46
- #
53
+ # This method returns the errors argument. The errors argument is unchanged if operator conformity validation
54
+ # passes, otherwise an error is added to errors.
47
55
  #
48
56
  # @param operator [Symbol] the operator that we want to know if the particular field supports it
49
57
  # @param field [Symbol] which field should the operator be checked for conformity
50
58
  # @param errors [Array] an array of validation errors - empty indicates that no errors have been encountered
51
59
  # @return [Array] errors merged with any validation errors encountered in validating the set
52
60
  def validate_operator_conforms(operator, field, errors)
61
+ errors << "Dataset operator conformity validation failed for operator: #{operator} against field: #{field}" unless operator_conforms?(operator, field)
53
62
  errors
54
63
  end
55
64
 
56
65
  # Method not implemented at this time
57
66
  #
67
+ # This method returns true if the operator is supported for the specified field by the dataset. While this
68
+ # is not currently implemented, the intent is that a hash of fields (as keys) would map to
69
+ # Arrays<Symbol> (as values) and then this method would validate that the operator argument meets this contract.
70
+ #
71
+ # @param operator [Symbol] the operator that needs to be checked for conformity
72
+ # @param field [Symbol] which field should the operator be checked against
73
+ # @return [Bool] true if the operator conforms, false otherwise
74
+ def operator_conforms?(operator, field)
75
+ true
76
+ end
77
+
78
+ # This method returns the errors argument. The errors argument is unchanged if value conformity validation
79
+ # passes, otherwise an error is added to errors.
58
80
  #
59
81
  # @param value [Object] the precoerced value (the value must be correctly typed)
60
82
  # that should be checked for validity based on the field, if the value does not conform an
@@ -72,8 +94,28 @@ module MSFL
72
94
  # foo.investors_value_conforms(12345, :total_funding) => # errors is unchanged
73
95
  #
74
96
  def validate_value_conforms(value, field, errors)
97
+ errors << "Dataset value conformity validation failed for value: #{value} against field: #{field}" unless value_conforms?(value, field, errors)
75
98
  errors
76
99
  end
100
+
101
+ # Method not implemented at this time
102
+ #
103
+ # This method returns true if the value is supported for the specified field by the dataset. While this is not
104
+ # currently implemented, the intent is that a hash of fields (as keys) would map to an Array of validation
105
+ # constraints. These constraints would then be executed against the value and if all are successful the value
106
+ # would be considered to have passed.
107
+ #
108
+ # It is likely that the methods invoked from the Array of validation constraints would actually return an Array
109
+ # of errors encountered, this method would then concat that Array into the errors array. If the encountered errors
110
+ # array is empty the method would return true, and false otherwise.
111
+ #
112
+ # @param value [Object] the object to on which to perform validation
113
+ # @param field [Symbol] the field the object should be validated against
114
+ # @param errors [Array] the array of errors from prior validations
115
+ # @return [Bool] true if no new errors are encountered, false otherwise
116
+ def value_conforms?(value, field, errors = [])
117
+ true
118
+ end
77
119
  end
78
120
  end
79
121
  end
@@ -2,12 +2,21 @@ require 'json'
2
2
  module MSFL
3
3
  module Parsers
4
4
  class JSON
5
+
6
+ # Parses json encoded MSFL into Ruby encoded MSFL
7
+ #
8
+ # @param json [String] the string to parse
9
+ # @return [Object] the Ruby encoded MSFL, which may be a Hash, MSFL::Types::Set, or any number of scalar types
5
10
  def self.parse(json)
6
11
  obj = ::JSON.parse(json)
7
12
  obj = arrays_to_sets obj
8
13
  obj
9
14
  end
10
15
 
16
+ # Converts Ruby Arrays is a partially parsed Ruby MSFL filter to MSFL::Types::Set objects
17
+ #
18
+ # @param obj [Object] the object in which to convert Ruby Array objects to MSFL::Types::Set objects
19
+ # @return [Object] the result of converting Ruby Arrays to MSFL::Types::Set objects
11
20
  def self.arrays_to_sets(obj)
12
21
  obj = Types::Set.new obj if obj.is_a?(::Array)
13
22
  if obj.respond_to? :each
@@ -11,8 +11,18 @@ module MSFL
11
11
  BOOLEAN_OPERATORS = [:and, :or]
12
12
  ENUMERATION_OPERATORS = [:in]
13
13
 
14
- def initialize(attributes = nil, opts = {})
15
- @dataset = MSFL.configuration.datasets.first.new unless MSFL.configuration.datasets.empty?
14
+ # Used for creating new semantic validator instances
15
+ #
16
+ # If the dataset argument is specified it will be used as the dataset for the validator. Otherwise
17
+ # the instance's dataset will default to the first value in MSFL.configuration.datasets, unless it is empty,
18
+ # in which case it will revert to MSFL::Datasets::Base, which will deliberately break execution when #validate
19
+ # is called on the validator instance, raising a NoMethodError.
20
+ #
21
+ # @param dataset [MSFL::Dataset::Base] optionally override the dataset instance that should be used by the validator
22
+ # @param opts [Hash] optional; currently not used, included for future additions
23
+ def initialize(dataset = nil, opts = {})
24
+ @dataset = dataset unless dataset.nil?
25
+ @dataset ||= MSFL.configuration.datasets.first.new unless MSFL.configuration.datasets.empty?
16
26
  @dataset ||= Datasets::Base.new
17
27
  @current_field = nil
18
28
  @current_operator = nil
data/msfl.gemspec ADDED
@@ -0,0 +1,20 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'msfl'
3
+ s.version = '0.0.1-rc1'
4
+ s.date = '2015-03-05'
5
+ s.summary = "MSFL in Ruby"
6
+ s.description = "Serializers, validators, and other tasty goodness for the Mattermark Semantic Filter Language in Ruby."
7
+ s.authors = ["Courtland Caldwell"]
8
+ s.email = 'courtland@mattermark.com'
9
+ s.files = `git ls-files`.split("\n")
10
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
11
+ s.homepage =
12
+ 'https://github.com/caldwecr/msfl'
13
+ s.add_runtime_dependency "json", "~> 1.7"
14
+ s.add_development_dependency "rake", "~> 10.3"
15
+ s.add_development_dependency "simplecov", "~> 0.9"
16
+ s.add_development_dependency "yard", "~> 0.8"
17
+ s.add_development_dependency "rspec", "~> 3.1"
18
+ s.add_development_dependency "byebug", "~> 3.5"
19
+ s.license = "MIT"
20
+ end
@@ -0,0 +1,5 @@
1
+ require 'simplecov'
2
+ SimpleCov.profiles.define 'msfl' do
3
+ add_filter '/spec'
4
+ add_filter '/test'
5
+ end
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ describe "MSFL::Datasets::Base" do
4
+
5
+ let(:test_instance) { MSFL::Datasets::Movies.new }
6
+
7
+ let(:errors) { [ ] }
8
+
9
+ let(:field) { :title }
10
+
11
+ describe "#fields" do
12
+
13
+ it "raises a NoMethodError" do
14
+ expect { MSFL::Datasets::Base.new.fields }.to raise_error NoMethodError
15
+ end
16
+ end
17
+
18
+ describe "#validate_type_conforms" do
19
+
20
+ subject(:mut) { test_instance.validate_type_conforms obj, field, errors }
21
+
22
+ let(:obj) { "i am a string" }
23
+
24
+ it "is currently a stubbed method that just returns the errors argument" do
25
+ expect(mut).to eq errors
26
+ end
27
+ end
28
+
29
+ describe "#type_conforms?" do
30
+
31
+ context "when MSFL is configured to use Movies as the dataset" do
32
+
33
+ subject(:mut) { test_instance.type_conforms? obj, field }
34
+
35
+ let(:obj) { "i am a string" }
36
+
37
+ it "is true for types that conform to the Dataset" do
38
+ expect(mut).to eq true
39
+ end
40
+
41
+ it "is false for types that do not conform to the Dataset" do
42
+ pending "Dataset specific semantic validation is not yet implemented."
43
+ expect(mut).to eq false
44
+ end
45
+ end
46
+ end
47
+
48
+ describe "#validate_operator_conforms" do
49
+
50
+ subject(:mut) { test_instance.validate_operator_conforms operator, field, errors }
51
+
52
+ let(:operator) { :and }
53
+
54
+ it "is currently a stubbed method that just returns the errors argument" do
55
+ expect(mut).to eq errors
56
+ end
57
+ end
58
+
59
+ describe "#validate_value_conforms" do
60
+
61
+ subject(:mut) { test_instance.validate_value_conforms value, field, errors }
62
+
63
+ let(:value) { 1234 }
64
+
65
+ it "is currently a stubbed method that just returns the errors argument" do
66
+ expect(mut).to eq errors
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,146 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ # Still need to deal with duplicates in array scenarios - is there a nested array variation with a non-obvious deduplication consequence?
5
+ describe "MSFL::Parsers::JSON" do
6
+ describe ".parse" do
7
+
8
+ subject(:mut) { MSFL::Parsers::JSON.parse test_json }
9
+
10
+ let(:test_json) { '{"total_funding": 5000000}' }
11
+
12
+ context "when parsing a json hash" do
13
+
14
+ it "is an equivalent Ruby Hash" do
15
+ expect(mut).to eq({ :total_funding => 5000000 })
16
+ end
17
+ end
18
+
19
+ context "when parsing a json array" do
20
+
21
+ let(:test_json) { '["abc", "def"]' }
22
+
23
+ it { is_expected.to be_a MSFL::Types::Set }
24
+ end
25
+
26
+ end
27
+
28
+ describe ".arrays_to_sets" do
29
+
30
+ subject(:mut) { MSFL::Parsers::JSON.arrays_to_sets arg }
31
+
32
+ let(:arg) { Object.new }
33
+
34
+ [55, "five", :fourty, nil].each do |item|
35
+ context "when the argument is a #{item.class}" do
36
+
37
+ let(:arg) { item }
38
+
39
+ it "is equal to the argument" do
40
+ expect(mut).to eq arg
41
+ end
42
+ end
43
+ end
44
+
45
+ context "when the argument is a Hash" do
46
+
47
+ context "when the hash's values are scalars" do
48
+
49
+ let(:arg) { { foo: "bar", cat: 1337 } }
50
+
51
+ it "is equal to the argument" do
52
+ expect(mut).to eq arg
53
+ end
54
+ end
55
+
56
+ context "when the hash's values include at least one Hash" do
57
+
58
+ let(:arg) do
59
+ { foo: { bar: "bar" }, abc: 123 }
60
+ end
61
+
62
+ it "is equal to the argument" do
63
+ expect(mut).to eq arg
64
+ end
65
+ end
66
+
67
+ context "when the hash's values include at least one Array" do
68
+
69
+ let(:arg) do
70
+ { inner_array: array_in_arg, abc: 123 }
71
+ end
72
+
73
+ let(:expected) do
74
+ { inner_array: MSFL::Types::Set.new(array_in_arg), abc: 123 }
75
+ end
76
+
77
+ let(:array_in_arg) { ["bar", "baz"] }
78
+
79
+ it "is the argument with the Array converted to a MSFL::Types::Set" do
80
+ expect(mut).to eq expected
81
+ end
82
+
83
+ context "when at least one included Array has a duplicate item" do
84
+
85
+ let(:array_in_arg) { ["cat", "cat", 44, 55, "dog", 44, :marco, :polo, nil, :polo, "cat", nil] }
86
+
87
+ it "includes the duplicate item(s) exactly once" do
88
+ expect(mut[:inner_array]).to eq MSFL::Types::Set.new(["cat", 44, 55, "dog", :marco, :polo, nil])
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ context "when the argument is an Array" do
95
+
96
+ let(:arg) { [:foo, "bar", nil, 99, "bar"] }
97
+
98
+ it { is_expected.to be_a MSFL::Types::Set }
99
+
100
+ it "is unordered" do
101
+ expect(mut).to eq MSFL::Types::Set.new(arg.shuffle)
102
+ end
103
+
104
+ it "is deduplicated" do
105
+ expect(mut).to eq MSFL::Types::Set.new([:foo, "bar", nil, 99])
106
+ end
107
+
108
+ context "when the array's values are scalars" do
109
+
110
+ let(:arg) { ["bar", 1337] }
111
+
112
+ it "is equal to MSFL::Types::Set.new(argument)" do
113
+ expect(mut).to eq(MSFL::Types::Set.new arg)
114
+ end
115
+ end
116
+
117
+ context "when the argument includes at least one Hash" do
118
+
119
+ let(:arg) { ["bar", hash_in_arg, 84] }
120
+
121
+ let(:hash_in_arg) { { cat: 1221, dog: "fur" } }
122
+
123
+ it "includes the hash from the argument" do
124
+ expect(mut).to include hash_in_arg
125
+ end
126
+ end
127
+
128
+ context "when the argument includes at least one Array" do
129
+
130
+ let(:arg) { ["bar", array_in_arg, 84] }
131
+
132
+ let(:array_in_arg) { [444.3, "where'swaldo"] }
133
+
134
+ let(:expected_result) { MSFL::Types::Set.new ["bar", MSFL::Types::Set.new(array_in_arg), 84] }
135
+
136
+ it "replaces the outer Array with an equivalent MSFL::Types::Set" do
137
+ expect(mut).to eq expected_result
138
+ end
139
+
140
+ it "replaces the inner Array with an equivalent MSFL::Types::Set" do
141
+ expect(mut).to include MSFL::Types::Set.new(array_in_arg)
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
File without changes
@@ -0,0 +1,124 @@
1
+ require 'spec_helper'
2
+
3
+ describe "MSFL::Validators::Semantic" do
4
+
5
+ describe "#initialize" do
6
+
7
+ subject(:mut) { MSFL::Validators::Semantic.new dataset }
8
+
9
+ let(:dataset) { nil }
10
+
11
+ context "when the dataset argument is specified" do
12
+
13
+ let(:dataset) { Object.new }
14
+
15
+ it "has the dataset argument's value as the dataset" do
16
+ expect(mut.dataset).to be dataset
17
+ end
18
+ end
19
+
20
+ context "when the dataset argument is not specified" do
21
+
22
+ context "when MSFL is configured for one or more datasets" do
23
+
24
+ before { MSFL.configure(reset: true) { |configuration| configuration.datasets = [MSFL::Datasets::Movies] } }
25
+
26
+ it "has an instance of the first item in MSFL.configuration.datasets (an instance of Class) as the dataset" do
27
+ expect(mut.dataset).to be_a MSFL::Datasets::Movies
28
+ end
29
+ end
30
+
31
+ context "when MSFL is not configured for any datasets" do
32
+
33
+ before { MSFL.configure(reset: true) }
34
+
35
+ it "has an instance of MSFL::Datasets::Base as the dataset" do
36
+ expect(mut.dataset).to be_a MSFL::Datasets::Base
37
+ end
38
+ end
39
+ end
40
+
41
+ end
42
+
43
+ describe "#validate_set" do
44
+
45
+ subject(:mut) { test_instance.validate_set set, errors, options }
46
+
47
+ let(:test_instance) { MSFL::Validators::Semantic.new }
48
+
49
+ let(:set) { MSFL::Types::Set.new([ ]) }
50
+
51
+ let(:errors) { [ ] }
52
+
53
+ let(:options) { { } }
54
+
55
+ context "when the errors argument has items" do
56
+
57
+ let(:errors) { [error_message] }
58
+
59
+ let(:error_message) { "This is an error message" }
60
+
61
+ it "is an array containing at least all of the error messages from the original errors argument" do
62
+ expect(mut).to include error_message
63
+ end
64
+ end
65
+
66
+ context "when opts does not have the key :parent_operator" do
67
+
68
+ let(:error_message) do
69
+ "Validate set requires the :parent_operator option be set and represented in either the BOOLEAN_OPERATORS
70
+ or ENUMERATION_OPERATORS constant"
71
+ end
72
+
73
+ it "appends an error to errors" do
74
+ expect(mut).to include error_message
75
+ end
76
+ end
77
+
78
+ context "when opts[:parent_operator] is in BOOLEAN_OPERATORS" do
79
+
80
+ let(:options) { { parent_operator: :and } }
81
+
82
+ let(:test_instance) do
83
+ t_i = MSFL::Validators::Semantic.new
84
+ allow(t_i).to receive(:validate_boolean_set) { errors }
85
+ expect(t_i).to receive(:validate_boolean_set).once.with(set, errors, options)
86
+ t_i
87
+ end
88
+
89
+ it "invokes #validate_boolean_set once with the same arguments" do
90
+ mut
91
+ end
92
+ end
93
+
94
+ context "when opts[:parent_operator] is in ENUMERATION_OPERATORS" do
95
+
96
+ let(:options) { { parent_operator: :in } }
97
+
98
+ let(:test_instance) do
99
+ t_i = MSFL::Validators::Semantic.new
100
+ allow(t_i).to receive(:validate_enumeration_set) { errors }
101
+ expect(t_i).to receive(:validate_enumeration_set).once.with(set, errors, options)
102
+ t_i
103
+ end
104
+
105
+ it "invokes #validate_enumeration_set once with the same arguments" do
106
+ mut
107
+ end
108
+ end
109
+
110
+ context "when opts[:parent_operator] is not in neither BOOLEAN_OPERATORS nor ENUMERATION_OPERATORS" do
111
+
112
+ let(:options) { { parent_operator: :not_in_either } }
113
+
114
+ let(:error_message) do
115
+ "Validate set requires the :parent_operator option be set and represented in either the BOOLEAN_OPERATORS
116
+ or ENUMERATION_OPERATORS constant"
117
+ end
118
+
119
+ it "appends an error to errors" do
120
+ expect(mut).to include error_message
121
+ end
122
+ end
123
+ end
124
+ end
data/spec/msfl_spec.rb ADDED
@@ -0,0 +1,91 @@
1
+ require 'spec_helper'
2
+ require 'msfl/datasets/movies'
3
+ describe "MSFL" do
4
+
5
+ let(:json_encoded_msfl) do
6
+ '{
7
+ "or": [
8
+ {
9
+ "and": [
10
+ {
11
+ "title": {
12
+ "in": [
13
+ "Frozen",
14
+ "Big Hero 6",
15
+ "Apollo 13"
16
+ ]
17
+ }
18
+ },
19
+ {
20
+ "rating": {
21
+ "gte": "PG"
22
+ }
23
+ }
24
+ ]
25
+ },
26
+ {
27
+ "earnings": {
28
+ "lt": 5000000
29
+ }
30
+ }
31
+ ]
32
+ }'
33
+ end
34
+
35
+ let(:invalid_ruby_encoded_msfl) do
36
+ { not_a_field_in_dataset: "foobar" }
37
+ end
38
+
39
+ let(:ruby_encoded_msfl) do
40
+ {
41
+ or: MSFL::Types::Set.new([
42
+ {
43
+ and: MSFL::Types::Set.new([
44
+ {
45
+ title: {
46
+ in: MSFL::Types::Set.new([
47
+ "Frozen",
48
+ "Big Hero 6",
49
+ "Apollo 13"
50
+ ])
51
+ }
52
+ },
53
+ {
54
+ rating: {
55
+ gte: "PG"
56
+ }
57
+ }
58
+ ])
59
+ },
60
+ {
61
+ earnings: {
62
+ lt: 5000000
63
+ }
64
+ }
65
+ ])
66
+ }
67
+ end
68
+
69
+ let(:parser) { MSFL::Parsers::JSON }
70
+
71
+ let(:validator) { MSFL::Validators::Semantic.new }
72
+
73
+ it "is configured using a block" do
74
+ MSFL.configure(reset: true) { |configuration| configuration.datasets = [MSFL::Datasets::Movies] }
75
+ expect(MSFL.configuration.datasets).to eq [MSFL::Datasets::Movies]
76
+ end
77
+
78
+ it "parses json encoded MSFL" do
79
+ expect(parser.parse json_encoded_msfl).to eq ruby_encoded_msfl
80
+ end
81
+
82
+ it "rejects invalid MSFL filters" do
83
+ MSFL.configure(reset: true) { |conf| conf.datasets = [MSFL::Datasets::Movies] }
84
+ expect(validator.validate invalid_ruby_encoded_msfl).to be false
85
+ end
86
+
87
+ it "accepts valid MSFL filters" do
88
+ MSFL.configure(reset: true) { |conf| conf.datasets = [MSFL::Datasets::Movies] }
89
+ expect(validator.validate ruby_encoded_msfl).to be true
90
+ end
91
+ end
@@ -0,0 +1,6 @@
1
+ require_relative '../simplecov_custom_profiles'
2
+ SimpleCov.start 'msfl'
3
+ require 'rspec/support/spec'
4
+ require 'byebug'
5
+ require_relative '../lib/msfl'
6
+ require_relative 'msfl/shared_examples'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: msfl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.pre.qa
4
+ version: 0.0.1.pre.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Courtland Caldwell
@@ -101,6 +101,13 @@ executables: []
101
101
  extensions: []
102
102
  extra_rdoc_files: []
103
103
  files:
104
+ - .gitignore
105
+ - Gemfile
106
+ - Gemfile.lock
107
+ - LICENSE
108
+ - README.md
109
+ - Rakefile
110
+ - circle.yml
104
111
  - lib/msfl.rb
105
112
  - lib/msfl/configuration.rb
106
113
  - lib/msfl/datasets.rb
@@ -114,6 +121,14 @@ files:
114
121
  - lib/msfl/validators/definitions.rb
115
122
  - lib/msfl/validators/definitions/hash_key.rb
116
123
  - lib/msfl/validators/semantic.rb
124
+ - msfl.gemspec
125
+ - simplecov_custom_profiles.rb
126
+ - spec/msfl/datasets/base_spec.rb
127
+ - spec/msfl/parsers/json_spec.rb
128
+ - spec/msfl/shared_examples.rb
129
+ - spec/msfl/validators/semantic_spec.rb
130
+ - spec/msfl_spec.rb
131
+ - spec/spec_helper.rb
117
132
  homepage: https://github.com/caldwecr/msfl
118
133
  licenses:
119
134
  - MIT
@@ -138,5 +153,11 @@ rubygems_version: 2.4.2
138
153
  signing_key:
139
154
  specification_version: 4
140
155
  summary: MSFL in Ruby
141
- test_files: []
156
+ test_files:
157
+ - spec/msfl/datasets/base_spec.rb
158
+ - spec/msfl/parsers/json_spec.rb
159
+ - spec/msfl/shared_examples.rb
160
+ - spec/msfl/validators/semantic_spec.rb
161
+ - spec/msfl_spec.rb
162
+ - spec/spec_helper.rb
142
163
  has_rdoc: