-
Notifications
You must be signed in to change notification settings - Fork 2
/
jenkins-cucumber-d3.html
507 lines (473 loc) · 20.6 KB
/
jenkins-cucumber-d3.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Cucumber Jenkins Reports</title>
<!-- Bootstrap -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<link href="css/report.css" rel="stylesheet">
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="js/report.js" charset="utf-8"></script>
<script src="js/fetch.js" charset="utf-8"></script>
<script src="js/filters.js" charset="utf-8"></script>
<style>
</style>
</head>
<body>
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<div class="navbar-brand">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sketch="http://www.bohemiancoding.com/sketch/ns" width="27px" height="32px"
viewBox="0 0 27 32" version="1.1" style="margin-top: -6px">
<!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch -->
<title>rect4005</title>
<desc>Created with Sketch.</desc>
<defs />
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="Artboard-2" sketch:type="MSArtboardGroup" transform="translate(-17.000000, -14.000000)" fill="#FFFFFF">
<g id="rect4005" sketch:type="MSLayerGroup" transform="translate(17.000000, 14.000000)">
<path style="fill:rgb(92, 184, 92);"
d="M13.4488636,0.473684211 C6.04388176,0.473684211 0.0511363636,6.64165608 0.0511363636,14.2631579 C0.0511363636,20.9734215 4.72463075,26.5489752 10.8920455,27.7894737 L10.8920455,31.7368421 C18.9103042,30.4926299 26.0099877,23.941584 26.5397727,15.3421053 C26.8586591,10.1659394 24.3511732,4.88169962 20.1221591,2.31578947 C19.8800305,2.16888059 19.6340285,2.02303798 19.3806818,1.89473684 C19.1225324,1.76400354 18.8574455,1.63658813 18.5880682,1.52631579 C18.50256,1.48950046 18.4187749,1.45610307 18.3323864,1.42105263 C18.0971125,1.33166189 17.8597121,1.23100109 17.6164773,1.15789474 C16.3054825,0.713157137 14.9040491,0.473684211 13.4488636,0.473684211 L13.4488636,0.473684211 Z M16.2102273,5.57894737 C15.7519178,5.53059208 15.2693182,5.69473684 14.9318182,6.10526316 C14.6863636,6.44210526 14.5329545,6.76842105 14.3693182,7.10526316 C13.8784091,8.28421053 14.0420455,9.54736842 14.7784091,10.4736842 C15.9238636,10.2210526 16.8954545,9.46842105 17.3863636,8.28947368 C17.55,7.95263158 17.6420455,7.52105263 17.6420455,7.18421053 C17.6931818,6.28947368 16.9740769,5.65953945 16.2102273,5.57894737 L16.2102273,5.57894737 Z M10.2528409,5.65789474 C9.50577055,5.73108556 8.79545455,6.34210526 8.79545455,7.18421053 C8.79545455,7.52105263 8.8875,7.95263158 9.05113636,8.28947368 C9.54204545,9.46842105 10.5903409,10.2210526 11.7357955,10.4736842 C12.3903409,9.54736842 12.5590909,8.28421053 12.0681818,7.10526316 C11.9045455,6.76842105 11.7511364,6.43684211 11.5056818,6.18421053 C11.1681818,5.77368421 10.7010835,5.61398029 10.2528409,5.65789474 L10.2528409,5.65789474 Z M6.23863636,9.71052632 C4.94844194,9.77868042 4.37215909,11.4473684 5.44602273,12.3157895 C5.77329545,12.5684211 6.09034091,12.7526316 6.41761364,12.9210526 C7.56306818,13.4263158 8.8875,13.2526316 9.86931818,12.5789474 C9.62386364,11.4842105 8.79034091,10.4789474 7.64488636,9.97368421 C7.23579545,9.80526316 6.90340909,9.71052632 6.49431818,9.71052632 C6.40227273,9.7 6.32464936,9.70598232 6.23863636,9.71052632 L6.23863636,9.71052632 Z M18.84375,14.8157895 C18.0942824,14.8009869 17.3352273,15.0263158 16.7215909,15.4473684 C16.9670455,16.5421053 17.8005682,17.5473684 18.9460227,18.0526316 C19.3551136,18.2210526 19.6875,18.3157895 20.0965909,18.3157895 C21.5693182,18.4 22.2903409,16.5263158 21.1448864,15.6842105 C20.8176136,15.4315789 20.5005682,15.2736842 20.1732955,15.1052632 C19.74375,14.9157895 19.2934301,14.8246712 18.84375,14.8157895 L18.84375,14.8157895 Z M7.67045455,14.8947368 C7.22077413,14.9036185 6.77045455,14.9947368 6.34090909,15.1842105 C5.93181818,15.3526316 5.61477273,15.5368421 5.36931818,15.7894737 C4.30568182,16.7157895 5.02159091,18.4789474 6.49431818,18.3947368 C6.90340909,18.3947368 7.31761364,18.3 7.64488636,18.1315789 C8.79034091,17.6263158 9.60340909,16.6210526 9.76704545,15.5263158 C9.15340909,15.1052632 8.41992218,14.8799343 7.67045455,14.8947368 L7.67045455,14.8947368 Z M11.8125,17.4736842 C10.6670455,17.7263158 9.69545455,18.4789474 9.20454545,19.6578947 C9.04090909,19.9947368 8.94886364,20.4 8.94886364,20.7368421 C8.86704545,22.1684211 10.7642045,22.9368421 11.5823864,21.8421053 C11.8278409,21.5052632 11.98125,21.1789474 12.1448864,20.8421053 C12.6357955,19.7473684 12.4670455,18.4842105 11.8125,17.4736842 L11.8125,17.4736842 Z M14.8551136,17.5526316 C14.2005682,18.4789474 14.0318182,19.7421053 14.5227273,20.9210526 C14.6863636,21.2578947 14.8397727,21.5894737 15.0852273,21.8421053 C15.9852273,22.8526316 17.8772727,22.1052632 17.7954545,20.8421053 C17.7954545,20.5052632 17.7034091,20.0736842 17.5397727,19.7368421 C17.0488636,18.5578947 16.0005682,17.8052632 14.8551136,17.5526316 L14.8551136,17.5526316 Z"
sketch:type="MSShapeGroup" />
</g>
</g>
</g>
</svg>
</div>
<div class="navbar-brand">Cucumber reports</div>
<div class="navbar-text">Jenkins home:</div>
<form class="navbar-form navbar-left">
<div class="form-group">
<input id="jenkins_url" type="text" class="form-control" placeholder="Jenkins URL...">
</div>
</form>
<div class="navbar-text">Job name:</div>
<form class="navbar-form navbar-left">
<div class="form-group">
<input id="job_name" type="text" class="form-control" placeholder="Job name...">
</div>
</form>
<div class="navbar-text">Pending tag name:</div>
<form class="navbar-form navbar-left">
<div class="form-group">
<input id="pendingTagName" type="text" class="form-control"
placeholder="Tag name to identify pending scenarios">
</div>
</form>
<div class="navbar-text">Branch name:</div>
<form class="navbar-form navbar-left">
<div class="form-group">
<input id="branchName" type="text" class="form-control" placeholder="Git branch name...">
</div>
</form>
<div class="navbar-text">Rerun job name:</div>
<form class="navbar-form navbar-left">
<div class="form-group">
<input id="rerunJobName" type="text" class="form-control"
placeholder="Name of the job to relaunch cucumber">
</div>
</form>
</div>
<div class="nav navbar-nav collapse navbar-collapse navbar-right">
<p class="navbar-text ">
Fork on <a href="https://github.com/anthonime/jenkins_cucumber_d3/" class="">GitHub</a>
</p>
</div>
</div>
</nav>
<div id="filters">
<form class="" action="#">
<div class="form-inline">
<p class="form-group" id="filters-status">
<label class="control-label">Severity:</label> <a href="javascript:void(0)" class="btn btn-link"
data-status="ALL_KOS">Only KOs</a> <a href="javascript:void(0)" class="btn btn-link"
data-status="ALL">All</a> <a href="javascript:void(0)" class="btn btn-success active"
data-status="OK">OK</a> <a href="javascript:void(0)" class="btn btn-success active"
data-status="FIXED">FIXED</a> <a href="javascript:void(0)" class="btn btn-warning active"
data-status="RECENTLY_FIXED">RECENTLY FIXED</a> <a href="javascript:void(0)"
class="btn btn-danger active" data-status="REGRESSION">REGRESSION</a> <a
href="javascript:void(0)" class="btn btn-default active" data-status="PERSISTENT_REGRESSION">PERSISTENT
REGRESSION</a> <a href="javascript:void(0)" class="btn btn-default active" data-status="KO">KO</a> <a
href="javascript:void(0)" class="btn btn-success active" data-status="DONE">DONE</a> <a
href="javascript:void(0)" class="btn btn-warning active" data-status="RECENTLY_DONE">RECENTLY
DONE</a> <a href="javascript:void(0)" class="btn btn-danger active" data-status="PENDING">PENDING</a>
<a href="javascript:void(0)" class="btn btn-default active" data-status="RANDOMNESS">RANDOMNESS</a>
</p>
</div>
<div class="form-inline">
<p class="form-group" id="filters-name">
<label class="control-label" for="fname">By name:</label> <input class="form-control" type="text"
id="fname" name="fname" placeholder="regexp" />
</p>
<p class="form-group" id="filters-tag">
<label class="control-label" for="ftag">By tag:</label> <input class="form-control" type="text"
id="ftag" name="ftag" placeholder="tag name" />
</p>
</div>
<div class="form-inline">
<p class="form-group" id="filters-category">
<label class="control-label" for="fjob">By job:</label> <select class="form-control" id="fjob"
name="fjob">
<option value="All jobs">All jobs</option>
</select> <label class="control-label" for="ffeature">By feature:</label> <select class="form-control"
id="ffeature" name="ffeature">
<option value="All features">All features</option>
</select> <label class="control-label" for="fconfig">By config:</label> <select class="form-control"
id="fconfig" name="fconfig">
<option value="All configs">All configs</option>
</select>
</p>
</div>
<!-- <div class="form-group"> -->
<!-- <label for="exampleInputEmail2">Email</label> <input type="email" -->
<!-- class="form-control" id="exampleInputEmail2" -->
<!-- placeholder="jane.doe@example.com"> -->
<!-- </div> -->
</form>
</div>
<div id="debugContainer" class="alert alert-info alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<p id="debug"></p>
<div id="progressbar" class="progress">
<div id="progress" class="progress-bar progress-bar-striped" role="progressbar" aria-valuenow="60"
aria-valuemin="0" aria-valuemax="100" style="width: 0%;"></div>
</div>
</div>
<div id="scenarios"></div>
<!-- Modal -->
<div class="modal" id="scenarioModal" tabindex="-1" role="dialog" aria-labelledby="scenarioModalTitle">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<span class="label" id="scenarioModalStatus"></span>
<h5 class="modal-title" id="scenarioModalTitle"/>
</div>
<div class="modal-body">
<div class="" id="scenarioModalAround">
<svg></svg>
</div>
<table class="table" id="scenarioModalSteps">
<tbody>
</tbody>
</table>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="js/jquery.ba-bbq.min.js" charset="utf-8"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="js/bootstrap.min.js"></script>
<script>
var fetching = false;
var remoteData = null;
var config = {
};
var currentParams = {};
//register hash change
//kind of "prepare from request" method
$(window).bind('hashchange', function(e) {
parseParams();
})
parseParams();
//kind of "prepare from request" method
function parseParams() {
var params = $.deparam.fragment();
console.log(params);
config = params;
currentParams = jQuery.extend(true, {}, params);
//append the list of KO statuses to the config
config.KO_STATUSES = ["REGRESSION",
"PERSISTENT_REGRESSION", "KO", "PENDING",
"RANDOMNESS"];
if (!config.jenkinsUrl) {
//default
config.jenkinsUrl = window.location.protocol + "//"
+ window.location.host;
}
if (!config.pendingTagName) {
config.pendingTagName = "@pending";
}
applyFilters(params);
}
function applyFilters(params) {
if (params.fstatus && !Array.isArray(params.fstatus)) {
params.fstatus = [ params.fstatus ];
}
//status
d3
.select("#filters-status")
.selectAll("a")
.classed(
"active",
function(d) {
if (!params.fstatus) {
return false;
}
var s = d3.select(this).attr(
"data-status");
return params.fstatus.indexOf(s) > -1;
});
//name
d3.select("#fname").property("value",
params.fname ? params.fname : "");
d3.select("#ftag").property("value",
params.ftag ? params.ftag : "");
d3.select("#jenkins_url").property("value",
params.jenkinsUrl ? params.jenkinsUrl : "");
d3.select("#job_name").property("value",
params.jobName ? params.jobName : "");
d3.select("#pendingTagName").property(
"value",
params.pendingTagName
? params.pendingTagName
: "");
d3.select("#branchName").property("value",
params.branchName ? params.branchName : "");
d3.select("#rerunJobName").property("value",
params.rerunJobName ? params.rerunJobName : "");
update();
}
//listens for filter changes
d3
.selectAll("#filters-status a")
.on(
"click",
function(e) {
var btn = d3.select(this);
var status = btn.attr("data-status");
var active = !btn.classed("active");
if (status == "ALL") {
currentParams.fstatus = [];
} else if (status == "ALL_KOS") {
//copy
currentParams.fstatus = config.KO_STATUSES
.slice();
} else {
if (!currentParams.fstatus) {
currentParams.fstatus = [];
}
//remove the element from the array
currentParams.fstatus = currentParams.fstatus
.filter(function(d) {
return d != status;
});
if (active) {
//add it if necessary
currentParams.fstatus
.push(status);
}
}
jQuery.bbq.pushState(currentParams);
});
d3.select("#fname").on("blur", function(e) {
var v = $("#fname").val();
currentParams.fname = v;
jQuery.bbq.pushState(currentParams);
});
d3.select("#ftag").on("blur", function(e) {
var v = $(this).val();
currentParams.ftag = v;
jQuery.bbq.pushState(currentParams);
});
d3.select("#jenkins_url").on("blur", function(e) {
var jenkinsUrl = $(this).val();
if (jenkinsUrl != currentParams.jenkinsUrl) {
currentParams.jenkinsUrl = jenkinsUrl;
remoteData = null;
}
jQuery.bbq.pushState(currentParams);
});
d3.select("#job_name").on("blur", function(e) {
var jobName = $(this).val();
if (jobName != currentParams.jobName) {
currentParams.jobName = jobName;
remoteData = null;
}
jQuery.bbq.pushState(currentParams);
});
d3.select("#pendingTagName").on("blur", function(e) {
var pendingTagName = $(this).val();
if (pendingTagName != currentParams.pendingTagName) {
currentParams.pendingTagName = pendingTagName;
}
jQuery.bbq.pushState(currentParams);
});
d3.select("#branchName").on("blur", function(e) {
var branchName = $(this).val();
if (branchName != currentParams.branchName) {
currentParams.branchName = branchName;
}
jQuery.bbq.pushState(currentParams);
});
d3.select("#rerunJobName").on("blur", function(e) {
var rerunJobName = $(this).val();
if (rerunJobName != currentParams.rerunJobName) {
currentParams.rerunJobName = rerunJobName;
}
jQuery.bbq.pushState(currentParams);
});
d3.select("#filters-category").selectAll("select").on(
"change", function(e) {
var v = this.value;
currentParams[this.name] = v;
jQuery.bbq.pushState(currentParams);
});
function showMessage(message, danger) {
d3.select("#debugContainer").classed("alert-danger",
danger ? true : false).classed("alert-info",
danger ? false : true);
d3.select("#debug").text(message);
}
function update() {
if (!remoteData && !fetching) {
fetching = true;
showMessage("Prepare to fetch", false);
// clear all
d3.select("#scenarios").selectAll("*").remove();
d3.select("#progressbar").style("display", "block");
d3.select("#progress").style("width", "0%").text(
"0%");
fetchBigJenkinsJson(
config,
function(o) {
d3.select("#progressbar").style(
"display", "none");
fetching = false;
remoteData = o;
console
.log("data fetched from jenkins "
+ remoteData);
refresh();
},
function(callbackDetails) {
if (callbackDetails.totalFetches) {
var percent = (100 * (callbackDetails.alreadyFetched / callbackDetails.totalFetches)) | 0;
d3.select("#progress").style(
"width", percent + "%")
.text(percent + "%");
}
d3
.select("#debug")
.text(
callbackDetails.message
+ (callbackDetails.totalFetches
? (" ("
+ callbackDetails.alreadyFetched
+ "/"
+ callbackDetails.totalFetches
+ ") (remaining:"
+ callbackDetails.pendingFetches + ")")
: ''));
}, function(error) {
d3.select("#progressbar").style(
"display", "none");
fetching = false;
remoteData = null;
showMessage(
"Impossible to fetch JSON from Jenkins (see console logs): "
+ error, true);
});
} else {
refresh();
}
}
function refresh() {
var result = processJson(remoteData, config);
updateFacets(result);
d3.select("#debug").text(
result.scenarios.length + " scenarios found!");
showScenarios(d3.select("#scenarios").node(),
result.scenarios, result.allScenarios);
}
function updateFacets(result) {
//status
d3.select("#filters-status").selectAll("a").text(
function(d) {
var btn = d3.select(this);
var status = btn.attr("data-status");
if (status == "ALL") {
return "All ("
+ result.allScenarios.length
+ ")";
} else if (status == "ALL_KOS") {
return "Only KOs (" + result.allKos
+ ")";
} else {
var count = result.status[status];
return status.replace(/_/g, " ") + " ("
+ count + ")";
}
});
d3.select("#filters-name").classed("has-error",
!!result.fnameerror).attr("title",
result.fnameerror);
//jobs
var jobFilter = d3.selectAll("#fjob").selectAll(
"option").data(result.jobs.entries(),
function(o, i) {
return o ? o.key : this.key;
});
jobFilter.enter().append("option");
jobFilter.text(function(d) {
return d.key + '(' + d.value + ')';
}).attr("value", function(d) {
return d.key;
});
d3.select("#fjob").property(
"value",
!currentParams.fjob
? "All jobs"
: currentParams.fjob);
//features
var featureFilter = d3.selectAll("#ffeature")
.selectAll("option").data(
result.features.entries(),
function(o, i) {
return o ? o.key : this.key;
});
featureFilter.enter().append("option");
featureFilter.text(function(d) {
return d.key + '(' + d.value + ')';
}).attr("value", function(d) {
return d.key;
});
d3.select("#ffeature").property(
"value",
!currentParams.ffeature
? "All features"
: currentParams.ffeature);
//configs
var configFilter = d3.selectAll("#fconfig").selectAll(
"option").data(result.configurations.entries(),
function(o, i) {
return o ? o.key : this.key;
});
configFilter.enter().append("option");
configFilter.text(function(d) {
return d.key + '(' + d.value + ')';
}).attr("value", function(d) {
return d.key;
});
d3.select("#fconfig").property(
"value",
!currentParams.fconfig
? "All configs"
: currentParams.fconfig);
}
</script>
</body>
</html>