Skip to content

Commit 6675e10

Browse files
authored
Merge pull request #1302 from emberjs/backport-fix
[backport] Remove the index signature from `TestContext`
2 parents b487c05 + a34c29b commit 6675e10

File tree

2 files changed

+23
-18
lines changed

2 files changed

+23
-18
lines changed

addon-test-support/@ember/test-helpers/setup-context.ts

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -60,34 +60,33 @@ registerWarnHandler((message, options, next) => {
6060
next.apply(null, [message, options]);
6161
});
6262

63-
export interface BaseContext {
64-
[key: string]: unknown;
65-
}
63+
export type BaseContext = object;
6664

6765
/**
6866
* The public API for the test context, which test authors can depend on being
6967
* available.
7068
*
7169
* Note: this is *not* user-constructible; it becomes available by calling
72-
* `setupContext()` with a `BaseContext`.
70+
* `setupContext()` with a base context object.
7371
*/
7472
export interface TestContext extends BaseContext {
7573
owner: Owner;
7674

7775
set<T>(key: string, value: T): T;
7876
setProperties<T extends Record<string, unknown>>(hash: T): T;
7977
get(key: string): unknown;
80-
getProperties(...args: string[]): Pick<BaseContext, string>;
78+
getProperties(...args: string[]): Record<string, unknown>;
8179

8280
pauseTest(): Promise<void>;
8381
resumeTest(): void;
8482
}
8583

8684
// eslint-disable-next-line require-jsdoc
8785
export function isTestContext(context: BaseContext): context is TestContext {
86+
let maybeContext = context as Record<string, unknown>;
8887
return (
89-
typeof context['pauseTest'] === 'function' &&
90-
typeof context['resumeTest'] === 'function'
88+
typeof maybeContext['pauseTest'] === 'function' &&
89+
typeof maybeContext['resumeTest'] === 'function'
9190
);
9291
}
9392

@@ -367,15 +366,17 @@ export const SetUsage = new WeakMap<BaseContext, Array<string>>();
367366
- setting up `pauseTest` (also available as `this.pauseTest()`) and `resumeTest` helpers
368367
369368
@public
370-
@param {Object} context the context to setup
369+
@param {Object} base the context to setup
371370
@param {Object} [options] options used to override defaults
372371
@param {Resolver} [options.resolver] a resolver to use for customizing normal resolution
373372
@returns {Promise<Object>} resolves with the context that was setup
374373
*/
375-
export default function setupContext(
376-
context: BaseContext,
374+
export default function setupContext<T extends object>(
375+
base: T,
377376
options: { resolver?: Resolver } = {}
378-
): Promise<TestContext> {
377+
): Promise<T & TestContext> {
378+
let context = base as T & TestContext;
379+
379380
// SAFETY: this is intimate API *designed* for us to override.
380381
(Ember as any).testing = true;
381382
setContext(context);
@@ -426,7 +427,8 @@ export default function setupContext(
426427
Object.defineProperty(context, 'set', {
427428
configurable: true,
428429
enumerable: true,
429-
value(key: string, value: unknown): unknown {
430+
// SAFETY: in all of these `defineProperty` calls, we can't actually guarantee any safety w.r.t. the corresponding field's type in `TestContext`
431+
value(key: any, value: any): unknown {
430432
let ret = run(function () {
431433
if (ComponentRenderMap.has(context)) {
432434
assert(
@@ -454,7 +456,8 @@ export default function setupContext(
454456
Object.defineProperty(context, 'setProperties', {
455457
configurable: true,
456458
enumerable: true,
457-
value(hash: { [key: string]: any }): { [key: string]: any } {
459+
// SAFETY: in all of these `defineProperty` calls, we can't actually guarantee any safety w.r.t. the corresponding field's type in `TestContext`
460+
value(hash: any): unknown {
458461
let ret = run(function () {
459462
if (ComponentRenderMap.has(context)) {
460463
assert(
@@ -490,13 +493,14 @@ export default function setupContext(
490493
Object.defineProperty(context, 'getProperties', {
491494
configurable: true,
492495
enumerable: true,
493-
value(...args: string[]): Pick<BaseContext, string> {
496+
// SAFETY: in all of these `defineProperty` calls, we can't actually guarantee any safety w.r.t. the corresponding field's type in `TestContext`
497+
value(...args: any[]): Record<string, unknown> {
494498
return getProperties(context, args);
495499
},
496500
writable: false,
497501
});
498502

499-
let resume: ((value?: unknown) => void) | undefined;
503+
let resume: ((value?: void | PromiseLike<void>) => void) | undefined;
500504
context['resumeTest'] = function resumeTest() {
501505
assert(
502506
'Testing has not been paused. There is nothing to resume.',
@@ -517,6 +521,6 @@ export default function setupContext(
517521

518522
_setupAJAXHooks();
519523

520-
return context as TestContext;
524+
return context;
521525
});
522526
}

addon-test-support/@ember/test-helpers/setup-rendering-context.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,11 @@ export interface RenderingTestContext extends TestContext {
3838
export function isRenderingTestContext(
3939
context: BaseContext
4040
): context is RenderingTestContext {
41+
let maybeContext = context as Partial<RenderingTestContext>;
4142
return (
4243
isTestContext(context) &&
43-
typeof context['render'] === 'function' &&
44-
typeof context['clearRender'] === 'function'
44+
typeof maybeContext['render'] === 'function' &&
45+
typeof maybeContext['clearRender'] === 'function'
4546
);
4647
}
4748

0 commit comments

Comments
 (0)