qunitx 0.3.0 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,10 +1,14 @@
1
1
  {
2
2
  "name": "qunitx",
3
3
  "type": "module",
4
- "version": "0.3.0",
4
+ "version": "0.3.3",
5
5
  "description": "Experimental improvements, suggestions for qunit CLI",
6
6
  "author": "Izel Nakri",
7
7
  "license": "MIT",
8
+ "keywords": [
9
+ "qunit",
10
+ "qunit-plugin"
11
+ ],
8
12
  "main": "index.js",
9
13
  "bin": {
10
14
  "qunitx": "cli.js"
@@ -32,30 +36,30 @@
32
36
  "dependencies": {
33
37
  "@nanoexpress/middleware-static-serve": "^1.0.3",
34
38
  "cheerio": "^1.0.0-rc.10",
35
- "chokidar": "^3.5.2",
36
- "esbuild": "^0.13.2",
39
+ "chokidar": "^3.5.3",
40
+ "esbuild": "^0.13.15",
37
41
  "js-yaml": "^4.1.0",
38
42
  "kleur": "^4.1.4",
39
- "nanoexpress": "5.1.0",
40
- "picomatch": "^2.2.3",
41
- "puppeteer": "10.4.0",
42
- "recursive-lookup": "1.0.0"
43
+ "nanoexpress": "5.2.2",
44
+ "picomatch": "^2.3.1",
45
+ "puppeteer": "13.4.1",
46
+ "recursive-lookup": "1.0.0",
47
+ "ts-node": "^10.6.0"
43
48
  },
44
49
  "devDependencies": {
45
- "auto-changelog": "^2.3.0",
46
- "axios": "^0.21.4",
50
+ "auto-changelog": "^2.4.0",
51
+ "axios": "^0.26.0",
47
52
  "cors": "^2.8.5",
48
- "express": "^4.17.1",
49
- "mocha": "^9.1.1",
50
- "prettier": "^2.4.1",
51
- "qunit": "^2.17.0",
52
- "qunitx": "^0.2.4",
53
- "release-it": "^14.11.6",
54
- "ts-node": "^10.2.1",
53
+ "express": "^4.17.3",
54
+ "mocha": "^9.2.1",
55
+ "prettier": "^2.5.1",
56
+ "qunit": "^2.18.0",
57
+ "qunitx": "^0.3.2",
58
+ "release-it": "^14.12.5",
55
59
  "uuid": "^8.3.2"
56
60
  },
57
61
  "volta": {
58
- "node": "16.5.0"
62
+ "node": "16.13.0"
59
63
  },
60
64
  "prettier": {
61
65
  "printWidth": 100,
package/vendor/qunit.css CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * QUnit 2.17.2
2
+ * QUnit 2.18.0
3
3
  * https://qunitjs.com/
4
4
  *
5
5
  * Copyright OpenJS Foundation and other contributors
package/vendor/qunit.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * QUnit 2.17.2
2
+ * QUnit 2.18.0
3
3
  * https://qunitjs.com/
4
4
  *
5
5
  * Copyright OpenJS Foundation and other contributors
@@ -349,25 +349,57 @@
349
349
  return array.indexOf(elem) !== -1;
350
350
  }
351
351
  /**
352
- * Makes a clone of an object using only Array or Object as base,
353
- * and copies over the own enumerable properties.
352
+ * Recursively clone an object into a plain array or object, taking only the
353
+ * own enumerable properties.
354
354
  *
355
- * @param {Object} obj
356
- * @return {Object} New object with only the own properties (recursively).
355
+ * @param {any} obj
356
+ * @param {bool} [allowArray=true]
357
+ * @return {Object|Array}
357
358
  */
358
359
 
359
360
  function objectValues(obj) {
360
- var vals = is("array", obj) ? [] : {};
361
+ var allowArray = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
362
+ var vals = allowArray && is("array", obj) ? [] : {};
361
363
 
362
364
  for (var key in obj) {
363
365
  if (hasOwn$1.call(obj, key)) {
364
366
  var val = obj[key];
365
- vals[key] = val === Object(val) ? objectValues(val) : val;
367
+ vals[key] = val === Object(val) ? objectValues(val, allowArray) : val;
366
368
  }
367
369
  }
368
370
 
369
371
  return vals;
370
372
  }
373
+ /**
374
+ * Recursively clone an object into a plain object, taking only the
375
+ * subset of own enumerable properties that exist a given model.
376
+ *
377
+ * @param {any} obj
378
+ * @param {any} model
379
+ * @return {Object}
380
+ */
381
+
382
+ function objectValuesSubset(obj, model) {
383
+ // Return primitive values unchanged to avoid false positives or confusing
384
+ // results from assert.propContains().
385
+ // E.g. an actual null or false wrongly equaling an empty object,
386
+ // or an actual string being reported as object not matching a partial object.
387
+ if (obj !== Object(obj)) {
388
+ return obj;
389
+ } // Unlike objectValues(), subset arrays to a plain objects as well.
390
+ // This enables subsetting [20, 30] with {1: 30}.
391
+
392
+
393
+ var subset = {};
394
+
395
+ for (var key in model) {
396
+ if (hasOwn$1.call(model, key) && hasOwn$1.call(obj, key)) {
397
+ subset[key] = objectValuesSubset(obj[key], model[key]);
398
+ }
399
+ }
400
+
401
+ return subset;
402
+ }
371
403
  function extend(a, b, undefOnly) {
372
404
  for (var prop in b) {
373
405
  if (hasOwn$1.call(b, prop)) {
@@ -808,6 +840,38 @@
808
840
  // Set of all modules.
809
841
  modules: [],
810
842
  // The first unnamed module
843
+ //
844
+ // By being defined as the intial value for currentModule, it is the
845
+ // receptacle and implied parent for any global tests. It is as if we
846
+ // called `QUnit.module( "" );` before any other tests were defined.
847
+ //
848
+ // If we reach begin() and no tests were put in it, we dequeue it as if it
849
+ // never existed, and in that case never expose it to the events and
850
+ // callbacks API.
851
+ //
852
+ // When global tests are defined, then this unnamed module will execute
853
+ // as any other module, including moduleStart/moduleDone events etc.
854
+ //
855
+ // Since this module isn't explicitly created by the user, they have no
856
+ // access to add hooks for it. The hooks object is defined to comply
857
+ // with internal expectations of test.js, but they will be empty.
858
+ // To apply hooks, place tests explicitly in a QUnit.module(), and use
859
+ // its hooks accordingly.
860
+ //
861
+ // For global hooks that apply to all tests and all modules, use QUnit.hooks.
862
+ //
863
+ // NOTE: This is *not* a "global module". It is not an ancestor of all modules
864
+ // and tests. It is merely the parent for any tests defined globally,
865
+ // before the first QUnit.module(). As such, the events for this unnamed
866
+ // module will fire as normal, right after its last test, and *not* at
867
+ // the end of the test run.
868
+ //
869
+ // NOTE: This also should probably also not become a global module, unless
870
+ // we keep it out of the public API. For example, it would likely not
871
+ // improve the user interface and plugin behaviour if all modules became
872
+ // wrapped between the start and end events of this module, and thus
873
+ // needlessly add indentation, indirection, or other visible noise.
874
+ // Unit tests for the callbacks API would detect that as a regression.
811
875
  currentModule: {
812
876
  name: "",
813
877
  tests: [],
@@ -821,6 +885,9 @@
821
885
  after: []
822
886
  }
823
887
  },
888
+ // Exposed to make resets easier
889
+ // Ref https://github.com/qunitjs/qunit/pull/1598
890
+ globalHooks: {},
824
891
  callbacks: {},
825
892
  // The storage module to use for reordering tests
826
893
  storage: localSessionStorage
@@ -1119,8 +1186,8 @@
1119
1186
 
1120
1187
  this.name = name;
1121
1188
  this.fullName = parentSuite ? parentSuite.fullName.concat(name) : []; // When an "error" event is emitted from onUncaughtException(), the
1122
- // "runEnd" event should report the status as failed.
1123
- // The "runEnd" event data is made by this class (as "globalSuite").
1189
+ // "runEnd" event should report the status as failed. The "runEnd" event data
1190
+ // is tracked through this property (via the "runSuite" instance).
1124
1191
 
1125
1192
  this.globalFailureCount = 0;
1126
1193
  this.tests = [];
@@ -1245,6 +1312,7 @@
1245
1312
  }();
1246
1313
 
1247
1314
  var moduleStack = [];
1315
+ var runSuite = new SuiteReport();
1248
1316
 
1249
1317
  function isParentModuleInQueue() {
1250
1318
  var modulesInQueue = config.modules.filter(function (module) {
@@ -1260,18 +1328,35 @@
1260
1328
  function createModule(name, testEnvironment, modifiers) {
1261
1329
  var parentModule = moduleStack.length ? moduleStack.slice(-1)[0] : null;
1262
1330
  var moduleName = parentModule !== null ? [parentModule.name, name].join(" > ") : name;
1263
- var parentSuite = parentModule ? parentModule.suiteReport : globalSuite;
1331
+ var parentSuite = parentModule ? parentModule.suiteReport : runSuite;
1264
1332
  var skip = parentModule !== null && parentModule.skip || modifiers.skip;
1265
1333
  var todo = parentModule !== null && parentModule.todo || modifiers.todo;
1334
+ var env = {};
1335
+
1336
+ if (parentModule) {
1337
+ extend(env, parentModule.testEnvironment);
1338
+ }
1339
+
1340
+ extend(env, testEnvironment);
1266
1341
  var module = {
1267
1342
  name: moduleName,
1268
1343
  parentModule: parentModule,
1344
+ hooks: {
1345
+ before: [],
1346
+ beforeEach: [],
1347
+ afterEach: [],
1348
+ after: []
1349
+ },
1350
+ testEnvironment: env,
1269
1351
  tests: [],
1270
1352
  moduleId: generateHash(moduleName),
1271
1353
  testsRun: 0,
1272
1354
  testsIgnored: 0,
1273
1355
  childModules: [],
1274
1356
  suiteReport: new SuiteReport(name, parentSuite),
1357
+ // Initialised by test.js when the module start executing,
1358
+ // i.e. before the first test in this module (or a child).
1359
+ stats: null,
1275
1360
  // Pass along `skip` and `todo` properties from parent module, in case
1276
1361
  // there is one, to childs. And use own otherwise.
1277
1362
  // This property will be used to mark own tests and tests of child suites
@@ -1280,19 +1365,35 @@
1280
1365
  todo: skip ? false : todo,
1281
1366
  ignored: modifiers.ignored || false
1282
1367
  };
1283
- var env = {};
1284
1368
 
1285
1369
  if (parentModule) {
1286
1370
  parentModule.childModules.push(module);
1287
- extend(env, parentModule.testEnvironment);
1288
1371
  }
1289
1372
 
1290
- extend(env, testEnvironment);
1291
- module.testEnvironment = env;
1292
1373
  config.modules.push(module);
1293
1374
  return module;
1294
1375
  }
1295
1376
 
1377
+ function setHookFromEnvironment(hooks, environment, name) {
1378
+ var potentialHook = environment[name];
1379
+
1380
+ if (typeof potentialHook === "function") {
1381
+ hooks[name].push(potentialHook);
1382
+ }
1383
+
1384
+ delete environment[name];
1385
+ }
1386
+
1387
+ function makeSetHook(module, hookName) {
1388
+ return function setHook(callback) {
1389
+ if (config.currentModule !== module) {
1390
+ Logger.warn("The `" + hookName + "` hook was called inside the wrong module (`" + config.currentModule.name + "`). " + "Instead, use hooks provided by the callback to the containing module (`" + module.name + "`). " + "This will become an error in QUnit 3.0.");
1391
+ }
1392
+
1393
+ module.hooks[hookName].push(callback);
1394
+ };
1395
+ }
1396
+
1296
1397
  function processModule(name, options, executeNow) {
1297
1398
  var modifiers = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
1298
1399
 
@@ -1301,19 +1402,19 @@
1301
1402
  options = undefined;
1302
1403
  }
1303
1404
 
1304
- var module = createModule(name, options, modifiers); // Move any hooks to a 'hooks' object
1405
+ var module = createModule(name, options, modifiers); // Transfer any initial hooks from the options object to the 'hooks' object
1305
1406
 
1306
1407
  var testEnvironment = module.testEnvironment;
1307
- var hooks = module.hooks = {};
1408
+ var hooks = module.hooks;
1308
1409
  setHookFromEnvironment(hooks, testEnvironment, "before");
1309
1410
  setHookFromEnvironment(hooks, testEnvironment, "beforeEach");
1310
1411
  setHookFromEnvironment(hooks, testEnvironment, "afterEach");
1311
1412
  setHookFromEnvironment(hooks, testEnvironment, "after");
1312
1413
  var moduleFns = {
1313
- before: setHookFunction(module, "before"),
1314
- beforeEach: setHookFunction(module, "beforeEach"),
1315
- afterEach: setHookFunction(module, "afterEach"),
1316
- after: setHookFunction(module, "after")
1414
+ before: makeSetHook(module, "before"),
1415
+ beforeEach: makeSetHook(module, "beforeEach"),
1416
+ afterEach: makeSetHook(module, "afterEach"),
1417
+ after: makeSetHook(module, "after")
1317
1418
  };
1318
1419
  var prevModule = config.currentModule;
1319
1420
  config.currentModule = module;
@@ -1336,22 +1437,6 @@
1336
1437
  config.currentModule = module.parentModule || prevModule;
1337
1438
  }
1338
1439
  }
1339
-
1340
- function setHookFromEnvironment(hooks, environment, name) {
1341
- var potentialHook = environment[name];
1342
- hooks[name] = typeof potentialHook === "function" ? [potentialHook] : [];
1343
- delete environment[name];
1344
- }
1345
-
1346
- function setHookFunction(module, hookName) {
1347
- return function setHook(callback) {
1348
- if (config.currentModule !== module) {
1349
- Logger.warn("The `" + hookName + "` hook was called inside the wrong module (`" + config.currentModule.name + "`). " + "Instead, use hooks provided by the callback to the containing module (`" + module.name + "`). " + "This will become an error in QUnit 3.0.");
1350
- }
1351
-
1352
- module.hooks[hookName].push(callback);
1353
- };
1354
- }
1355
1440
  }
1356
1441
 
1357
1442
  var focused$1 = false; // indicates that the "only" filter was used
@@ -2102,7 +2187,7 @@
2102
2187
  var runtime = now() - config.started;
2103
2188
  var passed = config.stats.all - config.stats.bad;
2104
2189
  ProcessingQueue.finished = true;
2105
- emit("runEnd", globalSuite.end(true));
2190
+ emit("runEnd", runSuite.end(true));
2106
2191
  runLoggingCallbacks("done", {
2107
2192
  passed: passed,
2108
2193
  failed: config.stats.bad,
@@ -2422,22 +2507,46 @@
2422
2507
  after: function after() {
2423
2508
  checkPollution();
2424
2509
  },
2425
- queueHook: function queueHook(hook, hookName, hookOwner) {
2510
+ queueGlobalHook: function queueGlobalHook(hook, hookName) {
2426
2511
  var _this2 = this;
2427
2512
 
2428
- var callHook = function callHook() {
2429
- var promise = hook.call(_this2.testEnvironment, _this2.assert);
2513
+ var runHook = function runHook() {
2514
+ config.current = _this2;
2515
+ var promise;
2516
+
2517
+ if (config.notrycatch) {
2518
+ promise = hook.call(_this2.testEnvironment, _this2.assert);
2519
+ } else {
2520
+ try {
2521
+ promise = hook.call(_this2.testEnvironment, _this2.assert);
2522
+ } catch (error) {
2523
+ _this2.pushFailure("Global " + hookName + " failed on " + _this2.testName + ": " + errorString(error), extractStacktrace(error, 0));
2524
+
2525
+ return;
2526
+ }
2527
+ }
2430
2528
 
2431
2529
  _this2.resolvePromise(promise, hookName);
2432
2530
  };
2433
2531
 
2532
+ return runHook;
2533
+ },
2534
+ queueHook: function queueHook(hook, hookName, hookOwner) {
2535
+ var _this3 = this;
2536
+
2537
+ var callHook = function callHook() {
2538
+ var promise = hook.call(_this3.testEnvironment, _this3.assert);
2539
+
2540
+ _this3.resolvePromise(promise, hookName);
2541
+ };
2542
+
2434
2543
  var runHook = function runHook() {
2435
2544
  if (hookName === "before") {
2436
2545
  if (hookOwner.testsRun !== 0) {
2437
2546
  return;
2438
2547
  }
2439
2548
 
2440
- _this2.preserveEnvironment = true;
2549
+ _this3.preserveEnvironment = true;
2441
2550
  } // The 'after' hook should only execute when there are not tests left and
2442
2551
  // when the 'after' and 'finish' tasks are the only tasks left to process
2443
2552
 
@@ -2446,7 +2555,7 @@
2446
2555
  return;
2447
2556
  }
2448
2557
 
2449
- config.current = _this2;
2558
+ config.current = _this3;
2450
2559
 
2451
2560
  if (config.notrycatch) {
2452
2561
  callHook();
@@ -2454,9 +2563,16 @@
2454
2563
  }
2455
2564
 
2456
2565
  try {
2566
+ // This try-block includes the indirect call to resolvePromise, which shouldn't
2567
+ // have to be inside try-catch. But, since we support any user-provided thenable
2568
+ // object, the thenable might throw in some unexpected way.
2569
+ // This subtle behaviour is undocumented. To avoid new failures in minor releases
2570
+ // we will not change this until QUnit 3.
2571
+ // TODO: In QUnit 3, reduce this try-block to just hook.call(), matching
2572
+ // the simplicity of queueGlobalHook.
2457
2573
  callHook();
2458
2574
  } catch (error) {
2459
- _this2.pushFailure(hookName + " failed on " + _this2.testName + ": " + (error.message || error), extractStacktrace(error, 0));
2575
+ _this3.pushFailure(hookName + " failed on " + _this3.testName + ": " + (error.message || error), extractStacktrace(error, 0));
2460
2576
  }
2461
2577
  };
2462
2578
 
@@ -2466,6 +2582,14 @@
2466
2582
  hooks: function hooks(handler) {
2467
2583
  var hooks = [];
2468
2584
 
2585
+ function processGlobalhooks(test) {
2586
+ if ((handler === "beforeEach" || handler === "afterEach") && config.globalHooks[handler]) {
2587
+ for (var i = 0; i < config.globalHooks[handler].length; i++) {
2588
+ hooks.push(test.queueGlobalHook(config.globalHooks[handler][i], handler));
2589
+ }
2590
+ }
2591
+ }
2592
+
2469
2593
  function processHooks(test, module) {
2470
2594
  if (module.parentModule) {
2471
2595
  processHooks(test, module.parentModule);
@@ -2480,6 +2604,7 @@
2480
2604
 
2481
2605
 
2482
2606
  if (!this.skip) {
2607
+ processGlobalhooks(this);
2483
2608
  processHooks(this, this.module);
2484
2609
  }
2485
2610
 
@@ -3398,6 +3523,35 @@
3398
3523
  negative: true
3399
3524
  });
3400
3525
  }
3526
+ }, {
3527
+ key: "propContains",
3528
+ value: function propContains(actual, expected, message) {
3529
+ actual = objectValuesSubset(actual, expected); // The expected parameter is usually a plain object, but clone it for
3530
+ // consistency with propEqual(), and to make it easy to explain that
3531
+ // inheritence is not considered (on either side), and to support
3532
+ // recursively checking subsets of nested objects.
3533
+
3534
+ expected = objectValues(expected, false);
3535
+ this.pushResult({
3536
+ result: equiv(actual, expected),
3537
+ actual: actual,
3538
+ expected: expected,
3539
+ message: message
3540
+ });
3541
+ }
3542
+ }, {
3543
+ key: "notPropContains",
3544
+ value: function notPropContains(actual, expected, message) {
3545
+ actual = objectValuesSubset(actual, expected);
3546
+ expected = objectValues(expected);
3547
+ this.pushResult({
3548
+ result: !equiv(actual, expected),
3549
+ actual: actual,
3550
+ expected: expected,
3551
+ message: message,
3552
+ negative: true
3553
+ });
3554
+ }
3401
3555
  }, {
3402
3556
  key: "deepEqual",
3403
3557
  value: function deepEqual(actual, expected, message) {
@@ -4009,7 +4163,7 @@
4009
4163
 
4010
4164
  _createClass(TapReporter, [{
4011
4165
  key: "onRunStart",
4012
- value: function onRunStart(_globalSuite) {
4166
+ value: function onRunStart(_runSuite) {
4013
4167
  this.log("TAP version 13");
4014
4168
  }
4015
4169
  }, {
@@ -4059,13 +4213,13 @@
4059
4213
  }
4060
4214
  }, {
4061
4215
  key: "onRunEnd",
4062
- value: function onRunEnd(globalSuite) {
4216
+ value: function onRunEnd(runSuite) {
4063
4217
  this.ended = true;
4064
- this.log("1..".concat(globalSuite.testCounts.total));
4065
- this.log("# pass ".concat(globalSuite.testCounts.passed));
4066
- this.log($.yellow("# skip ".concat(globalSuite.testCounts.skipped)));
4067
- this.log($.cyan("# todo ".concat(globalSuite.testCounts.todo)));
4068
- this.log($.red("# fail ".concat(globalSuite.testCounts.failed)));
4218
+ this.log("1..".concat(runSuite.testCounts.total));
4219
+ this.log("# pass ".concat(runSuite.testCounts.passed));
4220
+ this.log($.yellow("# skip ".concat(runSuite.testCounts.skipped)));
4221
+ this.log($.cyan("# todo ".concat(runSuite.testCounts.todo)));
4222
+ this.log($.red("# fail ".concat(runSuite.testCounts.failed)));
4069
4223
  }
4070
4224
  }, {
4071
4225
  key: "logAssertion",
@@ -4120,6 +4274,21 @@
4120
4274
  tap: TapReporter
4121
4275
  };
4122
4276
 
4277
+ function makeAddGlobalHook(hookName) {
4278
+ return function addGlobalHook(callback) {
4279
+ if (!config.globalHooks[hookName]) {
4280
+ config.globalHooks[hookName] = [];
4281
+ }
4282
+
4283
+ config.globalHooks[hookName].push(callback);
4284
+ };
4285
+ }
4286
+
4287
+ var hooks = {
4288
+ beforeEach: makeAddGlobalHook("beforeEach"),
4289
+ afterEach: makeAddGlobalHook("afterEach")
4290
+ };
4291
+
4123
4292
  /**
4124
4293
  * Handle a global error that should result in a failed test run.
4125
4294
  *
@@ -4158,7 +4327,7 @@
4158
4327
  // Increase "bad assertion" stats despite no longer pushing an assertion in this case.
4159
4328
  // This ensures "runEnd" and "QUnit.done()" handlers behave as expected, since the "bad"
4160
4329
  // count is typically how reporters decide on the boolean outcome of the test run.
4161
- globalSuite.globalFailureCount++;
4330
+ runSuite.globalFailureCount++;
4162
4331
  config.stats.bad++;
4163
4332
  config.stats.all++;
4164
4333
  emit("error", error);
@@ -4199,24 +4368,27 @@
4199
4368
  return false;
4200
4369
  }
4201
4370
 
4202
- var QUnit = {};
4203
- var globalSuite = new SuiteReport(); // The initial "currentModule" represents the global (or top-level) module that
4204
- // is not explicitly defined by the user, therefore we add the "globalSuite" to
4205
- // it since each module has a suiteReport associated with it.
4371
+ var QUnit = {}; // The "currentModule" object would ideally be defined using the createModule()
4372
+ // function. Since it isn't, add the missing suiteReport property to it now that
4373
+ // we have loaded all source code required to do so.
4374
+ //
4375
+ // TODO: Consider defining currentModule in core.js or module.js in its entirely
4376
+ // rather than partly in config.js and partly here.
4206
4377
 
4207
- config.currentModule.suiteReport = globalSuite;
4378
+ config.currentModule.suiteReport = runSuite;
4208
4379
  var globalStartCalled = false;
4209
4380
  var runStarted = false; // Figure out if we're running the tests from a server or not
4210
4381
 
4211
4382
  QUnit.isLocal = window$1 && window$1.location && window$1.location.protocol === "file:"; // Expose the current QUnit version
4212
4383
 
4213
- QUnit.version = "2.17.2";
4384
+ QUnit.version = "2.18.0";
4214
4385
 
4215
4386
  extend(QUnit, {
4216
4387
  config: config,
4217
4388
  dump: dump,
4218
4389
  equiv: equiv,
4219
4390
  reporters: reporters,
4391
+ hooks: hooks,
4220
4392
  is: is,
4221
4393
  objectType: objectType,
4222
4394
  on: on,
@@ -4371,7 +4543,7 @@
4371
4543
  } // The test run is officially beginning now
4372
4544
 
4373
4545
 
4374
- emit("runStart", globalSuite.start(true));
4546
+ emit("runStart", runSuite.start(true));
4375
4547
  runLoggingCallbacks("begin", {
4376
4548
  totalTests: Test.count,
4377
4549
  modules: modulesLog