paradocs 1.0.22
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/.github/workflows/spec.yml +25 -0
- data/.gitignore +19 -0
- data/.gitlab-ci.yml +20 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +23 -0
- data/README.md +1078 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/lib/paradocs/base_policy.rb +123 -0
- data/lib/paradocs/context.rb +54 -0
- data/lib/paradocs/default_types.rb +95 -0
- data/lib/paradocs/dsl.rb +68 -0
- data/lib/paradocs/extensions/insides.rb +77 -0
- data/lib/paradocs/field.rb +152 -0
- data/lib/paradocs/field_dsl.rb +36 -0
- data/lib/paradocs/policies.rb +170 -0
- data/lib/paradocs/registry.rb +42 -0
- data/lib/paradocs/results.rb +13 -0
- data/lib/paradocs/schema.rb +214 -0
- data/lib/paradocs/struct.rb +102 -0
- data/lib/paradocs/support.rb +47 -0
- data/lib/paradocs/version.rb +3 -0
- data/lib/paradocs/whitelist.rb +91 -0
- data/lib/paradocs.rb +36 -0
- data/paradocs.gemspec +25 -0
- data/spec/custom_block_validator_spec.rb +88 -0
- data/spec/custom_validator.rb +61 -0
- data/spec/dsl_spec.rb +175 -0
- data/spec/expand_spec.rb +29 -0
- data/spec/field_spec.rb +416 -0
- data/spec/helpers.rb +18 -0
- data/spec/policies_spec.rb +159 -0
- data/spec/schema_spec.rb +299 -0
- data/spec/schema_structures_spec.rb +169 -0
- data/spec/schema_walk_spec.rb +42 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/struct_spec.rb +324 -0
- data/spec/subschema_spec.rb +178 -0
- data/spec/validators_spec.rb +86 -0
- data/spec/whitelist_spec.rb +97 -0
- metadata +162 -0
data/spec/field_spec.rb
ADDED
@@ -0,0 +1,416 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Paradocs::Field do
|
4
|
+
let(:context) { Paradocs::Context.new }
|
5
|
+
|
6
|
+
subject { described_class.new(:a_key) }
|
7
|
+
|
8
|
+
def register_coercion(name, block)
|
9
|
+
Paradocs.registry.policy name do
|
10
|
+
coerce &block
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def resolve(subject, payload)
|
15
|
+
subject.resolve(payload, context)
|
16
|
+
end
|
17
|
+
|
18
|
+
def has_errors
|
19
|
+
expect(context.errors.keys).not_to be_empty
|
20
|
+
end
|
21
|
+
|
22
|
+
def no_errors
|
23
|
+
expect(context.errors.keys).to be_empty
|
24
|
+
end
|
25
|
+
|
26
|
+
def has_error(key, message)
|
27
|
+
expect(context.errors[key]).to include(message)
|
28
|
+
end
|
29
|
+
|
30
|
+
let(:payload) { {a_key: "Joe"} }
|
31
|
+
|
32
|
+
describe "#resolve" do
|
33
|
+
it "returns value" do
|
34
|
+
resolve(subject, payload).tap do |r|
|
35
|
+
expect(r.eligible?).to be true
|
36
|
+
no_errors
|
37
|
+
expect(r.value).to eq "Joe"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
BUILT_IN_COERCIONS = [:string, :integer, :number, :array, :object, :boolean]
|
43
|
+
|
44
|
+
describe "#meta_data" do
|
45
|
+
BUILT_IN_COERCIONS.each do |t|
|
46
|
+
it "policy #{t} adds #{t} to meta data" do
|
47
|
+
subject.policy(t)
|
48
|
+
expect(subject.meta_data[:type]).to eq t
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#type" do
|
54
|
+
it "is an alias for #policy" do
|
55
|
+
subject.type(:integer)
|
56
|
+
resolve(subject, a_key: "10.0").tap do |r|
|
57
|
+
expect(r.value).to eq 10
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "#policy" do
|
63
|
+
it "coerces integer" do
|
64
|
+
subject.policy(:integer)
|
65
|
+
resolve(subject, a_key: "10.0").tap do |r|
|
66
|
+
expect(r.eligible?).to be true
|
67
|
+
no_errors
|
68
|
+
expect(r.value).to eq 10
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
it "coerces number" do
|
73
|
+
subject.policy(:number)
|
74
|
+
resolve(subject, a_key: "10.0").tap do |r|
|
75
|
+
expect(r.eligible?).to be true
|
76
|
+
no_errors
|
77
|
+
expect(r.value).to eq 10.0
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
it "coerces string" do
|
82
|
+
subject.policy(:string)
|
83
|
+
resolve(subject, a_key: 10.0).tap do |r|
|
84
|
+
expect(r.eligible?).to be true
|
85
|
+
no_errors
|
86
|
+
expect(r.value).to eq "10.0"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "#default" do
|
92
|
+
it "is default if missing key" do
|
93
|
+
resolve(subject.default("AA"), foobar: 1).tap do |r|
|
94
|
+
expect(r.eligible?).to be true
|
95
|
+
no_errors
|
96
|
+
expect(r.value).to eq "AA"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
it "returns value if key is present" do
|
101
|
+
resolve(subject.default("AA"), a_key: nil).tap do |r|
|
102
|
+
expect(r.eligible?).to be true
|
103
|
+
no_errors
|
104
|
+
expect(r.value).to eq nil
|
105
|
+
end
|
106
|
+
|
107
|
+
resolve(subject.default("AA"), a_key: "abc").tap do |r|
|
108
|
+
expect(r.eligible?).to be true
|
109
|
+
no_errors
|
110
|
+
expect(r.value).to eq "abc"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe "#present" do
|
116
|
+
it "is valid if value is present" do
|
117
|
+
resolve(subject.present, a_key: "abc").tap do |r|
|
118
|
+
expect(r.eligible?).to be true
|
119
|
+
no_errors
|
120
|
+
expect(r.value).to eq "abc"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
it "is invalid if value is empty" do
|
125
|
+
resolve(subject.present, a_key: "").tap do |r|
|
126
|
+
expect(r.eligible?).to be true
|
127
|
+
has_errors
|
128
|
+
expect(r.value).to eq ""
|
129
|
+
end
|
130
|
+
|
131
|
+
resolve(subject.present, a_key: nil).tap do |r|
|
132
|
+
expect(r.eligible?).to be true
|
133
|
+
has_errors
|
134
|
+
expect(r.value).to eq nil
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
it "is invalid if key is missing" do
|
139
|
+
resolve(subject.present, foo: "abc").tap do |r|
|
140
|
+
expect(r.eligible?).to be true
|
141
|
+
has_errors
|
142
|
+
expect(r.value).to eq nil
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe "#required" do
|
148
|
+
it "is valid if key is present" do
|
149
|
+
resolve(subject.required, a_key: "abc").tap do |r|
|
150
|
+
expect(r.eligible?).to be true
|
151
|
+
no_errors
|
152
|
+
expect(r.value).to eq "abc"
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
it "is valid if key is present and value empty" do
|
157
|
+
resolve(subject.required, a_key: "").tap do |r|
|
158
|
+
expect(r.eligible?).to be true
|
159
|
+
no_errors
|
160
|
+
expect(r.value).to eq ""
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
it "is invalid if key is missing" do
|
165
|
+
resolve(subject.required, foobar: "lala").tap do |r|
|
166
|
+
expect(r.eligible?).to be true
|
167
|
+
has_errors
|
168
|
+
expect(r.value).to eq nil
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
describe "#options" do
|
174
|
+
before do
|
175
|
+
subject.options(['a', 'b', 'c'])
|
176
|
+
end
|
177
|
+
|
178
|
+
it "resolves if value within options" do
|
179
|
+
resolve(subject, a_key: "b").tap do |r|
|
180
|
+
expect(r.eligible?).to be true
|
181
|
+
no_errors
|
182
|
+
expect(r.value).to eq "b"
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
it "resolves if value is array within options" do
|
187
|
+
resolve(subject, a_key: ["b", "c"]).tap do |r|
|
188
|
+
expect(r.eligible?).to be true
|
189
|
+
no_errors
|
190
|
+
expect(r.value).to eq ["b", "c"]
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
it "does not resolve if missing key" do
|
195
|
+
resolve(subject, foobar: ["b", "c"]).tap do |r|
|
196
|
+
expect(r.eligible?).to be false
|
197
|
+
no_errors
|
198
|
+
expect(r.value).to be_nil
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
it "does resolve if missing key and default set" do
|
203
|
+
subject.default("Foobar")
|
204
|
+
resolve(subject, foobar: ["b", "c"]).tap do |r|
|
205
|
+
expect(r.eligible?).to be true
|
206
|
+
has_errors
|
207
|
+
expect(r.value).to eq "Foobar"
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
it "is invalid if missing key and required" do
|
212
|
+
subject = described_class.new(:a_key).required.options(%w(a b c))
|
213
|
+
resolve(subject, foobar: ["b", "c"]).tap do |r|
|
214
|
+
expect(r.eligible?).to be true
|
215
|
+
has_errors
|
216
|
+
expect(r.value).to be_nil
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
it "is invalid if value outside options" do
|
221
|
+
resolve(subject, a_key: "x").tap do |r|
|
222
|
+
expect(r.eligible?).to be true
|
223
|
+
has_errors
|
224
|
+
expect(r.value).to eq "x"
|
225
|
+
end
|
226
|
+
|
227
|
+
resolve(subject, a_key: ["x", "b"]).tap do |r|
|
228
|
+
expect(r.eligible?).to be true
|
229
|
+
has_errors
|
230
|
+
expect(r.value).to eq ["x", "b"]
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
describe ":split policy" do
|
236
|
+
it "splits by comma" do
|
237
|
+
resolve(subject.policy(:split), a_key: "tag1,tag2").tap do |r|
|
238
|
+
expect(r.eligible?).to be true
|
239
|
+
no_errors
|
240
|
+
expect(r.value).to eq ["tag1", "tag2"]
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
describe ":declared policy" do
|
246
|
+
it "is eligible if key exists" do
|
247
|
+
resolve(subject.policy(:declared).present, a_key: "").tap do |r|
|
248
|
+
expect(r.eligible?).to be true
|
249
|
+
has_errors
|
250
|
+
expect(r.value).to eq ""
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
it "is available as method" do
|
255
|
+
resolve(subject.declared.present, a_key: "").tap do |r|
|
256
|
+
expect(r.eligible?).to be true
|
257
|
+
has_errors
|
258
|
+
expect(r.value).to eq ""
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
it "is not eligible if key does not exist" do
|
263
|
+
resolve(subject.policy(:declared).present, foo: "").tap do |r|
|
264
|
+
expect(r.eligible?).to be false
|
265
|
+
no_errors
|
266
|
+
expect(r.value).to eq nil
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
describe ":noop policy" do
|
272
|
+
it "does not do anything" do
|
273
|
+
resolve(subject.policy(:noop).present, a_key: "").tap do |r|
|
274
|
+
expect(r.eligible?).to be true
|
275
|
+
has_errors
|
276
|
+
expect(r.value).to eq ""
|
277
|
+
end
|
278
|
+
|
279
|
+
resolve(subject.policy(:noop).present, foo: "").tap do |r|
|
280
|
+
expect(r.eligible?).to be true
|
281
|
+
has_errors
|
282
|
+
expect(r.value).to eq nil
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
describe "#schema" do
|
288
|
+
it "runs sub-schema" do
|
289
|
+
subject.schema do
|
290
|
+
field(:name).policy(:string)
|
291
|
+
field(:tags).policy(:split).policy(:array)
|
292
|
+
end
|
293
|
+
|
294
|
+
payload = {a_key: [{name: "n1", tags: "t1,t2"}, {name: "n2", tags: ["t3"]}]}
|
295
|
+
|
296
|
+
resolve(subject, payload).tap do |r|
|
297
|
+
expect(r.eligible?).to be true
|
298
|
+
no_errors
|
299
|
+
expect(r.value).to eq([
|
300
|
+
{name: "n1", tags: ["t1", "t2"]},
|
301
|
+
{name: "n2", tags: ["t3"]},
|
302
|
+
])
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
describe '#policy' do
|
308
|
+
let(:custom_klass) do
|
309
|
+
Class.new do
|
310
|
+
def initialize(title = 'Sr.')
|
311
|
+
@title = title
|
312
|
+
end
|
313
|
+
|
314
|
+
def eligible?(*_)
|
315
|
+
true
|
316
|
+
end
|
317
|
+
|
318
|
+
def valid?(*_)
|
319
|
+
true
|
320
|
+
end
|
321
|
+
|
322
|
+
def coerce(value, key, context)
|
323
|
+
"#{@title} #{value}"
|
324
|
+
end
|
325
|
+
|
326
|
+
def meta_data
|
327
|
+
{foo: "bar"}
|
328
|
+
end
|
329
|
+
|
330
|
+
def policy_name
|
331
|
+
:custom_policy
|
332
|
+
end
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
it 'works with policy in registry' do
|
337
|
+
register_coercion :foo, ->(v, k, c){ "Hello #{v}" }
|
338
|
+
subject.policy(:foo)
|
339
|
+
resolve(subject, a_key: "Ismael").tap do |r|
|
340
|
+
expect(r.eligible?).to be true
|
341
|
+
no_errors
|
342
|
+
expect(r.value).to eq "Hello Ismael"
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
it 'raises if policy not found' do
|
347
|
+
expect{
|
348
|
+
subject.policy(:foobar)
|
349
|
+
}.to raise_exception Paradocs::ConfigurationError
|
350
|
+
end
|
351
|
+
|
352
|
+
it 'chains policies' do
|
353
|
+
Paradocs.registry.policy :general, custom_klass.new("General")
|
354
|
+
Paradocs.registry.policy :commander, custom_klass.new("Commander")
|
355
|
+
|
356
|
+
subject
|
357
|
+
.policy(:general)
|
358
|
+
.policy(:commander)
|
359
|
+
|
360
|
+
resolve(subject, a_key: "Ismael").tap do |r|
|
361
|
+
expect(r.eligible?).to be true
|
362
|
+
no_errors
|
363
|
+
expect(r.value).to eq "Commander General Ismael"
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
it "can instantiate policy class and pass arguments" do
|
368
|
+
Paradocs.registry.policy :job_title, custom_klass
|
369
|
+
|
370
|
+
subject.policy(:job_title, "Developer")
|
371
|
+
|
372
|
+
resolve(subject, a_key: "Ismael").tap do |r|
|
373
|
+
expect(r.eligible?).to be true
|
374
|
+
no_errors
|
375
|
+
expect(r.value).to eq "Developer Ismael"
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
it "can take a class not in the registry" do
|
380
|
+
subject.policy(custom_klass, "Developer")
|
381
|
+
|
382
|
+
resolve(subject, a_key: "Ismael").tap do |r|
|
383
|
+
expect(r.eligible?).to be true
|
384
|
+
no_errors
|
385
|
+
expect(r.value).to eq "Developer Ismael"
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
it "adds policy meta data" do
|
390
|
+
subject.policy(custom_klass, "Developer")
|
391
|
+
expect(subject.meta_data[:foo]).to eq "bar"
|
392
|
+
end
|
393
|
+
|
394
|
+
it "can take an instance not in the registry" do
|
395
|
+
subject.policy(custom_klass.new("Developer"), "ignore this")
|
396
|
+
|
397
|
+
resolve(subject, a_key: "Ismael").tap do |r|
|
398
|
+
expect(r.eligible?).to be true
|
399
|
+
no_errors
|
400
|
+
expect(r.value).to eq "Developer Ismael"
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
it 'add policy message to #errors if validation fails' do
|
405
|
+
register_coercion :error, ->(v, k, c) { raise "This is an error" }
|
406
|
+
|
407
|
+
subject.policy(:error)
|
408
|
+
|
409
|
+
resolve(subject, a_key: "b").tap do |r|
|
410
|
+
expect(r.eligible?).to be true
|
411
|
+
has_error("$", "is invalid")
|
412
|
+
expect(r.value).to eq "b"
|
413
|
+
end
|
414
|
+
end
|
415
|
+
end
|
416
|
+
end
|
data/spec/helpers.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
def expected_policy_behavior(policy:, policy_args: [], input:, output: nil, errors: {}, environment: {}, ignore_for: [])
|
2
|
+
output ||= input
|
3
|
+
schema = Paradocs::Schema.new do
|
4
|
+
input.map do |key, value|
|
5
|
+
instruction = ignore_for.include?(key) ? -> { field(key) } : -> { field(key).policy(*([policy] + policy_args)) }
|
6
|
+
|
7
|
+
instance_exec &instruction
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
if block_given? || output.nil?
|
12
|
+
expect { schema.resolve(input, environment) }.to yield
|
13
|
+
else
|
14
|
+
result = schema.resolve(input, environment)
|
15
|
+
expect(result.output).to eq(output)
|
16
|
+
expect(result.errors).to eq(errors)
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'default coercions' do
|
4
|
+
def test_coercion(key, value, expected)
|
5
|
+
coercion = Paradocs.registry.coercions[key]
|
6
|
+
expect(coercion.new.coerce(value, nil, nil)).to eq expected
|
7
|
+
end
|
8
|
+
|
9
|
+
describe ':datetime' do
|
10
|
+
it {
|
11
|
+
coercion = Paradocs.registry.coercions[:datetime]
|
12
|
+
coercion.new.coerce("2016-11-05T14:23:34Z", nil, nil).tap do |d|
|
13
|
+
expect(d).to be_a Date
|
14
|
+
expect(d.year).to eq 2016
|
15
|
+
expect(d.month).to eq 11
|
16
|
+
expect(d.day).to eq 5
|
17
|
+
expect(d.hour).to eq 14
|
18
|
+
expect(d.minute).to eq 23
|
19
|
+
expect(d.second).to eq 34
|
20
|
+
expect(d.zone).to eq "+00:00"
|
21
|
+
end
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
describe ':integer' do
|
26
|
+
it {
|
27
|
+
test_coercion(:integer, '10', 10)
|
28
|
+
test_coercion(:integer, '10.20', 10)
|
29
|
+
test_coercion(:integer, 10.20, 10)
|
30
|
+
test_coercion(:integer, 10, 10)
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
describe ':number' do
|
35
|
+
it {
|
36
|
+
test_coercion(:number, '10', 10.0)
|
37
|
+
test_coercion(:number, '10.20', 10.20)
|
38
|
+
test_coercion(:number, 10.20, 10.20)
|
39
|
+
test_coercion(:number, 10, 10.0)
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
describe ':string' do
|
44
|
+
it {
|
45
|
+
test_coercion(:string, '10', '10')
|
46
|
+
test_coercion(:string, '10.20', '10.20')
|
47
|
+
test_coercion(:string, 10.20, '10.2')
|
48
|
+
test_coercion(:string, 10, '10')
|
49
|
+
test_coercion(:string, true, 'true')
|
50
|
+
test_coercion(:string, 'hello', 'hello')
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
describe ':boolean' do
|
55
|
+
it {
|
56
|
+
test_coercion(:boolean, true, true)
|
57
|
+
test_coercion(:boolean, '10', true)
|
58
|
+
test_coercion(:boolean, '', true)
|
59
|
+
test_coercion(:boolean, nil, false)
|
60
|
+
test_coercion(:boolean, false, false)
|
61
|
+
}
|
62
|
+
end
|
63
|
+
|
64
|
+
describe ':split' do
|
65
|
+
it {
|
66
|
+
test_coercion(:split, 'aaa,bb,cc', ['aaa', 'bb', 'cc'])
|
67
|
+
test_coercion(:split, 'aaa ,bb, cc', ['aaa', 'bb', 'cc'])
|
68
|
+
test_coercion(:split, 'aaa', ['aaa'])
|
69
|
+
test_coercion(:split, ['aaa', 'bb', 'cc'], ['aaa', 'bb', 'cc'])
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
describe ':gt' do
|
74
|
+
it "passes the value if it's greater than policy param" do
|
75
|
+
expected_policy_behavior(policy: :gt, policy_args: [3], input: {a: 4}, output: {a: 4})
|
76
|
+
end
|
77
|
+
|
78
|
+
it "raises error if value is greater to policy param" do
|
79
|
+
errors = {"$.a"=>["value must be strictly greater than 10"]}
|
80
|
+
errors2 = {"$.a"=>["value must be strictly greater than 10"]}
|
81
|
+
expected_policy_behavior(policy: :gt, policy_args: [10], input: {a: 4}, errors: errors)
|
82
|
+
expected_policy_behavior(policy: :gt, policy_args: [10], input: {a: 10}, errors: errors2)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe ':gte' do
|
87
|
+
it "passes the value if it's greater or equal to policy param" do
|
88
|
+
expected_policy_behavior(policy: :gte, policy_args: [3], input: {a: 4}, output: {a: 4})
|
89
|
+
expected_policy_behavior(policy: :gte, policy_args: [3], input: {a: 3}, output: {a: 3})
|
90
|
+
end
|
91
|
+
|
92
|
+
it "raises error if value is greater than policy param" do
|
93
|
+
errors = {"$.a"=>["value must be greater than or equal to 10"]}
|
94
|
+
expected_policy_behavior(policy: :gte, policy_args: [10], input: {a: 4}, errors: errors)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe ':lt' do
|
99
|
+
it "passes the value if it's less to policy param" do
|
100
|
+
expected_policy_behavior(policy: :lt, policy_args: [100], input: {a: 4}, output: {a: 4})
|
101
|
+
end
|
102
|
+
|
103
|
+
it "raises error if value is strictly less to policy param" do
|
104
|
+
errors = {"$.a"=>["value must be strictly less than 10"]}
|
105
|
+
errors2 = {"$.a"=>["value must be strictly less than 10"]}
|
106
|
+
expected_policy_behavior(policy: :lt, policy_args: [10], input: {a: 40}, errors: errors)
|
107
|
+
expected_policy_behavior(policy: :lt, policy_args: [10], input: {a: 10}, errors: errors2)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe ':lte' do
|
112
|
+
it "passes the value if it's less or equal to policy param" do
|
113
|
+
expected_policy_behavior(policy: :lte, policy_args: [100], input: {a: 4}, output: {a: 4})
|
114
|
+
expected_policy_behavior(policy: :lte, policy_args: [100], input: {a: 100}, output: {a: 100})
|
115
|
+
end
|
116
|
+
|
117
|
+
it "raises error if value is less or equal than policy param" do
|
118
|
+
errors = {"$.a"=>["value must be less than or equal to 1"]}
|
119
|
+
expected_policy_behavior(policy: :lte, policy_args: [1], input: {a: 40}, output: {a: 40}, errors: errors)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe ':length' do
|
124
|
+
it "passes the value if it's between min and max limits" do
|
125
|
+
expected_policy_behavior(policy: :length, policy_args: [{min: 5, max: 20}], input: {a: "string"}, output: {a: "string"})
|
126
|
+
expected_policy_behavior(policy: :length, policy_args: [{min: 5}], input: {a: "string"}, output: {a: "string"})
|
127
|
+
expected_policy_behavior(policy: :length, policy_args: [{max: 20}], input: {a: "string"}, output: {a: "string"})
|
128
|
+
end
|
129
|
+
|
130
|
+
it "passes the value if it's exactly :eq limit" do
|
131
|
+
expected_policy_behavior(policy: :length, policy_args: [{eq: 5}], input: {a: "12345"}, output: {a: "12345"})
|
132
|
+
end
|
133
|
+
|
134
|
+
it "raises error if value is not exactly than defined :eq limit" do
|
135
|
+
errors = {"$.a"=>["value must be exactly 10 characters"]}
|
136
|
+
expected_policy_behavior(policy: :length, policy_args: [{eq: 10}], input: {a: "test"}, output: {a: "test"}, errors: errors)
|
137
|
+
end
|
138
|
+
|
139
|
+
it "raises error if value is less than min limit" do
|
140
|
+
errors = {"$.a"=>["value must be minimum 10 characters"]}
|
141
|
+
expected_policy_behavior(policy: :length, policy_args: [{min: 10}], input: {a: "test"}, output: {a: "test"}, errors: errors)
|
142
|
+
end
|
143
|
+
|
144
|
+
it "raises error if value is greater than max limit" do
|
145
|
+
errors = {"$.a"=>["value must be maximum 3 characters"]}
|
146
|
+
expected_policy_behavior(policy: :length, policy_args: [{max: 3}], input: {a: "test"}, output: {a: "test"}, errors: errors)
|
147
|
+
end
|
148
|
+
|
149
|
+
it "raises error with full description if value is less than min limit" do
|
150
|
+
errors = {"$.a"=>["value must be minimum 10 characters, maximum 20 characters"]}
|
151
|
+
expected_policy_behavior(policy: :length, policy_args: [{min: 10, max: 20}], input: {a: "test"}, output: {a: "test"}, errors: errors)
|
152
|
+
end
|
153
|
+
|
154
|
+
it "raises error with full description if value is greater than max limit" do
|
155
|
+
errors = {"$.a"=>["value must be minimum 3 characters, maximum 5 characters"]}
|
156
|
+
expected_policy_behavior(policy: :length, policy_args: [{min: 3, max: 5}], input: {a: "test_test"}, output: {a: "test_test"}, errors: errors)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|