apipost-cli 1.0.8 → 1.0.9

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.
@@ -0,0 +1,750 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Document</title>
7
+ <style>
8
+ body {
9
+ padding: 30px 20%;
10
+ }
11
+ .apipost-logo {
12
+ width: 121px;
13
+ display: flex;
14
+ align-items: center;
15
+ height: 35px;
16
+ }
17
+ .apipost-report-wrap .apipost-report-wrap-tpl .report-info {
18
+ padding-top: 30px;
19
+ }
20
+
21
+ .apipost-report-wrap .apipost-report-wrap-tpl .report-info .report-item {
22
+ padding-bottom: 10px;
23
+ color: #666666;
24
+ font-weight: 400;
25
+ font-size: 14px;
26
+ }
27
+
28
+ .apipost-report-wrap-tpl .report-info .report-item .label {
29
+ display: inline-block;
30
+ width: 135px;
31
+ text-align: right;
32
+ }
33
+
34
+ .apipost-report-wrap-tpl .report-info .report-item .value {
35
+ }
36
+
37
+ .apipost-report-wrap-tpl .report-info .report-item .value a {
38
+ color: #ff6907;
39
+ }
40
+
41
+ .apipost-report-wrap .dashed {
42
+ height: 1px;
43
+ width: 100%;
44
+ border: 1px dashed #d8d8d8;
45
+ }
46
+
47
+ .report-title {
48
+ padding-top: 15px;
49
+ display: flex;
50
+ align-items: center;
51
+ }
52
+ .report-title img {
53
+ width: 15px;
54
+ height: 17px;
55
+ }
56
+ .report-title .title {
57
+ padding-left: 10px;
58
+ font-weight: 400;
59
+ font-size: 18px;
60
+ color: #fa7600;
61
+ }
62
+ .report-table {
63
+ margin-top: 30px;
64
+ }
65
+ .report-table table {
66
+ width: 100%;
67
+ border: 1px solid #e9e9e9;
68
+ border-collapse: collapse;
69
+ }
70
+
71
+ .report-table table th {
72
+ font-weight: 400;
73
+ font-size: 12px;
74
+ color: #666666;
75
+ background: #f4f4f4;
76
+ height: 32px;
77
+ border: 1px solid #e9e9e9;
78
+ text-align: center;
79
+ }
80
+ .report-table table td {
81
+ background: #ffffff;
82
+ height: 32px;
83
+ color: #666666;
84
+ font-weight: 400;
85
+ font-size: 12px;
86
+ border: 1px solid #e9e9e9;
87
+ text-align: center;
88
+ }
89
+
90
+ .report-info-list {
91
+ width: 100%;
92
+ display: flex;
93
+ align-items: center;
94
+ flex-wrap: wrap;
95
+ padding-top: 15px;
96
+ }
97
+
98
+ .report-info-list .report-info-item {
99
+ display: inline-flex;
100
+ align-items: center;
101
+ width: 25%;
102
+ padding-bottom: 15px;
103
+ }
104
+
105
+ .report-info-list .report-info-item img {
106
+ width: 13px;
107
+ height: 13px;
108
+ }
109
+ .report-info-list .report-info-item span {
110
+ padding-left: 10px;
111
+ font-weight: 400;
112
+ font-size: 12px;
113
+ color: #666666;
114
+ }
115
+ .test-detail {
116
+ padding-top: 15px;
117
+ padding-bottom: 15px;
118
+ }
119
+ .test-detail .toggle-arrow {
120
+ display: flex;
121
+ align-items: center;
122
+ }
123
+ .test-detail .icon-bg {
124
+ display: inline-flex;
125
+ justify-content: center;
126
+ align-items: center;
127
+ width: 16px;
128
+ height: 16px;
129
+ background: #f2f2f2;
130
+ border-radius: 3px;
131
+ }
132
+ .test-detail img {
133
+ width: 8px;
134
+ height: 4px;
135
+ }
136
+ .test-detail span.title {
137
+ font-weight: 400;
138
+ font-size: 16px;
139
+ padding-left: 10px;
140
+ color: #2b2b2b;
141
+ }
142
+
143
+ .test-detail .test-event-list {
144
+ width: 100%;
145
+ }
146
+ .test-detail .test-event-list .test-event-item {
147
+ }
148
+ .test-detail .test-event-list .test-event-item .loop {
149
+ padding: 10px 0;
150
+ font-weight: 400;
151
+ font-size: 12px;
152
+ color: #666666;
153
+ }
154
+ .test-detail .test-event-list .test-event-item .panel {
155
+ display: flex;
156
+ align-items: center;
157
+ height: 36px;
158
+ font-weight: 400;
159
+ font-size: 12px;
160
+ background: #f8f8f8;
161
+ border-radius: 5px;
162
+ }
163
+ .test-event-list .test-event-item .panel .status {
164
+ width: 16px;
165
+ height: 16px;
166
+ margin-left: 25px;
167
+ margin-right: 30px;
168
+ }
169
+ .test-event-list .test-event-item .panel .index {
170
+ padding-right: 30px;
171
+ color: #666666;
172
+ }
173
+
174
+ .test-event-list .test-event-item .panel .method {
175
+ padding-right: 30px;
176
+ color: #26cea4;
177
+ }
178
+ .test-event-list .test-event-item .panel .name {
179
+ padding-right: 30px;
180
+ color: #666666;
181
+ }
182
+ .test-event-list .test-event-item .panel .link a {
183
+ text-decoration: none;
184
+ }
185
+
186
+ .test-event-list .test-event-item .item-info {
187
+ width: 100%;
188
+ display: flex;
189
+ align-items: center;
190
+ padding: 10px;
191
+ font-weight: 400;
192
+ font-size: 12px;
193
+ color: #666666;
194
+ }
195
+ .test-event-list .test-event-item .item-info span {
196
+ display: inline-block;
197
+ width: 25%;
198
+ }
199
+
200
+ .test-event-list .test-event-item .assert-info {
201
+ display: flex;
202
+ width: 100%;
203
+ font-weight: 400;
204
+ font-size: 12px;
205
+ }
206
+ .test-event-list .test-event-item .assert-info .assert-label {
207
+ min-width: 60px;
208
+ }
209
+ .test-event-item .assert-info .response-panel {
210
+ width: 100%;
211
+ }
212
+ .test-event-item .assert-info .response-panel img {
213
+ width: 12px;
214
+ height: 12px;
215
+ margin: 0 10px;
216
+ }
217
+ .test-event-item .assert-info .response-panel .success,
218
+ .test-event-item .assert-info .response-panel .error {
219
+ display: flex;
220
+ align-items: center;
221
+ width: 100%;
222
+ height: 34px;
223
+ }
224
+ .test-event-item .assert-info .response-panel .success {
225
+ background: #f1faf3;
226
+ color: #2ba58f;
227
+ }
228
+
229
+ .test-event-item .assert-info .response-panel .error {
230
+ background: #ffedee;
231
+ color: #ff4c4c;
232
+ }
233
+ .show {
234
+ display: block;
235
+ }
236
+ .hide {
237
+ display: none;
238
+ }
239
+ .chart-wrap {
240
+ display: flex;
241
+ align-items: center;
242
+ padding-top: 15px;
243
+ }
244
+
245
+ .chart-wrap .api {
246
+ display: flex;
247
+ align-items: center;
248
+ width: 50%;
249
+ }
250
+ .chart-wrap .api .api-des {
251
+ display: flex;
252
+ flex-direction: column;
253
+ padding-left: 50px;
254
+ }
255
+
256
+ .chart-wrap .api .api-des .api-title {
257
+ padding-bottom: 15px;
258
+ font-weight: 600;
259
+ font-size: 16px;
260
+ color: #666666;
261
+ }
262
+
263
+ .chart-wrap .api .api-des .api-label {
264
+ padding-bottom: 10px;
265
+ font-weight: 400;
266
+ font-size: 12px;
267
+ color: #666666;
268
+ }
269
+ #api-pie,
270
+ #assert-pie {
271
+ width: 80px;
272
+ height: 80px;
273
+ }
274
+ </style>
275
+ <script src="https://img.cdn.apipost.cn/cdn/test-report/js/template-web.js"></script>
276
+ <script src="https://img.cdn.apipost.cn/cdn/test-report/js/echarts.min.js"></script>
277
+ </head>
278
+ <body>
279
+ <div id="app">
280
+ <img class="apipost-logo" src="https://img.cdn.apipost.cn/new_www/index_img/apipost-logo_or.svg" />
281
+ <div class="apipost-report-wrap"></div>
282
+ </div>
283
+
284
+ <script type="text/html" id="tpl">
285
+ <div class="apipost-report-wrap-tpl">
286
+ <h1>{{value.report_name}}</h1>
287
+ <div class="report-info">
288
+ <div class="report-item">
289
+ <span class="label">测试用例/测试套件:</span>
290
+ <span class="value">{{value.report_name}}</span>
291
+ </div>
292
+ <div class="report-item">
293
+ <span class="label">测试时间:</span>
294
+ <span class="value">{{value.start_time}}</span>
295
+ </div>
296
+ <div class="report-item">
297
+ <span class="label">测试工具:</span>
298
+ <span class="value"><a href="https://www.apipost.cn/download.html">apipost客户端</a></span>
299
+ </div>
300
+ </div>
301
+ <div class="dashed"></div>
302
+
303
+ <div class="report-title">
304
+ <img src="https://img.cdn.apipost.cn/cdn/test-report/img/doc.png" alt="" />
305
+ <span class="title">测试结果</span>
306
+ </div>
307
+ <div class="chart-wrap">
308
+ <div class="api">
309
+ <div id="api-pie"></div>
310
+ <div class="api-des">
311
+ <span class="api-title">接口</span>
312
+ <span class="api-label"
313
+ >接口通过率:{{formatRate({ passed: value?.http?.passed, failure:
314
+ value?.http?.failure }, value?.http?.passed)}}</span
315
+ >
316
+ <span class="api-label"
317
+ >接口失败率:{{formatRate({ passed: value?.http?.passed, failure:
318
+ value?.http?.failure }, value?.http?.failure)}}</span
319
+ >
320
+ </div>
321
+ </div>
322
+ <div class="api">
323
+ <div id="assert-pie"></div>
324
+ <div class="api-des">
325
+ <span class="api-title">断言</span>
326
+ <span class="api-label"
327
+ >断言通过率:{{formatRate({ passed: value?.assert?.passed, failure:
328
+ value?.assert?.failure }, value?.assert?.passed)}}</span
329
+ >
330
+ <span class="api-label"
331
+ >断言失败率:{{formatRate({ passed: value?.assert?.passed, failure:
332
+ value?.assert?.failure }, value?.assert?.failure)}}</span
333
+ >
334
+ </div>
335
+ </div>
336
+ </div>
337
+ <div class="report-table">
338
+ <table>
339
+ <thead>
340
+ <tr>
341
+ <th></th>
342
+ <th>请求总数</th>
343
+ <th>通过</th>
344
+ <th>失败</th>
345
+ </tr>
346
+ </thead>
347
+ <tbody>
348
+ <tr>
349
+ <td>接口</td>
350
+ <td>{{value.http.failure + value.http.passed}}</td>
351
+ <td>{{value.http.passed}}</td>
352
+ <td>{{value.http.failure}}</td>
353
+ </tr>
354
+ <tr>
355
+ <td>断言</td>
356
+ <td>{{value.assert.failure + value.assert.passed}}</td>
357
+ <td>{{value.assert.passed}}</td>
358
+ <td>{{value.assert.failure}}</td>
359
+ </tr>
360
+ </tbody>
361
+ </table>
362
+ </div>
363
+
364
+ <div class="report-info-list">
365
+ <div class="report-info-item">
366
+ <span>开始时间 : {{value.start_time}}</span>
367
+ </div>
368
+ <div class="report-info-item">
369
+ <span>结束时间 : {{value.end_time}}</span>
370
+ </div>
371
+ <div class="report-info-item">
372
+ <span>总耗时 : {{value.long_time}}</span>
373
+ </div>
374
+ <div class="report-info-item">
375
+ <span>总响应时间 : {{value.total_response_time}}ms</span>
376
+ </div>
377
+ <div class="report-info-item">
378
+ <span>平均响应时间 : {{value.average_response_time}}ms</span>
379
+ </div>
380
+ <div class="report-info-item">
381
+ <span>总响应数据大小 : {{value.total_received_data}}kb</span>
382
+ </div>
383
+ <div class="report-info-item">
384
+ <span>未测接口 : {{value.ignore_count}}</span>
385
+ </div>
386
+ </div>
387
+
388
+ <div class="dashed"></div>
389
+ {{if value.type === 'single'}}
390
+ <div class="report-title">
391
+ <img src="https://img.cdn.apipost.cn/cdn/test-report/img/doc.png" alt="" />
392
+ <span class="title">测试情况</span>
393
+ </div>
394
+
395
+ <div class="action-wrap">
396
+ <div class="test-detail failed">
397
+ <div class="toggle-arrow">
398
+ <span class="icon-bg">
399
+ <img src="https://img.cdn.apipost.cn/cdn/test-report/img/arrow.png" class="arrow" alt="" />
400
+ </span>
401
+ <span class="title">失败情况</span>
402
+ </div>
403
+ <div class="test-event-list show">
404
+ {{each value.logList.filter(item => item.http_error === 1 || item.assert_error === 1) item
405
+ key}}
406
+ <div data-text="{{key}}" id="{{key}}" class="test-event-item">
407
+ <div class="panel">
408
+ <img class="status" src="https://img.cdn.apipost.cn/cdn/test-report/img/error.png" alt="" />
409
+ <div class="index">{{key + 1}}</div>
410
+ <div class="method">{{item?.request?.method}}</div>
411
+ <span class="name">{{item?.request?.name}}</span>
412
+ <div class="link">
413
+ <a href="{{item?.request?.url}}">{{item?.request?.url}}</a>
414
+ </div>
415
+ </div>
416
+ <div class="item-info">
417
+ <span>请求状况:{{(item?.http_error === 1) ? '失败' : '成功'}}</span>
418
+ <span>状态码:{{item?.response?.data?.response?.code}}</span>
419
+ <span>响应时间:{{item?.response?.data?.response?.responseTime}}ms</span>
420
+ <span>响应数据大小:{{item?.response?.data?.response?.responseSize}}kb</span>
421
+ </div>
422
+ {{if item?.assert && item?.assert.length > 0}}
423
+ <div class="assert-info">
424
+ <span class="assert-label">断言:</span>
425
+ <div class="response-panel">
426
+ {{each item?.assert assert cKey}} {{if assert.status === 'error'}}
427
+ <div class="error">
428
+ <img src="https://img.cdn.apipost.cn/cdn/test-report/img/error.png" alt="" />
429
+ <span>{{assert?.expect}}</span>
430
+ </div>
431
+ {{/if}} {{if assert.status !== 'error'}}
432
+ <div class="success">
433
+ <img src="https://img.cdn.apipost.cn/cdn/test-report/img/success.png" alt="" />
434
+ <span>{{assert?.expect}}</span>
435
+ </div>
436
+ {{/if}} {{/each}}
437
+ </div>
438
+ </div>
439
+ {{/if}}
440
+ </div>
441
+ {{/each}}
442
+ </div>
443
+ </div>
444
+ <div class="dashed"></div>
445
+ <div class="test-detail success">
446
+ <div class="toggle-arrow">
447
+ <span class="icon-bg">
448
+ <img src="https://img.cdn.apipost.cn/cdn/test-report/img/arrow.png" alt="" />
449
+ </span>
450
+ <span class="title">测试详情</span>
451
+ </div>
452
+ <div class="test-event-list show">
453
+ {{each value.logList item key}}
454
+ <div data-text="{{key}}" id="{{key}}" class="test-event-item">
455
+ <div class="panel">
456
+ {{if item.http_error === -1 && item.assert_error === -1}}
457
+ <img class="status" src="https://img.cdn.apipost.cn/cdn/test-report/img/success.png" alt="" />
458
+ {{/if}} {{if item.http_error === 1 || item.assert_error === 1}}
459
+ <img class="status" src="https://img.cdn.apipost.cn/cdn/test-report/img/error.png" alt="" />
460
+ {{/if}}
461
+
462
+ <div class="index">{{key + 1}}</div>
463
+ <div class="method">{{item?.request?.method}}</div>
464
+ <span class="name">{{item?.request?.name}}</span>
465
+ <div class="link">
466
+ <a href="{{item?.request?.url}}">{{item?.request?.url}}</a>
467
+ </div>
468
+ </div>
469
+ <div class="item-info">
470
+ <span>请求状况:{{(item?.http_error === 1) ? '失败' : '成功'}}</span>
471
+ <span>状态码:{{item?.response?.data?.response?.code}}</span>
472
+ <span>响应时间:{{item?.response?.data?.response?.responseTime}}ms</span>
473
+ <span>响应数据大小:{{item?.response?.data?.response?.responseSize}}kb</span>
474
+ </div>
475
+ {{if item?.assert && item?.assert.length > 0}}
476
+ <div class="assert-info">
477
+ <span class="assert-label">断言:</span>
478
+ <div class="response-panel">
479
+ {{each item?.assert assert cKey}}
480
+ {{if assert.status === 'error'}}
481
+ <div class="error">
482
+ <img src="https://img.cdn.apipost.cn/cdn/test-report/img/error.png" alt="" />
483
+ <span>{{assert?.expect}}</span>
484
+ </div>
485
+ {{/if}}
486
+ {{if assert.status !== 'error'}}
487
+ <div class="success">
488
+ <img src="https://img.cdn.apipost.cn/cdn/test-report/img/success.png" alt="" />
489
+ <span>{{assert?.expect}}</span>
490
+ </div>
491
+ {{/if}} {{/each}}
492
+ </div>
493
+ </div>
494
+ {{/if}}
495
+ </div>
496
+ {{/each}}
497
+ </div>
498
+ </div>
499
+ </div>
500
+ {{/if}}
501
+ {{if value.type === 'combined'}}
502
+ {{each value.children child childKey}}
503
+ <div data-text="{{childKey}}" id="{{childKey}}">
504
+ <div class="report-title">
505
+ <img src="https://img.cdn.apipost.cn/cdn/test-report/img/doc.png" alt="" />
506
+ <span class="title">{{child?.report_name}}_测试情况</span>
507
+ </div>
508
+
509
+ <div class="action-wrap">
510
+ <div class="test-detail failed">
511
+ <div class="toggle-arrow">
512
+ <span class="icon-bg">
513
+ <img src="https://img.cdn.apipost.cn/cdn/test-report/img/arrow.png" class="arrow" alt="" />
514
+ </span>
515
+ <span class="title">失败情况</span>
516
+ </div>
517
+ <div class="test-event-list show">
518
+ {{each value.logList.filter(item => (item.http_error === 1 || item.assert_error === 1) && item.test_id === child.test_id) item
519
+ key}}
520
+ <div data-text="{{key}}" id="{{key}}" class="test-event-item">
521
+ <div class="panel">
522
+ <img class="status" src="https://img.cdn.apipost.cn/cdn/test-report/img/error.png" alt="" />
523
+ <div class="index">{{key + 1}}</div>
524
+ <div class="method">{{item?.request?.method}}</div>
525
+ <span class="name">{{item?.request?.name}}</span>
526
+ <div class="link">
527
+ <a href="{{item?.request?.url}}">{{item?.request?.url}}</a>
528
+ </div>
529
+ </div>
530
+ <div class="item-info">
531
+ <span>请求状况:{{(item?.http_error === 1) ? '失败' : '成功'}}</span>
532
+ <span>状态码:{{item?.response?.data?.response?.code}}</span>
533
+ <span>响应时间:{{item?.response?.data?.response?.responseTime}}ms</span>
534
+ <span>响应数据大小:{{item?.response?.data?.response?.responseSize}}kb</span>
535
+ </div>
536
+ {{if item?.assert && item?.assert.length > 0}}
537
+ <div class="assert-info">
538
+ <span class="assert-label">断言:</span>
539
+ <div class="response-panel">
540
+ {{each item?.assert assert cKey}} {{if assert.status === 'error'}}
541
+ <div class="error">
542
+ <img src="https://img.cdn.apipost.cn/cdn/test-report/img/error.png" alt="" />
543
+ <span>{{assert?.expect}}</span>
544
+ </div>
545
+ {{/if}} {{if assert.status !== 'error'}}
546
+ <div class="success">
547
+ <img src="https://img.cdn.apipost.cn/cdn/test-report/img/success.png" alt="" />
548
+ <span>{{assert?.expect}}</span>
549
+ </div>
550
+ {{/if}} {{/each}}
551
+ </div>
552
+ </div>
553
+ {{/if}}
554
+ </div>
555
+ {{/each}}
556
+ </div>
557
+ </div>
558
+ <div class="dashed"></div>
559
+ <div class="test-detail success">
560
+ <div class="toggle-arrow">
561
+ <span class="icon-bg">
562
+ <img src="https://img.cdn.apipost.cn/cdn/test-report/img/arrow.png" alt="" />
563
+ </span>
564
+ <span class="title">测试详情</span>
565
+ </div>
566
+ <div class="test-event-list show">
567
+ {{each value.logList.filter(item => item.test_id === child.test_id) item key}}
568
+ <div data-text="{{key}}" id="{{key}}" class="test-event-item">
569
+ <div class="panel">
570
+ {{if item.http_error === -1 && item.assert_error === -1}}
571
+ <img class="status" src="https://img.cdn.apipost.cn/cdn/test-report/img/success.png" alt="" />
572
+ {{/if}} {{if item.http_error === 1 || item.assert_error === 1}}
573
+ <img class="status" src="https://img.cdn.apipost.cn/cdn/test-report/img/error.png" alt="" />
574
+ {{/if}}
575
+
576
+ <div class="index">{{key + 1}}</div>
577
+ <div class="method">{{item?.request?.method}}</div>
578
+ <span class="name">{{item?.request?.name}}</span>
579
+ <div class="link">
580
+ <a href="{{item?.request?.url}}">{{item?.request?.url}}</a>
581
+ </div>
582
+ </div>
583
+ <div class="item-info">
584
+ <span>请求状况:{{(item?.http_error === 1) ? '失败' : '成功'}}</span>
585
+ <span>状态码:{{item?.response?.data?.response?.code}}</span>
586
+ <span>响应时间:{{item?.response?.data?.response?.responseTime}}ms</span>
587
+ <span>响应数据大小:{{item?.response?.data?.response?.responseSize}}kb</span>
588
+ </div>
589
+ {{if item?.assert && item?.assert.length > 0}}
590
+ <div class="assert-info">
591
+ <span class="assert-label">断言:</span>
592
+ <div class="response-panel">
593
+ {{each item?.assert assert cKey}}
594
+ {{if assert.status === 'error'}}
595
+ <div class="error">
596
+ <img src="https://img.cdn.apipost.cn/cdn/test-report/img/error.png" alt="" />
597
+ <span>{{assert?.expect}}</span>
598
+ </div>
599
+ {{/if}}
600
+ {{if assert.status !== 'error'}}
601
+ <div class="success">
602
+ <img src="https://img.cdn.apipost.cn/cdn/test-report/img/success.png" alt="" />
603
+ <span>{{assert?.expect}}</span>
604
+ </div>
605
+ {{/if}} {{/each}}
606
+ </div>
607
+ </div>
608
+ {{/if}}
609
+ </div>
610
+ {{/each}}
611
+ </div>
612
+ </div>
613
+ </div>
614
+ </div>
615
+ {{/each}}
616
+ {{/if}}
617
+ </div>
618
+ </script>
619
+
620
+ <script>
621
+ template.defaults.imports.formatRate = function (info, per) {
622
+ if (
623
+ typeof info.passed !== 'number' ||
624
+ typeof info.failure !== 'number' ||
625
+ info?.passed + info?.failure === 0
626
+ ) {
627
+ return '0%';
628
+ }
629
+ if (typeof per === 'number') {
630
+ return ((per / (info?.passed + info?.failure)) * 100).toFixed(2) + '%';
631
+ }
632
+ return '-';
633
+ };
634
+
635
+ const data = {"combined_id":"0","report_id":"","report_name":"新建测试用例测试报告","env_id":"6e734f0b-3d77-4e95-896a-f20f58fa1889","env_name":"dev","env_pre_url":"http://cc.apipost.cc:6002/proxy","env_pre_urls":{"default":"http://cc.apipost.cc:6002/proxy"},"user":{"role":2,"nick_name":"wenjin","email":null,"portrait":"https://img.cdn.apipost.cn/user/default_profile_photo/Vector-6.png","is_manager":1,"uuid":"UL4XWF681351","is_super_admin":1,"project_id":"e337b75f-93eb-4263-82ca-2b9832ffbd02","id":"e337b75f-93eb-4263-82ca-2b9832ffbd02/UL4XWF681351"},"total_count":1,"total_effective_count":1,"ignore_count":0,"total_received_data":0.07,"total_response_time":23,"average_response_time":23,"http_errors":[],"assert_errors":[],"ignore_errors":[],"http":{"passed":1,"passed_per":1,"failure":0,"failure_per":0},"assert":{"passed":0,"passed_per":0,"failure":0,"failure_per":0},"start_time":"2024-01-06 15:16:30","end_time":"2024-01-06 15:16:30","long_time":"0.04 秒","children":[],"type":"single","test_id":"85c4b152-85d3-4c00-895a-b361541d1349","event_status":{"406cc32a-691a-436a-8833-99af0b34e5fa":"passed"},"test_events":[{"event_id":"406cc32a-691a-436a-8833-99af0b34e5fa","parent_event_id":"0","data":{"parent_id":"f2af0203-f760-4fb6-b7e5-8f80c1b50e58","target_id":"bfa94803-79db-4442-916d-41c2dc5e9fab","name":"测试路径1","method":"POST","url":"/test","request":{"url":"/test","description":"","auth":{"type":"noauth","kv":{"key":"","value":""},"bearer":{"key":""},"basic":{"username":"","password":""},"digest":{"username":"","password":"","realm":"","nonce":"","algorithm":"","qop":"","nc":"","cnonce":"","opaque":""},"hawk":{"authId":"","authKey":"","algorithm":"","user":"","nonce":"","extraData":"","app":"","delegation":"","timestamp":"","includePayloadHash":-1},"awsv4":{"accessKey":"","secretKey":"","region":"","service":"","sessionToken":"","addAuthDataToQuery":-1},"ntlm":{"username":"","password":"","domain":"","workstation":"","disableRetryRequest":1},"edgegrid":{"accessToken":"","clientToken":"","clientSecret":"","nonce":"","timestamp":"","baseURi":"","headersToSign":""},"oauth1":{"consumerKey":"","consumerSecret":"","signatureMethod":"","addEmptyParamsToSign":-1,"includeBodyHash":-1,"addParamsToHeader":-1,"realm":"","version":"1.0","nonce":"","timestamp":"","verifier":"","callback":"","tokenSecret":"","token":""}},"body":{"mode":"none","parameter":[],"raw":"","raw_para":[],"raw_schema":{"type":"object"},"binary":null},"event":{"pre_script":"","test":""},"header":{"parameter":[]},"query":{"parameter":[]},"cookie":{"parameter":[]},"resful":{"parameter":[]},"protocol":"http/1.1"}},"enabled":1,"project_id":"e337b75f-93eb-4263-82ca-2b9832ffbd02","sort":1,"test_id":"85c4b152-85d3-4c00-895a-b361541d1349","type":"api","report_id":"","runtime_status":"passed"}],"logList":[{"test_id":"85c4b152-85d3-4c00-895a-b361541d1349","parent_id":"0","event_id":"406cc32a-691a-436a-8833-99af0b34e5fa","iteration_id":"8e87157f-e03b-44f1-9ae8-71374ece56dd","type":"api","target_id":"bfa94803-79db-4442-916d-41c2dc5e9fab","request":{"parent_id":"f2af0203-f760-4fb6-b7e5-8f80c1b50e58","target_id":"bfa94803-79db-4442-916d-41c2dc5e9fab","name":"测试路径1","method":"POST","url":"http://cc.apipost.cc:6002/proxy/test","request":{"url":"http://cc.apipost.cc:6002/proxy/test","description":"","auth":{"type":"noauth","kv":{"key":"","value":""},"bearer":{"key":""},"basic":{"username":"","password":""},"digest":{"username":"","password":"","realm":"","nonce":"","algorithm":"","qop":"","nc":"","cnonce":"","opaque":""},"hawk":{"authId":"","authKey":"","algorithm":"","user":"","nonce":"","extraData":"","app":"","delegation":"","timestamp":"","includePayloadHash":-1},"awsv4":{"accessKey":"","secretKey":"","region":"","service":"","sessionToken":"","addAuthDataToQuery":-1},"ntlm":{"username":"","password":"","domain":"","workstation":"","disableRetryRequest":1},"edgegrid":{"accessToken":"","clientToken":"","clientSecret":"","nonce":"","timestamp":"","baseURi":"","headersToSign":""},"oauth1":{"consumerKey":"","consumerSecret":"","signatureMethod":"","addEmptyParamsToSign":-1,"includeBodyHash":-1,"addParamsToHeader":-1,"realm":"","version":"1.0","nonce":"","timestamp":"","verifier":"","callback":"","tokenSecret":"","token":""}},"body":{"mode":"none","parameter":[],"raw":"","raw_para":[],"raw_schema":{"type":"object"},"binary":null},"event":{"pre_script":"","test":""},"header":{"parameter":[]},"query":{"parameter":[]},"cookie":{"parameter":[]},"resful":{"parameter":[]},"protocol":"http/1.1"}},"response":{"status":"success","message":"success","data":{"request":{"url":"http://cc.apipost.cc:6002/proxy/test","uri":{"slashes":true,"protocol":"http:","hash":"","query":"","pathname":"/proxy/test","auth":"","host":"cc.apipost.cc:6002","port":"6002","hostname":"cc.apipost.cc","password":"","username":"","origin":"http://cc.apipost.cc:6002","href":"http://cc.apipost.cc:6002/proxy/test"},"method":"POST","timeout":0,"contentType":"none","header":[{"key":"User-Agent","value":"PostmanRuntime-ApipostRuntime/1.1.0"},{"key":"Cache-Control","value":"no-cache"},{"key":"Accept-Encoding","value":"gzip, deflate, br"},{"key":"Content-Length","value":0}],"proxy":null,"request_headers":{"User-Agent":"PostmanRuntime-ApipostRuntime/1.1.0","Cache-Control":"no-cache","Accept-Encoding":"gzip, deflate, br","Content-Length":0},"request_bodys":"","body":{"mode":"none"}},"response":{"target_id":"bfa94803-79db-4442-916d-41c2dc5e9fab","responseTime":23,"responseSize":0.07,"resposneAt":"15:16:30","netWork":{"agent":"Desktop-Agent","address":{"local":{"address":"192.168.0.20","port":58072},"remote":{"address":"114.242.33.198","family":"IPv4","port":6002}}},"status":"OK","code":200,"timingPhases":{"wait":0.8354170024394989,"dns":11.288708001375198,"tcp":4.6827090084552765,"firstByte":5.858790993690491,"download":0.4039590060710907,"total":23.069584012031555},"headers":{"Content-Type":"application/json","Date":"Sat, 06 Jan 2024 07:16:30 GMT","Content-Length":"69","Connection":"close"},"fitForShow":"Monaco","resMime":{"ext":"json","mime":"application/json"},"stream":{"type":"Buffer","data":[120,156,171,86,242,77,45,201,200,79,81,178,82,10,240,15,14,81,210,81,10,72,44,201,0,242,244,11,138,242,43,42,245,75,82,139,75,64,130,249,197,37,46,137,37,137,64,9,32,175,176,52,181,168,50,32,177,40,49,183,88,201,170,186,182,22,0,247,129,22,135]},"filename":"response_bfa94803-79db-4442-916d-41c2dc5e9fab.json"}}},"http_error":-1,"assert":[],"datetime":"2024-01-06 15:16:30","assert_error":-1}]};
636
+ console.log(data, 'data')
637
+
638
+ document.title = data?.report_name || '';
639
+ const _docContentHtml = template('tpl', {
640
+ value: data,
641
+ });
642
+ const oWrap = document.querySelector('.apipost-report-wrap');
643
+ oWrap.innerHTML = _docContentHtml;
644
+
645
+ (() => {
646
+ const oApp = document.querySelector('#app'),
647
+ oTestReport = oApp.querySelector('.apipost-report-wrap'),
648
+ oActionWrap = oTestReport.querySelector('.action-wrap'),
649
+ oTestDetailFailed = oActionWrap.querySelector('.test-detail.failed'),
650
+ oTestDetailSuccess = oActionWrap.querySelector('.test-detail.success');
651
+
652
+ const oTestDetails = document.querySelectorAll('.test-detail');
653
+ let curIndex = 0;
654
+
655
+ const init = () => {
656
+ bindEvent();
657
+ initPie();
658
+ };
659
+
660
+ function bindEvent() {
661
+ Array.from(oTestDetails).forEach(item => {
662
+ item.addEventListener('click', handleToggle.bind(null, item), false)
663
+ })
664
+ }
665
+
666
+ function handleToggle(detailWrap, e) {
667
+ const clickClassName = e.target.className;
668
+ const oTestList = detailWrap.querySelector('.test-event-list');
669
+
670
+ if (oTestList && ['title', 'toggle-arrow', 'arrow'].includes(clickClassName)) {
671
+ const className = oTestList.className;
672
+ if (className.includes('show')) {
673
+ oTestList.className = 'test-event-list hide';
674
+ } else {
675
+ oTestList.className = 'test-event-list show';
676
+ }
677
+ }
678
+ }
679
+
680
+ const computedInfo = (info) => {
681
+ if (info?.passed == 0 && info?.failure == 0) {
682
+ return [{ value: info?.passed, name: '接口通过率' }];
683
+ }
684
+ return [
685
+ { value: info?.passed, name: '接口通过率' },
686
+ { value: info?.failure, name: '接口失败率' },
687
+ ];
688
+ };
689
+
690
+ const getOption = (info, color) => {
691
+ return {
692
+ color: color || ['#26CEA4', 'red'],
693
+ series: [
694
+ {
695
+ name: 'Access From',
696
+ type: 'pie',
697
+ radius: ['50%', '80%'],
698
+ avoidLabelOverlap: false,
699
+ label: {
700
+ show: false,
701
+ position: 'center',
702
+ },
703
+ emphasis: {
704
+ label: {
705
+ show: true,
706
+ fontSize: 5,
707
+ },
708
+ },
709
+ labelLine: {
710
+ show: false,
711
+ },
712
+ data: computedInfo(info),
713
+ },
714
+ ],
715
+ };
716
+ };
717
+ function initPie() {
718
+ const apiPieWrap = document.querySelector('#api-pie');
719
+ const assertPieWrap = document.querySelector('#assert-pie');
720
+
721
+ if (apiPieWrap) {
722
+ const pie = echarts.init(apiPieWrap);
723
+ const options = getOption(
724
+ {
725
+ passed: data?.http?.passed,
726
+ failure: data?.http?.failure,
727
+ },
728
+ ['#26CEA4', '#E45252']
729
+ );
730
+ pie && pie.setOption(options);
731
+ }
732
+ if (assertPieWrap) {
733
+ const pie = echarts.init(assertPieWrap);
734
+ const options = getOption(
735
+ {
736
+ passed: data?.assert?.passed,
737
+ failure: data?.assert?.failure,
738
+ },
739
+ ['#26CEA4', '#E45252']
740
+ );
741
+ pie && pie.setOption(options);
742
+ }
743
+ }
744
+
745
+ init();
746
+ })();
747
+ </script>
748
+ </body>
749
+ </html>
750
+
package/bin/cli.js CHANGED
@@ -74,6 +74,18 @@ const runTestEvents = async (data, options) => {
74
74
  }
