diff --git a/src/common/tests/functional/all.ts b/src/common/tests/functional/all.ts index c587a02832..46d53ddf9c 100644 --- a/src/common/tests/functional/all.ts +++ b/src/common/tests/functional/all.ts @@ -8,6 +8,7 @@ import '../../../listbox/tests/functional/Listbox'; import '../../../radio/tests/functional/Radio'; import '../../../slidepane/tests/functional/SlidePane'; import '../../../tabcontroller/tests/functional/TabController'; +import '../../../textarea/tests/functional/Textarea'; import '../../../textinput/tests/functional/TextInput'; import '../../../titlepane/tests/functional/TitlePane'; import '../../../tooltip/tests/functional/Tooltip'; diff --git a/src/textarea/example/index.ts b/src/textarea/example/index.ts index 4144fa23c8..dff13c28bc 100644 --- a/src/textarea/example/index.ts +++ b/src/textarea/example/index.ts @@ -9,7 +9,7 @@ export class App extends WidgetBase { private _theme: {}; private _value1: string; private _value2: string; - private _invalid = false; + private _invalid: boolean; themeChange(event: TypedTargetEvent) { const checked = event.target.checked; @@ -27,46 +27,65 @@ export class App extends WidgetBase { onchange: this.themeChange }) ]), - w(Textarea, { - key: 't1', - columns: 40, - rows: 8, - placeholder: 'Hello, World', - label: 'Type Something', - value: this._value1, - onChange: (event: TypedTargetEvent) => { - this._value1 = event.target.value; - this.invalidate(); - }, - theme: this._theme - }), + v('div', { id: 'example-t1'}, [ + w(Textarea, { + key: 't1', + columns: 40, + rows: 8, + placeholder: 'Hello, World', + label: 'Type Something', + value: this._value1, + onChange: (event: TypedTargetEvent) => { + this._value1 = event.target.value; + this.invalidate(); + }, + theme: this._theme + }) + ]), v('h3', {}, ['Disabled Textarea']), - w(Textarea, { - key: 't2', - columns: 40, - rows: 3, - label: 'Can\'t type here', - value: 'Initial value', - disabled: true, - theme: this._theme - }), + v('div', { id: 'example-t2'}, [ + w(Textarea, { + key: 't2', + columns: 40, + rows: 3, + label: 'Can\'t type here', + value: 'Initial value', + disabled: true, + theme: this._theme + }) + ]), v('h3', {}, ['Validated, Required Textarea']), - w(Textarea, { - key: 't3', - columns: 40, - rows: 8, - label: 'Required', - required: true, - value: this._value2, - invalid: this._invalid, - onChange: (event: TypedTargetEvent) => { - const value = event.target.value; - this._value2 = value; - this._invalid = value.trim().length === 0; - this.invalidate(); - }, - theme: this._theme - }) + v('div', { id: 'example-t3'}, [ + w(Textarea, { + key: 't3', + columns: 40, + rows: 8, + label: 'Required', + required: true, + value: this._value2, + invalid: this._invalid, + onChange: (event: TypedTargetEvent) => { + const value = event.target.value; + this._value2 = value; + this._invalid = value.trim().length === 0; + this.invalidate(); + }, + theme: this._theme + }) + ]), + v('h3', {}, ['Hidden Label Textarea']), + v('div', { id: 'example-t4'}, [ + w(Textarea, { + key: 't4', + columns: 40, + rows: 8, + label: { + content: 'Hidden label', + before: false, + hidden: true + } + }) + ]) ]); } } diff --git a/src/textarea/tests/functional/Textarea.ts b/src/textarea/tests/functional/Textarea.ts new file mode 100644 index 0000000000..a9575b8b7e --- /dev/null +++ b/src/textarea/tests/functional/Textarea.ts @@ -0,0 +1,164 @@ +const { registerSuite } = intern.getInterface('object'); +const { assert } = intern.getPlugin('chai'); + +import { Remote } from 'intern/lib/executors/Node'; +import keys from '@theintern/leadfoot/keys'; +import * as css from '../../styles/textarea.m.css'; +import * as baseCss from '../../../common/styles/base.m.css'; + +function getPage(remote: Remote) { + return remote + .get('http://localhost:9000/_build/common/example/?module=textarea') + .setFindTimeout(5000); +} + +registerSuite('Textarea', { + 'should be visible'() { + return getPage(this.remote) + .findByCssSelector(`#example-t1 .${css.root}`) + .isDisplayed() + .findByCssSelector(`.${css.inputWrapper}`) + .isDisplayed() + .end() + + .findByCssSelector(`.${css.input}`) + .getSize() + .then(({ height, width }) => { + assert.isAbove(height, 0, 'The height of the textarea should be greater than zero.'); + assert.isAbove(width, 0, 'The width of the textarea should be greater than zero.'); + }) + .end() + .end(); + }, + 'label should be as defined'() { + const { browserName = '' } = this.remote.session.capabilities; + if (browserName.toLowerCase() === 'internet explorer') { + this.skip('Label is including textarea placeholder.'); + } + + return getPage(this.remote) + .findByCssSelector(`#example-t1 .${css.root}`) + .getVisibleText() + .then(text => { + assert.strictEqual(text, 'Type Something'); + }) + .end(); + }, + 'should gain focus when clicking on the label'() { + const { browserName } = this.remote.session.capabilities; + if (browserName === 'firefox') { + this.skip('Firefox is not locating the input.'); + } + + return getPage(this.remote) + .findByCssSelector(`#example-t1 .${css.root}`) + .click() + .sleep(1000) + .end() + .execute(`return document.activeElement === document.querySelector('#example-t1 .${css.root} .${css.input}');`) + .then(isEqual => { + assert.isTrue(isEqual); + }); + }, + 'should allow input to be typed'() { + const { browserName } = this.remote.session.capabilities; + if (browserName === 'firefox') { + this.skip('Firefox is not locating the input.'); + } + + const testInput = 'test text'; + return getPage(this.remote) + .findByCssSelector(`#example-t1 .${css.root}`) + .click() + .findByCssSelector(`.${css.input}`) + .type(testInput) + .getProperty('value') + .then((value: string) => { + assert.strictEqual(value, testInput); + }) + .end() + .end(); + }, + 'disabled should not allow input to be typed'() { + const initValue = 'Initial value'; + return getPage(this.remote) + .findByCssSelector(`#example-t2 .${css.root} .${css.input}`) + .click() + .then(null, () => {}) + .type('text') + .then(null, () => {}) + .getProperty('value') + .then((value: string) => { + assert.strictEqual(value, initValue); + }) + .end(); + }, + 'validated should update style based on validity'() { + const { browserName, version } = this.remote.session.capabilities; + if (browserName === 'safari') { + this.skip('Classes are not being updated for this unit test in Safari 9 ' + version); + } + + const validText = 'exists'; + const backspaces = []; + for (let i = 0; i < validText.length; i++) { + backspaces.push(keys.BACKSPACE); + } + + return getPage(this.remote) + .findByCssSelector(`#example-t3 .${css.root}`) + .getProperty('className') + .then((className: string) => { + assert.notInclude(className, css.invalid); + assert.notInclude(className, css.valid); + }) + .findByCssSelector(`.${css.input}`) + .click() + .type(validText) + .end() + .end() + // focus another input + .findByCssSelector(`#example-t1 .${css.root} .${css.input}`) + .click() + .end() + .sleep(500) + // enter invalid value + .findByCssSelector(`#example-t3 .${css.root}`) + .getProperty('className') + .then((className: string) => { + assert.notInclude(className, css.invalid); + assert.include(className, css.valid); + }) + .findByCssSelector(`.${css.input}`) + .click() + .type(backspaces) + .end() + .end() + // focus another input + .findByCssSelector(`#example-t1 .${css.root} .${css.input}`) + .click() + .end() + .sleep(500) + .findByCssSelector(`#example-t3 .${css.root}`) + .getProperty('className') + .then((className: string) => { + assert.notInclude(className, css.valid); + assert.include(className, css.invalid); + }) + .end(); + }, + 'hidden label should not be displayed'() { + return getPage(this.remote) + .findByCssSelector(`#example-t4 .${css.root}`) + .getVisibleText() + .then(text => { + assert.isTrue(text && text.length > 0); + }) + .findByCssSelector(`.${baseCss.visuallyHidden}`) + .then(element => { + assert(element, 'element with specified class "visuallyHidden" should exist.`'); + }) + .end() + .end(); + } +});