@@ -20,24 +20,30 @@ angular.scenario.ui.Html = function(context) {
2020 ) ;
2121} ;
2222
23+ /**
24+ * The severity order of an error.
25+ */
26+ angular . scenario . ui . Html . SEVERITY = [ 'pending' , 'success' , 'failure' , 'error' ] ;
27+
2328/**
2429 * Adds a new spec to the UI.
2530 *
2631 * @param {Object } The spec object created by the Describe object.
2732 */
2833angular . scenario . ui . Html . prototype . addSpec = function ( spec ) {
34+ var self = this ;
2935 var specContext = this . findContext ( spec . definition ) ;
3036 specContext . find ( '> .tests' ) . append (
3137 '<li class="status-pending test-it"></li>'
3238 ) ;
3339 specContext = specContext . find ( '> .tests li:last' ) ;
34- return new angular . scenario . ui . Html . Spec ( specContext , spec . name ,
35- angular . bind ( this , function ( status ) {
36- status = this . context . find ( '#status-legend .status-' + status ) ;
40+ return new angular . scenario . ui . Html . Spec ( specContext , spec . name ,
41+ function ( status ) {
42+ status = self . context . find ( '#status-legend .status-' + status ) ;
3743 var parts = status . text ( ) . split ( ' ' ) ;
3844 var value = ( parts [ 0 ] * 1 ) + 1 ;
3945 status . text ( value + ' ' + parts [ 1 ] ) ;
40- } )
46+ }
4147 ) ;
4248} ;
4349
@@ -47,27 +53,28 @@ angular.scenario.ui.Html.prototype.addSpec = function(spec) {
4753 * @param {Object } The definition created by the Describe object.
4854 */
4955angular . scenario . ui . Html . prototype . findContext = function ( definition ) {
56+ var self = this ;
5057 var path = [ ] ;
5158 var currentContext = this . context . find ( '#specs' ) ;
5259 var currentDefinition = definition ;
5360 while ( currentDefinition && currentDefinition . name ) {
5461 path . unshift ( currentDefinition ) ;
5562 currentDefinition = currentDefinition . parent ;
5663 }
57- angular . foreach ( path , angular . bind ( this , function ( defn ) {
64+ angular . foreach ( path , function ( defn ) {
5865 var id = 'describe-' + defn . id ;
59- if ( ! this . context . find ( '#' + id ) . length ) {
66+ if ( ! self . context . find ( '#' + id ) . length ) {
6067 currentContext . find ( '> .test-children' ) . append (
6168 '<div class="test-describe" id="' + id + '">' +
6269 ' <h2></h2>' +
6370 ' <div class="test-children"></div>' +
6471 ' <ul class="tests"></ul>' +
6572 '</div>'
6673 ) ;
67- this . context . find ( '#' + id ) . find ( '> h2' ) . text ( 'describe: ' + defn . name ) ;
74+ self . context . find ( '#' + id ) . find ( '> h2' ) . text ( 'describe: ' + defn . name ) ;
6875 }
69- currentContext = this . context . find ( '#' + id ) ;
70- } ) ) ;
76+ currentContext = self . context . find ( '#' + id ) ;
77+ } ) ;
7178 return this . context . find ( '#describe-' + definition . id ) ;
7279} ;
7380
@@ -90,23 +97,45 @@ angular.scenario.ui.Html.Spec = function(context, name, doneFn) {
9097 ' <span class="test-name"></span>' +
9198 ' </p>' +
9299 '</div>' +
93- '<ol class="test-actions">' +
94- '</ol>'
100+ '<div class="scrollpane">' +
101+ ' <ol class="test-actions">' +
102+ ' </ol>' +
103+ '</div>'
95104 ) ;
105+ context . find ( '> .test-info' ) . click ( function ( ) {
106+ var scrollpane = context . find ( '> .scrollpane' ) ;
107+ var actions = scrollpane . find ( '> .test-actions' ) ;
108+ var name = context . find ( '> .test-info .test-name' ) ;
109+ if ( actions . find ( ':visible' ) . length ) {
110+ actions . hide ( ) ;
111+ name . removeClass ( 'open' ) . addClass ( 'closed' ) ;
112+ } else {
113+ actions . show ( ) ;
114+ scrollpane . attr ( 'scrollTop' , scrollpane . attr ( 'scrollHeight' ) ) ;
115+ name . removeClass ( 'closed' ) . addClass ( 'open' ) ;
116+ }
117+ } ) ;
96118 context . find ( '> .test-info .test-name' ) . text ( 'it ' + name ) ;
97119} ;
98120
99121/**
100122 * Adds a new Step to this spec and returns it.
101123 *
102124 * @param {String } The name of the step.
125+ * @param {Function } function() that returns a string with the file/line number
126+ * where the step was added from.
103127 */
104- angular . scenario . ui . Html . Spec . prototype . addStep = function ( name ) {
105- this . context . find ( '> .test-actions' ) . append ( '<li class="status-pending"></li>' ) ;
106- var stepContext = this . context . find ( '> .test-actions li:last' ) ;
128+ angular . scenario . ui . Html . Spec . prototype . addStep = function ( name , location ) {
129+ this . context . find ( '> .scrollpane . test-actions' ) . append ( '<li class="status-pending"></li>' ) ;
130+ var stepContext = this . context . find ( '> .scrollpane . test-actions li:last' ) ;
107131 var self = this ;
108- return new angular . scenario . ui . Html . Step ( stepContext , name , function ( status ) {
109- self . status = status ;
132+ return new angular . scenario . ui . Html . Step ( stepContext , name , location , function ( status ) {
133+ if ( indexOf ( angular . scenario . ui . Html . SEVERITY , status ) >
134+ indexOf ( angular . scenario . ui . Html . SEVERITY , self . status ) ) {
135+ self . status = status ;
136+ }
137+ var scrollpane = self . context . find ( '> .scrollpane' ) ;
138+ scrollpane . attr ( 'scrollTop' , scrollpane . attr ( 'scrollHeight' ) ) ;
110139 } ) ;
111140} ;
112141
@@ -118,22 +147,19 @@ angular.scenario.ui.Html.Spec.prototype.complete = function() {
118147 var endTime = new Date ( ) . getTime ( ) ;
119148 this . context . find ( "> .test-info .timer-result" ) .
120149 text ( ( endTime - this . startTime ) + "ms" ) ;
150+ if ( this . status === 'success' ) {
151+ this . context . find ( '> .test-info .test-name' ) . addClass ( 'closed' ) ;
152+ this . context . find ( '> .scrollpane .test-actions' ) . hide ( ) ;
153+ }
121154} ;
122155
123156/**
124157 * Finishes the spec, possibly with an error.
125158 *
126159 * @param {Object } An optional error
127160 */
128- angular . scenario . ui . Html . Spec . prototype . finish = function ( error ) {
161+ angular . scenario . ui . Html . Spec . prototype . finish = function ( ) {
129162 this . complete ( ) ;
130- if ( error ) {
131- if ( this . status !== 'failure' ) {
132- this . status = 'error' ;
133- }
134- this . context . append ( '<pre></pre>' ) ;
135- this . context . find ( 'pre:first' ) . text ( error . stack || error . toString ( ) ) ;
136- }
137163 this . context . addClass ( 'status-' + this . status ) ;
138164 this . doneFn ( this . status ) ;
139165} ;
@@ -144,36 +170,50 @@ angular.scenario.ui.Html.Spec.prototype.finish = function(error) {
144170 * @param {Object } Required error
145171 */
146172angular . scenario . ui . Html . Spec . prototype . error = function ( error ) {
147- this . finish ( error ) ;
173+ this . status = 'error' ;
174+ this . context . append ( '<pre></pre>' ) ;
175+ this . context . find ( '> pre' ) . text ( formatException ( error ) ) ;
176+ this . finish ( ) ;
148177} ;
149178
150179/**
151180 * A single step inside an it block (or a before/after function).
152181 *
153182 * @param {Object } The jQuery object for the context of the step.
154183 * @param {String } The name of the step.
184+ * @param {Function } function() that returns file/line number of step.
155185 * @param {Function } Callback function(status) to call when complete.
156186 */
157- angular . scenario . ui . Html . Step = function ( context , name , doneFn ) {
187+ angular . scenario . ui . Html . Step = function ( context , name , location , doneFn ) {
158188 this . context = context ;
159189 this . name = name ;
190+ this . location = location ;
160191 this . startTime = new Date ( ) . getTime ( ) ;
161192 this . doneFn = doneFn ;
162193 context . append (
163- '<span class="timer-result"></span >' +
164- '<span class="test-title"></span >'
194+ '<div class="timer-result"></div >' +
195+ '<div class="test-title"></div >'
165196 ) ;
166197 context . find ( '> .test-title' ) . text ( name ) ;
198+ var scrollpane = context . parents ( '.scrollpane' ) ;
199+ scrollpane . attr ( 'scrollTop' , scrollpane . attr ( 'scrollHeight' ) ) ;
167200} ;
168201
169202/**
170203 * Completes the step and sets the timer value.
171204 */
172- angular . scenario . ui . Html . Step . prototype . complete = function ( ) {
205+ angular . scenario . ui . Html . Step . prototype . complete = function ( error ) {
173206 this . context . removeClass ( 'status-pending' ) ;
174207 var endTime = new Date ( ) . getTime ( ) ;
175208 this . context . find ( ".timer-result" ) .
176209 text ( ( endTime - this . startTime ) + "ms" ) ;
210+ if ( error ) {
211+ if ( ! this . context . find ( '.test-title pre' ) . length ) {
212+ this . context . find ( '.test-title' ) . append ( '<pre></pre>' ) ;
213+ }
214+ var message = _jQuery . trim ( this . location ( ) + '\n\n' + formatException ( error ) ) ;
215+ this . context . find ( '.test-title pre' ) . text ( message ) ;
216+ }
177217} ;
178218
179219/**
@@ -182,7 +222,7 @@ angular.scenario.ui.Html.Step.prototype.complete = function() {
182222 * @param {Object } An optional error
183223 */
184224angular . scenario . ui . Html . Step . prototype . finish = function ( error ) {
185- this . complete ( ) ;
225+ this . complete ( error ) ;
186226 if ( error ) {
187227 this . context . addClass ( 'status-failure' ) ;
188228 this . doneFn ( 'failure' ) ;
@@ -198,7 +238,7 @@ angular.scenario.ui.Html.Step.prototype.finish = function(error) {
198238 * @param {Object } Required error
199239 */
200240angular . scenario . ui . Html . Step . prototype . error = function ( error ) {
201- this . complete ( ) ;
241+ this . complete ( error ) ;
202242 this . context . addClass ( 'status-error' ) ;
203243 this . doneFn ( 'error' ) ;
204244} ;
0 commit comments