diff --git a/API.md b/API.md index fd71951d4..a937292b7 100644 --- a/API.md +++ b/API.md @@ -31,87 +31,90 @@ - [isValid][27] - [Parameters][28] - [Examples][29] - - [isVisible][30] + - [isNotValid][30] - [Parameters][31] - [Examples][32] - - [isNotVisible][33] + - [isVisible][33] - [Parameters][34] - [Examples][35] - - [hasAttribute][36] + - [isNotVisible][36] - [Parameters][37] - [Examples][38] - - [doesNotHaveAttribute][39] + - [hasAttribute][39] - [Parameters][40] - [Examples][41] - - [hasAria][42] + - [doesNotHaveAttribute][42] - [Parameters][43] - [Examples][44] - - [doesNotHaveAria][45] + - [hasAria][45] - [Parameters][46] - [Examples][47] - - [hasProperty][48] + - [doesNotHaveAria][48] - [Parameters][49] - [Examples][50] - - [isDisabled][51] + - [hasProperty][51] - [Parameters][52] - [Examples][53] - - [isNotDisabled][54] + - [isDisabled][54] - [Parameters][55] - [Examples][56] - - [hasClass][57] + - [isNotDisabled][57] - [Parameters][58] - [Examples][59] - - [doesNotHaveClass][60] + - [hasClass][60] - [Parameters][61] - [Examples][62] - - [hasStyle][63] + - [doesNotHaveClass][63] - [Parameters][64] - [Examples][65] - - [hasPseudoElementStyle][66] + - [hasStyle][66] - [Parameters][67] - [Examples][68] - - [doesNotHaveStyle][69] + - [hasPseudoElementStyle][69] - [Parameters][70] - [Examples][71] - - [doesNotHavePseudoElementStyle][72] + - [doesNotHaveStyle][72] - [Parameters][73] - [Examples][74] - - [hasText][75] + - [doesNotHavePseudoElementStyle][75] - [Parameters][76] - [Examples][77] - - [hasAnyText][78] + - [hasText][78] - [Parameters][79] - [Examples][80] - - [hasNoText][81] + - [hasAnyText][81] - [Parameters][82] - [Examples][83] - - [includesText][84] + - [hasNoText][84] - [Parameters][85] - [Examples][86] - - [doesNotIncludeText][87] + - [includesText][87] - [Parameters][88] - [Examples][89] - - [hasValue][90] + - [doesNotIncludeText][90] - [Parameters][91] - [Examples][92] - - [hasAnyValue][93] + - [hasValue][93] - [Parameters][94] - [Examples][95] - - [hasNoValue][96] + - [hasAnyValue][96] - [Parameters][97] - [Examples][98] - - [matchesSelector][99] + - [hasNoValue][99] - [Parameters][100] - [Examples][101] - - [doesNotMatchSelector][102] + - [matchesSelector][102] - [Parameters][103] - [Examples][104] - - [hasTagName][105] + - [doesNotMatchSelector][105] - [Parameters][106] - [Examples][107] - - [doesNotHaveTagName][108] + - [hasTagName][108] - [Parameters][109] - [Examples][110] + - [doesNotHaveTagName][111] + - [Parameters][112] + - [Examples][113] ## assert.dom() @@ -119,8 +122,8 @@ Once installed the DOM element assertions are available at `assert.dom(...).*`: **Parameters** -- `target` **([string][111] \| [HTMLElement][112])** A CSS selector that can be used to find elements using [`querySelector()`][113], or an [HTMLElement][] (Not all assertions support both target types.) (optional, default `rootElement` or `document`) -- `rootElement` **[HTMLElement][112]?** The root element of the DOM in which to search for the `target` (optional, default `document`) +- `target` **([string][114] \| [HTMLElement][115])** A CSS selector that can be used to find elements using [`querySelector()`][116], or an [HTMLElement][] (Not all assertions support both target types.) (optional, default `rootElement` or `document`) +- `rootElement` **[HTMLElement][115]?** The root element of the DOM in which to search for the `target` (optional, default `document`) **Examples** @@ -135,16 +138,16 @@ test('the title exists', function(assert) { ### exists -- **See: [#doesNotExist][114] +- **See: [#doesNotExist][117] ** -Assert an [HTMLElement][115] (or multiple) matching the `selector` exists. +Assert an [HTMLElement][118] (or multiple) matching the `selector` exists. #### Parameters -- `options` **[object][116]?** - - `options.count` **[number][117]?** -- `message` **[string][118]?** +- `options` **[object][119]?** + - `options.count` **[number][120]?** +- `message` **[string][121]?** #### Examples @@ -158,11 +161,11 @@ assert.dom('.choice').exists({ count: 4 }); - **See: [#exists][3] ** -Assert an [HTMLElement][115] matching the `selector` does not exists. +Assert an [HTMLElement][118] matching the `selector` does not exists. #### Parameters -- `message` **[string][118]?** +- `message` **[string][121]?** #### Examples @@ -172,17 +175,17 @@ assert.dom('.should-not-exist').doesNotExist(); ### isChecked -- **See: [#isNotChecked][119] +- **See: [#isNotChecked][122] ** -Assert that the [HTMLElement][115] or an [HTMLElement][115] matching the +Assert that the [HTMLElement][118] or an [HTMLElement][118] matching the `selector` is currently checked. Note: This also supports `aria-checked="true/false"`. #### Parameters -- `message` **[string][118]?** +- `message` **[string][121]?** #### Examples @@ -192,17 +195,17 @@ assert.dom('input.active').isChecked(); ### isNotChecked -- **See: [#isChecked][120] +- **See: [#isChecked][123] ** -Assert that the [HTMLElement][115] or an [HTMLElement][115] matching the +Assert that the [HTMLElement][118] or an [HTMLElement][118] matching the `selector` is currently unchecked. Note: This also supports `aria-checked="true/false"`. #### Parameters -- `message` **[string][118]?** +- `message` **[string][121]?** #### Examples @@ -212,15 +215,15 @@ assert.dom('input.active').isNotChecked(); ### isFocused -- **See: [#isNotFocused][121] +- **See: [#isNotFocused][124] ** -Assert that the [HTMLElement][115] or an [HTMLElement][115] matching the +Assert that the [HTMLElement][118] or an [HTMLElement][118] matching the `selector` is currently focused. #### Parameters -- `message` **[string][118]?** +- `message` **[string][121]?** #### Examples @@ -230,15 +233,15 @@ assert.dom('input.email').isFocused(); ### isNotFocused -- **See: [#isFocused][122] +- **See: [#isFocused][125] ** -Assert that the [HTMLElement][115] or an [HTMLElement][115] matching the +Assert that the [HTMLElement][118] or an [HTMLElement][118] matching the `selector` is not currently focused. #### Parameters -- `message` **[string][118]?** +- `message` **[string][121]?** #### Examples @@ -248,15 +251,15 @@ assert.dom('input[type="password"]').isNotFocused(); ### isRequired -- **See: [#isNotRequired][123] +- **See: [#isNotRequired][126] ** -Assert that the [HTMLElement][115] or an [HTMLElement][115] matching the +Assert that the [HTMLElement][118] or an [HTMLElement][118] matching the `selector` is currently required. #### Parameters -- `message` **[string][118]?** +- `message` **[string][121]?** #### Examples @@ -266,15 +269,15 @@ assert.dom('input[type="text"]').isRequired(); ### isNotRequired -- **See: [#isRequired][124] +- **See: [#isRequired][127] ** -Assert that the [HTMLElement][115] or an [HTMLElement][115] matching the +Assert that the [HTMLElement][118] or an [HTMLElement][118] matching the `selector` is currently not required. #### Parameters -- `message` **[string][118]?** +- `message` **[string][121]?** #### Examples @@ -284,10 +287,10 @@ assert.dom('input[type="text"]').isNotRequired(); ### isValid -- **See: [#isValid][125] +- **See: [#isValid][128] ** -Assert that the [HTMLElement][115] passes validation +Assert that the [HTMLElement][118] passes validation Validity is determined by asserting that: @@ -295,7 +298,7 @@ Validity is determined by asserting that: #### Parameters -- `message` **[string][118]?** +- `message` **[string][121]?** #### Examples @@ -303,12 +306,33 @@ Validity is determined by asserting that: assert.dom('.input').isValid(); ``` +### isNotValid + +- **See: [#isValid][128] + ** + +Assert that the [HTMLElement][118] does not pass validation + +Validity is determined by asserting that: + +- `element.reportValidity() === true` + +#### Parameters + +- `message` **[string][121]?** + +#### Examples + +```javascript +assert.dom('.input').isNotValid(); +``` + ### isVisible -- **See: [#isNotVisible][126] +- **See: [#isNotVisible][129] ** -Assert that the [HTMLElement][115] or an [HTMLElement][115] matching the +Assert that the [HTMLElement][118] or an [HTMLElement][118] matching the `selector` exists and is visible. Visibility is determined by asserting that: @@ -321,9 +345,9 @@ but not necessarily in the viewport. #### Parameters -- `options` **[object][116]?** - - `options.count` **[number][117]?** -- `message` **[string][118]?** +- `options` **[object][119]?** + - `options.count` **[number][120]?** +- `message` **[string][121]?** #### Examples @@ -334,10 +358,10 @@ assert.dom('.choice').isVisible({ count: 4 }); ### isNotVisible -- **See: [#isVisible][127] +- **See: [#isVisible][130] ** -Assert that the [HTMLElement][115] or an [HTMLElement][115] matching the +Assert that the [HTMLElement][118] or an [HTMLElement][118] matching the `selector` does not exist or is not visible on the page. Visibility is determined by asserting that: @@ -350,7 +374,7 @@ but not necessarily in the viewport. #### Parameters -- `message` **[string][118]?** +- `message` **[string][121]?** #### Examples @@ -360,18 +384,18 @@ assert.dom('.foo').isNotVisible(); ### hasAttribute -- **See: [#doesNotHaveAttribute][128] +- **See: [#doesNotHaveAttribute][131] ** -Assert that the [HTMLElement][115] has an attribute with the provided `name` +Assert that the [HTMLElement][118] has an attribute with the provided `name` and optionally checks if the attribute `value` matches the provided text or regular expression. #### Parameters -- `name` **[string][118]** -- `value` **([string][118] \| [RegExp][129] \| [object][116]?)** -- `message` **[string][118]?** +- `name` **[string][121]** +- `value` **([string][121] \| [RegExp][132] \| [object][119]?)** +- `message` **[string][121]?** #### Examples @@ -381,17 +405,17 @@ assert.dom('input.password-input').hasAttribute('type', 'password'); ### doesNotHaveAttribute -- **See: [#hasAttribute][130] +- **See: [#hasAttribute][133] ** -Assert that the [HTMLElement][115] has no attribute with the provided `name`. +Assert that the [HTMLElement][118] has no attribute with the provided `name`. **Aliases:** `hasNoAttribute`, `lacksAttribute` #### Parameters -- `name` **[string][118]** -- `message` **[string][118]?** +- `name` **[string][121]** +- `message` **[string][121]?** #### Examples @@ -401,18 +425,18 @@ assert.dom('input.username').hasNoAttribute('disabled'); ### hasAria -- **See: [#hasNoAria][131] +- **See: [#hasNoAria][134] ** -Assert that the [HTMLElement][115] has an ARIA attribute with the provided +Assert that the [HTMLElement][118] has an ARIA attribute with the provided `name` and optionally checks if the attribute `value` matches the provided text or regular expression. #### Parameters -- `name` **[string][118]** -- `value` **([string][118] \| [RegExp][129] \| [object][116]?)** -- `message` **[string][118]?** +- `name` **[string][121]** +- `value` **([string][121] \| [RegExp][132] \| [object][119]?)** +- `message` **[string][121]?** #### Examples @@ -422,16 +446,16 @@ assert.dom('button').hasAria('pressed', 'true'); ### doesNotHaveAria -- **See: [#hasAria][132] +- **See: [#hasAria][135] ** -Assert that the [HTMLElement][115] has no ARIA attribute with the +Assert that the [HTMLElement][118] has no ARIA attribute with the provided `name`. #### Parameters -- `name` **[string][118]** -- `message` **[string][118]?** +- `name` **[string][121]** +- `message` **[string][121]?** #### Examples @@ -441,18 +465,18 @@ assert.dom('button').doesNotHaveAria('pressed'); ### hasProperty -- **See: [#doesNotHaveProperty][133] +- **See: [#doesNotHaveProperty][136] ** -Assert that the [HTMLElement][115] has a property with the provided `name` +Assert that the [HTMLElement][118] has a property with the provided `name` and checks if the property `value` matches the provided text or regular expression. #### Parameters -- `name` **[string][118]** -- `value` **([string][118] \| [RegExp][129])** -- `message` **[string][118]?** +- `name` **[string][121]** +- `value` **([string][121] \| [RegExp][132])** +- `message` **[string][121]?** #### Examples @@ -462,15 +486,15 @@ assert.dom('input.password-input').hasProperty('type', 'password'); ### isDisabled -- **See: [#isNotDisabled][134] +- **See: [#isNotDisabled][137] ** -Assert that the [HTMLElement][115] or an [HTMLElement][115] matching the +Assert that the [HTMLElement][118] or an [HTMLElement][118] matching the `selector` is disabled. #### Parameters -- `message` **[string][118]?** +- `message` **[string][121]?** #### Examples @@ -480,17 +504,17 @@ assert.dom('.foo').isDisabled(); ### isNotDisabled -- **See: [#isDisabled][135] +- **See: [#isDisabled][138] ** -Assert that the [HTMLElement][115] or an [HTMLElement][115] matching the +Assert that the [HTMLElement][118] or an [HTMLElement][118] matching the `selector` is not disabled. **Aliases:** `isEnabled` #### Parameters -- `message` **[string][118]?** +- `message` **[string][121]?** #### Examples @@ -500,19 +524,19 @@ assert.dom('.foo').isNotDisabled(); ### hasClass -- **See: [#doesNotHaveClass][136] +- **See: [#doesNotHaveClass][139] ** -Assert that the [HTMLElement][115] has the `expected` CSS class using -[`classList`][137]. +Assert that the [HTMLElement][118] has the `expected` CSS class using +[`classList`][140]. `expected` can also be a regular expression, and the assertion will return true if any of the element's CSS classes match. #### Parameters -- `expected` **([string][118] \| [RegExp][129])** -- `message` **[string][118]?** +- `expected` **([string][121] \| [RegExp][132])** +- `message` **[string][121]?** #### Examples @@ -526,11 +550,11 @@ assert.dom('input[type="password"]').hasClass(/.*password-input/); ### doesNotHaveClass -- **See: [#hasClass][138] +- **See: [#hasClass][141] ** -Assert that the [HTMLElement][115] does not have the `expected` CSS class using -[`classList`][137]. +Assert that the [HTMLElement][118] does not have the `expected` CSS class using +[`classList`][140]. `expected` can also be a regular expression, and the assertion will return true if none of the element's CSS classes match. @@ -539,8 +563,8 @@ true if none of the element's CSS classes match. #### Parameters -- `expected` **([string][118] \| [RegExp][129])** -- `message` **[string][118]?** +- `expected` **([string][121] \| [RegExp][132])** +- `message` **[string][121]?** #### Examples @@ -554,16 +578,16 @@ assert.dom('input[type="password"]').doesNotHaveClass(/username-.*-input/); ### hasStyle -- **See: [#hasClass][138] +- **See: [#hasClass][141] ** Assert that the [HTMLElement][] has the `expected` style declarations using -[`window.getComputedStyle`][139]. +[`window.getComputedStyle`][142]. #### Parameters -- `expected` **[object][116]** -- `message` **[string][118]?** +- `expected` **[object][119]** +- `message` **[string][121]?** #### Examples @@ -576,17 +600,17 @@ assert.dom('.progress-bar').hasStyle({ ### hasPseudoElementStyle -- **See: [#hasClass][138] +- **See: [#hasClass][141] ** Assert that the pseudo element for `selector` of the [HTMLElement][] has the `expected` style declarations using -[`window.getComputedStyle`][139]. +[`window.getComputedStyle`][142]. #### Parameters -- `selector` **[string][118]** -- `expected` **[object][116]** -- `message` **[string][118]?** +- `selector` **[string][121]** +- `expected` **[object][119]** +- `message` **[string][121]?** #### Examples @@ -598,16 +622,16 @@ assert.dom('.progress-bar').hasPseudoElementStyle(':after', { ### doesNotHaveStyle -- **See: [#hasClass][138] +- **See: [#hasClass][141] ** Assert that the [HTMLElement][] does not have the `expected` style declarations using -[`window.getComputedStyle`][139]. +[`window.getComputedStyle`][142]. #### Parameters -- `expected` **[object][116]** -- `message` **[string][118]?** +- `expected` **[object][119]** +- `message` **[string][121]?** #### Examples @@ -620,17 +644,17 @@ assert.dom('.progress-bar').doesNotHaveStyle({ ### doesNotHavePseudoElementStyle -- **See: [#hasClass][138] +- **See: [#hasClass][141] ** Assert that the pseudo element for `selector` of the [HTMLElement][] does not have the `expected` style declarations using -[`window.getComputedStyle`][139]. +[`window.getComputedStyle`][142]. #### Parameters -- `selector` **[string][118]** -- `expected` **[object][116]** -- `message` **[string][118]?** +- `selector` **[string][121]** +- `expected` **[object][119]** +- `message` **[string][121]?** #### Examples @@ -642,12 +666,12 @@ assert.dom('.progress-bar').doesNotHavePseudoElementStyle(':after', { ### hasText -- **See: [#includesText][140] +- **See: [#includesText][143] ** -Assert that the text of the [HTMLElement][115] or an [HTMLElement][115] +Assert that the text of the [HTMLElement][118] or an [HTMLElement][118] matching the `selector` matches the `expected` text, using the -[`textContent`][141] +[`textContent`][144] attribute and stripping/collapsing whitespace. `expected` can also be a regular expression. @@ -660,8 +684,8 @@ attribute and stripping/collapsing whitespace. #### Parameters -- `expected` **([string][118] \| [RegExp][129])** -- `message` **[string][118]?** +- `expected` **([string][121] \| [RegExp][132])** +- `message` **[string][121]?** #### Examples @@ -679,14 +703,14 @@ assert.dom('.foo').hasText(/[12]\d{3}/); ### hasAnyText -- **See: [#hasText][142] +- **See: [#hasText][145] ** -Assert that the `textContent` property of an [HTMLElement][115] is not empty. +Assert that the `textContent` property of an [HTMLElement][118] is not empty. #### Parameters -- `message` **[string][118]?** +- `message` **[string][121]?** #### Examples @@ -696,14 +720,14 @@ assert.dom('button.share').hasAnyText(); ### hasNoText -- **See: [#hasNoText][143] +- **See: [#hasNoText][146] ** -Assert that the `textContent` property of an [HTMLElement][115] is empty. +Assert that the `textContent` property of an [HTMLElement][118] is empty. #### Parameters -- `message` **[string][118]?** +- `message` **[string][121]?** #### Examples @@ -713,25 +737,25 @@ assert.dom('div').hasNoText(); ### includesText -- **See: [#hasText][142] +- **See: [#hasText][145] ** -Assert that the text of the [HTMLElement][115] or an [HTMLElement][115] +Assert that the text of the [HTMLElement][118] or an [HTMLElement][118] matching the `selector` contains the given `text`, using the -[`textContent`][141] +[`textContent`][144] attribute. > Note: This assertion will collapse whitespace in `textContent` before searching. > If you would like to assert on a string that _should_ contain line breaks, tabs, -> more than one space in a row, or starting/ending whitespace, use the [#hasText][142] +> more than one space in a row, or starting/ending whitespace, use the [#hasText][145] > selector and pass your expected text in as a RegEx pattern. **Aliases:** `containsText`, `hasTextContaining` #### Parameters -- `text` **[string][118]** -- `message` **[string][118]?** +- `text` **[string][121]** +- `message` **[string][121]?** #### Examples @@ -741,17 +765,17 @@ assert.dom('#title').includesText('Welcome'); ### doesNotIncludeText -Assert that the text of the [HTMLElement][115] or an [HTMLElement][115] +Assert that the text of the [HTMLElement][118] or an [HTMLElement][118] matching the `selector` does not include the given `text`, using the -[`textContent`][141] +[`textContent`][144] attribute. **Aliases:** `doesNotContainText`, `doesNotHaveTextContaining` #### Parameters -- `text` **[string][118]** -- `message` **[string][118]?** +- `text` **[string][121]** +- `message` **[string][121]?** #### Examples @@ -761,12 +785,12 @@ assert.dom('#title').doesNotIncludeText('Welcome'); ### hasValue -- **See: [#hasAnyValue][144] +- **See: [#hasAnyValue][147] ** -- **See: [#hasNoValue][145] +- **See: [#hasNoValue][148] ** -Assert that the `value` property of an [HTMLInputElement][146] matches +Assert that the `value` property of an [HTMLInputElement][149] matches the `expected` text or regular expression. If no `expected` value is provided, the assertion will fail if the @@ -774,8 +798,8 @@ If no `expected` value is provided, the assertion will fail if the #### Parameters -- `expected` **([string][118] \| [RegExp][129] \| [object][116]?)** -- `message` **[string][118]?** +- `expected` **([string][121] \| [RegExp][132] \| [object][119]?)** +- `message` **[string][121]?** #### Examples @@ -785,16 +809,16 @@ assert.dom('input.username').hasValue('HSimpson'); ### hasAnyValue -- **See: [#hasValue][147] +- **See: [#hasValue][150] ** -- **See: [#hasNoValue][145] +- **See: [#hasNoValue][148] ** -Assert that the `value` property of an [HTMLInputElement][146] is not empty. +Assert that the `value` property of an [HTMLInputElement][149] is not empty. #### Parameters -- `message` **[string][118]?** +- `message` **[string][121]?** #### Examples @@ -804,18 +828,18 @@ assert.dom('input.username').hasAnyValue(); ### hasNoValue -- **See: [#hasValue][147] +- **See: [#hasValue][150] ** -- **See: [#hasAnyValue][144] +- **See: [#hasAnyValue][147] ** -Assert that the `value` property of an [HTMLInputElement][146] is empty. +Assert that the `value` property of an [HTMLInputElement][149] is empty. **Aliases:** `lacksValue` #### Parameters -- `message` **[string][118]?** +- `message` **[string][121]?** #### Examples @@ -830,8 +854,8 @@ compareSelector. #### Parameters -- `compareSelector` **[string][118]** -- `message` **[string][118]?** +- `compareSelector` **[string][121]** +- `message` **[string][121]?** #### Examples @@ -846,8 +870,8 @@ compareSelector. #### Parameters -- `compareSelector` **[string][118]** -- `message` **[string][118]?** +- `compareSelector` **[string][121]** +- `message` **[string][121]?** #### Examples @@ -857,16 +881,16 @@ assert.dom('input').doesNotMatchSelector('input[disabled]') ### hasTagName -Assert that the tagName of the [HTMLElement][115] or an [HTMLElement][115] +Assert that the tagName of the [HTMLElement][118] or an [HTMLElement][118] matching the `selector` matches the `expected` tagName, using the -[`tagName`][148] -property of the [HTMLElement][115]. +[`tagName`][151] +property of the [HTMLElement][118]. #### Parameters - `tagName` -- `message` **[string][118]?** -- `expected` **[string][118]** +- `message` **[string][121]?** +- `expected` **[string][121]** #### Examples @@ -880,16 +904,16 @@ assert.dom('#title').hasTagName('h1'); ### doesNotHaveTagName -Assert that the tagName of the [HTMLElement][115] or an [HTMLElement][115] +Assert that the tagName of the [HTMLElement][118] or an [HTMLElement][118] matching the `selector` does not match the `expected` tagName, using the -[`tagName`][148] -property of the [HTMLElement][115]. +[`tagName`][151] +property of the [HTMLElement][118]. #### Parameters - `tagName` -- `message` **[string][118]?** -- `expected` **[string][118]** +- `message` **[string][121]?** +- `expected` **[string][121]** #### Examples @@ -959,240 +983,246 @@ assert.dom('section#block').doesNotHaveTagName('div'); [29]: #examples-8 -[30]: #isvisible +[30]: #isnotvalid [31]: #parameters-9 [32]: #examples-9 -[33]: #isnotvisible +[33]: #isvisible [34]: #parameters-10 [35]: #examples-10 -[36]: #hasattribute +[36]: #isnotvisible [37]: #parameters-11 [38]: #examples-11 -[39]: #doesnothaveattribute +[39]: #hasattribute [40]: #parameters-12 [41]: #examples-12 -[42]: #hasaria +[42]: #doesnothaveattribute [43]: #parameters-13 [44]: #examples-13 -[45]: #doesnothavearia +[45]: #hasaria [46]: #parameters-14 [47]: #examples-14 -[48]: #hasproperty +[48]: #doesnothavearia [49]: #parameters-15 [50]: #examples-15 -[51]: #isdisabled +[51]: #hasproperty [52]: #parameters-16 [53]: #examples-16 -[54]: #isnotdisabled +[54]: #isdisabled [55]: #parameters-17 [56]: #examples-17 -[57]: #hasclass +[57]: #isnotdisabled [58]: #parameters-18 [59]: #examples-18 -[60]: #doesnothaveclass +[60]: #hasclass [61]: #parameters-19 [62]: #examples-19 -[63]: #hasstyle +[63]: #doesnothaveclass [64]: #parameters-20 [65]: #examples-20 -[66]: #haspseudoelementstyle +[66]: #hasstyle [67]: #parameters-21 [68]: #examples-21 -[69]: #doesnothavestyle +[69]: #haspseudoelementstyle [70]: #parameters-22 [71]: #examples-22 -[72]: #doesnothavepseudoelementstyle +[72]: #doesnothavestyle [73]: #parameters-23 [74]: #examples-23 -[75]: #hastext +[75]: #doesnothavepseudoelementstyle [76]: #parameters-24 [77]: #examples-24 -[78]: #hasanytext +[78]: #hastext [79]: #parameters-25 [80]: #examples-25 -[81]: #hasnotext +[81]: #hasanytext [82]: #parameters-26 [83]: #examples-26 -[84]: #includestext +[84]: #hasnotext [85]: #parameters-27 [86]: #examples-27 -[87]: #doesnotincludetext +[87]: #includestext [88]: #parameters-28 [89]: #examples-28 -[90]: #hasvalue +[90]: #doesnotincludetext [91]: #parameters-29 [92]: #examples-29 -[93]: #hasanyvalue +[93]: #hasvalue [94]: #parameters-30 [95]: #examples-30 -[96]: #hasnovalue +[96]: #hasanyvalue [97]: #parameters-31 [98]: #examples-31 -[99]: #matchesselector +[99]: #hasnovalue [100]: #parameters-32 [101]: #examples-32 -[102]: #doesnotmatchselector +[102]: #matchesselector [103]: #parameters-33 [104]: #examples-33 -[105]: #hastagname +[105]: #doesnotmatchselector [106]: #parameters-34 [107]: #examples-34 -[108]: #doesnothavetagname +[108]: #hastagname [109]: #parameters-35 [110]: #examples-35 -[111]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String +[111]: #doesnothavetagname + +[112]: #parameters-36 + +[113]: #examples-36 + +[114]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String -[112]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element +[115]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element -[113]: https://developer.mozilla.org/de/docs/Web/API/Document/querySelector +[116]: https://developer.mozilla.org/de/docs/Web/API/Document/querySelector -[114]: #doesNotExist +[117]: #doesNotExist -[115]: https://developer.mozilla.org/docs/Web/HTML/Element +[118]: https://developer.mozilla.org/docs/Web/HTML/Element -[116]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object +[119]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object -[117]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number +[120]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number -[118]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String +[121]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String -[119]: #isNotChecked +[122]: #isNotChecked -[120]: #isChecked +[123]: #isChecked -[121]: #isNotFocused +[124]: #isNotFocused -[122]: #isFocused +[125]: #isFocused -[123]: #isNotRequired +[126]: #isNotRequired -[124]: #isRequired +[127]: #isRequired -[125]: #isValid +[128]: #isValid -[126]: #isNotVisible +[129]: #isNotVisible -[127]: #isVisible +[130]: #isVisible -[128]: #doesNotHaveAttribute +[131]: #doesNotHaveAttribute -[129]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RegExp +[132]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RegExp -[130]: #hasAttribute +[133]: #hasAttribute -[131]: #hasNoAria +[134]: #hasNoAria -[132]: #hasAria +[135]: #hasAria -[133]: #doesNotHaveProperty +[136]: #doesNotHaveProperty -[134]: #isNotDisabled +[137]: #isNotDisabled -[135]: #isDisabled +[138]: #isDisabled -[136]: #doesNotHaveClass +[139]: #doesNotHaveClass -[137]: https://developer.mozilla.org/en-US/docs/Web/API/Element/classList +[140]: https://developer.mozilla.org/en-US/docs/Web/API/Element/classList -[138]: #hasClass +[141]: #hasClass -[139]: https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle +[142]: https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle -[140]: #includesText +[143]: #includesText -[141]: https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent +[144]: https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent -[142]: #hasText +[145]: #hasText -[143]: #hasNoText +[146]: #hasNoText -[144]: #hasAnyValue +[147]: #hasAnyValue -[145]: #hasNoValue +[148]: #hasNoValue -[146]: https://developer.mozilla.org/docs/Web/API/HTMLInputElement +[149]: https://developer.mozilla.org/docs/Web/API/HTMLInputElement -[147]: #hasValue +[150]: #hasValue -[148]: https://developer.mozilla.org/en-US/docs/Web/API/Element/tagName +[151]: https://developer.mozilla.org/en-US/docs/Web/API/Element/tagName diff --git a/lib/__tests__/is-not-valid.ts b/lib/__tests__/is-not-valid.ts new file mode 100644 index 000000000..6b32c6981 --- /dev/null +++ b/lib/__tests__/is-not-valid.ts @@ -0,0 +1,170 @@ +/* eslint-env jest */ +import TestAssertions from '../helpers/test-assertions'; + +describe('assert.dom(...).isNotValid()', () => { + let assert: TestAssertions; + + beforeEach(() => { + assert = new TestAssertions(); + }); + + describe('invalid', () => { + test('with no custom message', () => { + document.body.innerHTML = ''; + + assert.dom('input').isNotValid(); + expect(assert.results).toEqual([ + { + actual: 'not valid', + expected: 'not valid', + message: 'Element input is not valid', + result: true, + }, + ]); + }); + + test('with custom message', () => { + document.body.innerHTML = ''; + + assert.dom('input').isNotValid('custom message'); + expect(assert.results).toEqual([ + { + actual: 'not valid', + expected: 'not valid', + message: 'custom message', + result: true, + }, + ]); + }); + }); + + describe('valid', () => { + test('with no custom message', () => { + document.body.innerHTML = ''; + + assert.dom('input').isNotValid(); + expect(assert.results).toEqual([ + { + actual: 'valid', + expected: 'not valid', + message: 'Element input is valid', + result: false, + }, + ]); + }); + }); + + describe('with HTMLElement', () => { + let element: HTMLInputElement; + + beforeEach(() => { + document.body.innerHTML = ''; + element = document.querySelector('input'); + }); + + test('fails if element is valid', () => { + assert.dom(element).isNotValid(); + + expect(assert.results).toEqual([ + { + actual: 'valid', + expected: 'not valid', + message: 'Element input[type="text"][value="foo"][required] is valid', + result: false, + }, + ]); + }); + + test('fails if element is not required', () => { + element.required = false; + assert.dom(element).isNotValid(); + + expect(assert.results).toEqual([ + { + actual: 'valid', + expected: 'not valid', + message: 'Element input[type="text"][value="foo"] is valid', + result: false, + }, + ]); + }); + + test('fails for missing element', () => { + assert.dom(null).isNotValid(); + + expect(assert.results).toEqual([ + { + message: 'Element should exist', + result: false, + }, + ]); + }); + }); + + describe('with selector', () => { + beforeEach(() => { + document.body.innerHTML = ''; + }); + + test('fails if element is required', () => { + assert.dom('input').isNotValid(); + + expect(assert.results).toEqual([ + { + actual: 'valid', + expected: 'not valid', + message: 'Element input is valid', + result: false, + }, + ]); + }); + + test('fails if element is not required', () => { + document.querySelector('input').required = false; + assert.dom('input').isNotValid(); + + expect(assert.results).toEqual([ + { + actual: 'valid', + expected: 'not valid', + message: 'Element input is valid', + result: false, + }, + ]); + }); + + test('fails for missing element', () => { + assert.dom('input[type="password"]').isNotValid(); + + expect(assert.results).toEqual([ + { + message: 'Element input[type="password"] should exist', + result: false, + }, + ]); + }); + }); + + test('throws for unexpected parameter types', () => { + //@ts-ignore -- These assertions are for JavaScript users who don't have type checking + expect(() => assert.dom(5).isNotValid()).toThrow('Unexpected Parameter: 5'); + //@ts-ignore + expect(() => assert.dom(true).isNotValid()).toThrow('Unexpected Parameter: true'); + expect(() => assert.dom(undefined).isNotValid()).toThrow('Unexpected Parameter: undefined'); + //@ts-ignore + expect(() => assert.dom({}).isNotValid()).toThrow('Unexpected Parameter: [object Object]'); + //@ts-ignore + expect(() => assert.dom(document).isNotValid()).toThrow('Unexpected Parameter: [object Document]'); + expect(() => assert.dom(document.createElement('div')).isNotValid()).toThrow( + 'Unexpected Element Type: [object HTMLDivElement]' + ); + }); + + test('supports chaining', () => { + document.body.innerHTML = ''; + + assert.dom('input').isNotValid().isNotValid(); + + expect(assert.results.length).toEqual(2); + }); +}); diff --git a/lib/assertions.ts b/lib/assertions.ts index 60f3ffa35..371ecc8de 100644 --- a/lib/assertions.ts +++ b/lib/assertions.ts @@ -213,6 +213,25 @@ export default class DOMAssertions { return this; } + /** + * Assert that the {@link HTMLElement} does not pass validation + * + * Validity is determined by asserting that: + * + * - `element.reportValidity() === true` + * + * @param {string?} message + * + * @example + * assert.dom('.input').isNotValid(); + * + * @see {@link #isValid} + */ + isNotValid(message?: string): DOMAssertions { + isValid.call(this, message, { inverted: true }); + return this; + } + /** * Assert that the {@link HTMLElement} or an {@link HTMLElement} matching the * `selector` exists and is visible. diff --git a/lib/assertions/is-valid.ts b/lib/assertions/is-valid.ts index 5589c6671..c5ca5d143 100644 --- a/lib/assertions/is-valid.ts +++ b/lib/assertions/is-valid.ts @@ -1,6 +1,6 @@ import elementToString from '../helpers/element-to-string'; -export default function isValid(message?: string) { +export default function isValid(message?: string, options: { inverted?: boolean } = {}) { let element = this.findTargetElement(); if (!element) return; @@ -17,9 +17,10 @@ export default function isValid(message?: string) { throw new TypeError(`Unexpected Element Type: ${element.toString()}`); } - let result = element.reportValidity() === true; - let actual = result ? 'valid' : 'not valid'; - let expected = 'valid'; + let validity = element.reportValidity() === true; + let result = validity === !options.inverted; + let actual = validity ? 'valid' : 'not valid'; + let expected = options.inverted ? 'not valid' : 'valid'; if (!message) { message = `Element ${elementToString(this.target)} is ${actual}`;