diff --git a/addon/src/setup-application-context.ts b/addon/src/setup-application-context.ts
index 40f3adfca..c2cb961a0 100644
--- a/addon/src/setup-application-context.ts
+++ b/addon/src/setup-application-context.ts
@@ -4,12 +4,9 @@ import {
isTestContext,
type TestContext,
} from './setup-context.ts';
-import global from './global.ts';
-import hasEmberVersion from './has-ember-version.ts';
import settled from './settled.ts';
import getTestMetadata from './test-metadata.ts';
import { runHooks } from './helper-hooks.ts';
-import type Router from '@ember/routing/router';
import type RouterService from '@ember/routing/router-service';
import { assert } from '@ember/debug';
@@ -17,9 +14,7 @@ export interface ApplicationTestContext extends TestContext {
element?: Element | null;
}
-const CAN_USE_ROUTER_EVENTS = hasEmberVersion(3, 6);
let routerTransitionsPending: boolean | null = null;
-const ROUTER = new WeakMap();
const HAS_SETUP_ROUTER = new WeakMap();
// eslint-disable-next-line require-jsdoc
@@ -36,33 +31,7 @@ export function isApplicationTestContext(
@returns {(boolean|null)} if there are pending transitions
*/
export function hasPendingTransitions(): boolean | null {
- if (CAN_USE_ROUTER_EVENTS) {
- return routerTransitionsPending;
- }
-
- const context = getContext();
-
- // there is no current context, we cannot check
- if (context === undefined) {
- return null;
- }
-
- const router = ROUTER.get(context);
-
- if (router === undefined) {
- // if there is no router (e.g. no `visit` calls made yet), we cannot
- // check for pending transitions but this is explicitly not an error
- // condition
- return null;
- }
-
- const routerMicrolib = router._routerMicrolib || router.router;
-
- if (routerMicrolib === undefined) {
- return null;
- }
-
- return !!routerMicrolib.activeTransition;
+ return routerTransitionsPending;
}
/**
@@ -88,29 +57,19 @@ export function setupRouterSettlednessTracking() {
HAS_SETUP_ROUTER.set(context, true);
const { owner } = context;
- let router: Router | RouterService;
- if (CAN_USE_ROUTER_EVENTS) {
- // SAFETY: unfortunately we cannot `assert` here at present because the
- // class is not exported, only the type, since it is not designed to be
- // sub-classed. The most we can do at present is assert that it at least
- // *exists* and assume that if it does exist, it is bound correctly.
- const routerService = owner.lookup('service:router');
- assert('router service is not set up correctly', !!routerService);
- router = routerService as RouterService;
-
- // track pending transitions via the public routeWillChange / routeDidChange APIs
- // routeWillChange can fire many times and is only useful to know when we have _started_
- // transitioning, we can then use routeDidChange to signal that the transition has settled
- router.on('routeWillChange', () => (routerTransitionsPending = true));
- router.on('routeDidChange', () => (routerTransitionsPending = false));
- } else {
- // SAFETY: similarly, this cast cannot be made safer because on the versions
- // where we fall into this path, this is *also* not an exported class.
- const mainRouter = owner.lookup('router:main');
- assert('router:main is not available', !!mainRouter);
- router = mainRouter as Router;
- ROUTER.set(context, router);
- }
+
+ // SAFETY: unfortunately we cannot `assert` here at present because the
+ // class is not exported, only the type, since it is not designed to be
+ // sub-classed. The most we can do at present is assert that it at least
+ // *exists* and assume that if it does exist, it is bound correctly.
+ const router = owner.lookup('service:router') as RouterService;
+ assert('router service is not set up correctly', !!router);
+
+ // track pending transitions via the public routeWillChange / routeDidChange APIs
+ // routeWillChange can fire many times and is only useful to know when we have _started_
+ // transitioning, we can then use routeDidChange to signal that the transition has settled
+ router.on('routeWillChange', () => (routerTransitionsPending = true));
+ router.on('routeDidChange', () => (routerTransitionsPending = false));
// hook into teardown to reset local settledness state
const ORIGINAL_WILL_DESTROY = router.willDestroy;
@@ -168,13 +127,7 @@ export function visit(
return visitResult;
})
.then(() => {
- if (global.EmberENV._APPLICATION_TEMPLATE_WRAPPER !== false) {
- context.element = document.querySelector(
- '#ember-testing > .ember-view',
- );
- } else {
- context.element = document.querySelector('#ember-testing');
- }
+ context.element = document.querySelector('#ember-testing');
})
.then(settled)
.then(() => {
@@ -203,8 +156,6 @@ export function currentRouteName(): string {
return currentRouteName;
}
-const HAS_CURRENT_URL_ON_ROUTER = hasEmberVersion(2, 13);
-
/**
@public
@returns {string} the applications current url
@@ -218,30 +169,22 @@ export function currentURL(): string {
}
const router = context.owner.lookup('router:main') as any;
+ const routerCurrentURL = router.currentURL;
+
+ // SAFETY: this path is a lie for the sake of the public-facing types. The
+ // framework itself sees this path, but users never do. A user who calls the
+ // API without calling `visit()` will see an `UnrecognizedURLError`, rather
+ // than getting back `null`.
+ if (routerCurrentURL === null) {
+ return routerCurrentURL as never as string;
+ }
- if (HAS_CURRENT_URL_ON_ROUTER) {
- const routerCurrentURL = router.currentURL;
-
- // SAFETY: this path is a lie for the sake of the public-facing types. The
- // framework itself sees this path, but users never do. A user who calls the
- // API without calling `visit()` will see an `UnrecognizedURLError`, rather
- // than getting back `null`.
- if (routerCurrentURL === null) {
- return routerCurrentURL as never as string;
- }
-
- assert(
- `currentUrl should be a string, but was ${typeof routerCurrentURL}`,
- typeof routerCurrentURL === 'string',
- );
+ assert(
+ `currentUrl should be a string, but was ${typeof routerCurrentURL}`,
+ typeof routerCurrentURL === 'string',
+ );
- return routerCurrentURL;
- } else {
- // SAFETY: this is *positively ancient* and should probably be removed at
- // some point; old routers which don't have `currentURL` *should* have a
- // `location` with `getURL()` per the docs for 2.12.
- return (router.location as any).getURL();
- }
+ return routerCurrentURL;
}
/**
diff --git a/addon/src/setup-rendering-context.ts b/addon/src/setup-rendering-context.ts
index d2581d75d..6006a8822 100644
--- a/addon/src/setup-rendering-context.ts
+++ b/addon/src/setup-rendering-context.ts
@@ -1,6 +1,5 @@
import { run } from '@ember/runloop';
import Ember from 'ember';
-import global from './global.ts';
import {
type BaseContext,
type TestContext,
@@ -13,7 +12,6 @@ import type { Owner } from './build-owner.ts';
import getTestMetadata from './test-metadata.ts';
import { assert } from '@ember/debug';
import { runHooks } from './helper-hooks.ts';
-import hasEmberVersion from './has-ember-version.ts';
import isComponent from './-internal/is-component.ts';
import { ComponentRenderMap, SetUsage } from './setup-context.ts';
@@ -188,20 +186,6 @@ export function render(
};
toplevelView.setOutletState(outletState);
- // Ember's rendering engine is integration with the run loop so that when a run
- // loop starts, the rendering is scheduled to be done.
- //
- // Ember should be ensuring an instance on its own here (the act of
- // setting outletState should ensureInstance, since we know we need to
- // render), but on Ember < 3.23 that is not guaranteed.
- if (!hasEmberVersion(3, 23)) {
- // SAFETY: this was correct and type checked on the Ember v3 types, but
- // since the `run` namespace does not exist in Ember v4, this no longer
- // can be type checked. When (eventually) dropping support for Ember v3,
- // and therefore for versions before 3.23, this can be removed entirely.
- (run as any).backburner.ensureInstance();
- }
-
// returning settled here because the actual rendering does not happen until
// the renderer detects it is dirty (which happens on backburner's end
// hook), see the following implementation details:
@@ -315,18 +299,7 @@ export default function setupRenderingContext(
Object.defineProperty(renderingContext, 'element', {
configurable: true,
enumerable: true,
- // ensure the element is based on the wrapping toplevel view
- // Ember still wraps the main application template with a
- // normal tagged view
- //
- // In older Ember versions (2.4) the element itself is not stable,
- // and therefore we cannot update the `this.element` until after the
- // rendering is completed
- value:
- global.EmberENV._APPLICATION_TEMPLATE_WRAPPER !== false
- ? getRootElement().querySelector('.ember-view')
- : getRootElement(),
-
+ value: getRootElement(),
writable: false,
});
diff --git a/test-app/tests/integration/rerender-test.js b/test-app/tests/integration/rerender-test.js
index b11d29a90..d1dd3844f 100644
--- a/test-app/tests/integration/rerender-test.js
+++ b/test-app/tests/integration/rerender-test.js
@@ -18,13 +18,8 @@ import GlimmerComponent from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { hbs } from 'ember-cli-htmlbars';
import { module, test } from 'qunit';
-import hasEmberVersion from '@ember/test-helpers/has-ember-version';
module('rerender real-world', function (hooks) {
- // this test requires Ember 3.25 in order to use lexically scoped values in templates
- if (!hasEmberVersion(3, 25)) {
- return;
- }
hooks.beforeEach(async function () {
await setupContext(this);
await setupRenderingContext(this);
diff --git a/test-app/tests/integration/settled-test.js b/test-app/tests/integration/settled-test.js
index f17bc51c4..ab9ccaef7 100644
--- a/test-app/tests/integration/settled-test.js
+++ b/test-app/tests/integration/settled-test.js
@@ -12,7 +12,6 @@ import {
render,
rerender,
} from '@ember/test-helpers';
-import hasEmberVersion from '@ember/test-helpers/has-ember-version';
import { module, test } from 'qunit';
import { hbs } from 'ember-cli-htmlbars';
import Pretender from 'pretender';
@@ -119,10 +118,6 @@ const TestComponent5 = Component.extend({
});
module('settled real-world scenarios', function (hooks) {
- if (!hasEmberVersion(2, 4)) {
- return;
- }
-
hooks.beforeEach(async function () {
await setupContext(this);
await setupRenderingContext(this);
diff --git a/test-app/tests/integration/setup-rendering-context-test.js b/test-app/tests/integration/setup-rendering-context-test.js
index ca974db91..4972ae7f3 100644
--- a/test-app/tests/integration/setup-rendering-context-test.js
+++ b/test-app/tests/integration/setup-rendering-context-test.js
@@ -15,7 +15,6 @@ import {
} from '@ember/test-helpers';
import templateOnly from '@ember/component/template-only';
-import hasEmberVersion from '@ember/test-helpers/has-ember-version';
import { setResolverRegistry } from '../helpers/resolver';
import { hbs } from 'ember-cli-htmlbars';
import { precompileTemplate } from '@ember/template-compilation';
@@ -149,60 +148,56 @@ module('setupRenderingContext "real world"', function (hooks) {
});
module('lexical scope access', function () {
- if (hasEmberVersion(3, 28)) {
- test('can render components passed as locals', async function (assert) {
- let add = helper(function ([first, second]) {
- return first + second;
- });
-
- await render(
- precompileTemplate('{{add 1 3}}', {
- scope() {
- return { add };
- },
- })
- );
-
- assert.equal(this.element.textContent, '4');
+ test('can render components passed as locals', async function (assert) {
+ let add = helper(function ([first, second]) {
+ return first + second;
});
- }
+
+ await render(
+ precompileTemplate('{{add 1 3}}', {
+ scope() {
+ return { add };
+ },
+ })
+ );
+
+ assert.equal(this.element.textContent, '4');
+ });
});
module('render with a component', function () {
- if (hasEmberVersion(3, 25)) {
- test('can render locally defined components', async function (assert) {
- class MyComponent extends GlimmerComponent {}
+ test('can render locally defined components', async function (assert) {
+ class MyComponent extends GlimmerComponent {}
- setComponentTemplate(hbs`my name is {{@name}}`, MyComponent);
+ setComponentTemplate(hbs`my name is {{@name}}`, MyComponent);
- const somePerson = new (class {
- @tracked name = 'Zoey';
- })();
+ const somePerson = new (class {
+ @tracked name = 'Zoey';
+ })();
- const template = precompileTemplate(
- '
Hello!
`); - - assert.equal(this.element.textContent, 'Hello!'); - }); - } else { - test('render exposes an `.element` property without an application template wrapper', async function (assert) { - let rootElement = document.getElementById('ember-testing'); - assert.equal( - this.element, - rootElement, - 'this.element should _be_ rootElement' - ); + test('render exposes an `.element` property without an application template wrapper', async function (assert) { + let rootElement = document.getElementById('ember-testing'); + assert.equal( + this.element, + rootElement, + 'this.element should _be_ rootElement' + ); - await render(hbs`Hello!
`); + await render(hbs`Hello!
`); - assert.equal(this.element.textContent, 'Hello!'); - }); - } + assert.equal(this.element.textContent, 'Hello!'); + }); test('is settled after rendering', async function (assert) { await render(hbs`Hi!`); @@ -557,346 +537,179 @@ module('setupRenderingContext', function (hooks) { assert.equal(getOwner(this), this.owner); }); - if (hasEmberVersion(3, 25)) { - // render tests for components in 3.25+ where we can use lexical scope - module('using render with a component in Ember >= 3.25', function () { - test('works with a template-only component', async function (assert) { - const name = 'Chris'; - - const template = precompileTemplate( - 'hello my name is {{name}}
', - { - scope() { - return { - name, - }; - }, - } - ); - const component = setComponentTemplate(template, templateOnly()); - await render(component); - assert.equal( - this.element.textContent, - 'hello my name is Chris', - 'has rendered content' - ); - }); - - test('works with a glimmer component', async function (assert) { - const name = 'Chris'; - const template = precompileTemplate( - 'hello my name is {{name}} and my favorite color is {{this.favoriteColor}}
', - { - scope() { - return { - name, - }; - }, - } - ); + // render tests for components in 3.25+ where we can use lexical scope + module('using render with a component in Ember >= 3.25', function () { + test('works with a template-only component', async function (assert) { + const name = 'Chris'; - class Foo extends GlimmerComponent { - favoriteColor = 'red'; + const template = precompileTemplate( + 'hello my name is {{name}}
', + { + scope() { + return { + name, + }; + }, } + ); + const component = setComponentTemplate(template, templateOnly()); + await render(component); + assert.equal( + this.element.textContent, + 'hello my name is Chris', + 'has rendered content' + ); + }); - setComponentTemplate(template, Foo); - await render(Foo); - - assert.equal( - this.element.textContent, - 'hello my name is Chris and my favorite color is red', - 'has rendered content' - ); - }); - - test('works with a classic component', async function (assert) { - const name = 'Chris'; - const template = precompileTemplate( - 'hello my name is {{name}} and my favorite color is {{this.favoriteColor}}
', - { - scope() { - return { - name, - }; - }, - } - ); - - const Foo = Component.extend({ - favoriteColor: 'red', - }); - - setComponentTemplate(template, Foo); - await render(Foo); - - assert.equal( - this.element.textContent, - 'hello my name is Chris and my favorite color is red', - 'has rendered content' - ); - }); - - test('components passed to render do *not* have access to the test context', async function (assert) { - const template = precompileTemplate( - 'the value of foo is {{this.foo}}' - ); - - class Foo extends GlimmerComponent { - foo = 'foo'; + test('works with a glimmer component', async function (assert) { + const name = 'Chris'; + const template = precompileTemplate( + 'hello my name is {{name}} and my favorite color is {{this.favoriteColor}}
', + { + scope() { + return { + name, + }; + }, } + ); - const component = setComponentTemplate(template, Foo); - - this.foo = 'bar'; + class Foo extends GlimmerComponent { + favoriteColor = 'red'; + } - await render(component); + setComponentTemplate(template, Foo); + await render(Foo); - assert.equal(this.element.textContent, 'the value of foo is foo'); - }); - - test('setting properties on the test context *before* rendering a component throws an assertion', async function (assert) { - assert.expect(1); - const template = precompileTemplate( - 'the value of foo is {{this.foo}}' - ); + assert.equal( + this.element.textContent, + 'hello my name is Chris and my favorite color is red', + 'has rendered content' + ); + }); - class Foo extends GlimmerComponent {} - - const component = setComponentTemplate(template, Foo); - - this.set('foo', 'FOO'); - this.set('bar', 'BAR'); - this.setProperties({ - baz: 'BAZ', - baq: 'BAQ', - }); - - let error; - try { - await render(component); - } catch (err) { - error = err; - } finally { - assert.equal( - error.toString(), - `Error: Assertion Failed: You cannot call \`this.set\` or \`this.setProperties\` when passing a component to \`render\`, but they were called for the following properties: - - foo - - bar - - baz - - baq` - ); + test('works with a classic component', async function (assert) { + const name = 'Chris'; + const template = precompileTemplate( + 'hello my name is {{name}} and my favorite color is {{this.favoriteColor}}
', + { + scope() { + return { + name, + }; + }, } - }); - - test('setting properties on the test context *after* rendering a component throws an assertion', async function (assert) { - const template = precompileTemplate( - 'the value of foo is {{this.foo}}' - ); + ); - class Foo extends GlimmerComponent {} + const Foo = Component.extend({ + favoriteColor: 'red', + }); - const component = setComponentTemplate(template, Foo); + setComponentTemplate(template, Foo); + await render(Foo); - await render(component); + assert.equal( + this.element.textContent, + 'hello my name is Chris and my favorite color is red', + 'has rendered content' + ); + }); - assert.throws( - () => this.set('foo', 'FOO'), - (err) => { - return err - .toString() - .includes( - 'You cannot call `this.set` when passing a component to `render()` (the rendered component does not have access to the test context).' - ); - }, - 'errors on this.set' - ); + test('components passed to render do *not* have access to the test context', async function (assert) { + const template = precompileTemplate('the value of foo is {{this.foo}}'); - assert.throws( - () => this.setProperties({ foo: 'bar?' }), - (err) => { - return err - .toString() - .includes( - 'You cannot call `this.setProperties` when passing a component to `render()` (the rendered component does not have access to the test context)' - ); - }, - 'errors on this.setProperties' - ); - }); + class Foo extends GlimmerComponent { + foo = 'foo'; + } - test('setting properties on the test context when rendering a template does not throw an assertion', async function (assert) { - const template = precompileTemplate( - 'the value of foo is {{this.foo}}' - ); + const component = setComponentTemplate(template, Foo); - this.set('foo', 'FOO'); - this.setProperties({ - foo: 'bar?', - }); + this.foo = 'bar'; - await render(template); + await render(component); - assert.true(true, 'no assertions are thrown'); - }); + assert.equal(this.element.textContent, 'the value of foo is foo'); }); - } else if (hasEmberVersion(3, 24)) { - module('using render with a component in Ember < 3.25', function () { - test('works with a template-only component', async function (assert) { - const template = precompileTemplate( - 'this is a template-only component with no dynamic content
' - ); - const component = setComponentTemplate(template, templateOnly()); - await render(component); - assert.equal( - this.element.textContent, - 'this is a template-only component with no dynamic content', - 'has rendered content' - ); - }); - test('works with a glimmer component', async function (assert) { - const template = precompileTemplate( - 'hello my favorite color is {{this.favoriteColor}}
' - ); + test('setting properties on the test context *before* rendering a component throws an assertion', async function (assert) { + assert.expect(1); + const template = precompileTemplate('the value of foo is {{this.foo}}'); - class Foo extends GlimmerComponent { - favoriteColor = 'red'; - } + class Foo extends GlimmerComponent {} - const component = setComponentTemplate(template, Foo); + const component = setComponentTemplate(template, Foo); - await render(component); - assert.equal( - this.element.textContent, - 'hello my favorite color is red', - 'has rendered content' - ); + this.set('foo', 'FOO'); + this.set('bar', 'BAR'); + this.setProperties({ + baz: 'BAZ', + baq: 'BAQ', }); - test('works with a classic component', async function (assert) { - const template = precompileTemplate( - 'hello my favorite color is {{this.favoriteColor}}
' - ); - - const Foo = Component.extend({ - favoriteColor: 'red', - }); - - const component = setComponentTemplate(template, Foo); - + let error; + try { await render(component); - + } catch (err) { + error = err; + } finally { assert.equal( - this.element.textContent, - 'hello my favorite color is red', - 'has rendered content' - ); - }); - - test('components passed to render do *not* have access to the test context', async function (assert) { - const template = precompileTemplate( - 'the value of foo is {{this.foo}}' - ); - - class Foo extends GlimmerComponent { - foo = 'foo'; - } - - const component = setComponentTemplate(template, Foo); - - this.foo = 'bar'; - - await render(component); - - assert.equal(this.element.textContent, 'the value of foo is foo'); - }); - - test('setting properties on the test context *before* rendering a component throws an assertion', async function (assert) { - assert.expect(1); - const template = precompileTemplate( - 'the value of foo is {{this.foo}}' - ); - - class Foo extends GlimmerComponent {} - - const component = setComponentTemplate(template, Foo); - - this.set('foo', 'FOO'); - this.set('bar', 'BAR'); - this.setProperties({ - baz: 'BAZ', - baq: 'BAQ', - }); - - let error; - try { - await render(component); - } catch (err) { - error = err; - } finally { - assert.equal( - error.toString(), - `Error: Assertion Failed: You cannot call \`this.set\` or \`this.setProperties\` when passing a component to \`render\`, but they were called for the following properties: + error.toString(), + `Error: Assertion Failed: You cannot call \`this.set\` or \`this.setProperties\` when passing a component to \`render\`, but they were called for the following properties: - foo - bar - baz - baq` - ); - } - }); - - test('setting properties on the test context *after* rendering a component throws an assertion', async function (assert) { - const template = precompileTemplate( - 'the value of foo is {{this.foo}}' ); + } + }); - class Foo extends GlimmerComponent {} + test('setting properties on the test context *after* rendering a component throws an assertion', async function (assert) { + const template = precompileTemplate('the value of foo is {{this.foo}}'); - const component = setComponentTemplate(template, Foo); + class Foo extends GlimmerComponent {} - await render(component); + const component = setComponentTemplate(template, Foo); - assert.throws( - () => this.set('foo', 'FOO'), - (err) => { - return err - .toString() - .includes( - 'You cannot call `this.set` when passing a component to `render()` (the rendered component does not have access to the test context).' - ); - }, - 'errors on this.set' - ); - - assert.throws( - () => this.setProperties({ foo: 'bar?' }), - (err) => { - return err - .toString() - .includes( - 'You cannot call `this.setProperties` when passing a component to `render()` (the rendered component does not have access to the test context)' - ); - }, - 'errors on this.setProperties' - ); - }); + await render(component); - test('setting properties on the test context when rendering a template does not throw an assertion', async function (assert) { - const template = precompileTemplate( - 'the value of foo is {{this.foo}}' - ); + assert.throws( + () => this.set('foo', 'FOO'), + (err) => { + return err + .toString() + .includes( + 'You cannot call `this.set` when passing a component to `render()` (the rendered component does not have access to the test context).' + ); + }, + 'errors on this.set' + ); - this.set('foo', 'FOO'); - this.setProperties({ - foo: 'bar?', - }); + assert.throws( + () => this.setProperties({ foo: 'bar?' }), + (err) => { + return err + .toString() + .includes( + 'You cannot call `this.setProperties` when passing a component to `render()` (the rendered component does not have access to the test context)' + ); + }, + 'errors on this.setProperties' + ); + }); - await render(template); + test('setting properties on the test context when rendering a template does not throw an assertion', async function (assert) { + const template = precompileTemplate('the value of foo is {{this.foo}}'); - assert.true(true, 'no assertions are thrown'); + this.set('foo', 'FOO'); + this.setProperties({ + foo: 'bar?', }); + + await render(template); + + assert.true(true, 'no assertions are thrown'); }); - } + }); } module('with only application set', function (hooks) { diff --git a/test-app/tests/unit/teardown-context-test.js b/test-app/tests/unit/teardown-context-test.js index 986f1007f..690088cd3 100644 --- a/test-app/tests/unit/teardown-context-test.js +++ b/test-app/tests/unit/teardown-context-test.js @@ -9,7 +9,6 @@ import { isSettled, } from '@ember/test-helpers'; import { setResolverRegistry } from '../helpers/resolver'; -import hasEmberVersion from '@ember/test-helpers/has-ember-version'; import Ember from 'ember'; import hasjQuery from '../helpers/has-jquery'; import ajax from '../helpers/ajax'; @@ -17,10 +16,6 @@ import Pretender from 'pretender'; import setupManualTestWaiter from '../helpers/manual-test-waiter'; module('teardownContext', function (hooks) { - if (!hasEmberVersion(2, 4)) { - return; - } - setupManualTestWaiter(hooks); let context;