0
0
mirror of https://github.com/twbs/bootstrap.git synced 2025-02-10 07:54:31 +01:00
Bootstrap/js/tests/unit/dom/selector-engine.spec.js
Martijn Cuppens 7d8c7c4ba8
prev() function fails when non-element nodes are present (#30117)
The `prev()` function doesn't take nodes other than elements into account. Also we could simplify things a lot using the `previousElementSibling` property. This property isn't fully supported in IE, it only works for elements, but since the `element` variable is an element, we can safely use it here.

I've also added an additional test.

I don't think we had this issue in v4, since we relied on jQuery back then.

Ref. https://developer.mozilla.org/en-US/docs/Web/API/NonDocumentTypeChildNode/nextElementSibling
2020-03-09 17:21:04 +02:00

131 lines
3.4 KiB
JavaScript

import SelectorEngine from '../../../src/dom/selector-engine'
import { makeArray } from '../../../src/util/index'
/** Test helpers */
import { getFixture, clearFixture } from '../../helpers/fixture'
describe('SelectorEngine', () => {
let fixtureEl
beforeAll(() => {
fixtureEl = getFixture()
})
afterEach(() => {
clearFixture()
})
describe('matches', () => {
it('should return matched elements', () => {
fixtureEl.innerHTML = '<div></div>'
expect(SelectorEngine.matches(fixtureEl, 'div')).toEqual(true)
})
})
describe('find', () => {
it('should find elements', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
expect(makeArray(SelectorEngine.find('div', fixtureEl))).toEqual([div])
})
it('should find elements globaly', () => {
fixtureEl.innerHTML = '<div id="test"></div>'
const div = fixtureEl.querySelector('#test')
expect(makeArray(SelectorEngine.find('#test'))).toEqual([div])
})
it('should handle :scope selectors', () => {
fixtureEl.innerHTML = `<ul>
<li></li>
<li>
<a href="#" class="active">link</a>
</li>
<li></li>
</ul>`
const listEl = fixtureEl.querySelector('ul')
const aActive = fixtureEl.querySelector('.active')
expect(makeArray(SelectorEngine.find(':scope > li > .active', listEl))).toEqual([aActive])
})
})
describe('findOne', () => {
it('should return one element', () => {
fixtureEl.innerHTML = '<div id="test"></div>'
const div = fixtureEl.querySelector('#test')
expect(SelectorEngine.findOne('#test')).toEqual(div)
})
})
describe('children', () => {
it('should find children', () => {
fixtureEl.innerHTML = `<ul>
<li></li>
<li></li>
<li></li>
</ul>`
const list = fixtureEl.querySelector('ul')
const liList = makeArray(fixtureEl.querySelectorAll('li'))
const result = makeArray(SelectorEngine.children(list, 'li'))
expect(result).toEqual(liList)
})
})
describe('parents', () => {
it('should return parents', () => {
expect(SelectorEngine.parents(fixtureEl, 'body').length).toEqual(1)
})
})
describe('prev', () => {
it('should return previous element', () => {
fixtureEl.innerHTML = '<div class="test"></div><button class="btn"></button>'
const btn = fixtureEl.querySelector('.btn')
const divTest = fixtureEl.querySelector('.test')
expect(SelectorEngine.prev(btn, '.test')).toEqual([divTest])
})
it('should return previous element with an extra element between', () => {
fixtureEl.innerHTML = [
'<div class="test"></div>',
'<span></span>',
'<button class="btn"></button>'
].join('')
const btn = fixtureEl.querySelector('.btn')
const divTest = fixtureEl.querySelector('.test')
expect(SelectorEngine.prev(btn, '.test')).toEqual([divTest])
})
it('should return previous element with comments or text nodes between', () => {
fixtureEl.innerHTML = [
'<div class="test"></div>',
'<div class="test"></div>',
'<!-- Comment-->',
'Text',
'<button class="btn"></button>'
].join('')
const btn = fixtureEl.querySelector('.btn')
const divTest = fixtureEl.querySelectorAll('.test')[1]
expect(SelectorEngine.prev(btn, '.test')).toEqual([divTest])
})
})
})