Skip to content

Commit

Permalink
Introduce new dom finders
Browse files Browse the repository at this point in the history
implements #463
  • Loading branch information
yratanov authored and ro0gr committed Jan 24, 2020
1 parent cbe9e65 commit 873e1cd
Show file tree
Hide file tree
Showing 24 changed files with 586 additions and 81 deletions.
20 changes: 14 additions & 6 deletions addon-test-support/-private/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,12 +166,20 @@ export function every(jqArray, cb) {
return A(arr).every((element) => cb($(element)));
}

export function map(jqArray, cb, options = {}) {
let arr = jqArray.get();

const values = A(arr).map(element => cb($(element)));

return options.multiple ? values : values[0];
/**
* @private
*
* Check if all options are in whitelist
*
*/
export function filterWhitelistedOption(options, whitelist) {
const result = {};
for (let [key, value] of Object.entries(options)) {
if(whitelist.includes(key)) {
result[key] = value;
}
}
return result;
}

/**
Expand Down
6 changes: 6 additions & 0 deletions addon-test-support/extend/find-element-with-assert.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { getExecutionContext } from '../-private/execution_context';
import { deprecate } from '@ember/application/deprecations';

/**
* @public
Expand Down Expand Up @@ -36,5 +37,10 @@ import { getExecutionContext } from '../-private/execution_context';
* @throws Will throw an error if multiple elements are matched by selector and multiple option is not set
*/
export function findElementWithAssert(pageObjectNode, targetSelector, options = {}) {
deprecate('findElementWithAssert is deprecated, please use findOne or findMany instead', false, {
id: 'ember-cli-page-object.old-finders',
until: '2.0.0',
url: 'https://ember-cli-page-object.js.org/docs/v1.16.x/deprecations/#old-finders'
});
return getExecutionContext(pageObjectNode).findWithAssert(targetSelector, options);
}
7 changes: 7 additions & 0 deletions addon-test-support/extend/find-element.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { getExecutionContext } from '../-private/execution_context';
import { deprecate } from '@ember/application/deprecations';

/**
* @public
Expand Down Expand Up @@ -34,5 +35,11 @@ import { getExecutionContext } from '../-private/execution_context';
* @throws Will throw an error if multiple elements are matched by selector and multiple option is not set
*/
export function findElement(pageObjectNode, targetSelector, options = {}) {
deprecate('findElement is deprecated, please use findOne or findMany instead', false, {
id: 'ember-cli-page-object.old-finders',
until: '2.0.0',
url: 'https://ember-cli-page-object.js.org/docs/v1.16.x/deprecations/#old-finders'
});

return getExecutionContext(pageObjectNode).find(targetSelector, options);
}
40 changes: 40 additions & 0 deletions addon-test-support/extend/find-many.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { getExecutionContext } from '../-private/execution_context';
import { filterWhitelistedOption } from '../-private/helpers';
/**
* @public
*
* Returns array of elements
*
* @example
*
* import { findMany } from '../extend';
*
* export default function count(selector, options = {}) {
* return {
* isDescriptor: true,
*
* get() {
* return findMany(this, selector, options).length;
* }
* };
* }
*
* @param {Ceibo} pageObjectNode - Node of the tree
* @param {string} targetSelector - Specific CSS selector
* @param {Object} options - Additional options
* @param {boolean} options.resetScope - Do not use inherited scope
* @param {string} options.contains - Filter by using :contains('foo') pseudo-class
* @param {string} options.scope
* @param {number} options.at - Filter by index using :eq(x) pseudo-class
* @param {boolean} options.last - Filter by using :last pseudo-class
* @param {boolean} options.visible - Filter by using :visible pseudo-class
* @param {string} options.testContainer - Context where to search elements in the DOM
* @return {Array} of Element
*/
export function findMany(pageObjectNode, targetSelector, options = {}) {
const filteredOptions = filterWhitelistedOption(options, [
'resetScope', 'visible', 'testContainer', 'contains', 'scope', 'at', 'last'
]);
const opts = Object.assign({}, filteredOptions, { multiple: true });
return getExecutionContext(pageObjectNode).find(targetSelector, opts).get();
}
45 changes: 45 additions & 0 deletions addon-test-support/extend/find-one.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { getExecutionContext } from '../-private/execution_context';
import { filterWhitelistedOption } from "../-private/helpers";

/**
* @public
*
* Returns a element
*
* @example
*
* import { findOne } from 'ember-cli-page-object';
*
* export default function isDisabled(selector, options = {}) {
* return {
* isDescriptor: true,
*
* get() {
* return findOne(this, selector, options).disabled;
* }
* };
* }
*
* @param {Ceibo} pageObjectNode - Node of the tree
* @param {string} targetSelector - Specific CSS selector
* @param {Object} options - Additional options
* @param {boolean} options.resetScope - Do not use inherited scope
* @param {string} options.contains - Filter by using :contains('foo') pseudo-class
* @param {string} options.scope
* @param {number} options.at - Filter by index using :eq(x) pseudo-class
* @param {boolean} options.last - Filter by using :last pseudo-class
* @param {boolean} options.visible - Filter by using :visible pseudo-class
* @param {string} options.testContainer - Context where to search elements in the DOM
* @param {string} options.pageObjectKey - Used in the error message when the element is not found
* @return {Element}
*
* @throws If no elements found
* @throws If more than one element found
*/
export function findOne(pageObjectNode, targetSelector, options = {}) {
const filteredOptions = filterWhitelistedOption(options, [
'resetScope', 'visible', 'testContainer', 'contains', 'at', 'last', 'scope', 'pageObjectKey'
]);
const opts = Object.assign({}, filteredOptions, { multiple: false });
return getExecutionContext(pageObjectNode).findWithAssert(targetSelector, opts).get(0);
}
2 changes: 2 additions & 0 deletions addon-test-support/extend/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export { findElement } from './find-element';
export { findElementWithAssert } from './find-element-with-assert';
export { findOne } from './find-one';
export { findMany } from './find-many';
export { buildSelector, getContext, fullScope } from '../-private/helpers';
import {
register as registerExecutionContext
Expand Down
12 changes: 7 additions & 5 deletions addon-test-support/properties/attribute.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assign, map } from '../-private/helpers';
import { findElementWithAssert } from '../extend';
import { assign } from '../-private/helpers';
import { findMany, findOne } from '../extend';

/**
* @public
Expand Down Expand Up @@ -82,9 +82,11 @@ export function attribute(attributeName, selector, userOptions = {}) {
get(key) {
let options = assign({ pageObjectKey: key }, userOptions);

let elements = findElementWithAssert(this, selector, options);

return map(elements, element => element.attr(attributeName), options);
if (options.multiple) {
return findMany(this, selector, options).map(element => element.getAttribute(attributeName), options);
} else {
return findOne(this, selector, options).getAttribute(attributeName);
}
}
};
}
11 changes: 5 additions & 6 deletions addon-test-support/properties/contains.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { assign, every } from '../-private/helpers';
import { findElementWithAssert } from '../extend';
import { assign } from '../-private/helpers';
import { findMany, findOne } from '../extend';
import { A } from '@ember/array';

/**
* Returns a boolean representing whether an element or a set of elements contains the specified text.
Expand Down Expand Up @@ -97,11 +98,9 @@ export function contains(selector, userOptions = {}) {
return function(textToSearch) {
let options = assign({ pageObjectKey: `${key}("${textToSearch}")` }, userOptions);

let elements = findElementWithAssert(this, selector, options);
let elements = options.multiple ? findMany(this, selector, options) : [findOne(this, selector, options)];

return every(elements, function(element) {
return element.text().indexOf(textToSearch) >= 0;
});
return A(elements).every((element) => element.innerText.indexOf(textToSearch) >= 0);
};
}
};
Expand Down
4 changes: 2 additions & 2 deletions addon-test-support/properties/count.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assign } from '../-private/helpers';
import { findElement } from '../extend';
import { findMany } from '../extend';

/**
* @public
Expand Down Expand Up @@ -90,7 +90,7 @@ export function count(selector, userOptions = {}) {

options = assign(options, { multiple: true });

return findElement(this, selector, options).length;
return findMany(this, selector, options).length;
}
};
}
11 changes: 5 additions & 6 deletions addon-test-support/properties/has-class.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { assign, every } from '../-private/helpers';
import { findElementWithAssert } from '../extend'
import { assign } from '../-private/helpers';
import { findOne, findMany } from '../extend';
import { A } from '@ember/array';

/**
* Validates if an element or a set of elements have a given CSS class.
Expand Down Expand Up @@ -99,11 +100,9 @@ export function hasClass(cssClass, selector, userOptions = {}) {
get(key) {
let options = assign({ pageObjectKey: key }, userOptions);

let elements = findElementWithAssert(this, selector, options);
let elements = options.multiple ? findMany(this, selector, options) : [findOne(this, selector, options)];

return every(elements, function(element) {
return element.hasClass(cssClass);
});
return A(elements).every((element) => element.classList.contains(cssClass));
}
};
}
13 changes: 9 additions & 4 deletions addon-test-support/properties/is-hidden.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { assign, every } from '../-private/helpers';
import { findElement } from '../extend';
import { assign, guardMultiple } from '../-private/helpers';
import { findMany } from '../extend';
import { A } from '@ember/array';
import $ from '-jquery';

/**
* Validates if an element or set of elements is hidden or does not exist in the DOM.
Expand Down Expand Up @@ -106,9 +108,12 @@ export function isHidden(selector, userOptions = {}) {
get(key) {
let options = assign({ pageObjectKey: key }, userOptions);

let elements = findElement(this, selector, options);
let elements = findMany(this, selector, options);

return every(elements, element => element.is(':hidden'));
guardMultiple(elements, selector, options.multiple);

return elements.length === 0 ||
A(elements).every(element => $(element).is(':hidden'));
}
};
}
17 changes: 10 additions & 7 deletions addon-test-support/properties/is-present.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { findElement } from 'ember-cli-page-object';
import { findMany } from '../extend';
import { guardMultiple } from "../-private/helpers";

/**
* Validates if any element matching the target selector is rendered in the DOM.
Expand All @@ -17,7 +18,7 @@ import { findElement } from 'ember-cli-page-object';
* // Lorem <span>ipsum</span>
*
* import { create, isPresent } from 'ember-cli-page-object';
*
*
* const page = create({
* spanIsPresent: isPresent('span')
* });
Expand All @@ -30,7 +31,7 @@ import { findElement } from 'ember-cli-page-object';
* // <span style="display:none">dolor</span>
*
* import { create, isPresent } from 'ember-cli-page-object';
*
*
* const page = create({
* spanIsPresent: isPresent('span', { multiple: true })
* });
Expand All @@ -44,7 +45,7 @@ import { findElement } from 'ember-cli-page-object';
* // </head>
*
* import { create, isPresent } from 'ember-cli-page-object';
*
*
* const page = create({
* notIndexed: isPresent(`meta[name='robots'][content='noindex']`, {
* testContainer: 'head'
Expand All @@ -58,7 +59,7 @@ import { findElement } from 'ember-cli-page-object';
* // Lorem <strong>ipsum</strong>
*
* import { create, isPresent } from 'ember-cli-page-object';
*
*
* const page = create({
* spanIsPresent: isPresent('span')
* });
Expand All @@ -79,11 +80,13 @@ import { findElement } from 'ember-cli-page-object';
*
* @throws Will throw an error if multiple elements are matched by selector and multiple option is not set
*/
export function isPresent(selector, options) {
export function isPresent(selector, options = {}) {
return {
isDescriptor: true,
get() {
return !!findElement(this, selector, options).length;
let elements = findMany(this, selector, options);
guardMultiple(elements, selector, options.multiple);
return elements.length > 0;
}
};
}
13 changes: 7 additions & 6 deletions addon-test-support/properties/is-visible.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { assign, every } from '../-private/helpers';
import { findElement } from '../extend';
import { assign, guardMultiple } from '../-private/helpers';
import { findMany } from '../extend';
import { A } from '@ember/array';
import $ from '-jquery';

/**
* Validates if an element or set of elements are visible.
Expand Down Expand Up @@ -112,15 +114,14 @@ export function isVisible(selector, userOptions = {}) {
get(key) {
let options = assign({ pageObjectKey: key }, userOptions);

let elements = findElement(this, selector, options);
let elements = findMany(this, selector, options);
guardMultiple(elements, selector, options.multiple);

if (elements.length === 0) {
return false;
}

return every(elements, function(element) {
return element.is(':visible');
});
return A(elements).every((element) => $(element).is(':visible'));
}
};
}
11 changes: 5 additions & 6 deletions addon-test-support/properties/not-has-class.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { assign, every } from '../-private/helpers';
import { findElementWithAssert } from '../extend';
import { assign } from '../-private/helpers';
import { findOne, findMany } from '../extend';
import { A } from '@ember/array';

/**
* @public
Expand Down Expand Up @@ -103,11 +104,9 @@ export function notHasClass(cssClass, selector, userOptions = {}) {
get(key) {
let options = assign({ pageObjectKey: key }, userOptions);

let elements = findElementWithAssert(this, selector, options);
let elements = options.multiple ? findMany(this, selector, options) : [findOne(this, selector, options)];

return every(elements, function(element) {
return !element.hasClass(cssClass);
});
return A(elements).every((element) => !element.classList.contains(cssClass));
}
};
}
Loading

0 comments on commit 873e1cd

Please sign in to comment.