|
1 |
| -import {configure} from '../config' |
2 | 1 | import {JSDOM} from 'jsdom'
|
| 2 | +import {configure} from '../config' |
3 | 3 | import * as dtl from '../'
|
4 | 4 |
|
| 5 | +beforeEach(() => { |
| 6 | + // reset back to original config |
| 7 | + configure({ |
| 8 | + queryAllElements: (element, query) => element.querySelectorAll(query), |
| 9 | + }) |
| 10 | +}) |
| 11 | + |
5 | 12 | test('works without a global dom', async () => {
|
6 | 13 | const container = new JSDOM(`
|
7 | 14 | <html>
|
@@ -78,50 +85,87 @@ test('works without a browser context on a dom node (JSDOM Fragment)', () => {
|
78 | 85 | `)
|
79 | 86 | })
|
80 | 87 |
|
81 |
| -test('works with a custom configured element query', () => { |
82 |
| - const container = JSDOM.fragment(` |
| 88 | +test('works with a custom configured element query for shadow dom elements', async () => { |
| 89 | + const window = new JSDOM(` |
83 | 90 | <html>
|
84 | 91 | <body>
|
85 |
| - <form id="login-form"> |
86 |
| - <label for="username">Username</label> |
87 |
| - <input id="username" /> |
88 |
| - <label for="password">Password</label> |
89 |
| - <input id="password" type="password" /> |
90 |
| - <button type="submit">Submit</button> |
91 |
| - <div id="data-container"></div> |
92 |
| - </form> |
93 |
| - <form id="other"> |
94 |
| - <label for="user_other">Username</label> |
95 |
| - <input id="user_other" /> |
96 |
| - <label for="pass_other">Password</label> |
97 |
| - <input id="pass_other" type="password" /> |
98 |
| - <button type="submit">Submit</button> |
99 |
| - <div id="data-container"></div> |
100 |
| - </form> |
| 92 | + <example-input></example-input> |
101 | 93 | </body>
|
102 | 94 | </html>
|
103 |
| - `) |
| 95 | + `).window |
| 96 | + const document = window.document |
| 97 | + const container = document.body |
| 98 | + |
| 99 | + // create custom element as system under test |
| 100 | + window.customElements.define( |
| 101 | + 'example-input', |
| 102 | + class extends window.HTMLElement { |
| 103 | + constructor() { |
| 104 | + super() |
| 105 | + const shadow = this.attachShadow({mode: 'open'}) |
| 106 | + |
| 107 | + const div = document.createElement('div') |
| 108 | + const label = document.createElement('label') |
| 109 | + label.setAttribute('for', 'invisible-from-outer-dom') |
| 110 | + label.innerHTML = |
| 111 | + 'Visible in browser, invisible for traditional queries' |
| 112 | + const input = document.createElement('input') |
| 113 | + input.setAttribute('id', 'invisible-from-outer-dom') |
| 114 | + div.appendChild(label) |
| 115 | + div.appendChild(input) |
| 116 | + shadow.appendChild(div) |
| 117 | + } |
| 118 | + }, |
| 119 | + ) |
104 | 120 |
|
| 121 | + // Given the default configuration is used |
| 122 | + |
| 123 | + // When querying for the label |
| 124 | + // Then it is not in the document |
| 125 | + expect( |
| 126 | + dtl.queryByLabelText( |
| 127 | + container, |
| 128 | + /Visible in browser, invisible for traditional queries/i, |
| 129 | + ), |
| 130 | + ).not.toBeInTheDocument() |
| 131 | + |
| 132 | + // Given I have a naive query that allows searching shadow dom |
| 133 | + const queryMeAndChildrenAndShadow = (element, query) => [ |
| 134 | + ...element.querySelectorAll(query), |
| 135 | + ...[...element.children].reduce( |
| 136 | + (result, child) => [ |
| 137 | + ...result, |
| 138 | + ...queryMeAndChildrenAndShadow(child, query), |
| 139 | + ], |
| 140 | + [], |
| 141 | + ), |
| 142 | + ...(element.shadowRoot?.querySelectorAll(query) ?? []), |
| 143 | + ] |
| 144 | + |
| 145 | + // When I configure the testing tools to use it |
105 | 146 | configure({
|
106 |
| - queryAllElements: (element, query) => |
107 |
| - element.querySelectorAll(`#other ${query}`), |
| 147 | + queryAllElements: queryMeAndChildrenAndShadow, |
108 | 148 | })
|
109 | 149 |
|
110 |
| - expect(dtl.getByLabelText(container, /username/i)).toMatchInlineSnapshot(` |
111 |
| - <input |
112 |
| - id=user_other |
113 |
| - /> |
114 |
| - `) |
115 |
| - expect(dtl.getByLabelText(container, /password/i)).toMatchInlineSnapshot(` |
| 150 | + // Then it is part of the document |
| 151 | + expect( |
| 152 | + dtl.queryByLabelText( |
| 153 | + container, |
| 154 | + /Visible in browser, invisible for traditional queries/i, |
| 155 | + ), |
| 156 | + ).toBeInTheDocument() |
| 157 | + |
| 158 | + // And it returns the expected item |
| 159 | + expect( |
| 160 | + dtl.getByLabelText( |
| 161 | + container, |
| 162 | + /Visible in browser, invisible for traditional queries/i, |
| 163 | + ), |
| 164 | + ).toMatchInlineSnapshot(` |
116 | 165 | <input
|
117 |
| - id=pass_other |
118 |
| - type=password |
| 166 | + id=invisible-from-outer-dom |
119 | 167 | />
|
120 | 168 | `)
|
121 |
| - // reset back to original config |
122 |
| - configure({ |
123 |
| - queryAllElements: (element, query) => element.querySelectorAll(query), |
124 |
| - }) |
125 | 169 | })
|
126 | 170 |
|
127 | 171 | test('byRole works without a global DOM', () => {
|
|
0 commit comments