diff --git a/addon/src/properties/value.js b/addon/src/properties/value.js index 95db38d1..5ea1a5c9 100644 --- a/addon/src/properties/value.js +++ b/addon/src/properties/value.js @@ -1,4 +1,3 @@ -import { $ } from '../-private/jquery'; import { findOne } from '../-private/finders'; import { getter } from '../macros/index'; @@ -83,7 +82,33 @@ export function value(selector, userOptions = {}) { const element = findOne(this, selector, options); return element.hasAttribute('contenteditable') - ? $(element).html() - : $(element).val(); + ? element.innerHTML + : getValue(element); }); } + +function getValue(element) { + const { value } = element; + if (value !== undefined && element.tagName.toLowerCase() === 'select') { + return selectValue(element); + } + + return element.value; +} + +function selectValue(element) { + const selectedOptions = Array.from(element.selectedOptions).filter( + (option) => + !option.disabled && + (option.parentNode.tagName.toLowerCase() !== 'optgroup' || + !option.parentNode.disabled) + ); + + if (element.multiple) { + return selectedOptions.map((option) => option.value); + } else if (selectedOptions.length === 0) { + return null; + } + + return element.value; +} diff --git a/addon/types.d.ts b/addon/types.d.ts index bb4a185e..0643e7d1 100644 --- a/addon/types.d.ts +++ b/addon/types.d.ts @@ -19,7 +19,7 @@ declare module 'ember-cli-page-object' { export function isHidden(scope?: string, options?: FindOptions): GetterDescriptor; export function isPresent(scope?: string, options?: FindOptions): GetterDescriptor; export function text(scope?: string, options?: FindOptions & { normalize?: boolean }): GetterDescriptor; - export function value(scope?: string, options?: FindOptions): GetterDescriptor; + export function value(scope?: string, options?: FindOptions): GetterDescriptor; export function property(name: string, scope?: string, options?: FindOptions): GetterDescriptor; export function hasClass(className: string, scope?: string, options?: FindOptions): GetterDescriptor; export function notHasClass(className: string, scope?: string, options?: FindOptions): GetterDescriptor; diff --git a/test-app/tests/unit/-private/properties/value-test.ts b/test-app/tests/unit/-private/properties/value-test.ts index d1c348a2..06c10be5 100644 --- a/test-app/tests/unit/-private/properties/value-test.ts +++ b/test-app/tests/unit/-private/properties/value-test.ts @@ -1,6 +1,8 @@ import { create, value } from 'ember-cli-page-object'; import { setupRenderingTest, TestContext } from '../../../helpers'; import { module, test } from 'qunit'; +import { render } from '@ember/test-helpers'; +import hbs from 'htmlbars-inline-precompile'; module('value', function (hooks) { setupRenderingTest(hooks); @@ -149,4 +151,428 @@ module('value', function (hooks) { assert.equal(page.foo, 'lorem'); }); + + module('jquery compatibility', function () { + module('input', function (hooks) { + test('no value', async function (this: TestContext, assert) { + const page = create({ + value: value('input'), + }); + + await render(hbs``); + + assert.strictEqual(page.value, ''); + }); + + test('with value', async function (this: TestContext, assert) { + const page = create({ + value: value('input'), + }); + + this.set('value', 'lorem'); + await render(hbs``); + + assert.strictEqual(page.value, 'lorem'); + + this.set('value', null); + + assert.strictEqual(page.value, ''); + }); + + test('disabled', async function (this: TestContext, assert) { + const page = create({ + value: value('input'), + }); + + this.set('value', 'lorem'); + await render(hbs``); + + assert.strictEqual(page.value, 'lorem'); + }); + }); + + module('checkbox', function () { + test('no value', async function (this: TestContext, assert) { + const page = create({ + value: value('input'), + }); + + await render(hbs``); + + assert.strictEqual(page.value, 'on'); + + this.set('checked', ''); + + assert.strictEqual(page.value, 'on'); + }); + + test('with value', async function (this: TestContext, assert) { + const page = create({ + value: value('input'), + }); + + this.set('value', 'lorem'); + await render( + hbs`` + ); + + assert.strictEqual(page.value, 'lorem'); + + this.set('value', null); + + assert.strictEqual(page.value, ''); + + this.set('checked', ''); + + assert.strictEqual(page.value, ''); + }); + + test('disabled', async function (this: TestContext, assert) { + const page = create({ + value: value('input'), + }); + + this.set('value', 'lorem'); + await render( + hbs`` + ); + + assert.strictEqual(page.value, 'lorem'); + + this.set('checked', ''); + + assert.strictEqual(page.value, 'lorem'); + }); + }); + + module('select', function () { + test('selected with [value]', async function (this: TestContext, assert) { + const page = create({ + value: value('select'), + }); + + await this.createTemplate(``); + + assert.strictEqual(page.value, '2'); + }); + + test('[disabled] selected option', async function (this: TestContext, assert) { + const page = create({ + value: value('select'), + }); + + await this.createTemplate(``); + + assert.strictEqual(page.value, '2'); + }); + + test('selected option[disabled] ', async function (this: TestContext, assert) { + const page = create({ + value: value('select'), + }); + + await this.createTemplate(``); + + assert.strictEqual(page.value, null); + }); + + test('no selected with [value]', async function (this: TestContext, assert) { + const page = create({ + value: value('select'), + }); + + await this.createTemplate(``); + + assert.strictEqual(page.value, '1'); + }); + + test('selected with no [value]', async function (this: TestContext, assert) { + const page = create({ + value: value('select'), + }); + + await this.createTemplate(``); + + assert.strictEqual(page.value, 'Ipsum'); + }); + + test('not selected with no [value]', async function (this: TestContext, assert) { + const page = create({ + value: value('select'), + }); + + await this.createTemplate(``); + + assert.strictEqual(page.value, 'lorem'); + }); + + module('optgroup', function () { + test('selected with [value]', async function (this: TestContext, assert) { + const page = create({ + value: value('select'), + }); + + await this.createTemplate(``); + + assert.strictEqual(page.value, '2'); + }); + + test('[disabled] selected with [value]', async function (this: TestContext, assert) { + const page = create({ + value: value('select'), + }); + + await this.createTemplate(``); + + assert.strictEqual(page.value, null); + }); + + test('selected with [value][disabled]', async function (this: TestContext, assert) { + const page = create({ + value: value('select'), + }); + + await this.createTemplate(``); + + assert.strictEqual(page.value, null); + }); + }); + }); + + module('select[multiple]', function () { + test('selected with [value]', async function (this: TestContext, assert) { + const page = create({ + value: value('select'), + }); + + await this.createTemplate(``); + + assert.deepEqual(page.value, ['2']); + }); + + test('[disabled] selected option', async function (this: TestContext, assert) { + const page = create({ + value: value('select'), + }); + + await this.createTemplate(``); + + assert.deepEqual(page.value, ['2']); + }); + + test('selected option[disabled] ', async function (this: TestContext, assert) { + const page = create({ + value: value('select'), + }); + + await this.createTemplate(``); + + assert.deepEqual(page.value, [] as string[]); + }); + + test('no selected with [value]', async function (this: TestContext, assert) { + const page = create({ + value: value('select'), + }); + + await this.createTemplate(``); + + assert.deepEqual(page.value, [] as string[]); + }); + + test('selected with no [value]', async function (this: TestContext, assert) { + const page = create({ + value: value('select'), + }); + + await this.createTemplate(``); + + assert.deepEqual(page.value, ['Ipsum']); + }); + + test('not selected with no [value]', async function (this: TestContext, assert) { + const page = create({ + value: value('select'), + }); + + await this.createTemplate(``); + + assert.deepEqual(page.value, [] as string[]); + }); + + module('optgroup', function () { + test('selected with [value]', async function (this: TestContext, assert) { + const page = create({ + value: value('select'), + }); + + await this.createTemplate(``); + + assert.strictEqual(page.value, '2'); + }); + + test('[disabled] selected with [value]', async function (this: TestContext, assert) { + const page = create({ + value: value('select'), + }); + + await this.createTemplate(``); + + assert.strictEqual(page.value, null); + }); + + test('selected with [value][disabled]', async function (this: TestContext, assert) { + const page = create({ + value: value('select'), + }); + + await this.createTemplate(``); + + assert.strictEqual(page.value, null); + }); + }); + }); + + module('option', function () { + test('selected', async function (this: TestContext, assert) { + const page = create({ + value: value('option[selected]'), + }); + + await this.createTemplate(``); + + assert.strictEqual(page.value, '2'); + }); + + test('not selected with [value]', async function (this: TestContext, assert) { + const page = create({ + value: value('option[value=1]'), + }); + + await this.createTemplate(``); + + assert.strictEqual(page.value, '1'); + }); + + test('selected with no [value]', async function (this: TestContext, assert) { + const page = create({ + value: value('#secondOption'), + }); + + await this.createTemplate(``); + + assert.strictEqual(page.value, 'Ipsum'); + }); + + test('not selected with no [value]', async function (this: TestContext, assert) { + const page = create({ + value: value('#secondOption'), + }); + + await this.createTemplate(``); + + assert.strictEqual(page.value, 'Ipsum'); + }); + }); + }); });