mirror of
https://github.com/twbs/bootstrap.git
synced 2025-08-13 00:54:04 +02:00
move util in a util folder with the sanitizer
This commit is contained in:
@@ -1,142 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<title>Bootstrap Plugin Test Suite</title>
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="../../node_modules/jquery/dist/jquery.slim.min.js"></script>
|
||||
<script src="../../node_modules/popper.js/dist/umd/popper.min.js"></script>
|
||||
|
||||
<!-- QUnit -->
|
||||
<link rel="stylesheet" href="../../node_modules/qunit/qunit/qunit.css" media="screen">
|
||||
<script src="../../node_modules/qunit/qunit/qunit.js"></script>
|
||||
|
||||
<!-- Sinon -->
|
||||
<script src="../../node_modules/sinon/pkg/sinon-no-sourcemaps.js"></script>
|
||||
|
||||
<!-- Hammer simulator -->
|
||||
<script src="../../node_modules/hammer-simulator/index.js"></script>
|
||||
|
||||
<script>
|
||||
// Disable jQuery event aliases to ensure we don't accidentally use any of them
|
||||
[
|
||||
'blur',
|
||||
'focus',
|
||||
'focusin',
|
||||
'focusout',
|
||||
'resize',
|
||||
'scroll',
|
||||
'click',
|
||||
'dblclick',
|
||||
'mousedown',
|
||||
'mouseup',
|
||||
'mousemove',
|
||||
'mouseover',
|
||||
'mouseout',
|
||||
'mouseenter',
|
||||
'mouseleave',
|
||||
'change',
|
||||
'select',
|
||||
'submit',
|
||||
'keydown',
|
||||
'keypress',
|
||||
'keyup',
|
||||
'contextmenu'
|
||||
].forEach(function(eventAlias) {
|
||||
$.fn[eventAlias] = function() {
|
||||
throw new Error('Using the ".' + eventAlias + '()" method is not allowed, so that Bootstrap can be compatible with custom jQuery builds which exclude the "event aliases" module that defines said method. See https://github.com/twbs/bootstrap/blob/master/CONTRIBUTING.md#js')
|
||||
}
|
||||
})
|
||||
|
||||
// Require assert.expect in each test
|
||||
QUnit.config.requireExpects = true
|
||||
|
||||
// See https://github.com/axemclion/grunt-saucelabs#test-result-details-with-qunit
|
||||
var log = []
|
||||
var testName
|
||||
|
||||
QUnit.done(function(testResults) {
|
||||
var tests = []
|
||||
for (var i = 0; i < log.length; i++) {
|
||||
var details = log[i]
|
||||
tests.push({
|
||||
name: details.name,
|
||||
result: details.result,
|
||||
expected: details.expected,
|
||||
actual: details.actual,
|
||||
source: details.source
|
||||
})
|
||||
}
|
||||
testResults.tests = tests
|
||||
|
||||
window.global_test_results = testResults
|
||||
})
|
||||
|
||||
QUnit.testStart(function(testDetails) {
|
||||
QUnit.log(function(details) {
|
||||
if (!details.result) {
|
||||
details.name = testDetails.name
|
||||
log.push(details)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// Display fixture on-screen on iOS to avoid false positives
|
||||
// See https://github.com/twbs/bootstrap/pull/15955
|
||||
if (/iPhone|iPad|iPod/.test(navigator.userAgent)) {
|
||||
QUnit.begin(function() {
|
||||
$('#qunit-fixture').css({ top: 0, left: 0 })
|
||||
})
|
||||
|
||||
QUnit.done(function() {
|
||||
$('#qunit-fixture').css({ top: '', left: '' })
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Transpiled Plugins -->
|
||||
<script src="../dist/util.js"></script>
|
||||
<script src="../dist/dom/polyfill.js"></script>
|
||||
<script src="../dist/dom/manipulator.js"></script>
|
||||
<script src="../dist/dom/eventHandler.js"></script>
|
||||
<script src="../dist/dom/selectorEngine.js"></script>
|
||||
<script src="../dist/dom/data.js"></script>
|
||||
<script src="../dist/alert.js"></script>
|
||||
<script src="../dist/button.js"></script>
|
||||
<script src="../dist/carousel.js"></script>
|
||||
<script src="../dist/collapse.js"></script>
|
||||
<script src="../dist/dropdown.js"></script>
|
||||
<script src="../dist/modal.js"></script>
|
||||
<script src="../dist/scrollspy.js"></script>
|
||||
<script src="../dist/tab.js"></script>
|
||||
<script src="../dist/tooltip.js"></script>
|
||||
<script src="../dist/popover.js"></script>
|
||||
<script src="../dist/toast.js"></script>
|
||||
|
||||
<!-- Unit Tests -->
|
||||
<script src="unit/dom/eventHandler.js"></script>
|
||||
<script src="unit/dom/manipulator.js"></script>
|
||||
<script src="unit/dom/data.js"></script>
|
||||
<script src="unit/dom/selectorEngine.js"></script>
|
||||
<script src="unit/alert.js"></script>
|
||||
<script src="unit/button.js"></script>
|
||||
<script src="unit/carousel.js"></script>
|
||||
<script src="unit/collapse.js"></script>
|
||||
<script src="unit/dropdown.js"></script>
|
||||
<script src="unit/modal.js"></script>
|
||||
<script src="unit/scrollspy.js"></script>
|
||||
<script src="unit/tab.js"></script>
|
||||
<script src="unit/tooltip.js"></script>
|
||||
<script src="unit/popover.js"></script>
|
||||
<script src="unit/util.js"></script>
|
||||
<script src="unit/toast.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="qunit-container">
|
||||
<div id="qunit"></div>
|
||||
<div id="qunit-fixture"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@@ -2,8 +2,6 @@ import 'popper.js'
|
||||
import bootstrap from '../../../dist/js/bootstrap'
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
document.getElementById('resultUID').innerHTML = bootstrap.Util.getUID('bs')
|
||||
|
||||
bootstrap.Util.makeArray(document.querySelectorAll('[data-toggle="tooltip"]'))
|
||||
Array.from(document.querySelectorAll('[data-toggle="tooltip"]'))
|
||||
.map((tooltipNode) => new bootstrap.Tooltip(tooltipNode))
|
||||
})
|
||||
|
@@ -13,11 +13,7 @@
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Hello, world!</h1>
|
||||
<div class="col-12">
|
||||
<div class="mt-5 mb-3">
|
||||
<span>Util.getUID: </span>
|
||||
<span id="resultUID"></span>
|
||||
</div>
|
||||
<div class="col-12 mt-5">
|
||||
<button type="button" class="btn btn-secondary" data-toggle="tooltip" data-placement="top" title="Tooltip on top">
|
||||
Tooltip on top
|
||||
</button>
|
||||
|
@@ -11,6 +11,7 @@ const {
|
||||
const jqueryFile = process.env.USE_OLD_JQUERY ? 'https://code.jquery.com/jquery-1.9.1.min.js' : 'node_modules/jquery/dist/jquery.slim.min.js'
|
||||
const bundle = process.env.BUNDLE === 'true'
|
||||
const browserStack = process.env.BROWSER === 'true'
|
||||
const debug = process.env.DEBUG === 'true'
|
||||
|
||||
const frameworks = [
|
||||
'qunit',
|
||||
@@ -28,11 +29,11 @@ const detectBrowsers = {
|
||||
usePhantomJS: false,
|
||||
postDetection(availableBrowser) {
|
||||
if (typeof process.env.TRAVIS_JOB_ID !== 'undefined' || availableBrowser.includes('Chrome')) {
|
||||
return ['ChromeHeadless']
|
||||
return debug ? ['Chrome'] : ['ChromeHeadless']
|
||||
}
|
||||
|
||||
if (availableBrowser.includes('Firefox')) {
|
||||
return ['FirefoxHeadless']
|
||||
return debug ? ['Firefox'] : ['FirefoxHeadless']
|
||||
}
|
||||
|
||||
throw new Error('Please install Firefox or Chrome')
|
||||
@@ -76,7 +77,8 @@ if (bundle) {
|
||||
conf.detectBrowsers = detectBrowsers
|
||||
files = files.concat([
|
||||
jqueryFile,
|
||||
'dist/js/bootstrap.js'
|
||||
'dist/js/bootstrap.js',
|
||||
'js/tests/unit/*.js'
|
||||
])
|
||||
} else if (browserStack) {
|
||||
conf.hostname = ip.address()
|
||||
@@ -93,7 +95,8 @@ if (bundle) {
|
||||
reporters.push('BrowserStack')
|
||||
files = files.concat([
|
||||
'node_modules/jquery/dist/jquery.slim.min.js',
|
||||
'js/coverage/dist/util.js',
|
||||
'js/coverage/dist/util/util.js',
|
||||
'js/coverage/dist/util/sanitizer.js',
|
||||
'js/coverage/dist/dom/polyfill.js',
|
||||
'js/coverage/dist/dom/eventHandler.js',
|
||||
'js/coverage/dist/dom/selectorEngine.js',
|
||||
@@ -103,7 +106,8 @@ if (bundle) {
|
||||
'js/coverage/dist/tooltip.js',
|
||||
'js/coverage/dist/!(util|index|tooltip).js', // include all of our js/dist files except util.js, index.js and tooltip.js
|
||||
'js/tests/unit/*.js',
|
||||
'js/tests/unit/dom/*.js'
|
||||
'js/tests/unit/dom/*.js',
|
||||
'js/tests/unit/util/*.js'
|
||||
])
|
||||
} else {
|
||||
frameworks.push('detectBrowsers')
|
||||
@@ -115,7 +119,8 @@ if (bundle) {
|
||||
)
|
||||
files = files.concat([
|
||||
jqueryFile,
|
||||
'js/coverage/dist/util.js',
|
||||
'js/coverage/dist/util/util.js',
|
||||
'js/coverage/dist/util/sanitizer.js',
|
||||
'js/coverage/dist/dom/polyfill.js',
|
||||
'js/coverage/dist/dom/eventHandler.js',
|
||||
'js/coverage/dist/dom/selectorEngine.js',
|
||||
@@ -125,7 +130,8 @@ if (bundle) {
|
||||
'js/coverage/dist/tooltip.js',
|
||||
'js/coverage/dist/!(util|index|tooltip).js', // include all of our js/dist files except util.js, index.js and tooltip.js
|
||||
'js/tests/unit/*.js',
|
||||
'js/tests/unit/dom/*.js'
|
||||
'js/tests/unit/dom/*.js',
|
||||
'js/tests/unit/util/*.js'
|
||||
])
|
||||
reporters.push('coverage-istanbul')
|
||||
conf.customLaunchers = customLaunchers
|
||||
@@ -153,9 +159,12 @@ if (bundle) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
files.push('js/tests/unit/*.js')
|
||||
if (debug) {
|
||||
conf.singleRun = false
|
||||
conf.autoWatch = true
|
||||
}
|
||||
}
|
||||
|
||||
conf.frameworks = frameworks
|
||||
conf.plugins = plugins
|
||||
|
@@ -8,6 +8,7 @@
|
||||
"bootstrap": false,
|
||||
"sinon": false,
|
||||
"Util": false,
|
||||
"Sanitizer": false,
|
||||
"Data": false,
|
||||
"Alert": false,
|
||||
"Button": false,
|
||||
|
@@ -695,13 +695,10 @@ $(function () {
|
||||
].join('')
|
||||
|
||||
var $modal = $(modalHTML).appendTo('#qunit-fixture')
|
||||
var expectedTransitionDuration = 300
|
||||
var spy = sinon.spy(Util, 'getTransitionDurationFromElement')
|
||||
|
||||
$modal.on('shown.bs.modal', function () {
|
||||
assert.ok(spy.returned(expectedTransitionDuration))
|
||||
$style.remove()
|
||||
spy.restore()
|
||||
assert.ok(true)
|
||||
done()
|
||||
})
|
||||
.bootstrapModal('show')
|
||||
|
@@ -722,8 +722,10 @@ $(function () {
|
||||
|
||||
QUnit.test('should not reload the tooltip on subsequent mouseenter events', function (assert) {
|
||||
assert.expect(1)
|
||||
var fakeId = 1
|
||||
var titleHtml = function () {
|
||||
var uid = Util.getUID('tooltip')
|
||||
var uid = fakeId
|
||||
fakeId++
|
||||
return '<p id="tt-content">' + uid + '</p><p>' + uid + '</p><p>' + uid + '</p>'
|
||||
}
|
||||
|
||||
@@ -753,8 +755,10 @@ $(function () {
|
||||
QUnit.test('should not reload the tooltip if the mouse leaves and re-enters before hiding', function (assert) {
|
||||
assert.expect(4)
|
||||
|
||||
var fakeId = 1
|
||||
var titleHtml = function () {
|
||||
var uid = Util.getUID('tooltip')
|
||||
var uid = 'tooltip' + fakeId
|
||||
fakeId++
|
||||
return '<p id="tt-content">' + uid + '</p><p>' + uid + '</p><p>' + uid + '</p>'
|
||||
}
|
||||
|
||||
@@ -1152,24 +1156,6 @@ $(function () {
|
||||
assert.strictEqual(tooltip.config.template.indexOf('onError'), -1)
|
||||
})
|
||||
|
||||
QUnit.test('should sanitize template by removing tags with XSS', function (assert) {
|
||||
assert.expect(1)
|
||||
|
||||
var $trigger = $('<a href="#" rel="tooltip" data-trigger="click" title="Another tooltip"/>')
|
||||
.appendTo('#qunit-fixture')
|
||||
.bootstrapTooltip({
|
||||
template: [
|
||||
'<div>',
|
||||
' <a href="javascript:alert(7)">Click me</a>',
|
||||
' <span>Some content</span>',
|
||||
'</div>'
|
||||
].join('')
|
||||
})
|
||||
|
||||
var tooltip = Tooltip._getInstance($trigger[0])
|
||||
assert.strictEqual(tooltip.config.template.indexOf('script'), -1)
|
||||
})
|
||||
|
||||
QUnit.test('should allow custom sanitization rules', function (assert) {
|
||||
assert.expect(2)
|
||||
|
||||
|
@@ -1,8 +1,6 @@
|
||||
$(function () {
|
||||
'use strict'
|
||||
|
||||
window.Util = typeof bootstrap !== 'undefined' ? bootstrap.Util : Util
|
||||
|
||||
QUnit.module('util', {
|
||||
afterEach: function () {
|
||||
$('#qunit-fixture').html('')
|
51
js/tests/unit/util/sanitizer.js
Normal file
51
js/tests/unit/util/sanitizer.js
Normal file
@@ -0,0 +1,51 @@
|
||||
$(function () {
|
||||
'use strict'
|
||||
|
||||
QUnit.module('sanitizer', {
|
||||
afterEach: function () {
|
||||
$('#qunit-fixture').html('')
|
||||
}
|
||||
})
|
||||
|
||||
QUnit.test('should export a default white list', function (assert) {
|
||||
assert.expect(1)
|
||||
|
||||
assert.ok(Sanitizer.DefaultWhitelist)
|
||||
})
|
||||
|
||||
QUnit.test('should sanitize template by removing tags with XSS', function (assert) {
|
||||
assert.expect(1)
|
||||
|
||||
var template = [
|
||||
'<div>',
|
||||
' <a href="javascript:alert(7)">Click me</a>',
|
||||
' <span>Some content</span>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
var result = Sanitizer.sanitizeHtml(template, Sanitizer.DefaultWhitelist, null)
|
||||
|
||||
assert.strictEqual(result.indexOf('script'), -1)
|
||||
})
|
||||
|
||||
QUnit.test('should not use native api to sanitize if a custom function passed', function (assert) {
|
||||
assert.expect(2)
|
||||
|
||||
var template = [
|
||||
'<div>',
|
||||
' <span>Some content</span>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
function mySanitize(htmlUnsafe) {
|
||||
return htmlUnsafe
|
||||
}
|
||||
|
||||
var spy = sinon.spy(DOMParser.prototype, 'parseFromString')
|
||||
var result = Sanitizer.sanitizeHtml(template, Sanitizer.DefaultWhitelist, mySanitize)
|
||||
|
||||
assert.strictEqual(result, template)
|
||||
assert.strictEqual(spy.called, false)
|
||||
spy.restore()
|
||||
})
|
||||
})
|
@@ -60,13 +60,13 @@
|
||||
<script src="../../dist/toast.js"></script>
|
||||
<script>
|
||||
window.addEventListener('load', function () {
|
||||
Util.makeArray(document.querySelectorAll('.toast'))
|
||||
Array.from(document.querySelectorAll('.toast'))
|
||||
.forEach(function (toastNode) {
|
||||
new Toast(toastNode)
|
||||
})
|
||||
|
||||
document.getElementById('btnShowToast').addEventListener('click', function () {
|
||||
Util.makeArray(document.querySelectorAll('.toast'))
|
||||
Array.from(document.querySelectorAll('.toast'))
|
||||
.forEach(function (toastNode) {
|
||||
var toast = Toast._getInstance(toastNode)
|
||||
toast.show()
|
||||
@@ -74,7 +74,7 @@
|
||||
})
|
||||
|
||||
document.getElementById('btnHideToast').addEventListener('click', function () {
|
||||
Util.makeArray(document.querySelectorAll('.toast'))
|
||||
Array.from(document.querySelectorAll('.toast'))
|
||||
.forEach(function (toastNode) {
|
||||
var toast = Toast._getInstance(toastNode)
|
||||
toast.hide()
|
||||
|
Reference in New Issue
Block a user