fitting 3.0.2 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.ruby-version +1 -1
  4. data/CHANGELOG.md +9 -0
  5. data/README.md +272 -109
  6. data/fitting.gemspec +2 -2
  7. data/images/b1.png +0 -0
  8. data/images/b2.png +0 -0
  9. data/images/w1.png +0 -0
  10. data/images/w2.png +0 -0
  11. data/lib/fitting/action.rb +105 -0
  12. data/lib/fitting/cover/json_schema.rb +2 -2
  13. data/lib/fitting/cover/json_schema_one_of.rb +4 -2
  14. data/lib/fitting/debug.rb +47 -0
  15. data/lib/fitting/doc/action.rb +141 -0
  16. data/lib/fitting/doc/code.rb +53 -0
  17. data/lib/fitting/doc/combination_enum.rb +110 -0
  18. data/lib/fitting/doc/combination_one_of.rb +61 -0
  19. data/lib/fitting/doc/combination_optional.rb +54 -0
  20. data/lib/fitting/doc/combination_step.rb +48 -0
  21. data/lib/fitting/doc/content_type.rb +152 -0
  22. data/lib/fitting/doc/json_schema.rb +116 -0
  23. data/lib/fitting/doc/step.rb +102 -0
  24. data/lib/fitting/doc.rb +107 -0
  25. data/lib/fitting/host.rb +37 -0
  26. data/lib/fitting/log.rb +102 -0
  27. data/lib/fitting/nocov.rb +64 -0
  28. data/lib/fitting/prefix.rb +62 -0
  29. data/lib/fitting/railtie.rb +0 -1
  30. data/lib/fitting/records/spherical/request.rb +7 -4
  31. data/lib/fitting/records/spherical/response.rb +22 -16
  32. data/lib/fitting/records/tested/request.rb +6 -1
  33. data/lib/fitting/records/tested/response.rb +6 -1
  34. data/lib/fitting/rep/html.rb +32 -0
  35. data/lib/fitting/rep.rb +24 -0
  36. data/lib/fitting/report/action.rb +9 -15
  37. data/lib/fitting/report/actions.rb +22 -33
  38. data/lib/fitting/report/combination.rb +10 -6
  39. data/lib/fitting/report/combinations.rb +9 -29
  40. data/lib/fitting/report/prefix.rb +7 -24
  41. data/lib/fitting/report/prefixes.rb +11 -25
  42. data/lib/fitting/report/response.rb +12 -22
  43. data/lib/fitting/report/responses.rb +23 -27
  44. data/lib/fitting/report/tests.rb +4 -8
  45. data/lib/fitting/skip/action.rb +44 -0
  46. data/lib/fitting/skip/api.rb +29 -0
  47. data/lib/fitting/skip.rb +21 -0
  48. data/lib/fitting/version.rb +1 -1
  49. data/lib/fitting.rb +12 -28
  50. data/lib/tasks/fitting.rake +23 -84
  51. data/lib/templates/htmlcss/bootstrap-nightshade.min.css +12 -0
  52. data/lib/templates/htmlcss/bootstrap.min.js +7 -0
  53. data/lib/templates/htmlcss/darkmode.min.js +6 -0
  54. data/lib/templates/htmlcss/fitting.html +196 -0
  55. data/lib/templates/htmlcss/jquery-3.6.0.min.js +2 -0
  56. metadata +40 -39
  57. data/lib/fitting/configuration.rb +0 -17
  58. data/lib/fitting/records/spherical/requests.rb +0 -25
  59. data/lib/fitting/storage/responses.rb +0 -21
  60. data/lib/fitting/tests.rb +0 -31
  61. data/lib/tasks/fitting_outgoing.rake +0 -91
  62. data/lib/templates/bomboniere/.gitignore +0 -21
  63. data/lib/templates/bomboniere/.tool-versions +0 -1
  64. data/lib/templates/bomboniere/README.md +0 -19
  65. data/lib/templates/bomboniere/dist/css/app.aa2bcd8a.css +0 -1
  66. data/lib/templates/bomboniere/dist/css/chunk-vendors.ec5f6c3f.css +0 -1
  67. data/lib/templates/bomboniere/dist/favicon.ico +0 -0
  68. data/lib/templates/bomboniere/dist/index.html +0 -1
  69. data/lib/templates/bomboniere/dist/js/app.e5f1a5ec.js +0 -2
  70. data/lib/templates/bomboniere/dist/js/app.e5f1a5ec.js.map +0 -1
  71. data/lib/templates/bomboniere/dist/js/chunk-vendors.0f99b670.js +0 -13
  72. data/lib/templates/bomboniere/dist/js/chunk-vendors.0f99b670.js.map +0 -1
  73. data/lib/templates/bomboniere/package-lock.json +0 -9292
  74. data/lib/templates/bomboniere/package.json +0 -27
  75. data/lib/templates/bomboniere/public/favicon.ico +0 -0
  76. data/lib/templates/bomboniere/public/index.html +0 -17
  77. data/lib/templates/bomboniere/src/App.vue +0 -102
  78. data/lib/templates/bomboniere/src/assets/logo.png +0 -0
  79. data/lib/templates/bomboniere/src/components/HelloWorld.vue +0 -204
  80. data/lib/templates/bomboniere/src/main.js +0 -10
  81. data/lib/templates/bomboniere/src/router/index.js +0 -31
  82. data/lib/templates/bomboniere/src/views/About.vue +0 -5
  83. data/lib/templates/bomboniere/src/views/Action.vue +0 -173
  84. data/lib/templates/bomboniere/src/views/Home.vue +0 -17
  85. data/lib/templates/bomboniere/vue.config.js +0 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: af3cbf8a5fa59f9d3f9e38008397af27d784ca682cbe9a25b33b17bf671cabc1
