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

Initial implementation of emberjs/rfcs#415 #1

Merged
merged 3 commits into from
Jan 28, 2019
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
Empty file removed addon/.gitkeep
Empty file.
17 changes: 17 additions & 0 deletions addon/modifiers/did-insert.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import Ember from 'ember';

export default Ember._setModifierManager(
() => ({
createModifier() {},

installModifier(_state, element, args) {
let [fn, ...positional] = args.positional;

fn(element, positional, args.named);
},

updateModifier() {},
destroyModifier() {},
}),
class DidInsertModifier {}
);
22 changes: 22 additions & 0 deletions addon/modifiers/did-update.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import Ember from 'ember';

export default Ember._setModifierManager(
() => ({
createModifier() {
return { element: null };
},
installModifier(state, element) {
// save element into state bucket
state.element = element;
},

updateModifier({ element }, args) {
let [fn, ...positional] = args.positional;

fn(element, positional, args.named);
},

destroyModifier() {},
}),
class DidUpdateModifier {}
);
22 changes: 22 additions & 0 deletions addon/modifiers/will-destroy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import Ember from 'ember';

export default Ember._setModifierManager(
() => ({
createModifier() {
return { element: null };
},

installModifier(state, element) {
state.element = element;
},

updateModifier() {},

destroyModifier({ element }, args) {
let [fn, ...positional] = args.positional;

fn(element, positional, args.named);
},
}),
class WillDestroyModifier {}
);
Empty file removed app/.gitkeep
Empty file.
1 change: 1 addition & 0 deletions app/modifiers/did-insert.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from '@ember/render-modifiers/modifiers/did-insert';
1 change: 1 addition & 0 deletions app/modifiers/did-update.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from '@ember/render-modifiers/modifiers/did-update';
1 change: 1 addition & 0 deletions app/modifiers/will-destroy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from '@ember/render-modifiers/modifiers/will-destroy';
79 changes: 79 additions & 0 deletions tests/integration/modifiers/did-insert-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
import Component from '@ember/component';

module('Integration | Modifier | did-insert', function(hooks) {
setupRenderingTest(hooks);

test('it basically works', async function(assert) {
assert.expect(2);

this.someMethod = element => {
assert.equal(element.tagName, 'DIV', 'correct element tagName');
assert.dom(element).hasAttribute('data-foo', 'some-thing');
};
await render(hbs`<div data-foo="some-thing" {{did-insert this.someMethod}}></div>`);
});

test('it can accept arguments', async function(assert) {
assert.expect(4);

this.someMethod = (element, positional, named) => {
assert.equal(element.tagName, 'DIV', 'correct element tagName');
assert.dom(element).hasAttribute('data-foo', 'some-thing');

assert.namedArgsEqual(named, { some: 'hash-value' }, 'named args match');
assert.deepEqual(positional, ['some-positional-value'], 'positional args match');
};

await render(
hbs`<div data-foo="some-thing" {{did-insert this.someMethod "some-positional-value" some="hash-value"}}></div>`
);
});

test('it is not invoked again when arguments change', async function(assert) {
assert.expect(4);

this.someMethod = (element, positional, named) => {
assert.equal(element.tagName, 'DIV', 'correct element tagName');
assert.dom(element).hasAttribute('data-foo', 'some-thing');

assert.namedArgsEqual(named, {}, 'named args match');
assert.deepEqual(positional, ['initial'], 'positional args match');
};

this.set('firstArg', 'initial');
await render(
hbs`<div data-foo="some-thing" {{did-insert this.someMethod this.firstArg}}></div>`
);
this.set('firstArg', 'updated');
});

test('adding class on insert (RFC example)', async function(assert) {
this.owner.register(
'component:sometimes-fades-in',
Component.extend({
fadeIn(element) {
element.classList.add('fade-in');
},
})
);

this.owner.register(
'template:components/sometimes-fades-in',
hbs`
{{#if shouldShow}}
<div {{did-insert this.fadeIn}} class="alert">
{{yield}}
</div>
{{/if}}
`
);

await render(hbs`{{sometimes-fades-in shouldShow=true}}`);

assert.dom('.alert').hasClass('fade-in');
});
});
27 changes: 27 additions & 0 deletions tests/integration/modifiers/did-update-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';

module('Integration | Modifier | did-update', function(hooks) {
setupRenderingTest(hooks);

test('it basically works', async function(assert) {
assert.expect(4);

this.someMethod = (element, positional, named) => {
assert.equal(element.tagName, 'DIV', 'correct element tagName');
assert.dom(element).hasAttribute('data-foo', 'some-thing');

assert.namedArgsEqual(named, {}, 'named args match');
assert.deepEqual(positional, ['update'], 'positional args match');
};

this.set('boundValue', 'initial');
await render(
hbs`<div data-foo="some-thing" {{did-update this.someMethod this.boundValue}}></div>`
);

this.set('boundValue', 'update');
});
});
46 changes: 46 additions & 0 deletions tests/integration/modifiers/will-destroy-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';

module('Integration | Modifier | will-destroy', function(hooks) {
setupRenderingTest(hooks);

test('it basically works', async function(assert) {
assert.expect(2);

this.someMethod = element => {
assert.equal(element.tagName, 'DIV', 'correct element tagName');
assert.dom(element).hasAttribute('data-foo', 'some-thing');
};
this.set('show', true);

await render(
hbs`{{#if show}}<div data-foo="some-thing" {{will-destroy this.someMethod}}></div>{{/if}}`
);

// trigger destroy
this.set('show', false);
});

test('it can accept arguments', async function(assert) {
assert.expect(4);

this.someMethod = (element, positional, named) => {
assert.equal(element.tagName, 'DIV', 'correct element tagName');
assert.dom(element).hasAttribute('data-foo', 'some-thing');

assert.namedArgsEqual(named, { some: 'hash-value' }, 'named args match');
assert.deepEqual(positional, ['some-positional-value'], 'positional args match');
};

this.set('show', true);

await render(
hbs`{{#if show}}<div data-foo="some-thing" {{will-destroy this.someMethod "some-positional-value" some="hash-value"}}></div>{{/if}}`
);

// trigger destroy
this.set('show', false);
});
});
10 changes: 10 additions & 0 deletions tests/test-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,17 @@ import Application from '../app';
import config from '../config/environment';
import { setApplication } from '@ember/test-helpers';
import { start } from 'ember-qunit';
import { assign } from '@ember/polyfills';
import QUnit from 'qunit';

setApplication(Application.create(config.APP));

start();

QUnit.assert.namedArgsEqual = function(actual, expected, message) {
// this is needed because older versions of Ember pass an `EmptyObject`
// based object and QUnit fails due to the prototypes not matching
let sanitizedActual = assign({}, actual);

this.deepEqual(sanitizedActual, expected, message);
};