Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion API.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ Once installed the DOM element assertions are available at `assert.dom(...).*`:
**Parameters**

* `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`)
* `rootElement` **([HTMLElement][115] | [Document][152] | [ShadowRoot][153] | [null][154])?** The root element of the DOM in which to search for the `target` (optional, defaults `document` when `null` or not provided)

**Examples**

Expand Down Expand Up @@ -1194,3 +1194,9 @@ assert.dom('section#block').doesNotHaveTagName('div');
[150]: #hasValue

[151]: https://developer.mozilla.org/en-US/docs/Web/API/Element/tagName

[152]: https://developer.mozilla.org/en-US/docs/Web/API/Document

[153]: https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot

[154]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/null
152 changes: 152 additions & 0 deletions packages/qunit-dom/lib/__tests__/root-element.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import { describe, beforeEach, test, expect } from 'vitest';

import TestAssertions from '../helpers/test-assertions';

describe('assert.dom(..., rootElement)', () => {
let assert: TestAssertions;

beforeEach(() => {
assert = new TestAssertions();
});

test('passing an Element as rootElement', () => {
document.body.innerHTML = `
<span class="target">dedcoy<span>

<h1 class="parent">
<span class="target">real target<span>
</h1>
`;

const rootElement = document.querySelector('.parent');

assert.dom('.target', rootElement).exists({ count: 1 });
assert.dom('.target', rootElement).hasText('real target');

expect(assert.results).toEqual([
{
result: true,
actual: 'Element .target exists once',
expected: 'Element .target exists once',
message: 'Element .target exists once',
},
{
result: true,
actual: 'real target',
expected: 'real target',
message: 'Element .target has text "real target"',
},
]);
});

test('not passing anything as rootElement', () => {
document.body.innerHTML = `
<span class="target">decoy<span>

<h1 class="parent">
<span class="target">real target<span>
</h1>
`;

assert.dom('.target').exists({ count: 2 });

expect(assert.results).toEqual([
{
result: true,
actual: 'Element .target exists twice',
expected: 'Element .target exists twice',
message: 'Element .target exists twice',
},
]);
});

test('passing document as rootElement', () => {
document.body.innerHTML = `
<span class="target">decoy<span>

<h1 class="parent">
<span class="target">real target<span>
</h1>
`;

assert.dom('.target', document).exists({ count: 2 });

expect(assert.results).toEqual([
{
result: true,
actual: 'Element .target exists twice',
expected: 'Element .target exists twice',
message: 'Element .target exists twice',
},
]);
});

test('passing null as rootElement', () => {
document.body.innerHTML = `
<span class="target">decoy<span>

<h1 class="parent">
<span class="target">real target<span>
</h1>
`;

assert.dom('.target', null).exists({ count: 2 });

expect(assert.results).toEqual([
{
result: true,
actual: 'Element .target exists twice',
expected: 'Element .target exists twice',
message: 'Element .target exists twice',
},
]);
});

test('passing shadow root as rootElement', () => {
document.body.innerHTML = `
<div id="container">
<span class="target">decoy<span>
</div>
`;

const container = document.getElementById('container');
const shadowRoot = container.attachShadow({ mode: 'closed' });

shadowRoot.innerHTML = '<span class="target">real target<span>';

assert.dom('.target').exists({ count: 1 }, 'Only decoy element is found outside shadow root');
assert.dom('.target').hasText('real target', 'decoy element text');

assert.dom('.target', shadowRoot).exists({ count: 1 }, 'Only target found in shadow root');
assert.dom('.target', shadowRoot).hasText('real target', 'Target element text');

console.log(assert.results);

expect(assert.results).toEqual([
{
result: true,
actual: 'Element .target exists once',
expected: 'Element .target exists once',
message: 'Only decoy element is found outside shadow root',
},
{
result: false,
actual: 'decoy',
expected: 'real target',
message: 'decoy element text',
},
{
result: true,
actual: 'Element .target exists once',
expected: 'Element .target exists once',
message: 'Only target found in shadow root',
},
{
result: true,
actual: 'real target',
expected: 'real target',
message: 'Target element text',
},
]);
});
});
2 changes: 1 addition & 1 deletion packages/qunit-dom/lib/assertions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ type ActualCSSStyleDeclaration = Partial<Record<CSSStyleDeclarationProperty, unk
export default class DOMAssertions {
constructor(
private target: string | Element | null,
private rootElement: Element | Document,
private rootElement: RootElement,
private testContext: Assert
) {}

Expand Down
2 changes: 1 addition & 1 deletion packages/qunit-dom/lib/helpers/test-assertions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import DOMAssertions, { type AssertionResult } from '../assertions.js';
export default class TestAssertions {
public results: AssertionResult[] = [];

dom(target: string | Element | null, rootElement?: Element) {
dom(target: string | Element | null, rootElement?: RootElement) {
return new DOMAssertions(target, rootElement || document, this as any);
}

Expand Down
9 changes: 7 additions & 2 deletions packages/qunit-dom/lib/install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@ import DOMAssertions from './assertions.js';
import { getRootElement } from './root-element.js';

declare global {
type RootElement = Element | Document | ShadowRoot | null;

interface Assert {
dom(target?: string | Element | null, rootElement?: Element): DOMAssertions;
dom(target?: string | Element | null, rootElement?: RootElement): DOMAssertions;
}
}

export default function (assert: Assert) {
assert.dom = function (target?: string | Element | null, rootElement?: Element): DOMAssertions {
assert.dom = function (
target?: string | Element | null,
rootElement?: RootElement
): DOMAssertions {
if (!isValidRootElement(rootElement)) {
throw new Error(`${rootElement} is not a valid root element`);
}
Expand Down