fakeit 0.5.2 → 0.6.3

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
  SHA256:
3
- metadata.gz: 30ea4d2aa93efde5e87605835f598e5f73de921fd00d2fd4f15b1784dbc44c87
4
- data.tar.gz: e10dc92c54c9463a7a75c9caf0391d1a563445d99ded2e0d02038cde2f7c9886
3
+ metadata.gz: 35c58ad2d52ce6f2ba2375738faaed686b7945ce0d3e438d0d5e3e78f7d32d71
4
+ data.tar.gz: 4c9a1566b7256b2b5b8fb7772daf1329810644b646f2ac0c939d5a3fd824a8db
5
5
  SHA512:
6
- metadata.gz: fdca80c0d4597949df629c3691bac048ed915bbe7fc69ea684c28d36bb21ecf6aa469910e107a9e8264fc93d11db6e23ded0d97a42b19e8bc613e63b2f0d0df2
7
- data.tar.gz: 12b14f11d000f28bc18534f3ceb20f6ccc2cb1fac8ced1e9b28e74c2a6886b302e0106f504229ac8becac342632c6df3fcbd133d8d77694a23d8aaec196c34f1
6
+ metadata.gz: 0c3b0375ac956484083b108bb3284ccd33adda44e002b310b7e44fdb2ce151f1b62729a095f9caa02d2953d7dd809e4144fa33612756aa3189cee358e279ae18
7
+ data.tar.gz: 71e3391f4570e12b3c940476e0657e700088ef72f122ccf6e354e71e43ed47ef3d082e7d7f972fc5b35c3fb111aba38110b00d36725eaaafbaeb18750d6ebc96
@@ -1,5 +1,6 @@
1
1
  AllCops:
2
2
  TargetRubyVersion: 2.7
3
+ NewCops: enable
3
4
 
4
5
  Style/Documentation:
5
6
  Enabled: false
@@ -18,11 +19,5 @@ Metrics/BlockLength:
18
19
  Security/Open:
19
20
  Enabled: false
20
21
 
21
- Style/HashEachMethods:
22
- Enabled: true
23
-
24
22
  Style/HashTransformKeys:
25
23
  Enabled: false
26
-
27
- Style/HashTransformValues:
28
- Enabled: true
@@ -1,67 +1,72 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fakeit (0.5.2)
5
- faker (~> 2.2)
6
- openapi_parser (= 0.8.0)
4
+ fakeit (0.6.3)
5
+ faker (= 2.13.0)
6
+ openapi_parser (= 0.12.1)
7
7
  rack (~> 2.0)
8
8
  rack-cors (~> 1.0)
9
9
  rainbow (~> 3.0)
10
- slop (~> 4.6)
10
+ regexp-examples (= 1.5.1)
11
+ slop (~> 4.8)
11
12
 
12
13
  GEM
13
14
  remote: https://rubygems.org/
14
15
  specs:
15
- ast (2.4.0)
16
- byebug (11.1.1)
17
- concurrent-ruby (1.1.6)
18
- diff-lcs (1.3)
16
+ ast (2.4.1)
17
+ byebug (11.1.3)
18
+ concurrent-ruby (1.1.7)
19
+ diff-lcs (1.4.4)
19
20
  docile (1.3.2)
20
- faker (2.10.2)
21
+ faker (2.13.0)
21
22
  i18n (>= 1.6, < 2)
22
- i18n (1.8.2)
23
+ i18n (1.8.5)
23
24
  concurrent-ruby (~> 1.0)
24
- jaro_winkler (1.5.4)
25
- openapi_parser (0.8.0)
26
- parallel (1.19.1)
27
- parser (2.7.0.2)
28
- ast (~> 2.4.0)
29
- rack (2.2.2)
25
+ openapi_parser (0.12.1)
26
+ parallel (1.19.2)
27
+ parser (2.7.1.4)
28
+ ast (~> 2.4.1)
29
+ rack (2.2.3)
30
30
  rack-cors (1.1.1)
