fakeit 0.5.2 → 0.6.3

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 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