fakeit 0.6.3 → 0.9.0

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: 35c58ad2d52ce6f2ba2375738faaed686b7945ce0d3e438d0d5e3e78f7d32d71
4
- data.tar.gz: 4c9a1566b7256b2b5b8fb7772daf1329810644b646f2ac0c939d5a3fd824a8db
3
+ metadata.gz: dbb5973b840c21eddd94a398c62a312bbbf21dba4b06323ca4ab8bf2fd7318f4
4
+ data.tar.gz: 3a2d30ed95aa61b39f68c3ddce26815ee7156f5a620a2fea097bf2d3466d5be6
5
5
  SHA512:
6
- metadata.gz: 0c3b0375ac956484083b108bb3284ccd33adda44e002b310b7e44fdb2ce151f1b62729a095f9caa02d2953d7dd809e4144fa33612756aa3189cee358e279ae18
7
- data.tar.gz: 71e3391f4570e12b3c940476e0657e700088ef72f122ccf6e354e71e43ed47ef3d082e7d7f972fc5b35c3fb111aba38110b00d36725eaaafbaeb18750d6ebc96
6
+ metadata.gz: 35fe9c896913f0a946586ad4945960b01e3b665c1eb101d7265ec67bb1b3e59e91e224b72ef2d330455f770e6546d97d172f7d63a2849a16e3a94053196fbad0
7
+ data.tar.gz: a0425724e4c9fb66f2feda3adc505c752b9b001ac8db6aee75715a20a06478434696bf4b082887b9c8e34470d029fdc7e88d236e32837307aa9ac0339dca34fe
data/.circleci/config.yml CHANGED
@@ -12,7 +12,7 @@ jobs:
12
12
 
13
13
  docker:
14
14
  # specify the version you desire here
15
- - image: circleci/ruby:2.7.0
15
+ - image: circleci/ruby:3.0.0
16
16
 
17
17
  # Specify service dependencies here if necessary
18
18
  # CircleCI maintains a library of pre-built images
data/.rubocop.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  AllCops:
2
- TargetRubyVersion: 2.7
2
+ TargetRubyVersion: 3.0
3
3
  NewCops: enable
4
4
 
5
5
  Style/Documentation:
data/CHANGELOG.md ADDED
@@ -0,0 +1,176 @@
1
+ # Changelog
2
+
3
+ ## [v0.8.0](https://github.com/JustinFeng/fakeit/tree/v0.8.0) (2021-02-27)
4
+
5
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.7.1...v0.8.0)
6
+
7
+ **Implemented enhancements:**
8
+
9
+ - Upgraded to ruby 3.0.0
10
+
11
+ ## [v0.7.1](https://github.com/JustinFeng/fakeit/tree/v0.7.1) (2021-02-07)
12
+
13
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.7.0...v0.7.1)
14
+
15
+ **Fixed bugs:**
16
+
17
+ - ERROR NoMethodError: undefined method `to\_example' for \# [\#20](https://github.com/JustinFeng/fakeit/issues/20)
18
+
19
+ ## [v0.7.0](https://github.com/JustinFeng/fakeit/tree/v0.7.0) (2020-10-22)
20
+
21
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.6.3...v0.7.0)
22
+
23
+ **Implemented enhancements:**
24
+
25
+ - Supported change mock server behaviour on the fly
26
+ - Allowed to redirect console log to a file
27
+
28
+ ## [v0.6.3](https://github.com/JustinFeng/fakeit/tree/v0.6.3) (2020-09-11)
29
+
30
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.6.2...v0.6.3)
31
+
32
+ **Implemented enhancements:**
33
+
34
+ - Enhanced regex example generation
35
+
36
+ ## [v0.6.2](https://github.com/JustinFeng/fakeit/tree/v0.6.2) (2020-07-12)
37
+
38
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.6.1...v0.6.2)
39
+
40
+ ## [v0.6.1](https://github.com/JustinFeng/fakeit/tree/v0.6.1) (2020-05-02)
41
+
42
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.6.0...v0.6.1)
43
+
44
+ ## [v0.6.0](https://github.com/JustinFeng/fakeit/tree/v0.6.0) (2020-05-02)
45
+
46
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.5.3...v0.6.0)
47
+
48
+ **Implemented enhancements:**
49
+
50
+ - Added support for multipart/form-data validation
51
+
52
+ **Fixed bugs:**
53
+
54
+ - Multipart request contain special character will respond 500 [\#16](https://github.com/JustinFeng/fakeit/issues/16)
55
+
56
+ ## [v0.5.3](https://github.com/JustinFeng/fakeit/tree/v0.5.3) (2020-04-05)
57
+
58
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.5.2...v0.5.3)
59
+
60
+ ## [v0.5.2](https://github.com/JustinFeng/fakeit/tree/v0.5.2) (2020-04-03)
61
+
62
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.5.1...v0.5.2)
63
+
64
+ ## [v0.5.1](https://github.com/JustinFeng/fakeit/tree/v0.5.1) (2020-04-03)
65
+
66
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.5.0...v0.5.1)
67
+
68
+ ## [v0.5.0](https://github.com/JustinFeng/fakeit/tree/v0.5.0) (2020-04-03)
69
+
70
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.4.2...v0.5.0)
71
+
72
+ **Merged pull requests:**
73
+
74
+ - 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))
75
+
76
+ ## [v0.4.2](https://github.com/JustinFeng/fakeit/tree/v0.4.2) (2019-11-22)
77
+
78
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.4.1...v0.4.2)
79
+
80
+ ## [v0.4.1](https://github.com/JustinFeng/fakeit/tree/v0.4.1) (2019-11-21)
81
+
82
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.4.0...v0.4.1)
83
+
84
+ **Merged pull requests:**
85
+
86
+ - 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))
87
+
88
+ ## [v0.4.0](https://github.com/JustinFeng/fakeit/tree/v0.4.0) (2019-10-09)
89
+
90
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.3.1...v0.4.0)
91
+
92
+ **Implemented enhancements:**
93
+
94
+ - Implement support for watching for changes in spec/yaml file. [\#15](https://github.com/JustinFeng/fakeit/issues/15)
95
+
96
+ ## [v0.3.1](https://github.com/JustinFeng/fakeit/tree/v0.3.1) (2019-09-01)
97
+
98
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.3.0...v0.3.1)
99
+
100
+ ## [v0.3.0](https://github.com/JustinFeng/fakeit/tree/v0.3.0) (2019-08-27)
101
+
102
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.2.1...v0.3.0)
103
+
104
+ **Closed issues:**
105
+
106
+ - Missing "motivation" section in readme [\#14](https://github.com/JustinFeng/fakeit/issues/14)
107
+
108
+ ## [v0.2.1](https://github.com/JustinFeng/fakeit/tree/v0.2.1) (2019-08-04)
109
+
110
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.2.0...v0.2.1)
111
+
112
+ **Implemented enhancements:**
113
+
114
+ - Support .yaml files [\#9](https://github.com/JustinFeng/fakeit/issues/9)
115
+
116
+ **Fixed bugs:**
117
+
118
+ - Adjust integer generation bounds [\#12](https://github.com/JustinFeng/fakeit/issues/12)
119
+
120
+ **Closed issues:**
121
+
122
+ - End to End Tests [\#8](https://github.com/JustinFeng/fakeit/issues/8)
123
+
124
+ **Merged pull requests:**
125
+
126
+ - support .yaml files [\#10](https://github.com/JustinFeng/fakeit/pull/10) ([monsterkrampe](https://github.com/monsterkrampe))
127
+
128
+ ## [v0.2.0](https://github.com/JustinFeng/fakeit/tree/v0.2.0) (2019-07-17)
129
+
130
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.1.5...v0.2.0)
131
+
132
+ **Implemented enhancements:**
133
+
134
+ - Generate more array elements with performance considered [\#7](https://github.com/JustinFeng/fakeit/issues/7)
135
+ - Non random response [\#5](https://github.com/JustinFeng/fakeit/issues/5)
136
+
137
+ **Fixed bugs:**
138
+
139
+ - Invalid example for number type with more than 2 decimal places 'multipleOf' [\#6](https://github.com/JustinFeng/fakeit/issues/6)
140
+
141
+ ## [v0.1.5](https://github.com/JustinFeng/fakeit/tree/v0.1.5) (2019-06-28)
142
+
143
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.1.4...v0.1.5)
144
+
145
+ **Implemented enhancements:**
146
+
147
+ - Allow CORS [\#4](https://github.com/JustinFeng/fakeit/pull/4) ([monsterkrampe](https://github.com/monsterkrampe))
148
+
149
+ ## [v0.1.4](https://github.com/JustinFeng/fakeit/tree/v0.1.4) (2019-06-25)
150
+
151
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.1.3...v0.1.4)
152
+
153
+ **Implemented enhancements:**
154
+
155
+ - W, \[2019-06-25T03:00:29.635993 \#1\] WARN -- : Unknown string format: guid [\#2](https://github.com/JustinFeng/fakeit/issues/2)
156
+
157
+ **Fixed bugs:**
158
+
159
+ - Request not completing [\#3](https://github.com/JustinFeng/fakeit/issues/3)
160
+ - Stack level too deep in docker container [\#1](https://github.com/JustinFeng/fakeit/issues/1)
161
+
162
+ ## [v0.1.3](https://github.com/JustinFeng/fakeit/tree/v0.1.3) (2019-06-16)
163
+
164
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.1.2...v0.1.3)
165
+
166
+ ## [v0.1.2](https://github.com/JustinFeng/fakeit/tree/v0.1.2) (2019-06-05)
167
+
168
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/v0.1.1...v0.1.2)
169
+
170
+ ## [v0.1.1](https://github.com/JustinFeng/fakeit/tree/v0.1.1) (2019-05-26)
171
+
172
+ [Full Changelog](https://github.com/JustinFeng/fakeit/compare/4f94874eaf87300496e9de632cd659a031cb3ce2...v0.1.1)
173
+
174
+
175
+
176
+ \* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fakeit (0.6.3)
4
+ fakeit (0.9.0)
5
5
  faker (= 2.13.0)
6
6
  openapi_parser (= 0.12.1)
7
7
  rack (~> 2.0)
@@ -9,22 +9,23 @@ PATH
9
9
  rainbow (~> 3.0)
10
10
  regexp-examples (= 1.5.1)
11
11
  slop (~> 4.8)
12
+ webrick (~> 1.7)
12
13
 
13
14
  GEM
14
15
  remote: https://rubygems.org/
15
16
  specs:
16
- ast (2.4.1)
17
+ ast (2.4.2)
17
18
  byebug (11.1.3)
18
- concurrent-ruby (1.1.7)
19
+ concurrent-ruby (1.1.8)
19
20
  diff-lcs (1.4.4)
20
- docile (1.3.2)
21
+ docile (1.3.5)
21
22
  faker (2.13.0)
22
23
  i18n (>= 1.6, < 2)
23
- i18n (1.8.5)
24
+ i18n (1.8.9)
24
25
  concurrent-ruby (~> 1.0)
25
26
  openapi_parser (0.12.1)
26
- parallel (1.19.2)
27
- parser (2.7.1.4)
27
+ parallel (1.20.1)
28
+ parser (3.0.0.0)
28
29
  ast (~> 2.4.1)
29
30
  rack (2.2.3)
30
31
  rack-cors (1.1.1)
@@ -32,41 +33,46 @@ GEM
32
33
  rack-test (1.1.0)
33
34
  rack (>= 1.0, < 3)
34
35
  rainbow (3.0.0)
35
- rake (12.3.3)
36
+ rake (13.0.3)
36
37
  regexp-examples (1.5.1)
37
- regexp_parser (1.7.1)
38
+ regexp_parser (2.1.1)
38
39
  rexml (3.2.4)
39
- rspec (3.9.0)
40
- rspec-core (~> 3.9.0)
41
- rspec-expectations (~> 3.9.0)
42
- rspec-mocks (~> 3.9.0)
43
- rspec-core (3.9.2)
44
- rspec-support (~> 3.9.3)
45
- rspec-expectations (3.9.2)
40
+ rspec (3.10.0)
41
+ rspec-core (~> 3.10.0)
42
+ rspec-expectations (~> 3.10.0)
43
+ rspec-mocks (~> 3.10.0)
44
+ rspec-core (3.10.1)
45
+ rspec-support (~> 3.10.0)
46
+ rspec-expectations (3.10.1)
46
47
  diff-lcs (>= 1.2.0, < 2.0)
47
- rspec-support (~> 3.9.0)
48
- rspec-mocks (3.9.1)
48
+ rspec-support (~> 3.10.0)
49
+ rspec-mocks (3.10.2)
49
50
  diff-lcs (>= 1.2.0, < 2.0)
50
- rspec-support (~> 3.9.0)
51
- rspec-support (3.9.3)
52
- rubocop (0.90.0)
51
+ rspec-support (~> 3.10.0)
52
+ rspec-support (3.10.2)
53
+ rubocop (1.10.0)
53
54
  parallel (~> 1.10)
54
- parser (>= 2.7.1.1)
55
+ parser (>= 3.0.0.0)
55
56
  rainbow (>= 2.2.2, < 4.0)
56
- regexp_parser (>= 1.7)
57
+ regexp_parser (>= 1.8, < 3.0)
57
58
  rexml
58
- rubocop-ast (>= 0.3.0, < 1.0)
59
+ rubocop-ast (>= 1.2.0, < 2.0)
59
60
  ruby-progressbar (~> 1.7)
60
- unicode-display_width (>= 1.4.0, < 2.0)
61
- rubocop-ast (0.3.0)
62
- parser (>= 2.7.1.4)
63
- ruby-progressbar (1.10.1)
64
- simplecov (0.19.0)
61
+ unicode-display_width (>= 1.4.0, < 3.0)
62
+ rubocop-ast (1.4.1)
63
+ parser (>= 2.7.1.5)
64
+ rubocop-rake (0.5.1)
65
+ rubocop
66
+ ruby-progressbar (1.11.0)
67
+ simplecov (0.21.2)
65
68
  docile (~> 1.1)
66
69
  simplecov-html (~> 0.11)
67
- simplecov-html (0.12.2)
70
+ simplecov_json_formatter (~> 0.1)
71
+ simplecov-html (0.12.3)
72
+ simplecov_json_formatter (0.1.2)
68
73
  slop (4.8.2)
69
- unicode-display_width (1.7.0)
74
+ unicode-display_width (2.0.0)
75
+ webrick (1.7.0)
70
76
 
71
77
  PLATFORMS
72
78
  ruby
@@ -76,10 +82,11 @@ DEPENDENCIES
76
82
  byebug (~> 11.0)
77
83
  fakeit!
78
84
  rack-test (~> 1.1)
79
- rake (~> 12.0)
85
+ rake (~> 13.0)
80
86
  rspec (~> 3.0)
81
- rubocop (~> 0.80)
87
+ rubocop (~> 1.10)
88
+ rubocop-rake (~> 0.5)
82
89
  simplecov (~> 0.18)
83
90
 
84
91
  BUNDLED WITH
85
- 2.1.2
92
+ 2.2.11
data/README.md CHANGED
@@ -35,6 +35,7 @@ After tried several existing options, we cannot find a best solution to meet all
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
+ * [Experimental] Support plain text and binary response, e.g. `application/pdf`
38
39
 
39
40
  ## Installation
40
41
 
@@ -48,13 +49,14 @@ Or use the [docker image](https://hub.docker.com/r/realfengjia/fakeit)
48
49
 
49
50
  $ fakeit --spec <Local file or remote url>
50
51
 
51
- Command line options:
52
+ ### Command line options
52
53
 
53
54
  $ fakeit --help
54
55
  usage:
55
56
  --spec spec file uri (required)
56
57
  -p, --port custom port
57
58
  -q, --quiet mute request and response log
59
+ -l, --log-file redirect log to a file
58
60
  --permissive log validation error as warning instead of denying request
59
61
  --use-example use example provided in spec if exists
60
62
  --static generate static response
@@ -71,6 +73,33 @@ Command line options:
71
73
  * Regarding `--use-example` mode, property without example specified will still be randomly or statically generated
72
74
  * Random response generation can not handle recursive schema reference. If you do need it in your spec file, please provide `example` property for the recursive part of schema and specify `--use-example` option.
73
75
 
76
+ ### Configuration endpoint
77
+
78
+ Mock server behaviour can be changed on the fly
79
+
80
+ Retrieve current config:
81
+
82
+ GET /__fakeit_config__
83
+
84
+ Update config:
85
+
86
+ PUT /__fakeit_config__
87
+
88
+ Request and response:
89
+ ```json
90
+ {
91
+ "permissive": false,
92
+ "use_example": true,
93
+ "static": false,
94
+ "static_types": [
95
+ "integer"
96
+ ],
97
+ "static_properties": [
98
+ "id"
99
+ ]
100
+ }
101
+ ```
102
+
74
103
  ## Development
75
104
 
76
105
  After checking out the repo, run `bundle install` to install dependencies. Then, run `rake` to run the tests.
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/fakeit.gemspec CHANGED
@@ -22,14 +22,15 @@ Gem::Specification.new do |spec|
22
22
  spec.executables = 'fakeit'
23
23
  spec.require_paths = ['lib']
24
24
 
25
- spec.required_ruby_version = '>= 2.7.0'
25
+ spec.required_ruby_version = '>= 3.0.0'
26
26
 
27
27
  spec.add_development_dependency 'bundler', '~> 2.0'
28
28
  spec.add_development_dependency 'byebug', '~> 11.0'
29
29
  spec.add_development_dependency 'rack-test', '~> 1.1'
30
- spec.add_development_dependency 'rake', '~> 12.0'
30
+ spec.add_development_dependency 'rake', '~> 13.0'
31
31
  spec.add_development_dependency 'rspec', '~> 3.0'
32
- spec.add_development_dependency 'rubocop', '~> 0.80'
32
+ spec.add_development_dependency 'rubocop', '~> 1.10'
33
+ spec.add_development_dependency 'rubocop-rake', '~> 0.5'
33
34
  spec.add_development_dependency 'simplecov', '~> 0.18'
34
35
 
35
36
  spec.add_dependency 'faker', '2.13.0'
@@ -39,4 +40,5 @@ Gem::Specification.new do |spec|
39
40
  spec.add_dependency 'rainbow', '~> 3.0'
40
41
  spec.add_dependency 'regexp-examples', '1.5.1'
41
42
  spec.add_dependency 'slop', '~> 4.8'
43
+ spec.add_dependency 'webrick', '~> 1.7'
42
44
  end
data/lib/fakeit.rb CHANGED
@@ -9,13 +9,13 @@ require 'rack'
9
9
  require 'logger'
10
10
  require 'rainbow'
11
11
 
12
- Dir.glob(File.join(File.dirname(__FILE__), 'fakeit', '**/*.rb')).sort.each { require _1 }
12
+ Dir.glob(File.join(File.dirname(__FILE__), 'fakeit', '**/*.rb')).each { require _1 }
13
13
 
14
14
  module Fakeit
15
15
  class << self
16
16
  def build(spec_file, options)
17
17
  Rack::Builder.new do
18
- run App.create(spec_file, options)
18
+ run App::AppBuilder.new(spec_file, options).build
19
19
  end
20
20
  end
21
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.instance_of?(Hash) && v[:tempfile] ? v[:tempfile].read : v }
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,19 @@
1
+ module Fakeit
2
+ module App
3
+ module Helpers
4
+ class ResponseBuilder
5
+ class << self
6
+ def error(code, err) = [code, { 'Content-Type' => 'application/json' }, [{ message: err.message }.to_json]]
7
+
8
+ def not_found = [404, {}, ['Not Found']]
9
+
10
+ def method_not_allowed = [405, {}, ['Method Not Allowed']]
11
+
12
+ def unsupported_media_type = [415, {}, ['Unsupported Media Type']]
13
+
14
+ def ok(body) = [200, { 'Content-Type' => 'application/json' }, [body.to_json]]
15
+ end
16
+ end
17
+ end
18
+ end
19
+ 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,36 @@
1
+ module Fakeit
2
+ module App
3
+ module Routes
4
+ class ConfigRoute
5
+ attr_reader :options
6
+
7
+ def initialize(options) = @options = options
8
+
9
+ def call(request)
10
+ case [request.request_method, request.media_type]
11
+ in ['GET', _]
12
+ Fakeit::App::Helpers::ResponseBuilder.ok(@options.to_hash)
13
+ in ['PUT', 'application/json']
14
+ update(request)
15
+ in ['PUT', _]
16
+ Fakeit::App::Helpers::ResponseBuilder.unsupported_media_type
17
+ else
18
+ Fakeit::App::Helpers::ResponseBuilder.method_not_allowed
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def update(request)
25
+ body = Fakeit::App::Helpers::BodyParser.parse(request)[:data]
26
+ @options = Fakeit::App::Options.new(**body.transform_keys(&:to_sym))
27
+
28
+ Fakeit::App::Helpers::ResponseBuilder.ok(@options.to_hash)
29
+ rescue ArgumentError => e
30
+ Logger.warn(Rainbow(e.message).red)
31
+ Fakeit::App::Helpers::ResponseBuilder.error(422, e)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,52 @@
1
+ module Fakeit
2
+ module App
3
+ module Routes
4
+ class OpenapiRoute
5
+ def initialize(spec_file) = @specification = Fakeit::Openapi::Specification.new(spec_file)
6
+
7
+ def call(request, options)
8
+ @specification
9
+ .operation(request.request_method.downcase.to_sym, request.path_info, options)
10
+ .then { _1 ? handle(_1, request, options) : Fakeit::App::Helpers::ResponseBuilder.not_found }
11
+ end
12
+
13
+ private
14
+
15
+ def handle(operation, request, options)
16
+ validate(operation, request)
17
+ response(operation)
18
+ rescue Fakeit::Validation::ValidationError => e
19
+ Logger.warn(Rainbow(e.message).red)
20
+ options.permissive ? response(operation) : Fakeit::App::Helpers::ResponseBuilder.error(418, e)
21
+ end
22
+
23
+ def response(operation) = [operation.status, operation.headers, [operation.body]]
24
+
25
+ def validate(operation, request)
26
+ operation.validate(
27
+ body: Helpers::BodyParser.parse(request),
28
+ params: parse_query(request.query_string),
29
+ headers: headers(request)
30
+ )
31
+ end
32
+
33
+ def headers(request)
34
+ request
35
+ .each_header
36
+ .select { |k, _| k.start_with? 'HTTP_' }
37
+ .map { |k, v| [k.sub(/^HTTP_/, '').split('_').map(&:capitalize).join('-'), v] }
38
+ .to_h
39
+ end
40
+
41
+ def parse_query(query_string)
42
+ rack_query = Rack::Utils.parse_nested_query(query_string)
43
+ cgi_query = CGI.parse(query_string)
44
+
45
+ rack_query.merge(cgi_query.slice(*rack_query.keys)) do |_, oldval, newval|
46
+ newval.is_a?(Array) && newval.size > 1 ? newval : oldval
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,9 @@
1
+ require 'fakeit/openapi/schema'
2
+
3
+ module OpenAPIParser
4
+ module Schemas
5
+ class Reference
6
+ def to_example(_) = raise(Fakeit::Openapi::ReferenceError, "Invalid $ref at \"#{ref}\"")
7
+ end
8
+ end
9
+ end
@@ -7,9 +7,7 @@ module OpenAPIParser
7
7
 
8
8
  alias old_type type
9
9
 
10
- def type
11
- old_type || inferred_type
12
- end
10
+ def type = old_type || inferred_type
13
11
 
14
12
  private
15
13
 
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
@@ -1,9 +1,7 @@
1
1
  module Fakeit
2
2
  module Middleware
3
3
  class Recorder
4
- def initialize(app)
5
- @app = app
6
- end
4
+ def initialize(app) = @app = app
7
5
 
8
6
  def call(env)
9
7
  env
@@ -20,9 +18,7 @@ module Fakeit
20
18
  &.tap { |body| body.rewind }
21
19
  end
22
20
 
23
- def log_response(response)
24
- Logger.info("Response body: #{response[2].first}")
25
- end
21
+ def log_response(response) = Logger.info("Response body: #{response[2].first}")
26
22
  end
27
23
  end
28
24
  end
@@ -33,25 +33,15 @@ module Fakeit
33
33
  end
34
34
  end
35
35
 
36
- def add_depth(example_options)
37
- { **example_options, depth: example_options[:depth] + 1 }
38
- end
36
+ def add_depth(example_options) = { **example_options, depth: example_options[:depth] + 1 }
39
37
 
40
- def need_retry?(item, result, retries)
41
- uniqueItems && result.include?(item) && retries.positive?
42
- end
38
+ def need_retry?(item, result, retries) = uniqueItems && result.include?(item) && retries.positive?
43
39
 
44
- def non_empty_size
45
- [min_array, 1].max
46
- end
40
+ def non_empty_size = [min_array, 1].max
47
41
 
48
- def min_array
49
- minItems || 1
50
- end
42
+ def min_array = minItems || 1
51
43
 
52
- def max_array(depth)
53
- maxItems || min_array + (depth > 1 ? 2 : 9)
54
- end
44
+ def max_array(depth) = maxItems || min_array + (depth > 1 ? 2 : 9)
55
45
  end
56
46
  end
57
47
  end
@@ -29,21 +29,13 @@ module Fakeit
29
29
  end
30
30
  end
31
31
 
32
- def int_rand_begin
33
- min_int / int_multiple + int_rand_begin_adjust
34
- end
32
+ def int_rand_begin = min_int / int_multiple + int_rand_begin_adjust
35
33
 
36
- def int_rand_end
37
- max_int / int_multiple
38
- end
34
+ def int_rand_end = max_int / int_multiple
39
35
 
40
- def int_rand_begin_adjust
41
- (min_int % int_multiple).zero? ? 0 : 1
42
- end
36
+ def int_rand_begin_adjust = (min_int % int_multiple).zero? ? 0 : 1
43
37
 
44
- def int_multiple
45
- multipleOf || 1
46
- end
38
+ def int_multiple = multipleOf || 1
47
39
 
48
40
  def min_int
49
41
  if minimum
@@ -14,35 +14,22 @@ module Fakeit
14
14
 
15
15
  private
16
16
 
17
- def static_number_example
18
- (num_rand_end * num_multiple)
19
- .then { multipleOf ? _1 : _1.round(2) }
20
- end
17
+ def static_number_example = (num_rand_end * num_multiple).then { multipleOf ? _1 : _1.round(2) }
21
18
 
22
19
  def random_number_example
23
20
  (Faker::Number.between(from: num_rand_begin, to: num_rand_end) * num_multiple)
24
21
  .then { multipleOf ? _1 : _1.round(2) }
25
22
  end
26
23
 
27
- def num_rand_begin
28
- multipleOf ? (min_num / multipleOf).ceil : min_num
29
- end
24
+ def num_rand_begin = multipleOf ? (min_num / multipleOf).ceil : min_num
30
25
 
31
- def num_rand_end
32
- multipleOf ? (max_num / multipleOf).floor : max_num
33
- end
26
+ def num_rand_end = multipleOf ? (max_num / multipleOf).floor : max_num
34
27
 
35
- def num_multiple
36
- multipleOf || 1
37
- end
28
+ def num_multiple = multipleOf || 1
38
29
 
39
- def min_num
40
- (minimum || MIN_NUM).to_f.ceil(2)
41
- end
30
+ def min_num = (minimum || MIN_NUM).to_f.ceil(2)
42
31
 
43
- def max_num
44
- (maximum || MAX_NUM).to_f.floor(2)
45
- end
32
+ def max_num = (maximum || MAX_NUM).to_f.floor(2)
46
33
  end
47
34
  end
48
35
  end
@@ -65,13 +65,9 @@ module Fakeit
65
65
  end
66
66
  end
67
67
 
68
- def static_string_with_length
69
- '1' * max_string_length
70
- end
68
+ def static_string_with_length = '1' * max_string_length
71
69
 
72
- def static_string_format
73
- (STATIC_FORMAT_HANDLERS[format] || method(:unknown_format))[]
74
- end
70
+ def static_string_format = (STATIC_FORMAT_HANDLERS[format] || method(:unknown_format))[]
75
71
 
76
72
  def static_string_pattern
77
73
  @static_string_pattern ||= @string_pattern.examples(
@@ -79,32 +75,20 @@ module Fakeit
79
75
  ).first
80
76
  end
81
77
 
82
- def length_constraint
83
- minLength || maxLength
84
- end
78
+ def length_constraint = minLength || maxLength
85
79
 
86
- def string_with_length
87
- Faker::Internet.username(specifier: min_string_length..max_string_length)
88
- end
80
+ def string_with_length = Faker::Internet.username(specifier: min_string_length..max_string_length)
89
81
 
90
- def min_string_length
91
- minLength || 0
92
- end
82
+ def min_string_length = minLength || 0
93
83
 
94
- def max_string_length
95
- maxLength || min_string_length + 10
96
- end
84
+ def max_string_length = maxLength || min_string_length + 10
97
85
 
98
- def random_string_format
99
- (RANDOM_FORMAT_HANDLERS[format] || method(:unknown_format))[]
100
- end
86
+ def random_string_format = (RANDOM_FORMAT_HANDLERS[format] || method(:unknown_format))[]
101
87
 
102
- def random_string_pattern
103
- @random_string_pattern ||= @string_pattern.random_example(max_repeater_variance: 1)
104
- end
88
+ def random_string_pattern = @random_string_pattern ||= @string_pattern.random_example(max_repeater_variance: 1)
105
89
 
106
90
  def unknown_format
107
- Fakeit::Logger.info("Unknown string format: #{format}")
91
+ Logger.info("Unknown string format: #{format}")
108
92
  'Unknown string format'
109
93
  end
110
94
  end
@@ -4,7 +4,8 @@ module Fakeit
4
4
  def load(src)
5
5
  parse_method = parse_method(src)
6
6
 
7
- open(src, &:read)
7
+ URI
8
+ .open(src, &:read)
8
9
  .then(&parse_method)
9
10
  .then(&OpenAPIParser.method(:parse))
10
11
  end
@@ -7,9 +7,7 @@ module Fakeit
7
7
  @app_options = app_options
8
8
  end
9
9
 
10
- def status
11
- response.first.to_i
12
- end
10
+ def status = response.first.to_i
13
11
 
14
12
  def headers
15
13
  response_headers
@@ -22,39 +20,31 @@ module Fakeit
22
20
  response_schema
23
21
  &.schema
24
22
  &.to_example(example_options)
25
- &.then(&JSON.method(:generate))
23
+ &.then(&method(:serialise))
26
24
  .to_s
27
25
  end
28
26
 
29
- def validate(**request_parts)
30
- @validator.validate(**request_parts)
31
- end
27
+ def validate(...) = @validator.validate(...)
32
28
 
33
29
  private
34
30
 
31
+ def serialise(body) = body.is_a?(String) ? body : JSON.generate(body)
32
+
35
33
  def example_options
36
34
  { use_example: @app_options.use_example, use_static: @app_options.method(:use_static?), depth: 0 }
37
35
  end
38
36
 
39
37
  def response_content
40
- response.last.content&.find { |k, _| k =~ %r{^application/.*json} }
38
+ response.last.content&.find { |k, _| k =~ %r{^application/.*json} || k == 'application/pdf' }
41
39
  end
42
40
 
43
- def response_schema
44
- response_content&.last
45
- end
41
+ def response_schema = response_content&.last
46
42
 
47
- def response_content_type
48
- response_content&.first
49
- end
43
+ def response_content_type = response_content&.first
50
44
 
51
- def response_headers
52
- response.last.headers
53
- end
45
+ def response_headers = response.last.headers
54
46
 
55
- def response
56
- @request_operation.operation_object.responses.response.min
57
- end
47
+ def response = @request_operation.operation_object.responses.response.min
58
48
  end
59
49
  end
60
50
  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,9 +1,7 @@
1
1
  module Fakeit
2
2
  module Validation
3
3
  class Validator
4
- def initialize(operation)
5
- @operation = operation
6
- end
4
+ def initialize(operation) = @operation = operation
7
5
 
8
6
  def validate(body: {}, params: {}, headers: {})
9
7
  options = OpenAPIParser::SchemaValidator::Options.new(coerce_value: true)
@@ -26,17 +24,11 @@ module Fakeit
26
24
  end
27
25
  end
28
26
 
29
- def can_validate?(media_type)
30
- media_type =~ %r{^application/.*json} || media_type == 'multipart/form-data'
31
- end
27
+ def can_validate?(media_type) = media_type =~ %r{^application/.*json} || media_type == 'multipart/form-data'
32
28
 
33
- def request_content_types
34
- request_body&.content&.keys.to_a
35
- end
29
+ def request_content_types = request_body&.content&.keys.to_a
36
30
 
37
- def request_body
38
- @operation.operation_object.request_body
39
- end
31
+ def request_body = @operation.operation_object.request_body
40
32
  end
41
33
  end
42
34
  end
@@ -1,3 +1,3 @@
1
1
  module Fakeit
2
- VERSION = '0.6.3'.freeze
2
+ VERSION = '0.9.0'.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.3
4
+ version: 0.9.0
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-09-11 00:00:00.000000000 Z
11
+ date: 2021-03-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '12.0'
61
+ version: '13.0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '12.0'
68
+ version: '13.0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -86,14 +86,28 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '0.80'
89
+ version: '1.10'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '0.80'
96
+ version: '1.10'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop-rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.5'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.5'
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: simplecov
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -206,6 +220,20 @@ dependencies:
206
220
  - - "~>"
207
221
  - !ruby/object:Gem::Version
208
222
  version: '4.8'
223
+ - !ruby/object:Gem::Dependency
224
+ name: webrick
225
+ requirement: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - "~>"
228
+ - !ruby/object:Gem::Version
229
+ version: '1.7'
230
+ type: :runtime
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - "~>"
235
+ - !ruby/object:Gem::Version
236
+ version: '1.7'
209
237
  description: Create mock server from Openapi specification
210
238
  email:
211
239
  - realfengjia@foxmail.com
@@ -218,6 +246,7 @@ files:
218
246
  - ".gitignore"
219
247
  - ".rspec"
220
248
  - ".rubocop.yml"
249
+ - CHANGELOG.md
221
250
  - Gemfile
222
251
  - Gemfile.lock
223
252
  - LICENSE.txt
@@ -228,9 +257,13 @@ files:
228
257
  - docs/static.md
229
258
  - fakeit.gemspec
230
259
  - lib/fakeit.rb
231
- - lib/fakeit/app/app.rb
232
- - lib/fakeit/app/body_parser.rb
260
+ - lib/fakeit/app/app_builder.rb
261
+ - lib/fakeit/app/helpers/body_parser.rb
262
+ - lib/fakeit/app/helpers/response_builder.rb
233
263
  - lib/fakeit/app/options.rb
264
+ - lib/fakeit/app/routes/config_route.rb
265
+ - lib/fakeit/app/routes/openapi_route.rb
266
+ - lib/fakeit/core_extensions/reference.rb
234
267
  - lib/fakeit/core_extensions/schema.rb
235
268
  - lib/fakeit/logger.rb
236
269
  - lib/fakeit/middleware/recorder.rb
@@ -242,6 +275,7 @@ files:
242
275
  - lib/fakeit/openapi/example/string_example.rb
243
276
  - lib/fakeit/openapi/loader.rb
244
277
  - lib/fakeit/openapi/operation.rb
278
+ - lib/fakeit/openapi/reference_error.rb
245
279
  - lib/fakeit/openapi/schema.rb
246
280
  - lib/fakeit/openapi/specification.rb
247
281
  - lib/fakeit/validation/validation_error.rb
@@ -251,7 +285,7 @@ homepage: https://github.com/JustinFeng/fakeit
251
285
  licenses:
252
286
  - MIT
253
287
  metadata: {}
254
- post_install_message:
288
+ post_install_message:
255
289
  rdoc_options: []
256
290
  require_paths:
257
291
  - lib
@@ -259,15 +293,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
259
293
  requirements:
260
294
  - - ">="
261
295
  - !ruby/object:Gem::Version
262
- version: 2.7.0
296
+ version: 3.0.0
263
297
  required_rubygems_version: !ruby/object:Gem::Requirement
264
298
  requirements:
265
299
  - - ">="
266
300
  - !ruby/object:Gem::Version
267
301
  version: '0'
268
302
  requirements: []
269
- rubygems_version: 3.1.2
270
- signing_key:
303
+ rubygems_version: 3.2.3
304
+ signing_key:
271
305
  specification_version: 4
272
306
  summary: Create mock server from Openapi specification
273
307
  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
- 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