31
31
  rack (>= 2.0.0)
32
32
  rack-test (1.1.0)
33
33
  rack (>= 1.0, < 3)
34
34
  rainbow (3.0.0)
35
35
  rake (12.3.3)
36
+ regexp-examples (1.5.1)
37
+ regexp_parser (1.7.1)
36
38
  rexml (3.2.4)
37
39
  rspec (3.9.0)
38
40
  rspec-core (~> 3.9.0)
39
41
  rspec-expectations (~> 3.9.0)
40
42
  rspec-mocks (~> 3.9.0)
41
- rspec-core (3.9.1)
42
- rspec-support (~> 3.9.1)
43
- rspec-expectations (3.9.0)
43
+ rspec-core (3.9.2)
44
+ rspec-support (~> 3.9.3)
45
+ rspec-expectations (3.9.2)
44
46
  diff-lcs (>= 1.2.0, < 2.0)
45
47
  rspec-support (~> 3.9.0)
46
48
  rspec-mocks (3.9.1)
47
49
  diff-lcs (>= 1.2.0, < 2.0)
48
50
  rspec-support (~> 3.9.0)
49
- rspec-support (3.9.2)
50
- rubocop (0.80.0)
51
- jaro_winkler (~> 1.5.1)
51
+ rspec-support (3.9.3)
52
+ rubocop (0.90.0)
52
53
  parallel (~> 1.10)
53
- parser (>= 2.7.0.1)
54
+ parser (>= 2.7.1.1)
54
55
  rainbow (>= 2.2.2, < 4.0)
56
+ regexp_parser (>= 1.7)
55
57
  rexml
58
+ rubocop-ast (>= 0.3.0, < 1.0)
56
59
  ruby-progressbar (~> 1.7)
57
- unicode-display_width (>= 1.4.0, < 1.7)
60
+ unicode-display_width (>= 1.4.0, < 2.0)
61
+ rubocop-ast (0.3.0)
62
+ parser (>= 2.7.1.4)
58
63
  ruby-progressbar (1.10.1)
59
- simplecov (0.18.2)
64
+ simplecov (0.19.0)
60
65
  docile (~> 1.1)
61
66
  simplecov-html (~> 0.11)
62
- simplecov-html (0.12.0)
63
- slop (4.8.0)
64
- unicode-display_width (1.6.1)
67
+ simplecov-html (0.12.2)
68
+ slop (4.8.2)
69
+ unicode-display_width (1.7.0)
65
70
 
66
71
  PLATFORMS
67
72
  ruby
data/README.md CHANGED
@@ -30,14 +30,12 @@ After tried several existing options, we cannot find a best solution to meet all
30
30
 
31
31
  ## Features
32
32
 
33
- * Randomly or statically generated response
34
- * Request validation
33
+ * Randomly or statically generated response (`application/.*json`)
34
+ * Request validation (`application/.*json`, `multipart/form-data`)
35
35
  * Load specification from local or remote
36
36
  * Support hot reload local specification
37
37
  * Support specification in yaml or json format
38
38
 
39
- **Note:** Only support json content type as of now
40
-
41
39
  ## Installation
42
40
 
43
41
  Install it with:
@@ -61,7 +59,7 @@ Command line options:
61
59
  --use-example use example provided in spec if exists
62
60
  --static generate static response
63
61
  --static-types generate static value for specified types, e.g. --static-types integer,string
64
- --static-properties generate static value for specified properties, e.g. --static-types id,uuid
62
+ --static-properties generate static value for specified properties, e.g. --static-properties id,uuid
65
63
 
66
64
  other options:
67
65
  -v, --version
@@ -11,7 +11,7 @@ The following Openapi properties are supported in random response generation
11
11
  | |minItems|Default: `1`|
12
12
  | |maxItems|Default: `minItems + 2`|
13
13
  |string|enum| |
14
- | |pattern| |
14
+ | |pattern|Random generated once and cached for performance concern|
15
15
  | |format=uri| |
