Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Expand Up @@ -37,7 +37,7 @@ import { BOUNDS, DIRTY_TAG, HAS_BLOCK, IS_DISPATCHING_ATTRS, ROOT_REF } from '..
import Environment from '../environment';
import { DynamicScope } from '../renderer';
import RuntimeResolver from '../resolver';
import { Factory as TemplateFactory, OwnedTemplate } from '../template';
import { Factory as TemplateFactory, isTemplateFactory, OwnedTemplate } from '../template';
import {
AttributeBinding,
ClassNameBinding,
Expand All @@ -61,10 +61,6 @@ function aliasIdToElementId(args: Arguments, props: any) {
}
}

function isTemplateFactory(template: OwnedTemplate | TemplateFactory): template is TemplateFactory {
return typeof template === 'function';
}

// We must traverse the attributeBindings in reverse keeping track of
// what has already been applied. This is essentially refining the concatenated
// properties applying right to left.
Expand Down
8 changes: 8 additions & 0 deletions packages/@ember/-internals/glimmer/lib/syntax/outlet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
import * as WireFormat from '@glimmer/wire-format';
import { OutletComponentDefinition, OutletDefinitionState } from '../component-managers/outlet';
import { DynamicScope } from '../renderer';
import { isTemplateFactory } from '../template';
import { OutletReference, OutletState } from '../utils/outlet';

/**
Expand Down Expand Up @@ -124,6 +125,13 @@ function stateFor(
if (render === undefined) return null;
let template = render.template;
if (template === undefined) return null;

// this guard can be removed once @ember/test-helpers@1.6.0 has "aged out"
// and is no longer considered supported

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

So is the intention to still merge and release emberjs/ember-test-helpers#677 or to rather make a new backwards-incompatible release of @ember/test-helpers that drops support for all Ember versions prior to #18096? 🤔

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Ya, I still think we should still land emberjs/ember-test-helpers#677.

if (isTemplateFactory(template)) {
template = template(render.owner);
}

return {
ref,
name: render.name,
Expand Down
4 changes: 4 additions & 0 deletions packages/@ember/-internals/glimmer/lib/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import { SerializedTemplateWithLazyBlock } from '@glimmer/wire-format';
export type StaticTemplate = SerializedTemplateWithLazyBlock<StaticTemplateMeta>;
export type OwnedTemplate = Template<OwnedTemplateMeta>;

export function isTemplateFactory(template: OwnedTemplate | Factory): template is Factory {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should we rename the interface below to TemplateFactory?

return typeof template === 'function';
}

export function id(factory: Factory): string {
return factory.__id;
}
Expand Down
4 changes: 2 additions & 2 deletions packages/@ember/-internals/glimmer/lib/utils/outlet.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Owner } from '@ember/-internals/owner';
import { Opaque } from '@glimmer/interfaces';
import { combine, DirtyableTag, Reference, Tag, VersionedPathReference } from '@glimmer/reference';
import { OwnedTemplate } from '../template';
import { Factory as TemplateFactory, OwnedTemplate } from '../template';

export interface RenderState {
/**
Expand Down Expand Up @@ -34,7 +34,7 @@ export interface RenderState {
/**
* template (the layout of the outlet component)
*/
template: OwnedTemplate | undefined;
template: OwnedTemplate | TemplateFactory | undefined;
}

export interface Outlets {
Expand Down
131 changes: 131 additions & 0 deletions packages/ember/tests/ember-test-helpers-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import { Promise } from 'rsvp';
import Application from '@ember/application';
import { run, hasScheduledTimers, getCurrentRunLoop } from '@ember/runloop';
import { compile } from 'ember-template-compiler';

const { module, test } = QUnit;

/*
This test file is intended to emulate what @ember/test-helpers does, and
should be considered a "smoke test" of when a given change will break
existing versions of @ember/test-helpers.

This generally means that we will have to represent multiple versions of
`@ember/test-helpers` here (will make a nested module for each significant
revision).
*/
module('@ember/test-helpers emulation test', function() {
module('v1.6.0', function() {
let EMPTY_TEMPLATE = compile('');

function settled() {
return new Promise(function(resolve) {
let watcher = setInterval(() => {
if (getCurrentRunLoop() || hasScheduledTimers()) {
return;
}

// Stop polling
clearInterval(watcher);

// Synchronously resolve the promise
run(null, resolve);
}, 10);
});
}

async function setupContext(context) {
// condensed version of https://github.com/emberjs/ember-test-helpers/blob/v1.6.0/addon-test-support/%40ember/test-helpers/build-owner.ts#L38
// without support for "custom resolver"
await context.application.boot();

context.owner = await context.application.buildInstance().boot();
}

function setupRenderingContext(context) {
let { owner } = context;
let OutletView = owner.factoryFor('view:-outlet');
let toplevelView = OutletView.create();

owner.register('-top-level-view:main', {
create() {
return toplevelView;
},
});

// initially render a simple empty template
return render(EMPTY_TEMPLATE, context).then(() => {
let rootElement = document.querySelector(owner.rootElement);
run(toplevelView, 'appendTo', rootElement);

context.element = rootElement;

return settled();
});
}

let templateId = 0;
function render(template, context) {
let { owner } = context;
let toplevelView = owner.lookup('-top-level-view:main');
let OutletTemplate = owner.lookup('template:-outlet');
templateId += 1;
let templateFullName = `template:-undertest-${templateId}`;
owner.register(templateFullName, template);

let outletState = {
render: {
owner,
into: undefined,
outlet: 'main',
name: 'application',
controller: undefined,
ViewClass: undefined,
template: OutletTemplate,
},

outlets: {
main: {
render: {
owner,
into: undefined,
outlet: 'main',
name: 'index',
controller: context,
ViewClass: undefined,
template: owner.lookup(templateFullName),
outlets: {},
},
outlets: {},
},
},
};
toplevelView.setOutletState(outletState);

return settled();
}

module('setupRenderingContext', function(hooks) {
hooks.beforeEach(async function() {
this.application = Application.create({
rootElement: '#qunit-fixture',
autoboot: false,
});

await setupContext(this);
await setupRenderingContext(this);
});

hooks.afterEach(function() {
run(this.owner, 'destroy');
run(this.application, 'destroy');
});

test('it basically works', async function(assert) {
await render(compile('Hi!'), this);

assert.equal(this.element.textContent, 'Hi!');
});
});
});
});