|  | 
| 1 |  | -import Mocha from 'mocha'; | 
| 2 | 1 | import assert from 'assert'; | 
| 3 | 2 | import type { | 
| 4 | 3 |   ChildProcess, | 
| @@ -49,7 +48,8 @@ export class TestShell { | 
| 49 | 48 |   private static _openShells: Set<TestShell> = new Set(); | 
| 50 | 49 | 
 | 
| 51 | 50 |   /** | 
| 52 |  | -   * @deprecated Use the {@link Mocha.Context.startTestShell} hook instead | 
|  | 51 | +   * Starts a test shell. | 
|  | 52 | +   * @private Use the {@link Mocha.Context.startTestShell} hook instead | 
| 53 | 53 |    */ | 
| 54 | 54 |   static start(options: TestShellOptions = { args: [] }): TestShell { | 
| 55 | 55 |     let shellProcess: ChildProcessWithoutNullStreams; | 
| @@ -335,98 +335,3 @@ export class TestShell { | 
| 335 | 335 |     return match.groups!.logId; | 
| 336 | 336 |   } | 
| 337 | 337 | } | 
| 338 |  | - | 
| 339 |  | -// Context extension to manage TestShell lifetime | 
| 340 |  | - | 
| 341 |  | -declare module 'mocha' { | 
| 342 |  | -  interface Context { | 
| 343 |  | -    /** | 
| 344 |  | -     * Starts a test shell and registers a hook to kill it after the test | 
| 345 |  | -     */ | 
| 346 |  | -    startTestShell(options?: TestShellOptions): TestShell; | 
| 347 |  | -  } | 
| 348 |  | -} | 
| 349 |  | - | 
| 350 |  | -const TEST_SHELLS_AFTER_ALL = Symbol('test-shells-after-all'); | 
| 351 |  | -const TEST_SHELLS_AFTER_EACH = Symbol('test-shells-after-each'); | 
| 352 |  | - | 
| 353 |  | -type AfterAllInjectedSuite = { | 
| 354 |  | -  [TEST_SHELLS_AFTER_ALL]: Set<TestShell>; | 
| 355 |  | -}; | 
| 356 |  | - | 
| 357 |  | -type AfterEachInjectedSuite = { | 
| 358 |  | -  [TEST_SHELLS_AFTER_EACH]: Set<TestShell>; | 
| 359 |  | -}; | 
| 360 |  | - | 
| 361 |  | -/** | 
| 362 |  | - * Registers an after (all or each) hook to kill test shells started during the hooks or tests. | 
| 363 |  | - * You don't have to call this from tests, but you can if you want to register an after (each) hook | 
| 364 |  | - * which runs after the shells have been killed. | 
| 365 |  | - */ | 
| 366 |  | -export function ensureTestShellAfterHook( | 
| 367 |  | -  hookName: 'afterEach', | 
| 368 |  | -  suite: Mocha.Suite | 
| 369 |  | -): asserts suite is AfterEachInjectedSuite & Mocha.Suite; | 
| 370 |  | -export function ensureTestShellAfterHook( | 
| 371 |  | -  hookName: 'afterAll', | 
| 372 |  | -  suite: Mocha.Suite | 
| 373 |  | -): asserts suite is AfterAllInjectedSuite & Mocha.Suite; | 
| 374 |  | -export function ensureTestShellAfterHook( | 
| 375 |  | -  hookName: 'afterEach' | 'afterAll', | 
| 376 |  | -  suite: Partial<AfterAllInjectedSuite & AfterEachInjectedSuite> & Mocha.Suite | 
| 377 |  | -): void { | 
| 378 |  | -  const symbol = | 
| 379 |  | -    hookName === 'afterAll' ? TEST_SHELLS_AFTER_ALL : TEST_SHELLS_AFTER_EACH; | 
| 380 |  | -  if (!suite[symbol]) { | 
| 381 |  | -    // Store the set of shells to kill afterwards | 
| 382 |  | -    const shells = new Set<TestShell>(); | 
| 383 |  | -    suite[symbol] = shells; | 
| 384 |  | -    suite[hookName](async () => { | 
| 385 |  | -      const shellsToKill = [...shells]; | 
| 386 |  | -      shells.clear(); | 
| 387 |  | -      await Promise.all( | 
| 388 |  | -        shellsToKill.map((shell) => { | 
| 389 |  | -          // TODO: Consider if it's okay to kill those that are already killed? | 
| 390 |  | -          shell.kill(); | 
| 391 |  | -          return shell.waitForExit(); | 
| 392 |  | -        }) | 
| 393 |  | -      ); | 
| 394 |  | -    }); | 
| 395 |  | -  } | 
| 396 |  | -} | 
| 397 |  | - | 
| 398 |  | -Mocha.Context.prototype.startTestShell = function ( | 
| 399 |  | -  this: Mocha.Context, | 
| 400 |  | -  options: TestShellOptions | 
| 401 |  | -) { | 
| 402 |  | -  const { test: runnable } = this; | 
| 403 |  | -  assert(runnable, 'Expected a runnable / test'); | 
| 404 |  | -  const { parent } = runnable; | 
| 405 |  | -  assert(parent, 'Expected runnable to have a parent'); | 
| 406 |  | -  // Start the shell | 
| 407 |  | -  const shell = TestShell.start(options); | 
| 408 |  | -  // Register a hook to kill the shell | 
| 409 |  | -  if (runnable instanceof Mocha.Hook) { | 
| 410 |  | -    if ( | 
| 411 |  | -      runnable.originalTitle === '"before each" hook' || | 
| 412 |  | -      runnable.originalTitle === '"after each" hook' | 
| 413 |  | -    ) { | 
| 414 |  | -      ensureTestShellAfterHook('afterEach', parent); | 
| 415 |  | -      parent[TEST_SHELLS_AFTER_EACH].add(shell); | 
| 416 |  | -    } else if ( | 
| 417 |  | -      runnable.originalTitle === '"before all" hook' || | 
| 418 |  | -      runnable.originalTitle === '"after all" hook' | 
| 419 |  | -    ) { | 
| 420 |  | -      ensureTestShellAfterHook('afterAll', parent); | 
| 421 |  | -      parent[TEST_SHELLS_AFTER_ALL].add(shell); | 
| 422 |  | -    } else { | 
| 423 |  | -      throw new Error(`Unexpected ${runnable.originalTitle || runnable.title}`); | 
| 424 |  | -    } | 
| 425 |  | -  } else if (runnable instanceof Mocha.Test) { | 
| 426 |  | -    ensureTestShellAfterHook('afterEach', parent); | 
| 427 |  | -    parent[TEST_SHELLS_AFTER_EACH].add(shell); | 
| 428 |  | -  } else { | 
| 429 |  | -    throw new Error('Unexpected Runnable: Expected a Hook or a Test'); | 
| 430 |  | -  } | 
| 431 |  | -  return shell; | 
| 432 |  | -}; | 
0 commit comments