fakeit 0.6.3 → 0.9.0
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 +4 -4
- data/.circleci/config.yml +1 -1
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +176 -0
- data/Gemfile.lock +41 -34
- data/README.md +30 -1
- data/bin/fakeit +4 -0
- data/fakeit.gemspec +5 -3
- data/lib/fakeit.rb +2 -2
- data/lib/fakeit/app/app_builder.rb +23 -0
- data/lib/fakeit/app/helpers/body_parser.rb +32 -0
- data/lib/fakeit/app/helpers/response_builder.rb +19 -0
- data/lib/fakeit/app/options.rb +10 -0
- data/lib/fakeit/app/routes/config_route.rb +36 -0
- data/lib/fakeit/app/routes/openapi_route.rb +52 -0
- data/lib/fakeit/core_extensions/reference.rb +9 -0
- data/lib/fakeit/core_extensions/schema.rb +1 -3
- data/lib/fakeit/logger.rb +1 -2
- data/lib/fakeit/middleware/recorder.rb +2 -6
- data/lib/fakeit/openapi/example/array_example.rb +5 -15
- data/lib/fakeit/openapi/example/integer_example.rb +4 -12
- data/lib/fakeit/openapi/example/number_example.rb +6 -19
- data/lib/fakeit/openapi/example/string_example.rb +9 -25
- data/lib/fakeit/openapi/loader.rb +2 -1
- data/lib/fakeit/openapi/operation.rb +10 -20
- data/lib/fakeit/openapi/reference_error.rb +6 -0
- data/lib/fakeit/openapi/specification.rb +1 -1
- data/lib/fakeit/validation/validator.rb +4 -12
- data/lib/fakeit/version.rb +1 -1
- metadata +47 -13
- data/lib/fakeit/app/app.rb +0 -63
- data/lib/fakeit/app/body_parser.rb +0 -30
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dbb5973b840c21eddd94a398c62a312bbbf21dba4b06323ca4ab8bf2fd7318f4
|
|
4
|
+
data.tar.gz: 3a2d30ed95aa61b39f68c3ddce26815ee7156f5a620a2fea097bf2d3466d5be6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 35fe9c896913f0a946586ad4945960b01e3b665c1eb101d7265ec67bb1b3e59e91e224b72ef2d330455f770e6546d97d172f7d63a2849a16e3a94053196fbad0
|
|
7
|
+
data.tar.gz: a0425724e4c9fb66f2feda3adc505c752b9b001ac8db6aee75715a20a06478434696bf4b082887b9c8e34470d029fdc7e88d236e32837307aa9ac0339dca34fe
|
data/.circleci/config.yml
CHANGED
data/.rubocop.yml
CHANGED
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.
|
|
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.
|
|
17
|
+
ast (2.4.2)
|
|
17
18
|
byebug (11.1.3)
|
|
18
|
-
concurrent-ruby (1.1.
|
|
19
|
+
concurrent-ruby (1.1.8)
|
|
19
20
|
diff-lcs (1.4.4)
|
|
20
|
-
docile (1.3.
|
|
21
|
+
docile (1.3.5)
|
|
21
22
|
faker (2.13.0)
|
|
22
23
|
i18n (>= 1.6, < 2)
|
|
23
|
-
i18n (1.8.
|
|
24
|
+
i18n (1.8.9)
|
|
24
25
|
concurrent-ruby (~> 1.0)
|
|
25
26
|
openapi_parser (0.12.1)
|
|
26
|
-
parallel (1.
|
|
27
|
-
parser (
|
|
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 (
|
|
36
|
+
rake (13.0.3)
|
|
36
37
|
regexp-examples (1.5.1)
|
|
37
|
-
regexp_parser (1.
|
|
38
|
+
regexp_parser (2.1.1)
|
|
38
39
|
rexml (3.2.4)
|
|
39
|
-
rspec (3.
|
|
40
|
-
rspec-core (~> 3.
|
|
41
|
-
rspec-expectations (~> 3.
|
|
42
|
-
rspec-mocks (~> 3.
|
|
43
|
-
rspec-core (3.
|
|
44
|
-
rspec-support (~> 3.
|
|
45
|
-
rspec-expectations (3.
|
|
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.
|
|
48
|
-
rspec-mocks (3.
|
|
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.
|
|
51
|
-
rspec-support (3.
|
|
52
|
-
rubocop (
|
|
51
|
+
rspec-support (~> 3.10.0)
|
|
52
|
+
rspec-support (3.10.2)
|
|
53
|
+
rubocop (1.10.0)
|
|
53
54
|
parallel (~> 1.10)
|
|
54
|
-
parser (>=
|
|
55
|
+
parser (>= 3.0.0.0)
|
|
55
56
|
rainbow (>= 2.2.2, < 4.0)
|
|
56
|
-
regexp_parser (>= 1.
|
|
57
|
+
regexp_parser (>= 1.8, < 3.0)
|
|
57
58
|
rexml
|
|
58
|
-
rubocop-ast (>=
|
|
59
|
+
rubocop-ast (>= 1.2.0, < 2.0)
|
|
59
60
|
ruby-progressbar (~> 1.7)
|
|
60
|
-
unicode-display_width (>= 1.4.0, <
|
|
61
|
-
rubocop-ast (
|
|
62
|
-
parser (>= 2.7.1.
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
|
|
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 (
|
|
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 (~>
|
|
85
|
+
rake (~> 13.0)
|
|
80
86
|
rspec (~> 3.0)
|
|
81
|
-
rubocop (~>
|
|
87
|
+
rubocop (~> 1.10)
|
|
88
|
+
rubocop-rake (~> 0.5)
|
|
82
89
|
simplecov (~> 0.18)
|
|
83
90
|
|
|
84
91
|
BUNDLED WITH
|
|
85
|
-
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 = '>=
|
|
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', '~>
|
|
30
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
|
31
31
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
|
32
|
-
spec.add_development_dependency 'rubocop', '~>
|
|
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')).
|
|
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.
|
|
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
|
data/lib/fakeit/app/options.rb
CHANGED
|
@@ -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
|
data/lib/fakeit/logger.rb
CHANGED
|
@@ -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
|
-
|
|
91
|
+
Logger.info("Unknown string format: #{format}")
|
|
108
92
|
'Unknown string format'
|
|
109
93
|
end
|
|
110
94
|
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(&
|
|
23
|
+
&.then(&method(:serialise))
|
|
26
24
|
.to_s
|
|
27
25
|
end
|
|
28
26
|
|
|
29
|
-
def validate(
|
|
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
|
|
@@ -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
|
-
|
|
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
|
data/lib/fakeit/version.rb
CHANGED
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.
|
|
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:
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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/
|
|
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:
|
|
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.
|
|
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: []
|
data/lib/fakeit/app/app.rb
DELETED
|
@@ -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
|