Skip to content

Commit

Permalink
query
Browse files Browse the repository at this point in the history
use Query directly in finders

in order to have get rid of build selector

 - breaking: ignore trailing spaces in selectors
  • Loading branch information
ro0gr committed Nov 24, 2022
1 parent 5f900f3 commit 112202e
Show file tree
Hide file tree
Showing 13 changed files with 541 additions and 190 deletions.
9 changes: 0 additions & 9 deletions addon/src/-private/better-errors.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,4 @@
import Ceibo from '@ro0gr/ceibo';
import { buildSelector } from './build-selector';

export const ELEMENT_NOT_FOUND = 'Element not found.';

export function throwContextualError(node, filters, e) {
const selector = buildSelector(node, filters.selector, filters);

throwBetterError(node, filters.pageObjectKey, e, { selector });
}

/**
* Throws an error with a descriptive message.
Expand Down
92 changes: 6 additions & 86 deletions addon/src/-private/build-selector.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import Ceibo from '@ro0gr/ceibo';
import deprecate from './deprecate';
import { Query } from './query';

/**
* @public
Expand Down Expand Up @@ -46,89 +45,10 @@ import deprecate from './deprecate';
*/

export function buildSelector(node, targetSelector, options) {
return new Selector(node, options.scope, targetSelector, options).toString();
}

export class Selector {
constructor(node, scope, selector, filters) {
this.targetNode = node;
this.targetScope = scope || '';
this.targetSelector = selector || '';
this.targetFilters = filters;
}

toString() {
let scope;
let filters;

if (this.targetFilters.resetScope) {
scope = this.targetScope;
} else {
scope = this.calculateScope(this.targetNode, this.targetScope);
}

if (`${scope} ${this.targetSelector}`.indexOf(',') > -1) {
deprecate(
'comma-separated-selectors',
'Usage of comma separated selectors is deprecated in ember-cli-page-object',
'1.16.0',
'2.0.0'
);
}

filters = this.calculateFilters(this.targetFilters);

let selector = `${scope} ${this.targetSelector}${filters}`.trim();

if (!selector.length) {
// When an empty selector is resolved take the first direct child of the
// testing container.
selector = ':first';
}

return selector;
}

calculateFilters() {
let filters = [];

if (this.targetFilters.visible) {
filters.push(`:visible`);
}

if (this.targetFilters.contains) {
filters.push(`:contains("${this.targetFilters.contains}")`);
}

if (typeof this.targetFilters.at === 'number') {
filters.push(`:eq(${this.targetFilters.at})`);
} else if (this.targetFilters.last) {
filters.push(':last');
}

return filters.join('');
}

calculateScope(node, targetScope) {
let scopes = this.getScopes(node);

scopes.reverse();
scopes.push(targetScope);

return scopes.join(' ').trim();
}

getScopes(node) {
let scopes = [];

if (node.scope) {
scopes.push(node.scope);
}

if (!node.resetScope && Ceibo.parent(node)) {
scopes = scopes.concat(this.calculateScope(Ceibo.parent(node)));
}
const q = new Query(node, {
...options,
selector: targetSelector,
});

return scopes;
}
return q.toString();
}
8 changes: 8 additions & 0 deletions addon/src/-private/element.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,11 @@ export function isVisible(element) {
element.getClientRects().length
);
}

export function text(element) {
return element.textContent;
}

export function containsText(element, searchText) {
return text(element).indexOf(searchText) > -1;
}
71 changes: 35 additions & 36 deletions addon/src/-private/finders.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,27 @@
import { $, findClosestValue, guardMultiple } from './helpers';
import { getAdapter } from '../adapters/index';
import { buildSelector } from './build-selector';
import { throwBetterError, ELEMENT_NOT_FOUND } from './better-errors';

function getContainer(pageObjectNode, options) {
return (
options.testContainer ||
findClosestValue(pageObjectNode, 'testContainer') ||
getAdapter().testContainer
);
}
import { $, guardMultiple } from './helpers';
import { throwBetterError } from './better-errors';
import { Query } from './query';

const ELEMENT_NOT_FOUND = 'Element not found.';

