describe('hx-swap-oob attribute', function() {
const savedConfig = htmx.config
beforeEach(function() {
this.server = makeServer()
htmx.config = Object.assign({}, savedConfig)
clearWorkArea()
})
afterEach(function() {
this.server.restore()
htmx.config = savedConfig
clearWorkArea()
})
// Repeat the same test to make sure it works with different configurations
for (const config of [{ allowNestedOobSwaps: true }, { allowNestedOobSwaps: false }]) {
it('handles basic response properly with config ' + JSON.stringify(config), function() {
Object.assign(htmx.config, config)
this.server.respondWith('GET', '/test', "Clicked
Swapped0
")
var div = make('
click me
')
make('')
div.click()
this.server.respond()
div.innerHTML.should.equal('Clicked')
byId('d1').innerHTML.should.equal('Swapped0')
})
}
for (const config of [{ allowNestedOobSwaps: true }, { allowNestedOobSwaps: false }]) {
it('oob swap works when the response has a body tag with config ' + JSON.stringify(config), function() {
Object.assign(htmx.config, config)
this.server.respondWith('GET', '/test', "Clicked
Swapped0
")
var div = make('
click me
')
make('')
div.click()
this.server.respond()
div.innerHTML.should.equal('Clicked')
byId('d2').innerHTML.should.equal('Swapped0')
})
}
for (const config of [{ allowNestedOobSwaps: true }, { allowNestedOobSwaps: false }]) {
it('oob swap works when the response has html and body tags with config ' + JSON.stringify(config), function() {
Object.assign(htmx.config, config)
this.server.respondWith('GET', '/test', "Clicked
Swapped0
")
var div = make('
click me
')
make('')
div.click()
this.server.respond()
div.innerHTML.should.equal('Clicked')
byId('d3').innerHTML.should.equal('Swapped0')
})
}
for (const config of [{ allowNestedOobSwaps: true }, { allowNestedOobSwaps: false }]) {
it('handles more than one oob swap properly with config ' + JSON.stringify(config), function() {
Object.assign(htmx.config, config)
this.server.respondWith('GET', '/test', "Clicked
')
byId('d1').innerHTML.should.equal('Swapped7')
})
it('swaps into all targets that match the selector (innerHTML)', function() {
this.server.respondWith('GET', '/test', "
Clicked
Swapped8
")
var div = make('
click me
')
make('
No swap
')
make('
Not swapped
')
make('
Not swapped
')
div.click()
this.server.respond()
byId('d1').innerHTML.should.equal('No swap')
byId('d2').innerHTML.should.equal('Swapped8')
byId('d3').innerHTML.should.equal('Swapped8')
})
it('swaps into all targets that match the selector (outerHTML)', function() {
var oobSwapContent = '
`
htmx.process(root) // Tell HTMX about this component's shadow DOM
}
}
var elementName = 'test-oobswap-inside-' + config.allowNestedOobSwaps
customElements.define(elementName, TestElement)
var div = make(`
this should not get swapped
<${elementName}/>
`)
var badTarget = div.querySelector('#oob-swap-target')
var webComponent = div.querySelector(elementName)
var btn = webComponent.shadowRoot.querySelector('button')
var goodTarget = webComponent.shadowRoot.querySelector('#oob-swap-target')
var mainTarget = webComponent.shadowRoot.querySelector('#main-target')
btn.click()
this.server.respond()
should.equal(mainTarget.textContent, 'Clicked')
should.equal(goodTarget.textContent, 'new contents')
should.equal(badTarget.textContent, 'this should not get swapped')
})
}
for (const config of [{ allowNestedOobSwaps: true }, { allowNestedOobSwaps: false }]) {
it('handles oob target in web components with main target outside web component config ' + JSON.stringify(config), function() {
this.server.respondWith('GET', '/test', '
`
htmx.process(root) // Tell HTMX about this component's shadow DOM
}
}
var elementName = 'test-oobswap-global-main-' + config.allowNestedOobSwaps
customElements.define(elementName, TestElement)
var div = make(`
this should not get swapped
<${elementName}/>
`)
var badTarget = div.querySelector('#oob-swap-target')
var webComponent = div.querySelector(elementName)
var btn = webComponent.shadowRoot.querySelector('button')
var goodTarget = webComponent.shadowRoot.querySelector('#oob-swap-target')
var mainTarget = div.querySelector('#main-target')
btn.click()
this.server.respond()
should.equal(mainTarget.textContent, 'Clicked')
should.equal(goodTarget.textContent, 'new contents')
should.equal(badTarget.textContent, 'this should not get swapped')
})
}
for (const config of [{ allowNestedOobSwaps: true }, { allowNestedOobSwaps: false }]) {
it('handles global oob target in web components with main target inside web component config ' + JSON.stringify(config), function() {
this.server.respondWith('GET', '/test', '
`
htmx.process(root) // Tell HTMX about this component's shadow DOM
}
}
var elementName = 'test-oobswap-global-oob-' + config.allowNestedOobSwaps
customElements.define(elementName, TestElement)
var div = make(`
this should get swapped
<${elementName}/>
`)
var webComponent = div.querySelector(elementName)
var badTarget = webComponent.shadowRoot.querySelector('#oob-swap-target')
var btn = webComponent.shadowRoot.querySelector('button')
var goodTarget = div.querySelector('#oob-swap-target')
var mainTarget = webComponent.shadowRoot.querySelector('#main-target')
btn.click()
this.server.respond()
should.equal(mainTarget.textContent, 'Clicked')
should.equal(goodTarget.textContent, 'new contents')
should.equal(badTarget.textContent, 'this should not get swapped')
})
}
it.skip('triggers htmx:oobErrorNoTarget when no targets found', function(done) {
// this test fails right now because when targets not found it returns an empty array which makes it miss the event as it should be if (targets.length)
this.server.respondWith('GET', '/test', "Clicked
Swapped
")
var div = make('
click me
')
// Define the event listener function so it can be removed later
var eventListenerFunction = function(event) {
event.detail.content.innerHTML.should.equal('Swapped')
document.body.removeEventListener('htmx:oobErrorNoTarget', eventListenerFunction)
done()
}
document.body.addEventListener('htmx:oobErrorNoTarget', eventListenerFunction)
div.click()
this.server.respond()
})
it('handles elements with IDs containing special characters properly', function() {
this.server.respondWith('GET', '/test', '
Swapped10
')
var div = make('
click me
')
make('
Existing Content
')
div.click()
this.server.respond()
var swappedElement = document.querySelector('[id="foo-/bar/"]')
swappedElement.innerHTML.should.equal('Swapped10')
})
it('handles one swap into multiple elements with the same ID properly', function() {
this.server.respondWith('GET', '/test', '