From 50aeab02c918d19402816621315558a379f4490c Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Sun, 2 Feb 2020 16:11:16 +0100 Subject: [PATCH] Add support for assertion chaining --- lib/__tests__/does-not-exist.ts | 11 ++ lib/__tests__/does-not-have-attribute.ts | 9 + lib/__tests__/does-not-have-class.ts | 11 ++ lib/__tests__/does-not-have-style.ts | 9 + lib/__tests__/does-not-have-tagname.ts | 11 ++ lib/__tests__/does-not-include-text.ts | 11 ++ lib/__tests__/does-not-match-selector.ts | 11 ++ lib/__tests__/exists.ts | 11 ++ lib/__tests__/has-any-text.ts | 11 ++ lib/__tests__/has-any-value.ts | 11 ++ lib/__tests__/has-attribute.ts | 11 ++ lib/__tests__/has-class.ts | 11 ++ lib/__tests__/has-no-text.ts | 11 ++ lib/__tests__/has-no-value.ts | 11 ++ lib/__tests__/has-property.ts | 11 ++ lib/__tests__/has-style.ts | 11 ++ lib/__tests__/has-tagname.ts | 11 ++ lib/__tests__/has-text.ts | 11 ++ lib/__tests__/has-value.ts | 11 ++ lib/__tests__/includes-text.ts | 11 ++ lib/__tests__/is-checked.ts | 11 ++ lib/__tests__/is-disabled.ts | 11 ++ lib/__tests__/is-focused.ts | 11 ++ lib/__tests__/is-not-checked.ts | 11 ++ lib/__tests__/is-not-disabled.ts | 11 ++ lib/__tests__/is-not-focused.ts | 11 ++ lib/__tests__/is-not-required.ts | 11 ++ lib/__tests__/is-not-visible.ts | 11 ++ lib/__tests__/is-required.ts | 11 ++ lib/__tests__/is-visible.ts | 11 ++ lib/__tests__/matches-selector.ts | 11 ++ lib/assertions.ts | 203 ++++++++++++++--------- 32 files changed, 461 insertions(+), 79 deletions(-) diff --git a/lib/__tests__/does-not-exist.ts b/lib/__tests__/does-not-exist.ts index 07a1eebc5..43230dd41 100644 --- a/lib/__tests__/does-not-exist.ts +++ b/lib/__tests__/does-not-exist.ts @@ -84,4 +84,15 @@ describe('assert.dom(...).doesNotExist()', () => { 'Unexpected Parameter: [object Document]' ); }); + + test('supports chaining', () => { + document.body.innerHTML = '

foo

bar'; + + assert + .dom('h2') + .doesNotExist() + .doesNotExist(); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/does-not-have-attribute.ts b/lib/__tests__/does-not-have-attribute.ts index ff32b5bc5..f9297930f 100644 --- a/lib/__tests__/does-not-have-attribute.ts +++ b/lib/__tests__/does-not-have-attribute.ts @@ -102,4 +102,13 @@ describe('assert.dom(...).doesNotHaveAttribute()', () => { 'Unexpected Parameter: [object Document]' ); }); + + test('supports chaining', () => { + assert + .dom('input') + .doesNotHaveAttribute('disabled') + .doesNotHaveAttribute('required'); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/does-not-have-class.ts b/lib/__tests__/does-not-have-class.ts index b70f524a0..be14d71de 100644 --- a/lib/__tests__/does-not-have-class.ts +++ b/lib/__tests__/does-not-have-class.ts @@ -134,4 +134,15 @@ describe('assert.dom(...).doesNotHaveClass()', () => { 'Unexpected Parameter: [object Document]' ); }); + + test('supports chaining', () => { + document.body.innerHTML = '

foo

'; + + assert + .dom('h1') + .doesNotHaveClass('foo') + .doesNotHaveClass('bar'); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/does-not-have-style.ts b/lib/__tests__/does-not-have-style.ts index 1391f2e8f..83264619c 100644 --- a/lib/__tests__/does-not-have-style.ts +++ b/lib/__tests__/does-not-have-style.ts @@ -115,4 +115,13 @@ describe('assert.dom(...).doesNotHaveStyle()', () => { 'Missing style expectations. There must be at least one style property in the passed in expectation object.' ); }); + + test('supports chaining', () => { + assert + .dom('h2') + .doesNotHaveStyle({ left: 0 }) + .doesNotHaveStyle({ top: 0 }); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/does-not-have-tagname.ts b/lib/__tests__/does-not-have-tagname.ts index da0fe63e5..22a42be10 100644 --- a/lib/__tests__/does-not-have-tagname.ts +++ b/lib/__tests__/does-not-have-tagname.ts @@ -153,4 +153,15 @@ describe('assert.dom(...).doesNotHaveTagName()', () => { ); }); }); + + test('supports chaining', () => { + document.body.innerHTML = '

foo

'; + + assert + .dom('h1') + .doesNotHaveTagName('div') + .doesNotHaveTagName('h1'); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/does-not-include-text.ts b/lib/__tests__/does-not-include-text.ts index fd010e5a8..b120f2e1b 100644 --- a/lib/__tests__/does-not-include-text.ts +++ b/lib/__tests__/does-not-include-text.ts @@ -130,4 +130,15 @@ describe('assert.dom(...).doesNotIncludeText()', () => { 'Unexpected Parameter: [object Document]' ); }); + + test('supports chaining', () => { + document.body.innerHTML = '

foo

'; + + assert + .dom('h1') + .doesNotIncludeText('foo') + .doesNotIncludeText('bar'); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/does-not-match-selector.ts b/lib/__tests__/does-not-match-selector.ts index 49551b0b9..9868f5f84 100644 --- a/lib/__tests__/does-not-match-selector.ts +++ b/lib/__tests__/does-not-match-selector.ts @@ -95,4 +95,15 @@ describe('assert.dom(...).doesNotMatchSelector()', () => { ]); }); }); + + test('supports chaining', () => { + document.body.innerHTML = '

foo

'; + + assert + .dom('h1') + .doesNotMatchSelector('.foo') + .doesNotMatchSelector('.bar'); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/exists.ts b/lib/__tests__/exists.ts index 6e071f614..d1d7e7e13 100644 --- a/lib/__tests__/exists.ts +++ b/lib/__tests__/exists.ts @@ -179,4 +179,15 @@ describe('assert.dom(...).exists()', () => { //@ts-ignore expect(() => assert.dom(document).exists()).toThrow('Unexpected Parameter: [object Document]'); }); + + test('supports chaining', () => { + document.body.innerHTML = '

foo

'; + + assert + .dom('h1') + .exists() + .exists(); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/has-any-text.ts b/lib/__tests__/has-any-text.ts index fee10ce1f..1b60e79d3 100644 --- a/lib/__tests__/has-any-text.ts +++ b/lib/__tests__/has-any-text.ts @@ -77,4 +77,15 @@ describe('assert.dom(...).hasAnyText()', () => { 'Unexpected Parameter: [object Document]' ); }); + + test('supports chaining', () => { + document.body.innerHTML = '

foo

'; + + assert + .dom('h1') + .hasAnyText() + .hasAnyText(); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/has-any-value.ts b/lib/__tests__/has-any-value.ts index 224a806aa..e8eaf2424 100644 --- a/lib/__tests__/has-any-value.ts +++ b/lib/__tests__/has-any-value.ts @@ -79,4 +79,15 @@ describe('assert.dom(...).hasAnyValue()', () => { 'Unexpected Parameter: [object Document]' ); }); + + test('supports chaining', () => { + document.body.innerHTML = ''; + + assert + .dom('input') + .hasAnyValue() + .hasAnyValue(); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/has-attribute.ts b/lib/__tests__/has-attribute.ts index ea7d0095c..aa8c04995 100644 --- a/lib/__tests__/has-attribute.ts +++ b/lib/__tests__/has-attribute.ts @@ -269,4 +269,15 @@ describe('assert.dom(...).hasAttribute()', () => { }, ]); }); + + test('supports chaining', () => { + document.body.innerHTML = '

foo

'; + + assert + .dom('h1') + .hasAttribute('class') + .hasAttribute('class', 'bar'); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/has-class.ts b/lib/__tests__/has-class.ts index 6a36e7b71..228492d0b 100644 --- a/lib/__tests__/has-class.ts +++ b/lib/__tests__/has-class.ts @@ -125,4 +125,15 @@ describe('assert.dom(...).hasClass()', () => { 'Unexpected Parameter: [object Document]' ); }); + + test('supports chaining', () => { + document.body.innerHTML = '

foo

'; + + assert + .dom('h1') + .hasClass('foo') + .hasClass('bar'); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/has-no-text.ts b/lib/__tests__/has-no-text.ts index ad88e4558..50ead90d4 100644 --- a/lib/__tests__/has-no-text.ts +++ b/lib/__tests__/has-no-text.ts @@ -75,4 +75,15 @@ describe('assert.dom(...).hasNoText()', () => { 'Unexpected Parameter: [object Document]' ); }); + + test('supports chaining', () => { + document.body.innerHTML = '

foo

'; + + assert + .dom('h1') + .hasNoText() + .hasNoText(); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/has-no-value.ts b/lib/__tests__/has-no-value.ts index 20d60010e..514cb734a 100644 --- a/lib/__tests__/has-no-value.ts +++ b/lib/__tests__/has-no-value.ts @@ -77,4 +77,15 @@ describe('assert.dom(...).hasNoValue()', () => { 'Unexpected Parameter: [object Document]' ); }); + + test('supports chaining', () => { + document.body.innerHTML = ''; + + assert + .dom('input') + .hasNoValue() + .hasNoValue(); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/has-property.ts b/lib/__tests__/has-property.ts index bb4ba79b5..2de9139ec 100644 --- a/lib/__tests__/has-property.ts +++ b/lib/__tests__/has-property.ts @@ -125,4 +125,15 @@ describe('assert.dom(...).hasProperty()', () => { 'Unexpected Parameter: [object Document]' ); }); + + test('supports chaining', () => { + document.body.innerHTML = '

foo

'; + + assert + .dom('h1') + .hasProperty('className', 'foo') + .hasProperty('tagName', 'BAR'); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/has-style.ts b/lib/__tests__/has-style.ts index d068ef9bd..e50affea8 100644 --- a/lib/__tests__/has-style.ts +++ b/lib/__tests__/has-style.ts @@ -112,4 +112,15 @@ describe('assert.dom(...).hasStyle()', () => { 'Missing style expectations. There must be at least one style property in the passed in expectation object.' ); }); + + test('supports chaining', () => { + document.body.innerHTML = '

foo

'; + + assert + .dom('h1') + .hasStyle({ top: 42 }) + .hasStyle({ left: 0 }); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/has-tagname.ts b/lib/__tests__/has-tagname.ts index 64bc9261f..6b4057154 100644 --- a/lib/__tests__/has-tagname.ts +++ b/lib/__tests__/has-tagname.ts @@ -149,4 +149,15 @@ describe('assert.dom(...).hasTagName()', () => { ); }); }); + + test('supports chaining', () => { + document.body.innerHTML = '

foo

'; + + assert + .dom('h1') + .hasTagName('h1') + .hasTagName('foo'); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/has-text.ts b/lib/__tests__/has-text.ts index d9b579df1..a949c99a8 100644 --- a/lib/__tests__/has-text.ts +++ b/lib/__tests__/has-text.ts @@ -149,4 +149,15 @@ describe('assert.dom(...).hasText()', () => { ); }); }); + + test('supports chaining', () => { + document.body.innerHTML = '

foo

'; + + assert + .dom('h1') + .hasText('foo') + .hasText('bar'); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/has-value.ts b/lib/__tests__/has-value.ts index 734440cbc..90e3a1053 100644 --- a/lib/__tests__/has-value.ts +++ b/lib/__tests__/has-value.ts @@ -234,4 +234,15 @@ describe('assert.dom(...).hasValue()', () => { 'Unexpected Parameter: [object Document]' ); }); + + test('supports chaining', () => { + document.body.innerHTML = ''; + + assert + .dom('input') + .hasValue('foo') + .hasValue('bar'); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/includes-text.ts b/lib/__tests__/includes-text.ts index 9a2c0704d..66292b74e 100644 --- a/lib/__tests__/includes-text.ts +++ b/lib/__tests__/includes-text.ts @@ -224,4 +224,15 @@ describe('assert.dom(...).includesText()', () => { 'Unexpected Parameter: [object Document]' ); }); + + test('supports chaining', () => { + document.body.innerHTML = '

foo

'; + + assert + .dom('h1') + .includesText('foo') + .includesText('bar'); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/is-checked.ts b/lib/__tests__/is-checked.ts index be4837bf2..11c693611 100644 --- a/lib/__tests__/is-checked.ts +++ b/lib/__tests__/is-checked.ts @@ -188,4 +188,15 @@ describe('assert.dom(...).isChecked()', () => { 'Unexpected Parameter: [object Document]' ); }); + + test('supports chaining', () => { + document.body.innerHTML = ''; + + assert + .dom('input') + .isChecked() + .isChecked(); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/is-disabled.ts b/lib/__tests__/is-disabled.ts index d6a87d6c6..2c1d55e35 100644 --- a/lib/__tests__/is-disabled.ts +++ b/lib/__tests__/is-disabled.ts @@ -161,4 +161,15 @@ describe('assert.dom(...).isDisabled()', () => { 'Unexpected Element Type: [object HTMLDivElement]' ); }); + + test('supports chaining', () => { + document.body.innerHTML = ''; + + assert + .dom('input') + .isDisabled() + .isDisabled(); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/is-focused.ts b/lib/__tests__/is-focused.ts index 2887f8b3e..524fc4eca 100644 --- a/lib/__tests__/is-focused.ts +++ b/lib/__tests__/is-focused.ts @@ -134,4 +134,15 @@ describe('assert.dom(...).isFocused()', () => { 'Unexpected Parameter: [object Document]' ); }); + + test('supports chaining', () => { + document.body.innerHTML = ''; + + assert + .dom('input') + .isFocused() + .isFocused(); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/is-not-checked.ts b/lib/__tests__/is-not-checked.ts index 359e77b08..b596eb643 100644 --- a/lib/__tests__/is-not-checked.ts +++ b/lib/__tests__/is-not-checked.ts @@ -188,4 +188,15 @@ describe('assert.dom(...).isNotChecked()', () => { 'Unexpected Parameter: [object Document]' ); }); + + test('supports chaining', () => { + document.body.innerHTML = ''; + + assert + .dom('input') + .isNotChecked() + .isNotChecked(); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/is-not-disabled.ts b/lib/__tests__/is-not-disabled.ts index a0181edef..c3ca2a228 100644 --- a/lib/__tests__/is-not-disabled.ts +++ b/lib/__tests__/is-not-disabled.ts @@ -161,4 +161,15 @@ describe('assert.dom(...).isNotDisabled()', () => { 'Unexpected Element Type: [object HTMLDivElement]' ); }); + + test('supports chaining', () => { + document.body.innerHTML = ''; + + assert + .dom('input') + .isNotDisabled() + .isNotDisabled(); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/is-not-focused.ts b/lib/__tests__/is-not-focused.ts index ca9affb83..6c6810f62 100644 --- a/lib/__tests__/is-not-focused.ts +++ b/lib/__tests__/is-not-focused.ts @@ -134,4 +134,15 @@ describe('assert.dom(...).isNotFocused()', () => { 'Unexpected Parameter: [object Document]' ); }); + + test('supports chaining', () => { + document.body.innerHTML = ''; + + assert + .dom('input') + .isNotFocused() + .isNotFocused(); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/is-not-required.ts b/lib/__tests__/is-not-required.ts index 56730a7c9..56a9b97c0 100644 --- a/lib/__tests__/is-not-required.ts +++ b/lib/__tests__/is-not-required.ts @@ -131,4 +131,15 @@ describe('assert.dom(...).isNotRequired()', () => { 'Unexpected Element Type: [object HTMLDivElement]' ); }); + + test('supports chaining', () => { + document.body.innerHTML = ''; + + assert + .dom('input') + .isNotRequired() + .isNotRequired(); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/is-not-visible.ts b/lib/__tests__/is-not-visible.ts index 340555202..b5c628cb8 100644 --- a/lib/__tests__/is-not-visible.ts +++ b/lib/__tests__/is-not-visible.ts @@ -64,4 +64,15 @@ describe('assert.dom(...).isNotVisible()', () => { 'Unexpected Parameter: [object Document]' ); }); + + test('supports chaining', () => { + document.body.innerHTML = ''; + + assert + .dom('input') + .isNotVisible() + .isNotVisible(); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/is-required.ts b/lib/__tests__/is-required.ts index f1d882e2d..75a83f396 100644 --- a/lib/__tests__/is-required.ts +++ b/lib/__tests__/is-required.ts @@ -131,4 +131,15 @@ describe('assert.dom(...).isRequired()', () => { 'Unexpected Element Type: [object HTMLDivElement]' ); }); + + test('supports chaining', () => { + document.body.innerHTML = ''; + + assert + .dom('input') + .isRequired() + .isRequired(); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/is-visible.ts b/lib/__tests__/is-visible.ts index 8898b59bf..c127df118 100644 --- a/lib/__tests__/is-visible.ts +++ b/lib/__tests__/is-visible.ts @@ -113,4 +113,15 @@ describe('assert.dom(...).isVisible()', () => { 'Unexpected Parameter: [object Document]' ); }); + + test('supports chaining', () => { + document.body.innerHTML = ''; + + assert + .dom('input') + .isVisible() + .isVisible(); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/__tests__/matches-selector.ts b/lib/__tests__/matches-selector.ts index 796959e94..561a55e1d 100644 --- a/lib/__tests__/matches-selector.ts +++ b/lib/__tests__/matches-selector.ts @@ -95,4 +95,15 @@ describe('assert.dom(...).matchesSelector()', () => { ]); }); }); + + test('supports chaining', () => { + document.body.innerHTML = ''; + + assert + .dom('input') + .matchesSelector('.foo') + .matchesSelector('.bar'); + + expect(assert.results.length).toEqual(2); + }); }); diff --git a/lib/assertions.ts b/lib/assertions.ts index 4e519cb82..40a5bea69 100644 --- a/lib/assertions.ts +++ b/lib/assertions.ts @@ -44,7 +44,7 @@ export default class DOMAssertions { * * @see {@link #doesNotExist} */ - exists(message?: string): void; + exists(message?: string): DOMAssertions; /** * Assert an {@link HTMLElement} (or multiple) matching the `selector` exists. @@ -58,7 +58,7 @@ export default class DOMAssertions { * * @see {@link #doesNotExist} */ - exists(options: ExistsOptions, message?: string): void; + exists(options: ExistsOptions, message?: string): DOMAssertions; /** * Assert an {@link HTMLElement} (or multiple) matching the `selector` exists. @@ -73,8 +73,9 @@ export default class DOMAssertions { * * @see {@link #doesNotExist} */ - exists(options: ExistsOptions | string, message?: string): void { + exists(options: ExistsOptions | string, message?: string): DOMAssertions { exists.call(this, options, message); + return this; } /** @@ -87,8 +88,9 @@ export default class DOMAssertions { * * @see {@link #exists} */ - doesNotExist(message?: string): void { + doesNotExist(message?: string): DOMAssertions { exists.call(this, { count: 0 }, message); + return this; } /** @@ -104,8 +106,9 @@ export default class DOMAssertions { * * @see {@link #isNotChecked} */ - isChecked(message?: string): void { + isChecked(message?: string): DOMAssertions { isChecked.call(this, message); + return this; } /** @@ -121,8 +124,9 @@ export default class DOMAssertions { * * @see {@link #isChecked} */ - isNotChecked(message?: string): void { + isNotChecked(message?: string): DOMAssertions { isNotChecked.call(this, message); + return this; } /** @@ -136,8 +140,9 @@ export default class DOMAssertions { * * @see {@link #isNotFocused} */ - isFocused(message?: string): void { + isFocused(message?: string): DOMAssertions { focused.call(this, message); + return this; } /** @@ -151,8 +156,9 @@ export default class DOMAssertions { * * @see {@link #isFocused} */ - isNotFocused(message?: string): void { + isNotFocused(message?: string): DOMAssertions { notFocused.call(this, message); + return this; } /** @@ -166,8 +172,9 @@ export default class DOMAssertions { * * @see {@link #isNotRequired} */ - isRequired(message?: string): void { + isRequired(message?: string): DOMAssertions { isRequired.call(this, message); + return this; } /** @@ -181,8 +188,9 @@ export default class DOMAssertions { * * @see {@link #isRequired} */ - isNotRequired(message?: string): void { + isNotRequired(message?: string): DOMAssertions { isNotRequired.call(this, message); + return this; } /** @@ -204,7 +212,7 @@ export default class DOMAssertions { * * @see {@link #isNotVisible} */ - isVisible(message?: string): void; + isVisible(message?: string): DOMAssertions; /** * Assert that the {@link HTMLElement} or an {@link HTMLElement} matching the @@ -227,7 +235,7 @@ export default class DOMAssertions { * * @see {@link #isNotVisible} */ - isVisible(options: ExistsOptions, message?: string): void; + isVisible(options: ExistsOptions, message?: string): DOMAssertions; /** * Assert that the {@link HTMLElement} or an {@link HTMLElement} matching the @@ -251,8 +259,9 @@ export default class DOMAssertions { * * @see {@link #isNotVisible} */ - isVisible(options: ExistsOptions | string, message?: string): void { + isVisible(options: ExistsOptions | string, message?: string): DOMAssertions { isVisible.call(this, options, message); + return this; } /** @@ -274,8 +283,9 @@ export default class DOMAssertions { * * @see {@link #isVisible} */ - isNotVisible(message?: string): void { + isNotVisible(message?: string): DOMAssertions { isVisible.call(this, { count: 0 }, message); + return this; } /** @@ -288,7 +298,7 @@ export default class DOMAssertions { * * @see {@link #doesNotHaveAttribute} */ - hasAttribute(name: string): void; + hasAttribute(name: string): DOMAssertions; /** * Assert that the {@link HTMLElement} has an attribute with the provided `name` @@ -304,7 +314,11 @@ export default class DOMAssertions { * * @see {@link #doesNotHaveAttribute} */ - hasAttribute(name: string, value: string | RegExp | { any: true }, message?: string): void; + hasAttribute( + name: string, + value: string | RegExp | { any: true }, + message?: string + ): DOMAssertions; /** * Assert that the {@link HTMLElement} has an attribute with the provided `name` @@ -320,9 +334,13 @@ export default class DOMAssertions { * * @see {@link #doesNotHaveAttribute} */ - hasAttribute(name: string, value?: string | RegExp | { any: true }, message?: string): void { + hasAttribute( + name: string, + value?: string | RegExp | { any: true }, + message?: string + ): DOMAssertions { let element = this.findTargetElement(); - if (!element) return; + if (!element) return this; if (arguments.length === 1) { value = { any: true }; @@ -375,6 +393,8 @@ export default class DOMAssertions { this.pushResult({ result, actual, expected, message }); } + + return this; } /** @@ -390,7 +410,7 @@ export default class DOMAssertions { * * @see {@link #hasAttribute} */ - doesNotHaveAttribute(name: string, message?: string): void { + doesNotHaveAttribute(name: string, message?: string): DOMAssertions { let element = this.findTargetElement(); if (!element) return; @@ -410,14 +430,15 @@ export default class DOMAssertions { } this.pushResult({ result, actual, expected, message }); + return this; } - hasNoAttribute(name: string, message?: string): void { - this.doesNotHaveAttribute(name, message); + hasNoAttribute(name: string, message?: string): DOMAssertions { + return this.doesNotHaveAttribute(name, message); } - lacksAttribute(name: string, message?: string): void { - this.doesNotHaveAttribute(name, message); + lacksAttribute(name: string, message?: string): DOMAssertions { + return this.doesNotHaveAttribute(name, message); } /** @@ -434,9 +455,9 @@ export default class DOMAssertions { * * @see {@link #doesNotHaveProperty} */ - hasProperty(name: string, value: string | RegExp, message?: string): void { + hasProperty(name: string, value: string | RegExp, message?: string): DOMAssertions { let element = this.findTargetElement(); - if (!element) return; + if (!element) return this; let description = this.targetDescription; @@ -469,6 +490,8 @@ export default class DOMAssertions { this.pushResult({ result, actual, expected, message }); } + + return this; } /** @@ -482,8 +505,9 @@ export default class DOMAssertions { * * @see {@link #isNotDisabled} */ - isDisabled(message?: string): void { + isDisabled(message?: string): DOMAssertions { isDisabled.call(this, message); + return this; } /** @@ -497,8 +521,9 @@ export default class DOMAssertions { * * @see {@link #isDisabled} */ - isNotDisabled(message?: string): void { + isNotDisabled(message?: string): DOMAssertions { isDisabled.call(this, message, { inverted: true }); + return this; } /** @@ -519,9 +544,9 @@ export default class DOMAssertions { * * @see {@link #doesNotHaveClass} */ - hasClass(expected: string | RegExp, message?: string): void { + hasClass(expected: string | RegExp, message?: string): DOMAssertions { let element = this.findTargetElement(); - if (!element) return; + if (!element) return this; let actual = element.classList.toString(); @@ -545,6 +570,8 @@ export default class DOMAssertions { this.pushResult({ result, actual, expected, message }); } + + return this; } /** @@ -567,9 +594,9 @@ export default class DOMAssertions { * * @see {@link #hasClass} */ - doesNotHaveClass(expected: string | RegExp, message?: string): void { + doesNotHaveClass(expected: string | RegExp, message?: string): DOMAssertions { let element = this.findTargetElement(); - if (!element) return; + if (!element) return this; let actual = element.classList.toString(); @@ -593,14 +620,16 @@ export default class DOMAssertions { this.pushResult({ result, actual, expected: `not: ${expected}`, message }); } + + return this; } - hasNoClass(expected: string | RegExp, message?: string): void { - this.doesNotHaveClass(expected, message); + hasNoClass(expected: string | RegExp, message?: string): DOMAssertions { + return this.doesNotHaveClass(expected, message); } - lacksClass(expected: string | RegExp, message?: string): void { - this.doesNotHaveClass(expected, message); + lacksClass(expected: string | RegExp, message?: string): DOMAssertions { + return this.doesNotHaveClass(expected, message); } /** @@ -619,11 +648,11 @@ export default class DOMAssertions { * * @see {@link #hasClass} */ - hasStyle(expected: object, message?: string): void { - this.hasPseudoElementStyle(null, expected, message); + hasStyle(expected: object, message?: string): DOMAssertions { + return this.hasPseudoElementStyle(null, expected, message); } - hasPseudoElementStyle(selector: string, expected: object, message?: string): void; + hasPseudoElementStyle(selector: string, expected: object, message?: string): DOMAssertions; /** * Assert that the pseudo element for `selector` of the [HTMLElement][] has the `expected` style declarations using @@ -645,9 +674,9 @@ export default class DOMAssertions { selector: string | null, expected: Dictionary, message?: string - ): void { + ): DOMAssertions { let element = this.findTargetElement(); - if (!element) return; + if (!element) return this; let computedStyle = window.getComputedStyle(element, selector); let expectedProperties = Object.keys(expected) as [keyof CSSStyleDeclaration]; @@ -672,6 +701,7 @@ export default class DOMAssertions { } this.pushResult({ result, actual, expected, message }); + return this; } /** @@ -690,11 +720,11 @@ export default class DOMAssertions { * * @see {@link #hasClass} */ - doesNotHaveStyle(expected: object, message?: string): void { - this.doesNotHavePseudoElementStyle(null, expected, message); + doesNotHaveStyle(expected: object, message?: string): DOMAssertions { + return this.doesNotHavePseudoElementStyle(null, expected, message); } - doesNotHavePseudoElementStyle(selector: string, expected: object, message: string): void; + doesNotHavePseudoElementStyle(selector: string, expected: object, message: string): DOMAssertions; /** * Assert that the pseudo element for `selector` of the [HTMLElement][] does not have the `expected` style declarations using @@ -716,9 +746,9 @@ export default class DOMAssertions { selector: string | null, expected: Dictionary, message: string - ): void { + ): DOMAssertions { let element = this.findTargetElement(); - if (!element) return; + if (!element) return this; let computedStyle = window.getComputedStyle(element, selector); @@ -744,6 +774,7 @@ export default class DOMAssertions { } this.pushResult({ result, actual, expected, message }); + return this; } /** @@ -775,9 +806,9 @@ export default class DOMAssertions { * * @see {@link #includesText} */ - hasText(expected: string | RegExp | { any: true }, message?: string): void { + hasText(expected: string | RegExp | { any: true }, message?: string): DOMAssertions { let element = this.findTargetElement(); - if (!element) return; + if (!element) return this; if (expected instanceof RegExp) { let result = expected.test(element.textContent); @@ -814,10 +845,12 @@ export default class DOMAssertions { `You must pass a string or Regular Expression to "hasText". You passed ${expected}.` ); } + + return this; } - matchesText(expected: string | RegExp | { any: true }, message?: string): void { - this.hasText(expected, message); + matchesText(expected: string | RegExp | { any: true }, message?: string): DOMAssertions { + return this.hasText(expected, message); } /** @@ -830,8 +863,8 @@ export default class DOMAssertions { * * @see {@link #hasText} */ - hasAnyText(message?: string): void { - this.hasText({ any: true }, message); + hasAnyText(message?: string): DOMAssertions { + return this.hasText({ any: true }, message); } /** @@ -844,8 +877,8 @@ export default class DOMAssertions { * * @see {@link #hasNoText} */ - hasNoText(message?: string): void { - this.hasText('', message); + hasNoText(message?: string): DOMAssertions { + return this.hasText('', message); } /** @@ -869,9 +902,9 @@ export default class DOMAssertions { * * @see {@link #hasText} */ - includesText(text: string, message?: string): void { + includesText(text: string, message?: string): DOMAssertions { let element = this.findTargetElement(); - if (!element) return; + if (!element) return this; let collapsedText = collapseWhitespace(element.textContent); let result = collapsedText.indexOf(text) !== -1; @@ -890,14 +923,15 @@ export default class DOMAssertions { } this.pushResult({ result, actual, expected, message }); + return this; } - containsText(expected: string, message?: string): void { - this.includesText(expected, message); + containsText(expected: string, message?: string): DOMAssertions { + return this.includesText(expected, message); } - hasTextContaining(expected: string, message?: string): void { - this.includesText(expected, message); + hasTextContaining(expected: string, message?: string): DOMAssertions { + return this.includesText(expected, message); } /** @@ -914,9 +948,9 @@ export default class DOMAssertions { * @example * assert.dom('#title').doesNotIncludeText('Welcome'); */ - doesNotIncludeText(text: string, message?: string): void { + doesNotIncludeText(text: string, message?: string): DOMAssertions { let element = this.findTargetElement(); - if (!element) return; + if (!element) return this; let collapsedText = collapseWhitespace(element.textContent); let result = collapsedText.indexOf(text) === -1; @@ -932,14 +966,15 @@ export default class DOMAssertions { } this.pushResult({ result, actual, expected, message }); + return this; } - doesNotContainText(unexpected: string, message?: string): void { - this.doesNotIncludeText(unexpected, message); + doesNotContainText(unexpected: string, message?: string): DOMAssertions { + return this.doesNotIncludeText(unexpected, message); } - doesNotHaveTextContaining(unexpected: string, message?: string): void { - this.doesNotIncludeText(unexpected, message); + doesNotHaveTextContaining(unexpected: string, message?: string): DOMAssertions { + return this.doesNotIncludeText(unexpected, message); } /** @@ -958,9 +993,9 @@ export default class DOMAssertions { * @see {@link #hasAnyValue} * @see {@link #hasNoValue} */ - hasValue(expected?: string | RegExp | { any: true }, message?: string): void { + hasValue(expected?: string | RegExp | { any: true }, message?: string): DOMAssertions { let element = this.findTargetElement(); - if (!element) return; + if (!element) return this; if (arguments.length === 0) { expected = { any: true }; @@ -998,6 +1033,8 @@ export default class DOMAssertions { this.pushResult({ result, actual, expected, message }); } + + return this; } /** @@ -1011,8 +1048,8 @@ export default class DOMAssertions { * @see {@link #hasValue} * @see {@link #hasNoValue} */ - hasAnyValue(message?: string): void { - this.hasValue({ any: true }, message); + hasAnyValue(message?: string): DOMAssertions { + return this.hasValue({ any: true }, message); } /** @@ -1028,12 +1065,12 @@ export default class DOMAssertions { * @see {@link #hasValue} * @see {@link #hasAnyValue} */ - hasNoValue(message?: string): void { - this.hasValue('', message); + hasNoValue(message?: string): DOMAssertions { + return this.hasValue('', message); } - lacksValue(message?: string): void { - this.hasNoValue(message); + lacksValue(message?: string): DOMAssertions { + return this.hasNoValue(message); } /** @@ -1046,7 +1083,7 @@ export default class DOMAssertions { * @example * assert.dom('p.red').matchesSelector('div.wrapper p:last-child') */ - matchesSelector(compareSelector: string, message?: string): void { + matchesSelector(compareSelector: string, message?: string): DOMAssertions { let targetElements = this.target instanceof Element ? [this.target] : this.findElements(); let targets = targetElements.length; let matchFailures = matchesSelector(targetElements, compareSelector); @@ -1078,6 +1115,8 @@ export default class DOMAssertions { : `${targets} elements should have matched ${compareSelector}.`; this.pushResult({ result: false, actual, expected, message }); } + + return this; } /** @@ -1090,7 +1129,7 @@ export default class DOMAssertions { * @example * assert.dom('input').doesNotMatchSelector('input[disabled]') */ - doesNotMatchSelector(compareSelector: string, message?: string): void { + doesNotMatchSelector(compareSelector: string, message?: string): DOMAssertions { let targetElements = this.target instanceof Element ? [this.target] : this.findElements(); let targets = targetElements.length; let matchFailures = matchesSelector(targetElements, compareSelector); @@ -1123,6 +1162,8 @@ export default class DOMAssertions { : `${targets} elements should not have matched ${compareSelector}.`; this.pushResult({ result: false, actual, expected, message }); } + + return this; } /** @@ -1141,12 +1182,12 @@ export default class DOMAssertions { * * assert.dom('#title').hasTagName('h1'); */ - hasTagName(tagName: string, message?: string): void { + hasTagName(tagName: string, message?: string): DOMAssertions { let element = this.findTargetElement(); let actual; let expected; - if (!element) return; + if (!element) return this; if (typeof tagName !== 'string') { throw new TypeError(`You must pass a string to "hasTagName". You passed ${tagName}.`); @@ -1168,6 +1209,8 @@ export default class DOMAssertions { this.pushResult({ result: false, actual, expected, message }); } + + return this; } /** @@ -1186,12 +1229,12 @@ export default class DOMAssertions { * * assert.dom('section#block').doesNotHaveTagName('div'); */ - doesNotHaveTagName(tagName: string, message?: string): void { + doesNotHaveTagName(tagName: string, message?: string): DOMAssertions { let element = this.findTargetElement(); let actual; let expected; - if (!element) return; + if (!element) return this; if (typeof tagName !== 'string') { throw new TypeError(`You must pass a string to "doesNotHaveTagName". You passed ${tagName}.`); @@ -1213,6 +1256,8 @@ export default class DOMAssertions { this.pushResult({ result: false, actual, expected, message }); } + + return this; } /**