From d393feffc5e29f1df9a0a0946784e1488fd54b8d Mon Sep 17 00:00:00 2001 From: Ben Demboski Date: Sat, 28 Nov 2020 22:50:58 -0800 Subject: [PATCH] feature: support IDOMElementDescriptors Extend qunit.dom() to accept IDOMElementDescriptors. See https://github.com/emberjs/rfcs/pull/726. --- .../qunit-dom/lib/__tests__/descriptor.ts | 119 ++++++++++++++++++ packages/qunit-dom/lib/assertions.ts | 95 +++++++------- packages/qunit-dom/lib/assertions/exists.ts | 4 + packages/qunit-dom/lib/assertions/focused.ts | 2 +- .../qunit-dom/lib/assertions/is-checked.ts | 4 +- .../lib/assertions/is-not-checked.ts | 4 +- .../lib/assertions/is-not-required.ts | 4 +- .../qunit-dom/lib/assertions/is-required.ts | 4 +- packages/qunit-dom/lib/assertions/is-valid.ts | 4 +- .../qunit-dom/lib/assertions/is-visible.ts | 4 + packages/qunit-dom/lib/descriptor.ts | 69 ++++++++++ .../qunit-dom/lib/helpers/test-assertions.ts | 3 +- packages/qunit-dom/lib/install.ts | 8 +- packages/qunit-dom/package.json | 3 + packages/qunit-dom/rollup.config.mjs | 7 +- packages/qunit-dom/tsconfig.json | 5 +- .../test-types-resolution-node/package.json | 1 + packages/test-types-resolution-node/test.ts | 3 +- .../test-types-resolution-node16/package.json | 1 + packages/test-types-resolution-node16/test.ts | 3 +- packages/test-types/package.json | 1 + packages/test-types/test.ts | 3 +- pnpm-lock.yaml | 16 +++ 23 files changed, 293 insertions(+), 74 deletions(-) create mode 100644 packages/qunit-dom/lib/__tests__/descriptor.ts create mode 100644 packages/qunit-dom/lib/descriptor.ts diff --git a/packages/qunit-dom/lib/__tests__/descriptor.ts b/packages/qunit-dom/lib/__tests__/descriptor.ts new file mode 100644 index 000000000..cf5803314 --- /dev/null +++ b/packages/qunit-dom/lib/__tests__/descriptor.ts @@ -0,0 +1,119 @@ +import { describe, beforeEach, test, expect } from 'vitest'; + +import createDescriptor from '../descriptor'; +import TestAssertions from '../helpers/test-assertions'; +import { + resolveDOMElement, + resolveDOMElements, + resolveDescription, + createDescriptor as createDescriptorBase, +} from 'dom-element-descriptors'; + +describe('createQuery()', () => { + beforeEach(() => { + document.body.innerHTML = + '
'; + }); + + test('it works with a selector', () => { + let expected = Array.from(document.querySelectorAll('.multiple')); + let descriptor = createDescriptor('.multiple', document); + + expect(resolveDOMElement(descriptor)).toEqual(expected[0]); + expect(resolveDOMElements(descriptor)).toEqual(expected); + expect(resolveDescription(descriptor)).toEqual('.multiple'); + }); + + test('selector respects the root element', () => { + document.body.innerHTML = + '
'; + let root = document.querySelector('.root'); + let [outOfRoot, inRoot] = Array.from(document.querySelectorAll('.multiple')); + + expect(resolveDOMElement(createDescriptor('.multiple', document))).toEqual(outOfRoot); + expect(resolveDOMElements(createDescriptor('.multiple', document))).toEqual([ + outOfRoot, + inRoot, + ]); + + expect(resolveDOMElement(createDescriptor('.multiple', root))).toEqual(inRoot); + expect(resolveDOMElements(createDescriptor('.multiple', root))).toEqual([inRoot]); + }); + + test('it works with an element', () => { + let expected = document.querySelector('.multiple'); + let descriptor = createDescriptor(expected, document); + + expect(resolveDOMElement(descriptor)).toEqual(expected); + expect(resolveDOMElements(descriptor)).toEqual([expected]); + expect(resolveDescription(descriptor)).toEqual('div.multiple'); + }); + + test('it works with null', () => { + let descriptor = createDescriptor(null, document); + + expect(resolveDOMElement(descriptor)).toEqual(null); + expect(resolveDOMElements(descriptor)).toEqual([]); + expect(resolveDescription(descriptor)).toEqual(''); + }); + + test('it works with a dom element descriptor', () => { + let expected = Array.from(document.querySelectorAll('.multiple')); + let descriptor = createDescriptor( + createDescriptorBase({ elements: expected, description: 'descriptoriffic' }), + document + ); + + expect(resolveDOMElement(descriptor)).toEqual(expected[0]); + expect(resolveDOMElements(descriptor)).toEqual(expected); + expect(resolveDescription(descriptor)).toEqual('descriptoriffic'); + }); + + test('it works via assert.dom()', () => { + let assert = new TestAssertions(); + + assert + .dom(createDescriptorBase({ elements: Array.from(document.querySelectorAll('.single')) })) + .exists({ count: 1 }); + assert + .dom(createDescriptorBase({ elements: Array.from(document.querySelectorAll('.multiple')) })) + .exists({ count: 2 }); + assert + .dom(createDescriptorBase({ elements: Array.from(document.querySelectorAll('.single')) })) + .hasTagName('div'); + + expect(assert.results).toEqual([ + { + actual: 'Element undefined exists once', + expected: 'Element undefined exists once', + message: 'Element undefined exists once', + result: true, + }, + { + actual: 'Element undefined exists twice', + expected: 'Element undefined exists twice', + message: 'Element undefined exists twice', + result: true, + }, + { + actual: 'div', + expected: 'div', + message: 'Element undefined has tagName div', + result: true, + }, + ]); + }); + + test('throws for unexpected parameter types', () => { + expect(() => createDescriptor(5, document)).toThrow('Unexpected Parameter: 5'); + expect(() => createDescriptor(true, document)).toThrow('Unexpected Parameter: true'); + expect(() => createDescriptor(undefined, document)).toThrow('Unexpected Parameter: undefined'); + expect(() => createDescriptor({}, document)).toThrow('Unexpected Parameter: [object Object]'); + expect(() => createDescriptor({ element: document.createElement('div') }, document)).toThrow( + 'Unexpected Parameter: [object Object]' + ); + expect(() => createDescriptor(document, document)).toThrow( + 'Unexpected Parameter: [object Document]' + ); + }); +}); diff --git a/packages/qunit-dom/lib/assertions.ts b/packages/qunit-dom/lib/assertions.ts index c117fe0d7..b6d83458e 100644 --- a/packages/qunit-dom/lib/assertions.ts +++ b/packages/qunit-dom/lib/assertions.ts @@ -9,9 +9,14 @@ import isValid from './assertions/is-valid.js'; import isVisible from './assertions/is-visible.js'; import isDisabled from './assertions/is-disabled.js'; import matchesSelector from './assertions/matches-selector.js'; -import elementToString from './helpers/element-to-string.js'; import collapseWhitespace from './helpers/collapse-whitespace.js'; -import { toArray } from './helpers/node-list.js'; +import { + type IDOMElementDescriptor, + resolveDOMElement, + resolveDOMElements, + resolveDescription, +} from 'dom-element-descriptors'; +import createDescriptor from './descriptor'; export interface AssertionResult { result: boolean; @@ -29,11 +34,24 @@ type CSSStyleDeclarationProperty = keyof CSSStyleDeclaration; type ActualCSSStyleDeclaration = Partial>; export default class DOMAssertions { + /** + * The target of our assertions + */ + private descriptor: IDOMElementDescriptor; + /** + * Whether we were constructed with an element, rather than a selector or + * descriptor. Used to make error messages more helpful. + */ + private wasPassedElement: boolean; + constructor( - private target: string | Element | null, - private rootElement: RootElement, + target: string | Element | null | IDOMElementDescriptor, + rootElement: RootElement, private testContext: Assert - ) {} + ) { + this.descriptor = createDescriptor(target, rootElement); + this.wasPassedElement = target instanceof Element; + } /** * Assert an {@link HTMLElement} (or multiple) matching the `selector` exists. @@ -1217,11 +1235,11 @@ export default class DOMAssertions { * assert.dom('p.red').matchesSelector('div.wrapper p:last-child') */ matchesSelector(compareSelector: string, message?: string): DOMAssertions { - let targetElements = this.target instanceof Element ? [this.target] : this.findElements(); + let targetElements = this.findElements(); let targets = targetElements.length; let matchFailures = matchesSelector(targetElements, compareSelector); let singleElement: boolean = targets === 1; - let selectedByPart = this.target instanceof Element ? 'passed' : `selected by ${this.target}`; + let selectedByPart = this.selectedBy; let actual; let expected; @@ -1230,7 +1248,7 @@ export default class DOMAssertions { if (!message) { message = singleElement ? `The element ${selectedByPart} also matches the selector ${compareSelector}.` - : `${targets} elements, selected by ${this.target}, also match the selector ${compareSelector}.`; + : `${targets} elements, ${selectedByPart}, also match the selector ${compareSelector}.`; } actual = expected = message; this.pushResult({ result: true, actual, expected, message }); @@ -1240,7 +1258,7 @@ export default class DOMAssertions { if (!message) { message = singleElement ? `The element ${selectedByPart} did not also match the selector ${compareSelector}.` - : `${matchFailures} out of ${targets} elements selected by ${this.target} did not also match the selector ${compareSelector}.`; + : `${matchFailures} out of ${targets} elements ${selectedByPart} did not also match the selector ${compareSelector}.`; } actual = singleElement ? message : `${difference} elements matched ${compareSelector}.`; expected = singleElement @@ -1263,11 +1281,11 @@ export default class DOMAssertions { * assert.dom('input').doesNotMatchSelector('input[disabled]') */ doesNotMatchSelector(compareSelector: string, message?: string): DOMAssertions { - let targetElements = this.target instanceof Element ? [this.target] : this.findElements(); + let targetElements = this.findElements(); let targets = targetElements.length; let matchFailures = matchesSelector(targetElements, compareSelector); let singleElement: boolean = targets === 1; - let selectedByPart = this.target instanceof Element ? 'passed' : `selected by ${this.target}`; + let selectedByPart = this.selectedBy; let actual; let expected; if (matchFailures === targets) { @@ -1275,7 +1293,7 @@ export default class DOMAssertions { if (!message) { message = singleElement ? `The element ${selectedByPart} did not also match the selector ${compareSelector}.` - : `${targets} elements, selected by ${this.target}, did not also match the selector ${compareSelector}.`; + : `${targets} elements, ${selectedByPart}, did not also match the selector ${compareSelector}.`; } actual = expected = message; this.pushResult({ result: true, actual, expected, message }); @@ -1285,7 +1303,7 @@ export default class DOMAssertions { if (!message) { message = singleElement ? `The element ${selectedByPart} must not also match the selector ${compareSelector}.` - : `${difference} elements out of ${targets}, selected by ${this.target}, must not also match the selector ${compareSelector}.`; + : `${difference} elements out of ${targets}, ${selectedByPart}, must not also match the selector ${compareSelector}.`; } actual = singleElement ? `The element ${selectedByPart} matched ${compareSelector}.` @@ -1407,10 +1425,10 @@ export default class DOMAssertions { * @returns (HTMLElement|null) a valid HTMLElement, or null */ private findTargetElement(): Element | null { - let el = this.findElement(); + let el = resolveDOMElement(this.descriptor); if (el === null) { - let message = `Element ${this.target || ''} should exist`; + let message = `Element ${this.targetDescription} should exist`; this.pushResult({ message, result: false, actual: undefined, expected: undefined }); return null; } @@ -1419,51 +1437,32 @@ export default class DOMAssertions { } /** - * Finds a valid HTMLElement from target + * Finds a collection of Element instances from target using querySelectorAll * @private - * @returns (HTMLElement|null) a valid HTMLElement, or null + * @returns (Element[]) an array of Element instances * @throws TypeError will be thrown if target is an unrecognized type */ - private findElement(): Element | null { - if (this.target === null) { - return null; - } else if (typeof this.target === 'string') { - if (!this.rootElement) { - throw new Error('Cannot do selector-based queries without a root element'); - } - return this.rootElement.querySelector(this.target); - } else if (this.target instanceof Element) { - return this.target; - } else { - throw new TypeError(`Unexpected Parameter: ${this.target}`); - } + private findElements(): Element[] { + return Array.from(resolveDOMElements(this.descriptor)); } /** - * Finds a collection of Element instances from target using querySelectorAll * @private - * @returns (Element[]) an array of Element instances - * @throws TypeError will be thrown if target is an unrecognized type */ - private findElements(): Element[] { - if (this.target === null) { - return []; - } else if (typeof this.target === 'string') { - if (!this.rootElement) { - throw new Error('Cannot do selector-based queries without a root element'); - } - return toArray(this.rootElement.querySelectorAll(this.target)); - } else if (this.target instanceof Element) { - return [this.target]; - } else { - throw new TypeError(`Unexpected Parameter: ${this.target}`); - } + private get targetDescription(): string { + return resolveDescription(this.descriptor) ?? 'undefined'; } /** * @private */ - private get targetDescription(): string { - return elementToString(this.target); + private get selectedBy(): string { + if (this.wasPassedElement) { + return 'passed'; + } else if (resolveDOMElement(this.descriptor)) { + return `selected by ${this.targetDescription}`; + } else { + return 'selected by null'; + } } } diff --git a/packages/qunit-dom/lib/assertions/exists.ts b/packages/qunit-dom/lib/assertions/exists.ts index 26f85d68b..b1ea43057 100644 --- a/packages/qunit-dom/lib/assertions/exists.ts +++ b/packages/qunit-dom/lib/assertions/exists.ts @@ -37,6 +37,10 @@ export default function exists(options?: ExistsOptions | string, message?: strin } function format(selector: string, num?: number) { + if (selector === '') { + selector = ''; + } + if (num === undefined || num === null) { return `Element ${selector} exists`; } else if (num === 0) { diff --git a/packages/qunit-dom/lib/assertions/focused.ts b/packages/qunit-dom/lib/assertions/focused.ts index 3cbb459ec..cca6e97b5 100644 --- a/packages/qunit-dom/lib/assertions/focused.ts +++ b/packages/qunit-dom/lib/assertions/focused.ts @@ -6,7 +6,7 @@ export default function focused(message?: string) { let result = document.activeElement === element; let actual = elementToString(document.activeElement); - let expected = elementToString(this.target); + let expected = this.targetDescription; if (!message) { message = `Element ${expected} is focused`; diff --git a/packages/qunit-dom/lib/assertions/is-checked.ts b/packages/qunit-dom/lib/assertions/is-checked.ts index d90ee62fc..363cac5fe 100644 --- a/packages/qunit-dom/lib/assertions/is-checked.ts +++ b/packages/qunit-dom/lib/assertions/is-checked.ts @@ -1,5 +1,3 @@ -import elementToString from '../helpers/element-to-string.js'; - export default function checked(message?: string) { let element = this.findTargetElement(); if (!element) return; @@ -21,7 +19,7 @@ export default function checked(message?: string) { let expected = 'checked'; if (!message) { - message = `Element ${elementToString(this.target)} is checked`; + message = `Element ${this.targetDescription} is checked`; } this.pushResult({ result, actual, expected, message }); diff --git a/packages/qunit-dom/lib/assertions/is-not-checked.ts b/packages/qunit-dom/lib/assertions/is-not-checked.ts index 60e81597e..471239858 100644 --- a/packages/qunit-dom/lib/assertions/is-not-checked.ts +++ b/packages/qunit-dom/lib/assertions/is-not-checked.ts @@ -1,5 +1,3 @@ -import elementToString from '../helpers/element-to-string.js'; - export default function notChecked(message?: string) { let element = this.findTargetElement(); if (!element) return; @@ -21,7 +19,7 @@ export default function notChecked(message?: string) { let expected = 'not checked'; if (!message) { - message = `Element ${elementToString(this.target)} is not checked`; + message = `Element ${this.targetDescription} is not checked`; } this.pushResult({ result, actual, expected, message }); diff --git a/packages/qunit-dom/lib/assertions/is-not-required.ts b/packages/qunit-dom/lib/assertions/is-not-required.ts index 555b39975..0f8ca4e04 100644 --- a/packages/qunit-dom/lib/assertions/is-not-required.ts +++ b/packages/qunit-dom/lib/assertions/is-not-required.ts @@ -1,5 +1,3 @@ -import elementToString from '../helpers/element-to-string.js'; - export default function notRequired(message?: string) { let element = this.findTargetElement(); if (!element) return; @@ -19,7 +17,7 @@ export default function notRequired(message?: string) { let expected = 'not required'; if (!message) { - message = `Element ${elementToString(this.target)} is not required`; + message = `Element ${this.targetDescription} is not required`; } this.pushResult({ result, actual, expected, message }); diff --git a/packages/qunit-dom/lib/assertions/is-required.ts b/packages/qunit-dom/lib/assertions/is-required.ts index ba49569f6..198d84efd 100644 --- a/packages/qunit-dom/lib/assertions/is-required.ts +++ b/packages/qunit-dom/lib/assertions/is-required.ts @@ -1,5 +1,3 @@ -import elementToString from '../helpers/element-to-string.js'; - export default function required(message?: string) { let element = this.findTargetElement(); if (!element) return; @@ -19,7 +17,7 @@ export default function required(message?: string) { let expected = 'required'; if (!message) { - message = `Element ${elementToString(this.target)} is required`; + message = `Element ${this.targetDescription} is required`; } this.pushResult({ result, actual, expected, message }); diff --git a/packages/qunit-dom/lib/assertions/is-valid.ts b/packages/qunit-dom/lib/assertions/is-valid.ts index a4740da0c..25b69bce4 100644 --- a/packages/qunit-dom/lib/assertions/is-valid.ts +++ b/packages/qunit-dom/lib/assertions/is-valid.ts @@ -1,5 +1,3 @@ -import elementToString from '../helpers/element-to-string.js'; - export default function isValid(message?: string, options: { inverted?: boolean } = {}) { let element = this.findTargetElement(); if (!element) return; @@ -23,7 +21,7 @@ export default function isValid(message?: string, options: { inverted?: boolean let expected = options.inverted ? 'not valid' : 'valid'; if (!message) { - message = `Element ${elementToString(this.target)} is ${actual}`; + message = `Element ${this.targetDescription} is ${actual}`; } this.pushResult({ result, actual, expected, message }); diff --git a/packages/qunit-dom/lib/assertions/is-visible.ts b/packages/qunit-dom/lib/assertions/is-visible.ts index 74cab96b8..5c681c847 100644 --- a/packages/qunit-dom/lib/assertions/is-visible.ts +++ b/packages/qunit-dom/lib/assertions/is-visible.ts @@ -38,6 +38,10 @@ export default function isVisible(options?: string | ExistsOptions, message?: st } function format(selector: string, num?: number) { + if (selector === '') { + selector = ''; + } + if (num === undefined || num === null) { return `Element ${selector} is visible`; } else if (num === 0) { diff --git a/packages/qunit-dom/lib/descriptor.ts b/packages/qunit-dom/lib/descriptor.ts new file mode 100644 index 000000000..8b898179a --- /dev/null +++ b/packages/qunit-dom/lib/descriptor.ts @@ -0,0 +1,69 @@ +import { + type IDOMElementDescriptor, + isDescriptor, + createDescriptor as create, +} from 'dom-element-descriptors'; +import elementToString from './helpers/element-to-string'; + +/** + * Descriptor data for creating an {@link IDOMElementDescriptor} from a CSS + * selector + */ +class SelectorData { + constructor( + private readonly selector: string, + private readonly rootElement: NonNullable + ) {} + + get element() { + return this.rootElement.querySelector(this.selector); + } + + get elements() { + return Array.from(this.rootElement.querySelectorAll(this.selector)); + } + + get description() { + return this.selector; + } +} + +/** + * Descriptor data for creating an {@link IDOMElementDescriptor} from an + * {@link Element} + */ +class ElementData { + constructor(public readonly element: Element) {} + + get description() { + return elementToString(this.element); + } +} + +/** + * Create an {@link IDOMElementDescriptor} from a target and a root element + */ +export default function createDescriptor( + target: string | Element | null | IDOMElementDescriptor, + rootElement: RootElement +): IDOMElementDescriptor { + if (typeof target === 'string') { + // selector + if (!rootElement) { + throw new Error('Cannot do selector-based queries without a root element'); + } + return create(new SelectorData(target, rootElement)); + } else if (target instanceof Element) { + // element + return create(new ElementData(target)); + } else if (target === null) { + // null, which we treat as an unmatched element, e.g. + // `createDescriptor(document.querySelector('.does-not-exist'))` + return create({ element: null, description: '' }); + } else if (isDescriptor(target)) { + // already a descriptor + return target; + } else { + throw new TypeError(`Unexpected Parameter: ${target}`); + } +} diff --git a/packages/qunit-dom/lib/helpers/test-assertions.ts b/packages/qunit-dom/lib/helpers/test-assertions.ts index 06214ab35..baa432cf4 100644 --- a/packages/qunit-dom/lib/helpers/test-assertions.ts +++ b/packages/qunit-dom/lib/helpers/test-assertions.ts @@ -1,9 +1,10 @@ import DOMAssertions, { type AssertionResult } from '../assertions.js'; +import type { IDOMElementDescriptor } from 'dom-element-descriptors'; export default class TestAssertions { public results: AssertionResult[] = []; - dom(target: string | Element | null, rootElement?: RootElement) { + dom(target: string | Element | null | IDOMElementDescriptor, rootElement?: RootElement) { return new DOMAssertions(target, rootElement || document, this as any); } diff --git a/packages/qunit-dom/lib/install.ts b/packages/qunit-dom/lib/install.ts index 5c9034be1..5ee21797a 100644 --- a/packages/qunit-dom/lib/install.ts +++ b/packages/qunit-dom/lib/install.ts @@ -1,17 +1,21 @@ import DOMAssertions from './assertions.js'; import { getRootElement } from './root-element.js'; +import type { IDOMElementDescriptor } from 'dom-element-descriptors'; declare global { type RootElement = Element | Document | ShadowRoot | null; interface Assert { - dom(target?: string | Element | null, rootElement?: RootElement): DOMAssertions; + dom( + target?: string | Element | IDOMElementDescriptor | null, + rootElement?: RootElement + ): DOMAssertions; } } export default function (assert: Assert) { assert.dom = function ( - target?: string | Element | null, + target?: string | Element | IDOMElementDescriptor | null, rootElement?: RootElement ): DOMAssertions { if (!isValidRootElement(rootElement)) { diff --git a/packages/qunit-dom/package.json b/packages/qunit-dom/package.json index bd10cc954..30f9a87da 100644 --- a/packages/qunit-dom/package.json +++ b/packages/qunit-dom/package.json @@ -64,6 +64,9 @@ "vitest": "1.0.1", "webpack": "5.89.0" }, + "dependencies": { + "dom-element-descriptors": "^0.5.1" + }, "packageManager": "pnpm@8.8.0", "volta": { "extends": "../../package.json" diff --git a/packages/qunit-dom/rollup.config.mjs b/packages/qunit-dom/rollup.config.mjs index 29a9285c4..d8986b466 100644 --- a/packages/qunit-dom/rollup.config.mjs +++ b/packages/qunit-dom/rollup.config.mjs @@ -20,7 +20,7 @@ const copyStaticArtifacts = copy({ const iifeBundle = { input: 'lib/qunit-dom.ts', - external: ['qunit'], + external: ['qunit', 'dom-element-descriptors'], plugins: [typescript({ ...typescriptConfiguration, tsconfigOverride: { @@ -35,13 +35,16 @@ const iifeBundle = { file: 'dist/qunit-dom.js', format: 'iife', sourcemap: true, + globals: { + 'dom-element-descriptors': 'DOMElementDescriptors', + }, }, }; const esBundle = { input: 'lib/qunit-dom-modules.ts', - external: ['qunit'], + external: ['qunit', 'dom-element-descriptors'], plugins: [typescript(typescriptConfiguration)], output: { diff --git a/packages/qunit-dom/tsconfig.json b/packages/qunit-dom/tsconfig.json index d2396043f..4d85b8208 100644 --- a/packages/qunit-dom/tsconfig.json +++ b/packages/qunit-dom/tsconfig.json @@ -7,11 +7,12 @@ "verbatimModuleSyntax": true, // We build to ESM, so we need to tell TS that we build to ESM // otherwise TS uses fake ESM (you use imports, but it assumes the compilation is to CJS) - // These are also required when using - // verbatimModuleSyntax, because it's an + // These are also required when using + // verbatimModuleSyntax, because it's an // ESM-only feature "target": "esnext", "module": "esnext", + "moduleResolution": "bundler", "lib": [ "ES6", diff --git a/packages/test-types-resolution-node/package.json b/packages/test-types-resolution-node/package.json index cc8aad976..e345c86a0 100644 --- a/packages/test-types-resolution-node/package.json +++ b/packages/test-types-resolution-node/package.json @@ -9,6 +9,7 @@ }, "devDependencies": { "@types/qunit": "2.19.7", + "dom-element-descriptors": "^0.5.1", "expect-type": "0.17.3", "typescript": "5.2.2" }, diff --git a/packages/test-types-resolution-node/test.ts b/packages/test-types-resolution-node/test.ts index aac737a06..77cf303cb 100644 --- a/packages/test-types-resolution-node/test.ts +++ b/packages/test-types-resolution-node/test.ts @@ -1,10 +1,11 @@ import QUnit from 'qunit'; import { setup } from 'qunit-dom'; import { expectTypeOf } from 'expect-type' +import type { IDOMElementDescriptor } from 'dom-element-descriptors'; setup(QUnit.assert); -expectTypeOf(QUnit.assert.dom).parameter(0).toEqualTypeOf(); +expectTypeOf(QUnit.assert.dom).parameter(0).toEqualTypeOf(); // @ts-expect-error - there is only one parameter expectTypeOf(QUnit.assert.dom).parameter(1).toEqualTypeOf(); diff --git a/packages/test-types-resolution-node16/package.json b/packages/test-types-resolution-node16/package.json index 96c77df4f..08920402e 100644 --- a/packages/test-types-resolution-node16/package.json +++ b/packages/test-types-resolution-node16/package.json @@ -9,6 +9,7 @@ }, "devDependencies": { "@types/qunit": "2.19.7", + "dom-element-descriptors": "^0.5.1", "expect-type": "0.17.3", "typescript": "5.2.2" }, diff --git a/packages/test-types-resolution-node16/test.ts b/packages/test-types-resolution-node16/test.ts index aac737a06..77cf303cb 100644 --- a/packages/test-types-resolution-node16/test.ts +++ b/packages/test-types-resolution-node16/test.ts @@ -1,10 +1,11 @@ import QUnit from 'qunit'; import { setup } from 'qunit-dom'; import { expectTypeOf } from 'expect-type' +import type { IDOMElementDescriptor } from 'dom-element-descriptors'; setup(QUnit.assert); -expectTypeOf(QUnit.assert.dom).parameter(0).toEqualTypeOf(); +expectTypeOf(QUnit.assert.dom).parameter(0).toEqualTypeOf(); // @ts-expect-error - there is only one parameter expectTypeOf(QUnit.assert.dom).parameter(1).toEqualTypeOf(); diff --git a/packages/test-types/package.json b/packages/test-types/package.json index 0558b871c..9cdd090c7 100644 --- a/packages/test-types/package.json +++ b/packages/test-types/package.json @@ -9,6 +9,7 @@ }, "devDependencies": { "@types/qunit": "2.19.7", + "dom-element-descriptors": "^0.5.1", "expect-type": "0.17.3", "typescript": "5.2.2" }, diff --git a/packages/test-types/test.ts b/packages/test-types/test.ts index aac737a06..77cf303cb 100644 --- a/packages/test-types/test.ts +++ b/packages/test-types/test.ts @@ -1,10 +1,11 @@ import QUnit from 'qunit'; import { setup } from 'qunit-dom'; import { expectTypeOf } from 'expect-type' +import type { IDOMElementDescriptor } from 'dom-element-descriptors'; setup(QUnit.assert); -expectTypeOf(QUnit.assert.dom).parameter(0).toEqualTypeOf(); +expectTypeOf(QUnit.assert.dom).parameter(0).toEqualTypeOf(); // @ts-expect-error - there is only one parameter expectTypeOf(QUnit.assert.dom).parameter(1).toEqualTypeOf(); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 39b028478..0249f84fd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -22,6 +22,10 @@ importers: version: 2.8.8 packages/qunit-dom: + dependencies: + dom-element-descriptors: + specifier: ^0.5.1 + version: 0.5.1 devDependencies: '@arethetypeswrong/cli': specifier: 0.12.2 @@ -361,6 +365,9 @@ importers: '@types/qunit': specifier: 2.19.7 version: 2.19.7 + dom-element-descriptors: + specifier: ^0.5.1 + version: 0.5.1 expect-type: specifier: 0.17.3 version: 0.17.3 @@ -380,6 +387,9 @@ importers: '@types/qunit': specifier: 2.19.7 version: 2.19.7 + dom-element-descriptors: + specifier: ^0.5.1 + version: 0.5.1 expect-type: specifier: 0.17.3 version: 0.17.3 @@ -399,6 +409,9 @@ importers: '@types/qunit': specifier: 2.19.7 version: 2.19.7 + dom-element-descriptors: + specifier: ^0.5.1 + version: 0.5.1 expect-type: specifier: 0.17.3 version: 0.17.3 @@ -9142,6 +9155,9 @@ packages: resolution: {integrity: sha512-CVzntLid1oFVHTKdTp/Qu7Kz+wSm8uO30TSQyAJ6n4Dz09yTzVQn3S1oRhVhUubxdMuKs1DjDqt88pubHagbPw==} dev: true + /dom-element-descriptors@0.5.1: + resolution: {integrity: sha512-DLayMRQ+yJaziF4JJX1FMjwjdr7wdTr1y9XvZ+NfHELfOMcYDnCHneAYXAS4FT1gLILh4V0juMZohhH1N5FsoQ==} + /domexception@2.0.1: resolution: {integrity: sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==} engines: {node: '>=8'}