Skip to content

Commit

Permalink
hookable
Browse files Browse the repository at this point in the history
  • Loading branch information
artemgurzhii committed May 3, 2019
1 parent d3daa10 commit db0e56e
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 14 deletions.
52 changes: 52 additions & 0 deletions addon-test-support/-private/hooks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { typeOf } from '@ember/utils';
import { assert } from '@ember/debug';

const SUPPORTED_BEFORE_EVENTS = [
'blur'
];

const SUPPORTED_AFTER_EVENTS = [
'blur'
];

const validateHook = (hook, supportedEvents) => {
const isString = typeOf(hook) === 'string';

if (isString) {
assert('should be of `string` type', supportedEvents.includes(hook));
}

return typeOf(hook) === 'function';
}

export function hookable(property, hooks = {}) {
// Validate options
assert('should be of `object` type', typeOf(hooks) === 'object');

// Validate option keys
if (hooks.before) validateHook(hooks.before, SUPPORTED_BEFORE_EVENTS);
if (hooks.after) validateHook(hooks.after, SUPPORTED_AFTER_EVENTS);

return function(selector, options) {
const descriptor = property(selector, options);

return {
isDescriptor: true,

get(key) {
const fn = descriptor.get.call(this, key);

return function() {
// Async before and after hooks? Any use case for that?
hooks.before();

fn.call(this, ...arguments);

hooks.after();

return this;
}
}
}
}
}
1 change: 1 addition & 0 deletions addon-test-support/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { visitable } from './properties/visitable'; export { visitable };
export { findElement } from './extend/find-element';
export { findElementWithAssert } from './extend/find-element-with-assert';
export { buildSelector, getContext } from './-private/helpers';
export { hookable } from './-private/hooks';

