Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP for test helper implementation #1

Draft
wants to merge 23 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Ember from 'ember';
import {
macroCondition,
importSync,
dependencySatisfies,
} from '@embroider/macros';
import { InternalComponentManager } from '@glimmer/interfaces';
cafreeman marked this conversation as resolved.
Show resolved Hide resolved

let getComponentManager: (
definition: object,
isOptional?: boolean
) => InternalComponentManager | null;

if (macroCondition(dependencySatisfies('ember-source', '>=3.27.0'))) {
cafreeman marked this conversation as resolved.
Show resolved Hide resolved
getComponentManager =
//@ts-ignore
importSync('@glimmer/manager').getInternalComponentManager;
} else {
getComponentManager = (Ember as any).__loader.require(
'@glimmer/runtime'
).getComponentManager;
}

export default getComponentManager;
33 changes: 33 additions & 0 deletions addon-test-support/@ember/test-helpers/-internal/render-settled.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import Ember from 'ember';
import {
macroCondition,
importSync,
dependencySatisfies,
} from '@embroider/macros';

let renderSettled: () => Promise<void>;

if (macroCondition(dependencySatisfies('ember-source', '>=4.4.0'))) {
cafreeman marked this conversation as resolved.
Show resolved Hide resolved
//@ts-ignore
renderSettled = importSync('@ember/renderer').renderSettled;
cafreeman marked this conversation as resolved.
Show resolved Hide resolved
} else if (macroCondition(dependencySatisfies('ember-source', '>=4.0.0'))) {
//@ts-ignore
renderSettled = importSync('@ember/-internals/glimmer').renderSettled;
} else if (macroCondition(dependencySatisfies('ember-source', '>=3.27.0'))) {
cafreeman marked this conversation as resolved.
Show resolved Hide resolved
//@ts-ignore
renderSettled = importSync('@ember/-internals/glimmer').renderSettled;
} else if (macroCondition(dependencySatisfies('ember-source', '>=3.6.0'))) {
renderSettled = (Ember as any).__loader.require(
'@ember/-internals/glimmer'
).renderSettled;
} else if (macroCondition(dependencySatisfies('ember-source', '>=3.0.0'))) {
renderSettled = renderSettled = (Ember as any).__loader.require(
'ember-glimmer'
).renderSettled;
cafreeman marked this conversation as resolved.
Show resolved Hide resolved
} else {
throw new Error(
'renderSettled is not available before v3.0 of ember-source.'
);
}