/**
* Finds a single element, otherwise fails
*
* @private
*/
export function findOne(pageObjectNode, targetSelector, options = {}) {
const elements = findMany(pageObjectNode, targetSelector, options);
export function findOne(pageObjectNode, selector, options = {}) {
const query = new Query(pageObjectNode, {
...options,
selector,
});

const elements = query.all();

const selector = buildSelector(pageObjectNode, targetSelector, options);
guardMultiple(elements, selector);
guardMultiple(elements, query);

if (elements.length === 0) {
throwBetterError(pageObjectNode, options.pageObjectKey, ELEMENT_NOT_FOUND, {
selector,
selector: query.toString(),
});
}

Expand All @@ -36,32 +33,32 @@ export function findOne(pageObjectNode, targetSelector, options = {}) {
*
* @private
*/
export function findMany(pageObjectNode, targetSelector, options = {}) {
const selector = buildSelector(pageObjectNode, targetSelector, options);
const container = getContainer(pageObjectNode, options);
export function findMany(pageObjectNode, selector, options = {}) {
const query = new Query(pageObjectNode, {
...options,
selector,
});

return $(selector, container).toArray();
return query.all();
}

/**
* @private
* @deprecated
*/
export function findElementWithAssert(
pageObjectNode,
targetSelector,
options = {}
) {
const selector = buildSelector(pageObjectNode, targetSelector, options);
const container = getContainer(pageObjectNode, options);
export function findElementWithAssert(pageObjectNode, selector, options = {}) {
const query = new Query(pageObjectNode, {
...options,
selector,
});

let $elements = $(selector, container);
let $elements = $(query.all());

guardMultiple($elements, selector, options.multiple);
guardMultiple($elements, query, options.multiple);

if ($elements.length === 0) {
throwBetterError(pageObjectNode, options.pageObjectKey, ELEMENT_NOT_FOUND, {
selector,
selector: query.toString(),
});
}

Expand All @@ -72,13 +69,15 @@ export function findElementWithAssert(
* @private
* @deprecated
*/
export function findElement(pageObjectNode, targetSelector, options = {}) {
const selector = buildSelector(pageObjectNode, targetSelector, options);
const container = getContainer(pageObjectNode, options);
export function findElement(pageObjectNode, selector, options = {}) {
const query = new Query(pageObjectNode, {
...options,
selector,
});

let $elements = $(selector, container);
let $elements = $(query.all());

guardMultiple($elements, selector, options.multiple);
guardMultiple($elements, query, options.multiple);

return $elements;
}
46 changes: 3 additions & 43 deletions addon/src/-private/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@ if (window.jQuery) {
}

export { jQuery as $ };

function isPresent(value) {
return typeof value !== 'undefined';
}
import { Query } from './query';

export function guardMultiple(items, selector, supportMultiple) {
if (items.length > 1 && !supportMultiple) {
Expand Down Expand Up @@ -44,21 +41,6 @@ export function getRoot(node) {
return root;
}

function getAllValuesForProperty(node, property) {
let iterator = node;
let values = [];

while (isPresent(iterator)) {
if (isPresent(iterator[property])) {
values.push(iterator[property]);
}

iterator = Ceibo.parent(iterator);
}

return values;
}

/**
* @public
*
Expand All @@ -68,29 +50,7 @@ function getAllValuesForProperty(node, property) {
* @return {string} Full scope of node
*/
export function fullScope(node) {
let scopes = getAllValuesForProperty(node, 'scope');
const q = new Query(node);

return scopes.reverse().join(' ');
}

/**
* @public
*
* Returns the value of property defined on the closest ancestor of given
* node.
*
* @param {Ceibo} node - Node of the tree
* @param {string} property - Property to look for
* @return {?Object} The value of property on closest node to the given node
*/
export function findClosestValue(node, property) {
if (typeof node[property] !== 'undefined') {
return node[property];
}

let parent = Ceibo.parent(node);

if (typeof parent !== 'undefined') {
return findClosestValue(parent, property);
}
return q.toString();
}
Loading

0 comments on commit 112202e

Please sign in to comment.