export default {
attribute,
Expand Down
92 changes: 78 additions & 14 deletions tests/unit/-private/properties/fillable-test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { moduleForProperty } from '../../../helpers/properties';
import { create, fillable, selectable } from 'ember-cli-page-object';
import { hookable, create, fillable, selectable } from 'ember-cli-page-object';

window.hookable = hookable;

/* eslint-disable no-console */
moduleForProperty('fillable', function(test) {
test("calls fillIn method belonging to execution context", async function(assert) {
assert.expect(1);
Expand All @@ -9,8 +12,12 @@ moduleForProperty('fillable', function(test) {
let expectedText = 'dummy text';
let page;

const customFillable = hookable(fillable, {
before() { console.log('before') },
after() { console.log('after') },
});
page = create({
foo: fillable(expectedSelector)
foo: customFillable(expectedSelector)
});

await this.adapter.createTemplate(this, page, '<input>');
Expand Down Expand Up @@ -50,9 +57,13 @@ moduleForProperty('fillable', function(test) {
test(`looks for ${tagName} with ${attrName}`, async function(assert) {
let expectedText = 'dummy text';
let clue = 'clue';
const customFillable = hookable(fillable, {
before() { console.log('before') },
after() { console.log('after') },
});
let page = create({
scope: '.scope',
foo: fillable()
foo: customFillable()
});

await this.adapter.createTemplate(this, page, `<div class="scope">${template}</div>`);
Expand All @@ -67,9 +78,13 @@ moduleForProperty('fillable', function(test) {
test(`looks for [contenteditable] with ${attrName}`, async function(assert) {
let expectedText = 'dummy text';
let clue = 'clue';
const customFillable = hookable(fillable, {
before() { console.log('before') },
after() { console.log('after') },
});
let page = create({
scope: '.scope',
foo: fillable()
foo: customFillable()
});

await this.adapter.createTemplate(this, page, `<div class="scope"><div contenteditable ${attrName}="clue"></div></div>`);
Expand All @@ -83,8 +98,14 @@ moduleForProperty('fillable', function(test) {
test('looks for elements inside the scope', async function(assert) {
assert.expect(1);

// NOTE: works as expected
const customFillable = hookable(fillable, {
before() { console.log('before') },
after() { console.log('after') },
});

let page = create({
foo: fillable('input', { scope: '.scope' })
foo: customFillable('input', { scope: '.scope' })
});

await this.adapter.createTemplate(this, page, '<div class="scope"><input></div>');
Expand All @@ -97,10 +118,16 @@ moduleForProperty('fillable', function(test) {
test("looks for elements inside page's scope", async function(assert) {
assert.expect(1);

// NOTE: works as expected
const customFillable = hookable(fillable, {
before() { console.log('before') },
after() { console.log('after') },
});

let page = create({
scope: '.scope',

foo: fillable('input')
foo: customFillable('input'),
});

await this.adapter.createTemplate(this, page, '<div class="scope"><input></div>');
Expand All @@ -113,9 +140,13 @@ moduleForProperty('fillable', function(test) {
test('resets scope', async function(assert) {
assert.expect(1);

const customFillable = hookable(fillable, {
before() { console.log('before') },
after() { console.log('after') },
});
let page = create({
scope: '.scope',
foo: fillable('input', { resetScope: true })
foo: customFillable('input', { resetScope: true })
});

await this.adapter.createTemplate(this, page, '<input>');
Expand All @@ -128,8 +159,14 @@ moduleForProperty('fillable', function(test) {
test('returns chainable object', async function(assert) {
assert.expect(1);

// NOTE: works as expected
const customFillable = hookable(fillable, {
before() { console.log('before') },
after() { console.log('after') },
});

let page = create({
foo: fillable('input')
foo: customFillable('input')
});

await this.adapter.createTemplate(this, page, '<input>');
Expand All @@ -143,8 +180,13 @@ moduleForProperty('fillable', function(test) {
assert.expect(1);

let expectedSelector = 'input:eq(3)';

const customFillable = hookable(fillable, {
before() { console.log('before') },
after() { console.log('after') },
});
let page = create({
foo: fillable('input', { at: 3 })
foo: customFillable('input', { at: 3 })
});

await this.adapter.createTemplate(this, page, '<input><input><input><input>');
Expand All @@ -159,8 +201,12 @@ moduleForProperty('fillable', function(test) {

let expectedSelector = 'input';
let expectedText = 'dummy text';
const customSelectable = hookable(selectable, {
before() { console.log('before') },
after() { console.log('after') },
});
let page = create({
foo: selectable(expectedSelector)
foo: customSelectable(expectedSelector)
});

await this.adapter.createTemplate(this, page, '<input>');
Expand All @@ -176,8 +222,12 @@ moduleForProperty('fillable', function(test) {
let expectedContext = '#alternate-ember-testing';
let expectedSelector = 'input';
let expectedText = 'foo';
const customFillable = hookable(fillable, {
before() { console.log('before') },
after() { console.log('after') },
});
let page = create({
foo: fillable(expectedSelector, { testContainer: expectedContext })
foo: customFillable(expectedSelector, { testContainer: expectedContext })
});

await this.adapter.createTemplate(this, page, '<input>', { useAlternateContainer: true });
Expand All @@ -193,9 +243,13 @@ moduleForProperty('fillable', function(test) {
let expectedContext = '#alternate-ember-testing';
let expectedSelector = 'input';
let expectedText = 'foo';
const customFillable = hookable(fillable, {
before() { console.log('before') },
after() { console.log('after') },
});
let page = create({
testContainer: expectedContext,
foo: fillable(expectedSelector)
foo: customFillable(expectedSelector)
});

await this.adapter.createTemplate(this, page, '<input>', { useAlternateContainer: true });
Expand All @@ -207,12 +261,16 @@ moduleForProperty('fillable', function(test) {

test("raises an error when the element doesn't exist", async function(assert) {
assert.expect(1);
const customFillable = hookable(fillable, {
before() { console.log('before') },
after() { console.log('after') },
});

let page = create({
foo: {
bar: {
baz: {
qux: fillable('input')
qux: customFillable('input')
}
}
}
Expand All @@ -226,8 +284,12 @@ moduleForProperty('fillable', function(test) {
});

test('raises an error when the element has contenteditable="false"', async function(assert) {
const customFillable = hookable(fillable, {
before() { console.log('before') },
after() { console.log('after') },
});
let page = create({
foo: fillable('div')
foo: customFillable('div')
});

await this.adapter.createTemplate(this, page, '<div contenteditable="false">');
Expand All @@ -237,3 +299,5 @@ moduleForProperty('fillable', function(test) {
}, /contenteditable/, 'Element should not be fillable because contenteditable="false"');
});
});

/* eslint-enable no-console */

0 comments on commit db0e56e

Please sign in to comment.