From 4737b98f05a76c44a8aa88d9ac6a7c2e39a42d18 Mon Sep 17 00:00:00 2001 From: Joel Kang Date: Sat, 26 Mar 2016 13:26:45 -0400 Subject: [PATCH] [Glimmer2] Remove block params test and migrate relevant rests to curly-components and with-test --- .../components/curly-components-test.js | 82 +++++++++ .../tests/integration/syntax/with-test.js | 56 ++++++ .../tests/integration/block_params_test.js | 164 ------------------ 3 files changed, 138 insertions(+), 164 deletions(-) delete mode 100644 packages/ember-htmlbars/tests/integration/block_params_test.js diff --git a/packages/ember-glimmer/tests/integration/components/curly-components-test.js b/packages/ember-glimmer/tests/integration/components/curly-components-test.js index 021358e2bf6..b139517950c 100644 --- a/packages/ember-glimmer/tests/integration/components/curly-components-test.js +++ b/packages/ember-glimmer/tests/integration/components/curly-components-test.js @@ -514,6 +514,88 @@ moduleFor('Components test: curly components', class extends RenderingTest { this.assertComponentElement(this.firstChild, { content: 'hello' }); } + ['@test it can yield internal and external properties positionally']() { + let instance; + + let FooBarComponent = Component.extend({ + init() { + this._super(...arguments); + instance = this; + }, + greeting: 'hello' + }); + + this.registerComponent('foo-bar', { ComponentClass: FooBarComponent, template: '{{yield greeting greetee.firstName}}' }); + + this.render('{{#foo-bar greetee=person as |greeting name|}}{{name}} {{person.lastName}}, {{greeting}}{{/foo-bar}}', { + person: { + firstName: 'Joel', + lastName: 'Kang' + } + }); + + this.assertComponentElement(this.firstChild, { content: 'Joel Kang, hello' }); + + this.runTask(() => this.rerender()); + + this.assertComponentElement(this.firstChild, { content: 'Joel Kang, hello' }); + + this.runTask(() => set(this.context, 'person', { firstName: 'Dora', lastName: 'the Explorer' })); + + this.assertComponentElement(this.firstChild, { content: 'Dora the Explorer, hello' }); + + this.runTask(() => set(instance, 'greeting', 'hola')); + + this.assertComponentElement(this.firstChild, { content: 'Dora the Explorer, hola' }); + + this.runTask(() => { + set(instance, 'greeting', 'hello'); + set(this.context, 'person', { + firstName: 'Joel', + lastName: 'Kang' + }); + }); + + this.assertComponentElement(this.firstChild, { content: 'Joel Kang, hello' }); + } + + ['@test #11519 - block param infinite loop']() { + let instance; + let FooBarComponent = Component.extend({ + init() { + this._super(...arguments); + instance = this; + }, + danger: 0 + }); + + this.registerComponent('foo-bar', { ComponentClass: FooBarComponent, template: '{{danger}}{{yield danger}}' }); + + // On initial render, create streams. The bug will not have manifested yet, but at this point + // we have created streams that create a circular invalidation. + this.render(`{{#foo-bar as |dangerBlockParam|}}{{/foo-bar}}`); + + this.assertText('0'); + + // Trigger a non-revalidating re-render. The yielded block will not be dirtied + // nor will block param streams, and thus no infinite loop will occur. + this.runTask(() => this.rerender()); + + this.assertText('0'); + + // Trigger a revalidation, which will cause an infinite loop without the fix + // in place. Note that we do not see the infinite loop is in testing mode, + // because a deprecation warning about re-renders is issued, which Ember + // treats as an exception. + this.runTask(() => set(instance, 'danger', 1)); + + this.assertText('1'); + + this.runTask(() => set(instance, 'danger', 0)); + + this.assertText('0'); + } + ['@test the component and its child components are destroyed'](assert) { let destroyed = { 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0 }; diff --git a/packages/ember-glimmer/tests/integration/syntax/with-test.js b/packages/ember-glimmer/tests/integration/syntax/with-test.js index b8e45eebccc..5dabdfbf96f 100644 --- a/packages/ember-glimmer/tests/integration/syntax/with-test.js +++ b/packages/ember-glimmer/tests/integration/syntax/with-test.js @@ -3,6 +3,7 @@ import { set } from 'ember-metal/property_set'; import { A as emberA } from 'ember-runtime/system/native_array'; import { moduleFor, RenderingTest } from '../../utils/test-case'; import { TogglingSyntaxConditionalsTest } from '../../utils/shared-conditional-tests'; +import { strip } from '../../utils/abstract-test-case'; moduleFor('Syntax test: {{#with}}', class extends TogglingSyntaxConditionalsTest { @@ -292,4 +293,59 @@ moduleFor('Syntax test: Multiple {{#with as}} helpers', class extends RenderingT this.assertText('Los Pivots'); } + ['@test nested {{#with}} blocks should have access to root context']() { + this.render(strip` + {{name}} + {{#with committer1.name as |name|}} + [{{name}} + {{#with committer2.name as |name|}} + [{{name}}] + {{/with}} + {{name}}] + {{/with}} + {{name}} + {{#with committer2.name as |name|}} + [{{name}} + {{#with committer1.name as |name|}} + [{{name}}] + {{/with}} + {{name}}] + {{/with}} + {{name}} + `, { + name: 'ebryn', + committer1: { name: 'trek' }, + committer2: { name: 'machty' } + }); + + this.assertText('ebryn[trek[machty]trek]ebryn[machty[trek]machty]ebryn'); + + this.runTask(() => this.rerender()); + + this.assertText('ebryn[trek[machty]trek]ebryn[machty[trek]machty]ebryn'); + + this.runTask(() => set(this.context, 'name', 'chancancode')); + + this.assertText('chancancode[trek[machty]trek]chancancode[machty[trek]machty]chancancode'); + + this.runTask(() => set(this.context, 'committer1', { name: 'krisselden' })); + + this.assertText('chancancode[krisselden[machty]krisselden]chancancode[machty[krisselden]machty]chancancode'); + + this.runTask(() => { + set(this.context, 'committer1.name', 'wycats'); + set(this.context, 'committer2', { name: 'rwjblue' }); + }); + + this.assertText('chancancode[wycats[rwjblue]wycats]chancancode[rwjblue[wycats]rwjblue]chancancode'); + + this.runTask(() => { + set(this.context, 'name', 'ebryn'); + set(this.context, 'committer1', { name: 'trek' }); + set(this.context, 'committer2', { name: 'machty' }); + }); + + this.assertText('ebryn[trek[machty]trek]ebryn[machty[trek]machty]ebryn'); + } + }); diff --git a/packages/ember-htmlbars/tests/integration/block_params_test.js b/packages/ember-htmlbars/tests/integration/block_params_test.js deleted file mode 100644 index cd1de8aeb38..00000000000 --- a/packages/ember-htmlbars/tests/integration/block_params_test.js +++ /dev/null @@ -1,164 +0,0 @@ -import run from 'ember-metal/run_loop'; -import ComponentLookup from 'ember-views/component_lookup'; -import View from 'ember-views/views/view'; -import Component from 'ember-views/components/component'; -import compile from 'ember-template-compiler/system/compile'; -import { runAppend, runDestroy } from 'ember-runtime/tests/utils'; - -import buildOwner from 'container/tests/test-helpers/build-owner'; -import { OWNER } from 'container/owner'; - -var owner, view; - -import isEnabled from 'ember-metal/features'; -if (!isEnabled('ember-glimmer')) { - // jscs:disable - -QUnit.module('ember-htmlbars: block params', { - setup() { - owner = buildOwner(); - owner.registerOptionsForType('component', { singleton: false }); - owner.registerOptionsForType('view', { singleton: false }); - owner.registerOptionsForType('template', { instantiate: false }); - owner.register('component-lookup:main', ComponentLookup); - }, - - teardown() { - runDestroy(view); - runDestroy(owner); - owner = view = null; - } -}); - -QUnit.test('should raise error if helper not available', function() { - view = View.create({ - template: compile('{{#shouldfail}}{{/shouldfail}}') - }); - - expectAssertion(function() { - runAppend(view); - }, `A helper named 'shouldfail' could not be found`); -}); - -QUnit.test('basic block params usage', function() { - view = View.create({ - committer: { name: 'rwjblue' }, - template: compile('{{#with view.committer.name as |name|}}name: {{name}}, length: {{name.length}}{{/with}}') - }); - - runAppend(view); - - equal(view.$().text(), 'name: rwjblue, length: 7'); - - run(function() { - view.set('committer.name', 'krisselden'); - }); - - equal(view.$().text(), 'name: krisselden, length: 10'); -}); - -QUnit.test('nested block params shadow correctly', function() { - view = View.create({ - context: { name: 'ebryn' }, - committer1: { name: 'trek' }, - committer2: { name: 'machty' }, - template: compile( - '{{name}}' + - '{{#with view.committer1.name as |name|}}' + - '[{{name}}' + - '{{#with view.committer2.name as |name|}}' + - '[{{name}}]' + - '{{/with}}' + - '{{name}}]' + - '{{/with}}' + - '{{name}}' + - '{{#with view.committer2.name as |name|}}' + - '[{{name}}' + - '{{#with view.committer1.name as |name|}}' + - '[{{name}}]' + - '{{/with}}' + - '{{name}}]' + - '{{/with}}' + - '{{name}}' - ) - }); - - runAppend(view); - - equal(view.$().text(), 'ebryn[trek[machty]trek]ebryn[machty[trek]machty]ebryn'); -}); - -QUnit.test('components can yield values', function() { - owner.register('template:components/x-alias', compile('{{yield attrs.param.name}}')); - - view = View.create({ - [OWNER]: owner, - context: { name: 'ebryn' }, - committer1: { name: 'trek' }, - committer2: { name: 'machty' }, - template: compile( - '{{name}}' + - '{{#x-alias param=view.committer1 as |name|}}' + - '[{{name}}' + - '{{#x-alias param=view.committer2 as |name|}}' + - '[{{name}}]' + - '{{/x-alias}}' + - '{{name}}]' + - '{{/x-alias}}' + - '{{name}}' + - '{{#x-alias param=view.committer2 as |name|}}' + - '[{{name}}' + - '{{#x-alias param=view.committer1 as |name|}}' + - '[{{name}}]' + - '{{/x-alias}}' + - '{{name}}]' + - '{{/x-alias}}' + - '{{name}}' - ) - }); - - runAppend(view); - - equal(view.$().text(), 'ebryn[trek[machty]trek]ebryn[machty[trek]machty]ebryn'); - - run(function() { - view.set('committer1', { name: 'wycats' }); - }); - - equal(view.$().text(), 'ebryn[wycats[machty]wycats]ebryn[machty[wycats]machty]ebryn'); -}); - -QUnit.test('#11519 - block param infinite loop', function(assert) { - // To trigger this case, a component must 1) consume a KeyStream and then yield that KeyStream - // into a parent light scope. - owner.register('template:components/block-with-yield', compile('{{danger}} {{yield danger}}')); - - var component; - owner.register('component:block-with-yield', Component.extend({ - init() { - component = this; - return this._super(...arguments); - }, - - danger: 0 - })); - - view = View.create({ - [OWNER]: owner, - template: compile('{{#block-with-yield as |dangerBlockParam|}} {{/block-with-yield}}') - }); - - // On initial render, create streams. The bug will not have manifested yet, but at this point - // we have created streams that create a circular invalidation. - runAppend(view); - - // Trigger a revalidation, which will cause an infinite loop without the fix - // in place. Note that we do not see the infinite loop is in testing mode, - // because a deprecation warning about re-renders is issued, which Ember - // treats as an exception. - run(() => { component.set('danger', 1); }); - - assert.equal(view.$().text().trim(), '1'); -}); - -}