export default renderSettled;
1 change: 1 addition & 0 deletions addon-test-support/@ember/test-helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export {
render,
clearRender,
} from './setup-rendering-context';
export { default as rerender } from './rerender';
export {
default as setupApplicationContext,
visit,
Expand Down
13 changes: 13 additions & 0 deletions addon-test-support/@ember/test-helpers/rerender.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import renderSettled from './-internal/render-settled';

/**
Returns a promise which will resolve when rendering has settled. Settled in
this context is defined as when all of the tags in use are "current" (e.g.
`renderers.every(r => r._isValid())`). When this is checked at the _end_ of
the run loop, this essentially guarantees that all rendering is completed.
@public
@returns {Promise<void>} a promise which fulfills when rendering has settled
*/
export default function rerender() {
return renderSettled();
}
30 changes: 23 additions & 7 deletions addon-test-support/@ember/test-helpers/setup-rendering-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ import getTestMetadata, { ITestMetadata } from './test-metadata';
import { deprecate } from '@ember/debug';
import { runHooks } from './-internal/helper-hooks';
import hasEmberVersion from './has-ember-version';
import getComponentManager from './-internal/get-component-manager';
import type { ComponentInstance } from '@glimmer/interfaces';

const OUTLET_TEMPLATE = hbs`{{outlet}}`;
const EMPTY_TEMPLATE = hbs``;
const INVOKE_PROVIDED_COMPONENT = hbs`<this.ProvidedComponent />`;

export interface RenderingTestContext extends TestContext {
render(template: TemplateFactory): Promise<void>;
Expand Down Expand Up @@ -84,20 +87,22 @@ export interface RenderOptions {
Renders the provided template and appends it to the DOM.

@public
@param {CompiledTemplate} template the template to render
@param {CompiledTemplate} templateOrComponent the template to render
@param {RenderOptions} options options hash containing engine owner ({ owner: engineOwner })
@returns {Promise<void>} resolves when settled
*/
export function render(
template: TemplateFactory,
templateOrComponent: TemplateFactory | ComponentInstance,
options?: RenderOptions
): Promise<void> {
let context = getContext();

if (!template) {
if (!templateOrComponent) {
throw new Error('you must pass a template to `render()`');
}

const wasPassedComponent = !!getComponentManager(templateOrComponent, true);

return Promise.resolve()
.then(() => runHooks('render', 'start'))
.then(() => {
Expand All @@ -115,9 +120,20 @@ export function render(
let OutletTemplate = lookupOutletTemplate(owner);
let ownerToRenderFrom = options?.owner || owner;

templateId += 1;
let templateFullName = `template:-undertest-${templateId}`;
ownerToRenderFrom.register(templateFullName, template);
if (wasPassedComponent) {
context = {
ProvidedComponent: templateOrComponent,
};
templateOrComponent = INVOKE_PROVIDED_COMPONENT;
} else {
templateId += 1;
let templateFullName = `template:-undertest-${templateId}`;
ownerToRenderFrom.register(templateFullName, templateOrComponent);
templateOrComponent = lookupTemplate(
ownerToRenderFrom,
templateFullName
);
}

let outletState = {
render: {
Expand All @@ -139,7 +155,7 @@ export function render(
name: 'index',
controller: context,
ViewClass: undefined,
template: lookupTemplate(ownerToRenderFrom, templateFullName),
template: templateOrComponent,
outlets: {},
},
outlets: {},
Expand Down
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,14 @@
"test": "ember test",
"test:all": "ember try:each"
},
"peerDependencies": {
"ember-source": "*"
},
"dependencies": {
"@ember/test-waiters": "^3.0.0",
"@embroider/macros": "^1.5.0",
"@glimmer/interfaces": "^0.84.1",
"@glimmer/manager": "^0.84.1",
cafreeman marked this conversation as resolved.
Show resolved Hide resolved
"broccoli-debug": "^0.6.5",
"broccoli-funnel": "^3.0.8",
"ember-cli-babel": "^7.26.6",
Expand Down
10 changes: 10 additions & 0 deletions tests/integration/settled-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
isSettled,
getSettledState,
render,
rerender,
} from '@ember/test-helpers';
import hasEmberVersion from '@ember/test-helpers/has-ember-version';
import { module, test } from 'qunit';
Expand Down Expand Up @@ -163,6 +164,15 @@ module('settled real-world scenarios', function (hooks) {
assert.equal(this.element.textContent, 'async value');
});

test('rerender', async function (assert) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need more rerender tests, discussed in person

this.owner.register('component:x-test-1', TestComponent1);

await render(hbs`{{x-test-1}}`);
await rerender();

assert.equal(this.element.textContent, 'async value');
});

test('does not error for various argument types', async function (assert) {
assert.expect(0); // no assertions, just shouldn't error

Expand Down
22 changes: 22 additions & 0 deletions tests/unit/setup-rendering-context-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ import {
import { hbs } from 'ember-cli-htmlbars';
import { getOwner } from '@ember/application';
import Engine from '@ember/engine';
import { precompileTemplate } from '@ember/template-compilation';
import { setComponentTemplate } from '@ember/component';
import templateOnly from '@ember/component/template-only';

async function buildEngineOwner(parentOwner, registry) {
parentOwner.register(
Expand Down Expand Up @@ -555,6 +558,25 @@ module('setupRenderingContext', function (hooks) {
assert.equal(getOwner(this), this.owner);
});

test('render accepts a component instead of a template', async function (assert) {
cafreeman marked this conversation as resolved.
Show resolved Hide resolved
const name = 'Chris';
const template = precompileTemplate('<p>hello my name is {{name}}</p>', {
scope() {
return {
name,
};
},
});
const component = setComponentTemplate(template, templateOnly());

await render(component);
assert.equal(
this.element.textContent,
'hello my name is Chris',
'has rendered content'
);
});

module('this.render and this.clearRender deprecations', function () {
test('this.render() and this.clearRender deprecation message', async function (assert) {
await this.render(hbs`<button>Click me</button>`);
Expand Down
Loading