Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/twbs/bootstrap.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/js/src/util
diff options
context:
space:
mode:
authorJohann-S <johann.servoire@gmail.com>2019-03-13 17:23:50 +0300
committerJohann-S <johann.servoire@gmail.com>2019-07-23 15:23:50 +0300
commitc8c207465043d940aa031570f0bce5e8fff9ffcf (patch)
tree482f430ee84aa4cae8f76cebdec75791a60a50d1 /js/src/util
parent08d81c843706c2b952fadb703f3f9be709a8ca6a (diff)
Switch from QUnit to Jasmine.
Diffstat (limited to 'js/src/util')
-rw-r--r--js/src/util/index.spec.js297
-rw-r--r--js/src/util/sanitizer.spec.js70
2 files changed, 367 insertions, 0 deletions
diff --git a/js/src/util/index.spec.js b/js/src/util/index.spec.js
new file mode 100644
index 0000000000..4b2d416856
--- /dev/null
+++ b/js/src/util/index.spec.js
@@ -0,0 +1,297 @@
+import * as Util from './index'
+
+/** Test helpers */
+import { getFixture, clearFixture } from '../../tests/helpers/fixture'
+
+describe('Util', () => {
+ let fixtureEl
+
+ beforeAll(() => {
+ fixtureEl = getFixture()
+ })
+
+ afterEach(() => {
+ clearFixture()
+ })
+
+ describe('getUID', () => {
+ it('should generate uid', () => {
+ const uid = Util.getUID('bs')
+ const uid2 = Util.getUID('bs')
+
+ expect(uid).not.toEqual(uid2)
+ })
+ })
+
+ describe('getSelectorFromElement', () => {
+ it('should get selector from data-target', () => {
+ fixtureEl.innerHTML = [
+ '<div id="test" data-target=".target"></div>',
+ '<div class="target"></div>'
+ ].join('')
+
+ const testEl = fixtureEl.querySelector('#test')
+
+ expect(Util.getSelectorFromElement(testEl)).toEqual('.target')
+ })
+
+ it('should get selector from href if no data-target set', () => {
+ fixtureEl.innerHTML = [
+ '<a id="test" href=".target"></a>',
+ '<div class="target"></div>'
+ ].join('')
+
+ const testEl = fixtureEl.querySelector('#test')
+
+ expect(Util.getSelectorFromElement(testEl)).toEqual('.target')
+ })
+
+ it('should get selector from href if data-target equal to #', () => {
+ fixtureEl.innerHTML = [
+ '<a id="test" data-target="#" href=".target"></a>',
+ '<div class="target"></div>'
+ ].join('')
+
+ const testEl = fixtureEl.querySelector('#test')
+
+ expect(Util.getSelectorFromElement(testEl)).toEqual('.target')
+ })
+
+ it('should return null if selector not found', () => {
+ fixtureEl.innerHTML = '<a id="test" href=".target"></a>'
+
+ const testEl = fixtureEl.querySelector('#test')
+
+ expect(Util.getSelectorFromElement(testEl)).toBeNull()
+ })
+ })
+
+ describe('getTransitionDurationFromElement', () => {
+ it('should get transition from element', () => {
+ fixtureEl.innerHTML = '<div style="transition: all 300ms ease-out;"></div>'
+
+ expect(Util.getTransitionDurationFromElement(fixtureEl.querySelector('div'))).toEqual(300)
+ })
+
+ it('should return 0 if the element is undefined or null', () => {
+ expect(Util.getTransitionDurationFromElement(null)).toEqual(0)
+ expect(Util.getTransitionDurationFromElement(undefined)).toEqual(0)
+ })
+
+ it('should return 0 if the element do not possess transition', () => {
+ fixtureEl.innerHTML = '<div></div>'
+
+ expect(Util.getTransitionDurationFromElement(fixtureEl.querySelector('div'))).toEqual(0)
+ })
+ })
+
+ describe('triggerTransitionEnd', () => {
+ it('should trigger transitionend event', done => {
+ fixtureEl.innerHTML = '<div style="transition: all 300ms ease-out;"></div>'
+
+ const el = fixtureEl.querySelector('div')
+
+ el.addEventListener('transitionend', () => {
+ expect().nothing()
+ done()
+ })
+
+ Util.triggerTransitionEnd(el)
+ })
+ })
+
+ describe('isElement', () => {
+ it('should detect if the parameter is an element or not', () => {
+ fixtureEl.innerHTML = '<div></div>'
+
+ const el = document.querySelector('div')
+
+ expect(Util.isElement(el)).toEqual(el.nodeType)
+ expect(Util.isElement({})).toEqual(undefined)
+ })
+
+ it('should detect jQuery element', () => {
+ fixtureEl.innerHTML = '<div></div>'
+
+ const el = document.querySelector('div')
+ const fakejQuery = {
+ 0: el
+ }
+
+ expect(Util.isElement(fakejQuery)).toEqual(el.nodeType)
+ })
+ })
+
+ describe('emulateTransitionEnd', () => {
+ it('should emulate transition end', () => {
+ fixtureEl.innerHTML = '<div></div>'
+
+ const el = document.querySelector('div')
+ const spy = spyOn(window, 'setTimeout')
+
+ Util.emulateTransitionEnd(el, 10)
+ expect(spy).toHaveBeenCalled()
+ })
+
+ it('should not emulate transition end if already triggered', done => {
+ fixtureEl.innerHTML = '<div></div>'
+
+ const el = fixtureEl.querySelector('div')
+ const spy = spyOn(el, 'removeEventListener')
+
+ Util.emulateTransitionEnd(el, 10)
+ Util.triggerTransitionEnd(el)
+
+ setTimeout(() => {
+ expect(spy).toHaveBeenCalled()
+ done()
+ }, 20)
+ })
+ })
+
+ describe('typeCheckConfig', () => {
+ it('should check type of the config object', () => {
+ const namePlugin = 'collapse'
+ const defaultType = {
+ toggle: 'boolean',
+ parent: '(string|element)'
+ }
+ const config = {
+ toggle: true,
+ parent: 777
+ }
+
+ expect(() => {
+ Util.typeCheckConfig(namePlugin, config, defaultType)
+ }).toThrow(new Error('COLLAPSE: Option "parent" provided type "number" but expected type "(string|element)".'))
+ })
+ })
+
+ describe('makeArray', () => {
+ it('should convert node list to array', () => {
+ const nodeList = document.querySelectorAll('div')
+
+ expect(Array.isArray(nodeList)).toEqual(false)
+ expect(Array.isArray(Util.makeArray(nodeList))).toEqual(true)
+ })
+
+ it('should return an empty array if the nodeList is undefined', () => {
+ expect(Util.makeArray(null)).toEqual([])
+ expect(Util.makeArray(undefined)).toEqual([])
+ })
+ })
+
+ describe('isVisible', () => {
+ it('should return false if the element is not defined', () => {
+ expect(Util.isVisible(null)).toEqual(false)
+ expect(Util.isVisible(undefined)).toEqual(false)
+ })
+
+ it('should return false if the element provided is not a dom element', () => {
+ expect(Util.isVisible({})).toEqual(false)
+ })
+
+ it('should return false if the element is not visible with display none', () => {
+ fixtureEl.innerHTML = '<div style="display: none;"></div>'
+
+ const div = fixtureEl.querySelector('div')
+
+ expect(Util.isVisible(div)).toEqual(false)
+ })
+
+ it('should return false if the element is not visible with visibility hidden', () => {
+ fixtureEl.innerHTML = '<div style="visibility: hidden;"></div>'
+
+ const div = fixtureEl.querySelector('div')
+
+ expect(Util.isVisible(div)).toEqual(false)
+ })
+
+ it('should return false if the parent element is not visible', () => {
+ fixtureEl.innerHTML = '<div></div>'
+
+ const div = fixtureEl.querySelector('div')
+
+ expect(Util.isVisible(div)).toEqual(false)
+ })
+
+ it('should return true if the element is visible', () => {
+ fixtureEl.innerHTML = [
+ '<div>',
+ ' <div id="element"></div>',
+ '</div>'
+ ].join('')
+
+ const div = fixtureEl.querySelector('#element')
+
+ expect(Util.isVisible(div)).toEqual(true)
+ })
+ })
+
+ describe('findShadowRoot', () => {
+ it('should return null if shadow dom is not available', () => {
+ // Only for newer browsers
+ if (!document.documentElement.attachShadow) {
+ expect().nothing()
+ return
+ }
+
+ fixtureEl.innerHTML = '<div></div>'
+
+ const div = fixtureEl.querySelector('div')
+
+ spyOn(document.documentElement, 'attachShadow').and.returnValue(null)
+
+ expect(Util.findShadowRoot(div)).toEqual(null)
+ })
+
+ it('should return null when we do not find a shadow root', () => {
+ // Only for newer browsers
+ if (!document.documentElement.attachShadow) {
+ expect().nothing()
+ return
+ }
+
+ spyOn(document, 'getRootNode').and.returnValue(undefined)
+
+ expect(Util.findShadowRoot(document)).toEqual(null)
+ })
+
+ it('should return the shadow root when found', () => {
+ // Only for newer browsers
+ if (!document.documentElement.attachShadow) {
+ expect().nothing()
+ return
+ }
+
+ fixtureEl.innerHTML = '<div></div>'
+
+ const div = fixtureEl.querySelector('div')
+ const shadowRoot = div.attachShadow({
+ mode: 'open'
+ })
+
+ expect(Util.findShadowRoot(shadowRoot)).toEqual(shadowRoot)
+
+ shadowRoot.innerHTML = '<button>Shadow Button</button>'
+
+ expect(Util.findShadowRoot(shadowRoot.firstChild)).toEqual(shadowRoot)
+ })
+ })
+
+ describe('noop', () => {
+ it('should return a function', () => {
+ expect(typeof Util.noop()).toEqual('function')
+ })
+ })
+
+ describe('reflow', () => {
+ it('should return element offset height to force the reflow', () => {
+ fixtureEl.innerHTML = '<div></div>'
+
+ const div = fixtureEl.querySelector('div')
+
+ expect(Util.reflow(div)).toEqual(0)
+ })
+ })
+})
diff --git a/js/src/util/sanitizer.spec.js b/js/src/util/sanitizer.spec.js
new file mode 100644
index 0000000000..6dadd29a5a
--- /dev/null
+++ b/js/src/util/sanitizer.spec.js
@@ -0,0 +1,70 @@
+import { DefaultWhitelist, sanitizeHtml } from './sanitizer'
+
+describe('Sanitizer', () => {
+ describe('sanitizeHtml', () => {
+ it('should return the same on empty string', () => {
+ const empty = ''
+
+ const result = sanitizeHtml(empty, DefaultWhitelist, null)
+
+ expect(result).toEqual(empty)
+ })
+
+ it('should sanitize template by removing tags with XSS', () => {
+ const template = [
+ '<div>',
+ ' <a href="javascript:alert(7)">Click me</a>',
+ ' <span>Some content</span>',
+ '</div>'
+ ].join('')
+
+ const result = sanitizeHtml(template, DefaultWhitelist, null)
+
+ expect(result.indexOf('script') === -1).toEqual(true)
+ })
+
+ it('should allow aria attributes and safe attributes', () => {
+ const template = [
+ '<div aria-pressed="true">',
+ ' <span class="test">Some content</span>',
+ '</div>'
+ ].join('')
+
+ const result = sanitizeHtml(template, DefaultWhitelist, null)
+
+ expect(result.indexOf('aria-pressed') !== -1).toEqual(true)
+ expect(result.indexOf('class="test"') !== -1).toEqual(true)
+ })
+
+ it('should remove not whitelist tags', () => {
+ const template = [
+ '<div>',
+ ' <script>alert(7)</script>',
+ '</div>'
+ ].join('')
+
+ const result = sanitizeHtml(template, DefaultWhitelist, null)
+
+ expect(result.indexOf('<script>') === -1).toEqual(true)
+ })
+
+ it('should not use native api to sanitize if a custom function passed', () => {
+ const template = [
+ '<div>',
+ ' <span>Some content</span>',
+ '</div>'
+ ].join('')
+
+ function mySanitize(htmlUnsafe) {
+ return htmlUnsafe
+ }
+
+ spyOn(DOMParser.prototype, 'parseFromString')
+
+ const result = sanitizeHtml(template, DefaultWhitelist, mySanitize)
+
+ expect(result).toEqual(template)
+ expect(DOMParser.prototype.parseFromString).not.toHaveBeenCalled()
+ })
+ })
+})