1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
|
describe('Basic Functionality', () => {
afterEach(() => {
cleanupTest();
})
it('Button click triggers fetch and swaps content', async ()=> {
// Set up mock response
mockResponse('GET', '/demo', '<div id="result">Success!</div>');
// Create test button
createProcessedHTML('<button id="test-btn" hx-action="/demo" hx-target="#target">Click</button><div id="target">Original</div>');
// Click the button
find("#test-btn").click()
await forRequest();
// Verify the swap occurred
assertTextContentIs("#target", "Success!");
})
it('validation errors prevent submission of a form', async function() {
// Set up mock response
mockResponse('POST', '/demo', '<div id="result">Success!</div>');
createProcessedHTML('<form><input id="i1" required/><button id="b1" hx-post="/demo" hx-validate="true">Demo</button></form>');
find('#b1').click();
assert.equal(fetchMock.pendingRequests.length, 0);
// fill in the required value
find("#i1").value = "foo"
find('#b1').click()
await forRequestWithDelay();
assert.isUndefined(find('#target'));
assertTextContentIs("#result", "Success!");
})
it('validation errors do not prevent submission of an element within a form marked as hx-validate=false', async function() {
// Set up mock response
mockResponse('POST', '/demo', new MockResponse('<div id="result">Success!</div>'));
// Create test button
createProcessedHTML('<form><input id="i1" required/><button id="b1" hx-post="/demo" hx-validate="false">Demo</button></form>');
// Click the button
find('#b1').click()
await forRequestWithDelay();
assert.isUndefined(find('#target'));
assertTextContentIs("#result", "Success!");
})
it('validation errors prevent submission of a single input with hx-validate=true', async function() {
mockResponse('POST', '/demo', '<div id="result">Success!</div>');
createProcessedHTML('<input id="i1" required hx-post="/demo" hx-validate="true" name="test" hx-trigger="click"/>');
find('#i1').click();
assert.equal(fetchMock.pendingRequests.length, 0);
find("#i1").value = "foo"
find('#i1').click()
await forRequestWithDelay();
assertTextContentIs("#result", "Success!");
})
it('validation errors prevent submission of hx-included inputs', async function() {
mockResponse('POST', '/demo', '<div id="result">Success!</div>');
createProcessedHTML('<input id="i1" required name="test1"/><button id="b1" hx-post="/demo" hx-validate="true" hx-include="#i1">Submit</button>');
find('#b1').click();
assert.equal(fetchMock.pendingRequests.length, 0);
find("#i1").value = "foo"
find('#b1').click()
await forRequestWithDelay();
assertTextContentIs("#result", "Success!");
})
it('form with noValidate does not validate by default', async function() {
mockResponse('POST', '/demo', '<div id="result">Success!</div>');
createProcessedHTML('<form novalidate><input id="i1" required name="test"/><button id="b1" hx-post="/demo">Submit</button></form>');
find('#b1').click();
await forRequestWithDelay();
assertTextContentIs("#result", "Success!");
})
it('form with noValidate can be overridden with hx-validate=true', async function() {
mockResponse('POST', '/demo', '<div id="result">Success!</div>');
createProcessedHTML('<form novalidate><input id="i1" required name="test"/><button id="b1" hx-post="/demo" hx-validate="true">Submit</button></form>');
find('#b1').click();
assert.equal(fetchMock.pendingRequests.length, 0);
find("#i1").value = "foo"
find('#b1').click()
await forRequestWithDelay();
assertTextContentIs("#result", "Success!");
})
it('submit button with formNoValidate skips validation', async function() {
mockResponse('POST', '/demo', '<div id="result">Success!</div>');
createProcessedHTML('<form><input id="i1" required name="test"/><button id="b1" hx-post="/demo" formnovalidate>Submit</button></form>');
find('#b1').click();
await forRequestWithDelay();
assertTextContentIs("#result", "Success!");
})
it('form validates by default without hx-validate attribute', async function() {
mockResponse('POST', '/demo', '<div id="result">Success!</div>');
createProcessedHTML('<form hx-post="/demo"><input id="i1" required name="test"/><button id="b1" type="submit">Submit</button></form>');
find('#b1').click();
assert.equal(fetchMock.pendingRequests.length, 0);
find("#i1").value = "foo"
find('#b1').click()
await forRequestWithDelay();
assertTextContentIs("#result", "Success!");
})
// it('Button added dynamically still triggers fetch and swaps', async function() {
// // Set up mock response
// fetchMock.mockResponse('/demo', new MockResponse('<div id="d1">Foo</div>'));
// // Add button dynamically
// const playground = find('#test-playground');
// playground.insertAdjacentHTML('beforeend', `<button hx-action="/demo">Button 1</button>`);
// // Wait for htmx to initialize the new element
// await htmx.forEvent("mx:init", 2000);
// // Click the button
// find('button').click();
// // Wait for the swap to complete
// await htmx.forEvent("htmx:after:swap", 2000);
// // Verify the swap occurred
// const result = find('#d1');
// assertExists(result);
// assertEquals("Foo", result.textContent);
// })
//
// it('Button with hx-target swaps into target element', async function() {
// // Set up mock response
// fetchMock.mockResponse('/demo', new MockResponse('<div id="d1">Foo</div>'));
// // Create test button with target
// await initLiveContent(`
// <button hx-action="/demo" hx-target="#output1">Button 1</button>
// <output id="output1">Bar</output>
// `);
// // Click the button
// find('button').click();
// // Wait for the swap to complete
// await htmx.forEvent("htmx:after:swap", 2000);
// // Verify the swap occurred in the target
// const result = find('#d1');
// assertExists(result);
// assertEquals("Foo", result.textContent);
// })
//
// it('Button with swap afterend swaps after the end of the target', async function() {
// // Set up mock response
// fetchMock.mockResponse('/demo', new MockResponse('<div id="d1">Foo</div>'));
// // Create test button with target
// await initLiveContent(`
// <button id="b1" hx-action="/demo" hx-swap="afterend">Button 1</button>`);
// // Click the button
// find('button').click();
// // Wait for the swap to complete
// await htmx.forEvent("htmx:after:swap", 2000);
//
// // Verify the swap occurred after the target
// const btn = find('#b1');
// assertExists(btn);
// assertEquals("Button 1", btn.textContent);
//
// // Verify the swap occurred after the target
// const result = btn.nextElementSibling;
// assertExists(result);
// assertEquals("Foo", result.textContent);
// })
//
// it('Test attributes can be explicity inherited to children', async function() {
// // Set up mock response
// fetchMock.mockResponse('/demo1', new MockResponse('<div>Foo</div>'));
// fetchMock.mockResponse('/demo2', new MockResponse('<div>Bar</div>'));
// // Create test button with target
// await initLiveContent(`
// <div hx-swap:inherited="beforeend" hx-target:inherited="#output">
// <button id="b1" hx-action="/demo1">Button 1</button>
// <button id="b2" hx-action="/demo2">Button 2</button>
// </div>
// <div id="output"></div>
// `);
// // Click the button
// find('#b1').click();
// await htmx.forEvent("htmx:after:swap", 2000);
//
// // Verify the swap occurred after the target
// const output = find('#output');
// assertExists(output);
// assertEquals("Foo", output.textContent);
//
// find('#b2').click();
// await htmx.forEvent("htmx:after:swap", 2000);
//
// assertEquals("FooBar", output.textContent);
// })
// })
//
// describe('Advanced Triggers', function() {
// afterEach(function() {
// cleanup()
// })
//
// it('Test multiple events can trigger', async function() {
// // Set up mock response
// fetchMock.mockResponse('/demo', new MockResponse('<div>Foo</div>'));
// // Create test button with target
// await initLiveContent(`
// <button id="b1" hx-action="/demo" hx-target="#output" hx-swap="beforeend" hx-trigger="foo, bar">Button 1</button>
// <output id="output"></output>
// `);
// // Click the button
// let btn = find('#b1');
// htmx.trigger(btn, 'foo');
// await htmx.forEvent("htmx:after:swap", 2000);
//
// // Verify the swap occurred after the target
// const output = find('#output');
// assertExists(output);
// assertEquals("Foo", output.textContent);
//
// htmx.trigger(btn, 'bar');
// await htmx.forEvent("htmx:after:swap", 2000);
//
// assertEquals("FooFoo", output.textContent);
// })
//
// it('Test delay can delay a trigger', async function() {
// fetchMock.mockResponse('/demo', new MockResponse('<div>Foo</div>'));
// await initLiveContent(`
// <div id="d1" hx-action="/demo" hx-swap="innerHTML" hx-trigger="foo delay:1s">Div 1</div>
// `);
//
// let div = find('#d1');
// htmx.trigger(div, 'foo');
// // should still be Div 1
// await htmx.timeout(300);
// assertEquals("Div 1", div.textContent);
//
// // delay should trigger eventually
// await htmx.forEvent("htmx:after:swap", 2000);
// assertEquals("Foo", div.textContent);
// })
//
// it('Test delay debounces a trigger', async function() {
// fetchMock.mockResponse('/demo', new MockResponse('<div>Foo</div>'));
// await initLiveContent(`
// <div id="d1" hx-action="/demo" hx-swap="innerHTML" hx-trigger="foo delay:1s">Div 1</div>
// `);
//
// let div = find('#d1');
// htmx.trigger(div, 'foo');
// // should still be Div 1
// await htmx.timeout(600);
// assertEquals("Div 1", div.textContent);
//
// htmx.trigger(div, 'foo');
// // should still be Div 1 due to retrigger
// await htmx.timeout(600);
// assertEquals("Div 1", div.textContent);
//
// // delay should trigger eventually
// await htmx.forEvent("htmx:after:swap", 2000);
// assertEquals("Foo", div.textContent);
// })
//
// it('Test \'every\' polls properly', async function() {
// fetchMock.mockResponse('/demo', new MockResponse('<div>Foo</div>'));
// await initLiveContent(`
// <div id="d1" hx-action="/demo" hx-swap="innerHTML" hx-trigger="every 1s">Div 1</div>
// `);
//
// let div = find('#d1');
//
// // should still be Div 1
// await htmx.timeout(600);
// assertEquals("Div 1", div.textContent);
//
// // delay should trigger eventually
// await htmx.forEvent("htmx:after:swap", 2000);
// assertEquals("Foo", div.textContent);
// })
})
|