diff --git a/API.md b/API.md index 1bd37eee4..1c6cc969e 100644 --- a/API.md +++ b/API.md @@ -61,6 +61,40 @@ Assert an [HTMLElement][] matching the `selector` does not exists. assert.dom('.should-not-exist').doesNotExist(); ``` +### isChecked + +- **See: [#isNotChecked](#isnotchecked)** + +Assert that the [HTMLElement][] or an [HTMLElement][] matching the +`selector` is currently checked. + +**Parameters** + +- `message` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** + +**Examples** + +```javascript +assert.dom('input.active').isChecked(); +``` + +### isNotChecked + +- **See: [#isChecked](#ischecked)** + +Assert that the [HTMLElement][] or an [HTMLElement][] matching the +`selector` is currently unchecked. + +**Parameters** + +- `message` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** + +**Examples** + +```javascript +assert.dom('input.active').isNotChecked(); +``` + ### isFocused - **See: [#isNotFocused](#isnotfocused)** @@ -95,6 +129,40 @@ Assert that the [HTMLElement][] or an [HTMLElement][] matching the assert.dom('input[type="password"]').isNotFocused(); ``` +### isRequired + +- **See: [#isNotRequired](#isnotrequired)** + +Assert that the [HTMLElement][] or an [HTMLElement][] matching the +`selector` is currently required. + +**Parameters** + +- `message` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** + +**Examples** + +```javascript +assert.dom('input[type="text"]').isRequired(); +``` + +### isNotRequired + +- **See: [#isRequired](#isrequired)** + +Assert that the [HTMLElement][] or an [HTMLElement][] matching the +`selector` is currently not required. + +**Parameters** + +- `message` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** + +**Examples** + +```javascript +assert.dom('input[type="text"]').isNotRequired(); +``` + ### hasAttribute - **See: [#doesNotHaveAttribute](#doesnothaveattribute)** diff --git a/lib/__tests__/is-not-required.js b/lib/__tests__/is-not-required.js new file mode 100644 index 000000000..aa0a8a5fd --- /dev/null +++ b/lib/__tests__/is-not-required.js @@ -0,0 +1,112 @@ +/* eslint-env jest */ + +import TestAssertions from "../helpers/test-assertions"; + +describe('assert.dom(...).isNotRequired()', () => { + let assert; + + beforeEach(() => { + assert = new TestAssertions(); + }); + + test('with custom message', () => { + document.body.innerHTML = ''; + + assert.dom('input').isNotRequired('custom message'); + + expect(assert.results).toEqual([{ + actual: 'required', + expected: 'not required', + message: 'custom message', + result: false, + }]); + }); + + describe('with HTMLElement', () => { + let element; + + beforeEach(() => { + document.body.innerHTML = ''; + element = document.querySelector('input'); + }); + + test('succeeds if element is not required', () => { + assert.dom(element).isNotRequired(); + + expect(assert.results).toEqual([{ + actual: 'not required', + expected: 'not required', + message: 'Element input[type=\"text\"] is not required', + result: true, + }]); + }); + + test('fails if element is required', () => { + element.required = true; + assert.dom(element).isNotRequired(); + + expect(assert.results).toEqual([{ + actual: 'required', + expected: 'not required', + message: 'Element input[type=\"text\"][required] is not required', + result: false, + }]); + }); + + test('fails for missing element', () => { + assert.dom(null).isNotRequired(); + + expect(assert.results).toEqual([{ + message: 'Element exists', + result: false, + }]); + }); + }); + + describe('with selector', () => { + beforeEach(() => { + document.body.innerHTML = ''; + }); + + test('succeeds if element is not required', () => { + assert.dom('input').isNotRequired(); + + expect(assert.results).toEqual([{ + actual: 'not required', + expected: 'not required', + message: 'Element input is not required', + result: true, + }]); + }); + + test('fails if element is required', () => { + document.querySelector('input').required = true; + assert.dom('input').isNotRequired(); + + expect(assert.results).toEqual([{ + actual: 'required', + expected: 'not required', + message: 'Element input is not required', + result: false, + }]); + }); + + test('fails for missing element', () => { + assert.dom('input[type="password"]').isNotRequired(); + + expect(assert.results).toEqual([{ + message: 'Element input[type="password"] exists', + result: false, + }]); + }); + }); + + test('throws for unexpected parameter types', () => { + expect(() => assert.dom(5).isNotRequired()).toThrow('Unexpected Parameter: 5'); + expect(() => assert.dom(true).isNotRequired()).toThrow('Unexpected Parameter: true'); + expect(() => assert.dom(undefined).isNotRequired()).toThrow('Unexpected Parameter: undefined'); + expect(() => assert.dom({}).isNotRequired()).toThrow('Unexpected Parameter: [object Object]'); + expect(() => assert.dom(document).isNotRequired()).toThrow('Unexpected Parameter: [object HTMLDocument]'); + expect(() => assert.dom(document.createElement('div')).isRequired()).toThrow('Unexpected Element Type: [object HTMLDivElement]'); + }); +}); diff --git a/lib/__tests__/is-required.js b/lib/__tests__/is-required.js new file mode 100644 index 000000000..d991c671a --- /dev/null +++ b/lib/__tests__/is-required.js @@ -0,0 +1,112 @@ +/* eslint-env jest */ + +import TestAssertions from "../helpers/test-assertions"; + +describe('assert.dom(...).isRequired()', () => { + let assert; + + beforeEach(() => { + assert = new TestAssertions(); + }); + + test('with custom message', () => { + document.body.innerHTML = ''; + + assert.dom('input').isRequired('custom message'); + + expect(assert.results).toEqual([{ + actual: 'not required', + expected: 'required', + message: 'custom message', + result: false, + }]); + }); + + describe('with HTMLElement', () => { + let element; + + beforeEach(() => { + document.body.innerHTML = ''; + element = document.querySelector('input'); + }); + + test('succeeds if element is required', () => { + assert.dom(element).isRequired(); + + expect(assert.results).toEqual([{ + actual: 'required', + expected: 'required', + message: 'Element input[type=\"text\"][required] is required', + result: true, + }]); + }); + + test('fails if element is not required', () => { + element.required = false; + assert.dom(element).isRequired(); + + expect(assert.results).toEqual([{ + actual: 'not required', + expected: 'required', + message: 'Element input[type=\"text\"] is required', + result: false, + }]); + }); + + test('fails for missing element', () => { + assert.dom(null).isRequired(); + + expect(assert.results).toEqual([{ + message: 'Element exists', + result: false, + }]); + }); + }); + + describe('with selector', () => { + beforeEach(() => { + document.body.innerHTML = ''; + }); + + test('succeeds if element is required', () => { + assert.dom('input').isRequired(); + + expect(assert.results).toEqual([{ + actual: 'required', + expected: 'required', + message: 'Element input is required', + result: true, + }]); + }); + + test('fails if element is not required', () => { + document.querySelector('input').required = false; + assert.dom('input').isRequired(); + + expect(assert.results).toEqual([{ + actual: 'not required', + expected: 'required', + message: 'Element input is required', + result: false, + }]); + }); + + test('fails for missing element', () => { + assert.dom('input[type="password"]').isRequired(); + + expect(assert.results).toEqual([{ + message: 'Element input[type="password"] exists', + result: false, + }]); + }); + }); + + test('throws for unexpected parameter types', () => { + expect(() => assert.dom(5).isRequired()).toThrow('Unexpected Parameter: 5'); + expect(() => assert.dom(true).isRequired()).toThrow('Unexpected Parameter: true'); + expect(() => assert.dom(undefined).isRequired()).toThrow('Unexpected Parameter: undefined'); + expect(() => assert.dom({}).isRequired()).toThrow('Unexpected Parameter: [object Object]'); + expect(() => assert.dom(document).isRequired()).toThrow('Unexpected Parameter: [object HTMLDocument]'); + expect(() => assert.dom(document.createElement('div')).isRequired()).toThrow('Unexpected Element Type: [object HTMLDivElement]'); + }); +}); diff --git a/lib/assertions.js b/lib/assertions.js index 0e1946926..3eb723ed1 100644 --- a/lib/assertions.js +++ b/lib/assertions.js @@ -3,6 +3,8 @@ import focused from './assertions/focused'; import notFocused from './assertions/not-focused'; import isChecked from './assertions/is-checked'; import isNotChecked from './assertions/is-not-checked'; +import isRequired from './assertions/is-required'; +import isNotRequired from './assertions/is-not-required'; import elementToString from './helpers/element-to-string'; import collapseWhitespace from './helpers/collapse-whitespace'; @@ -104,6 +106,36 @@ export default class DOMAssertions { notFocused.call(this, message); } + /** + * Assert that the [HTMLElement][] or an [HTMLElement][] matching the + * `selector` is currently required. + * + * @param {string?} message + * + * @example + * assert.dom('input[type="text"]').isRequired(); + * + * @see {@link #isNotRequired} + */ + isRequired(message) { + isRequired.call(this, message); + } + + /** + * Assert that the [HTMLElement][] or an [HTMLElement][] matching the + * `selector` is currently not required. + * + * @param {string?} message + * + * @example + * assert.dom('input[type="text"]').isNotRequired(); + * + * @see {@link #isRequired} + */ + isNotRequired(message) { + isNotRequired.call(this, message); + } + /** * Assert that the [HTMLElement][] has an attribute with the provided `name` * and optionally checks if the attribute `value` matches the provided text diff --git a/lib/assertions/is-not-required.js b/lib/assertions/is-not-required.js new file mode 100644 index 000000000..34b5fd91d --- /dev/null +++ b/lib/assertions/is-not-required.js @@ -0,0 +1,24 @@ +import elementToString from '../helpers/element-to-string'; + +export default function notRequired(message) { + let element = this.findTargetElement(); + if (!element) return; + + if (!( + element instanceof HTMLInputElement || + element instanceof HTMLTextAreaElement || + element instanceof HTMLSelectElement + )) { + throw new TypeError(`Unexpected Element Type: ${element.toString()}`); + } + + let result = element.required === false; + let actual = !result ? 'required' : 'not required'; + let expected = 'not required'; + + if (!message) { + message = `Element ${elementToString(this.target)} is not required`; + } + + this.pushResult({ result, actual, expected, message }); +} diff --git a/lib/assertions/is-required.js b/lib/assertions/is-required.js new file mode 100644 index 000000000..6f4f81c43 --- /dev/null +++ b/lib/assertions/is-required.js @@ -0,0 +1,24 @@ +import elementToString from '../helpers/element-to-string'; + +export default function required(message) { + let element = this.findTargetElement(); + if (!element) return; + + if (!( + element instanceof HTMLInputElement || + element instanceof HTMLTextAreaElement || + element instanceof HTMLSelectElement + )) { + throw new TypeError(`Unexpected Element Type: ${element.toString()}`); + } + + let result = element.required === true; + let actual = result ? 'required' : 'not required'; + let expected = 'required'; + + if (!message) { + message = `Element ${elementToString(this.target)} is required`; + } + + this.pushResult({ result, actual, expected, message }); +} \ No newline at end of file