diff options
author | Johann-S <johann.servoire@gmail.com> | 2019-03-13 17:23:50 +0300 |
---|---|---|
committer | Johann-S <johann.servoire@gmail.com> | 2019-07-23 15:23:50 +0300 |
commit | c8c207465043d940aa031570f0bce5e8fff9ffcf (patch) | |
tree | 482f430ee84aa4cae8f76cebdec75791a60a50d1 /js/src/util | |
parent | 08d81c843706c2b952fadb703f3f9be709a8ca6a (diff) |
Switch from QUnit to Jasmine.
Diffstat (limited to 'js/src/util')
-rw-r--r-- | js/src/util/index.spec.js | 297 | ||||
-rw-r--r-- | js/src/util/sanitizer.spec.js | 70 |
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() + }) + }) +}) |