16
16
  | |format=uuid| |
17
17
  | |format=guid| |
@@ -6,8 +6,9 @@ Static value generation rule
6
6
  |---|---|---|
7
7
  |complex|oneOf|first item|
8
8
  | |anyOf|same as allOf|
9
+ |boolean|N/A|`true`|
9
10
  |array|N/A|size is `1`|
10
- | |minItems|size is minItems|
11
+ | |minItems|size is max(minItems,1)|
11
12
  |string|N/A|`string`|
12
13
  | |enum|first item|
13
14
  | |pattern|Generated but always the same|
@@ -32,10 +32,11 @@ Gem::Specification.new do |spec|
32
32
  spec.add_development_dependency 'rubocop', '~> 0.80'
33
33
  spec.add_development_dependency 'simplecov', '~> 0.18'
34
34
 
35
- spec.add_dependency 'faker', '~> 2.2'
36
- spec.add_dependency 'openapi_parser', '0.8.0'
35
+ spec.add_dependency 'faker', '2.13.0'
36
+ spec.add_dependency 'openapi_parser', '0.12.1'
37
37
  spec.add_dependency 'rack', '~> 2.0'
38
38
  spec.add_dependency 'rack-cors', '~> 1.0'
39
39
  spec.add_dependency 'rainbow', '~> 3.0'
40
- spec.add_dependency 'slop', '~> 4.6'
40
+ spec.add_dependency 'regexp-examples', '1.5.1'
41
+ spec.add_dependency 'slop', '~> 4.8'
41
42
  end
@@ -4,6 +4,7 @@ require 'open-uri'
4
4
  require 'base64'
5
5
  require 'openapi_parser'
6
6
  require 'faker'
7
+ require 'regexp-examples'
7
8
  require 'rack'
8
9
  require 'logger'
9
10
  require 'rainbow'
@@ -36,7 +36,7 @@ module Fakeit
36
36
 
37
37
  def validate(operation, request)
38
38
  operation.validate(
39
- body: request.body&.read.to_s,
39
+ body: BodyParser.parse(request),
40
40
  params: parse_query(request.query_string),
41
41
  headers: headers(request)
42
42
  )
@@ -0,0 +1,30 @@
1
+ module Fakeit
2
+ module App
3
+ class BodyParser
4
+ class << self
5
+ def parse(request)
6
+ case request.media_type
7
+ when %r{^application/.*json}
8
+ { media_type: request.media_type, data: parse_json(request.body.read) }
9
+ when 'multipart/form-data'
10
+ { media_type: request.media_type, data: parse_form_data(request.params) }
11
+ else
12
+ { media_type: request.media_type, data: request.body.read }
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def parse_json(body)
19
+ body.empty? ? {} : JSON.parse(body)
20
+ rescue StandardError
21
+ raise Fakeit::Validation::ValidationError, 'Invalid json payload'
22
+ end
23
+
24
+ def parse_form_data(params)
25
+ params.transform_values { |v| v.class == Hash && v[:tempfile] ? v[:tempfile].read : v }
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,4 +1,4 @@
1
1
  module Fakeit
2
- STDOUT.sync = true
3
- Logger = ::Logger.new(STDOUT)
2
+ $stdout.sync = true
3
+ Logger = ::Logger.new($stdout)
4
4
  end
@@ -4,7 +4,7 @@ module Fakeit
4
4
  def array_example(options)
5
5
  example_options = add_depth(options)
6
6
  if example_options[:use_static][type: 'array', property: example_options[:property]]
7
- generate_array_example(example_options, -> { min_array })
7
+ generate_array_example(example_options, -> { non_empty_size })
8
8
  else
9
9
  generate_array_example(example_options, -> { random_array_size(example_options) })
10
10
  end
@@ -18,17 +18,17 @@ module Fakeit
18
18
  end
19
19
 
20
20
  def random_array_size(example_options)