4
- data.tar.gz: fbee4660c1c6e26e85420c76ea7c924fcc9aa5b0eadea53beacead3f3c00a44e
3
+ metadata.gz: acf56757fc3fe3dca52c0ffc19624debab877fd8f9ea71ffa891ab19674c1a65
4
+ data.tar.gz: c2238a9ad8374f72075aa07b48323910bfb670ab57f95dfff6ca12dace14faaf
5
5
  SHA512:
6
- metadata.gz: afdbc7965db9bd5dcfe8267ddbb69e6bddb1229baa66a6ed723a4fac7468a35ff1ec5766b6ef1f9ae511d5e08b10f72efaa60237fb29da2c174e172ff4b3b7f6
7
- data.tar.gz: 2567a2ec55744422f59979b67cf94ff0deb32740ed69001f47c28634bf851a77df41c4a1499b9bc5f1365456cd483851dff44e9deedb0df31265386ba6470063
6
+ metadata.gz: 3e2a972498110e3c2b8ea625d0b7e73f5a127209b94e3f4373cf49a3cd38eb5c04483e876dc07bcb9b71ee3c90c7b5900e8fe31fc73ce39aec597bf70fad7e88
7
+ data.tar.gz: debb064c3590bc59c5a783d3546d4de6f75727ab4aa354d3e40f6548f7b72cc8ae9b05a1d009dab55aa0eba900a0e783979265c38dfda89b483f64c3e0f2d6ee
data/.gitignore CHANGED
@@ -9,3 +9,4 @@
9
9
  /tmp/
10
10
  .idea/
11
11
  .byebug_history
