@@ -3,7 +3,6 @@ import diff from '../diff.js';
3
3
import dump from '../dump.js' ;
4
4
import { prioritySymbol } from '../events.js' ;
5
5
import { window , document , navigator , StringMap } from '../globals.js' ;
6
- import { urlParams } from '../urlparams.js' ;
7
6
import version from '../version.js' ;
8
7
import fuzzysort from 'fuzzysort' ;
9
8
@@ -52,70 +51,6 @@ const DOM = {
52
51
}
53
52
} ;
54
53
55
- function getUrlConfigHtml ( config ) {
56
- const urlConfig = config . urlConfig ;
57
- let urlConfigHtml = '' ;
58
-
59
- for ( let i = 0 ; i < urlConfig . length ; i ++ ) {
60
- // Options can be either strings or objects with nonempty "id" properties
61
- let val = urlConfig [ i ] ;
62
- if ( typeof val === 'string' ) {
63
- val = {
64
- id : val ,
65
- label : val
66
- } ;
67
- }
68
- const currentVal = config [ val . id ] ;
69
-
70
- let escaped = escapeText ( val . id ) ;
71
- let escapedTooltip = escapeText ( val . tooltip ) ;
72
-
73
- if ( ! val . value || typeof val . value === 'string' ) {
74
- urlConfigHtml += '<label for="qunit-urlconfig-' + escaped
75
- + '" title="' + escapedTooltip + '"><input id="qunit-urlconfig-' + escaped
76
- + '" name="' + escaped + '" type="checkbox"'
77
- + ( val . value ? ' value="' + escapeText ( val . value ) + '"' : '' )
78
- + ( currentVal ? ' checked="checked"' : '' )
79
- + ' title="' + escapedTooltip + '" />' + escapeText ( val . label ) + '</label>' ;
80
- } else {
81
- let selection = false ;
82
- urlConfigHtml += '<label for="qunit-urlconfig-' + escaped
83
- + '" title="' + escapedTooltip + '">' + escapeText ( val . label )
84
- + ': <select id="qunit-urlconfig-' + escaped
85
- + '" name="' + escaped + '" title="' + escapedTooltip + '"><option></option>' ;
86
-
87
- if ( Array . isArray ( val . value ) ) {
88
- for ( let j = 0 ; j < val . value . length ; j ++ ) {
89
- escaped = escapeText ( val . value [ j ] ) ;
90
- urlConfigHtml += '<option value="' + escaped + '"'
91
- + ( currentVal === val . value [ j ]
92
- ? ( selection = true ) && ' selected="selected"'
93
- : '' )
94
- + '>' + escaped + '</option>' ;
95
- }
96
- } else {
97
- for ( let j in val . value ) {
98
- if ( hasOwn . call ( val . value , j ) ) {
99
- urlConfigHtml += '<option value="' + escapeText ( j ) + '"'
100
- + ( currentVal === j
101
- ? ( selection = true ) && ' selected="selected"'
102
- : '' )
103
- + '>' + escapeText ( val . value [ j ] ) + '</option>' ;
104
- }
105
- }
106
- }
107
- if ( currentVal && ! selection ) {
108
- escaped = escapeText ( currentVal ) ;
109
- urlConfigHtml += '<option value="' + escaped
110
- + '" selected="selected" disabled="disabled">' + escaped + '</option>' ;
111
- }
112
- urlConfigHtml += '</select></label>' ;
113
- }
114
- }
115
-
116
- return urlConfigHtml ;
117
- }
118
-
119
54
function stripHtml ( string ) {
120
55
// Strip tags, html entity and whitespaces
121
56
return string
@@ -131,6 +66,7 @@ export default class HtmlReporter {
131
66
*/
132
67
static init ( QUnit , options = { } ) {
133
68
return new HtmlReporter ( QUnit , extend ( options , {
69
+ urlParams : QUnit . urlParams ,
134
70
// This must use a live reference (i.e. not store a copy), because
135
71
// users may apply their settings to QUnit.config anywhere between
136
72
// loading qunit.js and the last QUnit.begin() listener finishing.
@@ -146,13 +82,14 @@ export default class HtmlReporter {
146
82
*
147
83
* @param {QUnit } QUnit
148
84
* @param {Object } options
85
+ * @param {Object } options.urlParams
149
86
* @param {Object } options.config
150
- * @param { boolean } options.config.hidepassed
151
- * @param { boolean } options.config.collapse For test result
152
- * @param { string } options.config.filter
153
- * @param { ?string } options.config.moduleId For module selector
154
- * @param { ?string } options.config.testId For test result, rerun link
155
- * @param { number } options.config.maxDepth For test result, error message
87
+ * - ` boolean` options.config.hidepassed
88
+ * - ` boolean` options.config.collapse For test result
89
+ * - ` string` options.config.filter
90
+ * - ` ?string` options.config.moduleId For module selector
91
+ * - ` ?string` options.config.testId For test result, rerun link
92
+ * - ` number` options.config.maxDepth For test result, error message
156
93
* @param {Function } options.abort
157
94
* @param {HTMLElement|undefined|null } options.element Output element
158
95
* If set to HTMLElement, the report will be written to this element.
@@ -170,6 +107,7 @@ export default class HtmlReporter {
170
107
defined : 0 ,
171
108
completed : 0
172
109
} ;
110
+ this . urlParams = options . urlParams ;
173
111
this . config = options . config ;
174
112
this . abort = options . abort ;
175
113
this . hiddenTests = [ ] ;
@@ -201,11 +139,10 @@ export default class HtmlReporter {
201
139
// potential internal errors when the HTML Reporter is disabled.
202
140
this . listen = function ( ) {
203
141
this . listen = null ;
204
- // Use prioritySignal for begin() to ensure the UI shows up
205
- // reliably to render errors from onError.
206
- // Without this, user-defined "QUnit.begin()" callbacks will end
207
- // up in the queue before ours, and if those throw an error,
208
- // then this handler will never run, thus leaving the page blank.
142
+ // It's important that we're in the callback queue before any user-defined
143
+ // "QUnit.begin()", because, if those may throw, ours wouldn't run and
144
+ // the UI would remain blank or incomplete.
145
+ // https://github.com/qunitjs/qunit/issues/1792
209
146
QUnit . begin ( this . onBegin . bind ( this ) , prioritySymbol ) ;
210
147
// Use prioritySignal for testStart() to increase availability
211
148
// of the HTML API for TESTID elements toward other event listeners.
@@ -256,7 +193,7 @@ export default class HtmlReporter {
256
193
// Check if we can apply the change without a page refresh
257
194
if ( field . name === 'hidepassed' && 'replaceState' in window . history ) {
258
195
// Set either true or undefined, which will now take precedence over
259
- // the original urlParams in makeUrl()
196
+ // the original QUnit. urlParams in makeUrl()
260
197
this . hidepassed = value ;
261
198
const tests = this . elementTests ;
262
199
@@ -298,7 +235,7 @@ export default class HtmlReporter {
298
235
* @return string
299
236
*/
300
237
makeUrl ( linkParams ) {
301
- const params = extend ( { } , urlParams ) ;
238
+ const params = extend ( { } , this . urlParams ) ;
302
239
if ( this . hidepassed !== null ) {
303
240
params . hidepassed = this . hidepassed ;
304
241
}
@@ -609,13 +546,81 @@ export default class HtmlReporter {
609
546
return moduleFilter ;
610
547
}
611
548
549
+ getUrlConfigHtml ( ) {
550
+ const urlConfig = this . config . urlConfig ;
551
+ let urlConfigHtml = '' ;
552
+
553
+ for ( let i = 0 ; i < urlConfig . length ; i ++ ) {
554
+ // Options can be either strings or objects with nonempty "id" properties
555
+ let val = urlConfig [ i ] ;
556
+ if ( typeof val === 'string' ) {
557
+ val = {
558
+ id : val ,
559
+ label : val
560
+ } ;
561
+ }
562
+
563
+ // https://github.com/qunitjs/qunit/issues/1792
564
+ const currentVal = this . config [ val . id ] !== undefined
565
+ ? this . config [ val . id ]
566
+ : this . urlParams [ val . id ] ;
567
+
568
+ let escaped = escapeText ( val . id ) ;
569
+ let escapedTooltip = escapeText ( val . tooltip ) ;
570
+
571
+ if ( ! val . value || typeof val . value === 'string' ) {
572
+ urlConfigHtml += '<label for="qunit-urlconfig-' + escaped
573
+ + '" title="' + escapedTooltip + '"><input id="qunit-urlconfig-' + escaped
574
+ + '" name="' + escaped + '" type="checkbox"'
575
+ + ( val . value ? ' value="' + escapeText ( val . value ) + '"' : '' )
576
+ + ( currentVal ? ' checked="checked"' : '' )
577
+ + ' title="' + escapedTooltip + '" />' + escapeText ( val . label ) + '</label>' ;
578
+ } else {
579
+ let selection = false ;
580
+ urlConfigHtml += '<label for="qunit-urlconfig-' + escaped
581
+ + '" title="' + escapedTooltip + '">' + escapeText ( val . label )
582
+ + ': <select id="qunit-urlconfig-' + escaped
583
+ + '" name="' + escaped + '" title="' + escapedTooltip + '"><option></option>' ;
584
+
585
+ if ( Array . isArray ( val . value ) ) {
586
+ for ( let j = 0 ; j < val . value . length ; j ++ ) {
587
+ escaped = escapeText ( val . value [ j ] ) ;
588
+ urlConfigHtml += '<option value="' + escaped + '"'
589
+ + ( currentVal === val . value [ j ]
590
+ ? ( selection = true ) && ' selected="selected"'
591
+ : '' )
592
+ + '>' + escaped + '</option>' ;
593
+ }
594
+ } else {
595
+ for ( let j in val . value ) {
596
+ if ( hasOwn . call ( val . value , j ) ) {
597
+ urlConfigHtml += '<option value="' + escapeText ( j ) + '"'
598
+ + ( currentVal === j
599
+ ? ( selection = true ) && ' selected="selected"'
600
+ : '' )
601
+ + '>' + escapeText ( val . value [ j ] ) + '</option>' ;
602
+ }
603
+ }
604
+ }
605
+ if ( currentVal && ! selection ) {
606
+ escaped = escapeText ( currentVal ) ;
607
+ urlConfigHtml += '<option value="' + escaped
608
+ + '" selected="selected" disabled="disabled">' + escaped + '</option>' ;
609
+ }
610
+ urlConfigHtml += '</select></label>' ;
611
+ }
612
+ }
613
+
614
+ return urlConfigHtml ;
615
+ }
616
+
612
617
appendToolbarControls ( beginDetails ) {
613
618
const toolbarControls = this . element . querySelector ( '#qunit-testrunner-toolbar' ) ;
614
619
if ( toolbarControls ) {
615
620
const urlConfigContainer = document . createElement ( 'span' ) ;
616
621
urlConfigContainer . id = 'qunit-toolbar-urlconfig' ;
617
622
urlConfigContainer . className = 'qunit-url-config' ;
618
- urlConfigContainer . innerHTML = getUrlConfigHtml ( this . config ) ;
623
+ urlConfigContainer . innerHTML = this . getUrlConfigHtml ( ) ;
619
624
DOM . onEach ( urlConfigContainer . getElementsByTagName ( 'input' ) , 'change' , this . onToolbarChanged . bind ( this ) ) ;
620
625
DOM . onEach ( urlConfigContainer . getElementsByTagName ( 'select' ) , 'change' , this . onToolbarChanged . bind ( this ) ) ;
621
626
0 commit comments