21
- uniqueItems ? min_array : Faker::Number.between(from: min_array, to: max_array(example_options[:depth]))
21
+ uniqueItems ? non_empty_size : Faker::Number.between(from: min_array, to: max_array(example_options[:depth]))
22
22
  end
23
23
 
24
24
  def generate_items(size, retries, example_options, result)
25
- loop do
25
+ while result.size < size
26
26
  item = items.to_example(example_options)
27
27
 
28
28
  if need_retry?(item, result, retries)
29
29
  retries -= 1
30
- elsif (result << item).size >= size
31
- break
30
+ else
31
+ result << item
32
32
  end
33
33
  end
34
34
  end
@@ -41,6 +41,10 @@ module Fakeit
41
41
  uniqueItems && result.include?(item) && retries.positive?
42
42
  end
43
43
 
44
+ def non_empty_size
45
+ [min_array, 1].max
46
+ end
47
+
44
48
  def min_array
45
49
  minItems || 1
46
50
  end
@@ -27,6 +27,8 @@ module Fakeit
27
27
  }.freeze
28
28
 
29
29
  def string_example(example_options)
30
+ @string_pattern ||= Regexp.new(pattern) if pattern
31
+
30
32
  if example_options[:use_static][type: 'string', property: example_options[:property]]
31
33
  static_string_example
32
34
  else
@@ -39,7 +41,7 @@ module Fakeit
39
41
  def static_string_example
40
42
  fixed_faker do
41
43
  if enum then enum.to_a.first
42
- elsif pattern then Faker::Base.regexify(pattern)
44
+ elsif pattern then static_string_pattern
43
45
  elsif format then static_string_format
44
46
  elsif length_constraint then static_string_with_length
45
47
  else 'string'
@@ -56,7 +58,7 @@ module Fakeit
56
58
 
57
59
  def random_string_example
58
60
  if enum then enum.to_a.sample
59
- elsif pattern then Faker::Base.regexify(pattern)
61
+ elsif pattern then random_string_pattern
60
62
  elsif format then random_string_format
61
63
  elsif length_constraint then string_with_length
62
64
  else Faker::Book.title
@@ -71,6 +73,12 @@ module Fakeit
71
73
  (STATIC_FORMAT_HANDLERS[format] || method(:unknown_format))[]
72
74
  end
73
75
 
76
+ def static_string_pattern
77
+ @static_string_pattern ||= @string_pattern.examples(
78
+ max_repeater_variance: 1, max_group_results: 1, max_results_limit: 1
79
+ ).first
80
+ end
81
+
74
82
  def length_constraint
75
83
  minLength || maxLength
76
84
  end
@@ -91,6 +99,10 @@ module Fakeit
91
99
  (RANDOM_FORMAT_HANDLERS[format] || method(:unknown_format))[]
92
100
  end
93
101
 
102
+ def random_string_pattern
103
+ @random_string_pattern ||= @string_pattern.random_example(max_repeater_variance: 1)
104
+ end
105
+
94
106
  def unknown_format
95
107
  Fakeit::Logger.info("Unknown string format: #{format}")
96
108
  'Unknown string format'
@@ -5,13 +5,10 @@ module Fakeit
5
5
  @operation = operation
6
6
  end
7
7
 
8
- def validate(body: '', params: {}, headers: {})
8
+ def validate(body: {}, params: {}, headers: {})
9
9
  options = OpenAPIParser::SchemaValidator::Options.new(coerce_value: true)
10
10
 
11
- if request_content_type
12
- body_data = parse(body)
13
- @operation.validate_request_body(request_content_type, body_data)
14
- end
11
+ validate_body(body) unless request_content_types.empty?
15
12
  @operation.validate_path_params(options)
16
13
  @operation.validate_request_parameter(params, headers, options)
17
14
  rescue StandardError => e
@@ -20,14 +17,21 @@ module Fakeit
20
17
 
21
18
  private
22
19
 
