fitting 3.0.2 → 4.0.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/.gitignore +1 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +9 -0
- data/README.md +272 -109
- data/fitting.gemspec +2 -2
- data/images/b1.png +0 -0
- data/images/b2.png +0 -0
- data/images/w1.png +0 -0
- data/images/w2.png +0 -0
- data/lib/fitting/action.rb +105 -0
- data/lib/fitting/cover/json_schema.rb +2 -2
- data/lib/fitting/cover/json_schema_one_of.rb +4 -2
- data/lib/fitting/debug.rb +47 -0
- data/lib/fitting/doc/action.rb +141 -0
- data/lib/fitting/doc/code.rb +53 -0
- data/lib/fitting/doc/combination_enum.rb +110 -0
- data/lib/fitting/doc/combination_one_of.rb +61 -0
- data/lib/fitting/doc/combination_optional.rb +54 -0
- data/lib/fitting/doc/combination_step.rb +48 -0
- data/lib/fitting/doc/content_type.rb +152 -0
- data/lib/fitting/doc/json_schema.rb +116 -0
- data/lib/fitting/doc/step.rb +102 -0
- data/lib/fitting/doc.rb +107 -0
- data/lib/fitting/host.rb +37 -0
- data/lib/fitting/log.rb +102 -0
- data/lib/fitting/nocov.rb +64 -0
- data/lib/fitting/prefix.rb +62 -0
- data/lib/fitting/railtie.rb +0 -1
- data/lib/fitting/records/spherical/request.rb +7 -4
- data/lib/fitting/records/spherical/response.rb +22 -16
- data/lib/fitting/records/tested/request.rb +6 -1
- data/lib/fitting/records/tested/response.rb +6 -1
- data/lib/fitting/rep/html.rb +32 -0
- data/lib/fitting/rep.rb +24 -0
- data/lib/fitting/report/action.rb +9 -15
- data/lib/fitting/report/actions.rb +22 -33
- data/lib/fitting/report/combination.rb +10 -6
- data/lib/fitting/report/combinations.rb +9 -29
- data/lib/fitting/report/prefix.rb +7 -24
- data/lib/fitting/report/prefixes.rb +11 -25
- data/lib/fitting/report/response.rb +12 -22
- data/lib/fitting/report/responses.rb +23 -27
- data/lib/fitting/report/tests.rb +4 -8
- data/lib/fitting/skip/action.rb +44 -0
- data/lib/fitting/skip/api.rb +29 -0
- data/lib/fitting/skip.rb +21 -0
- data/lib/fitting/version.rb +1 -1
- data/lib/fitting.rb +12 -28
- data/lib/tasks/fitting.rake +23 -84
- data/lib/templates/htmlcss/bootstrap-nightshade.min.css +12 -0
- data/lib/templates/htmlcss/bootstrap.min.js +7 -0
- data/lib/templates/htmlcss/darkmode.min.js +6 -0
- data/lib/templates/htmlcss/fitting.html +196 -0
- data/lib/templates/htmlcss/jquery-3.6.0.min.js +2 -0
- metadata +40 -39
- data/lib/fitting/configuration.rb +0 -17
- data/lib/fitting/records/spherical/requests.rb +0 -25
- data/lib/fitting/storage/responses.rb +0 -21
- data/lib/fitting/tests.rb +0 -31
- data/lib/tasks/fitting_outgoing.rake +0 -91
- data/lib/templates/bomboniere/.gitignore +0 -21
- data/lib/templates/bomboniere/.tool-versions +0 -1
- data/lib/templates/bomboniere/README.md +0 -19
- data/lib/templates/bomboniere/dist/css/app.aa2bcd8a.css +0 -1
- data/lib/templates/bomboniere/dist/css/chunk-vendors.ec5f6c3f.css +0 -1
- data/lib/templates/bomboniere/dist/favicon.ico +0 -0
- data/lib/templates/bomboniere/dist/index.html +0 -1
- data/lib/templates/bomboniere/dist/js/app.e5f1a5ec.js +0 -2
- data/lib/templates/bomboniere/dist/js/app.e5f1a5ec.js.map +0 -1
- data/lib/templates/bomboniere/dist/js/chunk-vendors.0f99b670.js +0 -13
- data/lib/templates/bomboniere/dist/js/chunk-vendors.0f99b670.js.map +0 -1
- data/lib/templates/bomboniere/package-lock.json +0 -9292
- data/lib/templates/bomboniere/package.json +0 -27
- data/lib/templates/bomboniere/public/favicon.ico +0 -0
- data/lib/templates/bomboniere/public/index.html +0 -17
- data/lib/templates/bomboniere/src/App.vue +0 -102
- data/lib/templates/bomboniere/src/assets/logo.png +0 -0
- data/lib/templates/bomboniere/src/components/HelloWorld.vue +0 -204
- data/lib/templates/bomboniere/src/main.js +0 -10
- data/lib/templates/bomboniere/src/router/index.js +0 -31
- data/lib/templates/bomboniere/src/views/About.vue +0 -5
- data/lib/templates/bomboniere/src/views/Action.vue +0 -173
- data/lib/templates/bomboniere/src/views/Home.vue +0 -17
- data/lib/templates/bomboniere/vue.config.js +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: acf56757fc3fe3dca52c0ffc19624debab877fd8f9ea71ffa891ab19674c1a65
|
4
|
+
data.tar.gz: c2238a9ad8374f72075aa07b48323910bfb670ab57f95dfff6ca12dace14faaf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3e2a972498110e3c2b8ea625d0b7e73f5a127209b94e3f4373cf49a3cd38eb5c04483e876dc07bcb9b71ee3c90c7b5900e8fe31fc73ce39aec597bf70fad7e88
|
7
|
+
data.tar.gz: debb064c3590bc59c5a783d3546d4de6f75727ab4aa354d3e40f6548f7b72cc8ae9b05a1d009dab55aa0eba900a0e783979265c38dfda89b483f64c3e0f2d6ee
|
data/.gitignore
CHANGED
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.5.5
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,19 +1,90 @@
|
|
1
1
|
# Fitting
|
2
2
|
|
3
3
|
<img align="right" width="192" height="192"
|
4
|
-
alt="
|
4
|
+
alt="Fitting avatar: Documents with hangers"
|
5
5
|
src="./images/logo.png">
|
6
6
|
|
7
|
-
|
8
|
-
This makes it easy to find out how much the documentation matches the implementation.
|
7
|
+
We set up test logs, validate them according to your API documentation and show the documentation coverage with logs.
|
9
8
|
|
10
|
-
|
9
|
+
Test logs setting supports RSpec test (and WebMock stubbing) for Ruby On Rails application and API documentation supports API Blueprint,
|
10
|
+
Swagger and OpenAPI.
|
11
11
|
|
12
|
-
|
12
|
+
This reduces the costs of support, testers and analysts.
|
13
13
|
|
14
|
-
|
14
|
+
Log
|
15
|
+
```text
|
16
|
+
FITTING incoming request {"method":"POST","path":"/public/api/v1/inboxes/tEX5JiZyceiwuKMi1oN9Sf8S/contacts","body":{},"response":{"status":200,"content_type":"application/json","body":{"source_id":"00dbf18d-879e-47cb-ac45-e9aece266eb1","pubsub_token":"ktn6YwPus57JDf4e59eFPom5","id":3291,"name":"shy-surf-401","email":null,"phone_number":null}},"title":"./spec/controllers/public/api/v1/inbox/contacts_controller_spec.rb:9","group":"./spec/controllers/public/api/v1/inbox/contacts_controller_spec.rb","host":"www.example.com"}
|
17
|
+
FITTING outgoing request {"method":"POST","path":"/v1/organizations/org_id/meeting","body":{},"response":{"status":200,"content_type":"application/json","body":{"success":true,"data":{"meeting":{"id":"meeting_id","roomName":"room_name"}}}},"title":"./spec/controllers/api/v1/accounts/integrations/dyte_controller_spec.rb:50","group":"./spec/controllers/api/v1/accounts/integrations/dyte_controller_spec.rb","host":"api.cluster.dyte.in"}
|
18
|
+
```
|
19
|
+
|
20
|
+
validation
|
21
|
+
```console
|
22
|
+
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF.FFF..FFFFFFFFFF....F.......F...FF.....F...F....F..............................FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF..FF.F..FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF..FF........FFF...FFFF......FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF........FFFFFFFFFFF..FFFFFF..FFFFFFFFFFFFFFFFF.......FFFFFF.............FFFFFFFFFFFF....F........FFF.F...FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF............FF........FFF......FFFFFFFFFFFFFFFFFFFFFF....FFFFFF......F............FFFF........FFFFFFFFFFFFFF.....FFFFFFFFFFFFFFFFFFFFFFF..FF.....FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF.....FF..........FFFFFFFFFFFFFFFFFF...FFFF...............F.F....FF..FFFFFFFF
|
23
|
+
|
24
|
+
1) Fitting::Doc::NotFound log error:
|
25
|
+
|
26
|
+
host: www.example.com
|
27
|
+
method: POST
|
28
|
+
path: /public/api/v1/inboxes/{inbox_identifier}/contacts
|
29
|
+
code: 200
|
30
|
+
|
31
|
+
content-type: application/json
|
32
|
+
|
33
|
+
json-schema: {
|
34
|
+
"$schema": "http://json-schema.org/draft-04/schema#",
|
35
|
+
"type": "object",
|
36
|
+
"properties": {
|
37
|
+
"id": {
|
38
|
+
"type": "integer",
|
39
|
+
"description": "Id of the contact"
|
40
|
+
},
|
41
|
+
"source_id": {
|
42
|
+
"type": "string",
|
43
|
+
"description": "The session identifier of the contact"
|
44
|
+
},
|
45
|
+
"name": {
|
46
|
+
"type": "string",
|
47
|
+
"description": "Name of the contact"
|
48
|
+
},
|
49
|
+
"email": {
|
50
|
+
"type": "string",
|
51
|
+
"description": "Email of the contact"
|
52
|
+
},
|
53
|
+
"pubsub_token": {
|
54
|
+
"type": "string",
|
55
|
+
"description": "The token to be used to connect to chatwoot websocket"
|
56
|
+
}
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
body: {
|
61
|
+
"source_id": "c9e8c31f-06df-49b4-8fb9-4466457ae65b",
|
62
|
+
"pubsub_token": "Zgc7DEvaj5TkgZ1a4C7AvJXo",
|
63
|
+
"id": 3293,
|
64
|
+
"name": "restless-snowflake-670",
|
65
|
+
"email": null,
|
66
|
+
"phone_number": null
|
67
|
+
}
|
68
|
+
|
69
|
+
error [
|
70
|
+
"The property '#/email' of type null did not match the following type: string in schema e56b7e65-d70c-5f7a-a96c-982df5f8f2f7"
|
71
|
+
]
|
72
|
+
|
73
|
+
...
|
74
|
+
|
75
|
+
804 examples, 565 failure, 0 pending
|
76
|
+
|
77
|
+
Coverage: 65.51%
|
78
|
+
```
|
15
79
|
|
16
|
-
|
80
|
+
and cover
|
81
|
+

