Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 3ea29e3

Browse filesBrowse files
committed
Merge pull request revel#725 from anonx/testrunner/response
Testrunner: show response info
2 parents d324f65 + ef0775f commit 3ea29e3
Copy full SHA for 3ea29e3

File tree

Expand file treeCollapse file tree

8 files changed

+283
-5824
lines changed
Filter options
Expand file treeCollapse file tree

8 files changed

+283
-5824
lines changed

‎modules/testrunner/app/controllers/testrunner.go

Copy file name to clipboardExpand all lines: modules/testrunner/app/controllers/testrunner.go
+34-2Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ package controllers
22

33
import (
44
"bytes"
5+
"encoding/json"
56
"fmt"
6-
"github.com/revel/revel"
77
"html"
88
"html/template"
99
"reflect"
1010
"strings"
11+
12+
"github.com/revel/revel"
1113
)
1214

1315
type TestRunner struct {
@@ -64,9 +66,16 @@ func (c TestRunner) Run(suite, test string) revel.Result {
6466
if error == nil {
6567
result.ErrorHtml = template.HTML(html.EscapeString(fmt.Sprint(err)))
6668
} else {
69+
testSuite := v.Elem().FieldByName("TestSuite").Interface().(revel.TestSuite)
70+
res := formatResponse(testSuite)
71+
6772
var buffer bytes.Buffer
6873
tmpl, _ := revel.MainTemplateLoader.Template("TestRunner/FailureDetail.html")
69-
tmpl.Render(&buffer, error)
74+
tmpl.Render(&buffer, map[string]interface{}{
75+
"error": error,
76+
"response": res,
77+
"postfix": suite + "_" + test,
78+
})
7079
result.ErrorSummary = errorSummary(error)
7180
result.ErrorHtml = template.HTML(buffer.String())
7281
}
@@ -150,3 +159,26 @@ func errorSummary(error *revel.Error) string {
150159
}
151160
return message
152161
}
162+
163+
// formatResponse gets *revel.TestSuite as input parameter and
164+
// transform response related info into a readable format.
165+
func formatResponse(t revel.TestSuite) map[string]string {
166+
if t.Response == nil {
167+
return map[string]string{}
168+
}
169+
170+
resp, err := json.MarshalIndent(t.Response, "", " ")
171+
if err != nil {
172+
// It is unlikely to ever happen.
173+
revel.ERROR.Println(err)
174+
}
175+
176+
// Remove extra new line symbols so they do not take too much space on a result page.
177+
body := strings.Replace(string(t.ResponseBody), "\n\n\n", "\n", -1)
178+
body = strings.Replace(body, "\r\n\r\n\r\n", "\r\n", -1)
179+
180+
return map[string]string{
181+
"Headers": string(resp),
182+
"Body": body,
183+
}
184+
}
+45-9Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,45 @@
1-
<b>{{.Description}}</b><br>
2-
In {{.Path}}
3-
{{if .Line}}
4-
(around {{if .Line}}line {{.Line}}{{end}}{{if .Column}} column {{.Column}}{{end}})
5-
{{end}}:
6-
{{range .ContextSource}}{{if .IsError}}<code>{{.Source}}</code>{{end}}{{end}}<br>
7-
<a style="cursor:pointer;"
8-
onclick="x=this.nextSibling.style;if(!x.display)x.display='none';else x.display=''">
9-
Show Stack</a><pre style="display:none;">{{.Stack}}</pre>
1+
<div class="panel panel-default">
2+
<div class="panel-heading">
3+
<b>{{.error.Description}}</b>
4+
</div>
5+
<div class="panel-body">
6+
7+
<ul class="nav nav-tabs" role="tablist">
8+
<li class="active"><a href="#error_{{.postfix}}" role="tab" data-toggle="tab">Error</a></li>
9+
<li><a href="#stack_{{.postfix}}" role="tab" data-toggle="tab">Stack</a></li>
10+
{{if .response}}
11+
<li><a href="#headers_{{.postfix}}" role="tab" data-toggle="tab">Headers</a></li>
12+
<li><a href="#body_{{.postfix}}" role="tab" data-toggle="tab">Response Body</a></li>
13+
{{end}}
14+
</ul>
15+
16+
<div class="tab-content" id="result_{{.postfix}}">
17+
<div class="tab-pane active" id="error_{{.postfix}}">
18+
<div class="panel panel-danger">
19+
<div class="panel-heading">
20+
In {{.error.Path}}{{if .error.Line}} (around {{if .error.Line}}line {{.error.Line}}{{end}}{{if .error.Column}} column {{.error.Column}}{{end}}){{end}}:
21+
</div>
22+
<div class="panel-body">
23+
{{range .error.ContextSource}}
24+
{{if .IsError}}
25+
<pre><code class="go">{{.Source}}</code></pre>
26+
{{end}}
27+
{{end}}
28+
</div>
29+
</div>
30+
</div>
31+
<div class="tab-pane" id="stack_{{.postfix}}">
32+
<pre><code class="bash">{{.error.Stack}}</code></pre>
33+
</div>
34+
{{if .response}}
35+
<div class="tab-pane" id="headers_{{.postfix}}">
36+
<pre><code class="json">{{.response.Headers}}</code></pre>
37+
</div>
38+
<div class="tab-pane" id="body_{{.postfix}}">
39+
<pre><code class="html">{{.response.Body}}</code></pre>
40+
</div>
41+
{{end}}
42+
</div>
43+
44+
</div>
45+
</div>

‎modules/testrunner/app/views/TestRunner/Index.html

Copy file name to clipboardExpand all lines: modules/testrunner/app/views/TestRunner/Index.html
+65-39Lines changed: 65 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,29 @@
33
<head>
44
<title>Revel Test Runner</title>
55
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
6-
<link href="{{url `Root`}}/@tests/public/css/bootstrap.css" type="text/css" rel="stylesheet"></link>
6+
<link href="{{url `Root`}}/@tests/public/css/bootstrap.min.css" type="text/css" rel="stylesheet"></link>
7+
<link href="{{url `Root`}}/@tests/public/css/github.css" type="text/css" rel="stylesheet"></link>
78
<script src="{{url `Root`}}/@tests/public/js/jquery-1.9.1.min.js" type="text/javascript"></script>
9+
<script src="{{url `Root`}}/@tests/public/js/bootstrap.min.js" type="text/javascript"></script>
10+
<script src="{{url `Root`}}/@tests/public/js/highlight.pack.js" type="text/javascript"></script>
811
<style>
912
header { padding:20px 0; background-color:#ADD8E6 }
1013
.passed td { background-color: #90EE90 !important; }
1114
.failed td { background-color: #FFB6C1 !important; }
1215
.tests td.name, .tests td.result { padding-top: 13px; }
1316
pre { font-size:10px; white-space: pre; }
17+
.name { width: 25%; }
18+
.w100 { width: 100%; }
1419
</style>
1520
</head>
1621
<body>
1722
<header>
1823
<div class="container">
19-
<table><tr><td>
24+
<table class="w100"><tr><td>
2025
<h1>Test Runner</h1>
2126
<p class="lead">Run all of your application's tests from here.</p>
22-
</td><td style="padding-left:150px;">
23-
<button class="btn btn-large" all-tests="">Run All Tests</button>
27+
</td><td style="padding-left:150px;" class="text-right">
28+
<button class="btn btn-lg btn-success" all-tests="">Run All Tests</button>
2429
</td></tr></table>
2530
</div>
2631
</header>
@@ -34,51 +39,72 @@ <h1>Test Runner</h1>
3439
<td class="name">{{.Name}}</td>
3540
<td class="result">
3641
</td>
37-
<td><button test="{{.Name}}" class="btn">Run</button></td>
42+
<td class="text-right"><button test="{{.Name}}" class="btn btn-success">Run</button></td>
3843
</tr>
3944
{{end}}
4045
</table>
4146
{{end}}
4247
</div>
4348

44-
<script>
45-
var running = 0;
49+
<script>
50+
var buttons = [];
51+
var running;
4652

47-
$("button[test]").click(function() {
48-
var button = $(this).addClass("disabled").text("Running");
49-
running += 1;
50-
runTest(button);
51-
});
53+
$("button[test]").click(function() {
54+
var button = $(this).addClass("disabled").text("Running");
55+
addToQueue(button);
56+
});
5257

53-
$("button[all-tests]").click(function() {
54-
var button = $(this).addClass("disabled").text("Running");
55-
$("button[test]").click();
56-
});
58+
$("button[all-tests]").click(function() {
59+
var button = $(this).addClass("disabled").text("Running");
60+
$("button[test]").click();
61+
});
5762

58-
function runTest(button) {
59-
var suite = button.parents("table").attr("suite");
60-
var test = button.attr("test");
61-
var row = button.parents("tr");
62-
var resultCell = row.children(".result");
63-
$.ajax({
64-
dataType: "json",
65-
url: "{{url `Root`}}/@tests/"+suite+"/"+test,
66-
async: false,
67-
success: function(result) {
68-
row.attr("class", result.Passed ? "passed" : "failed");
69-
if (result.Passed) {
70-
resultCell.html("");
71-
} else {
72-
resultCell.html(result.ErrorHtml);
73-
}
74-
button.removeClass("disabled").text("Run");
75-
running -= 1;
76-
if (running == 0) {
77-
$("button[all-tests]").removeClass("disabled").text("Run All Tests");
63+
function addToQueue(button) {
64+
buttons.push(button);
65+
if (!running) {
66+
running = true;
67+
nextTest();
68+
}
69+
}
70+
71+
function nextTest() {
72+
if (buttons.length == 0) {
73+
running = false;
74+
} else {
75+
var next = buttons.shift();
76+
runTest(next);
77+
}
78+
}
79+
80+
function runTest(button) {
81+
var suite = button.parents("table").attr("suite");
82+
var test = button.attr("test");
83+
var row = button.parents("tr");
84+
var resultCell = row.children(".result");
85+
$.ajax({
86+
dataType: "json",
87+
url: "{{url `Root`}}/@tests/"+suite+"/"+test,
88+
success: function(result) {
89+
row.attr("class", result.Passed ? "passed" : "failed");
90+
if (result.Passed) {
91+
resultCell.html("");
92+
} else {
93+
resultCell.html(result.ErrorHtml);
94+
95+
$("#result_" + suite + "_" + test + " pre code").each(function(i, block) {
96+
hljs.highlightBlock(block);
97+
});
98+
}
99+
button.removeClass("disabled").text("Run");
100+
if (buttons.length == 0) {
101+
$("button[all-tests]").removeClass("disabled").text("Run All Tests");
102+
}
103+
nextTest();
78104
}
79-
}});
80-
}
81-
</script>
105+
});
106+
}
107+
</script>
82108

83109
</body>
84110
</html>

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.