23
- def parse(body)
24
- JSON.parse(body)
25
- rescue StandardError
26
- raise ValidationError, 'Invalid json payload'
20
+ def validate_body(body)
21
+ if request_content_types.include?(body[:media_type])
22
+ @operation.validate_request_body(body[:media_type], body[:data]) if can_validate?(body[:media_type])
23
+ else
24
+ raise ValidationError, 'Invalid request content type' if body[:media_type]
25
+ raise ValidationError, 'Request body is required' if request_body.required
26
+ end
27
+ end
28
+
29
+ def can_validate?(media_type)
30
+ media_type =~ %r{^application/.*json} || media_type == 'multipart/form-data'
27
31
  end
28
32
 
29
- def request_content_type
30
- request_body&.content&.find { |k, _| k =~ %r{^application/.*json} }&.first
33
+ def request_content_types
34
+ request_body&.content&.keys.to_a
31
35
  end
32
36
 
33
37
  def request_body
@@ -1,3 +1,3 @@
1
1
  module Fakeit
2
- VERSION = '0.5.2'.freeze
2
+ VERSION = '0.6.3'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fakeit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.6.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Feng
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-03 00:00:00.000000000 Z
11
+ date: 2020-09-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -112,30 +112,30 @@ dependencies:
112
112
  name: faker
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - "~>"
115
+ - - '='
116
116
  - !ruby/object:Gem::Version
117
- version: '2.2'
117
+ version: 2.13.0
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - "~>"
122
+ - - '='
123
123
  - !ruby/object:Gem::Version
124
- version: '2.2'
124
+ version: 2.13.0
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: openapi_parser
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - '='
130
130
  - !ruby/object:Gem::Version
131
- version: 0.8.0
131
+ version: 0.12.1
132
132
  type: :runtime
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - '='
137
137
  - !ruby/object:Gem::Version
138
- version: 0.8.0
138
+ version: 0.12.1
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: rack
141
141
  requirement: !ruby/object:Gem::Requirement
@@ -178,20 +178,34 @@ dependencies:
178
178
  - - "~>"
179
179
  - !ruby/object:Gem::Version
180
180
  version: '3.0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: regexp-examples
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - '='
186
+ - !ruby/object:Gem::Version
187
+ version: 1.5.1
188
+ type: :runtime
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - '='
193
+ - !ruby/object:Gem::Version
194
+ version: 1.5.1
181
195
  - !ruby/object:Gem::Dependency
182
196
  name: slop
183
197
  requirement: !ruby/object:Gem::Requirement
184
198
  requirements:
185
199
  - - "~>"
186
200
  - !ruby/object:Gem::Version
187
- version: '4.6'
201
+ version: '4.8'
188
202
  type: :runtime
189
203
  prerelease: false
190
204
  version_requirements: !ruby/object:Gem::Requirement
191
205
  requirements:
192
206
  - - "~>"
193
207
  - !ruby/object:Gem::Version
194
- version: '4.6'
208
+ version: '4.8'
195
209
  description: Create mock server from Openapi specification
196
210
  email:
197
211
  - realfengjia@foxmail.com
@@ -215,8 +229,8 @@ files:
215
229
  - fakeit.gemspec
216
230
  - lib/fakeit.rb
217
231
  - lib/fakeit/app/app.rb
232
+ - lib/fakeit/app/body_parser.rb
218
233
  - lib/fakeit/app/options.rb
219
- - lib/fakeit/core_extensions/findable.rb
220
234
  - lib/fakeit/core_extensions/schema.rb
221
235
  - lib/fakeit/logger.rb
222
236
  - lib/fakeit/middleware/recorder.rb
@@ -1,12 +0,0 @@
1
- module OpenAPIParser
2
- module Findable
3
- def purge_object_cache
4
- return if @purged
5
-
6
- @find_object_cache = {}
7
- @purged = true
8
-
9
- _openapi_all_child_objects.values.each(&:purge_object_cache)
10
- end
11
- end
12
- end