fakeit 0.6.0 → 0.7.1

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: '08e498097efdfb3a803d5fcafc2f755b37f74ade0b0d409ba9ea36cd0ffbc0fd'
4
- data.tar.gz: 77abcf6e9aa8db912d6b6a158a2cc8a95bbced90311617692e1f67f99e1d7249
3
+ metadata.gz: 93f26471f33c1f3a90dc3f473be8bdf790b14e8f737102b48d743c2fe95f6753
4
+ data.tar.gz: 17bb12387546a8e9239d2e219b19e84ec7e2736c6de831dfe9e6618038f9517e
5
5
  SHA512:
6
- metadata.gz: cce0c415a9e2fb40b9b55178dd9b85b8b8f643453ab3e3d4a2203269af0ca7650adca35b464c30f7e82c3b29e8f2319ff1a8543ee8f3d0f793dfa28945f038f5
7
- data.tar.gz: ac9ca06debd2181ee4332edbd30e7a3413f1cf4caeec7981340c6189258615411928364836601b8772be3d8efa87dd72e69e18870b8bd1e0c5dbcf3eb5ee821c
6
+ metadata.gz: fd1c8a33d1b58047aec06abce511450ca57044d0928af3e4ed5c6b5a55ce54c2d299d3a9ed9fde1e83315129a0c37aafc1f5783cd843b8c9d1705327c0a0557c
7
+ data.tar.gz: 6d9f737bc7b52fd7f497efeb20a88958e9f865b9466213b68f439f6a41a52ec07df56b2ebb09fe536971ab0196de62ebc16ae6b151037a5fe73e1ca5ab985d87
data/.rubocop.yml CHANGED
@@ -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,17 +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
29
-
30
- Lint/RaiseException:
31
- Enabled: true
32
-
33
- Lint/StructNewOverride:
34
- Enabled: true
data/CHANGELOG.md ADDED
@@ -0,0 +1,160 @@
1
+ # Changelog
2
+
3
+ ## [v0.7.0](https://github.com/JustinFeng/fakeit/tree/v0.7.0) (2020-10-22)
4
+
5
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.6.3...v0.7.0)
6
+
7
+ **Implemented enhancements:**
8
+
9
+ - Supported change mock server behaviour on the fly
10
+ - Allowed to redirect console log to a file
11
+
12
+ ## [v0.6.3](https://github.com/JustinFeng/fakeit/tree/v0.6.3) (2020-09-11)
13
+
14
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.6.2...v0.6.3)
15
+
16
+ **Implemented enhancements:**
17
+
18
+ - Enhanced regex example generation
19
+
20
+ ## [v0.6.2](https://github.com/JustinFeng/fakeit/tree/v0.6.2) (2020-07-12)
21
+
22
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.6.1...v0.6.2)
23
+
24
+ ## [v0.6.1](https://github.com/JustinFeng/fakeit/tree/v0.6.1) (2020-05-02)
25
+
26
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.6.0...v0.6.1)
27
+
28
+ ## [v0.6.0](https://github.com/JustinFeng/fakeit/tree/v0.6.0) (2020-05-02)
29
+
30
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.5.3...v0.6.0)
31
+
32
+ **Implemented enhancements:**
33
+
34
+ - Added support for multipart/form-data validation
35
+
36
+ **Fixed bugs:**
37
+
38
+ - Multipart request contain special character will respond 500 [\#16](https://github.com/JustinFeng/fakeit/issues/16)
39
+
40
+ ## [v0.5.3](https://github.com/JustinFeng/fakeit/tree/v0.5.3) (2020-04-05)
41
+
42
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.5.2...v0.5.3)
43
+
44
+ ## [v0.5.2](https://github.com/JustinFeng/fakeit/tree/v0.5.2) (2020-04-03)
45
+
46
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.5.1...v0.5.2)
47
+
48
+ ## [v0.5.1](https://github.com/JustinFeng/fakeit/tree/v0.5.1) (2020-04-03)
49
+
50
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.5.0...v0.5.1)
51
+
52
+ ## [v0.5.0](https://github.com/JustinFeng/fakeit/tree/v0.5.0) (2020-04-03)
53
+
54
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.4.2...v0.5.0)
55
+
56
+ **Merged pull requests:**
57
+
58
+ - Bump rack from 2.0.7 to 2.0.8 [\#18](https://github.com/JustinFeng/fakeit/pull/18) ([dependabot[bot]](https://github.com/apps/dependabot))
59
+
60
+ ## [v0.4.2](https://github.com/JustinFeng/fakeit/tree/v0.4.2) (2019-11-22)
61
+
62
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.4.1...v0.4.2)
63
+
64
+ ## [v0.4.1](https://github.com/JustinFeng/fakeit/tree/v0.4.1) (2019-11-21)
65
+
66
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.4.0...v0.4.1)
67
+
68
+ **Merged pull requests:**
69
+
70
+ - Bump rack-cors from 1.0.3 to 1.0.6 [\#17](https://github.com/JustinFeng/fakeit/pull/17) ([dependabot[bot]](https://github.com/apps/dependabot))
71
+
72
+ ## [v0.4.0](https://github.com/JustinFeng/fakeit/tree/v0.4.0) (2019-10-09)
73
+
74
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.3.1...v0.4.0)
75
+
76
+ **Implemented enhancements:**
77
+
78
+ - Implement support for watching for changes in spec/yaml file. [\#15](https://github.com/JustinFeng/fakeit/issues/15)
79
+
80
+ ## [v0.3.1](https://github.com/JustinFeng/fakeit/tree/v0.3.1) (2019-09-01)
81
+
82
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.3.0...v0.3.1)
83
+
84
+ ## [v0.3.0](https://github.com/JustinFeng/fakeit/tree/v0.3.0) (2019-08-27)
85
+
86
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.2.1...v0.3.0)
87
+
88
+ **Closed issues:**
89
+
90
+ - Missing "motivation" section in readme [\#14](https://github.com/JustinFeng/fakeit/issues/14)
91
+
92
+ ## [v0.2.1](https://github.com/JustinFeng/fakeit/tree/v0.2.1) (2019-08-04)
93
+
94
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.2.0...v0.2.1)
95
+
96
+ **Implemented enhancements:**
97
+
98
+ - Support .yaml files [\#9](https://github.com/JustinFeng/fakeit/issues/9)
99
+
100
+ **Fixed bugs:**
101
+
102
+ - Adjust integer generation bounds [\#12](https://github.com/JustinFeng/fakeit/issues/12)
103
+
104
+ **Closed issues:**
105
+
106
+ - End to End Tests [\#8](https://github.com/JustinFeng/fakeit/issues/8)
107
+
108
+ **Merged pull requests:**
109
+
110
+ - support .yaml files [\#10](https://github.com/JustinFeng/fakeit/pull/10) ([monsterkrampe](https://github.com/monsterkrampe))
111
+
112
+ ## [v0.2.0](https://github.com/JustinFeng/fakeit/tree/v0.2.0) (2019-07-17)
113
+
114
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.1.5...v0.2.0)
115
+
116
+ **Implemented enhancements:**
117
+
118
+ - Generate more array elements with performance considered [\#7](https://github.com/JustinFeng/fakeit/issues/7)
119
+ - Non random response [\#5](https://github.com/JustinFeng/fakeit/issues/5)
120
+
121
+ **Fixed bugs:**
122
+
123
+ - Invalid example for number type with more than 2 decimal places 'multipleOf' [\#6](https://github.com/JustinFeng/fakeit/issues/6)
124
+
125
+ ## [v0.1.5](https://github.com/JustinFeng/fakeit/tree/v0.1.5) (2019-06-28)
126
+
127
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.1.4...v0.1.5)
128
+
129
+ **Implemented enhancements:**
130
+
131
+ - Allow CORS [\#4](https://github.com/JustinFeng/fakeit/pull/4) ([monsterkrampe](https://github.com/monsterkrampe))
132
+
133
+ ## [v0.1.4](https://github.com/JustinFeng/fakeit/tree/v0.1.4) (2019-06-25)
134
+
135
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.1.3...v0.1.4)
136
+
137
+ **Implemented enhancements:**
138
+
139
+ - W, \[2019-06-25T03:00:29.635993 \#1\] WARN -- : Unknown string format: guid [\#2](https://github.com/JustinFeng/fakeit/issues/2)
140
+
141
+ **Fixed bugs:**
142
+
143
+ - Request not completing [\#3](https://github.com/JustinFeng/fakeit/issues/3)
144
+ - Stack level too deep in docker container [\#1](https://github.com/JustinFeng/fakeit/issues/1)
145
+
146
+ ## [v0.1.3](https://github.com/JustinFeng/fakeit/tree/v0.1.3) (2019-06-16)
147
+
148
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.1.2...v0.1.3)
149
+
150
+ ## [v0.1.2](https://github.com/JustinFeng/fakeit/tree/v0.1.2) (2019-06-05)
151
+
152
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.1.1...v0.1.2)
153
+
154
+ ## [v0.1.1](https://github.com/JustinFeng/fakeit/tree/v0.1.1) (2019-05-26)
155
+
156
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/4f94874eaf87300496e9de632cd659a031cb3ce2...v0.1.1)
157
+
158
+
159
+
160
+ \* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
data/Gemfile.lock CHANGED
@@ -1,66 +1,71 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fakeit (0.6.0)
5
- faker (= 2.11.0)
6
- openapi_parser (= 0.8.0)
4
+ fakeit (0.7.1)
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
+ regexp-examples (= 1.5.1)
10
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.11.0)
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.5)
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.1)
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.81.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
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.5)
64
+ simplecov (0.19.0)
60
65
  docile (~> 1.1)
61
66
  simplecov-html (~> 0.11)
62
67
  simplecov-html (0.12.2)
63
- slop (4.8.1)
68
+ slop (4.8.2)
64
69
  unicode-display_width (1.7.0)
65
70
 
66
71
  PLATFORMS
@@ -77,4 +82,4 @@ DEPENDENCIES
77
82
  simplecov (~> 0.18)
78
83
 
79
84
  BUNDLED WITH
80
- 2.1.2
85
+ 2.1.4
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:
@@ -50,13 +48,14 @@ Or use the [docker image](https://hub.docker.com/r/realfengjia/fakeit)
50
48
 
51
49
  $ fakeit --spec <Local file or remote url>
52
50
 
53
- Command line options:
51
+ ### Command line options
54
52
 
55
53
  $ fakeit --help
56
54
  usage:
57
55
  --spec spec file uri (required)
58
56
  -p, --port custom port
59
57
  -q, --quiet mute request and response log
58
+ -l, --log-file redirect log to a file
60
59
  --permissive log validation error as warning instead of denying request
61
60
  --use-example use example provided in spec if exists
62
61
  --static generate static response
@@ -67,6 +66,33 @@ Command line options:
67
66
  -v, --version
68
67
  -h, --help
69
68
 
69
+ ### Configuration endpoint
70
+
71
+ Mock server behaviour can be changed on the fly
72
+
73
+ Retrieve current config:
74
+
75
+ GET /__fakeit_config__
76
+
77
+ Update config:
78
+
79
+ PUT /__fakeit_config__
80
+
81
+ Request and response:
82
+ ```json
83
+ {
84
+ "permissive": false,
85
+ "use_example": true,
86
+ "static": false,
87
+ "static_types": [
88
+ "integer"
89
+ ],
90
+ "static_properties": [
91
+ "id"
92
+ ]
93
+ }
94
+ ```
95
+
70
96
  **Notes:**
71
97
  * See [here](docs/random.md) for Openapi properties supported in random response generation
72
98
  * See [here](docs/static.md) for default value in static response generation
data/bin/fakeit CHANGED
@@ -10,6 +10,7 @@ begin
10
10
  o.string '--spec', 'spec file uri (required)', required: true
11
11
  o.integer '-p', '--port', 'custom port'
12
12
  o.bool '-q', '--quiet', 'mute request and response log'
13
+ o.string '-l', '--log-file', 'redirect log to a file'
13
14
  o.bool '--permissive', 'log validation error as warning instead of denying request'
14
15
  o.bool '--use-example', 'use example provided in spec if exists'
15
16
  o.bool '--static', 'generate static response'
@@ -53,6 +54,9 @@ options = Fakeit::App::Options.new(
53
54
  )
54
55
  app = Fakeit.build(opts[:spec], options)
55
56
 
57
+ $stderr.reopen(File.new(opts[:log_file], File::WRONLY | File::TRUNC | File::CREAT)) if opts[:log_file]
58
+ $stderr.sync = true
59
+
56
60
  app.use Rack::Cors do
57
61
  allow do
58
62
  origins '*'
data/docs/random.md CHANGED
@@ -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| |
data/docs/static.md CHANGED
@@ -8,7 +8,7 @@ Static value generation rule
8
8
  | |anyOf|same as allOf|
9
9
  |boolean|N/A|`true`|
10
10
  |array|N/A|size is `1`|
11
- | |minItems|size is minItems|
11
+ | |minItems|size is max(minItems,1)|
12
12
  |string|N/A|`string`|
13
13
  | |enum|first item|
14
14
  | |pattern|Generated but always the same|
data/fakeit.gemspec CHANGED
@@ -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.11.0'
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 'regexp-examples', '1.5.1'
40
41
  spec.add_dependency 'slop', '~> 4.8'
41
42
  end
data/lib/fakeit.rb CHANGED
@@ -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'
@@ -14,7 +15,7 @@ module Fakeit
14
15
  class << self
15
16
  def build(spec_file, options)
16
17
  Rack::Builder.new do
17
- run App.create(spec_file, options)
18
+ run App::AppBuilder.new(spec_file, options).build
18
19
  end
19
20
  end
20
21
  end
@@ -0,0 +1,23 @@
1
+ module Fakeit
2
+ module App
3
+ class AppBuilder
4
+ def initialize(spec_file, options)
5
+ @config_route = Routes::ConfigRoute.new(options)
6
+ @openapi_route = Routes::OpenapiRoute.new(spec_file)
7
+ end
8
+
9
+ def build
10
+ proc do |env|
11
+ request = Rack::Request.new(env)
12
+
13
+ case request.path_info
14
+ when '/__fakeit_config__'
15
+ @config_route.call(request)
16
+ else
17
+ @openapi_route.call(request, @config_route.options)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,32 @@
1
+ module Fakeit
2
+ module App
3
+ module Helpers
4
+ class BodyParser
5
+ class << self
6
+ def parse(request)
7
+ case request.media_type
8
+ when %r{^application/.*json}
9
+ { media_type: request.media_type, data: parse_json(request.body.read) }
10
+ when 'multipart/form-data'
11
+ { media_type: request.media_type, data: parse_form_data(request.params) }
12
+ else
13
+ { media_type: request.media_type, data: request.body.read }
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def parse_json(body)
20
+ body.empty? ? {} : JSON.parse(body)
21
+ rescue StandardError
22
+ raise Fakeit::Validation::ValidationError, 'Invalid json payload'
23
+ end
24
+
25
+ def parse_form_data(params)
26
+ params.transform_values { |v| v.class == Hash && v[:tempfile] ? v[:tempfile].read : v }
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,29 @@
1
+ module Fakeit
2
+ module App
3
+ module Helpers
4
+ class ResponseBuilder
5
+ class << self
6
+ def error(code, err)
7
+ [code, { 'Content-Type' => 'application/json' }, [{ message: err.message }.to_json]]
8
+ end
9
+
10
+ def not_found
11
+ [404, {}, ['Not Found']]
12
+ end
13
+
14
+ def method_not_allowed
15
+ [405, {}, ['Method Not Allowed']]
16
+ end
17
+
18
+ def unsupported_media_type
19
+ [415, {}, ['Unsupported Media Type']]
20
+ end
21
+
22
+ def ok(body)
23
+ [200, { 'Content-Type' => 'application/json' }, [body.to_json]]
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -14,6 +14,16 @@ module Fakeit
14
14
  def use_static?(type: nil, property: nil)
15
15
  @static || @static_types.include?(type) || @static_properties.include?(property)
16
16
  end
17
+
18
+ def to_hash
19
+ {
20
+ permissive: @permissive,
21
+ use_example: @use_example,
22
+ static: @static,
23
+ static_types: @static_types,
24
+ static_properties: @static_properties
25
+ }
26
+ end
17
27
  end
18
28
  end
19
29
  end
@@ -0,0 +1,38 @@
1
+ module Fakeit
2
+ module App
3
+ module Routes
4
+ class ConfigRoute
5
+ attr_reader :options
6
+
7
+ def initialize(options)
8
+ @options = options
9
+ end
10
+
11
+ def call(request)
12
+ case [request.request_method, request.media_type]
13
+ in ['GET', _]
14
+ Fakeit::App::Helpers::ResponseBuilder.ok(@options.to_hash)
15
+ in ['PUT', 'application/json']
16
+ update(request)
17
+ in ['PUT', _]
18
+ Fakeit::App::Helpers::ResponseBuilder.unsupported_media_type
19
+ else
20
+ Fakeit::App::Helpers::ResponseBuilder.method_not_allowed
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def update(request)
27
+ body = Fakeit::App::Helpers::BodyParser.parse(request)[:data]
28
+ @options = Fakeit::App::Options.new(**body.transform_keys(&:to_sym))
29
+
30
+ Fakeit::App::Helpers::ResponseBuilder.ok(@options.to_hash)
31
+ rescue ArgumentError => e
32
+ Logger.warn(Rainbow(e.message).red)
33
+ Fakeit::App::Helpers::ResponseBuilder.error(422, e)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,56 @@
1
+ module Fakeit
2
+ module App
3
+ module Routes
4
+ class OpenapiRoute
5
+ def initialize(spec_file)
6
+ @specification = Fakeit::Openapi::Specification.new(spec_file)
7
+ end
8
+
9
+ def call(request, options)
10
+ @specification
11
+ .operation(request.request_method.downcase.to_sym, request.path_info, options)
12
+ .then { _1 ? handle(_1, request, options) : Fakeit::App::Helpers::ResponseBuilder.not_found }
13
+ end
14
+
15
+ private
16
+
17
+ def handle(operation, request, options)
18
+ validate(operation, request)
19
+ response(operation)
20
+ rescue Fakeit::Validation::ValidationError => e
21
+ Logger.warn(Rainbow(e.message).red)
22
+ options.permissive ? response(operation) : Fakeit::App::Helpers::ResponseBuilder.error(418, e)
23
+ end
24
+
25
+ def response(operation)
26
+ [operation.status, operation.headers, [operation.body]]
27
+ end
28
+
29
+ def validate(operation, request)
30
+ operation.validate(
31
+ body: Helpers::BodyParser.parse(request),
32
+ params: parse_query(request.query_string),
33
+ headers: headers(request)
34
+ )
35
+ end
36
+
37
+ def headers(request)
38
+ request
39
+ .each_header
40
+ .select { |k, _| k.start_with? 'HTTP_' }
41
+ .map { |k, v| [k.sub(/^HTTP_/, '').split('_').map(&:capitalize).join('-'), v] }
42
+ .to_h
43
+ end
44
+
45
+ def parse_query(query_string)
46
+ rack_query = Rack::Utils.parse_nested_query(query_string)
47
+ cgi_query = CGI.parse(query_string)
48
+
49
+ rack_query.merge(cgi_query.slice(*rack_query.keys)) do |_, oldval, newval|
50
+ newval.is_a?(Array) && newval.size > 1 ? newval : oldval
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,11 @@
1
+ require 'fakeit/openapi/schema'
2
+
3
+ module OpenAPIParser
4
+ module Schemas
5
+ class Reference
6
+ def to_example(_)
7
+ raise Fakeit::Openapi::ReferenceError, "Invalid $ref at \"#{ref}\""
8
+ end
9
+ end
10
+ end
11
+ end
data/lib/fakeit/logger.rb CHANGED
@@ -1,4 +1,3 @@
1
1
  module Fakeit
2
- STDOUT.sync = true
3
- Logger = ::Logger.new(STDOUT)
2
+ Logger = ::Logger.new($stderr)
4
3
  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,7 +18,7 @@ module Fakeit
18
18
  end
19
19
 
20
20
  def random_array_size(example_options)
21
- uniqueItems ? unique_array_size : 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)
@@ -41,7 +41,7 @@ module Fakeit
41
41
  uniqueItems && result.include?(item) && retries.positive?
42
42
  end
43
43
 
44
- def unique_array_size
44
+ def non_empty_size
45
45
  [min_array, 1].max
46
46
  end
47
47
 
@@ -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,8 +99,12 @@ 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
- Fakeit::Logger.info("Unknown string format: #{format}")
107
+ Logger.info("Unknown string format: #{format}")
96
108
  'Unknown string format'
97
109
  end
98
110
  end
@@ -0,0 +1,6 @@
1
+ module Fakeit
2
+ module Openapi
3
+ class ReferenceError < StandardError
4
+ end
5
+ end
6
+ end
@@ -25,7 +25,7 @@ module Fakeit
25
25
  @mtime = new_mtime
26
26
  @doc = Fakeit::Openapi.load(@spec_file)
27
27
  rescue StandardError => _e
28
- Fakeit::Logger.warn(Rainbow('Invalid spec file, use previous snapshot instead').red)
28
+ Logger.warn(Rainbow('Invalid spec file, use previous snapshot instead').red)
29
29
  end
30
30
  end
31
31
  end
@@ -1,3 +1,3 @@
1
1
  module Fakeit
2
- VERSION = '0.6.0'.freeze
2
+ VERSION = '0.7.1'.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.6.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Feng
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-02 00:00:00.000000000 Z
11
+ date: 2021-02-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -114,28 +114,28 @@ dependencies:
114
114
  requirements:
115
115
  - - '='
116
116
  - !ruby/object:Gem::Version
117
- version: 2.11.0
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.11.0
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,6 +178,20 @@ 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
@@ -204,6 +218,7 @@ files:
204
218
  - ".gitignore"
205
219
  - ".rspec"
206
220
  - ".rubocop.yml"
221
+ - CHANGELOG.md
207
222
  - Gemfile
208
223
  - Gemfile.lock
209
224
  - LICENSE.txt
@@ -214,11 +229,13 @@ files:
214
229
  - docs/static.md
215
230
  - fakeit.gemspec
216
231
  - lib/fakeit.rb
217
- - lib/fakeit/app/app.rb
218
- - lib/fakeit/app/body_parser.rb
232
+ - lib/fakeit/app/app_builder.rb
233
+ - lib/fakeit/app/helpers/body_parser.rb
234
+ - lib/fakeit/app/helpers/response_builder.rb
219
235
  - lib/fakeit/app/options.rb
220
- - lib/fakeit/core_extensions/findable.rb
221
- - lib/fakeit/core_extensions/path_item_finder.rb
236
+ - lib/fakeit/app/routes/config_route.rb
237
+ - lib/fakeit/app/routes/openapi_route.rb
238
+ - lib/fakeit/core_extensions/reference.rb
222
239
  - lib/fakeit/core_extensions/schema.rb
223
240
  - lib/fakeit/logger.rb
224
241
  - lib/fakeit/middleware/recorder.rb
@@ -230,6 +247,7 @@ files:
230
247
  - lib/fakeit/openapi/example/string_example.rb
231
248
  - lib/fakeit/openapi/loader.rb
232
249
  - lib/fakeit/openapi/operation.rb
250
+ - lib/fakeit/openapi/reference_error.rb
233
251
  - lib/fakeit/openapi/schema.rb
234
252
  - lib/fakeit/openapi/specification.rb
235
253
  - lib/fakeit/validation/validation_error.rb
@@ -239,7 +257,7 @@ homepage: https://github.com/JustinFeng/fakeit
239
257
  licenses:
240
258
  - MIT
241
259
  metadata: {}
242
- post_install_message:
260
+ post_install_message:
243
261
  rdoc_options: []
244
262
  require_paths:
245
263
  - lib
@@ -255,7 +273,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
255
273
  version: '0'
256
274
  requirements: []
257
275
  rubygems_version: 3.1.2
258
- signing_key:
276
+ signing_key:
259
277
  specification_version: 4
260
278
  summary: Create mock server from Openapi specification
261
279
  test_files: []
@@ -1,63 +0,0 @@
1
- module Fakeit
2
- module App
3
- class << self
4
- def create(spec_file, options)
5
- specification = Fakeit::Openapi::Specification.new(spec_file)
6
-
7
- proc do |env|
8
- request = Rack::Request.new(env)
9
- specification
10
- .operation(request.request_method.downcase.to_sym, request.path_info, options)
11
- .then { _1 ? handle(_1, request, options) : not_found }
12
- end
13
- end
14
-
15
- private
16
-
17
- def handle(operation, request, options)
18
- validate(operation, request)
19
- response(operation)
20
- rescue Fakeit::Validation::ValidationError => e
21
- Fakeit::Logger.warn(Rainbow(e.message).red)
22
- options.permissive ? response(operation) : error(e)
23
- end
24
-
25
- def error(err)
26
- [418, { 'Content-Type' => 'application/json' }, [{ message: err.message }.to_json]]
27
- end
28
-
29
- def not_found
30
- [404, {}, ['Not Found']]
31
- end
32
-
33
- def response(operation)
34
- [operation.status, operation.headers, [operation.body]]
35
- end
36
-
37
- def validate(operation, request)
38
- operation.validate(
39
- body: BodyParser.parse(request),
40
- params: parse_query(request.query_string),
41
- headers: headers(request)
42
- )
43
- end
44
-
45
- def headers(request)
46
- request
47
- .each_header
48
- .select { |k, _| k.start_with? 'HTTP_' }
49
- .map { |k, v| [k.sub(/^HTTP_/, '').split('_').map(&:capitalize).join('-'), v] }
50
- .to_h
51
- end
52
-
53
- def parse_query(query_string)
54
- rack_query = Rack::Utils.parse_nested_query(query_string)
55
- cgi_query = CGI.parse(query_string)
56
-
57
- rack_query.merge(cgi_query.slice(*rack_query.keys)) do |_, oldval, newval|
58
- newval.is_a?(Array) && newval.size > 1 ? newval : oldval
59
- end
60
- end
61
- end
62
- end
63
- end
@@ -1,30 +0,0 @@
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
- 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,13 +0,0 @@
1
- # https://github.com/ota42y/openapi_parser/issues/41
2
- module OpenAPIParser
3
- module Findable
4
- def purge_object_cache
5
- return if @purged
6
-
7
- @find_object_cache = {}
8
- @purged = true
9
-
10
- _openapi_all_child_objects.values.each(&:purge_object_cache)
11
- end
12
- end
13
- end
@@ -1,14 +0,0 @@
1
- # https://github.com/ota42y/openapi_parser/issues/75
2
- module OpenAPIParser
3
- class PathItemFinder
4
- private
5
-
6
- def find_path_and_params(http_method, request_path)
7
- return [request_path, {}] if matches_directly?(request_path, http_method)
8
-
9
- matching = matching_paths_with_params(request_path, http_method)
10
-
11
- matching.min_by { |match| match[1].size }
12
- end
13
- end
14
- end