@@ -165,6 +165,9 @@ struct State {
165
165
/// How to actually format output, either node.js or browser-specific
166
166
/// implementation.
167
167
formatter : Box < dyn Formatter > ,
168
+
169
+ /// Timing the total duration.
170
+ timer : Option < Timer > ,
168
171
}
169
172
170
173
/// Failure reasons.
@@ -252,6 +255,18 @@ extern "C" {
252
255
// General-purpose conversion into a `String`.
253
256
#[ wasm_bindgen( js_name = String ) ]
254
257
fn stringify ( val : & JsValue ) -> String ;
258
+
259
+ type Global ;
260
+
261
+ #[ wasm_bindgen( method, getter) ]
262
+ fn performance ( this : & Global ) -> JsValue ;
263
+
264
+ /// Type for the [`Performance` object](https://developer.mozilla.org/en-US/docs/Web/API/Performance).
265
+ type Performance ;
266
+
267
+ /// Binding to [`Performance.now()`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now).
268
+ #[ wasm_bindgen( method) ]
269
+ fn now ( this : & Performance ) -> f64 ;
255
270
}
256
271
257
272
/// Internal implementation detail of the `console_log!` macro.
@@ -328,6 +343,8 @@ impl Context {
328
343
detect:: Runtime :: Worker => Box :: new ( worker:: Worker :: new ( ) ) as Box < dyn Formatter > ,
329
344
} ;
330
345
346
+ let timer = Timer :: new ( ) ;
347
+
331
348
Context {
332
349
state : Rc :: new ( State {
333
350
filter : Default :: default ( ) ,
@@ -340,6 +357,7 @@ impl Context {
340
357
running : Default :: default ( ) ,
341
358
succeeded : Default :: default ( ) ,
342
359
formatter,
360
+ timer,
343
361
} ) ,
344
362
}
345
363
}
@@ -373,7 +391,6 @@ impl Context {
373
391
self . state
374
392
. formatter
375
393
. writeln ( & format ! ( "running {} {}" , tests. len( ) , noun) ) ;
376
- self . state . formatter . writeln ( "" ) ;
377
394
378
395
// Execute all our test functions through their Wasm shims (unclear how
379
396
// to pass native function pointers around here). Each test will
@@ -523,6 +540,8 @@ impl Context {
523
540
should_panic : Option < Option < & ' static str > > ,
524
541
ignore : Option < Option < & ' static str > > ,
525
542
) {
543
+ // Split away
544
+ let name = name. split_once ( "::" ) . unwrap ( ) . 1 ;
526
545
// If our test is filtered out, record that it was filtered and move
527
546
// on, nothing to do here.
528
547
let filter = self . state . filter . borrow ( ) ;
@@ -677,18 +696,25 @@ impl State {
677
696
self . formatter . writeln ( & format ! ( " {}" , test. name) ) ;
678
697
}
679
698
}
699
+ let finished_in = if let Some ( timer) = & self . timer {
700
+ format ! ( "; finished in {:.2?}s" , timer. elapsed( ) )
701
+ } else {
702
+ String :: new ( )
703
+ } ;
680
704
self . formatter . writeln ( "" ) ;
681
705
self . formatter . writeln ( & format ! (
682
706
"test result: {}. \
683
707
{} passed; \
684
708
{} failed; \
685
709
{} ignored; \
686
- {} filtered out\n ",
710
+ {} filtered out\
711
+ {}\n ",
687
712
if failures. len( ) == 0 { "ok" } else { "FAILED" } ,
688
713
self . succeeded. get( ) ,
689
714
failures. len( ) ,
690
715
self . ignored. get( ) ,
691
716
self . filtered. get( ) ,
717
+ finished_in,
692
718
) ) ;
693
719
}
694
720
@@ -813,3 +839,27 @@ fn tab(s: &str) -> String {
813
839
}
814
840
result
815
841
}
842
+
843
+ struct Timer {
844
+ performance : Performance ,
845
+ started : f64 ,
846
+ }
847
+
848
+ impl Timer {
849
+ fn new ( ) -> Option < Self > {
850
+ let global: Global = js_sys:: global ( ) . unchecked_into ( ) ;
851
+ let performance = global. performance ( ) ;
852
+ ( !performance. is_undefined ( ) ) . then ( || {
853
+ let performance: Performance = performance. unchecked_into ( ) ;
854
+ let started = performance. now ( ) ;
855
+ Self {
856
+ performance,
857
+ started,
858
+ }
859
+ } )
860
+ }
861
+
862
+ fn elapsed ( & self ) -> f64 {
863
+ ( self . performance . now ( ) - self . started ) / 1000.
864
+ }
865
+ }
0 commit comments