1
1
/**
2
2
* @license
3
- * Copyright 2017 Google Inc.
3
+ * Copyright 2017 Google LLC
4
4
*
5
5
* Licensed under the Apache License, Version 2.0 (the "License");
6
6
* you may not use this file except in compliance with the License.
@@ -19,11 +19,14 @@ import { ExclusiveTestFunction, PendingTestFunction } from 'mocha';
19
19
20
20
import { IndexedDbPersistence } from '../../../src/local/indexeddb_persistence' ;
21
21
import { assert } from '../../../src/util/assert' ;
22
+ import { primitiveComparator } from '../../../src/util/misc' ;
22
23
import { addEqualityMatcher } from '../../util/equality_matcher' ;
23
24
24
25
import { SpecBuilder } from './spec_builder' ;
25
26
import { SpecStep } from './spec_test_runner' ;
26
27
28
+ import * as stringify from 'json-stable-stringify' ;
29
+
27
30
// Disables all other tests; useful for debugging. Multiple tests can have
28
31
// this tag and they'll all be run (but all others won't).
29
32
const EXCLUSIVE_TAG = 'exclusive' ;
@@ -242,7 +245,65 @@ export function describeSpec(
242
245
} else {
243
246
specsInThisTest = { } ;
244
247
builder ( ) ;
245
- const output = JSON . stringify ( specsInThisTest , null , 2 ) ;
248
+ // Note: We use json-stable-stringify instead of JSON.stringify() to ensure
249
+ // that the generated JSON does not produce diffs merely due to the order
250
+ // of the keys in an object changing.
251
+ const output = stringify ( specsInThisTest , {
252
+ space : 2 ,
253
+ cmp : stringifyComparator
254
+ } ) ;
246
255
writeJSONFile ( output ) ;
247
256
}
248
257
}
258
+
259
+ /**
260
+ * The key ordering overrides used when sorting keys in the generated JSON.
261
+ * If both keys being compared are present in this array then they should be
262
+ * ordered in the generated JSON in the same relative order of this array.
263
+ */
264
+ const stringifyCustomOrdering = [
265
+ 'comment' ,
266
+ 'describeName' ,
267
+ 'itName' ,
268
+ 'tags' ,
269
+ 'config' ,
270
+ 'steps'
271
+ ] ;
272
+
273
+ /**
274
+ * Assigns a "group number" to the given key in the generated JSON.
275
+ *
276
+ * Keys with lower group numbers should be ordered before keys with greater
277
+ * group numbers. Keys with equal group numbers should be ordered
278
+ * alphabetically.
279
+ */
280
+ function stringifyGroup ( s : string ) : number {
281
+ const index = stringifyCustomOrdering . indexOf ( s ) ;
282
+ if ( index >= 0 ) {
283
+ return index ;
284
+ } else if ( ! s . startsWith ( 'expected' ) ) {
285
+ return stringifyCustomOrdering . length ;
286
+ } else {
287
+ return stringifyCustomOrdering . length + 1 ;
288
+ }
289
+ }
290
+
291
+ /**
292
+ * A comparator function for stringify() that sorts keys in the JSON output.
293
+ *
294
+ * In order to produce JSON that has somewhat-intuitively-ordered keys, this
295
+ * comparator intentionally deviates from pure alphabetic ordering, placing
296
+ * some logically-first keys before others.
297
+ */
298
+ function stringifyComparator (
299
+ a : stringify . Element ,
300
+ b : stringify . Element
301
+ ) : number {
302
+ const aGroup = stringifyGroup ( a . key ) ;
303
+ const bGroup = stringifyGroup ( b . key ) ;
304
+ if ( aGroup === bGroup ) {
305
+ return primitiveComparator ( a . key , b . key ) ;
306
+ } else {
307
+ return primitiveComparator ( aGroup , bGroup ) ;
308
+ }
309
+ }
0 commit comments