diff --git a/addon-test-support/-private/execution_context/acceptance.js b/addon-test-support/-private/execution_context/acceptance.js index ef17352d..c8941122 100644 --- a/addon-test-support/-private/execution_context/acceptance.js +++ b/addon-test-support/-private/execution_context/acceptance.js @@ -2,7 +2,8 @@ import { run } from '../action'; import { guardMultiple, buildSelector, - findClosestValue + findClosestValue, + getCustomTextFilters } from '../helpers'; import { fillElement, @@ -86,7 +87,12 @@ AcceptanceExecutionContext.prototype = { assertElementExists(selector, options) { /* global find */ - let result = find(selector, options.testContainer || findClosestValue(this.pageObjectNode, 'testContainer')); + let result = find(selector, options.testContainer || findClosestValue(this.pageObjectNode, 'testContainer')).toArray(); + + Object.values(getCustomTextFilters(options)) + .forEach(customFilter => { + result = result.filter($ele => customFilter($ele.textContent.trim(), options.contains)); + }); if (result.length === 0) { throwBetterError( @@ -96,6 +102,8 @@ AcceptanceExecutionContext.prototype = { { selector } ); } + + return result; }, find(selector, options) { diff --git a/addon-test-support/-private/execution_context/integration.js b/addon-test-support/-private/execution_context/integration.js index e8985d84..b5f8b959 100644 --- a/addon-test-support/-private/execution_context/integration.js +++ b/addon-test-support/-private/execution_context/integration.js @@ -4,7 +4,8 @@ import { run as runAction } from '../action'; import { guardMultiple, buildSelector, - findClosestValue + findClosestValue, + getCustomTextFilters } from '../helpers'; import { fillElement, @@ -100,11 +101,16 @@ IntegrationExecutionContext.prototype = { let container = options.testContainer || findClosestValue(this.pageObjectNode, 'testContainer'); if (container) { - result = $(selector, container); + result = $(selector, container).toArray(); } else { - result = this.testContext.$(selector); + result = this.testContext.$(selector).toArray(); } + Object.values(getCustomTextFilters(options)) + .forEach(customFilter => { + result = result.filter($ele => customFilter($ele.textContent.trim(), options.contains)); + }); + if (result.length === 0) { throwBetterError( this.pageObjectNode, @@ -113,6 +119,8 @@ IntegrationExecutionContext.prototype = { { selector } ); } + + return result; }, find(selector, options) { diff --git a/addon-test-support/-private/execution_context/native-events-context.js b/addon-test-support/-private/execution_context/native-events-context.js index e345f39b..dc0d1584 100644 --- a/addon-test-support/-private/execution_context/native-events-context.js +++ b/addon-test-support/-private/execution_context/native-events-context.js @@ -12,7 +12,8 @@ import { run } from '../action'; import { guardMultiple, buildSelector, - findClosestValue + findClosestValue, + getCustomTextFilters } from '../helpers'; import { fillElement, @@ -114,7 +115,12 @@ ExecutionContext.prototype = { assertElementExists(selector, options) { let container = options.testContainer || findClosestValue(this.pageObjectNode, 'testContainer'); - let result = this.$(selector, container); + let result = this.$(selector, container).toArray(); + + Object.values(getCustomTextFilters(options)) + .forEach(customFilter => { + result = result.filter($ele => customFilter($ele.textContent.trim(), options.contains)); + }); if (result.length === 0) { throwBetterError( @@ -124,6 +130,8 @@ ExecutionContext.prototype = { { selector } ); } + + return result; }, find(selector, options) { diff --git a/addon-test-support/-private/execution_context/rfc268.js b/addon-test-support/-private/execution_context/rfc268.js index f7ffff9f..22d1aaa8 100644 --- a/addon-test-support/-private/execution_context/rfc268.js +++ b/addon-test-support/-private/execution_context/rfc268.js @@ -4,6 +4,7 @@ import { guardMultiple, buildSelector, findClosestValue, + getCustomTextFilters } from '../helpers'; import { getRootElement, @@ -62,7 +63,12 @@ ExecutionContext.prototype = { }, assertElementExists(selector, options) { - let result = this.getElements(selector, options); + let result = this.getElements(selector, options).toArray(); + + Object.values(getCustomTextFilters(options)) + .forEach(customFilter => { + result = result.filter($ele => customFilter($ele.textContent.trim(), options.contains)); + }); if (result.length === 0) { throwBetterError( @@ -72,6 +78,8 @@ ExecutionContext.prototype = { { selector } ); } + + return result; }, find(selector, options) { diff --git a/addon-test-support/-private/helpers.js b/addon-test-support/-private/helpers.js index f521f1df..3d514c18 100644 --- a/addon-test-support/-private/helpers.js +++ b/addon-test-support/-private/helpers.js @@ -352,3 +352,22 @@ export function getPageObjectDefinition(node){ export function storePageObjectDefinition(node, definition){ Ceibo.meta(node).__poDef__ = definition; } + +export function getCustomTextFilters(obj) { + const requestedCustomFilters = {}; + + Object.keys(obj) + .forEach(filter => { + if (customTextFilters[filter]) { + requestedCustomFilters[filter] = customTextFilters[filter]; + } + }); + + return requestedCustomFilters; +} + +const customTextFilters = { + exact: (a, b) => a === b +} + +export { customTextFilters }; diff --git a/addon-test-support/properties/click-on-text.js b/addon-test-support/properties/click-on-text.js index 351629ac..783990b3 100644 --- a/addon-test-support/properties/click-on-text.js +++ b/addon-test-support/properties/click-on-text.js @@ -97,9 +97,9 @@ export function clickOnText(selector, userOptions = {}) { let fullSelector = buildSelector(this, context, selector, options); let container = options.testContainer || findClosestValue(this, 'testContainer'); - context.assertElementExists(fullSelector, options); + const $ele = context.assertElementExists(fullSelector, options); - return context.click(fullSelector, container, options); + return context.click($ele[0], container, options); }); }; } diff --git a/tests/unit/-private/properties/click-on-text-test.ts b/tests/unit/-private/properties/click-on-text-test.ts index 7ca752d2..1cf5078b 100644 --- a/tests/unit/-private/properties/click-on-text-test.ts +++ b/tests/unit/-private/properties/click-on-text-test.ts @@ -233,4 +233,33 @@ moduleForProperty('clickOnText', function(test) { return page.foo('Click me'); }, /page\.foo/, 'Element not found'); }); + + test('should click on element matching exact text', async function(assert) { + assert.expect(2); + + let page = create({ + foo: clickOnText('button', { exact: true }) + }); + + await this.adapter.createTemplate(this, page, ` + + + + `); + + this.adapter.$('button:contains("foo")').one('click', function() { + assert.ok(true); + }); + + this.adapter.$('button:contains("foobar")').one('click', function() { + assert.ok(true); + }); + + await this.adapter.await(page.foo('foo')); + + + await this.adapter.throws(assert, function() { + return page.foo('fooobar'); + }, /page\.foo/, 'Element not found'); + }); }); diff --git a/types/index.d.ts b/types/index.d.ts index 4fa01c25..dcc121c3 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -5,6 +5,7 @@ declare module 'ember-cli-page-object' { Definition, FindOptions, TriggerOptions, + ClickOnTextOptions, GetterDescriptor, MethodDescriptor, DSL @@ -31,7 +32,7 @@ declare module 'ember-cli-page-object' { // Actions function clickable(scope?: string, userOptions?: FindOptions): MethodDescriptor<(this: T) => T>; - function clickOnText(scope?: string, userOptions?: FindOptions): MethodDescriptor<(this: T, text: string) => T>; + function clickOnText(scope?: string, userOptions?: ClickOnTextOptions): MethodDescriptor<(this: T, text: string) => T>; function fillable(scope?: string, userOptions?: FindOptions): MethodDescriptor<(this: T, clueOrContent: string, content?: string) => T>; function selectable(scope?: string, userOptions?: FindOptions): MethodDescriptor<(this: T, clueOrContent: string, content?: string) => T>; function triggerable(event: string, scope?: string, eventOptions?: TriggerOptions, options?: FindOptions): MethodDescriptor<(this: T, options?: {}) => T>; @@ -162,4 +163,8 @@ declare module 'ember-cli-page-object/-private' { resetScope?: boolean; testContainer?: string|HTMLElement|JQuery; } + + interface ClickOnTextOptions extends FindOptions { + exact?: boolean + } }