inkstream 0.1.0 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE.txt +21 -0
- data/README.md +95 -0
- data/_config.yml +131 -0
- data/_includes/button.html +4 -0
- data/_includes/icon.html +1 -0
- data/_includes/nav-default.html +23 -0
- data/_includes/nav-header.html +25 -0
- data/_includes/post-list.html +59 -0
- data/_includes/post-meta.html +0 -0
- data/_includes/post-pagination.html +29 -0
- data/_includes/promo-section.html +12 -0
- data/_includes/site-before-end.html +1 -0
- data/_includes/site-before-start.html +1 -0
- data/_includes/site-favicons.html +12 -0
- data/_includes/site-fonts.html +13 -0
- data/_includes/site-footer-default.html +17 -0
- data/_includes/site-footer.html +23 -0
- data/_includes/site-header.html +66 -0
- data/_includes/site-styles.html +6 -0
- data/_layouts/blog.html +24 -0
- data/_layouts/default.html +62 -0
- data/_layouts/page.html +35 -0
- data/_layouts/post.html +201 -0
- data/assets/css/styles.css +11167 -0
- data/assets/favicon/android-chrome-192x192.png +0 -0
- data/assets/favicon/android-chrome-512x512.png +0 -0
- data/assets/favicon/apple-touch-icon.png +0 -0
- data/assets/favicon/browserconfig.xml +9 -0
- data/assets/favicon/favicon-16x16.png +0 -0
- data/assets/favicon/favicon-32x32.png +0 -0
- data/assets/favicon/favicon.ico +0 -0
- data/assets/favicon/favicon.svg +1 -0
- data/assets/favicon/mstile-150x150.png +0 -0
- data/assets/favicon/safari-pinned-tab.svg +88 -0
- data/assets/favicon/site.webmanifest +19 -0
- data/assets/images/about-me.jpg +0 -0
- data/assets/images/posts/default-post-img.jpg +0 -0
- data/assets/images/posts/text-syntax.jpg +0 -0
- data/assets/images/posts/welcome.jpg +0 -0
- data/assets/images/profile.png +0 -0
- data/assets/images/promo-banner.jpg +0 -0
- data/assets/js/blog.js +9 -0
- data/assets/js/demo/style-switcher.js +45 -0
- data/assets/logo/logo.jpg +0 -0
- data/assets/logo/logo.svg +1 -0
- data/assets/plugins/bootstrap/js/bootstrap.min.js +7 -0
- data/assets/plugins/jquery-3.3.1.min.js +2 -0
- data/assets/plugins/popper.min.js +5 -0
- data/assets/resume/resume.pdf +0 -0
- data/assets/scss/bootstrap/js/dist/alert.js +199 -0
- data/assets/scss/bootstrap/js/dist/alert.js.map +1 -0
- data/assets/scss/bootstrap/js/dist/button.js +187 -0
- data/assets/scss/bootstrap/js/dist/button.js.map +1 -0
- data/assets/scss/bootstrap/js/dist/carousel.js +668 -0
- data/assets/scss/bootstrap/js/dist/carousel.js.map +1 -0
- data/assets/scss/bootstrap/js/dist/collapse.js +428 -0
- data/assets/scss/bootstrap/js/dist/collapse.js.map +1 -0
- data/assets/scss/bootstrap/js/dist/dropdown.js +595 -0
- data/assets/scss/bootstrap/js/dist/dropdown.js.map +1 -0
- data/assets/scss/bootstrap/js/dist/index.js +23 -0
- data/assets/scss/bootstrap/js/dist/index.js.map +1 -0
- data/assets/scss/bootstrap/js/dist/modal.js +650 -0
- data/assets/scss/bootstrap/js/dist/modal.js.map +1 -0
- data/assets/scss/bootstrap/js/dist/popover.js +261 -0
- data/assets/scss/bootstrap/js/dist/popover.js.map +1 -0
- data/assets/scss/bootstrap/js/dist/scrollspy.js +375 -0
- data/assets/scss/bootstrap/js/dist/scrollspy.js.map +1 -0
- data/assets/scss/bootstrap/js/dist/tab.js +269 -0
- data/assets/scss/bootstrap/js/dist/tab.js.map +1 -0
- data/assets/scss/bootstrap/js/dist/toast.js +283 -0
- data/assets/scss/bootstrap/js/dist/toast.js.map +1 -0
- data/assets/scss/bootstrap/js/dist/tooltip.js +760 -0
- data/assets/scss/bootstrap/js/dist/tooltip.js.map +1 -0
- data/assets/scss/bootstrap/js/dist/util.js +172 -0
- data/assets/scss/bootstrap/js/dist/util.js.map +1 -0
- data/assets/scss/bootstrap/js/src/alert.js +179 -0
- data/assets/scss/bootstrap/js/src/button.js +171 -0
- data/assets/scss/bootstrap/js/src/carousel.js +606 -0
- data/assets/scss/bootstrap/js/src/collapse.js +402 -0
- data/assets/scss/bootstrap/js/src/dropdown.js +545 -0
- data/assets/scss/bootstrap/js/src/index.js +52 -0
- data/assets/scss/bootstrap/js/src/modal.js +594 -0
- data/assets/scss/bootstrap/js/src/popover.js +184 -0
- data/assets/scss/bootstrap/js/src/scrollspy.js +326 -0
- data/assets/scss/bootstrap/js/src/tab.js +260 -0
- data/assets/scss/bootstrap/js/src/toast.js +227 -0
- data/assets/scss/bootstrap/js/src/tooltip.js +752 -0
- data/assets/scss/bootstrap/js/src/util.js +177 -0
- data/assets/scss/bootstrap/js/tests/README.md +69 -0
- data/assets/scss/bootstrap/js/tests/browsers.js +82 -0
- data/assets/scss/bootstrap/js/tests/index.html +133 -0
- data/assets/scss/bootstrap/js/tests/integration/bundle.js +8 -0
- data/assets/scss/bootstrap/js/tests/integration/index.html +66 -0
- data/assets/scss/bootstrap/js/tests/integration/rollup.bundle.js +20 -0
- data/assets/scss/bootstrap/js/tests/karma.conf.js +143 -0
- data/assets/scss/bootstrap/js/tests/unit/.eslintrc.json +40 -0
- data/assets/scss/bootstrap/js/tests/unit/alert.js +123 -0
- data/assets/scss/bootstrap/js/tests/unit/button.js +222 -0
- data/assets/scss/bootstrap/js/tests/unit/carousel.js +1333 -0
- data/assets/scss/bootstrap/js/tests/unit/collapse.js +892 -0
- data/assets/scss/bootstrap/js/tests/unit/dropdown.js +1419 -0
- data/assets/scss/bootstrap/js/tests/unit/modal.js +815 -0
- data/assets/scss/bootstrap/js/tests/unit/popover.js +471 -0
- data/assets/scss/bootstrap/js/tests/unit/scrollspy.js +728 -0
- data/assets/scss/bootstrap/js/tests/unit/tab.js +518 -0
- data/assets/scss/bootstrap/js/tests/unit/toast.js +259 -0
- data/assets/scss/bootstrap/js/tests/unit/tooltip.js +1109 -0
- data/assets/scss/bootstrap/js/tests/unit/util.js +163 -0
- data/assets/scss/bootstrap/js/tests/visual/alert.html +58 -0
- data/assets/scss/bootstrap/js/tests/visual/button.html +51 -0
- data/assets/scss/bootstrap/js/tests/visual/carousel.html +66 -0
- data/assets/scss/bootstrap/js/tests/visual/collapse.html +78 -0
- data/assets/scss/bootstrap/js/tests/visual/dropdown.html +212 -0
- data/assets/scss/bootstrap/js/tests/visual/modal.html +268 -0
- data/assets/scss/bootstrap/js/tests/visual/popover.html +46 -0
- data/assets/scss/bootstrap/js/tests/visual/scrollspy.html +95 -0
- data/assets/scss/bootstrap/js/tests/visual/tab.html +234 -0
- data/assets/scss/bootstrap/js/tests/visual/toast.html +72 -0
- data/assets/scss/bootstrap/js/tests/visual/tooltip.html +106 -0
- data/assets/scss/bootstrap/scss/_alert.scss +51 -0
- data/assets/scss/bootstrap/scss/_badge.scss +54 -0
- data/assets/scss/bootstrap/scss/_breadcrumb.scss +41 -0
- data/assets/scss/bootstrap/scss/_button-group.scss +163 -0
- data/assets/scss/bootstrap/scss/_buttons.scss +137 -0
- data/assets/scss/bootstrap/scss/_card.scss +289 -0
- data/assets/scss/bootstrap/scss/_carousel.scss +197 -0
- data/assets/scss/bootstrap/scss/_close.scss +41 -0
- data/assets/scss/bootstrap/scss/_code.scss +48 -0
- data/assets/scss/bootstrap/scss/_custom-forms.scss +507 -0
- data/assets/scss/bootstrap/scss/_dropdown.scss +191 -0
- data/assets/scss/bootstrap/scss/_forms.scss +330 -0
- data/assets/scss/bootstrap/scss/_functions.scss +86 -0
- data/assets/scss/bootstrap/scss/_grid.scss +52 -0
- data/assets/scss/bootstrap/scss/_images.scss +42 -0
- data/assets/scss/bootstrap/scss/_input-group.scss +193 -0
- data/assets/scss/bootstrap/scss/_jumbotron.scss +17 -0
- data/assets/scss/bootstrap/scss/_list-group.scss +149 -0
- data/assets/scss/bootstrap/scss/_media.scss +8 -0
- data/assets/scss/bootstrap/scss/_mixins.scss +47 -0
- data/assets/scss/bootstrap/scss/_modal.scss +229 -0
- data/assets/scss/bootstrap/scss/_nav.scss +120 -0
- data/assets/scss/bootstrap/scss/_navbar.scss +294 -0
- data/assets/scss/bootstrap/scss/_pagination.scss +73 -0
- data/assets/scss/bootstrap/scss/_popover.scss +171 -0
- data/assets/scss/bootstrap/scss/_print.scss +141 -0
- data/assets/scss/bootstrap/scss/_progress.scss +43 -0
- data/assets/scss/bootstrap/scss/_reboot.scss +483 -0
- data/assets/scss/bootstrap/scss/_root.scss +19 -0
- data/assets/scss/bootstrap/scss/_spinners.scss +55 -0
- data/assets/scss/bootstrap/scss/_tables.scss +185 -0
- data/assets/scss/bootstrap/scss/_toasts.scss +44 -0
- data/assets/scss/bootstrap/scss/_tooltip.scss +115 -0
- data/assets/scss/bootstrap/scss/_transitions.scss +20 -0
- data/assets/scss/bootstrap/scss/_type.scss +125 -0
- data/assets/scss/bootstrap/scss/_utilities.scss +17 -0
- data/assets/scss/bootstrap/scss/_variables.scss +1123 -0
- data/assets/scss/bootstrap/scss/bootstrap-grid.scss +29 -0
- data/assets/scss/bootstrap/scss/bootstrap-reboot.scss +12 -0
- data/assets/scss/bootstrap/scss/bootstrap.scss +44 -0
- data/assets/scss/bootstrap/scss/mixins/_alert.scss +13 -0
- data/assets/scss/bootstrap/scss/mixins/_background-variant.scss +21 -0
- data/assets/scss/bootstrap/scss/mixins/_badge.scss +17 -0
- data/assets/scss/bootstrap/scss/mixins/_border-radius.scss +63 -0
- data/assets/scss/bootstrap/scss/mixins/_box-shadow.scss +20 -0
- data/assets/scss/bootstrap/scss/mixins/_breakpoints.scss +123 -0
- data/assets/scss/bootstrap/scss/mixins/_buttons.scss +107 -0
- data/assets/scss/bootstrap/scss/mixins/_caret.scss +62 -0
- data/assets/scss/bootstrap/scss/mixins/_clearfix.scss +7 -0
- data/assets/scss/bootstrap/scss/mixins/_deprecate.scss +10 -0
- data/assets/scss/bootstrap/scss/mixins/_float.scss +14 -0
- data/assets/scss/bootstrap/scss/mixins/_forms.scss +192 -0
- data/assets/scss/bootstrap/scss/mixins/_gradients.scss +45 -0
- data/assets/scss/bootstrap/scss/mixins/_grid-framework.scss +66 -0
- data/assets/scss/bootstrap/scss/mixins/_grid.scss +51 -0
- data/assets/scss/bootstrap/scss/mixins/_hover.scss +37 -0
- data/assets/scss/bootstrap/scss/mixins/_image.scss +36 -0
- data/assets/scss/bootstrap/scss/mixins/_list-group.scss +21 -0
- data/assets/scss/bootstrap/scss/mixins/_lists.scss +7 -0
- data/assets/scss/bootstrap/scss/mixins/_nav-divider.scss +10 -0
- data/assets/scss/bootstrap/scss/mixins/_pagination.scss +22 -0
- data/assets/scss/bootstrap/scss/mixins/_reset-text.scss +17 -0
- data/assets/scss/bootstrap/scss/mixins/_resize.scss +6 -0
- data/assets/scss/bootstrap/scss/mixins/_screen-reader.scss +33 -0
- data/assets/scss/bootstrap/scss/mixins/_size.scss +7 -0
- data/assets/scss/bootstrap/scss/mixins/_table-row.scss +39 -0
- data/assets/scss/bootstrap/scss/mixins/_text-emphasis.scss +16 -0
- data/assets/scss/bootstrap/scss/mixins/_text-hide.scss +11 -0
- data/assets/scss/bootstrap/scss/mixins/_text-truncate.scss +8 -0
- data/assets/scss/bootstrap/scss/mixins/_transition.scss +16 -0
- data/assets/scss/bootstrap/scss/mixins/_visibility.scss +8 -0
- data/assets/scss/bootstrap/scss/utilities/_align.scss +8 -0
- data/assets/scss/bootstrap/scss/utilities/_background.scss +19 -0
- data/assets/scss/bootstrap/scss/utilities/_borders.scss +75 -0
- data/assets/scss/bootstrap/scss/utilities/_clearfix.scss +3 -0
- data/assets/scss/bootstrap/scss/utilities/_display.scss +26 -0
- data/assets/scss/bootstrap/scss/utilities/_embed.scss +39 -0
- data/assets/scss/bootstrap/scss/utilities/_flex.scss +51 -0
- data/assets/scss/bootstrap/scss/utilities/_float.scss +11 -0
- data/assets/scss/bootstrap/scss/utilities/_overflow.scss +5 -0
- data/assets/scss/bootstrap/scss/utilities/_position.scss +32 -0
- data/assets/scss/bootstrap/scss/utilities/_screenreaders.scss +11 -0
- data/assets/scss/bootstrap/scss/utilities/_shadows.scss +6 -0
- data/assets/scss/bootstrap/scss/utilities/_sizing.scss +20 -0
- data/assets/scss/bootstrap/scss/utilities/_spacing.scss +73 -0
- data/assets/scss/bootstrap/scss/utilities/_stretched-link.scss +19 -0
- data/assets/scss/bootstrap/scss/utilities/_text.scss +72 -0
- data/assets/scss/bootstrap/scss/utilities/_visibility.scss +13 -0
- data/assets/scss/bootstrap/scss/vendor/_rfs.scss +212 -0
- data/assets/scss/theme/_about.scss +28 -0
- data/assets/scss/theme/_base.scss +207 -0
- data/assets/scss/theme/_blog.scss +140 -0
- data/assets/scss/theme/_demo.scss +153 -0
- data/assets/scss/theme/_mixins.scss +34 -0
- data/assets/scss/theme/_responsive.scss +88 -0
- data/assets/scss/theme/styles.scss +14 -0
- data/assets/scss/theme-8.scss +41 -0
- data/assets/styles.scss +6 -0
- metadata +221 -4
@@ -0,0 +1,177 @@
|
|
1
|
+
/**
|
2
|
+
* --------------------------------------------------------------------------
|
3
|
+
* Bootstrap (v4.3.0): util.js
|
4
|
+
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
5
|
+
* --------------------------------------------------------------------------
|
6
|
+
*/
|
7
|
+
|
8
|
+
import $ from 'jquery'
|
9
|
+
|
10
|
+
/**
|
11
|
+
* ------------------------------------------------------------------------
|
12
|
+
* Private TransitionEnd Helpers
|
13
|
+
* ------------------------------------------------------------------------
|
14
|
+
*/
|
15
|
+
|
16
|
+
const TRANSITION_END = 'transitionend'
|
17
|
+
const MAX_UID = 1000000
|
18
|
+
const MILLISECONDS_MULTIPLIER = 1000
|
19
|
+
|
20
|
+
// Shoutout AngusCroll (https://goo.gl/pxwQGp)
|
21
|
+
function toType(obj) {
|
22
|
+
return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase()
|
23
|
+
}
|
24
|
+
|
25
|
+
function getSpecialTransitionEndEvent() {
|
26
|
+
return {
|
27
|
+
bindType: TRANSITION_END,
|
28
|
+
delegateType: TRANSITION_END,
|
29
|
+
handle(event) {
|
30
|
+
if ($(event.target).is(this)) {
|
31
|
+
return event.handleObj.handler.apply(this, arguments) // eslint-disable-line prefer-rest-params
|
32
|
+
}
|
33
|
+
return undefined // eslint-disable-line no-undefined
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
function transitionEndEmulator(duration) {
|
39
|
+
let called = false
|
40
|
+
|
41
|
+
$(this).one(Util.TRANSITION_END, () => {
|
42
|
+
called = true
|
43
|
+
})
|
44
|
+
|
45
|
+
setTimeout(() => {
|
46
|
+
if (!called) {
|
47
|
+
Util.triggerTransitionEnd(this)
|
48
|
+
}
|
49
|
+
}, duration)
|
50
|
+
|
51
|
+
return this
|
52
|
+
}
|
53
|
+
|
54
|
+
function setTransitionEndSupport() {
|
55
|
+
$.fn.emulateTransitionEnd = transitionEndEmulator
|
56
|
+
$.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent()
|
57
|
+
}
|
58
|
+
|
59
|
+
/**
|
60
|
+
* --------------------------------------------------------------------------
|
61
|
+
* Public Util Api
|
62
|
+
* --------------------------------------------------------------------------
|
63
|
+
*/
|
64
|
+
|
65
|
+
const Util = {
|
66
|
+
|
67
|
+
TRANSITION_END: 'bsTransitionEnd',
|
68
|
+
|
69
|
+
getUID(prefix) {
|
70
|
+
do {
|
71
|
+
// eslint-disable-next-line no-bitwise
|
72
|
+
prefix += ~~(Math.random() * MAX_UID) // "~~" acts like a faster Math.floor() here
|
73
|
+
} while (document.getElementById(prefix))
|
74
|
+
return prefix
|
75
|
+
},
|
76
|
+
|
77
|
+
getSelectorFromElement(element) {
|
78
|
+
let selector = element.getAttribute('data-target')
|
79
|
+
|
80
|
+
if (!selector || selector === '#') {
|
81
|
+
const hrefAttr = element.getAttribute('href')
|
82
|
+
selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : ''
|
83
|
+
}
|
84
|
+
|
85
|
+
try {
|
86
|
+
return document.querySelector(selector) ? selector : null
|
87
|
+
} catch (err) {
|
88
|
+
return null
|
89
|
+
}
|
90
|
+
},
|
91
|
+
|
92
|
+
getTransitionDurationFromElement(element) {
|
93
|
+
if (!element) {
|
94
|
+
return 0
|
95
|
+
}
|
96
|
+
|
97
|
+
// Get transition-duration of the element
|
98
|
+
let transitionDuration = $(element).css('transition-duration')
|
99
|
+
let transitionDelay = $(element).css('transition-delay')
|
100
|
+
|
101
|
+
const floatTransitionDuration = parseFloat(transitionDuration)
|
102
|
+
const floatTransitionDelay = parseFloat(transitionDelay)
|
103
|
+
|
104
|
+
// Return 0 if element or transition duration is not found
|
105
|
+
if (!floatTransitionDuration && !floatTransitionDelay) {
|
106
|
+
return 0
|
107
|
+
}
|
108
|
+
|
109
|
+
// If multiple durations are defined, take the first
|
110
|
+
transitionDuration = transitionDuration.split(',')[0]
|
111
|
+
transitionDelay = transitionDelay.split(',')[0]
|
112
|
+
|
113
|
+
return (parseFloat(transitionDuration) + parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER
|
114
|
+
},
|
115
|
+
|
116
|
+
reflow(element) {
|
117
|
+
return element.offsetHeight
|
118
|
+
},
|
119
|
+
|
120
|
+
triggerTransitionEnd(element) {
|
121
|
+
$(element).trigger(TRANSITION_END)
|
122
|
+
},
|
123
|
+
|
124
|
+
// TODO: Remove in v5
|
125
|
+
supportsTransitionEnd() {
|
126
|
+
return Boolean(TRANSITION_END)
|
127
|
+
},
|
128
|
+
|
129
|
+
isElement(obj) {
|
130
|
+
return (obj[0] || obj).nodeType
|
131
|
+
},
|
132
|
+
|
133
|
+
typeCheckConfig(componentName, config, configTypes) {
|
134
|
+
for (const property in configTypes) {
|
135
|
+
if (Object.prototype.hasOwnProperty.call(configTypes, property)) {
|
136
|
+
const expectedTypes = configTypes[property]
|
137
|
+
const value = config[property]
|
138
|
+
const valueType = value && Util.isElement(value)
|
139
|
+
? 'element' : toType(value)
|
140
|
+
|
141
|
+
if (!new RegExp(expectedTypes).test(valueType)) {
|
142
|
+
throw new Error(
|
143
|
+
`${componentName.toUpperCase()}: ` +
|
144
|
+
`Option "${property}" provided type "${valueType}" ` +
|
145
|
+
`but expected type "${expectedTypes}".`)
|
146
|
+
}
|
147
|
+
}
|
148
|
+
}
|
149
|
+
},
|
150
|
+
|
151
|
+
findShadowRoot(element) {
|
152
|
+
if (!document.documentElement.attachShadow) {
|
153
|
+
return null
|
154
|
+
}
|
155
|
+
|
156
|
+
// Can find the shadow root otherwise it'll return the document
|
157
|
+
if (typeof element.getRootNode === 'function') {
|
158
|
+
const root = element.getRootNode()
|
159
|
+
return root instanceof ShadowRoot ? root : null
|
160
|
+
}
|
161
|
+
|
162
|
+
if (element instanceof ShadowRoot) {
|
163
|
+
return element
|
164
|
+
}
|
165
|
+
|
166
|
+
// when we don't find a shadow root
|
167
|
+
if (!element.parentNode) {
|
168
|
+
return null
|
169
|
+
}
|
170
|
+
|
171
|
+
return Util.findShadowRoot(element.parentNode)
|
172
|
+
}
|
173
|
+
}
|
174
|
+
|
175
|
+
setTransitionEndSupport()
|
176
|
+
|
177
|
+
export default Util
|
@@ -0,0 +1,69 @@
|
|
1
|
+
## How does Bootstrap's test suite work?
|
2
|
+
|
3
|
+
Bootstrap uses [QUnit](https://qunitjs.com/) and [Sinon](https://sinonjs.org/). Each plugin has a file dedicated to its tests in `unit/<plugin-name>.js`.
|
4
|
+
|
5
|
+
* `unit/` contains the unit test files for each Bootstrap plugin.
|
6
|
+
* `vendor/` contains third-party testing-related code (QUnit, jQuery and Sinon).
|
7
|
+
* `visual/` contains "visual" tests which are run interactively in real browsers and require manual verification by humans.
|
8
|
+
|
9
|
+
To run the unit test suite via [Karma](https://karma-runner.github.io/), run `npm run js-test`.
|
10
|
+
|
11
|
+
To run the unit test suite via a real web browser, open `index.html` in the browser.
|
12
|
+
|
13
|
+
|
14
|
+
## How do I add a new unit test?
|
15
|
+
|
16
|
+
1. Locate and open the file dedicated to the plugin which you need to add tests to (`unit/<plugin-name>.js`).
|
17
|
+
2. Review the [QUnit API Documentation](https://api.qunitjs.com/) and use the existing tests as references for how to structure your new tests.
|
18
|
+
3. Write the necessary unit test(s) for the new or revised functionality.
|
19
|
+
4. Run `npm run js-test` to see the results of your newly-added test(s).
|
20
|
+
|
21
|
+
**Note:** Your new unit tests should fail before your changes are applied to the plugin, and should pass after your changes are applied to the plugin.
|
22
|
+
|
23
|
+
## What should a unit test look like?
|
24
|
+
|
25
|
+
* Each test should have a unique name clearly stating what unit is being tested.
|
26
|
+
* Each test should test only one unit per test, although one test can include several assertions. Create multiple tests for multiple units of functionality.
|
27
|
+
* Each test should begin with [`assert.expect`](https://api.qunitjs.com/assert/expect/) to ensure that the expected assertions are run.
|
28
|
+
* Each test should follow the project's [JavaScript Code Guidelines](https://github.com/twbs/bootstrap/blob/master/CONTRIBUTING.md#js)
|
29
|
+
|
30
|
+
## Code coverage
|
31
|
+
|
32
|
+
Currently we're aiming for at least 80% test coverage for our code. To ensure your changes meet or exceed this limit, run `npm run js-compile && npm run js-test` and open the file in `js/coverage/lcov-report/index.html` to see the code coverage for each plugin. See more details when you select a plugin and ensure your change is fully covered by unit tests.
|
33
|
+
|
34
|
+
### Example tests
|
35
|
+
|
36
|
+
```js
|
37
|
+
// Synchronous test
|
38
|
+
QUnit.test('should describe the unit being tested', function (assert) {
|
39
|
+
assert.expect(1)
|
40
|
+
var templateHTML = '<div class="alert alert-danger fade show">' +
|
41
|
+
'<a class="close" href="#" data-dismiss="alert">×</a>' +
|
42
|
+
'<p><strong>Template necessary for the test.</p>' +
|
43
|
+
'</div>'
|
44
|
+
var $alert = $(templateHTML).appendTo('#qunit-fixture').bootstrapAlert()
|
45
|
+
|
46
|
+
$alert.find('.close').trigger('click')
|
47
|
+
|
48
|
+
// Make assertion
|
49
|
+
assert.strictEqual($alert.hasClass('show'), false, 'remove .show class on .close click')
|
50
|
+
})
|
51
|
+
|
52
|
+
// Asynchronous test
|
53
|
+
QUnit.test('should describe the unit being tested', function (assert) {
|
54
|
+
assert.expect(2)
|
55
|
+
var done = assert.async()
|
56
|
+
|
57
|
+
var $tooltip = $('<div title="tooltip title"></div>').bootstrapTooltip()
|
58
|
+
var tooltipInstance = $tooltip.data('bs.tooltip')
|
59
|
+
var spyShow = sinon.spy(tooltipInstance, 'show')
|
60
|
+
|
61
|
+
$tooltip.appendTo('#qunit-fixture')
|
62
|
+
.on('shown.bs.tooltip', function () {
|
63
|
+
assert.ok(true, '"shown" event was fired after calling "show"')
|
64
|
+
assert.ok(spyShow.called, 'show called')
|
65
|
+
done()
|
66
|
+
})
|
67
|
+
.bootstrapTooltip('show')
|
68
|
+
})
|
69
|
+
```
|
@@ -0,0 +1,82 @@
|
|
1
|
+
/* eslint-env node */
|
2
|
+
/* eslint-disable camelcase */
|
3
|
+
|
4
|
+
const browsers = {
|
5
|
+
safariMac: {
|
6
|
+
base: 'BrowserStack',
|
7
|
+
os: 'OS X',
|
8
|
+
os_version: 'High Sierra',
|
9
|
+
browser: 'Safari',
|
10
|
+
browser_version: 'latest'
|
11
|
+
},
|
12
|
+
chromeMac: {
|
13
|
+
base: 'BrowserStack',
|
14
|
+
os: 'OS X',
|
15
|
+
os_version: 'High Sierra',
|
16
|
+
browser : 'Chrome',
|
17
|
+
browser_version : 'latest'
|
18
|
+
},
|
19
|
+
firefoxMac: {
|
20
|
+
base: 'BrowserStack',
|
21
|
+
os: 'OS X',
|
22
|
+
os_version: 'High Sierra',
|
23
|
+
browser: 'Firefox',
|
24
|
+
browser_version: 'latest'
|
25
|
+
},
|
26
|
+
edgeWin10: {
|
27
|
+
base: 'BrowserStack',
|
28
|
+
os: 'Windows',
|
29
|
+
os_version: '10',
|
30
|
+
browser: 'Edge',
|
31
|
+
browser_version: 'latest'
|
32
|
+
},
|
33
|
+
ie11Win10: {
|
34
|
+
base: 'BrowserStack',
|
35
|
+
os: 'Windows',
|
36
|
+
os_version: '10',
|
37
|
+
browser: 'IE',
|
38
|
+
browser_version: '11.0'
|
39
|
+
},
|
40
|
+
chromeWin10: {
|
41
|
+
base: 'BrowserStack',
|
42
|
+
os: 'Windows',
|
43
|
+
os_version: '10',
|
44
|
+
browser: 'Chrome',
|
45
|
+
browser_version: 'latest'
|
46
|
+
},
|
47
|
+
firefoxWin10: {
|
48
|
+
base: 'BrowserStack',
|
49
|
+
os: 'Windows',
|
50
|
+
os_version: '10',
|
51
|
+
browser: 'Firefox',
|
52
|
+
browser_version: 'latest'
|
53
|
+
},
|
54
|
+
ie10Win8: {
|
55
|
+
base: 'BrowserStack',
|
56
|
+
os: 'Windows',
|
57
|
+
os_version: '8',
|
58
|
+
browser: 'IE',
|
59
|
+
browser_version: '10.0'
|
60
|
+
},
|
61
|
+
iphoneX: {
|
62
|
+
base: 'BrowserStack',
|
63
|
+
os: 'ios',
|
64
|
+
os_version: '11.0',
|
65
|
+
device: 'iPhone X',
|
66
|
+
real_mobile: true
|
67
|
+
},
|
68
|
+
pixel2: {
|
69
|
+
base: 'BrowserStack',
|
70
|
+
os: 'android',
|
71
|
+
os_version: '8.0',
|
72
|
+
device: 'Google Pixel 2',
|
73
|
+
real_mobile: true
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
const browsersKeys = Object.keys(browsers)
|
78
|
+
|
79
|
+
module.exports = {
|
80
|
+
browsers,
|
81
|
+
browsersKeys
|
82
|
+
}
|
@@ -0,0 +1,133 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
6
|
+
<title>Bootstrap Plugin Test Suite</title>
|
7
|
+
|
8
|
+
<!-- jQuery -->
|
9
|
+
<script src="../../node_modules/jquery/dist/jquery.slim.min.js"></script>
|
10
|
+
<script src="../../node_modules/popper.js/dist/umd/popper.min.js"></script>
|
11
|
+
|
12
|
+
<!-- QUnit -->
|
13
|
+
<link rel="stylesheet" href="../../node_modules/qunit/qunit/qunit.css" media="screen">
|
14
|
+
<script src="../../node_modules/qunit/qunit/qunit.js"></script>
|
15
|
+
|
16
|
+
<!-- Sinon -->
|
17
|
+
<script src="../../node_modules/sinon/pkg/sinon-no-sourcemaps.js"></script>
|
18
|
+
|
19
|
+
<!-- Hammer simulator -->
|
20
|
+
<script src="../../node_modules/hammer-simulator/index.js"></script>
|
21
|
+
|
22
|
+
<script>
|
23
|
+
// Disable jQuery event aliases to ensure we don't accidentally use any of them
|
24
|
+
[
|
25
|
+
'blur',
|
26
|
+
'focus',
|
27
|
+
'focusin',
|
28
|
+
'focusout',
|
29
|
+
'resize',
|
30
|
+
'scroll',
|
31
|
+
'click',
|
32
|
+
'dblclick',
|
33
|
+
'mousedown',
|
34
|
+
'mouseup',
|
35
|
+
'mousemove',
|
36
|
+
'mouseover',
|
37
|
+
'mouseout',
|
38
|
+
'mouseenter',
|
39
|
+
'mouseleave',
|
40
|
+
'change',
|
41
|
+
'select',
|
42
|
+
'submit',
|
43
|
+
'keydown',
|
44
|
+
'keypress',
|
45
|
+
'keyup',
|
46
|
+
'contextmenu'
|
47
|
+
].forEach(function(eventAlias) {
|
48
|
+
$.fn[eventAlias] = function() {
|
49
|
+
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')
|
50
|
+
}
|
51
|
+
})
|
52
|
+
|
53
|
+
// Require assert.expect in each test
|
54
|
+
QUnit.config.requireExpects = true
|
55
|
+
|
56
|
+
// See https://github.com/axemclion/grunt-saucelabs#test-result-details-with-qunit
|
57
|
+
var log = []
|
58
|
+
var testName
|
59
|
+
|
60
|
+
QUnit.done(function(testResults) {
|
61
|
+
var tests = []
|
62
|
+
for (var i = 0; i < log.length; i++) {
|
63
|
+
var details = log[i]
|
64
|
+
tests.push({
|
65
|
+
name: details.name,
|
66
|
+
result: details.result,
|
67
|
+
expected: details.expected,
|
68
|
+
actual: details.actual,
|
69
|
+
source: details.source
|
70
|
+
})
|
71
|
+
}
|
72
|
+
testResults.tests = tests
|
73
|
+
|
74
|
+
window.global_test_results = testResults
|
75
|
+
})
|
76
|
+
|
77
|
+
QUnit.testStart(function(testDetails) {
|
78
|
+
QUnit.log(function(details) {
|
79
|
+
if (!details.result) {
|
80
|
+
details.name = testDetails.name
|
81
|
+
log.push(details)
|
82
|
+
}
|
83
|
+
})
|
84
|
+
})
|
85
|
+
|
86
|
+
// Display fixture on-screen on iOS to avoid false positives
|
87
|
+
// See https://github.com/twbs/bootstrap/pull/15955
|
88
|
+
if (/iPhone|iPad|iPod/.test(navigator.userAgent)) {
|
89
|
+
QUnit.begin(function() {
|
90
|
+
$('#qunit-fixture').css({ top: 0, left: 0 })
|
91
|
+
})
|
92
|
+
|
93
|
+
QUnit.done(function() {
|
94
|
+
$('#qunit-fixture').css({ top: '', left: '' })
|
95
|
+
})
|
96
|
+
}
|
97
|
+
</script>
|
98
|
+
|
99
|
+
<!-- Transpiled Plugins -->
|
100
|
+
<script src="../dist/util.js"></script>
|
101
|
+
<script src="../dist/alert.js"></script>
|
102
|
+
<script src="../dist/button.js"></script>
|
103
|
+
<script src="../dist/carousel.js"></script>
|
104
|
+
<script src="../dist/collapse.js"></script>
|
105
|
+
<script src="../dist/dropdown.js"></script>
|
106
|
+
<script src="../dist/modal.js"></script>
|
107
|
+
<script src="../dist/scrollspy.js"></script>
|
108
|
+
<script src="../dist/tab.js"></script>
|
109
|
+
<script src="../dist/tooltip.js"></script>
|
110
|
+
<script src="../dist/popover.js"></script>
|
111
|
+
<script src="../dist/toast.js"></script>
|
112
|
+
|
113
|
+
<!-- Unit Tests -->
|
114
|
+
<script src="unit/alert.js"></script>
|
115
|
+
<script src="unit/button.js"></script>
|
116
|
+
<script src="unit/carousel.js"></script>
|
117
|
+
<script src="unit/collapse.js"></script>
|
118
|
+
<script src="unit/dropdown.js"></script>
|
119
|
+
<script src="unit/modal.js"></script>
|
120
|
+
<script src="unit/scrollspy.js"></script>
|
121
|
+
<script src="unit/tab.js"></script>
|
122
|
+
<script src="unit/tooltip.js"></script>
|
123
|
+
<script src="unit/popover.js"></script>
|
124
|
+
<script src="unit/util.js"></script>
|
125
|
+
<script src="unit/toast.js"></script>
|
126
|
+
</head>
|
127
|
+
<body>
|
128
|
+
<div id="qunit-container">
|
129
|
+
<div id="qunit"></div>
|
130
|
+
<div id="qunit-fixture"></div>
|
131
|
+
</div>
|
132
|
+
</body>
|
133
|
+
</html>
|
@@ -0,0 +1,66 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<!-- Required meta tags -->
|
5
|
+
<meta charset="utf-8">
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
7
|
+
|
8
|
+
<!-- Bootstrap CSS -->
|
9
|
+
<link rel="stylesheet" href="../../../dist/css/bootstrap.min.css">
|
10
|
+
|
11
|
+
<title>Hello, world!</title>
|
12
|
+
</head>
|
13
|
+
<body>
|
14
|
+
<div class="container">
|
15
|
+
<h1>Hello, world!</h1>
|
16
|
+
<div class="col-12">
|
17
|
+
<div class="mt-5 mb-3">
|
18
|
+
<span>Util.getUID: </span>
|
19
|
+
<span id="resultUID"></span>
|
20
|
+
</div>
|
21
|
+
<button type="button" class="btn btn-secondary" data-toggle="tooltip" data-placement="top" title="Tooltip on top">
|
22
|
+
Tooltip on top
|
23
|
+
</button>
|
24
|
+
<div id="carouselExampleCaptions" class="carousel slide mt-2" data-ride="carousel">
|
25
|
+
<ol class="carousel-indicators">
|
26
|
+
<li data-target="#carouselExampleCaptions" data-slide-to="0"></li>
|
27
|
+
<li data-target="#carouselExampleCaptions" data-slide-to="1" class="active"></li>
|
28
|
+
<li data-target="#carouselExampleCaptions" data-slide-to="2"></li>
|
29
|
+
</ol>
|
30
|
+
<div class="carousel-inner">
|
31
|
+
<div class="carousel-item">
|
32
|
+
<img class="d-block w-100" data-src="holder.js/800x400?auto=yes&bg=777&fg=555&text=First slide" alt="First slide [800x400]" src="data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22800%22%20height%3D%22400%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20800%20400%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_167a6f826cb%20text%20%7B%20fill%3A%23555%3Bfont-weight%3Anormal%3Bfont-family%3AHelvetica%2C%20monospace%3Bfont-size%3A40pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_167a6f826cb%22%3E%3Crect%20width%3D%22800%22%20height%3D%22400%22%20fill%3D%22%23777%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%22285.921875%22%20y%3D%22217.7%22%3EFirst%20slide%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E" data-holder-rendered="true">
|
33
|
+
<div class="carousel-caption d-none d-md-block">
|
34
|
+
<h5>First slide label</h5>
|
35
|
+
<p>Nulla vitae elit libero, a pharetra augue mollis interdum.</p>
|
36
|
+
</div>
|
37
|
+
</div>
|
38
|
+
<div class="carousel-item active">
|
39
|
+
<img class="d-block w-100" data-src="holder.js/800x400?auto=yes&bg=666&fg=444&text=Second slide" alt="Second slide [800x400]" src="data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22800%22%20height%3D%22400%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20800%20400%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_167a6f826ce%20text%20%7B%20fill%3A%23444%3Bfont-weight%3Anormal%3Bfont-family%3AHelvetica%2C%20monospace%3Bfont-size%3A40pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_167a6f826ce%22%3E%3Crect%20width%3D%22800%22%20height%3D%22400%22%20fill%3D%22%23666%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%22247.3203125%22%20y%3D%22217.7%22%3ESecond%20slide%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E" data-holder-rendered="true">
|
40
|
+
<div class="carousel-caption d-none d-md-block">
|
41
|
+
<h5>Second slide label</h5>
|
42
|
+
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
|
43
|
+
</div>
|
44
|
+
</div>
|
45
|
+
<div class="carousel-item">
|
46
|
+
<img class="d-block w-100" data-src="holder.js/800x400?auto=yes&bg=555&fg=333&text=Third slide" alt="Third slide [800x400]" src="data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22800%22%20height%3D%22400%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20800%20400%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_167a6f826cf%20text%20%7B%20fill%3A%23333%3Bfont-weight%3Anormal%3Bfont-family%3AHelvetica%2C%20monospace%3Bfont-size%3A40pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_167a6f826cf%22%3E%3Crect%20width%3D%22800%22%20height%3D%22400%22%20fill%3D%22%23555%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%22277%22%20y%3D%22217.7%22%3EThird%20slide%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E" data-holder-rendered="true">
|
47
|
+
<div class="carousel-caption d-none d-md-block">
|
48
|
+
<h5>Third slide label</h5>
|
49
|
+
<p>Praesent commodo cursus magna, vel scelerisque nisl consectetur.</p>
|
50
|
+
</div>
|
51
|
+
</div>
|
52
|
+
</div>
|
53
|
+
<a class="carousel-control-prev" href="#carouselExampleCaptions" role="button" data-slide="prev">
|
54
|
+
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
|
55
|
+
<span class="sr-only">Previous</span>
|
56
|
+
</a>
|
57
|
+
<a class="carousel-control-next" href="#carouselExampleCaptions" role="button" data-slide="next">
|
58
|
+
<span class="carousel-control-next-icon" aria-hidden="true"></span>
|
59
|
+
<span class="sr-only">Next</span>
|
60
|
+
</a>
|
61
|
+
</div>
|
62
|
+
</div>
|
63
|
+
</div>
|
64
|
+
<script src="../../coverage/bundle.js"></script>
|
65
|
+
</body>
|
66
|
+
</html>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
/* eslint-env node */
|
2
|
+
|
3
|
+
const resolve = require('rollup-plugin-node-resolve')
|
4
|
+
const commonjs = require('rollup-plugin-commonjs')
|
5
|
+
const babel = require('rollup-plugin-babel')
|
6
|
+
|
7
|
+
module.exports = {
|
8
|
+
input: 'js/tests/integration/bundle.js',
|
9
|
+
output: {
|
10
|
+
file: 'js/coverage/bundle.js',
|
11
|
+
format: 'iife'
|
12
|
+
},
|
13
|
+
plugins: [
|
14
|
+
resolve(),
|
15
|
+
commonjs(),
|
16
|
+
babel({
|
17
|
+
exclude: 'node_modules/**'
|
18
|
+
})
|
19
|
+
]
|
20
|
+
}
|