12
+ spec/fixtures/report/*
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.6.1
1
+ 2.5.5
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Change log
2
2
 
3
+ ### 4.0.0 - 2023-02-03
4
+
5
+ * features
6
+ * use fitting*.log instead of new two dirs
7
+ * output validation details
8
+ * new cover report
9
+ * smart skip
10
+ * smart nocov
11
+
3
12
  ### 3.0.2 - 2022-01-25
4
13
 
5
14
  * patch
data/README.md CHANGED
@@ -1,19 +1,90 @@
1
1
  # Fitting
2
2
 
3
3
  <img align="right" width="192" height="192"
4
- alt="Optimizt avatar: OK sign with Mona Lisa picture between the fingers"
4
+ alt="Fitting avatar: Documents with hangers"
5
5
  src="./images/logo.png">
6
6
 
7
- There are such ways of describing the API documentation as API Blueprint, Swagger and OpenAPI. And using the tests already writed for your code, you can reuse them to find out the documentation coverage.
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
- * Cool if you already have a project with tests and documentation, you can check how good everything is and fix microbags.
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
- * If are you going developing API and write documentation for it, this tool will help you document-driven development easily create high-quality write API documentation and API.
12
+ This reduces the costs of support, testers and analysts.
13
13
 
14
- * Also, if you have an undocumented API, this is an easy way to describe it.
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
- ![exmaple](images/example.png)
80
+ and cover
81
+ ![exmaple](images/b1.png)
82
+
83
+ ![exmaple](images/b2.png)
84
+
85
+ ![exmaple](images/w1.png)
86
+
87
+ ![exmaple](images/w2.png)
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
- And next to your `spec_helper.rb`:
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.save_test_data
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
- ### OpenAPI 2.0
46
- Also Swagger
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
+ ![exmaple](images/b1.png)
208
+
209
+ ![exmaple](images/b2.png)
210
+
211
+ More information on action coverage
212
+
213
+ ![exmaple2](images/w1.png)
214
+
215
+ ![exmaple2](images/w2.png)
216
+
217
+ ## Settings
218
+
219
+ ### APIs
220
+
221
+ #### type
222
+
223
+ ##### OpenAPI 2.0
224
+ Swagger
47
225
 
48
226
  ```yaml
49
- prefixes:
50
- - name: /api/v1
227
+ APIs:
228
+ - host: www.example.com
51
229
  type: openapi2
52
- schema_paths:
53
- - doc.json
230
+ path: doc/api.json
54
231
  ```
55
232
 
56
- ### OpenAPI 3.0
233
+ ##### OpenAPI 3.0
57
234
  Also OpenAPI
58
235
 
59
236
  ```yaml
60
- prefixes:
61
- - name: /api/v1
237
+ APIs:
238
+ - host: www.example.com
62
239
  type: openapi3
63
- schema_paths:
64
- - doc.yaml
240
+ path: doc/api.json
65
241
  ```
66
242
 
67
- ### API Blueprint
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
- prefixes:
81
- - name: /api/v1
262
+ APIs:
263
+ - host: www.example.com
82
264
  type: drafter
83
- schema_paths:
84
- - doc.yaml
265
+ path: doc/api.yaml
85
266
  ```
86
267
 
87
- ### Tomograph
88
-
89
- To use additional features of the pre-converted [tomograph](https://github.com/funbox/tomograph)
268
+ or
90
269
 
91
270
  ```yaml
92
- prefixes:
93
- - name: /api/v1
94
- type: tomogram
95
- schema_paths:
96
- - doc.json
271
+ APIs:
272
+ - host: www.example.com
273
+ type: crafter
274
+ path: doc/api.yaml
97
275
  ```
98
276
 
99
- ## Run
100
- Run tests first to get run artifacts
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 e rspec
284
+ bundle exec tomograph -d crafter --exclude-description doc/api.yml doc/api.json
103
285
  ```
104
286
 
105
287
  and then
106
- ```bash
107
- bundle e rake fitting:report
288
+
289
+ ```yaml
290
+ APIs:
291
+ - host: www.example.com
292
+ type: tomogram
293
+ path: doc/api.json
108
294
  ```
109
295
 
110
- Run tests by outgoing request first to get run artifacts
111
- ```bash
112
- bundle e rake fitting_out:report
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
- Console ouptut
308
+ ### SkipValidation
116
309
 
117
- ```text
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
- ![exmaple](images/example.png)
310
+ #### host
149
311
 
150
- More information on action coverage
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
- ![exmaple2](images/example2.png)
314
+ ```yaml
315
+ SkipAPIs:
316
+ - host: api.cluster.dyte.in
317
+ ```
153
318
 
154
- ## prefix name
319
+ #### prefix
155
320
 
156
- Setting the prefix name is optional. For example, you can do this:
321
+ If you want to skip a specific prefix in the host
157
322
 
158
323
  ```yaml
159
- prefixes:
160
- - type: openapi2
161
- schema_paths:
162
- - doc.json
324
+ SkipAPIs:
325
+ - host: api.cluster.dyte.in
326
+ prefix: /admin/api
163
327
  ```
164
328
 
165
- ## prefix skip
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
- prefixes:
170
- - name: /api/v1
171
- type: openapi2
172
- schema_paths:
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
- For work with WebMock outgoing request, you should set up outgoing prefixes
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
- outgoing_prefixes:
181
- - name: /api/v1
182
- type: openapi2
183
- schema_paths:
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
- You can choose location that must be teste
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
- prefixes:
193
- - type: openapi2
194
- schema_paths:
195
- - doc.json
196
- only:
197
- - POST /api/v1/users
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.6.0'
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.0'
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] = json_schema.merge(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
- combinations.push([schema.merge('oneOf' => [one_of[index]]), "oneOf.#{index}"])
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, [])