75
75
  }
76
76
 
77
+ //fix apipost-runtime@126 修复数option env 不为空时,pre_url 重命名为 env_pre_url
78
+ if (_.has(newOptions, 'option.env.pre_url') && (!_.has(newOptions, 'option.env.env_pre_url'))) {
79
+ _.set(newOptions, 'option.env.env_pre_url', _.get(newOptions, 'option.env.pre_url'));
80
+ }
81
+ if (_.has(newOptions, 'option.env.name') && (!_.has(newOptions, 'option.env.env_name'))) {
82
+ _.set(newOptions, 'option.env.env_name', _.get(newOptions, 'option.env.name'));
83
+ }
84
+ if (_.has(newOptions, 'option.env.pre_urls') && (!_.has(newOptions, 'option.env.env_pre_urls'))) {
85
+ _.set(newOptions, 'option.env.env_pre_urls', _.get(newOptions, 'option.env.pre_urls'));
86
+ }
87
+
88
+
77
89
  // 外部数据文件
78
90
  if (cliOption.iterationData != '') {
79
91
  try {
@@ -112,9 +124,11 @@ const runTestEvents = async (data, options) => {
112
124
  passphrase: cliOption.sslClientPassphrase
113
125
  })
114
126
  .value();
127
+
115
128
 
116
129
  const myCollection = new Collection(newOptions?.test_events, { iterationCount: newOptions?.option?.iterationCount, sleep: newOptions?.option.sleep });
117
130
  const runTimeEvent = new Runtime(emitRuntimeEvent, false);
131
+
118
132
  await runTimeEvent.run(myCollection.definition, newOptions?.option);
119
133
 
120
134
  // 处理文件过大错误问题
@@ -153,7 +167,9 @@ const parseCommandString = async (url, options) => {
153
167
  fs.appendFileSync(path.join(homedir, 'apipost-cli-error.log'), `${formattedTime}\t请执行正确的url链接 [${url}]\n`);
154
168
  return;
155
169
  }
170
+
156
171
  let response = await nodeFetch(url);
172
+
157
173
  let runData = await response.json();
158
174
 
159
175
  if (_.has(runData, 'code')) {
@@ -205,7 +221,6 @@ const bindEvent = (program) => {
205
221
  program.on('-h --help', () => {
206
222
  console.log('如何使用 Apipost');
207
223
  });
208
-
209
224
  program.parse();
210
225
  }
211
226
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apipost-cli",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "Apipost 命令行运行工具",
5
5
  "main": "bin/cli.js",
6
6
  "scripts": {