From a34c29b71d88cb16a876900ce657366916da08ba Mon Sep 17 00:00:00 2001 From: Dan Freeman Date: Tue, 20 Dec 2022 14:48:18 -0700 Subject: [PATCH] Remove the index signature from `TestContext` This incorporates the same basic fix for `isRenderingTestContext` as the original does for `isTestContext`, since that mechanic changes between v2 and v3. (cherry picked from commit cba01bea57e4f514afc792526b25a53e499acea0) --- .../@ember/test-helpers/setup-context.ts | 36 ++++++++++--------- .../test-helpers/setup-rendering-context.ts | 5 +-- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/addon-test-support/@ember/test-helpers/setup-context.ts b/addon-test-support/@ember/test-helpers/setup-context.ts index ee6689b41..5ff4c5d1b 100644 --- a/addon-test-support/@ember/test-helpers/setup-context.ts +++ b/addon-test-support/@ember/test-helpers/setup-context.ts @@ -60,16 +60,14 @@ registerWarnHandler((message, options, next) => { next.apply(null, [message, options]); }); -export interface BaseContext { - [key: string]: unknown; -} +export type BaseContext = object; /** * The public API for the test context, which test authors can depend on being * available. * * Note: this is *not* user-constructible; it becomes available by calling - * `setupContext()` with a `BaseContext`. + * `setupContext()` with a base context object. */ export interface TestContext extends BaseContext { owner: Owner; @@ -77,7 +75,7 @@ export interface TestContext extends BaseContext { set(key: string, value: T): T; setProperties>(hash: T): T; get(key: string): unknown; - getProperties(...args: string[]): Pick; + getProperties(...args: string[]): Record; pauseTest(): Promise; resumeTest(): void; @@ -85,9 +83,10 @@ export interface TestContext extends BaseContext { // eslint-disable-next-line require-jsdoc export function isTestContext(context: BaseContext): context is TestContext { + let maybeContext = context as Record; return ( - typeof context['pauseTest'] === 'function' && - typeof context['resumeTest'] === 'function' + typeof maybeContext['pauseTest'] === 'function' && + typeof maybeContext['resumeTest'] === 'function' ); } @@ -367,15 +366,17 @@ export const SetUsage = new WeakMap>(); - setting up `pauseTest` (also available as `this.pauseTest()`) and `resumeTest` helpers @public - @param {Object} context the context to setup + @param {Object} base the context to setup @param {Object} [options] options used to override defaults @param {Resolver} [options.resolver] a resolver to use for customizing normal resolution @returns {Promise} resolves with the context that was setup */ -export default function setupContext( - context: BaseContext, +export default function setupContext( + base: T, options: { resolver?: Resolver } = {} -): Promise { +): Promise { + let context = base as T & TestContext; + // SAFETY: this is intimate API *designed* for us to override. (Ember as any).testing = true; setContext(context); @@ -426,7 +427,8 @@ export default function setupContext( Object.defineProperty(context, 'set', { configurable: true, enumerable: true, - value(key: string, value: unknown): unknown { + // SAFETY: in all of these `defineProperty` calls, we can't actually guarantee any safety w.r.t. the corresponding field's type in `TestContext` + value(key: any, value: any): unknown { let ret = run(function () { if (ComponentRenderMap.has(context)) { assert( @@ -454,7 +456,8 @@ export default function setupContext( Object.defineProperty(context, 'setProperties', { configurable: true, enumerable: true, - value(hash: { [key: string]: any }): { [key: string]: any } { + // SAFETY: in all of these `defineProperty` calls, we can't actually guarantee any safety w.r.t. the corresponding field's type in `TestContext` + value(hash: any): unknown { let ret = run(function () { if (ComponentRenderMap.has(context)) { assert( @@ -490,13 +493,14 @@ export default function setupContext( Object.defineProperty(context, 'getProperties', { configurable: true, enumerable: true, - value(...args: string[]): Pick { + // SAFETY: in all of these `defineProperty` calls, we can't actually guarantee any safety w.r.t. the corresponding field's type in `TestContext` + value(...args: any[]): Record { return getProperties(context, args); }, writable: false, }); - let resume: ((value?: unknown) => void) | undefined; + let resume: ((value?: void | PromiseLike) => void) | undefined; context['resumeTest'] = function resumeTest() { assert( 'Testing has not been paused. There is nothing to resume.', @@ -517,6 +521,6 @@ export default function setupContext( _setupAJAXHooks(); - return context as TestContext; + return context; }); } diff --git a/addon-test-support/@ember/test-helpers/setup-rendering-context.ts b/addon-test-support/@ember/test-helpers/setup-rendering-context.ts index c5a84c0ea..9c08b083f 100644 --- a/addon-test-support/@ember/test-helpers/setup-rendering-context.ts +++ b/addon-test-support/@ember/test-helpers/setup-rendering-context.ts @@ -38,10 +38,11 @@ export interface RenderingTestContext extends TestContext { export function isRenderingTestContext( context: BaseContext ): context is RenderingTestContext { + let maybeContext = context as Partial; return ( isTestContext(context) && - typeof context['render'] === 'function' && - typeof context['clearRender'] === 'function' + typeof maybeContext['render'] === 'function' && + typeof maybeContext['clearRender'] === 'function' ); }