From b0f94bac9b958f025923bc66830579b6fec87e97 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Tue, 25 Aug 2020 10:22:54 -0400 Subject: [PATCH] Migrate to using @ember/destroyable for teardown. Moves actual logic from `teardownContext` into `setupContext` by using `registerDestructor` and `associateDestroyableChild`. --- .../@ember/test-helpers/setup-context.ts | 23 +++++++++++++++++- .../@ember/test-helpers/teardown-context.ts | 24 ++++--------------- package.json | 3 ++- tests/unit/teardown-context-test.js | 21 ++++++++++++++++ tsconfig.json | 1 + yarn.lock | 18 ++++++++++++++ 6 files changed, 69 insertions(+), 21 deletions(-) diff --git a/addon-test-support/@ember/test-helpers/setup-context.ts b/addon-test-support/@ember/test-helpers/setup-context.ts index 1a89bc465..e1331a1ad 100644 --- a/addon-test-support/@ember/test-helpers/setup-context.ts +++ b/addon-test-support/@ember/test-helpers/setup-context.ts @@ -3,7 +3,7 @@ import { set, setProperties, get, getProperties } from '@ember/object'; import Resolver from '@ember/application/resolver'; import buildOwner, { Owner } from './build-owner'; -import { _setupAJAXHooks } from './settled'; +import { _setupAJAXHooks, _teardownAJAXHooks } from './settled'; import Ember from 'ember'; import { Promise } from 'rsvp'; import { assert } from '@ember/debug'; @@ -12,6 +12,7 @@ import { getResolver } from './resolver'; import { getApplication } from './application'; import { nextTickPromise } from './-utils'; import getTestMetadata, { ITestMetadata } from './test-metadata'; +import { registerDestructor, associateDestroyableChild } from '@ember/destroyable'; export interface BaseContext { [key: string]: any; @@ -132,6 +133,22 @@ export function resumeTest(): void { context.resumeTest(); } +/** + @private + @param {Object} context the test context being cleaned up +*/ +function cleanup(context: BaseContext) { + _teardownAJAXHooks(); + + (Ember as any).testing = false; + + unsetContext(); + + // this should not be required, but until https://github.com/emberjs/ember.js/pull/19106 + // lands in a 3.20 patch release + context.owner.destroy(); +} + /** Used by test framework addons to setup the provided context for testing. @@ -161,6 +178,8 @@ export default function setupContext( run.backburner.DEBUG = true; + registerDestructor(context, cleanup); + return nextTickPromise() .then(() => { let application = getApplication(); @@ -185,6 +204,8 @@ export default function setupContext( return buildOwner(getApplication(), getResolver()); }) .then(owner => { + associateDestroyableChild(context, owner); + Object.defineProperty(context, 'owner', { configurable: true, enumerable: true, diff --git a/addon-test-support/@ember/test-helpers/teardown-context.ts b/addon-test-support/@ember/test-helpers/teardown-context.ts index 7d3233e83..881d11a10 100644 --- a/addon-test-support/@ember/test-helpers/teardown-context.ts +++ b/addon-test-support/@ember/test-helpers/teardown-context.ts @@ -1,9 +1,7 @@ -import { run } from '@ember/runloop'; -import { _teardownAJAXHooks } from './settled'; -import { unsetContext, TestContext } from './setup-context'; +import { TestContext } from './setup-context'; import { nextTickPromise } from './-utils'; import settled from './settled'; -import Ember from 'ember'; +import { destroy } from '@ember/destroyable'; /** Used by test framework addons to tear down the provided context after testing is completed. @@ -28,28 +26,16 @@ export default function teardownContext( if (options !== undefined && 'waitForSettled' in options) { waitForSettled = options.waitForSettled!; } + return nextTickPromise() .then(() => { - let { owner } = context; - - _teardownAJAXHooks(); - - run(owner, 'destroy'); - (Ember as any).testing = false; - - unsetContext(); - - if (waitForSettled) { - return settled(); - } - - return nextTickPromise(); + destroy(context); }) .finally(() => { if (waitForSettled) { return settled(); } - return nextTickPromise(); + return; }); } diff --git a/package.json b/package.json index 8e35a9050..711ed24eb 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,8 @@ "broccoli-debug": "^0.6.5", "broccoli-funnel": "^3.0.3", "ember-cli-babel": "^7.22.1", - "ember-cli-htmlbars": "^5.2.0" + "ember-cli-htmlbars": "^5.2.0", + "ember-destroyable-polyfill": "^2.0.1" }, "devDependencies": { "@ember/optional-features": "^1.3.0", diff --git a/tests/unit/teardown-context-test.js b/tests/unit/teardown-context-test.js index 6ea246ddb..2ff725372 100644 --- a/tests/unit/teardown-context-test.js +++ b/tests/unit/teardown-context-test.js @@ -15,6 +15,7 @@ import hasjQuery from '../helpers/has-jquery'; import ajax from '../helpers/ajax'; import Pretender from 'pretender'; import setupManualTestWaiter from '../helpers/manual-test-waiter'; +import { registerDestructor } from '@ember/destroyable'; module('teardownContext', function (hooks) { if (!hasEmberVersion(2, 4)) { @@ -64,6 +65,26 @@ module('teardownContext', function (hooks) { assert.strictEqual(getContext(), undefined, 'context is unset'); }); + test('destroyables registered with the context are invoked', async function (assert) { + registerDestructor(context, () => { + assert.step('destructor was ran'); + }); + + assert.step('teardown started'); + + await teardownContext(context); + + assert.step('teardown completed'); + + assert.verifySteps(['teardown started', 'destructor was ran', 'teardown completed']); + }); + + test('the owner is destroyed', async function (assert) { + await teardownContext(context); + + assert.ok(context.owner.isDestroyed); + }); + if (hasjQuery()) { test('out of balance xhr semaphores are cleaned up on teardown', async function (assert) { this.pretender.unhandledRequest = function (/* verb, path, request */) { diff --git a/tsconfig.json b/tsconfig.json index 2b52abc82..a7e35ff07 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -33,6 +33,7 @@ "@ember/test-helpers/*": [ "addon-test-support/@ember/test-helpers/*" ], + "@ember/destroyable": ["node_modules/ember-destroyable-polyfill"], "*": [ "types/*" ] diff --git a/yarn.lock b/yarn.lock index 50c997043..9f6837f9d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5151,6 +5151,15 @@ ember-compatibility-helpers@^1.1.1, ember-compatibility-helpers@^1.2.0: ember-cli-version-checker "^2.1.1" semver "^5.4.1" +ember-compatibility-helpers@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ember-compatibility-helpers/-/ember-compatibility-helpers-1.2.1.tgz#87c92c4303f990ff455c28ca39fb3ee11441aa16" + integrity sha512-6wzYvnhg1ihQUT5yGqnLtleq3Nv5KNv79WhrEuNU9SwR4uIxCO+KpyC7r3d5VI0EM7/Nmv9Nd0yTkzmTMdVG1A== + dependencies: + babel-plugin-debug-macros "^0.2.0" + ember-cli-version-checker "^2.1.1" + semver "^5.4.1" + ember-data@~3.20.0: version "3.20.0" resolved "https://registry.yarnpkg.com/ember-data/-/ember-data-3.20.0.tgz#613cfca5276b16b4f4bbfb35432e58f3e5a2d9f3" @@ -5171,6 +5180,15 @@ ember-data@~3.20.0: ember-cli-typescript "^3.1.3" ember-inflector "^3.0.1" +ember-destroyable-polyfill@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ember-destroyable-polyfill/-/ember-destroyable-polyfill-2.0.1.tgz#391cd95a99debaf24148ce953054008d00f151a6" + integrity sha512-hyK+/GPWOIxM1vxnlVMknNl9E5CAFVbcxi8zPiM0vCRwHiFS8Wuj7PfthZ1/OFitNNv7ITTeU8hxqvOZVsrbnQ== + dependencies: + ember-cli-babel "^7.22.1" + ember-cli-version-checker "^5.1.1" + ember-compatibility-helpers "^1.2.1" + ember-disable-prototype-extensions@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/ember-disable-prototype-extensions/-/ember-disable-prototype-extensions-1.1.3.tgz#1969135217654b5e278f9fe2d9d4e49b5720329e"