|
82
|
+
|
83
|
+

|
84
|
+
|
85
|
+

|
86
|
+
|
87
|
+

|
17
88
|
|
18
89
|
## Installation
|
19
90
|
Add this line to your application's Gemfile:
|
@@ -32,41 +103,146 @@ $ gem install fitting
|
|
32
103
|
```
|
33
104
|
|
34
105
|
## Usage
|
35
|
-
|
106
|
+
### Log
|
107
|
+
Firstly, improve `test.log`.
|
108
|
+
|
109
|
+
To your `spec_helper.rb`:
|
36
110
|
|
37
111
|
```ruby
|
38
112
|
require 'fitting'
|
39
113
|
|
40
|
-
Fitting.
|
114
|
+
Fitting.logger
|
41
115
|
```
|
42
116
|
|
117
|
+
Delete all files `log/*.log` and run rspec
|
118
|
+
|
119
|
+
You get more information about incoming and outgoing request in `log/fitting*.log`.
|
120
|
+
|
121
|
+
```text
|
122
|
+
FITTING incoming request {"method":"POST","path":"/public/api/v1/inboxes/tEX5JiZyceiwuKMi1oN9Sf8S/contacts","body":{},"response":{"status":200,"content_type":"application/json","body":{"source_id":"00dbf18d-879e-47cb-ac45-e9aece266eb1","pubsub_token":"ktn6YwPus57JDf4e59eFPom5","id":3291,"name":"shy-surf-401","email":null,"phone_number":null}},"title":"./spec/controllers/public/api/v1/inbox/contacts_controller_spec.rb:9","group":"./spec/controllers/public/api/v1/inbox/contacts_controller_spec.rb","host":"www.example.com"}
|
123
|
+
FITTING outgoing request {"method":"POST","path":"/v1/organizations/org_id/meeting","body":{},"response":{"status":200,"content_type":"application/json","body":{"success":true,"data":{"meeting":{"id":"meeting_id","roomName":"room_name"}}}},"title":"./spec/controllers/api/v1/accounts/integrations/dyte_controller_spec.rb:50","group":"./spec/controllers/api/v1/accounts/integrations/dyte_controller_spec.rb","host":"api.cluster.dyte.in"}
|
124
|
+
```
|
125
|
+
|
126
|
+
### Validation
|
127
|
+
Secondly, validate the logs to the documentation.
|
128
|
+
|
43
129
|
Add this to your `.fitting.yml`:
|
44
130
|
|
45
|
-
|
46
|
-
|
131
|
+
```yaml
|
132
|
+
APIs:
|
133
|
+
- host: www.example.com
|
134
|
+
type: openapi2
|
135
|
+
path: swagger/swagger.json
|
136
|
+
```
|
137
|
+
|
138
|
+
Run
|
139
|
+
```bash
|
140
|
+
bundle e rake fitting:validate
|
141
|
+
```
|
142
|
+
|
143
|
+
Console output
|
144
|
+
|
145
|
+
```console
|
146
|
+
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF.FFF..FFFFFFFFFF....F.......F...FF.....F...F....F..............................FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF..FF.F..FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF..FF........FFF...FFFF......FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF........FFFFFFFFFFF..FFFFFF..FFFFFFFFFFFFFFFFF.......FFFFFF.............FFFFFFFFFFFF....F........FFF.F...FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF............FF........FFF......FFFFFFFFFFFFFFFFFFFFFF....FFFFFF......F............FFFF........FFFFFFFFFFFFFF.....FFFFFFFFFFFFFFFFFFFFFFF..FF.....FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF.....FF..........FFFFFFFFFFFFFFFFFF...FFFF...............F.F....FF..FFFFFFFF
|
147
|
+
|
148
|
+
1) Fitting::Doc::NotFound log error:
|
149
|
+
|
150
|
+
host: www.example.com
|
151
|
+
method: POST
|
152
|
+
path: /public/api/v1/inboxes/{inbox_identifier}/contacts
|
153
|
+
code: 200
|
154
|
+
|
155
|
+
content-type: application/json
|
156
|
+
|
157
|
+
json-schema: {
|
158
|
+
"$schema": "http://json-schema.org/draft-04/schema#",
|
159
|
+
"type": "object",
|
160
|
+
"properties": {
|
161
|
+
"id": {
|
162
|
+
"type": "integer",
|
163
|
+
"description": "Id of the contact"
|
164
|
+
},
|
165
|
+
"source_id": {
|
166
|
+
"type": "string",
|
167
|
+
"description": "The session identifier of the contact"
|
168
|
+
},
|
169
|
+
"name": {
|
170
|
+
"type": "string",
|
171
|
+
"description": "Name of the contact"
|
172
|
+
},
|
173
|
+
"email": {
|
174
|
+
"type": "string",
|
175
|
+
"description": "Email of the contact"
|
176
|
+
},
|
177
|
+
"pubsub_token": {
|
178
|
+
"type": "string",
|
179
|
+
"description": "The token to be used to connect to chatwoot websocket"
|
180
|
+
}
|
181
|
+
}
|
182
|
+
}
|
183
|
+
|
184
|
+
body: {
|
185
|
+
"source_id": "c9e8c31f-06df-49b4-8fb9-4466457ae65b",
|
186
|
+
"pubsub_token": "Zgc7DEvaj5TkgZ1a4C7AvJXo",
|
187
|
+
"id": 3293,
|
188
|
+
"name": "restless-snowflake-670",
|
189
|
+
"email": null,
|
190
|
+
"phone_number": null
|
191
|
+
}
|
192
|
+
|
193
|
+
error [
|
194
|
+
"The property '#/email' of type null did not match the following type: string in schema e56b7e65-d70c-5f7a-a96c-982df5f8f2f7"
|
195
|
+
]
|
196
|
+
|
197
|
+
...
|
198
|
+
|
199
|
+
804 examples, 565 failure, 0 pending
|
200
|
+
|
201
|
+
Coverage: 65.51%
|
202
|
+
```
|
203
|
+
|
204
|
+
### Coverage
|
205
|
+
And task will create HTML (`coverage/fitting.html`) reports.
|
206
|
+
|
207
|
+

|
208
|
+
|
209
|
+

|
210
|
+
|
211
|
+
More information on action coverage
|
212
|
+
|
213
|
+

|
214
|
+
|
215
|
+

|
216
|
+
|
217
|
+
## Settings
|
218
|
+
|
219
|
+
### APIs
|
220
|
+
|
221
|
+
#### type
|
222
|
+
|
223
|
+
##### OpenAPI 2.0
|
224
|
+
Swagger
|
47
225
|
|
48
226
|
```yaml
|
49
|
-
|
50
|
-
-
|
227
|
+
APIs:
|
228
|
+
- host: www.example.com
|
51
229
|
type: openapi2
|
52
|
-
|
53
|
-
- doc.json
|
230
|
+
path: doc/api.json
|
54
231
|
```
|
55
232
|
|
56
|
-
|
233
|
+
##### OpenAPI 3.0
|
57
234
|
Also OpenAPI
|
58
235
|
|
59
236
|
```yaml
|
60
|
-
|
61
|
-
-
|
237
|
+
APIs:
|
238
|
+
- host: www.example.com
|
62
239
|
type: openapi3
|
63
|
-
|
64
|
-
- doc.yaml
|
240
|
+
path: doc/api.json
|
65
241
|
```
|
66
242
|
|
67
|
-
|
68
|
-
First you need to install [drafter](https://github.com/apiaryio/drafter).
|
69
|
-
Works after conversion from API Blueprint to API Elements (in YAML file) with Drafter.
|
243
|
+
##### API Blueprint
|
244
|
+
First you need to install [drafter](https://github.com/apiaryio/drafter) or [crafter](https://github.com/funbox/crafter).
|
245
|
+
Works after conversion from API Blueprint to API Elements (in YAML file) with Drafter or Crafter.
|
70
246
|
|
71
247
|
That is, I mean that you first need to do this
|
72
248
|
|
@@ -74,128 +250,115 @@ That is, I mean that you first need to do this
|
|
74
250
|
drafter doc.apib -o doc.yaml
|
75
251
|
```
|
76
252
|
|
253
|
+
or
|
254
|
+
|
255
|
+
```bash
|
256
|
+
node_modules/.bin/crafter doc.apib > doc.yaml
|
257
|
+
```
|
258
|
+
|
77
259
|
and then
|
78
260
|
|
79
261
|
```yaml
|
80
|
-
|
81
|
-
-
|
262
|
+
APIs:
|
263
|
+
- host: www.example.com
|
82
264
|
type: drafter
|
83
|
-
|
84
|
-
- doc.yaml
|
265
|
+
path: doc/api.yaml
|
85
266
|
```
|
86
267
|
|
87
|
-
|
88
|
-
|
89
|
-
To use additional features of the pre-converted [tomograph](https://github.com/funbox/tomograph)
|
268
|
+
or
|
90
269
|
|
91
270
|
```yaml
|
92
|
-
|
93
|
-
-
|
94
|
-
type:
|
95
|
-
|
96
|
-
- doc.json
|
271
|
+
APIs:
|
272
|
+
- host: www.example.com
|
273
|
+
type: crafter
|
274
|
+
path: doc/api.yaml
|
97
275
|
```
|
98
276
|
|
99
|
-
|
100
|
-
|
277
|
+
##### Tomograph
|
278
|
+
|
279
|
+
To use additional features of the pre-converted [tomograph](https://github.com/funbox/tomograph)
|
280
|
+
|
281
|
+
example
|
282
|
+
|
101
283
|
```bash
|
102
|
-
bundle
|
284
|
+
bundle exec tomograph -d crafter --exclude-description doc/api.yml doc/api.json
|
103
285
|
```
|
104
286
|
|
105
287
|
and then
|
106
|
-
|
107
|
-
|
288
|
+
|
289
|
+
```yaml
|
290
|
+
APIs:
|
291
|
+
- host: www.example.com
|
292
|
+
type: tomogram
|
293
|
+
path: doc/api.json
|
108
294
|
```
|
109
295
|
|
110
|
-
|
111
|
-
|
112
|
-
|
296
|
+
#### prefix
|
297
|
+
|
298
|
+
Setting the prefix name is optional. For example, you can do this:
|
299
|
+
|
300
|
+
```yaml
|
301
|
+
APIs:
|
302
|
+
- host: www.example.com
|
303
|
+
prefix: /api/v3
|
304
|
+
type: openapi2
|
305
|
+
path: swagger/swagger.json
|
113
306
|
```
|
114
307
|
|
115
|
-
|
308
|
+
### SkipValidation
|
116
309
|
|
117
|
-
|
118
|
-
/api/v1
|
119
|
-
POST /api/v1/accounts/{account_id}/inboxes 0% 200 0% 404 0% 403
|
120
|
-
PATCH /api/v1/accounts/{account_id}/inboxes/{id} 0% 200 0% 404 0% 403
|
121
|
-
POST /api/v1/accounts/{account_id}/inboxes/{id}/set_agent_bot 0% 204 100% 404 0% 403
|
122
|
-
GET /api/v1/agent_bots 0% 200 0% 404 0% 403
|
123
|
-
GET /api/v1/accounts/{account_id}/conversations 0% 200 0% 400 0% description
|
124
|
-
POST /api/v1/accounts/{account_id}/conversations 0% 200 0% 403
|
125
|
-
GET /api/v1/accounts/{account_id}/conversations/{id} 59% 200 0% 404 0% 403
|
126
|
-
POST /api/v1/accounts/{account_id}/conversations/{id}/toggle_status 80% 200 0% 404 0% 403
|
127
|
-
GET /api/v1/accounts/{account_id}/conversations/{id}/messages 47% 200 0% 404 0% 403
|
128
|
-
POST /api/v1/accounts/{account_id}/conversations/{id}/messages 0% 200 0% 404 0% 403
|
129
|
-
GET /api/v1/accounts/{account_id}/conversations/{id}/labels 100% 200 0% 404 0% 403
|
130
|
-
POST /api/v1/accounts/{account_id}/conversations/{id}/labels 100% 200 0% 404 0% 403
|
131
|
-
POST /api/v1/accounts/{account_id}/conversations/{id}/assignments 77% 200 0% 404 0% 403
|
132
|
-
GET /api/v1/accounts/{account_id}/contacts 0% 200 0% 400
|
133
|
-
POST /api/v1/accounts/{account_id}/contacts 14% 200 0% 400
|
134
|
-
GET /api/v1/accounts/{account_id}/contacts/{id} 14% 200 0% 404 0% 403
|
135
|
-
PUT /api/v1/accounts/{account_id}/contacts/{id} 0% 204 0% 404 0% 403
|
136
|
-
GET /api/v1/accounts/{account_id}/contacts/{id}/conversations 0% 200 0% 404 0% 403
|
137
|
-
GET /api/v1/accounts/{account_id}/contacts/search 0% 200 0% 401
|
138
|
-
POST /api/v1/accounts/{account_id}/contacts/{id}/contact_inboxes 0% 200 0% 401 100% 422
|
139
|
-
GET /api/v1/profile 88% 200 100% 401
|
140
|
-
|
141
|
-
tests_without_prefixes: 42
|
142
|
-
tests_without_actions: 144
|
143
|
-
tests_without_responses: 43
|
144
|
-
```
|
145
|
-
|
146
|
-
And task will create HTML (`fitting/index.html`) reports.
|
147
|
-
|
148
|
-

|
310
|
+
#### host
|
149
311
|
|
150
|
-
|
312
|
+
It is not necessary to immediately describe each host in detail, you can only specify its name and skip it until you are ready to documented it
|
151
313
|
|
152
|
-
|
314
|
+
```yaml
|
315
|
+
SkipAPIs:
|
316
|
+
- host: api.cluster.dyte.in
|
317
|
+
```
|
153
318
|
|
154
|
-
|
319
|
+
#### prefix
|
155
320
|
|
156
|
-
|
321
|
+
If you want to skip a specific prefix in the host
|
157
322
|
|
158
323
|
```yaml
|
159
|
-
|
160
|
-
-
|
161
|
-
|
162
|
-
- doc.json
|
324
|
+
SkipAPIs:
|
325
|
+
- host: api.cluster.dyte.in
|
326
|
+
prefix: /admin/api
|
163
327
|
```
|
164
328
|
|
165
|
-
|
329
|
+
#### method and path
|
330
|
+
|
331
|
+
If you want to skip a specific request in the host
|
166
332
|
|
167
|
-
It is not necessary to immediately describe each prefix in detail, you can only specify its name and skip it until you are ready to documented it
|
168
333
|
```yaml
|
169
|
-
|
170
|
-
-
|
171
|
-
|
172
|
-
|
173
|
-
- doc.json
|
174
|
-
- name: /api/v3
|
175
|
-
skip: true
|
334
|
+
SkipAPIs:
|
335
|
+
- host: api.cluster.dyte.in
|
336
|
+
method: GET
|
337
|
+
path: /api/v1/cars
|
176
338
|
```
|
177
339
|
|
178
|
-
|
340
|
+
### NoCov
|
341
|
+
|
342
|
+
It is not necessary to immediately test each doc in detail, you can only specify its name and skip it until you are ready to test it
|
343
|
+
|
179
344
|
```yaml
|
180
|
-
|
181
|
-
-
|
182
|
-
|
183
|
-
|
184
|
-
- doc.json
|
185
|
-
- name: /api/v3
|
186
|
-
skip: true
|
345
|
+
NoCov:
|
346
|
+
- host: sso.test
|
347
|
+
method: GET
|
348
|
+
path: /users/{userId}
|
187
349
|
```
|
188
350
|
|
189
|
-
|
351
|
+
### Debug
|
352
|
+
|
353
|
+
If you find bug, you can debug it or create task in this github project with new file `coverage/fitting.debug.yml`
|
190
354
|
|
191
355
|
```yaml
|
192
|
-
|
193
|
-
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
- GET /api/v1/user/{id}
|
356
|
+
Debug:
|
357
|
+
- host: www.example.com
|
358
|
+
method: GET
|
359
|
+
path: /api/v3/users
|
360
|
+
code: 200
|
361
|
+
content-type: application/json
|
199
362
|
```
|
200
363
|
|
201
364
|
## Contributing
|
data/fitting.gemspec
CHANGED
@@ -18,10 +18,10 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.required_ruby_version = '>= 2.
|
21
|
+
spec.required_ruby_version = '>= 2.5.0'
|
22
22
|
spec.add_runtime_dependency 'json-schema', '~> 2.6', '>= 2.6.2'
|
23
23
|
spec.add_runtime_dependency 'terminal-table', '~> 3.0', '>= 3.0.2'
|
24
|
-
spec.add_runtime_dependency 'tomograph', '~> 3.1', '>= 3.1.
|
24
|
+
spec.add_runtime_dependency 'tomograph', '~> 3.1', '>= 3.1.5'
|
25
25
|
|
26
26
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
27
27
|
spec.add_development_dependency 'byebug', '~> 11.1', '>= 11.1.3'
|
data/images/b1.png
ADDED
Binary file
|
data/images/b2.png
ADDED
Binary file
|
data/images/w1.png
ADDED
Binary file
|
data/images/w2.png
ADDED
Binary file
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'fitting/host'
|
2
|
+
require 'fitting/prefix'
|
3
|
+
require 'fitting/report/prefixes'
|
4
|
+
|
5
|
+
module Fitting
|
6
|
+
class Action
|
7
|
+
class Skip < RuntimeError; end
|
8
|
+
class Empty < RuntimeError; end
|
9
|
+
class NotFound < RuntimeError
|
10
|
+
attr_reader :log
|
11
|
+
|
12
|
+
def initialize(msg, log)
|
13
|
+
@log = log
|
14
|
+
super(msg)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(action)
|
19
|
+
@action = action
|
20
|
+
end
|
21
|
+
|
22
|
+
def action
|
23
|
+
@action
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.all
|
27
|
+
[]
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.find!(actions, log)
|
31
|
+
host = Fitting::Host.find!(log)
|
32
|
+
host.cover!
|
33
|
+
|
34
|
+
prefix = Fitting::Prefix.find(host: host, log: log)
|
35
|
+
prefix.cover!
|
36
|
+
|
37
|
+
new(prefix.actions.find!(log))
|
38
|
+
rescue Fitting::Report::Actions::Empty,
|
39
|
+
Fitting::Host::Skip,
|
40
|
+
Fitting::Prefix::Skip
|
41
|
+
raise Skip
|
42
|
+
rescue Fitting::Report::Combinations::Empty,
|
43
|
+
Fitting::Report::Combinations::NotFound
|
44
|
+
raise Skip
|
45
|
+
rescue Fitting::Host::NotFound,
|
46
|
+
Fitting::Prefix::NotFound,
|
47
|
+
Fitting::Report::Actions::NotFound,
|
48
|
+
Fitting::Report::Responses::NotFound => e
|
49
|
+
raise NotFound.new(e.message, log)
|
50
|
+
end
|
51
|
+
|
52
|
+
def cover!(log)
|
53
|
+
action.cover!
|
54
|
+
|
55
|
+
response = action.responses.find!(log)
|
56
|
+
response.cover!
|
57
|
+
|
58
|
+
combination = response.combinations.find!(log)
|
59
|
+
combination.cover!
|
60
|
+
|
61
|
+
print "\e[32m.\e[0m"
|
62
|
+
rescue Fitting::Report::Actions::Empty,
|
63
|
+
Fitting::Host::Skip,
|
64
|
+
Fitting::Prefix::Skip
|
65
|
+
rescue Fitting::Report::Combinations::Empty,
|
66
|
+
Fitting::Report::Combinations::NotFound
|
67
|
+
rescue Fitting::Host::NotFound,
|
68
|
+
Fitting::Prefix::NotFound,
|
69
|
+
Fitting::Report::Actions::NotFound,
|
70
|
+
Fitting::Report::Responses::NotFound => e
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.report(actions)
|
74
|
+
all = 0
|
75
|
+
cover = 0
|
76
|
+
|
77
|
+
# prefixes.to_a.map do |prefix|
|
78
|
+
# all += 1
|
79
|
+
# break unless prefix.cover?
|
80
|
+
# cover += 1
|
81
|
+
# prefix.actions.to_a.map do |action|
|
82
|
+
# all += 1
|
83
|
+
# break unless action.cover?
|
84
|
+
# cover += 1
|
85
|
+
# action.responses.to_a.map do |response|
|
86
|
+
# all += 1
|
87
|
+
# break unless action.cover?
|
88
|
+
# cover += 1
|
89
|
+
# response.combinations.to_a.map do |combination|
|
90
|
+
# all += 1
|
91
|
+
# break unless combination.cover?
|
92
|
+
# cover += 1
|
93
|
+
# end
|
94
|
+
# end
|
95
|
+
# end
|
96
|
+
# end
|
97
|
+
|
98
|
+
puts
|
99
|
+
puts "Coverage #{(cover.to_f / all.to_f * 100).round(2)}%"
|
100
|
+
exit 1 unless false
|
101
|
+
|
102
|
+
exit 0
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -17,12 +17,12 @@ module Fitting
|
|
17
17
|
|
18
18
|
def inception(json_schema, combinations)
|
19
19
|
json_schema.each do |key, value|
|
20
|
-
if (key == 'properties') && (json_schema['required'] != value.keys)
|
20
|
+
if (key == 'properties') && value && (json_schema['required'] != value.keys)
|
21
21
|
schema = json_schema.dup
|
22
22
|
one_of = schema.delete('required') || []
|
23
23
|
schema['properties'].each_key do |property|
|
24
24
|
next if one_of.include?(property)
|
25
|
-
|
25
|
+
next if property == 'type' || property == 'properties'
|
26
26
|
combinations.push([schema.merge('required' => one_of + [property]), "required.#{property}"])
|
27
27
|
end
|
28
28
|
elsif value.is_a?(Hash)
|
@@ -10,7 +10,7 @@ module Fitting
|
|
10
10
|
|
11
11
|
def combi
|
12
12
|
inception(json_schema, combinations).each do |combination|
|
13
|
-
combination[0] =
|
13
|
+
combination[0] = combination[0]
|
14
14
|
combination[1] = ['one_of', combination[1]]
|
15
15
|
end
|
16
16
|
end
|
@@ -21,7 +21,9 @@ module Fitting
|
|
21
21
|
schema = json_schema.dup
|
22
22
|
one_of = schema.delete('oneOf')
|
23
23
|
one_of.each_index do |index|
|
24
|
-
|
24
|
+
schema_new = json_schema.dup
|
25
|
+
schema_new.delete('oneOf')
|
26
|
+
combinations.push([schema_new.merge(one_of[index]), "oneOf.#{index}"])
|
25
27
|
end
|
26
28
|
elsif value.is_a?(Hash)
|
27
29
|
com = inception(value, [])
|