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