mirror of
https://github.com/jquery/jquery.git
synced 2024-11-23 02:54:22 +00:00
Build: migrate most grunt tasks off of grunt (3.x)
Close gh-5330 - lint - npmcopy - build, minify, and process for distribution. - new custom build command using yargs - compare size of minified/gzip built files - pretest scripts, including qunit-fixture, babel transpilation, and npmcopy - node smoke tests - promises aplus tests - new watch task using nodemon, which runs `npm run build:all` on `src` changes. Also: - upgraded husky and added the new lint command - updated lint config to use new "flat" config format. See https://eslint.org/docs/latest/use/configure/configuration-files-new - Temporarily disabled one lint rule until flat config is supported by eslint-plugin-import. See https://github.com/import-js/eslint-plugin-import/issues/2556 - committed package-lock.json - updated all test scripts to use the new build - added an express test server that uses middleware-mockserver this can be used to run tests without karma - build-all-variants is now build:all - run pretest script in jenkins --------- Co-authored-by: Michał Gołębiowski-Owczarek <m.goleb@gmail.com>
This commit is contained in:
parent
6fe88690a3
commit
ec8802bafe
@ -10,7 +10,7 @@ charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[package.json]
|
||||
[*.{json,yml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
|
@ -1,17 +0,0 @@
|
||||
external
|
||||
node_modules
|
||||
*.min.js
|
||||
dist/**
|
||||
!dist/jquery.js
|
||||
!dist/jquery.min.js
|
||||
!dist/jquery.slim.js
|
||||
!dist/jquery.slim.min.js
|
||||
test/data/jquery-1.9.1.js
|
||||
test/data/badcall.js
|
||||
test/data/badjson.js
|
||||
test/data/json_obj.js
|
||||
test/data/readywaitasset.js
|
||||
test/data/readywaitloader.js
|
||||
test/data/support/csp.js
|
||||
test/data/support/getComputedSupport.js
|
||||
test/data/core/jquery-iterability-transpiled.js
|
@ -1,32 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
|
||||
"extends": "jquery",
|
||||
|
||||
"reportUnusedDisableDirectives": true,
|
||||
|
||||
// Support: IE <=9 only, Android <=4.0 only
|
||||
// The above browsers are failing a lot of tests in the ES5
|
||||
// test suite at http://test262.ecmascript.org.
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 3
|
||||
},
|
||||
|
||||
// The browser env is not enabled on purpose so that code takes
|
||||
// all browser-only globals from window instead of assuming
|
||||
// they're available as globals. This makes it possible to use
|
||||
// jQuery with tools like jsdom which provide a custom window
|
||||
// implementation.
|
||||
"env": {},
|
||||
|
||||
"globals": {
|
||||
"window": true,
|
||||
"define": true,
|
||||
"module": true
|
||||
},
|
||||
|
||||
"rules": {
|
||||
"one-var": ["error", {"var": "always"}],
|
||||
"strict": ["error", "function"]
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
|
||||
"extends": "jquery",
|
||||
|
||||
"reportUnusedDisableDirectives": true,
|
||||
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2017
|
||||
},
|
||||
|
||||
"env": {
|
||||
"es6": true,
|
||||
"node": true
|
||||
},
|
||||
|
||||
"rules": {
|
||||
"strict": ["error", "global"]
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
|
||||
"extends": "./.eslintrc-node.json"
|
||||
}
|
15
.github/workflows/node.js.yml
vendored
15
.github/workflows/node.js.yml
vendored
@ -40,6 +40,7 @@ jobs:
|
||||
NODE_VERSION: "18.x"
|
||||
NPM_SCRIPT: "test:browser"
|
||||
BROWSERS: "FirefoxHeadless"
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||
@ -61,15 +62,21 @@ jobs:
|
||||
run: |
|
||||
export FIREFOX_SOURCE_URL='https://download.mozilla.org/?product=firefox-esr-latest&lang=en-US&os=linux64'
|
||||
wget --no-verbose $FIREFOX_SOURCE_URL -O - | tar -jx -C ${HOME}
|
||||
if: "contains(matrix.NAME, 'Firefox ESR')"
|
||||
if: contains(matrix.NAME, 'Firefox ESR')
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
npm install
|
||||
run: npm install
|
||||
|
||||
- name: Install Playwright dependencies
|
||||
run: npx playwright-webkit install-deps
|
||||
if: "matrix.NPM_SCRIPT == 'test:browser' && contains(matrix.BROWSERS, 'WebkitHeadless')"
|
||||
if: matrix.NPM_SCRIPT == 'test:browser' && contains(matrix.BROWSERS, 'WebkitHeadless')
|
||||
|
||||
- name: Lint code
|
||||
run: npm run build && npm run lint
|
||||
if: matrix.NODE_VERSION == '18.x'
|
||||
|
||||
- name: Prepare tests
|
||||
run: npm run pretest
|
||||
|
||||
- name: Run tests
|
||||
env:
|
||||
|
7
.gitignore
vendored
7
.gitignore
vendored
@ -8,14 +8,13 @@
|
||||
.bower.json
|
||||
.sizecache.json
|
||||
yarn.lock
|
||||
package-lock.json
|
||||
.eslintcache
|
||||
|
||||
npm-debug.log*
|
||||
|
||||
# Ignore everything in `dist` folder except for the ESLint config
|
||||
/dist/*
|
||||
!/dist/.eslintrc.json
|
||||
/dist
|
||||
|
||||
/external
|
||||
/node_modules
|
||||
|
||||
/test/data/core/jquery-iterability-transpiled.js
|
||||
|
4
.husky/commit-msg
Executable file
4
.husky/commit-msg
Executable file
@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
npx commitplease .git/COMMIT_EDITMSG
|
5
.husky/pre-commit
Executable file
5
.husky/pre-commit
Executable file
@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
npm run lint
|
||||
npm run qunit-fixture
|
@ -1,5 +1,5 @@
|
||||
.eslintignore
|
||||
.eslintrc.json
|
||||
eslint.config.js
|
||||
|
||||
/.editorconfig
|
||||
/.gitattributes
|
||||
|
@ -124,10 +124,10 @@ This will only run the "css" module tests. This will significantly speed up your
|
||||
|
||||
#### Loading changes on the test page
|
||||
|
||||
Rather than rebuilding jQuery with `grunt` every time you make a change, you can use the included `grunt watch` task to rebuild distribution files whenever a file is saved.
|
||||
Rather than rebuilding jQuery with `npm run build` every time you make a change, you can use the included watch task to rebuild distribution files whenever a file is saved.
|
||||
|
||||
```bash
|
||||
$ grunt watch
|
||||
$ npm start
|
||||
```
|
||||
|
||||
Alternatively, you can **load tests in AMD** to avoid the need for rebuilding altogether.
|
||||
|
238
Gruntfile.js
238
Gruntfile.js
@ -1,20 +1,6 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function( grunt ) {
|
||||
function readOptionalJSON( filepath ) {
|
||||
const stripJSONComments = require( "strip-json-comments" );
|
||||
let data = {};
|
||||
try {
|
||||
data = JSON.parse( stripJSONComments(
|
||||
fs.readFileSync( filepath, { encoding: "utf8" } )
|
||||
) );
|
||||
} catch ( e ) {}
|
||||
return data;
|
||||
}
|
||||
|
||||
const fs = require( "fs" );
|
||||
const { spawn } = require( "child_process" );
|
||||
const gzip = require( "gzip-js" );
|
||||
const nodeV16OrNewer = !/^v1[0-5]\./.test( process.version );
|
||||
const nodeV17OrNewer = !/^v1[0-6]\./.test( process.version );
|
||||
const customBrowsers = process.env.BROWSERS && process.env.BROWSERS.split( "," );
|
||||
@ -34,112 +20,8 @@ module.exports = function( grunt ) {
|
||||
grunt.option( "filename", "jquery.js" );
|
||||
}
|
||||
|
||||
const builtJsFiles = [
|
||||
"dist/jquery.js",
|
||||
"dist/jquery.min.js",
|
||||
"dist/jquery.slim.js",
|
||||
"dist/jquery.slim.min.js"
|
||||
];
|
||||
|
||||
const builtJsMinFiles = builtJsFiles
|
||||
.filter( filepath => filepath.endsWith( ".min.js" ) );
|
||||
|
||||
grunt.initConfig( {
|
||||
pkg: grunt.file.readJSON( "package.json" ),
|
||||
dst: readOptionalJSON( "dist/.destination.json" ),
|
||||
compare_size: {
|
||||
files: builtJsMinFiles,
|
||||
options: {
|
||||
compress: {
|
||||
gz: function( contents ) {
|
||||
return gzip.zip( contents, {} ).length;
|
||||
}
|
||||
},
|
||||
cache: "build/.sizecache.json"
|
||||
}
|
||||
},
|
||||
babel: {
|
||||
options: {
|
||||
sourceMap: "inline",
|
||||
retainLines: true,
|
||||
plugins: [ "@babel/transform-for-of" ]
|
||||
},
|
||||
tests: {
|
||||
files: {
|
||||
"test/data/core/jquery-iterability-transpiled.js":
|
||||
"test/data/core/jquery-iterability-transpiled-es6.js"
|
||||
}
|
||||
}
|
||||
},
|
||||
build: {
|
||||
all: {
|
||||
dest: "dist/jquery.js",
|
||||
minimum: [
|
||||
"core"
|
||||
],
|
||||
|
||||
// Exclude specified modules if the module matching the key is removed
|
||||
removeWith: {
|
||||
ajax: [ "manipulation/_evalUrl", "deprecated/ajax-event-alias" ],
|
||||
callbacks: [ "deferred" ],
|
||||
css: [ "effects", "dimensions", "offset" ],
|
||||
"css/showHide": [ "effects" ],
|
||||
deferred: {
|
||||
remove: [ "ajax", "effects", "queue", "core/ready" ],
|
||||
include: [ "core/ready-no-deferred" ]
|
||||
},
|
||||
event: [ "deprecated/ajax-event-alias", "deprecated/event" ],
|
||||
selector: [ "css/hiddenVisibleSelectors", "effects/animatedSelector" ]
|
||||
}
|
||||
}
|
||||
},
|
||||
npmcopy: {
|
||||
all: {
|
||||
options: {
|
||||
destPrefix: "external"
|
||||
},
|
||||
files: {
|
||||
"bootstrap/bootstrap.css": "bootstrap/dist/css/bootstrap.css",
|
||||
"bootstrap/bootstrap.min.css": "bootstrap/dist/css/bootstrap.min.css",
|
||||
"bootstrap/bootstrap.min.css.map": "bootstrap/dist/css/bootstrap.min.css.map",
|
||||
|
||||
"core-js/core-js.js": "core-js/client/core.min.js",
|
||||
"core-js/LICENSE.txt": "core-js/LICENSE",
|
||||
|
||||
"npo/npo.js": "native-promise-only/lib/npo.src.js",
|
||||
|
||||
"qunit/qunit.js": "qunit/qunit/qunit.js",
|
||||
"qunit/qunit.css": "qunit/qunit/qunit.css",
|
||||
"qunit/LICENSE.txt": "qunit/LICENSE.txt",
|
||||
|
||||
"requirejs/require.js": "requirejs/require.js",
|
||||
|
||||
"sinon/sinon.js": "sinon/pkg/sinon.js",
|
||||
"sinon/LICENSE.txt": "sinon/LICENSE"
|
||||
}
|
||||
}
|
||||
},
|
||||
jsonlint: {
|
||||
pkg: {
|
||||
src: [ "package.json" ]
|
||||
}
|
||||
},
|
||||
eslint: {
|
||||
options: {
|
||||
|
||||
// See https://github.com/sindresorhus/grunt-eslint/issues/119
|
||||
quiet: true
|
||||
},
|
||||
|
||||
// We have to explicitly declare "src" property otherwise "newer"
|
||||
// task wouldn't work properly :/
|
||||
dist: {
|
||||
src: builtJsFiles
|
||||
},
|
||||
dev: {
|
||||
src: [ "src/**/*.js", "Gruntfile.js", "test/**/*.js", "build/**/*.js" ]
|
||||
}
|
||||
},
|
||||
testswarm: {
|
||||
tests: [
|
||||
|
||||
@ -206,9 +88,14 @@ module.exports = function( grunt ) {
|
||||
"external/npo/npo.js",
|
||||
"external/requirejs/require.js",
|
||||
"test/data/testinit.js",
|
||||
|
||||
"test/jquery.js",
|
||||
|
||||
{
|
||||
pattern: "external/**",
|
||||
included: false,
|
||||
served: true,
|
||||
nocache: true
|
||||
},
|
||||
{
|
||||
pattern: "dist/jquery.*",
|
||||
included: false,
|
||||
@ -221,13 +108,6 @@ module.exports = function( grunt ) {
|
||||
served: true,
|
||||
nocache: true
|
||||
},
|
||||
{
|
||||
pattern: "external/**",
|
||||
included: false,
|
||||
served: true,
|
||||
nocache: true
|
||||
},
|
||||
{ pattern: "node_modules/**", included: false, served: true },
|
||||
{
|
||||
pattern: "test/**/*.@(js|css|jpg|html|xml|svg)",
|
||||
included: false,
|
||||
@ -281,7 +161,6 @@ module.exports = function( grunt ) {
|
||||
// jsdom only runs basic tests
|
||||
"test/unit/basic.js",
|
||||
|
||||
{ pattern: "external/**", included: false, served: true },
|
||||
{
|
||||
pattern: "test/**/*.@(js|css|jpg|html|xml|svg)",
|
||||
included: false,
|
||||
@ -310,100 +189,27 @@ module.exports = function( grunt ) {
|
||||
browsers: [ "IE" ],
|
||||
singleRun: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
files: [ "<%= eslint.dev.src %>" ],
|
||||
tasks: [ "dev" ]
|
||||
},
|
||||
uglify: {
|
||||
all: {
|
||||
files: {
|
||||
"dist/<%= grunt.option('filename').replace(/\\.js$/, '.min.js') %>":
|
||||
"dist/<%= grunt.option('filename') %>"
|
||||
},
|
||||
options: {
|
||||
preserveComments: false,
|
||||
sourceMap: true,
|
||||
sourceMapName:
|
||||
"dist/<%= grunt.option('filename').replace('.js', '.min.map') %>",
|
||||
report: "min",
|
||||
output: {
|
||||
"ascii_only": true,
|
||||
|
||||
// Support: Android 4.0 only
|
||||
// UglifyJS 3 breaks Android 4.0 if this option is not enabled.
|
||||
// This is in lieu of setting ie8 for all of mangle, compress, and output
|
||||
"ie8": true
|
||||
},
|
||||
banner: "/*! jQuery v<%= pkg.version %> | " +
|
||||
"(c) OpenJS Foundation and other contributors | jquery.org/license */",
|
||||
compress: {
|
||||
"hoist_funs": false,
|
||||
loops: false,
|
||||
|
||||
// Support: IE <11
|
||||
// typeofs transformation is unsafe for IE9-10
|
||||
// See https://github.com/mishoo/UglifyJS2/issues/2198
|
||||
typeofs: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
// Load grunt tasks from NPM packages
|
||||
require( "load-grunt-tasks" )( grunt, {
|
||||
pattern: nodeV16OrNewer ? [ "grunt-*" ] : [ "grunt-*", "!grunt-eslint" ]
|
||||
pattern: [ "grunt-*" ]
|
||||
} );
|
||||
|
||||
// Integrate jQuery specific tasks
|
||||
grunt.loadTasks( "build/tasks" );
|
||||
grunt.loadTasks( "build/grunt-tasks" );
|
||||
|
||||
grunt.registerTask( "print_old_node_message", ( ...args ) => {
|
||||
var task = args.join( ":" );
|
||||
grunt.log.writeln( "Old Node.js detected, running the task \"" + task + "\" skipped..." );
|
||||
} );
|
||||
|
||||
grunt.registerTask( "build-all-variants",
|
||||
"Build both the full & slim builds",
|
||||
function() {
|
||||
const done = this.async();
|
||||
|
||||
spawn( "npm run build-all-variants", {
|
||||
stdio: "inherit",
|
||||
shell: true
|
||||
} )
|
||||
.on( "close", code => {
|
||||
done( code === 0 );
|
||||
} );
|
||||
} );
|
||||
|
||||
grunt.registerTask( "print_jsdom_message", () => {
|
||||
grunt.log.writeln( "Node.js 17 or newer detected, skipping jsdom tests..." );
|
||||
} );
|
||||
|
||||
grunt.registerTask( "lint", [
|
||||
"jsonlint",
|
||||
|
||||
// Running the full eslint task without breaking it down to targets
|
||||
// would run the dist target first which would point to errors in the built
|
||||
// file, making it harder to fix them. We want to check the built file only
|
||||
// if we already know the source files pass the linter.
|
||||
runIfNewNode( "eslint:dev" ),
|
||||
runIfNewNode( "eslint:dist" )
|
||||
] );
|
||||
|
||||
grunt.registerTask( "lint:newer", [
|
||||
"newer:jsonlint",
|
||||
|
||||
// Don't replace it with just the task; see the above comment.
|
||||
runIfNewNode( "newer:eslint:dev" ),
|
||||
runIfNewNode( "newer:eslint:dist" )
|
||||
] );
|
||||
|
||||
grunt.registerTask( "test:fast", [ "node_smoke_tests" ] );
|
||||
grunt.registerTask( "test:slow", [
|
||||
runIfNewNode( "promises_aplus_tests" ),
|
||||
grunt.registerTask( "test:jsdom", [
|
||||
|
||||
// Support: Node.js 17+
|
||||
// jsdom fails to connect to the Karma server in Node 17+.
|
||||
@ -411,33 +217,11 @@ module.exports = function( grunt ) {
|
||||
nodeV17OrNewer ? "print_jsdom_message" : runIfNewNode( "karma:jsdom" )
|
||||
] );
|
||||
|
||||
grunt.registerTask( "test:prepare", [
|
||||
"qunit_fixture",
|
||||
"babel:tests"
|
||||
] );
|
||||
|
||||
grunt.registerTask( "test", [
|
||||
"test:prepare",
|
||||
"test:fast",
|
||||
"test:slow"
|
||||
] );
|
||||
|
||||
grunt.registerTask( "dev", [
|
||||
"build:*:*",
|
||||
runIfNewNode( "newer:eslint:dev" ),
|
||||
"newer:uglify",
|
||||
"remove_map_comment",
|
||||
"dist:*",
|
||||
"qunit_fixture",
|
||||
"compare_size"
|
||||
"test:jsdom"
|
||||
] );
|
||||
|
||||
grunt.registerTask( "default", [
|
||||
runIfNewNode( "eslint:dev" ),
|
||||
"build-all-variants",
|
||||
"test:prepare",
|
||||
runIfNewNode( "eslint:dist" ),
|
||||
"test:fast",
|
||||
"compare_size"
|
||||
"test"
|
||||
] );
|
||||
};
|
||||
|
146
README.md
146
README.md
@ -35,7 +35,7 @@ To build jQuery, you need to have the latest Node.js/npm and git 1.7 or later. E
|
||||
|
||||
For Windows, you have to download and install [git](https://git-scm.com/downloads) and [Node.js](https://nodejs.org/en/download/).
|
||||
|
||||
OS X users should install [Homebrew](https://brew.sh/). Once Homebrew is installed, run `brew install git` to install git,
|
||||
macOS users should install [Homebrew](https://brew.sh/). Once Homebrew is installed, run `brew install git` to install git,
|
||||
and `brew install node` to install Node.js.
|
||||
|
||||
Linux/BSD users should use their appropriate package managers to install git and Node.js, or build from source
|
||||
@ -45,47 +45,47 @@ if you swing that way. Easy-peasy.
|
||||
How to build your own jQuery
|
||||
----------------------------
|
||||
|
||||
Clone a copy of the main jQuery git repo by running:
|
||||
First, [clone the jQuery git repo](https://help.github.com/en/github/creating-cloning-and-archiving-repositories/cloning-a-repository).
|
||||
|
||||
Then, enter the jquery directory, install dependencies, and run the build script:
|
||||
|
||||
```bash
|
||||
git clone git://github.com/jquery/jquery.git
|
||||
cd jquery
|
||||
npm install
|
||||
npm run build
|
||||
```
|
||||
|
||||
Enter the jquery directory and run the build script:
|
||||
The built version of jQuery will be placed in the `dist/` directory, along with a minified copy and associated map file.
|
||||
|
||||
## Build all jQuery release files
|
||||
|
||||
To build all variants of jQuery, run the following command:
|
||||
|
||||
```bash
|
||||
cd jquery && npm run build
|
||||
```
|
||||
The built version of jQuery will be put in the `dist/` subdirectory, along with the minified copy and associated map file.
|
||||
|
||||
If you want to create custom build or help with jQuery development, it would be better to install [grunt command line interface](https://github.com/gruntjs/grunt-cli) as a global package:
|
||||
|
||||
```
|
||||
npm install -g grunt-cli
|
||||
```
|
||||
Make sure you have `grunt` installed by testing:
|
||||
```
|
||||
grunt -V
|
||||
npm run build:all
|
||||
```
|
||||
|
||||
Now by running the `grunt` command, in the jquery directory, you can build a full version of jQuery, just like with an `npm run build` command:
|
||||
```
|
||||
grunt
|
||||
```
|
||||
This will create all of the variants that jQuery includes in a release, including `jquery.js` and `jquery.slim.js` along their associated minified files and sourcemaps.
|
||||
|
||||
There are many other tasks available for jQuery Core:
|
||||
```
|
||||
grunt -help
|
||||
## Building a Custom jQuery
|
||||
|
||||
The build script can be used to create a custom version of jQuery that includes only the modules you need.
|
||||
|
||||
Any module may be excluded except for `core`. When excluding `selector`, it is not removed but replaced with a small wrapper around native `querySelectorAll` (see below for more information).
|
||||
|
||||
### Build Script Help
|
||||
|
||||
To see the full list of available options for the build script, run the following:
|
||||
|
||||
```bash
|
||||
npm run build -- --help
|
||||
```
|
||||
|
||||
### Modules
|
||||
|
||||
Special builds can be created that exclude subsets of jQuery functionality.
|
||||
This allows for smaller custom builds when the builder is certain that those parts of jQuery are not being used.
|
||||
For example, an app that only used JSONP for `$.ajax()` and did not need to calculate offsets or positions of elements could exclude the offset and ajax/xhr modules.
|
||||
To exclude a module, pass its path relative to the `src` folder (without the `.js` extension) to the `--exclude` option. When using the `--include` option, the default includes are dropped and a build is created with only those modules.
|
||||
|
||||
Any module may be excluded except for `core`, and `selector`. To exclude a module, pass its path relative to the `src` folder (without the `.js` extension).
|
||||
|
||||
Some example modules that can be excluded are:
|
||||
Some example modules that can be excluded or included are:
|
||||
|
||||
- **ajax**: All AJAX functionality: `$.ajax()`, `$.get()`, `$.post()`, `$.ajaxSetup()`, `.load()`, transports, and ajax event shorthands such as `.ajaxStart()`.
|
||||
- **ajax/xhr**: The XMLHTTPRequest AJAX transport only.
|
||||
@ -101,84 +101,67 @@ Some example modules that can be excluded are:
|
||||
- **offset**: The `.offset()`, `.position()`, `.offsetParent()`, `.scrollLeft()`, and `.scrollTop()` methods.
|
||||
- **wrap**: The `.wrap()`, `.wrapAll()`, `.wrapInner()`, and `.unwrap()` methods.
|
||||
- **core/ready**: Exclude the ready module if you place your scripts at the end of the body. Any ready callbacks bound with `jQuery()` will simply be called immediately. However, `jQuery(document).ready()` will not be a function and `.on("ready", ...)` or similar will not be triggered.
|
||||
- **deferred**: Exclude jQuery.Deferred. This also removes jQuery.Callbacks. *Note* that modules that depend on jQuery.Deferred(AJAX, effects, core/ready) will not be removed and will still expect jQuery.Deferred to be there. Include your own jQuery.Deferred implementation or exclude those modules as well (`grunt custom:-deferred,-ajax,-effects,-core/ready`).
|
||||
- **deferred**: Exclude jQuery.Deferred. This also excludes all modules that rely on Deferred, including **ajax**, **effects**, and **queue**, but replaces **core/ready** with **core/ready-no-deferred**.
|
||||
- **exports/global**: Exclude the attachment of global jQuery variables ($ and jQuery) to the window.
|
||||
- **exports/amd**: Exclude the AMD definition.
|
||||
|
||||
As a special case, you may also replace the full jQuery `selector` module by using a special flag `grunt custom:-selector`.
|
||||
|
||||
- **selector**: The full jQuery selector engine. When this module is excluded, it is replaced by a rudimentary selector engine based on the browser's `querySelectorAll` method that does not support jQuery selector extensions or enhanced semantics. See the [selector-native.js](https://github.com/jquery/jquery/blob/main/src/selector-native.js) file for details.
|
||||
|
||||
For backwards compatibility purposes, the name `sizzle` is recognized as the alias for `selector`.
|
||||
- **selector**: The full jQuery selector engine. When this module is excluded, it is replaced with a rudimentary selector engine based on the browser's `querySelectorAll` method that does not support jQuery selector extensions or enhanced semantics. See the [selector-native.js](https://github.com/jquery/jquery/blob/main/src/selector-native.js) file for details.
|
||||
|
||||
*Note*: Excluding the full `selector` module will also exclude all jQuery selector extensions (such as `effects/animatedSelector` and `css/hiddenVisibleSelectors`).
|
||||
|
||||
The build process shows a message for each dependent module it excludes or includes.
|
||||
|
||||
##### AMD name
|
||||
|
||||
As an option, you can set the module name for jQuery's AMD definition. By default, it is set to "jquery", which plays nicely with plugins and third-party libraries, but there may be cases where you'd like to change this. Simply pass it to the `--amd` parameter:
|
||||
You can set the module name for jQuery's AMD definition. By default, it is set to "jquery", which plays nicely with plugins and third-party libraries, but there may be cases where you'd like to change this. Pass it to the `--amd` parameter:
|
||||
|
||||
```bash
|
||||
grunt custom --amd="custom-name"
|
||||
npm run build -- --amd="custom-name"
|
||||
```
|
||||
|
||||
Or, to define anonymously, set the name to an empty string.
|
||||
Or, to define anonymously, leave the name blank.
|
||||
|
||||
```bash
|
||||
grunt custom --amd=""
|
||||
npm run build -- --amd
|
||||
```
|
||||
|
||||
##### File name
|
||||
##### File name and directory
|
||||
|
||||
The default name for the built jQuery file is `jquery.js`; it is placed under the `dist/` directory. It's possible to change the file name using the `--filename` parameter:
|
||||
The default name for the built jQuery file is `jquery.js`; it is placed under the `dist/` directory. It's possible to change the file name using `--filename` and the directory using `--dir`. `--dir` is relative to the project root.
|
||||
|
||||
```bash
|
||||
grunt custom:slim --filename="jquery.slim.js"
|
||||
npm run build -- --slim --filename="jquery.slim.js" --dir="/tmp"
|
||||
```
|
||||
|
||||
This would create a slim version of jQuery and place it under `dist/jquery.slim.js`. In fact, this is exactly the command we use to generate the slim jQuery during the release process.
|
||||
This would create a slim version of jQuery and place it under `tmp/jquery.slim.js`.
|
||||
|
||||
#### Custom Build Examples
|
||||
|
||||
To create a custom build, first check out the version:
|
||||
|
||||
```bash
|
||||
git pull; git checkout VERSION
|
||||
```
|
||||
|
||||
Where VERSION is the version you want to customize. Then, make sure all Node dependencies are installed:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
Create the custom build using the `grunt custom` option, listing the modules to be excluded.
|
||||
Create a custom build using `npm run build`, listing the modules to be excluded. Excluding a top-level module also excludes its corresponding directory of modules.
|
||||
|
||||
Exclude all **ajax** functionality:
|
||||
|
||||
```bash
|
||||
grunt custom:-ajax
|
||||
npm run build -- --exclude=ajax
|
||||
```
|
||||
|
||||
Excluding **css** removes modules depending on CSS: **effects**, **offset**, **dimensions**.
|
||||
|
||||
```bash
|
||||
grunt custom:-css
|
||||
npm run build -- --exclude=css
|
||||
```
|
||||
|
||||
Exclude a bunch of modules:
|
||||
Exclude a bunch of modules (`-e` is an alias for `--exclude`):
|
||||
|
||||
```bash
|
||||
grunt custom:-ajax/jsonp,-css,-deprecated,-dimensions,-effects,-offset,-wrap
|
||||
npm run build -- -e ajax/jsonp -e css -e deprecated -e dimensions -e effects -e offset -e wrap
|
||||
```
|
||||
|
||||
There is also a special alias to generate a build with the same configuration as the official jQuery Slim build is generated:
|
||||
There is a special alias to generate a build with the same configuration as the official jQuery Slim build:
|
||||
|
||||
```bash
|
||||
grunt custom:slim
|
||||
npm run build -- --filename=jquery.slim.js --slim
|
||||
```
|
||||
|
||||
For questions or requests regarding custom builds, please start a thread on the [Developing jQuery Core](https://forum.jquery.com/developing-jquery-core) section of the forum. Due to the combinatorics and custom nature of these builds, they are not regularly tested in jQuery's unit test process.
|
||||
*Non-official custom builds are not regularly tested. Use them at your own risk.*
|
||||
|
||||
Running the Unit Tests
|
||||
--------------------------------------
|
||||
@ -189,10 +172,10 @@ Make sure you have the necessary dependencies:
|
||||
npm install
|
||||
```
|
||||
|
||||
Start `grunt watch` or `npm start` to auto-build jQuery as you work:
|
||||
Start `npm start` to auto-build jQuery as you work:
|
||||
|
||||
```bash
|
||||
grunt watch
|
||||
npm start
|
||||
```
|
||||
|
||||
|
||||
@ -205,35 +188,6 @@ Run the unit tests with a local server that supports PHP. Ensure that you run th
|
||||
|
||||
|
||||
|
||||
|
||||
Building to a different directory
|
||||
---------------------------------
|
||||
|
||||
To copy the built jQuery files from `/dist` to another directory:
|
||||
|
||||
```bash
|
||||
grunt && grunt dist:/path/to/special/location/
|
||||
```
|
||||
With this example, the output files would be:
|
||||
|
||||
```bash
|
||||
/path/to/special/location/jquery.js
|
||||
/path/to/special/location/jquery.min.js
|
||||
```
|
||||
|
||||
To add a permanent copy destination, create a file in `dist/` called ".destination.json". Inside the file, paste and customize the following:
|
||||
|
||||
```json
|
||||
|
||||
{
|
||||
"/Absolute/path/to/other/destination": true
|
||||
}
|
||||
```
|
||||
|
||||
Additionally, both methods can be combined.
|
||||
|
||||
|
||||
|
||||
Essential Git
|
||||
-------------
|
||||
|
||||
|
69
build/command.js
Executable file
69
build/command.js
Executable file
@ -0,0 +1,69 @@
|
||||
"use strict";
|
||||
|
||||
const { build } = require( "./tasks/build" );
|
||||
const yargs = require( "yargs/yargs" );
|
||||
const slimExclude = require( "./tasks/lib/slim-exclude" );
|
||||
|
||||
const argv = yargs( process.argv.slice( 2 ) )
|
||||
.version( false )
|
||||
.command( {
|
||||
command: "[options]",
|
||||
describe: "Build a jQuery bundle"
|
||||
} )
|
||||
.option( "filename", {
|
||||
alias: "f",
|
||||
type: "string",
|
||||
description:
|
||||
"Set the filename of the built file. Defaults to jquery.js."
|
||||
} )
|
||||
.option( "dir", {
|
||||
alias: "d",
|
||||
type: "string",
|
||||
description:
|
||||
"Set the dir to which to output the built file. Defaults to /dist."
|
||||
} )
|
||||
.option( "version", {
|
||||
alias: "v",
|
||||
type: "string",
|
||||
description:
|
||||
"Set the version to include in the built file. " +
|
||||
"Defaults to the version in package.json plus the " +
|
||||
"short commit SHA and any excluded modules."
|
||||
} )
|
||||
.option( "watch", {
|
||||
alias: "w",
|
||||
type: "boolean",
|
||||
description:
|
||||
"Watch the source files and rebuild when they change."
|
||||
} )
|
||||
.option( "exclude", {
|
||||
alias: "e",
|
||||
type: "array",
|
||||
description:
|
||||
"Modules to exclude from the build. " +
|
||||
"Specifying this option will cause the " +
|
||||
"specified modules to be excluded from the build."
|
||||
} )
|
||||
.option( "include", {
|
||||
alias: "i",
|
||||
type: "array",
|
||||
description:
|
||||
"Modules to include in the build. " +
|
||||
"Specifying this option will override the " +
|
||||
"default included modules and only include these modules."
|
||||
} )
|
||||
.option( "slim", {
|
||||
alias: "s",
|
||||
type: "boolean",
|
||||
description: "Build a slim bundle, which excludes " +
|
||||
slimExclude.join( ", " )
|
||||
} )
|
||||
.option( "amd", {
|
||||
type: "string",
|
||||
description:
|
||||
"Set the name of the AMD module. Leave blank to make an anonymous module."
|
||||
} )
|
||||
.help()
|
||||
.argv;
|
||||
|
||||
build( argv );
|
@ -1,50 +1,85 @@
|
||||
/**
|
||||
* Special concat/build task to handle various jQuery build requirements
|
||||
* Concats AMD modules, removes their definitions,
|
||||
* Special build task to handle various jQuery build requirements.
|
||||
* Compiles JS modules into one bundle, sets the custom AMD name,
|
||||
* and includes/excludes specified modules
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
module.exports = function( grunt ) {
|
||||
var fs = require( "fs" ),
|
||||
requirejs = require( "requirejs" ),
|
||||
slimBuildFlags = require( "./lib/slim-build-flags" ),
|
||||
srcFolder = __dirname + "/../../src/",
|
||||
rdefineEnd = /\}\s*?\);[^}\w]*$/,
|
||||
read = function( fileName ) {
|
||||
return grunt.file.read( srcFolder + fileName );
|
||||
const fs = require( "fs" );
|
||||
const path = require( "path" );
|
||||
const util = require( "util" );
|
||||
const exec = util.promisify( require( "child_process" ).exec );
|
||||
const requirejs = require( "requirejs" );
|
||||
const excludedFromSlim = require( "./lib/slim-exclude" );
|
||||
const pkg = require( "../../package.json" );
|
||||
const isCleanWorkingDir = require( "./lib/isCleanWorkingDir" );
|
||||
const minify = require( "./minify" );
|
||||
const getTimestamp = require( "./lib/getTimestamp" );
|
||||
const verifyNodeVersion = require( "./lib/verifyNodeVersion" );
|
||||
const srcFolder = path.resolve( __dirname, "../../src" );
|
||||
|
||||
const rdefineEnd = /\}\s*?\);[^}\w]*$/;
|
||||
|
||||
const minimum = [ "core" ];
|
||||
|
||||
// Exclude specified modules if the module matching the key is removed
|
||||
const removeWith = {
|
||||
ajax: [ "manipulation/_evalUrl", "deprecated/ajax-event-alias" ],
|
||||
callbacks: [ "deferred" ],
|
||||
css: [ "effects", "dimensions", "offset" ],
|
||||
"css/showHide": [ "effects" ],
|
||||
deferred: {
|
||||
remove: [ "ajax", "effects", "queue", "core/ready" ],
|
||||
include: [ "core/ready-no-deferred" ]
|
||||
},
|
||||
event: [ "deprecated/ajax-event-alias", "deprecated/event" ],
|
||||
selector: [ "css/hiddenVisibleSelectors", "effects/animatedSelector" ]
|
||||
};
|
||||
|
||||
async function read( filename ) {
|
||||
return fs.promises.readFile( path.join( srcFolder, filename ), "utf8" );
|
||||
}
|
||||
|
||||
// Remove the src folder and file extension
|
||||
// and ensure unix-style path separators
|
||||
function moduleName( filename ) {
|
||||
return filename
|
||||
.replace( `${srcFolder}${path.sep}`, "" )
|
||||
.replace( /\.js$/, "" )
|
||||
.split( path.sep )
|
||||
.join( path.posix.sep );
|
||||
}
|
||||
|
||||
async function readdirRecursive( dir, all = [] ) {
|
||||
let files;
|
||||
try {
|
||||
files = await fs.promises.readdir( path.join( srcFolder, dir ), {
|
||||
withFileTypes: true
|
||||
} );
|
||||
} catch ( e ) {
|
||||
return all;
|
||||
}
|
||||
for ( const file of files ) {
|
||||
const filepath = path.join( dir, file.name );
|
||||
|
||||
if ( file.isDirectory() ) {
|
||||
all.push( ...( await readdirRecursive( filepath ) ) );
|
||||
} else {
|
||||
all.push( moduleName( filepath ) );
|
||||
}
|
||||
}
|
||||
return all;
|
||||
}
|
||||
|
||||
async function getRequireConfig( { amd } = {} ) {
|
||||
const wrapperSource = await read( "wrapper.js" );
|
||||
|
||||
// Catch `// @CODE` and subsequent comment lines event if they don't start
|
||||
// in the first column.
|
||||
wrapper = read( "wrapper.js" ).split( /[\x20\t]*\/\/ @CODE\n(?:[\x20\t]*\/\/[^\n]+\n)*/ ),
|
||||
|
||||
config = {
|
||||
baseUrl: "src",
|
||||
name: "jquery",
|
||||
|
||||
// Allow strict mode
|
||||
useStrict: true,
|
||||
|
||||
// We have multiple minify steps
|
||||
optimize: "none",
|
||||
|
||||
// Include dependencies loaded with require
|
||||
findNestedDependencies: true,
|
||||
|
||||
// Avoid inserting define() placeholder
|
||||
skipModuleInsertion: true,
|
||||
|
||||
// Avoid breaking semicolons inserted by r.js
|
||||
skipSemiColonInsertion: true,
|
||||
wrap: {
|
||||
start: wrapper[ 0 ].replace( /\/\*\s*eslint(?: |-).*\s*\*\/\n/, "" ),
|
||||
end: wrapper[ 1 ]
|
||||
},
|
||||
rawText: {},
|
||||
onBuildWrite: convert
|
||||
};
|
||||
const wrapper = wrapperSource.split(
|
||||
/[\x20\t]*\/\/ @CODE\n(?:[\x20\t]*\/\/[^\n]+\n)*/
|
||||
);
|
||||
|
||||
/**
|
||||
* Strip all definitions generated by requirejs
|
||||
@ -57,7 +92,6 @@ module.exports = function( grunt ) {
|
||||
* @param {String} contents The contents to be written (including their AMD wrappers)
|
||||
*/
|
||||
function convert( name, path, contents ) {
|
||||
var amdName;
|
||||
|
||||
// Convert var modules
|
||||
if ( /.\/var\//.test( path.replace( process.cwd(), "" ) ) ) {
|
||||
@ -96,273 +130,214 @@ module.exports = function( grunt ) {
|
||||
}
|
||||
|
||||
// AMD Name
|
||||
if ( ( amdName = grunt.option( "amd" ) ) != null && /^exports\/amd$/.test( name ) ) {
|
||||
if ( amdName ) {
|
||||
grunt.log.writeln( "Naming jQuery with AMD name: " + amdName );
|
||||
if ( amd != null && /^exports\/amd$/.test( name ) ) {
|
||||
if ( amd ) {
|
||||
console.log( "Naming jQuery with AMD name: " + amd );
|
||||
} else {
|
||||
grunt.log.writeln( "AMD name now anonymous" );
|
||||
console.log( "AMD name now anonymous" );
|
||||
}
|
||||
|
||||
// Remove the comma for anonymous defines
|
||||
contents = contents
|
||||
.replace( /(\s*)"jquery"(\,\s*)/, amdName ? "$1\"" + amdName + "\"$2" : "" );
|
||||
.replace( /(\s*)"jquery"(\,\s*)/, amd ? "$1\"" + amd + "\"$2" : "" );
|
||||
|
||||
}
|
||||
return contents;
|
||||
}
|
||||
|
||||
grunt.registerMultiTask(
|
||||
"build",
|
||||
"Concatenate source, remove sub AMD definitions, " +
|
||||
"(include/exclude modules with +/- flags), embed date/version",
|
||||
function() {
|
||||
var flag, index,
|
||||
done = this.async(),
|
||||
flags = this.flags,
|
||||
optIn = flags[ "*" ],
|
||||
name = grunt.option( "filename" ),
|
||||
minimum = this.data.minimum,
|
||||
removeWith = this.data.removeWith,
|
||||
excluded = [],
|
||||
included = [],
|
||||
version = grunt.config( "pkg.version" ),
|
||||
return {
|
||||
baseUrl: "src",
|
||||
name: "jquery",
|
||||
|
||||
/**
|
||||
* Recursively calls the excluder to remove on all modules in the list
|
||||
* @param {Array} list
|
||||
* @param {String} [prepend] Prepend this to the module name.
|
||||
* Indicates we're walking a directory
|
||||
*/
|
||||
excludeList = function( list, prepend ) {
|
||||
if ( list ) {
|
||||
prepend = prepend ? prepend + "/" : "";
|
||||
list.forEach( function( module ) {
|
||||
// Allow strict mode
|
||||
useStrict: true,
|
||||
|
||||
// Exclude var modules as well
|
||||
if ( module === "var" ) {
|
||||
excludeList(
|
||||
fs.readdirSync( srcFolder + prepend + module ), prepend + module
|
||||
);
|
||||
return;
|
||||
}
|
||||
if ( prepend ) {
|
||||
// We have multiple minify steps
|
||||
optimize: "none",
|
||||
|
||||
// Skip if this is not a js file and we're walking files in a dir
|
||||
if ( !( module = /([\w-\/]+)\.js$/.exec( module ) ) ) {
|
||||
return;
|
||||
}
|
||||
// Include dependencies loaded with require
|
||||
findNestedDependencies: true,
|
||||
|
||||
// Prepend folder name if passed
|
||||
// Remove .js extension
|
||||
module = prepend + module[ 1 ];
|
||||
}
|
||||
// Avoid inserting define() placeholder
|
||||
skipModuleInsertion: true,
|
||||
|
||||
// Avoid infinite recursion
|
||||
if ( excluded.indexOf( module ) === -1 ) {
|
||||
excluder( "-" + module );
|
||||
}
|
||||
} );
|
||||
}
|
||||
// Avoid breaking semicolons inserted by r.js
|
||||
skipSemiColonInsertion: true,
|
||||
wrap: {
|
||||
start: wrapper[ 0 ].replace( /\/\*\s*eslint(?: |-).*\s*\*\/\n/, "" ),
|
||||
end: wrapper[ 1 ]
|
||||
},
|
||||
rawText: {},
|
||||
onBuildWrite: convert
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified module to the excluded or included list, depending on the flag
|
||||
* @param {String} flag A module path relative to
|
||||
* the src directory starting with + or - to indicate
|
||||
* whether it should be included or excluded
|
||||
*/
|
||||
excluder = function( flag ) {
|
||||
var additional,
|
||||
m = /^(\+|-|)([\w\/-]+)$/.exec( flag ),
|
||||
exclude = m[ 1 ] === "-",
|
||||
module = m[ 2 ];
|
||||
function unique( array ) {
|
||||
return [ ...new Set( array ) ];
|
||||
}
|
||||
|
||||
// Recognize the legacy `sizzle` alias
|
||||
if ( module === "sizzle" ) {
|
||||
module = "selector";
|
||||
async function checkExclude( exclude, include ) {
|
||||
const included = [ ...include ];
|
||||
const excluded = [ ...exclude ];
|
||||
|
||||
for ( const module of exclude ) {
|
||||
if ( minimum.indexOf( module ) !== -1 ) {
|
||||
throw new Error( `Module \"${module}\" is a minimum requirement.` );
|
||||
}
|
||||
|
||||
if ( exclude ) {
|
||||
|
||||
// Can't exclude certain modules
|
||||
if ( minimum.indexOf( module ) === -1 ) {
|
||||
|
||||
// Add to excluded
|
||||
if ( excluded.indexOf( module ) === -1 ) {
|
||||
grunt.log.writeln( flag );
|
||||
excluded.push( module );
|
||||
|
||||
// Exclude all files in the folder of the same name
|
||||
// Exclude all files in the dir of the same name
|
||||
// These are the removable dependencies
|
||||
// It's fine if the directory is not there
|
||||
try {
|
||||
|
||||
// `selector` is a special case as we don't just remove
|
||||
// the module, but we replace it with `selector-native`
|
||||
// which re-uses parts of the `src/selector` folder.
|
||||
if ( module !== "selector" ) {
|
||||
excludeList(
|
||||
fs.readdirSync( `${ srcFolder }/${ module }` ),
|
||||
module
|
||||
);
|
||||
// "sizzle" is legacy for selector
|
||||
if ( module !== "selector" && module !== "sizzle" ) {
|
||||
const files = await readdirRecursive( module );
|
||||
excluded.push( ...files );
|
||||
}
|
||||
} catch ( e ) {
|
||||
grunt.verbose.writeln( e );
|
||||
}
|
||||
}
|
||||
|
||||
additional = removeWith[ module ];
|
||||
|
||||
// Check removeWith list
|
||||
const additional = removeWith[ module ];
|
||||
if ( additional ) {
|
||||
excludeList( additional.remove || additional );
|
||||
if ( additional.include ) {
|
||||
included = included.concat( additional.include );
|
||||
grunt.log.writeln( "+" + additional.include );
|
||||
const [ additionalExcluded, additionalIncluded ] = await checkExclude(
|
||||
additional.remove || additional,
|
||||
additional.include || []
|
||||
);
|
||||
excluded.push( ...additionalExcluded );
|
||||
included.push( ...additionalIncluded );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
grunt.log.error( "Module \"" + module + "\" is a minimum requirement." );
|
||||
}
|
||||
} else {
|
||||
grunt.log.writeln( flag );
|
||||
included.push( module );
|
||||
}
|
||||
};
|
||||
|
||||
// Filename can be passed to the command line using
|
||||
// command line options
|
||||
// e.g. grunt build --filename=jquery-custom.js
|
||||
name = name ? ( "dist/" + name ) : this.data.dest;
|
||||
|
||||
// append commit id to version
|
||||
if ( process.env.COMMIT ) {
|
||||
version += " " + process.env.COMMIT;
|
||||
}
|
||||
|
||||
// figure out which files to exclude based on these rules in this order:
|
||||
// dependency explicit exclude
|
||||
// > explicit exclude
|
||||
// > explicit include
|
||||
// > dependency implicit exclude
|
||||
// > implicit exclude
|
||||
// examples:
|
||||
// * none (implicit exclude)
|
||||
// *:* all (implicit include)
|
||||
// *:*:-css all except css and dependents (explicit > implicit)
|
||||
// *:*:-css:+effects same (excludes effects because explicit include is
|
||||
// trumped by explicit exclude of dependency)
|
||||
// *:+effects none except effects and its dependencies
|
||||
// (explicit include trumps implicit exclude of dependency)
|
||||
delete flags[ "*" ];
|
||||
for ( flag in flags ) {
|
||||
excluder( flag );
|
||||
return [ unique( excluded ), unique( included ) ];
|
||||
}
|
||||
|
||||
async function build( {
|
||||
amd,
|
||||
dir = "dist",
|
||||
exclude = [],
|
||||
filename = "jquery.js",
|
||||
include = [],
|
||||
slim = false,
|
||||
version
|
||||
} = {} ) {
|
||||
|
||||
// Add the short commit hash to the version string
|
||||
// when the version is not for a release.
|
||||
if ( !version ) {
|
||||
const { stdout } = await exec( "git rev-parse --short HEAD" );
|
||||
const isClean = await isCleanWorkingDir();
|
||||
|
||||
// Add "+SHA" if the version is not set.
|
||||
// Add ".dirty" as well if the working dir is not clean.
|
||||
version = `${pkg.version}+${stdout.trim()}${isClean ? "" : ".dirty"}`;
|
||||
}
|
||||
|
||||
// Handle full selector module exclusion.
|
||||
// Replace with selector-native.
|
||||
if ( excluded.indexOf( "selector" ) > -1 ) {
|
||||
config.rawText.selector = "define([ \"./selector-native\" ]);";
|
||||
}
|
||||
await fs.promises.mkdir( dir, { recursive: true } );
|
||||
|
||||
// Exclude slim modules when slim is true
|
||||
const [ excluded, included ] = await checkExclude(
|
||||
slim ? exclude.concat( excludedFromSlim ) : exclude,
|
||||
include
|
||||
);
|
||||
const config = await getRequireConfig( { amd } );
|
||||
|
||||
// Replace exports/global with a noop noConflict
|
||||
if ( ( index = excluded.indexOf( "exports/global" ) ) > -1 ) {
|
||||
if ( excluded.includes( "exports/global" ) ) {
|
||||
const index = excluded.indexOf( "exports/global" );
|
||||
config.rawText[ "exports/global" ] = "define( [\n\t\"../core\"\n], " +
|
||||
"function( jQuery ) {\n\tjQuery.noConflict = function() {};\n} );";
|
||||
excluded.splice( index, 1 );
|
||||
}
|
||||
|
||||
grunt.verbose.writeflags( excluded, "Excluded" );
|
||||
grunt.verbose.writeflags( included, "Included" );
|
||||
// "sizzle" is legacy for selector
|
||||
if ( excluded.indexOf( "selector" ) > -1 || excluded.indexOf( "sizzle" ) > -1 ) {
|
||||
config.rawText.selector = "define( [ \"./selector-native\" ] );";
|
||||
}
|
||||
|
||||
// append excluded modules to version
|
||||
if ( excluded.length ) {
|
||||
|
||||
// Append excluded modules to version.
|
||||
// Skip adding exclusions for slim builds.
|
||||
// Don't worry about semver syntax for these.
|
||||
if ( excluded.length ) {
|
||||
version += " -" + excluded.join( ",-" );
|
||||
|
||||
// set pkg.version to version with excludes, so minified file picks it up
|
||||
grunt.config.set( "pkg.version", version );
|
||||
grunt.verbose.writeln( "Version changed to " + version );
|
||||
}
|
||||
|
||||
// Have to use shallow or core will get excluded since it is a dependency
|
||||
config.excludeShallow = excluded;
|
||||
}
|
||||
|
||||
if ( included.length ) {
|
||||
config.include = included;
|
||||
|
||||
// Append extra included modules to version.
|
||||
if ( included.length ) {
|
||||
version += " +" + included.join( ",+" );
|
||||
}
|
||||
|
||||
// Overwrite the default inclusions with the explicit ones provided
|
||||
config.rawText.jquery = "define( [\n" +
|
||||
included.map( module => "\t\"./" + module + "\"" ).join( ",\n" ) +
|
||||
"\n] );";
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Final output from the optimizer
|
||||
* @param {String} compiled
|
||||
*/
|
||||
config.out = function( compiled ) {
|
||||
compiled = compiled
|
||||
config.out = async function( compiled ) {
|
||||
const compiledContents = compiled
|
||||
|
||||
// Embed Version
|
||||
.replace( /@VERSION/g, version )
|
||||
|
||||
// Embed Date
|
||||
// yyyy-mm-ddThh:mmZ
|
||||
.replace( /@DATE/g, ( new Date() ).toISOString().replace( /:\d+\.\d+Z$/, "Z" ) );
|
||||
.replace( /@DATE/g, new Date().toISOString().replace( /:\d+\.\d+Z$/, "Z" ) );
|
||||
|
||||
// Write concatenated source to file
|
||||
grunt.file.write( name, compiled );
|
||||
await fs.promises.writeFile(
|
||||
path.join( dir, filename ),
|
||||
compiledContents
|
||||
);
|
||||
};
|
||||
|
||||
// Turn off opt-in if necessary
|
||||
if ( !optIn ) {
|
||||
await new Promise( ( resolve, reject ) => {
|
||||
requirejs.optimize( config, () => {
|
||||
|
||||
// Overwrite the default inclusions with the explicit ones provided
|
||||
config.rawText.jquery = "define( [\n" +
|
||||
( included.length ?
|
||||
included.map( module => "\t\"./" + module + "\"" ).join( ",\n" ) :
|
||||
"" ) +
|
||||
"\n] );";
|
||||
// Wait a beat. For some reason, the write can
|
||||
// take a moment after this to complete in Node 10.
|
||||
setTimeout( resolve, 100 );
|
||||
}, ( error ) => {
|
||||
console.error( error );
|
||||
reject( error );
|
||||
} );
|
||||
} );
|
||||
|
||||
console.log( `[${getTimestamp()}] ${filename} v${version} created.` );
|
||||
|
||||
await minify( { filename, dir } );
|
||||
}
|
||||
|
||||
async function buildDefaultFiles( { version } = {} ) {
|
||||
await Promise.all( [
|
||||
build( { version } ),
|
||||
build( { filename: "jquery.slim.js", slim: true, version } )
|
||||
] );
|
||||
|
||||
// Earlier Node.js versions do not support the ESM format.
|
||||
if ( !verifyNodeVersion() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Trace dependencies and concatenate files
|
||||
requirejs.optimize( config, function( response ) {
|
||||
grunt.verbose.writeln( response );
|
||||
grunt.log.ok( "File '" + name + "' created." );
|
||||
done();
|
||||
}, function( err ) {
|
||||
done( err );
|
||||
} );
|
||||
const { compareSize } = await import( "./compare_size.mjs" );
|
||||
return compareSize( {
|
||||
files: [
|
||||
"dist/jquery.min.js",
|
||||
"dist/jquery.slim.min.js"
|
||||
]
|
||||
} );
|
||||
}
|
||||
|
||||
// Special "alias" task to make custom build creation less grawlix-y
|
||||
// Translation example
|
||||
//
|
||||
// grunt custom:+ajax,-dimensions,-effects,-offset
|
||||
//
|
||||
// Becomes:
|
||||
//
|
||||
// grunt build:*:*:+ajax:-dimensions:-effects:-offset
|
||||
//
|
||||
// There's also a special "slim" alias that resolves to the jQuery Slim build
|
||||
// configuration:
|
||||
//
|
||||
// grunt custom:slim
|
||||
grunt.registerTask( "custom", function() {
|
||||
var args = this.args,
|
||||
modules = args.length ?
|
||||
args[ 0 ]
|
||||
.split( "," )
|
||||
|
||||
// Replace "slim" with respective exclusions meant for
|
||||
// the official slim build
|
||||
.reduce( ( acc, elem ) => acc.concat(
|
||||
elem === "slim" ?
|
||||
slimBuildFlags :
|
||||
[ elem ]
|
||||
), [] )
|
||||
|
||||
.join( ":" ) :
|
||||
"";
|
||||
|
||||
grunt.log.writeln( "Creating custom build...\n" );
|
||||
grunt.task.run( [
|
||||
"build:*:*" + ( modules ? ":" + modules : "" ),
|
||||
"uglify",
|
||||
"remove_map_comment",
|
||||
"dist"
|
||||
] );
|
||||
} );
|
||||
};
|
||||
module.exports = { build, buildDefaultFiles };
|
||||
|
174
build/tasks/compare_size.mjs
Normal file
174
build/tasks/compare_size.mjs
Normal file
@ -0,0 +1,174 @@
|
||||
import chalk from "chalk";
|
||||
import fs from "node:fs";
|
||||
import { promisify } from "node:util";
|
||||
import zlib from "node:zlib";
|
||||
import { exec as nodeExec } from "node:child_process";
|
||||
import isCleanWorkingDir from "./lib/isCleanWorkingDir.js";
|
||||
|
||||
const VERSION = 1;
|
||||
|
||||
const gzip = promisify( zlib.gzip );
|
||||
const exec = promisify( nodeExec );
|
||||
|
||||
async function getBranchName() {
|
||||
const { stdout } = await exec( "git rev-parse --abbrev-ref HEAD" );
|
||||
return stdout.trim();
|
||||
}
|
||||
|
||||
async function getCommitHash() {
|
||||
const { stdout } = await exec( "git rev-parse HEAD" );
|
||||
return stdout.trim();
|
||||
}
|
||||
|
||||
function getBranchHeader( branch, commit ) {
|
||||
let branchHeader = branch.trim();
|
||||
if ( commit ) {
|
||||
branchHeader = chalk.bold( branchHeader ) + chalk.gray( ` @${commit}` );
|
||||
} else {
|
||||
branchHeader = chalk.italic( branchHeader );
|
||||
}
|
||||
return branchHeader;
|
||||
}
|
||||
|
||||
async function getCache( loc ) {
|
||||
let cache;
|
||||
try {
|
||||
const contents = await fs.promises.readFile( loc, "utf8" );
|
||||
cache = JSON.parse( contents );
|
||||
} catch ( err ) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const lastRun = cache[ " last run" ];
|
||||
if ( !lastRun || !lastRun.meta || lastRun.meta.version !== VERSION ) {
|
||||
console.log( "Compare cache version mismatch. Rewriting..." );
|
||||
return {};
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
|
||||
function cacheResults( results ) {
|
||||
const files = Object.create( null );
|
||||
results.forEach( function( result ) {
|
||||
files[ result.filename ] = {
|
||||
raw: result.raw,
|
||||
gz: result.gz
|
||||
};
|
||||
} );
|
||||
return files;
|
||||
}
|
||||
|
||||
function saveCache( loc, cache ) {
|
||||
return fs.promises.writeFile( loc, JSON.stringify( cache ) );
|
||||
}
|
||||
|
||||
function compareSizes( existing, current, padLength ) {
|
||||
if ( typeof current !== "number" ) {
|
||||
return chalk.grey( `${existing}`.padStart( padLength ) );
|
||||
}
|
||||
const delta = current - existing;
|
||||
if ( delta > 0 ) {
|
||||
return chalk.red( `+${delta}`.padStart( padLength ) );
|
||||
}
|
||||
return chalk.green( `${delta}`.padStart( padLength ) );
|
||||
}
|
||||
|
||||
export async function compareSize( { cache = ".sizecache.json", files } = {} ) {
|
||||
if ( !files || !files.length ) {
|
||||
throw new Error( "No files specified" );
|
||||
}
|
||||
|
||||
const branch = await getBranchName();
|
||||
const commit = await getCommitHash();
|
||||
const sizeCache = await getCache( cache );
|
||||
|
||||
let rawPadLength = 0;
|
||||
let gzPadLength = 0;
|
||||
const results = await Promise.all(
|
||||
files.map( async function( filename ) {
|
||||
|
||||
let contents = await fs.promises.readFile( filename, "utf8" );
|
||||
|
||||
// Remove the short SHA and .dirty from comparisons.
|
||||
// The short SHA so commits can be compared against each other
|
||||
// and .dirty to compare with the existing branch during development.
|
||||
const sha = /jQuery v\d+.\d+.\d+(?:-\w+)?\+(?:slim.)?([^ \.]+(?:\.dirty)?)/.exec( contents )[ 1 ];
|
||||
contents = contents.replace( new RegExp( sha, "g" ), "" );
|
||||
|
||||
const size = Buffer.byteLength( contents, "utf8" );
|
||||
const gzippedSize = ( await gzip( contents ) ).length;
|
||||
|
||||
// Add one to give space for the `+` or `-` in the comparison
|
||||
rawPadLength = Math.max( rawPadLength, size.toString().length + 1 );
|
||||
gzPadLength = Math.max( gzPadLength, gzippedSize.toString().length + 1 );
|
||||
|
||||
return { filename, raw: size, gz: gzippedSize };
|
||||
} )
|
||||
);
|
||||
|
||||
const sizeHeader = "raw".padStart( rawPadLength ) +
|
||||
"gz".padStart( gzPadLength + 1 ) +
|
||||
" Filename";
|
||||
|
||||
const sizes = results.map( function( result ) {
|
||||
const rawSize = result.raw.toString().padStart( rawPadLength );
|
||||
const gzSize = result.gz.toString().padStart( gzPadLength );
|
||||
return `${rawSize} ${gzSize} ${result.filename}`;
|
||||
} );
|
||||
|
||||
const comparisons = Object.keys( sizeCache ).map( function( branch ) {
|
||||
const meta = sizeCache[ branch ].meta || {};
|
||||
const commit = meta.commit;
|
||||
|
||||
const files = sizeCache[ branch ].files;
|
||||
const branchSizes = Object.keys( files ).map( function( filename ) {
|
||||
const branchResult = files[ filename ];
|
||||
const compareResult = results.find( function( result ) {
|
||||
return result.filename === filename;
|
||||
} ) || {};
|
||||
|
||||
const compareRaw = compareSizes( branchResult.raw, compareResult.raw, rawPadLength );
|
||||
const compareGz = compareSizes( branchResult.gz, compareResult.gz, gzPadLength );
|
||||
return `${compareRaw} ${compareGz} ${filename}`;
|
||||
} );
|
||||
|
||||
return [
|
||||
"", // New line before each branch
|
||||
getBranchHeader( branch, commit ),
|
||||
sizeHeader,
|
||||
...branchSizes
|
||||
].join( "\n" );
|
||||
} );
|
||||
|
||||
const output = [
|
||||
"", // Opening new line
|
||||
chalk.bold( "Sizes" ),
|
||||
sizeHeader,
|
||||
...sizes,
|
||||
...comparisons,
|
||||
"" // Closing new line
|
||||
].join( "\n" );
|
||||
|
||||
console.log( output );
|
||||
|
||||
// Always save the last run
|
||||
// Save version under last run
|
||||
sizeCache[ " last run" ] = {
|
||||
meta: { version: VERSION },
|
||||
files: cacheResults( results )
|
||||
};
|
||||
|
||||
// Only save cache for the current branch
|
||||
// if the working directory is clean.
|
||||
if ( await isCleanWorkingDir() ) {
|
||||
sizeCache[ branch ] = {
|
||||
meta: { commit },
|
||||
files: cacheResults( results )
|
||||
};
|
||||
console.log( `Saved cache for ${branch}.` );
|
||||
}
|
||||
|
||||
await saveCache( cache, sizeCache );
|
||||
|
||||
return results;
|
||||
}
|
@ -1,71 +1,31 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function( grunt ) {
|
||||
const fs = require( "fs" );
|
||||
const filename = grunt.option( "filename" );
|
||||
const distPaths = [
|
||||
`dist/${ filename }`,
|
||||
`dist/${ filename.replace( ".js", ".min.js" ) }`,
|
||||
`dist/${ filename.replace( ".js", ".min.map" ) }`
|
||||
];
|
||||
// Process files for distribution.
|
||||
module.exports = function processForDist( text, filename ) {
|
||||
if ( !text ) {
|
||||
throw new Error( "text required for processForDist" );
|
||||
}
|
||||
|
||||
// Process files for distribution
|
||||
grunt.registerTask( "dist", function() {
|
||||
let stored, flags, paths, nonascii;
|
||||
|
||||
// Check for stored destination paths
|
||||
// ( set in dist/.destination.json )
|
||||
stored = Object.keys( grunt.config( "dst" ) );
|
||||
|
||||
// Allow command line input as well
|
||||
flags = Object.keys( this.flags );
|
||||
|
||||
// Combine all output target paths
|
||||
paths = [].concat( stored, flags ).filter( function( path ) {
|
||||
return path !== "*";
|
||||
} );
|
||||
|
||||
// Ensure the dist files are pure ASCII
|
||||
nonascii = false;
|
||||
|
||||
distPaths.forEach( function( filename ) {
|
||||
let i, c;
|
||||
const text = fs.readFileSync( filename, "utf8" );
|
||||
if ( !filename ) {
|
||||
throw new Error( "filename required for processForDist" );
|
||||
}
|
||||
|
||||
// Ensure files use only \n for line endings, not \r\n
|
||||
if ( /\x0d\x0a/.test( text ) ) {
|
||||
grunt.log.writeln( filename + ": Incorrect line endings (\\r\\n)" );
|
||||
nonascii = true;
|
||||
throw new Error( filename + ": Incorrect line endings (\\r\\n)" );
|
||||
}
|
||||
|
||||
// Ensure only ASCII chars so script tags don't need a charset attribute
|
||||
if ( text.length !== Buffer.byteLength( text, "utf8" ) ) {
|
||||
grunt.log.writeln( filename + ": Non-ASCII characters detected:" );
|
||||
for ( i = 0; i < text.length; i++ ) {
|
||||
c = text.charCodeAt( i );
|
||||
let message = filename + ": Non-ASCII characters detected:\n";
|
||||
for ( let i = 0; i < text.length; i++ ) {
|
||||
const c = text.charCodeAt( i );
|
||||
if ( c > 127 ) {
|
||||
grunt.log.writeln( "- position " + i + ": " + c );
|
||||
grunt.log.writeln( "-- " + text.substring( i - 20, i + 20 ) );
|
||||
message += "- position " + i + ": " + c + "\n";
|
||||
message += "==> " + text.substring( i - 20, i + 20 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
nonascii = true;
|
||||
throw new Error( message );
|
||||
}
|
||||
|
||||
// Optionally copy dist files to other locations
|
||||
paths.forEach( function( path ) {
|
||||
let created;
|
||||
|
||||
if ( !/\/$/.test( path ) ) {
|
||||
path += "/";
|
||||
}
|
||||
|
||||
created = path + filename.replace( "dist/", "" );
|
||||
grunt.file.write( created, text );
|
||||
grunt.log.writeln( "File '" + created + "' created." );
|
||||
} );
|
||||
} );
|
||||
|
||||
return !nonascii;
|
||||
} );
|
||||
};
|
||||
|
9
build/tasks/lib/getTimestamp.js
Normal file
9
build/tasks/lib/getTimestamp.js
Normal file
@ -0,0 +1,9 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function getTimestamp() {
|
||||
const now = new Date();
|
||||
const hours = now.getHours().toString().padStart( 2, "0" );
|
||||
const minutes = now.getMinutes().toString().padStart( 2, "0" );
|
||||
const seconds = now.getSeconds().toString().padStart( 2, "0" );
|
||||
return `${hours}:${minutes}:${seconds}`;
|
||||
};
|
9
build/tasks/lib/isCleanWorkingDir.js
Normal file
9
build/tasks/lib/isCleanWorkingDir.js
Normal file
@ -0,0 +1,9 @@
|
||||
"use strict";
|
||||
|
||||
const util = require( "util" );
|
||||
const exec = util.promisify( require( "child_process" ).exec );
|
||||
|
||||
module.exports = async function isCleanWorkingDir() {
|
||||
const { stdout } = await exec( "git status --untracked-files=no --porcelain" );
|
||||
return !stdout.trim();
|
||||
};
|
@ -2,6 +2,6 @@
|
||||
|
||||
// NOTE: keep it in sync with test/data/testinit.js
|
||||
module.exports = [
|
||||
"-ajax",
|
||||
"-effects"
|
||||
"ajax",
|
||||
"effects"
|
||||
];
|
@ -1,16 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
// Run Node with provided parameters: the first one being the Grunt
|
||||
// done function and latter ones being files to be tested.
|
||||
// See the comment in ../node_smoke_tests.js for more information.
|
||||
module.exports = function spawnTest( done, command ) {
|
||||
var spawn = require( "child_process" ).spawn;
|
||||
|
||||
spawn( command, {
|
||||
stdio: "inherit",
|
||||
shell: true
|
||||
} )
|
||||
.on( "close", function( code ) {
|
||||
done( code === 0 );
|
||||
} );
|
||||
};
|
12
build/tasks/lib/verifyNodeVersion.js
Normal file
12
build/tasks/lib/verifyNodeVersion.js
Normal file
@ -0,0 +1,12 @@
|
||||
"use strict";
|
||||
|
||||
const { version } = require( "process" );
|
||||
const nodeV16OrNewer = !/^v1[0-5]\./.test( version );
|
||||
|
||||
module.exports = function verifyNodeVersion() {
|
||||
if ( !nodeV16OrNewer ) {
|
||||
console.log( "Old Node.js detected, task skipped..." );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
83
build/tasks/minify.js
Normal file
83
build/tasks/minify.js
Normal file
@ -0,0 +1,83 @@
|
||||
"use strict";
|
||||
|
||||
const UglifyJS = require( "uglify-js" );
|
||||
const fs = require( "fs" );
|
||||
const path = require( "path" );
|
||||
const processForDist = require( "./dist" );
|
||||
const getTimestamp = require( "./lib/getTimestamp" );
|
||||
|
||||
const rjs = /\.js$/;
|
||||
|
||||
module.exports = async function minify( { dir, filename } ) {
|
||||
const filepath = path.join( dir, filename );
|
||||
const contents = await fs.promises.readFile( filepath, "utf8" );
|
||||
const version = /jQuery JavaScript Library ([^\n]+)/.exec( contents )[ 1 ];
|
||||
const banner = `/*! jQuery ${version}` +
|
||||
" | (c) OpenJS Foundation and other contributors" +
|
||||
" | jquery.org/license */";
|
||||
|
||||
const minFilename = filename.replace( rjs, ".min.js" );
|
||||
const mapFilename = filename.replace( rjs, ".min.map" );
|
||||
|
||||
const { code, error, map: incompleteMap, warning } = UglifyJS.minify(
|
||||
contents,
|
||||
{
|
||||
compress: {
|
||||
hoist_funs: false,
|
||||
loops: false,
|
||||
|
||||
// Support: IE <11
|
||||
// typeofs transformation is unsafe for IE9-10
|
||||
// See https://github.com/mishoo/UglifyJS2/issues/2198
|
||||
typeofs: false
|
||||
},
|
||||
output: {
|
||||
ascii_only: true,
|
||||
|
||||
// Support: Android 4.0 only
|
||||
// UglifyJS 3 breaks Android 4.0 if this option is not enabled.
|
||||
// This is in lieu of setting ie for all of mangle, compress, and output
|
||||
ie8: true,
|
||||
preamble: banner
|
||||
},
|
||||
sourceMap: {
|
||||
filename: minFilename
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if ( error ) {
|
||||
throw new Error( error );
|
||||
}
|
||||
|
||||
if ( warning ) {
|
||||
console.warn( warning );
|
||||
}
|
||||
|
||||
// The map's `sources` property is set to an array index.
|
||||
// Fix it by setting it to the correct filename.
|
||||
const map = JSON.stringify( {
|
||||
...JSON.parse( incompleteMap ),
|
||||
file: minFilename,
|
||||
sources: [ filename ]
|
||||
} );
|
||||
|
||||
await Promise.all( [
|
||||
fs.promises.writeFile(
|
||||
path.join( dir, minFilename ),
|
||||
code
|
||||
),
|
||||
fs.promises.writeFile(
|
||||
path.join( dir, mapFilename ),
|
||||
map
|
||||
)
|
||||
] );
|
||||
|
||||
// Always process files for dist
|
||||
// Doing it here avoids extra file reads
|
||||
processForDist( contents, filename );
|
||||
processForDist( code, minFilename );
|
||||
processForDist( map, mapFilename );
|
||||
|
||||
console.log( `[${getTimestamp()}] ${minFilename} ${version} with ${mapFilename} created.` );
|
||||
};
|
@ -1,42 +1,42 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = ( grunt ) => {
|
||||
const fs = require( "fs" );
|
||||
const spawnTest = require( "./lib/spawn_test.js" );
|
||||
const nodeV16OrNewer = !/^v1[0-5]\./.test( process.version );
|
||||
const fs = require( "fs" );
|
||||
const util = require( "util" );
|
||||
const exec = util.promisify( require( "child_process" ).exec );
|
||||
const verifyNodeVersion = require( "./lib/verifyNodeVersion" );
|
||||
|
||||
grunt.registerTask( "node_smoke_tests", function( jQueryModuleSpecifier = "./dist/jquery.js" ) {
|
||||
if ( !nodeV16OrNewer ) {
|
||||
grunt.log.writeln( "Old Node.js detected, running the task " +
|
||||
`"node_smoke_tests:${ jQueryModuleSpecifier }" skipped...` );
|
||||
if ( !verifyNodeVersion() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Fire up all tests defined in test/node_smoke_tests/*.js in spawned sub-processes.
|
||||
// All the files under test/node_smoke_tests/*.js are supposed to exit with 0 code
|
||||
// on success or another one on failure. Spawning in sub-processes is
|
||||
// important so that the tests & the main process don't interfere with
|
||||
// each other, e.g. so that they don't share the `require` cache.
|
||||
|
||||
async function runTests( { module } ) {
|
||||
const dir = "./test/node_smoke_tests";
|
||||
const files = await fs.promises.readdir( dir, { withFileTypes: true } );
|
||||
const testFiles = files.filter( ( testFilePath ) => testFilePath.isFile() );
|
||||
|
||||
if ( !testFiles.length ) {
|
||||
throw new Error( `No test files found for "${module}"` );
|
||||
}
|
||||
|
||||
const testsDir = "./test/node_smoke_tests";
|
||||
const nodeSmokeTests = [];
|
||||
|
||||
// Fire up all tests defined in test/node_smoke_tests/*.js in spawned sub-processes.
|
||||
// All the files under test/node_smoke_tests/*.js are supposed to exit with 0 code
|
||||
// on success or another one on failure. Spawning in sub-processes is
|
||||
// important so that the tests & the main process don't interfere with
|
||||
// each other, e.g. so that they don't share the `require` cache.
|
||||
|
||||
fs.readdirSync( testsDir )
|
||||
.filter( ( testFilePath ) =>
|
||||
fs.statSync( `${ testsDir }/${ testFilePath }` ).isFile() &&
|
||||
/\.[cm]?js$/.test( testFilePath )
|
||||
await Promise.all(
|
||||
testFiles.map( ( testFile ) =>
|
||||
exec( `node "${dir}/${testFile.name}" ${module}` )
|
||||
)
|
||||
.forEach( ( testFilePath ) => {
|
||||
const taskName = `node_${ testFilePath.replace( /\.[cm]?js$/, "" ) }:${ jQueryModuleSpecifier }`;
|
||||
);
|
||||
console.log( `Node smoke tests passed for "${module}".` );
|
||||
}
|
||||
|
||||
grunt.registerTask( taskName, function() {
|
||||
spawnTest( this.async(), `node "${ testsDir }/${
|
||||
testFilePath }" ${ jQueryModuleSpecifier }` );
|
||||
} );
|
||||
async function runDefaultTests() {
|
||||
await Promise.all( [
|
||||
runTests( { module: "./dist/jquery.js" } ),
|
||||
runTests( { module: "./dist/jquery.slim.js" } )
|
||||
] );
|
||||
}
|
||||
|
||||
nodeSmokeTests.push( taskName );
|
||||
} );
|
||||
|
||||
grunt.task.run( nodeSmokeTests );
|
||||
} );
|
||||
};
|
||||
runDefaultTests();
|
||||
|
42
build/tasks/npmcopy.js
Normal file
42
build/tasks/npmcopy.js
Normal file
@ -0,0 +1,42 @@
|
||||
"use strict";
|
||||
|
||||
const fs = require( "fs" );
|
||||
const path = require( "path" );
|
||||
|
||||
const projectDir = path.resolve( __dirname, "..", ".." );
|
||||
|
||||
const files = {
|
||||
"bootstrap/bootstrap.css": "bootstrap/dist/css/bootstrap.css",
|
||||
"bootstrap/bootstrap.min.css": "bootstrap/dist/css/bootstrap.min.css",
|
||||
"bootstrap/bootstrap.min.css.map": "bootstrap/dist/css/bootstrap.min.css.map",
|
||||
|
||||
"core-js-bundle/core-js-bundle.js": "core-js-bundle/minified.js",
|
||||
"core-js-bundle/LICENSE": "core-js-bundle/LICENSE",
|
||||
|
||||
"npo/npo.js": "native-promise-only/lib/npo.src.js",
|
||||
|
||||
"qunit/qunit.js": "qunit/qunit/qunit.js",
|
||||
"qunit/qunit.css": "qunit/qunit/qunit.css",
|
||||
"qunit/LICENSE.txt": "qunit/LICENSE.txt",
|
||||
|
||||
"requirejs/require.js": "requirejs/require.js",
|
||||
|
||||
"sinon/sinon.js": "sinon/pkg/sinon.js",
|
||||
"sinon/LICENSE.txt": "sinon/LICENSE"
|
||||
};
|
||||
|
||||
async function npmcopy() {
|
||||
await fs.promises.mkdir( path.resolve( projectDir, "external" ), {
|
||||
recursive: true
|
||||
} );
|
||||
for ( const [ dest, source ] of Object.entries( files ) ) {
|
||||
const from = path.resolve( projectDir, "node_modules", source );
|
||||
const to = path.resolve( projectDir, "external", dest );
|
||||
const toDir = path.dirname( to );
|
||||
await fs.promises.mkdir( toDir, { recursive: true } );
|
||||
await fs.promises.copyFile( from, to );
|
||||
console.log( `${source} → ${dest}` );
|
||||
}
|
||||
}
|
||||
|
||||
npmcopy();
|
@ -1,27 +1,32 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = grunt => {
|
||||
const timeout = 2000;
|
||||
const spawnTest = require( "./lib/spawn_test.js" );
|
||||
const { spawn } = require( "child_process" );
|
||||
const verifyNodeVersion = require( "./lib/verifyNodeVersion" );
|
||||
const path = require( "path" );
|
||||
const os = require( "os" );
|
||||
|
||||
grunt.registerTask( "promises_aplus_tests",
|
||||
[ "promises_aplus_tests:deferred", "promises_aplus_tests:when" ] );
|
||||
if ( !verifyNodeVersion() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
grunt.registerTask( "promises_aplus_tests:deferred", function() {
|
||||
spawnTest( this.async(),
|
||||
"\"" + __dirname + "/../../node_modules/.bin/promises-aplus-tests\"" +
|
||||
" test/promises_aplus_adapters/deferred.js" +
|
||||
" --reporter dot" +
|
||||
" --timeout " + timeout
|
||||
const command = path.resolve(
|
||||
__dirname,
|
||||
`../../node_modules/.bin/promises-aplus-tests${os.platform() === "win32" ? ".cmd" : ""}`
|
||||
);
|
||||
const args = [ "--reporter", "dot", "--timeout", "2000" ];
|
||||
const tests = [
|
||||
"test/promises_aplus_adapters/deferred.js",
|
||||
"test/promises_aplus_adapters/when.js"
|
||||
];
|
||||
|
||||
async function runTests() {
|
||||
tests.forEach( ( test ) => {
|
||||
spawn(
|
||||
command,
|
||||
[ test ].concat( args ),
|
||||
{ stdio: "inherit" }
|
||||
);
|
||||
} );
|
||||
}
|
||||
|
||||
grunt.registerTask( "promises_aplus_tests:when", function() {
|
||||
spawnTest( this.async(),
|
||||
"\"" + __dirname + "/../../node_modules/.bin/promises-aplus-tests\"" +
|
||||
" test/promises_aplus_adapters/when.js" +
|
||||
" --reporter dot" +
|
||||
" --timeout " + timeout
|
||||
);
|
||||
} );
|
||||
};
|
||||
runTests();
|
||||
|
17
build/tasks/qunit-fixture.js
Normal file
17
build/tasks/qunit-fixture.js
Normal file
@ -0,0 +1,17 @@
|
||||
"use strict";
|
||||
|
||||
const fs = require( "fs" );
|
||||
|
||||
async function generateFixture() {
|
||||
const fixture = await fs.promises.readFile( "./test/data/qunit-fixture.html", "utf8" );
|
||||
await fs.promises.writeFile(
|
||||
"./test/data/qunit-fixture.js",
|
||||
"// Generated by build/tasks/qunit-fixture.js\n" +
|
||||
"QUnit.config.fixture = " +
|
||||
JSON.stringify( fixture.replace( /\r\n/g, "\n" ) ) +
|
||||
";\n"
|
||||
);
|
||||
console.log( "Updated ./test/data/qunit-fixture.js" );
|
||||
}
|
||||
|
||||
generateFixture();
|
@ -1,22 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
var fs = require( "fs" );
|
||||
|
||||
module.exports = function( grunt ) {
|
||||
grunt.registerTask( "qunit_fixture", function() {
|
||||
var dest = "./test/data/qunit-fixture.js";
|
||||
fs.writeFileSync(
|
||||
dest,
|
||||
"// Generated by build/tasks/qunit_fixture.js\n" +
|
||||
"QUnit.config.fixture = " +
|
||||
JSON.stringify(
|
||||
fs.readFileSync(
|
||||
"./test/data/qunit-fixture.html",
|
||||
"utf8"
|
||||
).toString().replace( /\r\n/g, "\n" )
|
||||
) +
|
||||
";\n"
|
||||
);
|
||||
grunt.log.ok( "Updated " + dest + "." );
|
||||
} );
|
||||
};
|
@ -1,17 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
var fs = require( "fs" );
|
||||
|
||||
module.exports = function( grunt ) {
|
||||
var config = grunt.config( "uglify.all.files" );
|
||||
grunt.registerTask( "remove_map_comment", function() {
|
||||
var minLoc = grunt.config.process( Object.keys( config )[ 0 ] );
|
||||
|
||||
// Remove the source map comment; it causes way too many problems.
|
||||
// The map file is still generated for manual associations
|
||||
// https://github.com/jquery/jquery/issues/1707
|
||||
var text = fs.readFileSync( minLoc, "utf8" )
|
||||
.replace( /\/\/# sourceMappingURL=\S+/, "" );
|
||||
fs.writeFileSync( minLoc, text );
|
||||
} );
|
||||
};
|
35
dist/.eslintrc.json
vendored
35
dist/.eslintrc.json
vendored
@ -1,35 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 5,
|
||||
"sourceType": "script"
|
||||
},
|
||||
|
||||
"overrides": [
|
||||
{
|
||||
"files": "jquery{,.slim}.min.js",
|
||||
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 5,
|
||||
"sourceType": "script"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"files": "jquery{,.slim}.js",
|
||||
"extends": "../.eslintrc-browser.json",
|
||||
|
||||
"rules": {
|
||||
|
||||
// That is okay for the built version
|
||||
"no-multiple-empty-lines": "off",
|
||||
|
||||
// When custom compilation is used, the version string
|
||||
// can get large. Accept that in the built version.
|
||||
"max-len": "off",
|
||||
"one-var": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
271
eslint.config.js
Normal file
271
eslint.config.js
Normal file
@ -0,0 +1,271 @@
|
||||
"use strict";
|
||||
|
||||
const jqueryConfig = require( "eslint-config-jquery" );
|
||||
const globals = require( "globals" );
|
||||
|
||||
module.exports = [
|
||||
{
|
||||
|
||||
// Only global ignores will bypass the parser
|
||||
// and avoid JS parsing errors
|
||||
// See https://github.com/eslint/eslint/discussions/17412
|
||||
ignores: [
|
||||
"external",
|
||||
"test/data/json_obj.js"
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
files: [
|
||||
"eslint.config.js",
|
||||
"Gruntfile.js",
|
||||
"test/node_smoke_tests/**",
|
||||
"test/promises_aplus_adapters/**",
|
||||
"test/middleware-mockserver.js"
|
||||
],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node
|
||||
},
|
||||
sourceType: "commonjs"
|
||||
},
|
||||
rules: {
|
||||
...jqueryConfig.rules,
|
||||
strict: [ "error", "global" ]
|
||||
}
|
||||
},
|
||||
|
||||
// Source
|
||||
{
|
||||
files: [ "src/**" ],
|
||||
languageOptions: {
|
||||
|
||||
// The browser env is not enabled on purpose so that code takes
|
||||
// all browser-only globals from window instead of assuming
|
||||
// they're available as globals. This makes it possible to use
|
||||
// jQuery with tools like jsdom which provide a custom window
|
||||
// implementation.
|
||||
globals: {
|
||||
define: false,
|
||||
window: false
|
||||
},
|
||||
sourceType: "commonjs"
|
||||
},
|
||||
rules: {
|
||||
...jqueryConfig.rules,
|
||||
indent: [
|
||||
"error",
|
||||
"tab",
|
||||
{
|
||||
outerIIFEBody: 0,
|
||||
|
||||
// Ignore the top level function defining an AMD module
|
||||
ignoredNodes: [
|
||||
"Program > ExpressionStatement > CallExpression > :last-child > *"
|
||||
]
|
||||
}
|
||||
],
|
||||
"one-var": [ "error", { var: "always" } ],
|
||||
strict: [ "error", "function" ]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
files: [ "src/selector.js" ],
|
||||
rules: {
|
||||
indent: "off"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
files: [ "src/wrapper.js" ],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
jQuery: false,
|
||||
module: true
|
||||
},
|
||||
sourceType: "script"
|
||||
},
|
||||
rules: {
|
||||
"no-unused-vars": "off",
|
||||
indent: [
|
||||
"error",
|
||||
"tab",
|
||||
{
|
||||
|
||||
// Unlike other codes, "wrapper.js" is implemented in UMD.
|
||||
// So it required a specific exception for jQuery's UMD
|
||||
// Code Style. This makes that indentation check is not
|
||||
// performed for 1 depth of outer FunctionExpressions
|
||||
ignoredNodes: [
|
||||
"Program > ExpressionStatement > CallExpression > :last-child > *"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
files: [ "src/exports/amd.js" ],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
define: false
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Tests
|
||||
{
|
||||
files: [
|
||||
"test/**"
|
||||
],
|
||||
ignores: [
|
||||
"test/data/jquery-1.9.1.js",
|
||||
"test/data/badcall.js",
|
||||
"test/data/badjson.js",
|
||||
"test/data/support/csp.js",
|
||||
"test/data/support/getComputedSupport.js",
|
||||
"test/data/core/jquery-iterability-transpiled.js"
|
||||
],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.browser,
|
||||
require: false,
|
||||
Promise: false,
|
||||
Symbol: false,
|
||||
trustedTypes: false,
|
||||
QUnit: false,
|
||||
ajaxTest: false,
|
||||
testIframe: false,
|
||||
createDashboardXML: false,
|
||||
createWithFriesXML: false,
|
||||
createXMLFragment: false,
|
||||
includesModule: false,
|
||||
moduleTeardown: false,
|
||||
url: false,
|
||||
q: false,
|
||||
jQuery: true,
|
||||
sinon: true,
|
||||
amdDefined: true,
|
||||
fireNative: true,
|
||||
Globals: true,
|
||||
hasPHP: true,
|
||||
isLocal: true,
|
||||
supportjQuery: true,
|
||||
originaljQuery: true,
|
||||
$: true,
|
||||
original$: true,
|
||||
baseURL: true,
|
||||
externalHost: true
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
...jqueryConfig.rules,
|
||||
strict: [ "error", "function" ],
|
||||
|
||||
// See https://github.com/eslint/eslint/issues/2342
|
||||
"no-unused-vars": "off",
|
||||
|
||||
// Too many errors
|
||||
"max-len": "off",
|
||||
camelcase: "off",
|
||||
"one-var": "off"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
files: [
|
||||
"test/data/testrunner.js",
|
||||
"test/data/core/jquery-iterability-transpiled-es6.js"
|
||||
],
|
||||
languageOptions: {
|
||||
sourceType: "script"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
files: [
|
||||
"test/unit/deferred.js"
|
||||
],
|
||||
rules: {
|
||||
|
||||
// Deferred tests set strict mode for certain tests
|
||||
strict: "off"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
files: [
|
||||
"test/node_smoke_tests/**",
|
||||
"test/promises_aplus_adapters/**",
|
||||
"test/middleware-mockserver.js"
|
||||
],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node,
|
||||
...globals.es2021
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
strict: [ "error", "global" ]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
files: [
|
||||
"build/**",
|
||||
"test/data/testinit.js",
|
||||
"test/data/testinit-jsdom.js"
|
||||
],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node,
|
||||
...globals.es2021
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
...jqueryConfig.rules,
|
||||
strict: [ "error", "global" ]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
files: [
|
||||
"build/**/*.js",
|
||||
"test/data/testinit.js",
|
||||
"test/data/testinit-jsdom.js"
|
||||
],
|
||||
languageOptions: {
|
||||
sourceType: "commonjs"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
files: [
|
||||
"dist/jquery.js",
|
||||
"dist/jquery.slim.js"
|
||||
],
|
||||
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.browser,
|
||||
...globals.es2021,
|
||||
define: false,
|
||||
module: false,
|
||||
Symbol: false
|
||||
}
|
||||
},
|
||||
|
||||
rules: {
|
||||
...jqueryConfig.rules,
|
||||
|
||||
// That is okay for the built version
|
||||
"no-multiple-empty-lines": "off",
|
||||
|
||||
// When custom compilation is used, the version string
|
||||
// can get large. Accept that in the built version.
|
||||
"max-len": "off",
|
||||
"one-var": "off"
|
||||
}
|
||||
}
|
||||
];
|
12071
external/bootstrap/bootstrap.css
vendored
12071
external/bootstrap/bootstrap.css
vendored
File diff suppressed because it is too large
Load Diff
6
external/bootstrap/bootstrap.min.css
vendored
6
external/bootstrap/bootstrap.min.css
vendored
File diff suppressed because one or more lines are too long
1
external/bootstrap/bootstrap.min.css.map
vendored
1
external/bootstrap/bootstrap.min.css.map
vendored
File diff suppressed because one or more lines are too long
19
external/core-js/LICENSE.txt
vendored
19
external/core-js/LICENSE.txt
vendored
@ -1,19 +0,0 @@
|
||||
Copyright (c) 2014-2019 Denis Pushkarev
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
10
external/core-js/core-js.js
vendored
10
external/core-js/core-js.js
vendored
File diff suppressed because one or more lines are too long
373
external/npo/npo.js
vendored
373
external/npo/npo.js
vendored
@ -1,373 +0,0 @@
|
||||
/*! Native Promise Only
|
||||
v0.8.1 (c) Kyle Simpson
|
||||
MIT License: http://getify.mit-license.org
|
||||
*/
|
||||
|
||||
(function UMD(name,context,definition){
|
||||
// special form of UMD for polyfilling across evironments
|
||||
context[name] = context[name] || definition();
|
||||
if (typeof module != "undefined" && module.exports) { module.exports = context[name]; }
|
||||
else if (typeof define == "function" && define.amd) { define(function $AMD$(){ return context[name]; }); }
|
||||
})("Promise",typeof global != "undefined" ? global : this,function DEF(){
|
||||
/*jshint validthis:true */
|
||||
"use strict";
|
||||
|
||||
var builtInProp, cycle, scheduling_queue,
|
||||
ToString = Object.prototype.toString,
|
||||
timer = (typeof setImmediate != "undefined") ?
|
||||
function timer(fn) { return setImmediate(fn); } :
|
||||
setTimeout
|
||||
;
|
||||
|
||||
// dammit, IE8.
|
||||
try {
|
||||
Object.defineProperty({},"x",{});
|
||||
builtInProp = function builtInProp(obj,name,val,config) {
|
||||
return Object.defineProperty(obj,name,{
|
||||
value: val,
|
||||
writable: true,
|
||||
configurable: config !== false
|
||||
});
|
||||
};
|
||||
}
|
||||
catch (err) {
|
||||
builtInProp = function builtInProp(obj,name,val) {
|
||||
obj[name] = val;
|
||||
return obj;
|
||||
};
|
||||
}
|
||||
|
||||
// Note: using a queue instead of array for efficiency
|
||||
scheduling_queue = (function Queue() {
|
||||
var first, last, item;
|
||||
|
||||
function Item(fn,self) {
|
||||
this.fn = fn;
|
||||
this.self = self;
|
||||
this.next = void 0;
|
||||
}
|
||||
|
||||
return {
|
||||
add: function add(fn,self) {
|
||||
item = new Item(fn,self);
|
||||
if (last) {
|
||||
last.next = item;
|
||||
}
|
||||
else {
|
||||
first = item;
|
||||
}
|
||||
last = item;
|
||||
item = void 0;
|
||||
},
|
||||
drain: function drain() {
|
||||
var f = first;
|
||||
first = last = cycle = void 0;
|
||||
|
||||
while (f) {
|
||||
f.fn.call(f.self);
|
||||
f = f.next;
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
function schedule(fn,self) {
|
||||
scheduling_queue.add(fn,self);
|
||||
if (!cycle) {
|
||||
cycle = timer(scheduling_queue.drain);
|
||||
}
|
||||
}
|
||||
|
||||
// promise duck typing
|
||||
function isThenable(o) {
|
||||
var _then, o_type = typeof o;
|
||||
|
||||
if (o != null &&
|
||||
(
|
||||
o_type == "object" || o_type == "function"
|
||||
)
|
||||
) {
|
||||
_then = o.then;
|
||||
}
|
||||
return typeof _then == "function" ? _then : false;
|
||||
}
|
||||
|
||||
function notify() {
|
||||
for (var i=0; i<this.chain.length; i++) {
|
||||
notifyIsolated(
|
||||
this,
|
||||
(this.state === 1) ? this.chain[i].success : this.chain[i].failure,
|
||||
this.chain[i]
|
||||
);
|
||||
}
|
||||
this.chain.length = 0;
|
||||
}
|
||||
|
||||
// NOTE: This is a separate function to isolate
|
||||
// the `try..catch` so that other code can be
|
||||
// optimized better
|
||||
function notifyIsolated(self,cb,chain) {
|
||||
var ret, _then;
|
||||
try {
|
||||
if (cb === false) {
|
||||
chain.reject(self.msg);
|
||||
}
|
||||
else {
|
||||
if (cb === true) {
|
||||
ret = self.msg;
|
||||
}
|
||||
else {
|
||||
ret = cb.call(void 0,self.msg);
|
||||
}
|
||||
|
||||
if (ret === chain.promise) {
|
||||
chain.reject(TypeError("Promise-chain cycle"));
|
||||
}
|
||||
else if (_then = isThenable(ret)) {
|
||||
_then.call(ret,chain.resolve,chain.reject);
|
||||
}
|
||||
else {
|
||||
chain.resolve(ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
chain.reject(err);
|
||||
}
|
||||
}
|
||||
|
||||
function resolve(msg) {
|
||||
var _then, self = this;
|
||||
|
||||
// already triggered?
|
||||
if (self.triggered) { return; }
|
||||
|
||||
self.triggered = true;
|
||||
|
||||
// unwrap
|
||||
if (self.def) {
|
||||
self = self.def;
|
||||
}
|
||||
|
||||
try {
|
||||
if (_then = isThenable(msg)) {
|
||||
schedule(function(){
|
||||
var def_wrapper = new MakeDefWrapper(self);
|
||||
try {
|
||||
_then.call(msg,
|
||||
function $resolve$(){ resolve.apply(def_wrapper,arguments); },
|
||||
function $reject$(){ reject.apply(def_wrapper,arguments); }
|
||||
);
|
||||
}
|
||||
catch (err) {
|
||||
reject.call(def_wrapper,err);
|
||||
}
|
||||
})
|
||||
}
|
||||
else {
|
||||
self.msg = msg;
|
||||
self.state = 1;
|
||||
if (self.chain.length > 0) {
|
||||
schedule(notify,self);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
reject.call(new MakeDefWrapper(self),err);
|
||||
}
|
||||
}
|
||||
|
||||
function reject(msg) {
|
||||
var self = this;
|
||||
|
||||
// already triggered?
|
||||
if (self.triggered) { return; }
|
||||
|
||||
self.triggered = true;
|
||||
|
||||
// unwrap
|
||||
if (self.def) {
|
||||
self = self.def;
|
||||
}
|
||||
|
||||
self.msg = msg;
|
||||
self.state = 2;
|
||||
if (self.chain.length > 0) {
|
||||
schedule(notify,self);
|
||||
}
|
||||
}
|
||||
|
||||
function iteratePromises(Constructor,arr,resolver,rejecter) {
|
||||
for (var idx=0; idx<arr.length; idx++) {
|
||||
(function IIFE(idx){
|
||||
Constructor.resolve(arr[idx])
|
||||
.then(
|
||||
function $resolver$(msg){
|
||||
resolver(idx,msg);
|
||||
},
|
||||
rejecter
|
||||
);
|
||||
})(idx);
|
||||
}
|
||||
}
|
||||
|
||||
function MakeDefWrapper(self) {
|
||||
this.def = self;
|
||||
this.triggered = false;
|
||||
}
|
||||
|
||||
function MakeDef(self) {
|
||||
this.promise = self;
|
||||
this.state = 0;
|
||||
this.triggered = false;
|
||||
this.chain = [];
|
||||
this.msg = void 0;
|
||||
}
|
||||
|
||||
function Promise(executor) {
|
||||
if (typeof executor != "function") {
|
||||
throw TypeError("Not a function");
|
||||
}
|
||||
|
||||
if (this.__NPO__ !== 0) {
|
||||
throw TypeError("Not a promise");
|
||||
}
|
||||
|
||||
// instance shadowing the inherited "brand"
|
||||
// to signal an already "initialized" promise
|
||||
this.__NPO__ = 1;
|
||||
|
||||
var def = new MakeDef(this);
|
||||
|
||||
this["then"] = function then(success,failure) {
|
||||
var o = {
|
||||
success: typeof success == "function" ? success : true,
|
||||
failure: typeof failure == "function" ? failure : false
|
||||
};
|
||||
// Note: `then(..)` itself can be borrowed to be used against
|
||||
// a different promise constructor for making the chained promise,
|
||||
// by substituting a different `this` binding.
|
||||
o.promise = new this.constructor(function extractChain(resolve,reject) {
|
||||
if (typeof resolve != "function" || typeof reject != "function") {
|
||||
throw TypeError("Not a function");
|
||||
}
|
||||
|
||||
o.resolve = resolve;
|
||||
o.reject = reject;
|
||||
});
|
||||
def.chain.push(o);
|
||||
|
||||
if (def.state !== 0) {
|
||||
schedule(notify,def);
|
||||
}
|
||||
|
||||
return o.promise;
|
||||
};
|
||||
this["catch"] = function $catch$(failure) {
|
||||
return this.then(void 0,failure);
|
||||
};
|
||||
|
||||
try {
|
||||
executor.call(
|
||||
void 0,
|
||||
function publicResolve(msg){
|
||||
resolve.call(def,msg);
|
||||
},
|
||||
function publicReject(msg) {
|
||||
reject.call(def,msg);
|
||||
}
|
||||
);
|
||||
}
|
||||
catch (err) {
|
||||
reject.call(def,err);
|
||||
}
|
||||
}
|
||||
|
||||
var PromisePrototype = builtInProp({},"constructor",Promise,
|
||||
/*configurable=*/false
|
||||
);
|
||||
|
||||
// Note: Android 4 cannot use `Object.defineProperty(..)` here
|
||||
Promise.prototype = PromisePrototype;
|
||||
|
||||
// built-in "brand" to signal an "uninitialized" promise
|
||||
builtInProp(PromisePrototype,"__NPO__",0,
|
||||
/*configurable=*/false
|
||||
);
|
||||
|
||||
builtInProp(Promise,"resolve",function Promise$resolve(msg) {
|
||||
var Constructor = this;
|
||||
|
||||
// spec mandated checks
|
||||
// note: best "isPromise" check that's practical for now
|
||||
if (msg && typeof msg == "object" && msg.__NPO__ === 1) {
|
||||
return msg;
|
||||
}
|
||||
|
||||
return new Constructor(function executor(resolve,reject){
|
||||
if (typeof resolve != "function" || typeof reject != "function") {
|
||||
throw TypeError("Not a function");
|
||||
}
|
||||
|
||||
resolve(msg);
|
||||
});
|
||||
});
|
||||
|
||||
builtInProp(Promise,"reject",function Promise$reject(msg) {
|
||||
return new this(function executor(resolve,reject){
|
||||
if (typeof resolve != "function" || typeof reject != "function") {
|
||||
throw TypeError("Not a function");
|
||||
}
|
||||
|
||||
reject(msg);
|
||||
});
|
||||
});
|
||||
|
||||
builtInProp(Promise,"all",function Promise$all(arr) {
|
||||
var Constructor = this;
|
||||
|
||||
// spec mandated checks
|
||||
if (ToString.call(arr) != "[object Array]") {
|
||||
return Constructor.reject(TypeError("Not an array"));
|
||||
}
|
||||
if (arr.length === 0) {
|
||||
return Constructor.resolve([]);
|
||||
}
|
||||
|
||||
return new Constructor(function executor(resolve,reject){
|
||||
if (typeof resolve != "function" || typeof reject != "function") {
|
||||
throw TypeError("Not a function");
|
||||
}
|
||||
|
||||
var len = arr.length, msgs = Array(len), count = 0;
|
||||
|
||||
iteratePromises(Constructor,arr,function resolver(idx,msg) {
|
||||
msgs[idx] = msg;
|
||||
if (++count === len) {
|
||||
resolve(msgs);
|
||||
}
|
||||
},reject);
|
||||
});
|
||||
});
|
||||
|
||||
builtInProp(Promise,"race",function Promise$race(arr) {
|
||||
var Constructor = this;
|
||||
|
||||
// spec mandated checks
|
||||
if (ToString.call(arr) != "[object Array]") {
|
||||
return Constructor.reject(TypeError("Not an array"));
|
||||
}
|
||||
|
||||
return new Constructor(function executor(resolve,reject){
|
||||
if (typeof resolve != "function" || typeof reject != "function") {
|
||||
throw TypeError("Not a function");
|
||||
}
|
||||
|
||||
iteratePromises(Constructor,arr,function resolver(idx,msg){
|
||||
resolve(msg);
|
||||
},reject);
|
||||
});
|
||||
});
|
||||
|
||||
return Promise;
|
||||
});
|
35
external/qunit/LICENSE.txt
vendored
35
external/qunit/LICENSE.txt
vendored
@ -1,35 +0,0 @@
|
||||
Copyright JS Foundation and other contributors, https://js.foundation
|
||||
|
||||
This software consists of voluntary contributions made by many
|
||||
individuals. For exact contribution history, see the revision history
|
||||
available at https://github.com/qunitjs/qunit
|
||||
|
||||
The following license applies to all parts of this software except as
|
||||
documented below:
|
||||
|
||||
====
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
====
|
||||
|
||||
All files located in the node_modules directory are externally maintained
|
||||
libraries used by this software which have their own licenses; we
|
||||
recommend you read them, as their terms may differ from the terms above.
|
436
external/qunit/qunit.css
vendored
436
external/qunit/qunit.css
vendored
@ -1,436 +0,0 @@
|
||||
/*!
|
||||
* QUnit 2.9.2
|
||||
* https://qunitjs.com/
|
||||
*
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
* Released under the MIT license
|
||||
* https://jquery.org/license
|
||||
*
|
||||
* Date: 2019-02-21T22:49Z
|
||||
*/
|
||||
|
||||
/** Font Family and Sizes */
|
||||
|
||||
#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult {
|
||||
font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
#qunit-testrunner-toolbar, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
|
||||
#qunit-tests { font-size: smaller; }
|
||||
|
||||
|
||||
/** Resets */
|
||||
|
||||
#qunit-tests, #qunit-header, #qunit-banner, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
/** Header (excluding toolbar) */
|
||||
|
||||
#qunit-header {
|
||||
padding: 0.5em 0 0.5em 1em;
|
||||
|
||||
color: #8699A4;
|
||||
background-color: #0D3349;
|
||||
|
||||
font-size: 1.5em;
|
||||
line-height: 1em;
|
||||
font-weight: 400;
|
||||
|
||||
border-radius: 5px 5px 0 0;
|
||||
}
|
||||
|
||||
#qunit-header a {
|
||||
text-decoration: none;
|
||||
color: #C2CCD1;
|
||||
}
|
||||
|
||||
#qunit-header a:hover,
|
||||
#qunit-header a:focus {
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
#qunit-banner {
|
||||
height: 5px;
|
||||
}
|
||||
|
||||
#qunit-filteredTest {
|
||||
padding: 0.5em 1em 0.5em 1em;
|
||||
color: #366097;
|
||||
background-color: #F4FF77;
|
||||
}
|
||||
|
||||
#qunit-userAgent {
|
||||
padding: 0.5em 1em 0.5em 1em;
|
||||
color: #FFF;
|
||||
background-color: #2B81AF;
|
||||
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
|
||||
}
|
||||
|
||||
|
||||
/** Toolbar */
|
||||
|
||||
#qunit-testrunner-toolbar {
|
||||
padding: 0.5em 1em 0.5em 1em;
|
||||
color: #5E740B;
|
||||
background-color: #EEE;
|
||||
}
|
||||
|
||||
#qunit-testrunner-toolbar .clearfix {
|
||||
height: 0;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
#qunit-testrunner-toolbar label {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#qunit-testrunner-toolbar input[type=checkbox],
|
||||
#qunit-testrunner-toolbar input[type=radio] {
|
||||
margin: 3px;
|
||||
vertical-align: -2px;
|
||||
}
|
||||
|
||||
#qunit-testrunner-toolbar input[type=text] {
|
||||
box-sizing: border-box;
|
||||
height: 1.6em;
|
||||
}
|
||||
|
||||
.qunit-url-config,
|
||||
.qunit-filter,
|
||||
#qunit-modulefilter {
|
||||
display: inline-block;
|
||||
line-height: 2.1em;
|
||||
}
|
||||
|
||||
.qunit-filter,
|
||||
#qunit-modulefilter {
|
||||
float: right;
|
||||
position: relative;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
.qunit-url-config label {
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
#qunit-modulefilter-search {
|
||||
box-sizing: border-box;
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
#qunit-modulefilter-search-container:after {
|
||||
position: absolute;
|
||||
right: 0.3em;
|
||||
content: "\25bc";
|
||||
color: black;
|
||||
}
|
||||
|
||||
#qunit-modulefilter-dropdown {
|
||||
/* align with #qunit-modulefilter-search */
|
||||
box-sizing: border-box;
|
||||
width: 400px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 50%;
|
||||
margin-top: 0.8em;
|
||||
|
||||
border: 1px solid #D3D3D3;
|
||||
border-top: none;
|
||||
border-radius: 0 0 .25em .25em;
|
||||
color: #000;
|
||||
background-color: #F5F5F5;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
#qunit-modulefilter-dropdown a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#qunit-modulefilter-dropdown .clickable.checked {
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
background-color: #D2E0E6;
|
||||
}
|
||||
|
||||
#qunit-modulefilter-dropdown .clickable:hover {
|
||||
color: #FFF;
|
||||
background-color: #0D3349;
|
||||
}
|
||||
|
||||
#qunit-modulefilter-actions {
|
||||
display: block;
|
||||
overflow: auto;
|
||||
|
||||
/* align with #qunit-modulefilter-dropdown-list */
|
||||
font: smaller/1.5em sans-serif;
|
||||
}
|
||||
|
||||
#qunit-modulefilter-dropdown #qunit-modulefilter-actions > * {
|
||||
box-sizing: border-box;
|
||||
max-height: 2.8em;
|
||||
display: block;
|
||||
padding: 0.4em;
|
||||
}
|
||||
|
||||
#qunit-modulefilter-dropdown #qunit-modulefilter-actions > button {
|
||||
float: right;
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
#qunit-modulefilter-dropdown #qunit-modulefilter-actions > :last-child {
|
||||
/* insert padding to align with checkbox margins */
|
||||
padding-left: 3px;
|
||||
}
|
||||
|
||||
#qunit-modulefilter-dropdown-list {
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
margin: 0;
|
||||
border-top: 2px groove threedhighlight;
|
||||
padding: 0.4em 0 0;
|
||||
font: smaller/1.5em sans-serif;
|
||||
}
|
||||
|
||||
#qunit-modulefilter-dropdown-list li {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
#qunit-modulefilter-dropdown-list .clickable {
|
||||
display: block;
|
||||
padding-left: 0.15em;
|
||||
}
|
||||
|
||||
|
||||
/** Tests: Pass/Fail */
|
||||
|
||||
#qunit-tests {
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
#qunit-tests li {
|
||||
padding: 0.4em 1em 0.4em 1em;
|
||||
border-bottom: 1px solid #FFF;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
#qunit-tests > li {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#qunit-tests li.running,
|
||||
#qunit-tests li.pass,
|
||||
#qunit-tests li.fail,
|
||||
#qunit-tests li.skipped,
|
||||
#qunit-tests li.aborted {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
#qunit-tests.hidepass {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#qunit-tests.hidepass li.running,
|
||||
#qunit-tests.hidepass li.pass:not(.todo) {
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#qunit-tests li strong {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#qunit-tests li.skipped strong {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
#qunit-tests li a {
|
||||
padding: 0.5em;
|
||||
color: #C2CCD1;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#qunit-tests li p a {
|
||||
padding: 0.25em;
|
||||
color: #6B6464;
|
||||
}
|
||||
#qunit-tests li a:hover,
|
||||
#qunit-tests li a:focus {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
#qunit-tests li .runtime {
|
||||
float: right;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
.qunit-assert-list {
|
||||
margin-top: 0.5em;
|
||||
padding: 0.5em;
|
||||
|
||||
background-color: #FFF;
|
||||
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.qunit-source {
|
||||
margin: 0.6em 0 0.3em;
|
||||
}
|
||||
|
||||
.qunit-collapsed {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#qunit-tests table {
|
||||
border-collapse: collapse;
|
||||
margin-top: 0.2em;
|
||||
}
|
||||
|
||||
#qunit-tests th {
|
||||
text-align: right;
|
||||
vertical-align: top;
|
||||
padding: 0 0.5em 0 0;
|
||||
}
|
||||
|
||||
#qunit-tests td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#qunit-tests pre {
|
||||
margin: 0;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
#qunit-tests del {
|
||||
color: #374E0C;
|
||||
background-color: #E0F2BE;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#qunit-tests ins {
|
||||
color: #500;
|
||||
background-color: #FFCACA;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/*** Test Counts */
|
||||
|
||||
#qunit-tests b.counts { color: #000; }
|
||||
#qunit-tests b.passed { color: #5E740B; }
|
||||
#qunit-tests b.failed { color: #710909; }
|
||||
|
||||
#qunit-tests li li {
|
||||
padding: 5px;
|
||||
background-color: #FFF;
|
||||
border-bottom: none;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
/*** Passing Styles */
|
||||
|
||||
#qunit-tests li li.pass {
|
||||
color: #3C510C;
|
||||
background-color: #FFF;
|
||||
border-left: 10px solid #C6E746;
|
||||
}
|
||||
|
||||
#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
|
||||
#qunit-tests .pass .test-name { color: #366097; }
|
||||
|
||||
#qunit-tests .pass .test-actual,
|
||||
#qunit-tests .pass .test-expected { color: #999; }
|
||||
|
||||
#qunit-banner.qunit-pass { background-color: #C6E746; }
|
||||
|
||||
/*** Failing Styles */
|
||||
|
||||
#qunit-tests li li.fail {
|
||||
color: #710909;
|
||||
background-color: #FFF;
|
||||
border-left: 10px solid #EE5757;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
#qunit-tests > li:last-child {
|
||||
border-radius: 0 0 5px 5px;
|
||||
}
|
||||
|
||||
#qunit-tests .fail { color: #000; background-color: #EE5757; }
|
||||
#qunit-tests .fail .test-name,
|
||||
#qunit-tests .fail .module-name { color: #000; }
|
||||
|
||||
#qunit-tests .fail .test-actual { color: #EE5757; }
|
||||
#qunit-tests .fail .test-expected { color: #008000; }
|
||||
|
||||
#qunit-banner.qunit-fail { background-color: #EE5757; }
|
||||
|
||||
|
||||
/*** Aborted tests */
|
||||
#qunit-tests .aborted { color: #000; background-color: orange; }
|
||||
/*** Skipped tests */
|
||||
|
||||
#qunit-tests .skipped {
|
||||
background-color: #EBECE9;
|
||||
}
|
||||
|
||||
#qunit-tests .qunit-todo-label,
|
||||
#qunit-tests .qunit-skipped-label {
|
||||
background-color: #F4FF77;
|
||||
display: inline-block;
|
||||
font-style: normal;
|
||||
color: #366097;
|
||||
line-height: 1.8em;
|
||||
padding: 0 0.5em;
|
||||
margin: -0.4em 0.4em -0.4em 0;
|
||||
}
|
||||
|
||||
#qunit-tests .qunit-todo-label {
|
||||
background-color: #EEE;
|
||||
}
|
||||
|
||||
/** Result */
|
||||
|
||||
#qunit-testresult {
|
||||
color: #2B81AF;
|
||||
background-color: #D2E0E6;
|
||||
|
||||
border-bottom: 1px solid #FFF;
|
||||
}
|
||||
#qunit-testresult .clearfix {
|
||||
height: 0;
|
||||
clear: both;
|
||||
}
|
||||
#qunit-testresult .module-name {
|
||||
font-weight: 700;
|
||||
}
|
||||
#qunit-testresult-display {
|
||||
padding: 0.5em 1em 0.5em 1em;
|
||||
width: 85%;
|
||||
float:left;
|
||||
}
|
||||
#qunit-testresult-controls {
|
||||
padding: 0.5em 1em 0.5em 1em;
|
||||
width: 10%;
|
||||
float:left;
|
||||
}
|
||||
|
||||
/** Fixture */
|
||||
|
||||
#qunit-fixture {
|
||||
position: absolute;
|
||||
top: -10000px;
|
||||
left: -10000px;
|
||||
width: 1000px;
|
||||
height: 1000px;
|
||||
}
|
6604
external/qunit/qunit.js
vendored
6604
external/qunit/qunit.js
vendored
File diff suppressed because it is too large
Load Diff
2145
external/requirejs/require.js
vendored
2145
external/requirejs/require.js
vendored
File diff suppressed because it is too large
Load Diff
27
external/sinon/LICENSE.txt
vendored
27
external/sinon/LICENSE.txt
vendored
@ -1,27 +0,0 @@
|
||||
(The BSD License)
|
||||
|
||||
Copyright (c) 2010-2017, Christian Johansen, christian@cjohansen.no
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of Christian Johansen nor the names of his contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
11809
external/sinon/sinon.js
vendored
11809
external/sinon/sinon.js
vendored
File diff suppressed because one or more lines are too long
7533
package-lock.json
generated
Normal file
7533
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
77
package.json
77
package.json
@ -4,6 +4,31 @@
|
||||
"description": "JavaScript library for DOM operations",
|
||||
"version": "3.7.2-pre",
|
||||
"main": "dist/jquery.js",
|
||||
"scripts": {
|
||||
"babel:tests": "babel test/data/core/jquery-iterability-transpiled-es6.js --out-file test/data/core/jquery-iterability-transpiled.js",
|
||||
"build": "node ./build/command.js",
|
||||
"build:all": "node -e \"require('./build/tasks/build.js').buildDefaultFiles()\"",
|
||||
"build:main": "node -e \"require('./build/tasks/build.js').build()\"",
|
||||
"jenkins": "npm run pretest && npm run test:browserless",
|
||||
"lint:dev": "eslint --cache .",
|
||||
"lint:json": "jsonlint --quiet package.json",
|
||||
"lint": "concurrently -r \"npm:lint:dev\" \"npm:lint:json\"",
|
||||
"npmcopy": "node build/tasks/npmcopy.js",
|
||||
"prepare": "husky install",
|
||||
"pretest": "npm run qunit-fixture && npm run babel:tests && npm run npmcopy",
|
||||
"qunit-fixture": "node build/tasks/qunit-fixture.js",
|
||||
"start": "nodemon --watch src -x \"npm run build:all\"",
|
||||
"test:browserless": "npm run test:node_smoke_tests && npm run test:promises_aplus && npm run test:jsdom",
|
||||
"test:browser": "npm run build:all && grunt karma:main",
|
||||
"test:amd": "npm run build:main && grunt karma:amd",
|
||||
"test:jsdom": "npm run build:main && grunt test:jsdom",
|
||||
"test:no-deprecated": "npm run build -- -e deprecated && grunt karma:main",
|
||||
"test:selector-native": "npm run build -- -e selector && grunt karma:main",
|
||||
"test:slim": "npm run build -- --slim && grunt karma:main",
|
||||
"test:node_smoke_tests": "npm run build:all && node build/tasks/node_smoke_tests.js",
|
||||
"test:promises_aplus": "npm run build:main && node build/tasks/promises_aplus_tests.js",
|
||||
"test": "npm run build:all && npm run lint && npm run test:browserless && npm run test:browser && npm run test:amd && npm run test:slim && npm run test:no-deprecated && npm run test:selector-native"
|
||||
},
|
||||
"homepage": "https://jquery.com",
|
||||
"author": {
|
||||
"name": "OpenJS Foundation and other contributors",
|
||||
@ -24,27 +49,25 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.3.3",
|
||||
"@babel/plugin-transform-for-of": "7.2.0",
|
||||
"@babel/cli": "7.22.10",
|
||||
"@babel/core": "7.22.11",
|
||||
"@babel/plugin-transform-for-of": "7.22.5",
|
||||
"@prantlf/jsonlint": "14.0.3",
|
||||
"bootstrap": "5.3.0",
|
||||
"chalk": "5.3.0",
|
||||
"colors": "1.4.0",
|
||||
"commitplease": "3.2.0",
|
||||
"core-js": "2.6.5",
|
||||
"eslint-config-jquery": "3.0.0",
|
||||
"concurrently": "8.2.0",
|
||||
"core-js-bundle": "3.32.1",
|
||||
"eslint": "8.48.0",
|
||||
"eslint-config-jquery": "3.0.1",
|
||||
"express": "4.18.2",
|
||||
"globals": "13.20.0",
|
||||
"grunt": "1.5.3",
|
||||
"grunt-babel": "8.0.0",
|
||||
"grunt-cli": "1.4.3",
|
||||
"grunt-compare-size": "0.4.2",
|
||||
"grunt-contrib-uglify": "3.4.0",
|
||||
"grunt-contrib-watch": "1.1.0",
|
||||
"grunt-eslint": "22.0.0",
|
||||
"grunt-git-authors": "3.2.0",
|
||||
"grunt-jsonlint": "2.1.2",
|
||||
"grunt-karma": "4.0.2",
|
||||
"grunt-newer": "1.3.0",
|
||||
"grunt-npmcopy": "0.2.0",
|
||||
"gzip-js": "0.3.2",
|
||||
"husky": "4.2.5",
|
||||
"husky": "8.0.3",
|
||||
"jsdom": "19.0.0",
|
||||
"karma": "6.4.1",
|
||||
"karma-browserstack-launcher": "1.6.0",
|
||||
@ -56,6 +79,7 @@
|
||||
"karma-webkit-launcher": "2.1.0",
|
||||
"load-grunt-tasks": "5.1.0",
|
||||
"native-promise-only": "0.8.1",
|
||||
"nodemon": "3.0.1",
|
||||
"playwright-webkit": "1.30.0",
|
||||
"promises-aplus-tests": "2.1.2",
|
||||
"q": "1.5.1",
|
||||
@ -65,23 +89,8 @@
|
||||
"sinon": "2.3.7",
|
||||
"strip-json-comments": "2.0.1",
|
||||
"testswarm": "1.1.2",
|
||||
"uglify-js": "3.4.7"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npm install && npm run build-all-variants",
|
||||
"build-all-variants": "grunt custom:slim --filename=jquery.slim.js && grunt custom",
|
||||
"start": "grunt watch",
|
||||
"test:browserless": "grunt && npm run test:node_smoke_tests && grunt test:slow",
|
||||
"test:browser": "grunt && grunt karma:main",
|
||||
"test:amd": "grunt && grunt karma:amd",
|
||||
"test:no-deprecated": "grunt test:prepare && grunt custom:-deprecated && grunt karma:main",
|
||||
"test:selector-native": "grunt test:prepare && grunt custom:-selector && grunt karma:main",
|
||||
"test:slim": "grunt test:prepare && grunt custom:slim && grunt karma:main",
|
||||
"test:node_smoke_tests:full": "grunt node_smoke_tests:./dist/jquery.js",
|
||||
"test:node_smoke_tests:slim": "grunt node_smoke_tests:./dist/jquery.slim.js",
|
||||
"test:node_smoke_tests": "npm run test:node_smoke_tests:full && npm run test:node_smoke_tests:slim",
|
||||
"test": "npm run test:browserless && npm run test:slim && npm run test:no-deprecated && npm run test:selector-native && grunt && grunt test:slow && grunt karma:main && grunt karma:amd",
|
||||
"jenkins": "npm run test:browserless"
|
||||
"uglify-js": "3.4.7",
|
||||
"yargs": "17.7.2"
|
||||
},
|
||||
"commitplease": {
|
||||
"nohook": true,
|
||||
@ -112,11 +121,5 @@
|
||||
],
|
||||
"markerPattern": "^((clos|fix|resolv)(e[sd]|ing))|^(refs?)",
|
||||
"ticketPattern": "^((Closes|Fixes) ([a-zA-Z]{2,}-)[0-9]+)|^(Refs? [^#])"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"commit-msg": "commitplease .git/COMMIT_EDITMSG",
|
||||
"pre-commit": "grunt lint:newer qunit_fixture"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,45 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
|
||||
"extends": "../.eslintrc-browser.json",
|
||||
|
||||
"rules": {
|
||||
"indent": [ "error", "tab", {
|
||||
"outerIIFEBody": 0,
|
||||
|
||||
// Ignore the top level function defining an AMD module
|
||||
"ignoredNodes": [
|
||||
"Program > ExpressionStatement > CallExpression > :last-child > *"
|
||||
]
|
||||
} ]
|
||||
},
|
||||
|
||||
"overrides": [
|
||||
{
|
||||
"files": "wrapper.js",
|
||||
"rules": {
|
||||
"no-unused-vars": "off",
|
||||
"indent": [ "error", "tab", {
|
||||
|
||||
// Unlike other codes, "wrapper.js" is implemented in UMD.
|
||||
// So it required a specific exception for jQuery's UMD
|
||||
// Code Style. This makes that indentation check is not
|
||||
// performed for 1 depth of outer FunctionExpressions
|
||||
"ignoredNodes": [
|
||||
"Program > ExpressionStatement > CallExpression > :last-child > *"
|
||||
]
|
||||
} ]
|
||||
},
|
||||
"globals": {
|
||||
"jQuery": false
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"files": "selector.js",
|
||||
"rules": {
|
||||
"indent": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
|
||||
"extends": "../.eslintrc-browser.json",
|
||||
|
||||
"env": {
|
||||
|
||||
// In source the browser env is not enabled but unit tests rely on them
|
||||
// too much and we don't run them in non-browser environments anyway.
|
||||
"browser": true
|
||||
},
|
||||
|
||||
"globals": {
|
||||
"require": false,
|
||||
"Promise": false,
|
||||
"Symbol": false,
|
||||
"QUnit": false,
|
||||
"ajaxTest": false,
|
||||
"testIframe": false,
|
||||
"createDashboardXML": false,
|
||||
"createWithFriesXML": false,
|
||||
"createXMLFragment": false,
|
||||
"includesModule": false,
|
||||
"moduleTeardown": false,
|
||||
"url": false,
|
||||
"q": false,
|
||||
"jQuery": true,
|
||||
"sinon": true,
|
||||
"amdDefined": true,
|
||||
"fireNative": true,
|
||||
"Globals": true,
|
||||
"hasPHP": true,
|
||||
"isLocal": true,
|
||||
"supportjQuery": true,
|
||||
"originaljQuery": true,
|
||||
"$": true,
|
||||
"original$": true,
|
||||
"baseURL": true,
|
||||
"externalHost": true
|
||||
},
|
||||
|
||||
"rules": {
|
||||
// See https://github.com/eslint/eslint/issues/2342
|
||||
"no-unused-vars": "off",
|
||||
|
||||
// Too many errors
|
||||
"max-len": "off",
|
||||
"brace-style": "off",
|
||||
"key-spacing": "off",
|
||||
"camelcase": "off",
|
||||
"one-var": "off",
|
||||
"strict": "off",
|
||||
|
||||
// Not really too many - waiting for autofix features for these rules
|
||||
"lines-around-comment": "off",
|
||||
"dot-notation": "off"
|
||||
},
|
||||
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"middleware-mockserver.js"
|
||||
],
|
||||
|
||||
"extends": "../.eslintrc-node.json"
|
||||
},
|
||||
|
||||
{
|
||||
"files": [
|
||||
"data/core/jquery-iterability-transpiled-es6.js",
|
||||
"data/testinit-jsdom.js"
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2015
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
5
test/data/core/.babelrc.json
Normal file
5
test/data/core/.babelrc.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"plugins": ["@babel/transform-for-of"],
|
||||
"retainLines": true,
|
||||
"sourceMaps": "inline"
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>jQuery objects transpiled iterability test page</title>
|
||||
<script src="../../../external/core-js/core-js.js"></script>
|
||||
<script src="../../../external/core-js-bundle/core-js-bundle.js"></script>
|
||||
<script src="../../jquery.js"></script>
|
||||
<script src="../iframeTest.js"></script>
|
||||
<script src="jquery-iterability-transpiled.js"></script>
|
||||
|
@ -2,19 +2,19 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="stylesheet" href="../../../external/bootstrap/bootstrap.min.css" class="stylesheet">
|
||||
<link rel="stylesheet" href="../../../external/bootstrap/bootstrap.min.css" class="stylesheet" />
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<div>
|
||||
<script src="../../jquery.js"></script>
|
||||
<script src="../iframeTest.js"></script>
|
||||
<script src="getComputedSupport.js"></script>
|
||||
</div>
|
||||
<script>
|
||||
</div>
|
||||
<script>
|
||||
startIframeTest(
|
||||
getComputedStyle( document.body ),
|
||||
getComputedSupport( jQuery.support )
|
||||
);
|
||||
</script>
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -34,10 +34,10 @@ window.original$ = this.$ = "replaced";
|
||||
* @example url("mock.php?foo=bar")
|
||||
* @result "data/mock.php?foo=bar&10538358345554"
|
||||
*/
|
||||
function url( value ) {
|
||||
this.url = function( value ) {
|
||||
return baseURL + value + ( /\?/.test( value ) ? "&" : "?" ) +
|
||||
new Date().getTime() + "" + parseInt( Math.random() * 100000, 10 );
|
||||
}
|
||||
};
|
||||
|
||||
// We only run basic tests in jsdom so we don't need to repeat the logic
|
||||
// from the regular testinit.js
|
||||
|
@ -17,13 +17,7 @@ var FILEPATH = "/test/data/testinit.js",
|
||||
supportjQuery = this.jQuery,
|
||||
|
||||
// see RFC 2606
|
||||
externalHost = "example.com",
|
||||
|
||||
// NOTE: keep it in sync with build/tasks/lib/slim-build-flags.js
|
||||
slimBuildFlags = [
|
||||
"-ajax",
|
||||
"-effects"
|
||||
];
|
||||
externalHost = "example.com";
|
||||
|
||||
this.hasPHP = true;
|
||||
this.isLocal = window.location.protocol === "file:";
|
||||
@ -265,7 +259,7 @@ this.ajaxTest = function( title, expect, options ) {
|
||||
completed = true;
|
||||
delete ajaxTest.abort;
|
||||
assert.ok( false, "aborted " + reason );
|
||||
jQuery.each( requests, function( i, request ) {
|
||||
jQuery.each( requests, function( _i, request ) {
|
||||
request.abort();
|
||||
} );
|
||||
}
|
||||
@ -346,16 +340,8 @@ this.includesModule = function( moduleName ) {
|
||||
|
||||
var excludedModulesPart, excludedModules;
|
||||
|
||||
// A short-cut for the slim build, e.g. "4.0.0-pre slim"
|
||||
if ( jQuery.fn.jquery.indexOf( " slim" ) > -1 ) {
|
||||
|
||||
// The module is included if it does NOT exist on the list
|
||||
// of modules excluded in the slim build
|
||||
return slimBuildFlags.indexOf( "-" + moduleName ) === -1;
|
||||
}
|
||||
|
||||
// example version for `grunt custom:-deprecated`:
|
||||
// "4.0.0-pre -deprecated,-deprecated/ajax-event-alias,-deprecated/event"
|
||||
// example version for `npm run build -- -e deprecated`:
|
||||
// "v3.7.2-pre+14dc9347 -deprecated,-deprecated/ajax-event-alias,-deprecated/event"
|
||||
excludedModulesPart = jQuery.fn.jquery
|
||||
|
||||
// Take the flags out of the version string.
|
||||
@ -420,6 +406,7 @@ this.loadTests = function() {
|
||||
|
||||
var i = 0,
|
||||
tests = [
|
||||
|
||||
// A special module with basic tests, meant for
|
||||
// not fully supported environments like Android 2.3,
|
||||
// jsdom or PhantomJS. We run it everywhere, though,
|
||||
|
@ -66,14 +66,34 @@ const mocks = {
|
||||
resp.end( "<root><element /></root>" );
|
||||
},
|
||||
script: function( req, resp ) {
|
||||
const headers = {};
|
||||
if ( req.query.header === "ecma" ) {
|
||||
resp.writeHead( 200, { "content-type": "application/ecmascript" } );
|
||||
headers[ "content-type" ] = "application/ecmascript";
|
||||
} else if ( "header" in req.query ) {
|
||||
resp.writeHead( 200, { "content-type": "text/javascript" } );
|
||||
headers[ "content-type" ] = "text/javascript";
|
||||
} else {
|
||||
resp.writeHead( 200, { "content-type": "text/html" } );
|
||||
headers[ "content-type" ] = "text/html";
|
||||
}
|
||||
|
||||
if ( req.query.cors ) {
|
||||
headers[ "access-control-allow-origin" ] = "*";
|
||||
}
|
||||
|
||||
if ( resp.set ) {
|
||||
resp.set( headers );
|
||||
} else {
|
||||
for ( const key in headers ) {
|
||||
resp.writeHead( 200, { [ key ]: headers[ key ] } );
|
||||
}
|
||||
}
|
||||
|
||||
if ( req.query.callback ) {
|
||||
resp.end( `${ cleanCallback( req.query.callback ) }(${ JSON.stringify( {
|
||||
headers: req.headers
|
||||
} ) })` );
|
||||
} else {
|
||||
resp.end( "QUnit.assert.ok( true, \"mock executed\" );" );
|
||||
}
|
||||
},
|
||||
testbar: function( _req, resp ) {
|
||||
resp.writeHead( 200 );
|
||||
@ -137,14 +157,25 @@ const mocks = {
|
||||
}
|
||||
},
|
||||
headers: function( req, resp ) {
|
||||
resp.writeHead( 200, {
|
||||
const headers = {
|
||||
"Sample-Header": "Hello World",
|
||||
"Empty-Header": "",
|
||||
"Sample-Header2": "Hello World 2",
|
||||
"List-Header": "Item 1",
|
||||
"list-header": "Item 2",
|
||||
"constructor": "prototype collision (constructor)"
|
||||
} );
|
||||
};
|
||||
|
||||
// Use resp.append in express to
|
||||
// avoid overwriting List-Header
|
||||
if ( resp.append ) {
|
||||
|
||||
for ( const key in headers ) {
|
||||
resp.append( key, headers[ key ] );
|
||||
}
|
||||
} else {
|
||||
resp.writeHead( 200, headers );
|
||||
}
|
||||
req.query.keys.split( "|" ).forEach( function( key ) {
|
||||
if ( key.toLowerCase() in req.headers ) {
|
||||
resp.write( `${ key }: ${ req.headers[ key.toLowerCase() ] }\n` );
|
||||
@ -297,7 +328,7 @@ function MockserverMiddlewareFactory() {
|
||||
parsed: parsed
|
||||
} );
|
||||
|
||||
if ( /^test\/data\/mock.php\//.test( path ) ) {
|
||||
if ( /^\/?test\/data\/mock.php\/?/.test( path ) ) {
|
||||
|
||||
// Support REST-like Apache PathInfo
|
||||
path = "test\/data\/mock.php";
|
||||
@ -308,6 +339,7 @@ function MockserverMiddlewareFactory() {
|
||||
return;
|
||||
}
|
||||
|
||||
// console.log( "Mock handling", req.method, parsed.href );
|
||||
handlers[ path ]( subReq, resp, next );
|
||||
};
|
||||
}
|
||||
|
@ -1,13 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
|
||||
"extends": "../../.eslintrc-node.json",
|
||||
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2015,
|
||||
"sourceType": "script"
|
||||
},
|
||||
"env": {
|
||||
"es2020": true
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
|
||||
"extends": "../../.eslintrc-node.json"
|
||||
}
|
21
test/server.js
Normal file
21
test/server.js
Normal file
@ -0,0 +1,21 @@
|
||||
const express = require( "express" );
|
||||
const mockServer = require( "./middleware-mockserver" );
|
||||
const fs = require( "fs" );
|
||||
|
||||
const nameHTML = fs.readFileSync( "./test/data/name.html", "utf8" );
|
||||
const app = express();
|
||||
|
||||
app.use( mockServer() );
|
||||
|
||||
app.post( "/test/data/name.html", function( _req, res ) {
|
||||
res.send( nameHTML );
|
||||
} );
|
||||
|
||||
app.use( "/dist", express.static( "dist" ) );
|
||||
app.use( "/src", express.static( "src" ) );
|
||||
app.use( "/test", express.static( "test" ) );
|
||||
app.use( "/external", express.static( "external" ) );
|
||||
|
||||
app.listen( 3000, function() {
|
||||
console.log( "Server is running on port 3000" );
|
||||
} );
|
@ -298,6 +298,7 @@ QUnit.module( "ajax", {
|
||||
assert.strictEqual( xhr.getResponseHeader( "Sample-Header2" ), "Hello World 2", "Second sample header received" );
|
||||
|
||||
if ( isAndroid ) {
|
||||
|
||||
// Support: Android 4.0-4.3 only
|
||||
// Android Browser only returns the last value for each header
|
||||
// so there's no way for jQuery get all parts.
|
||||
@ -307,6 +308,7 @@ QUnit.module( "ajax", {
|
||||
}
|
||||
|
||||
if ( isAndroid && QUnit.isSwarm ) {
|
||||
|
||||
// Support: Android 4.0-4.3 on BrowserStack only
|
||||
// Android Browser versions provided by BrowserStack fail this test
|
||||
// while locally fired emulators don't, even when they connect
|
||||
@ -426,6 +428,7 @@ QUnit.module( "ajax", {
|
||||
},
|
||||
cache: false,
|
||||
beforeSend: function( xhr, settings ) {
|
||||
|
||||
// Clear the cache-buster param value
|
||||
var url = settings.url.replace( /_=[^&#]+/, "_=" );
|
||||
assert.equal( url, baseURL + "name.html?abc&devo=hat&_=#brownies",
|
||||
@ -850,8 +853,8 @@ QUnit.module( "ajax", {
|
||||
success: function( data ) {
|
||||
assert.ok( data.match( /^html text/ ), "Check content for datatype html" );
|
||||
jQuery( "#ap" ).html( data );
|
||||
assert.strictEqual( window[ "testFoo" ], "foo", "Check if script was evaluated for datatype html" );
|
||||
assert.strictEqual( window[ "testBar" ], "bar", "Check if script src was evaluated for datatype html" );
|
||||
assert.strictEqual( window.testFoo, "foo", "Check if script was evaluated for datatype html" );
|
||||
assert.strictEqual( window.testBar, "bar", "Check if script src was evaluated for datatype html" );
|
||||
}
|
||||
};
|
||||
} );
|
||||
@ -861,6 +864,7 @@ QUnit.module( "ajax", {
|
||||
return {
|
||||
dataType: "jsonp",
|
||||
url: url( "mock.php?action=errorWithScript" ),
|
||||
|
||||
// error is the significant assertion
|
||||
error: function( xhr ) {
|
||||
var expected = { "status": 404, "msg": "Not Found" };
|
||||
@ -889,6 +893,7 @@ QUnit.module( "ajax", {
|
||||
complete: function() {
|
||||
jQuery.globalEval = globalEval;
|
||||
},
|
||||
|
||||
// error is the significant assertion
|
||||
error: function( xhr ) {
|
||||
assert.strictEqual( xhr.status, 404, testMsg );
|
||||
@ -1148,8 +1153,8 @@ QUnit.module( "ajax", {
|
||||
Globals.register( "functionToCleanUp" );
|
||||
Globals.register( "XXX" );
|
||||
Globals.register( "jsonpResults" );
|
||||
window[ "jsonpResults" ] = function( data ) {
|
||||
assert.ok( data[ "data" ], "JSON results returned (GET, custom callback function)" );
|
||||
window.jsonpResults = function( data ) {
|
||||
assert.ok( data.data, "JSON results returned (GET, custom callback function)" );
|
||||
};
|
||||
},
|
||||
requests: [ {
|
||||
@ -1158,7 +1163,7 @@ QUnit.module( "ajax", {
|
||||
crossDomain: crossDomain,
|
||||
jsonp: "callback",
|
||||
success: function( data ) {
|
||||
assert.ok( data[ "data" ], "JSON results returned (GET, data obj callback)" );
|
||||
assert.ok( data.data, "JSON results returned (GET, data obj callback)" );
|
||||
}
|
||||
}, {
|
||||
url: baseURL + "mock.php?action=jsonp",
|
||||
@ -1167,7 +1172,7 @@ QUnit.module( "ajax", {
|
||||
jsonpCallback: "jsonpResults",
|
||||
success: function( data ) {
|
||||
assert.strictEqual(
|
||||
typeof window[ "jsonpResults" ],
|
||||
typeof window.jsonpResults,
|
||||
"function",
|
||||
"should not rewrite original function"
|
||||
);
|
||||
@ -1179,8 +1184,8 @@ QUnit.module( "ajax", {
|
||||
crossDomain: crossDomain,
|
||||
jsonpCallback: "functionToCleanUp",
|
||||
success: function( data ) {
|
||||
assert.ok( data[ "data" ], "JSON results returned (GET, custom callback name to be cleaned up)" );
|
||||
assert.strictEqual( window[ "functionToCleanUp" ], true, "Callback was removed (GET, custom callback name to be cleaned up)" );
|
||||
assert.ok( data.data, "JSON results returned (GET, custom callback name to be cleaned up)" );
|
||||
assert.strictEqual( window.functionToCleanUp, true, "Callback was removed (GET, custom callback name to be cleaned up)" );
|
||||
var xhr;
|
||||
jQuery.ajax( {
|
||||
url: baseURL + "mock.php?action=jsonp",
|
||||
@ -1194,7 +1199,7 @@ QUnit.module( "ajax", {
|
||||
} );
|
||||
xhr.fail( function() {
|
||||
assert.ok( true, "Ajax error JSON (GET, custom callback name to be cleaned up)" );
|
||||
assert.strictEqual( window[ "functionToCleanUp" ], true, "Callback was removed after early abort (GET, custom callback name to be cleaned up)" );
|
||||
assert.strictEqual( window.functionToCleanUp, true, "Callback was removed after early abort (GET, custom callback name to be cleaned up)" );
|
||||
} );
|
||||
}
|
||||
}, {
|
||||
@ -1207,7 +1212,7 @@ QUnit.module( "ajax", {
|
||||
assert.ok( /action=jsonp&callback=XXX&_=\d+$/.test( this.url ), "The URL wasn't messed with (GET, custom callback name with no url manipulation)" );
|
||||
},
|
||||
success: function( data ) {
|
||||
assert.ok( data[ "data" ], "JSON results returned (GET, custom callback name with no url manipulation)" );
|
||||
assert.ok( data.data, "JSON results returned (GET, custom callback name with no url manipulation)" );
|
||||
}
|
||||
} ]
|
||||
};
|
||||
@ -1244,7 +1249,7 @@ QUnit.module( "ajax", {
|
||||
dataType: "jsonp",
|
||||
crossDomain: crossDomain,
|
||||
success: function( data ) {
|
||||
assert.ok( data[ "data" ], "JSON results returned (POST, no callback)" );
|
||||
assert.ok( data.data, "JSON results returned (POST, no callback)" );
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1254,7 +1259,7 @@ QUnit.module( "ajax", {
|
||||
dataType: "jsonp",
|
||||
crossDomain: crossDomain,
|
||||
success: function( data ) {
|
||||
assert.ok( data[ "data" ], "JSON results returned (POST, data callback)" );
|
||||
assert.ok( data.data, "JSON results returned (POST, data callback)" );
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1264,7 +1269,7 @@ QUnit.module( "ajax", {
|
||||
dataType: "jsonp",
|
||||
crossDomain: crossDomain,
|
||||
success: function( data ) {
|
||||
assert.ok( data[ "data" ], "JSON results returned (POST, data obj callback)" );
|
||||
assert.ok( data.data, "JSON results returned (POST, data obj callback)" );
|
||||
}
|
||||
}
|
||||
];
|
||||
@ -1312,7 +1317,7 @@ QUnit.module( "ajax", {
|
||||
url: url( "mock.php?action=testbar" ),
|
||||
dataType: "script",
|
||||
success: function() {
|
||||
assert.strictEqual( window[ "testBar" ], "bar", "Script results returned (GET, no callback)" );
|
||||
assert.strictEqual( window.testBar, "bar", "Script results returned (GET, no callback)" );
|
||||
}
|
||||
};
|
||||
} );
|
||||
@ -1326,7 +1331,7 @@ QUnit.module( "ajax", {
|
||||
type: "POST",
|
||||
dataType: "script",
|
||||
success: function( data, status ) {
|
||||
assert.strictEqual( window[ "testBar" ], "bar", "Script results returned (POST, no callback)" );
|
||||
assert.strictEqual( window.testBar, "bar", "Script results returned (POST, no callback)" );
|
||||
assert.strictEqual( status, "success", "Script results returned (POST, no callback)" );
|
||||
}
|
||||
};
|
||||
@ -1340,7 +1345,7 @@ QUnit.module( "ajax", {
|
||||
url: url( "mock.php?action=testbar" ),
|
||||
dataType: "script",
|
||||
success: function() {
|
||||
assert.strictEqual( window[ "testBar" ], "bar", "Script results returned (GET, no callback)" );
|
||||
assert.strictEqual( window.testBar, "bar", "Script results returned (GET, no callback)" );
|
||||
}
|
||||
};
|
||||
} );
|
||||
@ -1385,10 +1390,10 @@ QUnit.module( "ajax", {
|
||||
},
|
||||
success: function( json ) {
|
||||
assert.ok( json.length >= 2, "Check length" );
|
||||
assert.strictEqual( json[ 0 ][ "name" ], "John", "Check JSON: first, name" );
|
||||
assert.strictEqual( json[ 0 ][ "age" ], 21, "Check JSON: first, age" );
|
||||
assert.strictEqual( json[ 1 ][ "name" ], "Peter", "Check JSON: second, name" );
|
||||
assert.strictEqual( json[ 1 ][ "age" ], 25, "Check JSON: second, age" );
|
||||
assert.strictEqual( json[ 0 ].name, "John", "Check JSON: first, name" );
|
||||
assert.strictEqual( json[ 0 ].age, 21, "Check JSON: first, age" );
|
||||
assert.strictEqual( json[ 1 ].name, "Peter", "Check JSON: second, name" );
|
||||
assert.strictEqual( json[ 1 ].age, 25, "Check JSON: second, age" );
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1405,10 +1410,10 @@ QUnit.module( "ajax", {
|
||||
],
|
||||
success: function( json ) {
|
||||
assert.ok( json.length >= 2, "Check length" );
|
||||
assert.strictEqual( json[ 0 ][ "name" ], "John", "Check JSON: first, name" );
|
||||
assert.strictEqual( json[ 0 ][ "age" ], 21, "Check JSON: first, age" );
|
||||
assert.strictEqual( json[ 1 ][ "name" ], "Peter", "Check JSON: second, name" );
|
||||
assert.strictEqual( json[ 1 ][ "age" ], 25, "Check JSON: second, age" );
|
||||
assert.strictEqual( json[ 0 ].name, "John", "Check JSON: first, name" );
|
||||
assert.strictEqual( json[ 0 ].age, 21, "Check JSON: first, age" );
|
||||
assert.strictEqual( json[ 1 ].name, "Peter", "Check JSON: second, name" );
|
||||
assert.strictEqual( json[ 1 ].age, 25, "Check JSON: second, age" );
|
||||
}
|
||||
}
|
||||
];
|
||||
@ -1429,10 +1434,10 @@ QUnit.module( "ajax", {
|
||||
assert.strictEqual( typeof text, "string", "json wasn't auto-determined" );
|
||||
var json = JSON.parse( text );
|
||||
assert.ok( json.length >= 2, "Check length" );
|
||||
assert.strictEqual( json[ 0 ][ "name" ], "John", "Check JSON: first, name" );
|
||||
assert.strictEqual( json[ 0 ][ "age" ], 21, "Check JSON: first, age" );
|
||||
assert.strictEqual( json[ 1 ][ "name" ], "Peter", "Check JSON: second, name" );
|
||||
assert.strictEqual( json[ 1 ][ "age" ], 25, "Check JSON: second, age" );
|
||||
assert.strictEqual( json[ 0 ].name, "John", "Check JSON: first, name" );
|
||||
assert.strictEqual( json[ 0 ].age, 21, "Check JSON: first, age" );
|
||||
assert.strictEqual( json[ 1 ].name, "Peter", "Check JSON: second, name" );
|
||||
assert.strictEqual( json[ 1 ].age, 25, "Check JSON: second, age" );
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1454,10 +1459,10 @@ QUnit.module( "ajax", {
|
||||
assert.strictEqual( typeof text, "string", "json wasn't auto-determined" );
|
||||
var json = JSON.parse( text );
|
||||
assert.ok( json.length >= 2, "Check length" );
|
||||
assert.strictEqual( json[ 0 ][ "name" ], "John", "Check JSON: first, name" );
|
||||
assert.strictEqual( json[ 0 ][ "age" ], 21, "Check JSON: first, age" );
|
||||
assert.strictEqual( json[ 1 ][ "name" ], "Peter", "Check JSON: second, name" );
|
||||
assert.strictEqual( json[ 1 ][ "age" ], 25, "Check JSON: second, age" );
|
||||
assert.strictEqual( json[ 0 ].name, "John", "Check JSON: first, name" );
|
||||
assert.strictEqual( json[ 0 ].age, 21, "Check JSON: first, age" );
|
||||
assert.strictEqual( json[ 1 ].name, "Peter", "Check JSON: second, name" );
|
||||
assert.strictEqual( json[ 1 ].age, 25, "Check JSON: second, age" );
|
||||
}
|
||||
}
|
||||
];
|
||||
@ -1683,6 +1688,7 @@ QUnit.module( "ajax", {
|
||||
var ifModifiedNow = new Date();
|
||||
|
||||
jQuery.each(
|
||||
|
||||
/* jQuery.each arguments start */
|
||||
{
|
||||
" (cache)": true,
|
||||
@ -1737,6 +1743,7 @@ QUnit.module( "ajax", {
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/* jQuery.each arguments end */
|
||||
);
|
||||
|
||||
@ -1813,6 +1820,7 @@ QUnit.module( "ajax", {
|
||||
}
|
||||
|
||||
jQuery.each(
|
||||
|
||||
/* jQuery.each arguments start */
|
||||
{
|
||||
"name.html": true,
|
||||
@ -1887,6 +1895,7 @@ QUnit.module( "ajax", {
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
/* jQuery.each arguments end*/
|
||||
);
|
||||
} );
|
||||
@ -2670,10 +2679,10 @@ if ( typeof window.ArrayBuffer === "undefined" || typeof new XMLHttpRequest().re
|
||||
},
|
||||
function( json ) {
|
||||
assert.ok( json.length >= 2, "Check length" );
|
||||
assert.strictEqual( json[ 0 ][ "name" ], "John", "Check JSON: first, name" );
|
||||
assert.strictEqual( json[ 0 ][ "age" ], 21, "Check JSON: first, age" );
|
||||
assert.strictEqual( json[ 1 ][ "name" ], "Peter", "Check JSON: second, name" );
|
||||
assert.strictEqual( json[ 1 ][ "age" ], 25, "Check JSON: second, age" );
|
||||
assert.strictEqual( json[ 0 ].name, "John", "Check JSON: first, name" );
|
||||
assert.strictEqual( json[ 0 ].age, 21, "Check JSON: first, age" );
|
||||
assert.strictEqual( json[ 1 ].name, "Peter", "Check JSON: second, name" );
|
||||
assert.strictEqual( json[ 1 ].age, 25, "Check JSON: second, age" );
|
||||
done();
|
||||
}
|
||||
);
|
||||
@ -2683,9 +2692,9 @@ if ( typeof window.ArrayBuffer === "undefined" || typeof new XMLHttpRequest().re
|
||||
assert.expect( 2 );
|
||||
var done = assert.async();
|
||||
jQuery.getJSON( url( "mock.php?action=json" ), function( json ) {
|
||||
if ( json && json[ "data" ] ) {
|
||||
assert.strictEqual( json[ "data" ][ "lang" ], "en", "Check JSON: lang" );
|
||||
assert.strictEqual( json[ "data" ].length, 25, "Check JSON: length" );
|
||||
if ( json && json.data ) {
|
||||
assert.strictEqual( json.data.lang, "en", "Check JSON: lang" );
|
||||
assert.strictEqual( json.data.length, 25, "Check JSON: length" );
|
||||
done();
|
||||
}
|
||||
} );
|
||||
@ -2725,7 +2734,7 @@ if ( typeof window.ArrayBuffer === "undefined" || typeof new XMLHttpRequest().re
|
||||
|
||||
Globals.register( "testBar" );
|
||||
jQuery.getScript( url( "mock.php?action=testbar" ), function() {
|
||||
assert.strictEqual( window[ "testBar" ], "bar", "Check if script was evaluated" );
|
||||
assert.strictEqual( window.testBar, "bar", "Check if script was evaluated" );
|
||||
done();
|
||||
} );
|
||||
}
|
||||
@ -2756,7 +2765,7 @@ if ( typeof window.ArrayBuffer === "undefined" || typeof new XMLHttpRequest().re
|
||||
jQuery.getScript( {
|
||||
url: url( "mock.php?action=testbar" ),
|
||||
success: function() {
|
||||
assert.strictEqual( window[ "testBar" ], "bar", "Check if script was evaluated" );
|
||||
assert.strictEqual( window.testBar, "bar", "Check if script was evaluated" );
|
||||
done();
|
||||
}
|
||||
} );
|
||||
@ -2858,7 +2867,7 @@ if ( typeof window.ArrayBuffer === "undefined" || typeof new XMLHttpRequest().re
|
||||
assert.expect( 7 );
|
||||
var done = assert.async();
|
||||
var verifyEvaluation = function() {
|
||||
assert.strictEqual( window[ "testBar" ], "bar", "Check if script src was evaluated after load" );
|
||||
assert.strictEqual( window.testBar, "bar", "Check if script src was evaluated after load" );
|
||||
assert.strictEqual( jQuery( "#ap" ).html(), "bar", "Check if script evaluation has modified DOM" );
|
||||
done();
|
||||
};
|
||||
@ -2869,7 +2878,7 @@ if ( typeof window.ArrayBuffer === "undefined" || typeof new XMLHttpRequest().re
|
||||
jQuery( "#first" ).load( url( "mock.php?action=testHTML&baseURL=" + baseURL ), function() {
|
||||
assert.ok( jQuery( "#first" ).html().match( /^html text/ ), "Check content after loading html" );
|
||||
assert.strictEqual( jQuery( "#foo" ).html(), "foo", "Check if script evaluation has modified DOM" );
|
||||
assert.strictEqual( window[ "testFoo" ], "foo", "Check if script was evaluated after load" );
|
||||
assert.strictEqual( window.testFoo, "foo", "Check if script was evaluated after load" );
|
||||
setTimeout( verifyEvaluation, 600 );
|
||||
} );
|
||||
} );
|
||||
@ -2881,7 +2890,7 @@ if ( typeof window.ArrayBuffer === "undefined" || typeof new XMLHttpRequest().re
|
||||
|
||||
jQuery( "#first" ).load( url( "test2.html" ), function() {
|
||||
assert.strictEqual( jQuery( "#foo" ).html(), "foo", "Check if script evaluation has modified DOM" );
|
||||
assert.strictEqual( window[ "testFoo" ], "foo", "Check if script was evaluated after load" );
|
||||
assert.strictEqual( window.testFoo, "foo", "Check if script was evaluated after load" );
|
||||
done();
|
||||
} );
|
||||
} );
|
||||
|
@ -239,7 +239,7 @@ QUnit.test( "attr(Hash)", function( assert ) {
|
||||
assert.equal(
|
||||
jQuery( "#text1" ).attr( {
|
||||
"value": function() {
|
||||
return this[ "id" ];
|
||||
return this.id;
|
||||
} } ).attr( "value" ),
|
||||
"text1",
|
||||
"Set attribute to computed value #1"
|
||||
@ -394,11 +394,11 @@ QUnit.test( "attr(String, Object)", function( assert ) {
|
||||
table = jQuery( "#table" ).append( "<tr><td>cell</td></tr><tr><td>cell</td><td>cell</td></tr><tr><td>cell</td><td>cell</td></tr>" );
|
||||
td = table.find( "td" ).eq( 0 );
|
||||
td.attr( "rowspan", "2" );
|
||||
assert.equal( td[ 0 ][ "rowSpan" ], 2, "Check rowspan is correctly set" );
|
||||
assert.equal( td[ 0 ].rowSpan, 2, "Check rowspan is correctly set" );
|
||||
td.attr( "colspan", "2" );
|
||||
assert.equal( td[ 0 ][ "colSpan" ], 2, "Check colspan is correctly set" );
|
||||
assert.equal( td[ 0 ].colSpan, 2, "Check colspan is correctly set" );
|
||||
table.attr( "cellspacing", "2" );
|
||||
assert.equal( table[ 0 ][ "cellSpacing" ], "2", "Check cellspacing is correctly set" );
|
||||
assert.equal( table[ 0 ].cellSpacing, "2", "Check cellspacing is correctly set" );
|
||||
|
||||
assert.equal( jQuery( "#area1" ).attr( "value" ), undefined, "Value attribute is distinct from value property." );
|
||||
|
||||
@ -456,6 +456,7 @@ QUnit.test( "attr(String, Object)", function( assert ) {
|
||||
|
||||
$radio = jQuery( "<input>", {
|
||||
"value": "sup",
|
||||
|
||||
// Use uppercase here to ensure the type
|
||||
// attrHook is still used
|
||||
"TYPE": "radio"
|
||||
@ -724,9 +725,9 @@ QUnit.test( "prop(String, Object) on null/undefined", function( assert ) {
|
||||
$body = jQuery( body );
|
||||
|
||||
assert.ok( $body.prop( "nextSibling" ) === null, "Make sure a null expando returns null" );
|
||||
body[ "foo" ] = "bar";
|
||||
body.foo = "bar";
|
||||
assert.equal( $body.prop( "foo" ), "bar", "Make sure the expando is preferred over the dom attribute" );
|
||||
body[ "foo" ] = undefined;
|
||||
body.foo = undefined;
|
||||
assert.ok( $body.prop( "foo" ) === undefined, "Make sure the expando is preferred over the dom attribute, even if undefined" );
|
||||
|
||||
select = document.createElement( "select" );
|
||||
@ -871,7 +872,7 @@ QUnit.test( "removeProp(String)", function( assert ) {
|
||||
obj = {};
|
||||
|
||||
assert.strictEqual(
|
||||
jQuery( "#firstp" ).prop( "nonexisting", "foo" ).removeProp( "nonexisting" )[ 0 ][ "nonexisting" ],
|
||||
jQuery( "#firstp" ).prop( "nonexisting", "foo" ).removeProp( "nonexisting" )[ 0 ].nonexisting,
|
||||
undefined,
|
||||
"removeprop works correctly on DOM element nodes"
|
||||
);
|
||||
@ -879,12 +880,12 @@ QUnit.test( "removeProp(String)", function( assert ) {
|
||||
jQuery.each( [ document, obj ], function( i, ele ) {
|
||||
var $ele = jQuery( ele );
|
||||
$ele.prop( "nonexisting", "foo" ).removeProp( "nonexisting" );
|
||||
assert.strictEqual( ele[ "nonexisting" ], undefined, "removeProp works correctly on non DOM element nodes (bug trac-7500)." );
|
||||
assert.strictEqual( ele.nonexisting, undefined, "removeProp works correctly on non DOM element nodes (bug trac-7500)." );
|
||||
} );
|
||||
jQuery.each( [ commentNode, textNode, attributeNode ], function( i, ele ) {
|
||||
var $ele = jQuery( ele );
|
||||
$ele.prop( "nonexisting", "foo" ).removeProp( "nonexisting" );
|
||||
assert.strictEqual( ele[ "nonexisting" ], undefined, "removeProp works correctly on non DOM element nodes (bug trac-7500)." );
|
||||
assert.strictEqual( ele.nonexisting, undefined, "removeProp works correctly on non DOM element nodes (bug trac-7500)." );
|
||||
} );
|
||||
} );
|
||||
|
||||
@ -1131,7 +1132,7 @@ QUnit.test( "val(select) after form.reset() (Bug trac-2551)", function( assert )
|
||||
|
||||
jQuery( "#kkk" ).val( "gf" );
|
||||
|
||||
document[ "kk" ].reset();
|
||||
document.kk.reset();
|
||||
|
||||
assert.equal( jQuery( "#kkk" )[ 0 ].value, "cf", "Check value of select after form reset." );
|
||||
assert.equal( jQuery( "#kkk" ).val(), "cf", "Check value of select after form reset." );
|
||||
|
@ -19,6 +19,7 @@ var output,
|
||||
outputA = addToOutput( "A" ),
|
||||
outputB = addToOutput( "B" ),
|
||||
outputC = addToOutput( "C" ),
|
||||
/* eslint-disable key-spacing */
|
||||
tests = {
|
||||
"": "XABC X XABCABCC X XBB X XABA X XX",
|
||||
"once": "XABC X X X X X XABA X XX",
|
||||
@ -227,7 +228,9 @@ jQuery.each( tests, function( strFlags, resultString ) {
|
||||
// Return false
|
||||
output = "X";
|
||||
cblist = jQuery.Callbacks( flags );
|
||||
cblist.add( outputA, function() { return false; }, outputB );
|
||||
cblist.add( outputA, function() {
|
||||
return false;
|
||||
}, outputB );
|
||||
cblist.add( outputA );
|
||||
cblist.fire();
|
||||
assert.strictEqual( output, results.shift(), "Callback returning false" );
|
||||
@ -269,7 +272,7 @@ QUnit.test( "jQuery.Callbacks( options ) - options are copied", function( assert
|
||||
fn = function() {
|
||||
assert.ok( !( count++ ), "called once" );
|
||||
};
|
||||
options[ "unique" ] = false;
|
||||
options.unique = false;
|
||||
cb.add( fn, fn );
|
||||
cb.fire();
|
||||
} );
|
||||
@ -364,7 +367,9 @@ QUnit.test( "jQuery.Callbacks() - disabled callback doesn't fire (gh-1790)", fun
|
||||
|
||||
var cb = jQuery.Callbacks(),
|
||||
fired = false,
|
||||
shot = function() { fired = true; };
|
||||
shot = function() {
|
||||
fired = true;
|
||||
};
|
||||
|
||||
cb.disable();
|
||||
cb.empty();
|
||||
@ -379,8 +384,12 @@ QUnit.test( "jQuery.Callbacks() - list with memory stays locked (gh-3469)", func
|
||||
|
||||
var cb = jQuery.Callbacks( "memory" ),
|
||||
fired = 0,
|
||||
count1 = function() { fired += 1; },
|
||||
count2 = function() { fired += 10; };
|
||||
count1 = function() {
|
||||
fired += 1;
|
||||
},
|
||||
count2 = function() {
|
||||
fired += 10;
|
||||
};
|
||||
|
||||
cb.add( count1 );
|
||||
cb.fire();
|
||||
|
@ -38,19 +38,21 @@ QUnit.test( "jQuery()", function( assert ) {
|
||||
// few here but beware of modular builds where these methods may be excluded.
|
||||
if ( includesModule( "deprecated" ) ) {
|
||||
expected++;
|
||||
attrObj[ "click" ] = function() { assert.ok( exec, "Click executed." ); };
|
||||
attrObj.click = function() {
|
||||
assert.ok( exec, "Click executed." );
|
||||
};
|
||||
}
|
||||
if ( includesModule( "dimensions" ) ) {
|
||||
expected++;
|
||||
attrObj[ "width" ] = 10;
|
||||
attrObj.width = 10;
|
||||
}
|
||||
if ( includesModule( "offset" ) ) {
|
||||
expected++;
|
||||
attrObj[ "offset" ] = { "top": 1, "left": 1 };
|
||||
attrObj.offset = { "top": 1, "left": 1 };
|
||||
}
|
||||
if ( includesModule( "css" ) ) {
|
||||
expected += 2;
|
||||
attrObj[ "css" ] = { "paddingLeft": 1, "paddingRight": 1 };
|
||||
attrObj.css = { "paddingLeft": 1, "paddingRight": 1 };
|
||||
}
|
||||
if ( includesModule( "attributes" ) ) {
|
||||
expected++;
|
||||
@ -216,17 +218,17 @@ QUnit.test( "noConflict", function( assert ) {
|
||||
var $$ = jQuery;
|
||||
|
||||
assert.strictEqual( jQuery, jQuery.noConflict(), "noConflict returned the jQuery object" );
|
||||
assert.strictEqual( window[ "jQuery" ], $$, "Make sure jQuery wasn't touched." );
|
||||
assert.strictEqual( window[ "$" ], original$, "Make sure $ was reverted." );
|
||||
assert.strictEqual( window.jQuery, $$, "Make sure jQuery wasn't touched." );
|
||||
assert.strictEqual( window.$, original$, "Make sure $ was reverted." );
|
||||
|
||||
jQuery = $ = $$;
|
||||
|
||||
assert.strictEqual( jQuery.noConflict( true ), $$, "noConflict returned the jQuery object" );
|
||||
assert.strictEqual( window[ "jQuery" ], originaljQuery, "Make sure jQuery was reverted." );
|
||||
assert.strictEqual( window[ "$" ], original$, "Make sure $ was reverted." );
|
||||
assert.strictEqual( window.jQuery, originaljQuery, "Make sure jQuery was reverted." );
|
||||
assert.strictEqual( window.$, original$, "Make sure $ was reverted." );
|
||||
assert.ok( $$().pushStack( [] ), "Make sure that jQuery still works." );
|
||||
|
||||
window[ "jQuery" ] = jQuery = $$;
|
||||
window.jQuery = jQuery = $$;
|
||||
} );
|
||||
|
||||
QUnit.test( "isPlainObject", function( assert ) {
|
||||
@ -274,7 +276,7 @@ QUnit.test( "isPlainObject", function( assert ) {
|
||||
|
||||
// Makes the function a little more realistic
|
||||
// (and harder to detect, incidentally)
|
||||
fn.prototype[ "someMethod" ] = function() {};
|
||||
fn.prototype.someMethod = function() {};
|
||||
|
||||
// Again, instantiated objects shouldn't be matched
|
||||
assert.ok( !jQuery.isPlainObject( new fn() ), "new fn" );
|
||||
@ -431,10 +433,10 @@ QUnit.test( "XSS via location.hash", function( assert ) {
|
||||
var done = assert.async();
|
||||
assert.expect( 1 );
|
||||
|
||||
jQuery[ "_check9521" ] = function( x ) {
|
||||
jQuery._check9521 = function( x ) {
|
||||
assert.ok( x, "script called from #id-like selector with inline handler" );
|
||||
jQuery( "#check9521" ).remove();
|
||||
delete jQuery[ "_check9521" ];
|
||||
delete jQuery._check9521;
|
||||
done();
|
||||
};
|
||||
try {
|
||||
@ -442,7 +444,7 @@ QUnit.test( "XSS via location.hash", function( assert ) {
|
||||
// This throws an error because it's processed like an id
|
||||
jQuery( "#<img id='check9521' src='no-such-.gif' onerror='jQuery._check9521(false)'>" ).appendTo( "#qunit-fixture" );
|
||||
} catch ( err ) {
|
||||
jQuery[ "_check9521" ]( true );
|
||||
jQuery._check9521( true );
|
||||
}
|
||||
} );
|
||||
|
||||
@ -451,12 +453,12 @@ QUnit.test( "jQuery('html')", function( assert ) {
|
||||
|
||||
var s, div, j;
|
||||
|
||||
jQuery[ "foo" ] = false;
|
||||
jQuery.foo = false;
|
||||
s = jQuery( "<script>jQuery.foo='test';</script>" )[ 0 ];
|
||||
assert.ok( s, "Creating a script" );
|
||||
assert.ok( !jQuery[ "foo" ], "Make sure the script wasn't executed prematurely" );
|
||||
assert.ok( !jQuery.foo, "Make sure the script wasn't executed prematurely" );
|
||||
jQuery( "body" ).append( "<script>jQuery.foo='test';</script>" );
|
||||
assert.ok( jQuery[ "foo" ], "Executing a script's contents in the right context" );
|
||||
assert.ok( jQuery.foo, "Executing a script's contents in the right context" );
|
||||
|
||||
// Test multi-line HTML
|
||||
div = jQuery( "<div>\r\nsome text\n<p>some p</p>\nmore text\r\n</div>" )[ 0 ];
|
||||
@ -634,7 +636,9 @@ QUnit.test( "each(Function)", function( assert ) {
|
||||
var div, pass, i;
|
||||
|
||||
div = jQuery( "div" );
|
||||
div.each( function() {this.foo = "zoo";} );
|
||||
div.each( function() {
|
||||
this.foo = "zoo";
|
||||
} );
|
||||
pass = true;
|
||||
for ( i = 0; i < div.length; i++ ) {
|
||||
if ( div.get( i ).foo !== "zoo" ) {
|
||||
@ -740,8 +744,13 @@ QUnit.test( "jQuery.map", function( assert ) {
|
||||
|
||||
result = {
|
||||
Zero: function() {},
|
||||
One: function( a ) { a = a; },
|
||||
Two: function( a, b ) { a = a; b = b; }
|
||||
One: function( a ) {
|
||||
a = a;
|
||||
},
|
||||
Two: function( a, b ) {
|
||||
a = a;
|
||||
b = b;
|
||||
}
|
||||
};
|
||||
callback = function( v, k ) {
|
||||
assert.equal( k, "foo", label + "-argument function treated like object" );
|
||||
@ -1000,25 +1009,25 @@ QUnit.test( "jQuery.extend(Object, Object)", function( assert ) {
|
||||
assert.deepEqual( options, optionsCopy, "Check if not modified: options must not be modified" );
|
||||
|
||||
jQuery.extend( true, deep1, deep2 );
|
||||
assert.deepEqual( deep1[ "foo" ], deepmerged[ "foo" ], "Check if foo: settings must be extended" );
|
||||
assert.deepEqual( deep2[ "foo" ], deep2copy[ "foo" ], "Check if not deep2: options must not be modified" );
|
||||
assert.equal( deep1[ "foo2" ], document, "Make sure that a deep clone was not attempted on the document" );
|
||||
assert.deepEqual( deep1.foo, deepmerged.foo, "Check if foo: settings must be extended" );
|
||||
assert.deepEqual( deep2.foo, deep2copy.foo, "Check if not deep2: options must not be modified" );
|
||||
assert.equal( deep1.foo2, document, "Make sure that a deep clone was not attempted on the document" );
|
||||
|
||||
assert.ok( jQuery.extend( true, {}, nestedarray )[ "arr" ] !== arr, "Deep extend of object must clone child array" );
|
||||
assert.ok( jQuery.extend( true, {}, nestedarray ).arr !== arr, "Deep extend of object must clone child array" );
|
||||
|
||||
// trac-5991
|
||||
assert.ok( Array.isArray( jQuery.extend( true, { "arr": {} }, nestedarray )[ "arr" ] ), "Cloned array have to be an Array" );
|
||||
assert.ok( jQuery.isPlainObject( jQuery.extend( true, { "arr": arr }, { "arr": {} } )[ "arr" ] ), "Cloned object have to be an plain object" );
|
||||
assert.ok( Array.isArray( jQuery.extend( true, { "arr": {} }, nestedarray ).arr ), "Cloned array have to be an Array" );
|
||||
assert.ok( jQuery.isPlainObject( jQuery.extend( true, { "arr": arr }, { "arr": {} } ).arr ), "Cloned object have to be an plain object" );
|
||||
|
||||
empty = {};
|
||||
optionsWithLength = { "foo": { "length": -1 } };
|
||||
jQuery.extend( true, empty, optionsWithLength );
|
||||
assert.deepEqual( empty[ "foo" ], optionsWithLength[ "foo" ], "The length property must copy correctly" );
|
||||
assert.deepEqual( empty.foo, optionsWithLength.foo, "The length property must copy correctly" );
|
||||
|
||||
empty = {};
|
||||
optionsWithDate = { "foo": { "date": new Date() } };
|
||||
jQuery.extend( true, empty, optionsWithDate );
|
||||
assert.deepEqual( empty[ "foo" ], optionsWithDate[ "foo" ], "Dates copy correctly" );
|
||||
assert.deepEqual( empty.foo, optionsWithDate.foo, "Dates copy correctly" );
|
||||
|
||||
/** @constructor */
|
||||
myKlass = function() {};
|
||||
@ -1026,13 +1035,13 @@ QUnit.test( "jQuery.extend(Object, Object)", function( assert ) {
|
||||
optionsWithCustomObject = { "foo": { "date": customObject } };
|
||||
empty = {};
|
||||
jQuery.extend( true, empty, optionsWithCustomObject );
|
||||
assert.ok( empty[ "foo" ] && empty[ "foo" ][ "date" ] === customObject, "Custom objects copy correctly (no methods)" );
|
||||
assert.ok( empty.foo && empty.foo.date === customObject, "Custom objects copy correctly (no methods)" );
|
||||
|
||||
// Makes the class a little more realistic
|
||||
myKlass.prototype = { "someMethod": function() {} };
|
||||
empty = {};
|
||||
jQuery.extend( true, empty, optionsWithCustomObject );
|
||||
assert.ok( empty[ "foo" ] && empty[ "foo" ][ "date" ] === customObject, "Custom objects copy correctly" );
|
||||
assert.ok( empty.foo && empty.foo.date === customObject, "Custom objects copy correctly" );
|
||||
|
||||
MyNumber = Number;
|
||||
|
||||
@ -1040,18 +1049,18 @@ QUnit.test( "jQuery.extend(Object, Object)", function( assert ) {
|
||||
assert.ok( parseInt( ret.foo, 10 ) === 5, "Wrapped numbers copy correctly" );
|
||||
|
||||
nullUndef = jQuery.extend( {}, options, { "xnumber2": null } );
|
||||
assert.ok( nullUndef[ "xnumber2" ] === null, "Check to make sure null values are copied" );
|
||||
assert.ok( nullUndef.xnumber2 === null, "Check to make sure null values are copied" );
|
||||
|
||||
nullUndef = jQuery.extend( {}, options, { "xnumber2": undefined } );
|
||||
assert.ok( nullUndef[ "xnumber2" ] === options[ "xnumber2" ], "Check to make sure undefined values are not copied" );
|
||||
assert.ok( nullUndef.xnumber2 === options.xnumber2, "Check to make sure undefined values are not copied" );
|
||||
|
||||
nullUndef = jQuery.extend( {}, options, { "xnumber0": null } );
|
||||
assert.ok( nullUndef[ "xnumber0" ] === null, "Check to make sure null values are inserted" );
|
||||
assert.ok( nullUndef.xnumber0 === null, "Check to make sure null values are inserted" );
|
||||
|
||||
target = {};
|
||||
recursive = { foo:target, bar:5 };
|
||||
recursive = { foo: target, bar: 5 };
|
||||
jQuery.extend( true, target, recursive );
|
||||
assert.deepEqual( target, { bar:5 }, "Check to make sure a recursive obj doesn't go never-ending loop by not copying it over" );
|
||||
assert.deepEqual( target, { bar: 5 }, "Check to make sure a recursive obj doesn't go never-ending loop by not copying it over" );
|
||||
|
||||
ret = jQuery.extend( true, { foo: [] }, { foo: [ 0 ] } ); // 1907
|
||||
assert.equal( ret.foo.length, 1, "Check to make sure a value with coercion 'false' copies over when necessary to fix trac-1907" );
|
||||
@ -1059,11 +1068,11 @@ QUnit.test( "jQuery.extend(Object, Object)", function( assert ) {
|
||||
ret = jQuery.extend( true, { foo: "1,2,3" }, { foo: [ 1, 2, 3 ] } );
|
||||
assert.ok( typeof ret.foo !== "string", "Check to make sure values equal with coercion (but not actually equal) overwrite correctly" );
|
||||
|
||||
ret = jQuery.extend( true, { foo:"bar" }, { foo:null } );
|
||||
ret = jQuery.extend( true, { foo: "bar" }, { foo: null } );
|
||||
assert.ok( typeof ret.foo !== "undefined", "Make sure a null value doesn't crash with deep extend, for trac-1908" );
|
||||
|
||||
obj = { foo:null };
|
||||
jQuery.extend( true, obj, { foo:"notnull" } );
|
||||
obj = { foo: null };
|
||||
jQuery.extend( true, obj, { foo: "notnull" } );
|
||||
assert.equal( obj.foo, "notnull", "Make sure a null value can be overwritten" );
|
||||
|
||||
function func() {}
|
||||
@ -1173,8 +1182,13 @@ QUnit.test( "jQuery.each(Object,Function)", function( assert ) {
|
||||
|
||||
seen = {
|
||||
Zero: function() {},
|
||||
One: function( a ) { a = a; },
|
||||
Two: function( a, b ) { a = a; b = b; }
|
||||
One: function( a ) {
|
||||
a = a;
|
||||
},
|
||||
Two: function( a, b ) {
|
||||
a = a;
|
||||
b = b;
|
||||
}
|
||||
};
|
||||
callback = function( k ) {
|
||||
assert.equal( k, "foo", label + "-argument function treated like object" );
|
||||
@ -1283,7 +1297,9 @@ QUnit.test( "jQuery.makeArray", function( assert ) {
|
||||
|
||||
assert.equal( jQuery.makeArray( document.getElementsByName( "PWD" ) ).slice( 0, 1 )[ 0 ].name, "PWD", "Pass makeArray a nodelist" );
|
||||
|
||||
assert.equal( ( function() { return jQuery.makeArray( arguments ); } )( 1, 2 ).join( "" ), "12", "Pass makeArray an arguments array" );
|
||||
assert.equal( ( function() {
|
||||
return jQuery.makeArray( arguments );
|
||||
} )( 1, 2 ).join( "" ), "12", "Pass makeArray an arguments array" );
|
||||
|
||||
assert.equal( jQuery.makeArray( [ 1, 2, 3 ] ).join( "" ), "123", "Pass makeArray a real array" );
|
||||
|
||||
@ -1297,12 +1313,14 @@ QUnit.test( "jQuery.makeArray", function( assert ) {
|
||||
|
||||
assert.equal( jQuery.makeArray( document.createElement( "div" ) )[ 0 ].nodeName.toUpperCase(), "DIV", "Pass makeArray a single node" );
|
||||
|
||||
assert.equal( jQuery.makeArray( { length:2, 0:"a", 1:"b" } ).join( "" ), "ab", "Pass makeArray an array like map (with length)" );
|
||||
assert.equal( jQuery.makeArray( { length: 2, 0: "a", 1: "b" } ).join( "" ), "ab", "Pass makeArray an array like map (with length)" );
|
||||
|
||||
assert.ok( !!jQuery.makeArray( document.documentElement.childNodes ).slice( 0, 1 )[ 0 ].nodeName, "Pass makeArray a childNodes array" );
|
||||
|
||||
// function, is tricky as it has length
|
||||
assert.equal( jQuery.makeArray( function() { return 1;} )[ 0 ](), 1, "Pass makeArray a function" );
|
||||
assert.equal( jQuery.makeArray( function() {
|
||||
return 1;
|
||||
} )[ 0 ](), 1, "Pass makeArray a function" );
|
||||
|
||||
//window, also has length
|
||||
assert.equal( jQuery.makeArray( window )[ 0 ], window, "Pass makeArray the window" );
|
||||
@ -1328,7 +1346,7 @@ QUnit.test( "jQuery.isEmptyObject", function( assert ) {
|
||||
assert.expect( 2 );
|
||||
|
||||
assert.equal( true, jQuery.isEmptyObject( {} ), "isEmptyObject on empty object literal" );
|
||||
assert.equal( false, jQuery.isEmptyObject( { a:1 } ), "isEmptyObject on non-empty object literal" );
|
||||
assert.equal( false, jQuery.isEmptyObject( { a: 1 } ), "isEmptyObject on non-empty object literal" );
|
||||
|
||||
// What about this ?
|
||||
// equal(true, jQuery.isEmptyObject(null), "isEmptyObject on null" );
|
||||
|
@ -38,7 +38,7 @@ QUnit.test( "css(String|Hash)", function( assert ) {
|
||||
|
||||
width = parseFloat( jQuery( "#nothiddendiv" ).css( "width" ) );
|
||||
height = parseFloat( jQuery( "#nothiddendiv" ).css( "height" ) );
|
||||
jQuery( "#nothiddendiv" ).css( { "overflow":"hidden", "width": -1, "height": -1 } );
|
||||
jQuery( "#nothiddendiv" ).css( { "overflow": "hidden", "width": -1, "height": -1 } );
|
||||
assert.equal( parseFloat( jQuery( "#nothiddendiv" ).css( "width" ) ), 0, "Test negative width set to 0" );
|
||||
assert.equal( parseFloat( jQuery( "#nothiddendiv" ).css( "height" ) ), 0, "Test negative height set to 0" );
|
||||
|
||||
@ -321,8 +321,7 @@ QUnit.test( "css(String, Object)", function( assert ) {
|
||||
success = true;
|
||||
try {
|
||||
jQuery( "#foo" ).css( "backgroundColor", "rgba(0, 0, 0, 0.1)" );
|
||||
}
|
||||
catch ( e ) {
|
||||
} catch ( e ) {
|
||||
success = false;
|
||||
}
|
||||
assert.ok( success, "Setting RGBA values does not throw Error (trac-5509)" );
|
||||
@ -1221,6 +1220,7 @@ QUnit.test( "Do not append px (trac-9548, trac-12990, gh-2792, gh-5179)", functi
|
||||
|
||||
$div.css( "animation-iteration-count", 2 );
|
||||
if ( $div.css( "animation-iteration-count" ) !== undefined ) {
|
||||
|
||||
// if $div.css( "animation-iteration-count" ) returns "1",
|
||||
// it actually returns the default value of animation-iteration-count
|
||||
assert.equal( $div.css( "animation-iteration-count" ), "2",
|
||||
@ -1788,7 +1788,7 @@ QUnit.test( "Do not throw on frame elements from css method (trac-15098)", funct
|
||||
if ( transformName ) {
|
||||
assert.equal( elemStyle[ transformName ], transformVal, "setting properly-prefixed transform" );
|
||||
}
|
||||
assert.equal( elemStyle[ "undefined" ], undefined, "Nothing writes to node.style.undefined" );
|
||||
assert.equal( elemStyle.undefined, undefined, "Nothing writes to node.style.undefined" );
|
||||
} );
|
||||
|
||||
QUnit.test( "Don't detect fake set properties on a node when caching the prefixed version", function( assert ) {
|
||||
|
@ -74,14 +74,14 @@ function dataTests( elem, assert ) {
|
||||
|
||||
assert.strictEqual( jQuery.hasData( elem ), false, "jQuery.hasData agrees no data exists even when an empty data obj exists" );
|
||||
|
||||
dataObj[ "foo" ] = "bar";
|
||||
dataObj.foo = "bar";
|
||||
assert.equal( jQuery.data( elem, "foo" ), "bar", "Data is readable by jQuery.data when set directly on a returned data object" );
|
||||
|
||||
assert.strictEqual( jQuery.hasData( elem ), true, "jQuery.hasData agrees data exists when data exists" );
|
||||
|
||||
jQuery.data( elem, "foo", "baz" );
|
||||
assert.equal( jQuery.data( elem, "foo" ), "baz", "Data can be changed by jQuery.data" );
|
||||
assert.equal( dataObj[ "foo" ], "baz", "Changes made through jQuery.data propagate to referenced data object" );
|
||||
assert.equal( dataObj.foo, "baz", "Changes made through jQuery.data propagate to referenced data object" );
|
||||
|
||||
jQuery.data( elem, "foo", undefined );
|
||||
assert.equal( jQuery.data( elem, "foo" ), "baz", "Data is not unset by passing undefined to jQuery.data" );
|
||||
@ -398,7 +398,7 @@ QUnit.test( "data-* attributes", function( assert ) {
|
||||
break;
|
||||
case 2:
|
||||
assert.equal( jQuery( elem ).data( "zoooo" ), "bar", "Check zoooo property" );
|
||||
assert.deepEqual( jQuery( elem ).data( "bar" ), { "test":"baz" }, "Check bar property" );
|
||||
assert.deepEqual( jQuery( elem ).data( "bar" ), { "test": "baz" }, "Check bar property" );
|
||||
break;
|
||||
case 3:
|
||||
assert.equal( jQuery( elem ).data( "number" ), true, "Check number property" );
|
||||
@ -426,13 +426,13 @@ QUnit.test( ".data(Object)", function( assert ) {
|
||||
assert.equal( div.data( "test" ), "in", "Verify setting an object in data" );
|
||||
assert.equal( div.data( "test2" ), "in2", "Verify setting an object in data" );
|
||||
|
||||
obj = { test:"unset" };
|
||||
obj = { test: "unset" };
|
||||
jqobj = jQuery( obj );
|
||||
|
||||
jqobj.data( "test", "unset" );
|
||||
jqobj.data( { "test": "in", "test2": "in2" } );
|
||||
assert.equal( jQuery.data( obj )[ "test" ], "in", "Verify setting an object on an object extends the data object" );
|
||||
assert.equal( obj[ "test2" ], undefined, "Verify setting an object on an object does not extend the object" );
|
||||
assert.equal( jQuery.data( obj ).test, "in", "Verify setting an object on an object extends the data object" );
|
||||
assert.equal( obj.test2, undefined, "Verify setting an object on an object does not extend the object" );
|
||||
|
||||
// manually clean up detached elements
|
||||
div.remove();
|
||||
@ -523,12 +523,12 @@ QUnit.test( ".data should follow html5 specification regarding camel casing", fu
|
||||
var div = jQuery( "<div id='myObject' data-w-t-f='ftw' data-big-a-little-a='bouncing-b' data-foo='a' data-foo-bar='b' data-foo-bar-baz='c'></div>" )
|
||||
.prependTo( "body" );
|
||||
|
||||
assert.equal( div.data()[ "wTF" ], "ftw", "Verify single letter data-* key" );
|
||||
assert.equal( div.data()[ "bigALittleA" ], "bouncing-b", "Verify single letter mixed data-* key" );
|
||||
assert.equal( div.data().wTF, "ftw", "Verify single letter data-* key" );
|
||||
assert.equal( div.data().bigALittleA, "bouncing-b", "Verify single letter mixed data-* key" );
|
||||
|
||||
assert.equal( div.data()[ "foo" ], "a", "Verify single word data-* key" );
|
||||
assert.equal( div.data()[ "fooBar" ], "b", "Verify multiple word data-* key" );
|
||||
assert.equal( div.data()[ "fooBarBaz" ], "c", "Verify multiple word data-* key" );
|
||||
assert.equal( div.data().foo, "a", "Verify single word data-* key" );
|
||||
assert.equal( div.data().fooBar, "b", "Verify multiple word data-* key" );
|
||||
assert.equal( div.data().fooBarBaz, "c", "Verify multiple word data-* key" );
|
||||
|
||||
assert.equal( div.data( "foo" ), "a", "Verify single word data-* key" );
|
||||
assert.equal( div.data( "fooBar" ), "b", "Verify multiple word data-* key" );
|
||||
|
@ -108,7 +108,9 @@ QUnit.test( "jQuery.Deferred.then - filtering (done)", function( assert ) {
|
||||
piped = defer.then( function( a, b ) {
|
||||
return a * b;
|
||||
} ),
|
||||
done = jQuery.map( new Array( 3 ), function() { return assert.async(); } );
|
||||
done = jQuery.map( new Array( 3 ), function() {
|
||||
return assert.async();
|
||||
} );
|
||||
|
||||
piped.done( function( result ) {
|
||||
value3 = result;
|
||||
@ -145,7 +147,9 @@ QUnit.test( "jQuery.Deferred.then - filtering (fail)", function( assert ) {
|
||||
piped = defer.then( null, function( a, b ) {
|
||||
return a * b;
|
||||
} ),
|
||||
done = jQuery.map( new Array( 3 ), function() { return assert.async(); } );
|
||||
done = jQuery.map( new Array( 3 ), function() {
|
||||
return assert.async();
|
||||
} );
|
||||
|
||||
piped.done( function( result ) {
|
||||
value3 = result;
|
||||
@ -178,10 +182,12 @@ QUnit.test( "jQuery.Deferred.catch", function( assert ) {
|
||||
|
||||
var value1, value2, value3,
|
||||
defer = jQuery.Deferred(),
|
||||
piped = defer[ "catch" ]( function( a, b ) {
|
||||
piped = defer.catch( function( a, b ) {
|
||||
return a * b;
|
||||
} ),
|
||||
done = jQuery.map( new Array( 3 ), function() { return assert.async(); } );
|
||||
done = jQuery.map( new Array( 3 ), function() {
|
||||
return assert.async();
|
||||
} );
|
||||
|
||||
piped.done( function( result ) {
|
||||
value3 = result;
|
||||
@ -192,18 +198,18 @@ QUnit.test( "jQuery.Deferred.catch", function( assert ) {
|
||||
value2 = b;
|
||||
} );
|
||||
|
||||
defer.reject( 2, 3 )[ "catch" ]( function() {
|
||||
defer.reject( 2, 3 ).catch( function() {
|
||||
assert.strictEqual( value1, 2, "first reject value ok" );
|
||||
assert.strictEqual( value2, 3, "second reject value ok" );
|
||||
assert.strictEqual( value3, 6, "result of filter ok" );
|
||||
done.pop().call();
|
||||
} );
|
||||
|
||||
jQuery.Deferred().resolve()[ "catch" ]( function() {
|
||||
jQuery.Deferred().resolve().catch( function() {
|
||||
assert.ok( false, "then should not be called on resolve" );
|
||||
} ).then( done.pop() );
|
||||
|
||||
jQuery.Deferred().reject()[ "catch" ]( jQuery.noop ).done( function( value ) {
|
||||
jQuery.Deferred().reject().catch( jQuery.noop ).done( function( value ) {
|
||||
assert.strictEqual( value, undefined, "then fail callback can return undefined/null" );
|
||||
done.pop().call();
|
||||
} );
|
||||
@ -218,7 +224,9 @@ QUnit.test( "[PIPE ONLY] jQuery.Deferred.pipe - filtering (fail)", function( ass
|
||||
piped = defer.pipe( null, function( a, b ) {
|
||||
return a * b;
|
||||
} ),
|
||||
done = jQuery.map( new Array( 3 ), function() { return assert.async(); } );
|
||||
done = jQuery.map( new Array( 3 ), function() {
|
||||
return assert.async();
|
||||
} );
|
||||
|
||||
piped.fail( function( result ) {
|
||||
value3 = result;
|
||||
@ -416,7 +424,9 @@ QUnit.test( "jQuery.Deferred.then - context", function( assert ) {
|
||||
|
||||
var defer, piped, defer2, piped2,
|
||||
context = { custom: true },
|
||||
done = jQuery.map( new Array( 5 ), function() { return assert.async(); } );
|
||||
done = jQuery.map( new Array( 5 ), function() {
|
||||
return assert.async();
|
||||
} );
|
||||
|
||||
jQuery.Deferred().resolveWith( context, [ 2 ] ).then( function( value ) {
|
||||
assert.strictEqual( this, context, "custom context received by .then handler" );
|
||||
@ -475,7 +485,9 @@ QUnit.test( "[PIPE ONLY] jQuery.Deferred.pipe - context", function( assert ) {
|
||||
|
||||
var defer, piped, defer2, piped2,
|
||||
context = { custom: true },
|
||||
done = jQuery.map( new Array( 5 ), function() { return assert.async(); } );
|
||||
done = jQuery.map( new Array( 5 ), function() {
|
||||
return assert.async();
|
||||
} );
|
||||
|
||||
jQuery.Deferred().resolveWith( context, [ 2 ] ).pipe( function( value ) {
|
||||
assert.strictEqual( this, context, "custom context received by .pipe handler" );
|
||||
@ -676,7 +688,9 @@ QUnit.test( "jQuery.Deferred - 1.x/2.x compatibility", function( assert ) {
|
||||
|
||||
var context = { id: "callback context" },
|
||||
thenable = jQuery.Deferred().resolve( "thenable fulfillment" ).promise(),
|
||||
done = jQuery.map( new Array( 8 ), function() { return assert.async(); } );
|
||||
done = jQuery.map( new Array( 8 ), function() {
|
||||
return assert.async();
|
||||
} );
|
||||
|
||||
thenable.unwrapped = false;
|
||||
|
||||
@ -727,7 +741,9 @@ QUnit.test( "jQuery.Deferred.then - progress and thenables", function( assert )
|
||||
|
||||
var trigger = jQuery.Deferred().notify(),
|
||||
expectedProgress = [ "baz", "baz" ],
|
||||
done = jQuery.map( new Array( 2 ), function() { return assert.async(); } ),
|
||||
done = jQuery.map( new Array( 2 ), function() {
|
||||
return assert.async();
|
||||
} ),
|
||||
failer = function( evt ) {
|
||||
return function() {
|
||||
assert.ok( false, "no unexpected " + evt );
|
||||
@ -752,7 +768,9 @@ QUnit.test( "jQuery.Deferred - notify and resolve", function( assert ) {
|
||||
assert.expect( 7 );
|
||||
|
||||
var notifiedResolved = jQuery.Deferred().notify( "foo" )/*xxx .resolve( "bar" )*/,
|
||||
done = jQuery.map( new Array( 3 ), function() { return assert.async(); } );
|
||||
done = jQuery.map( new Array( 3 ), function() {
|
||||
return assert.async();
|
||||
} );
|
||||
|
||||
notifiedResolved.progress( function( v ) {
|
||||
assert.strictEqual( v, "foo", "progress value" );
|
||||
@ -836,7 +854,9 @@ QUnit.test( "jQuery.when(nonThenable) - like Promise.resolve", function( assert
|
||||
|
||||
// Support: Android 4.0 only
|
||||
// Strict mode functions invoked without .call/.apply get global-object context
|
||||
defaultContext = ( function getDefaultContext() { return this; } ).call(),
|
||||
defaultContext = ( function getDefaultContext() {
|
||||
return this;
|
||||
} ).call(),
|
||||
|
||||
done = assert.async( 20 );
|
||||
|
||||
@ -891,6 +911,7 @@ QUnit.test( "jQuery.when(thenable) - like Promise.resolve", function( assert ) {
|
||||
|
||||
var customToStringThen = {
|
||||
then: function( onFulfilled ) {
|
||||
|
||||
// Support: Android 4.0 only
|
||||
// Strict mode functions invoked without .call/.apply get global-object context
|
||||
onFulfilled.call();
|
||||
@ -956,7 +977,9 @@ QUnit.test( "jQuery.when(thenable) - like Promise.resolve", function( assert ) {
|
||||
|
||||
// Support: Android 4.0 only
|
||||
// Strict mode functions invoked without .call/.apply get global-object context
|
||||
defaultContext = ( function getDefaultContext() { return this; } ).call(),
|
||||
defaultContext = ( function getDefaultContext() {
|
||||
return this;
|
||||
} ).call(),
|
||||
|
||||
done = assert.async( numCases * 2 );
|
||||
|
||||
@ -1036,7 +1059,9 @@ QUnit.test( "jQuery.when(a, b) - like Promise.all", function( assert ) {
|
||||
|
||||
// Support: Android 4.0 only
|
||||
// Strict mode functions invoked without .call/.apply get global-object context
|
||||
defaultContext = ( function getDefaultContext() { return this; } ).call(),
|
||||
defaultContext = ( function getDefaultContext() {
|
||||
return this;
|
||||
} ).call(),
|
||||
|
||||
done = assert.async( 98 );
|
||||
|
||||
|
@ -46,8 +46,12 @@ QUnit.test( "hover() mouseenter mouseleave", function( assert ) {
|
||||
assert.expect( 1 );
|
||||
|
||||
var times = 0,
|
||||
handler1 = function() { ++times; },
|
||||
handler2 = function() { ++times; };
|
||||
handler1 = function() {
|
||||
++times;
|
||||
},
|
||||
handler2 = function() {
|
||||
++times;
|
||||
};
|
||||
|
||||
jQuery( "#firstp" )
|
||||
.hover( handler1, handler2 )
|
||||
|
62
test/unit/effects.js
vendored
62
test/unit/effects.js
vendored
@ -7,8 +7,12 @@ if ( !includesModule( "effects" ) ) {
|
||||
|
||||
var oldRaf = window.requestAnimationFrame,
|
||||
hideOptions = {
|
||||
inline: function() { jQuery.style( this, "display", "none" ); },
|
||||
cascade: function() { this.className = "hidden"; }
|
||||
inline: function() {
|
||||
jQuery.style( this, "display", "none" );
|
||||
},
|
||||
cascade: function() {
|
||||
this.className = "hidden";
|
||||
}
|
||||
};
|
||||
|
||||
QUnit.module( "effects", {
|
||||
@ -564,12 +568,12 @@ QUnit.test( "animate duration 0", function( assert ) {
|
||||
assert.expect( 11 );
|
||||
|
||||
var $elem,
|
||||
$elems = jQuery( [ { a:0 }, { a:0 } ] ),
|
||||
$elems = jQuery( [ { a: 0 }, { a: 0 } ] ),
|
||||
counter = 0;
|
||||
|
||||
assert.equal( jQuery.timers.length, 0, "Make sure no animation was running from another test" );
|
||||
|
||||
$elems.eq( 0 ).animate( { a:1 }, 0, function() {
|
||||
$elems.eq( 0 ).animate( { a: 1 }, 0, function() {
|
||||
assert.ok( true, "Animate a simple property." );
|
||||
counter++;
|
||||
} );
|
||||
@ -579,18 +583,18 @@ QUnit.test( "animate duration 0", function( assert ) {
|
||||
|
||||
assert.equal( counter, 1, "One synchronic animations" );
|
||||
|
||||
$elems.animate( { a:2 }, 0, function() {
|
||||
$elems.animate( { a: 2 }, 0, function() {
|
||||
assert.ok( true, "Animate a second simple property." );
|
||||
counter++;
|
||||
} );
|
||||
|
||||
assert.equal( counter, 3, "Multiple synchronic animations" );
|
||||
|
||||
$elems.eq( 0 ).animate( { a:3 }, 0, function() {
|
||||
$elems.eq( 0 ).animate( { a: 3 }, 0, function() {
|
||||
assert.ok( true, "Animate a third simple property." );
|
||||
counter++;
|
||||
} );
|
||||
$elems.eq( 1 ).animate( { a:3 }, 200, function() {
|
||||
$elems.eq( 1 ).animate( { a: 3 }, 200, function() {
|
||||
counter++;
|
||||
|
||||
// Failed until [6115]
|
||||
@ -981,15 +985,33 @@ jQuery.each( {
|
||||
num = 0;
|
||||
|
||||
// TODO: uncrowd this
|
||||
if ( t_h === "show" ) { num++; }
|
||||
if ( t_w === "show" ) { num++; }
|
||||
if ( t_w === "hide" || t_w === "show" ) { num++; }
|
||||
if ( t_h === "hide" || t_h === "show" ) { num++; }
|
||||
if ( t_o === "hide" || t_o === "show" ) { num++; }
|
||||
if ( t_w === "hide" ) { num++; }
|
||||
if ( t_o.constructor === Number ) { num += 2; }
|
||||
if ( t_w.constructor === Number ) { num += 2; }
|
||||
if ( t_h.constructor === Number ) { num += 2; }
|
||||
if ( t_h === "show" ) {
|
||||
num++;
|
||||
}
|
||||
if ( t_w === "show" ) {
|
||||
num++;
|
||||
}
|
||||
if ( t_w === "hide" || t_w === "show" ) {
|
||||
num++;
|
||||
}
|
||||
if ( t_h === "hide" || t_h === "show" ) {
|
||||
num++;
|
||||
}
|
||||
if ( t_o === "hide" || t_o === "show" ) {
|
||||
num++;
|
||||
}
|
||||
if ( t_w === "hide" ) {
|
||||
num++;
|
||||
}
|
||||
if ( t_o.constructor === Number ) {
|
||||
num += 2;
|
||||
}
|
||||
if ( t_w.constructor === Number ) {
|
||||
num += 2;
|
||||
}
|
||||
if ( t_h.constructor === Number ) {
|
||||
num += 2;
|
||||
}
|
||||
|
||||
assert.expect( num );
|
||||
|
||||
@ -2487,7 +2509,9 @@ QUnit.test( "Show/hide/toggle and display: inline", function( assert ) {
|
||||
.hide().show( N ),
|
||||
$el.clone().data( { call: "hide+toggle", done: "inline" } ).appendTo( fixture )
|
||||
.hide().toggle( N )
|
||||
], function( $clone ) { return $clone[ 0 ]; } );
|
||||
], function( $clone ) {
|
||||
return $clone[ 0 ];
|
||||
} );
|
||||
|
||||
// Animations not allowed to complete
|
||||
interrupted = jQuery.map( [
|
||||
@ -2495,7 +2519,9 @@ QUnit.test( "Show/hide/toggle and display: inline", function( assert ) {
|
||||
$el.clone().data( { call: "toggle+stop" } ).appendTo( fixture ).toggle( N ),
|
||||
$el.clone().data( { call: "hide+show+stop" } ).appendTo( fixture ).hide().show( N ),
|
||||
$el.clone().data( { call: "hide+toggle+stop" } ).appendTo( fixture ).hide().toggle( N )
|
||||
], function( $clone ) { return $clone[ 0 ]; } );
|
||||
], function( $clone ) {
|
||||
return $clone[ 0 ];
|
||||
} );
|
||||
|
||||
// All elements should be inline-block during the animation
|
||||
clock.tick( N / 2 );
|
||||
|
@ -224,12 +224,12 @@ QUnit.test( "on(), namespace with special add", function( assert ) {
|
||||
|
||||
div.on( "test.a", { x: 1 }, function( e ) {
|
||||
assert.ok( !!e.xyz, "Make sure that the data is getting passed through." );
|
||||
assert.equal( e.data[ "x" ], 1, "Make sure data is attached properly." );
|
||||
assert.equal( e.data.x, 1, "Make sure data is attached properly." );
|
||||
} );
|
||||
|
||||
div.on( "test.b", { x: 2 }, function( e ) {
|
||||
assert.ok( !!e.xyz, "Make sure that the data is getting passed through." );
|
||||
assert.equal( e.data[ "x" ], 2, "Make sure data is attached properly." );
|
||||
assert.equal( e.data.x, 2, "Make sure data is attached properly." );
|
||||
} );
|
||||
|
||||
// Should trigger 5
|
||||
@ -293,14 +293,14 @@ QUnit.test( "on/one/off(Object)", function( assert ) {
|
||||
|
||||
// Regular bind
|
||||
.on( {
|
||||
"click":handler,
|
||||
"mouseover":handler
|
||||
"click": handler,
|
||||
"mouseover": handler
|
||||
} )
|
||||
|
||||
// Bind with data
|
||||
.one( {
|
||||
"click":handlerWithData,
|
||||
"mouseover":handlerWithData
|
||||
"click": handlerWithData,
|
||||
"mouseover": handlerWithData
|
||||
}, 2 );
|
||||
|
||||
trigger();
|
||||
@ -313,8 +313,8 @@ QUnit.test( "on/one/off(Object)", function( assert ) {
|
||||
assert.equal( mouseoverCounter, 4, "on(Object)" );
|
||||
|
||||
jQuery( "#firstp" ).off( {
|
||||
"click":handler,
|
||||
"mouseover":handler
|
||||
"click": handler,
|
||||
"mouseover": handler
|
||||
} );
|
||||
|
||||
trigger();
|
||||
@ -553,7 +553,9 @@ QUnit.test( "on(), namespaced events, cloned events", function( assert ) {
|
||||
} ).trigger( "tester" );
|
||||
|
||||
// Make sure events stick with appendTo'd elements (which are cloned) trac-2027
|
||||
jQuery( "<a href='#fail' class='test'>test</a>" ).on( "click", function() { return false; } ).appendTo( "#qunit-fixture" );
|
||||
jQuery( "<a href='#fail' class='test'>test</a>" ).on( "click", function() {
|
||||
return false;
|
||||
} ).appendTo( "#qunit-fixture" );
|
||||
assert.ok( jQuery( "a.test" ).eq( 0 ).triggerHandler( "click" ) === false, "Handler is bound to appendTo'd elements" );
|
||||
} );
|
||||
|
||||
@ -704,7 +706,9 @@ QUnit.test( "on(name, false), off(name, false)", function( assert ) {
|
||||
assert.expect( 3 );
|
||||
|
||||
var main = 0;
|
||||
jQuery( "#qunit-fixture" ).on( "click", function() { main++; } );
|
||||
jQuery( "#qunit-fixture" ).on( "click", function() {
|
||||
main++;
|
||||
} );
|
||||
jQuery( "#ap" ).trigger( "click" );
|
||||
assert.equal( main, 1, "Verify that the trigger happened correctly." );
|
||||
|
||||
@ -727,7 +731,9 @@ QUnit.test( "on(name, selector, false), off(name, selector, false)", function( a
|
||||
|
||||
var main = 0;
|
||||
|
||||
jQuery( "#qunit-fixture" ).on( "click", "#ap", function() { main++; } );
|
||||
jQuery( "#qunit-fixture" ).on( "click", "#ap", function() {
|
||||
main++;
|
||||
} );
|
||||
jQuery( "#ap" ).trigger( "click" );
|
||||
assert.equal( main, 1, "Verify that the trigger happened correctly." );
|
||||
|
||||
@ -766,7 +772,7 @@ QUnit.test( "on()/trigger()/off() on plain object", function( assert ) {
|
||||
|
||||
events = jQuery._data( obj, "events" );
|
||||
assert.ok( events, "Object has events bound." );
|
||||
assert.equal( obj[ "events" ], undefined, "Events object on plain objects is not events" );
|
||||
assert.equal( obj.events, undefined, "Events object on plain objects is not events" );
|
||||
assert.equal( obj.test, undefined, "Make sure that test event is not on the plain object." );
|
||||
assert.equal( obj.handle, undefined, "Make sure that the event handler is not on the plain object." );
|
||||
|
||||
@ -785,7 +791,7 @@ QUnit.test( "on()/trigger()/off() on plain object", function( assert ) {
|
||||
|
||||
assert.equal( obj && obj[ jQuery.expando ] &&
|
||||
obj[ jQuery.expando ][ jQuery.expando ] &&
|
||||
obj[ jQuery.expando ][ jQuery.expando ][ "events" ], undefined, "Make sure events object is removed" );
|
||||
obj[ jQuery.expando ][ jQuery.expando ].events, undefined, "Make sure events object is removed" );
|
||||
} );
|
||||
|
||||
QUnit.test( "off(type)", function( assert ) {
|
||||
@ -938,12 +944,26 @@ QUnit.test( "trigger() bubbling", function( assert ) {
|
||||
|
||||
var win = 0, doc = 0, html = 0, body = 0, main = 0, ap = 0;
|
||||
|
||||
jQuery( window ).on( "click", function() { win++; } );
|
||||
jQuery( document ).on( "click", function( e ) { if ( e.target !== document ) { doc++; } } );
|
||||
jQuery( "html" ).on( "click", function() { html++; } );
|
||||
jQuery( "body" ).on( "click", function() { body++; } );
|
||||
jQuery( "#qunit-fixture" ).on( "click", function() { main++; } );
|
||||
jQuery( "#ap" ).on( "click", function() { ap++; return false; } );
|
||||
jQuery( window ).on( "click", function() {
|
||||
win++;
|
||||
} );
|
||||
jQuery( document ).on( "click", function( e ) {
|
||||
if ( e.target !== document ) {
|
||||
doc++;
|
||||
}
|
||||
} );
|
||||
jQuery( "html" ).on( "click", function() {
|
||||
html++;
|
||||
} );
|
||||
jQuery( "body" ).on( "click", function() {
|
||||
body++;
|
||||
} );
|
||||
jQuery( "#qunit-fixture" ).on( "click", function() {
|
||||
main++;
|
||||
} );
|
||||
jQuery( "#ap" ).on( "click", function() {
|
||||
ap++; return false;
|
||||
} );
|
||||
|
||||
jQuery( "html" ).trigger( "click" );
|
||||
assert.equal( win, 1, "HTML bubble" );
|
||||
@ -1159,7 +1179,9 @@ QUnit.test( "trigger(eventObject, [data], [fn])", function( assert ) {
|
||||
event.stopPropagation();
|
||||
assert.equal( event.isPropagationStopped(), true, "Verify isPropagationStopped" );
|
||||
|
||||
event.isPropagationStopped = function() { return false; };
|
||||
event.isPropagationStopped = function() {
|
||||
return false;
|
||||
};
|
||||
event.stopImmediatePropagation();
|
||||
assert.equal( event.isPropagationStopped(), true, "Verify isPropagationStopped" );
|
||||
assert.equal( event.isImmediatePropagationStopped(), true, "Verify isPropagationStopped" );
|
||||
@ -1394,7 +1416,9 @@ QUnit.test( "Submit event can be stopped (trac-11049)", function( assert ) {
|
||||
return false;
|
||||
} )
|
||||
.find( "#myform input[type=submit]" )
|
||||
.each( function() { this.click(); } )
|
||||
.each( function() {
|
||||
this.click();
|
||||
} )
|
||||
.end()
|
||||
.on( "submit", function() {
|
||||
assert.ok( false, "submit bubbled on second handler" );
|
||||
@ -1506,10 +1530,18 @@ QUnit.test( ".on()/.off()", function( assert ) {
|
||||
var event, clicked, hash, called, livec, lived, livee,
|
||||
submit = 0, div = 0, livea = 0, liveb = 0;
|
||||
|
||||
jQuery( "#body" ).on( "submit", "#qunit-fixture div", function() { submit++; return false; } );
|
||||
jQuery( "#body" ).on( "click", "#qunit-fixture div", function() { div++; } );
|
||||
jQuery( "#body" ).on( "click", "div#nothiddendiv", function() { livea++; } );
|
||||
jQuery( "#body" ).on( "click", "div#nothiddendivchild", function() { liveb++; } );
|
||||
jQuery( "#body" ).on( "submit", "#qunit-fixture div", function() {
|
||||
submit++; return false;
|
||||
} );
|
||||
jQuery( "#body" ).on( "click", "#qunit-fixture div", function() {
|
||||
div++;
|
||||
} );
|
||||
jQuery( "#body" ).on( "click", "div#nothiddendiv", function() {
|
||||
livea++;
|
||||
} );
|
||||
jQuery( "#body" ).on( "click", "div#nothiddendivchild", function() {
|
||||
liveb++;
|
||||
} );
|
||||
|
||||
// Nothing should trigger on the body
|
||||
jQuery( "body" ).trigger( "click" );
|
||||
@ -1569,7 +1601,9 @@ QUnit.test( ".on()/.off()", function( assert ) {
|
||||
|
||||
// Make sure that stopPropagation doesn't stop live events
|
||||
submit = 0; div = 0; livea = 0; liveb = 0;
|
||||
jQuery( "#body" ).on( "click", "div#nothiddendivchild", function( e ) { liveb++; e.stopPropagation(); } );
|
||||
jQuery( "#body" ).on( "click", "div#nothiddendivchild", function( e ) {
|
||||
liveb++; e.stopPropagation();
|
||||
} );
|
||||
jQuery( "div#nothiddendivchild" ).trigger( "click" );
|
||||
assert.equal( submit, 0, "stopPropagation Click on inner div" );
|
||||
assert.equal( div, 1, "stopPropagation Click on inner div" );
|
||||
@ -1591,7 +1625,9 @@ QUnit.test( ".on()/.off()", function( assert ) {
|
||||
|
||||
// Test binding with a different context
|
||||
clicked = 0;
|
||||
jQuery( "#qunit-fixture" ).on( "click", "#foo", function() { clicked++; } );
|
||||
jQuery( "#qunit-fixture" ).on( "click", "#foo", function() {
|
||||
clicked++;
|
||||
} );
|
||||
jQuery( "#qunit-fixture div" ).trigger( "click" );
|
||||
jQuery( "#foo" ).trigger( "click" );
|
||||
jQuery( "#qunit-fixture" ).trigger( "click" );
|
||||
@ -1635,14 +1671,18 @@ QUnit.test( ".on()/.off()", function( assert ) {
|
||||
jQuery( "#body" ).off( "click", "#foo" );
|
||||
|
||||
// Verify that return false prevents default action
|
||||
jQuery( "#body" ).on( "click", "#anchor2", function() { return false; } );
|
||||
jQuery( "#body" ).on( "click", "#anchor2", function() {
|
||||
return false;
|
||||
} );
|
||||
hash = window.location.hash;
|
||||
jQuery( "#anchor2" ).trigger( "click" );
|
||||
assert.equal( window.location.hash, hash, "return false worked" );
|
||||
jQuery( "#body" ).off( "click", "#anchor2" );
|
||||
|
||||
// Verify that .preventDefault() prevents default action
|
||||
jQuery( "#body" ).on( "click", "#anchor2", function( e ) { e.preventDefault(); } );
|
||||
jQuery( "#body" ).on( "click", "#anchor2", function( e ) {
|
||||
e.preventDefault();
|
||||
} );
|
||||
hash = window.location.hash;
|
||||
jQuery( "#anchor2" ).trigger( "click" );
|
||||
assert.equal( window.location.hash, hash, "e.preventDefault() worked" );
|
||||
@ -1650,7 +1690,9 @@ QUnit.test( ".on()/.off()", function( assert ) {
|
||||
|
||||
// Test binding the same handler to multiple points
|
||||
called = 0;
|
||||
function callback() { called++; return false; }
|
||||
function callback() {
|
||||
called++; return false;
|
||||
}
|
||||
|
||||
jQuery( "#body" ).on( "click", "#nothiddendiv", callback );
|
||||
jQuery( "#body" ).on( "click", "#anchor2", callback );
|
||||
@ -1696,8 +1738,14 @@ QUnit.test( ".on()/.off()", function( assert ) {
|
||||
livec = 0;
|
||||
jQuery( "#nothiddendivchild" ).html( "<span></span>" );
|
||||
|
||||
jQuery( "#body" ).on( "click", "#nothiddendivchild", function() { jQuery( "#nothiddendivchild" ).html( "" ); } );
|
||||
jQuery( "#body" ).on( "click", "#nothiddendivchild", function( e ) { if ( e.target ) {livec++;} } );
|
||||
jQuery( "#body" ).on( "click", "#nothiddendivchild", function() {
|
||||
jQuery( "#nothiddendivchild" ).html( "" );
|
||||
} );
|
||||
jQuery( "#body" ).on( "click", "#nothiddendivchild", function( e ) {
|
||||
if ( e.target ) {
|
||||
livec++;
|
||||
}
|
||||
} );
|
||||
|
||||
jQuery( "#nothiddendiv span" ).trigger( "click" );
|
||||
assert.equal( jQuery( "#nothiddendiv span" ).length, 0, "Verify that first handler occurred and modified the DOM." );
|
||||
@ -1712,16 +1760,24 @@ QUnit.test( ".on()/.off()", function( assert ) {
|
||||
livee = 0;
|
||||
|
||||
// bind one pair in one order
|
||||
jQuery( "#body" ).on( "click", "span#liveSpan1 a", function() { lived++; return false; } );
|
||||
jQuery( "#body" ).on( "click", "span#liveSpan1", function() { livee++; } );
|
||||
jQuery( "#body" ).on( "click", "span#liveSpan1 a", function() {
|
||||
lived++; return false;
|
||||
} );
|
||||
jQuery( "#body" ).on( "click", "span#liveSpan1", function() {
|
||||
livee++;
|
||||
} );
|
||||
|
||||
jQuery( "span#liveSpan1 a" ).trigger( "click" );
|
||||
assert.equal( lived, 1, "Verify that only one first handler occurred." );
|
||||
assert.equal( livee, 0, "Verify that second handler doesn't." );
|
||||
|
||||
// and one pair in inverse
|
||||
jQuery( "#body" ).on( "click", "span#liveSpan2", function() { livee++; } );
|
||||
jQuery( "#body" ).on( "click", "span#liveSpan2 a", function() { lived++; return false; } );
|
||||
jQuery( "#body" ).on( "click", "span#liveSpan2", function() {
|
||||
livee++;
|
||||
} );
|
||||
jQuery( "#body" ).on( "click", "span#liveSpan2 a", function() {
|
||||
lived++; return false;
|
||||
} );
|
||||
|
||||
lived = 0;
|
||||
livee = 0;
|
||||
@ -1747,11 +1803,17 @@ QUnit.test( ".on()/.off()", function( assert ) {
|
||||
// Work with deep selectors
|
||||
livee = 0;
|
||||
|
||||
function clickB() { livee++; }
|
||||
function clickB() {
|
||||
livee++;
|
||||
}
|
||||
|
||||
jQuery( "#body" ).on( "click", "#nothiddendiv div", function() { livee++; } );
|
||||
jQuery( "#body" ).on( "click", "#nothiddendiv div", function() {
|
||||
livee++;
|
||||
} );
|
||||
jQuery( "#body" ).on( "click", "#nothiddendiv div", clickB );
|
||||
jQuery( "#body" ).on( "mouseover", "#nothiddendiv div", function() { livee++; } );
|
||||
jQuery( "#body" ).on( "mouseover", "#nothiddendiv div", function() {
|
||||
livee++;
|
||||
} );
|
||||
|
||||
assert.equal( livee, 0, "No clicks, deep selector." );
|
||||
|
||||
@ -1825,6 +1887,7 @@ QUnit.test( "events with type matching an Object.prototype property, cloned elem
|
||||
elem.appendTo( "#qunit-fixture" );
|
||||
|
||||
try {
|
||||
|
||||
// Make sure the original element has some event data.
|
||||
elem.on( "click", function() {} );
|
||||
|
||||
@ -1859,6 +1922,7 @@ QUnit[ QUnit.jQuerySelectors ? "test" : "skip" ]( "delegated event with delegate
|
||||
.off( "click" );
|
||||
|
||||
if ( QUnit.jQuerySelectorsPos ) {
|
||||
|
||||
// Positional selector (trac-11315)
|
||||
markup.find( "ul" ).eq( 0 )
|
||||
.on( "click", ">li>a", function() {
|
||||
@ -1954,8 +2018,12 @@ QUnit.test( "off all bound delegated events", function( assert ) {
|
||||
clicks = 0,
|
||||
div = jQuery( "#body" );
|
||||
|
||||
div.on( "click submit", "div#nothiddendivchild", function() { count++; } );
|
||||
div.on( "click", function() { clicks++; } );
|
||||
div.on( "click submit", "div#nothiddendivchild", function() {
|
||||
count++;
|
||||
} );
|
||||
div.on( "click", function() {
|
||||
clicks++;
|
||||
} );
|
||||
div.off( undefined, "**" );
|
||||
|
||||
jQuery( "div#nothiddendivchild" ).trigger( "click" );
|
||||
@ -1974,7 +2042,9 @@ QUnit.test( "on with multiple delegated events", function( assert ) {
|
||||
var count = 0,
|
||||
div = jQuery( "#body" );
|
||||
|
||||
div.on( "click submit", "div#nothiddendivchild", function() { count++; } );
|
||||
div.on( "click submit", "div#nothiddendivchild", function() {
|
||||
count++;
|
||||
} );
|
||||
|
||||
jQuery( "div#nothiddendivchild" ).trigger( "click" );
|
||||
jQuery( "div#nothiddendivchild" ).trigger( "submit" );
|
||||
@ -2329,7 +2399,7 @@ QUnit.test( ".on and .off", function( assert ) {
|
||||
|
||||
// We should have removed all the event handlers ... kinda hacky way to check this
|
||||
data = jQuery.data[ jQuery( "#onandoff" )[ 0 ].expando ] || {};
|
||||
assert.equal( data[ "events" ], undefined, "no events left" );
|
||||
assert.equal( data.events, undefined, "no events left" );
|
||||
|
||||
$onandoff.remove();
|
||||
} );
|
||||
@ -2403,7 +2473,7 @@ QUnit.test( "special on name mapping", function( assert ) {
|
||||
.trigger( "gutfeeling" ) // This one should not
|
||||
.remove();
|
||||
|
||||
delete jQuery.event.special[ "gutfeeling" ];
|
||||
delete jQuery.event.special.gutfeeling;
|
||||
} );
|
||||
|
||||
QUnit.test( ".on and .off, selective mixed removal (trac-10705)", function( assert ) {
|
||||
@ -2544,7 +2614,9 @@ QUnit.test( "addProp extensions", function( assert ) {
|
||||
fireNative( $fixture[ 0 ], "click" );
|
||||
$fixture.off( "click" );
|
||||
|
||||
jQuery.event.addProp( "testProperty", function() { return 42; } );
|
||||
jQuery.event.addProp( "testProperty", function() {
|
||||
return 42;
|
||||
} );
|
||||
|
||||
// Trigger a native click and ensure the property is set
|
||||
$fixture.on( "click", function( event ) {
|
||||
@ -3362,6 +3434,7 @@ QUnit.test( "focus change during a focus handler (gh-4382)", function( assert )
|
||||
} );
|
||||
|
||||
jQuery( document ).on( "focusin.focusTests", function( ev ) {
|
||||
|
||||
// Support: IE 11+
|
||||
// In IE focus is async so focusin on document is fired multiple times,
|
||||
// for each of the elements. In other browsers it's fired just once, for
|
||||
|
@ -518,6 +518,7 @@ QUnit.test( "Tag name processing respects the HTML Standard (gh-2005)", function
|
||||
}
|
||||
|
||||
function assertSpecialCharsSupport( method, characters ) {
|
||||
|
||||
// Support: Android 4.4 only
|
||||
// Chromium < 35 incorrectly upper-cases µ; Android 4.4 uses such a version by default
|
||||
// (and its WebView, being un-updatable, will use it for eternity) so we need to blacklist
|
||||
@ -1364,9 +1365,13 @@ QUnit.test( "Empty replaceWith (trac-13401; trac-13596; gh-2204)", function( ass
|
||||
jQuery.each( tests, function( label, input ) {
|
||||
$el.html( "<a></a>" ).children().replaceWith( input );
|
||||
assert.strictEqual( $el.html(), "", "replaceWith(" + label + ")" );
|
||||
$el.html( "<b></b>" ).children().replaceWith( function() { return input; } );
|
||||
$el.html( "<b></b>" ).children().replaceWith( function() {
|
||||
return input;
|
||||
} );
|
||||
assert.strictEqual( $el.html(), "", "replaceWith(function returning " + label + ")" );
|
||||
$el.html( "<i></i>" ).children().replaceWith( function( i ) { return input; } );
|
||||
$el.html( "<i></i>" ).children().replaceWith( function( i ) {
|
||||
return input;
|
||||
} );
|
||||
assert.strictEqual( $el.html(), "", "replaceWith(other function returning " + label + ")" );
|
||||
$el.html( "<p></p>" ).children().replaceWith( function( i ) {
|
||||
return i ?
|
||||
@ -1606,7 +1611,9 @@ QUnit.test( "clone(form element) (Bug trac-3879, trac-6655)", function( assert )
|
||||
|
||||
element = jQuery( "<select><option>Foo</option><option value='selected' selected>Bar</option></select>" );
|
||||
|
||||
assert.equal( element.clone().find( "option" ).filter( function() { return this.selected; } ).val(), "selected", "Selected option cloned correctly" );
|
||||
assert.equal( element.clone().find( "option" ).filter( function() {
|
||||
return this.selected;
|
||||
} ).val(), "selected", "Selected option cloned correctly" );
|
||||
|
||||
element = jQuery( "<input type='checkbox' value='foo'>" ).attr( "checked", "checked" );
|
||||
clone = element.clone();
|
||||
@ -1805,6 +1812,7 @@ QUnit.test( "html(Function)", function( assert ) {
|
||||
} );
|
||||
|
||||
QUnit[
|
||||
|
||||
// Support: Edge 16-18+
|
||||
// Edge sometimes doesn't execute module scripts so skip the test there.
|
||||
( QUnit.moduleTypeSupported && !/edge\//i.test( navigator.userAgent ) ) ?
|
||||
@ -1833,6 +1841,7 @@ QUnit[
|
||||
} );
|
||||
|
||||
QUnit[
|
||||
|
||||
// Support: IE 9-11 only, Android 4.0-4.4 only, iOS 7-10 only
|
||||
// `nomodule` scripts should be executed by legacy browsers only.
|
||||
// iOS 10 supports `<script type="module">` but doesn't support the nomodule attribute
|
||||
@ -2266,8 +2275,7 @@ QUnit.test( "domManip plain-text caching (trac-6779)", function( assert ) {
|
||||
for ( i = 0; i < bad.length; i++ ) {
|
||||
try {
|
||||
$f.append( bad[ i ] );
|
||||
}
|
||||
catch ( e ) {}
|
||||
} catch ( e ) {}
|
||||
}
|
||||
assert.equal( $f.text(), bad.join( "" ), "Cached strings that match Object properties" );
|
||||
$f.remove();
|
||||
|
@ -622,6 +622,7 @@ QUnit.test( "chaining", function( assert ) {
|
||||
// parent is not offsetParent); offset includes parent offset+border+padding
|
||||
// static: same as relative
|
||||
for ( ; parent; parent = expectations[ parent.parent ] ) {
|
||||
|
||||
// position:fixed
|
||||
if ( props.style === "fixed" ) {
|
||||
break;
|
||||
|
@ -88,7 +88,9 @@ QUnit.test( "queue() passes in the next item in the queue as a parameter to fx q
|
||||
|
||||
div.queue( function( next ) {
|
||||
assert.equal( ++counter, 1, "Dequeueing" );
|
||||
setTimeout( function() { next(); }, 500 );
|
||||
setTimeout( function() {
|
||||
next();
|
||||
}, 500 );
|
||||
} ).queue( function( next ) {
|
||||
assert.equal( ++counter, 2, "Next was called" );
|
||||
next();
|
||||
@ -187,7 +189,9 @@ QUnit.test( "clearQueue() clears the fx queue", function( assert ) {
|
||||
div.queue( function( next ) {
|
||||
counter++;
|
||||
var self = this;
|
||||
setTimeout( function() { jQuery( self ).clearQueue(); next(); }, 50 );
|
||||
setTimeout( function() {
|
||||
jQuery( self ).clearQueue(); next();
|
||||
}, 50 );
|
||||
} ).queue( function() {
|
||||
counter++;
|
||||
} );
|
||||
|
@ -41,8 +41,8 @@ QUnit.test( "empty", function( assert ) {
|
||||
QUnit.test( "star", function( assert ) {
|
||||
assert.expect( 2 );
|
||||
|
||||
var good, i;
|
||||
var all = jQuery.find( "*" );
|
||||
var good, i,
|
||||
all = jQuery.find( "*" );
|
||||
|
||||
assert.ok( all.length >= 30, "Select all" );
|
||||
good = true;
|
||||
@ -57,8 +57,8 @@ QUnit.test( "star", function( assert ) {
|
||||
QUnit.test( "element", function( assert ) {
|
||||
assert.expect( 37 );
|
||||
|
||||
var i, lengthtest, siblingTest, html;
|
||||
var fixture = document.getElementById( "qunit-fixture" );
|
||||
var i, lengthtest, siblingTest, html,
|
||||
fixture = document.getElementById( "qunit-fixture" );
|
||||
|
||||
assert.deepEqual( jQuery( "p", fixture ).get(), q( "firstp", "ap", "sndp", "en", "sap", "first" ), "Finding elements with a Node context." );
|
||||
assert.deepEqual( jQuery( "p", "#qunit-fixture" ).get(), q( "firstp", "ap", "sndp", "en", "sap", "first" ), "Finding elements with a selector context." );
|
||||
@ -892,6 +892,7 @@ QUnit.test( "pseudo - nth-child", function( assert ) {
|
||||
"Seeded nth-child"
|
||||
);
|
||||
} else {
|
||||
|
||||
// Support: Chrome 75+, Firefox 67+
|
||||
// Some browsers mark disconnected elements as matching `:nth-child(n)`
|
||||
// so let's skip the test.
|
||||
@ -948,6 +949,7 @@ QUnit.test( "pseudo - nth-last-child", function( assert ) {
|
||||
"Seeded nth-last-child"
|
||||
);
|
||||
} else {
|
||||
|
||||
// Support: Chrome 75+, Firefox 67+
|
||||
// Some browsers mark disconnected elements as matching `:nth-last-child(n)`
|
||||
// so let's skip the test.
|
||||
@ -1084,6 +1086,7 @@ QUnit.test( "pseudo - misc", function( assert ) {
|
||||
tmp = document.createElement( "div" );
|
||||
tmp.id = "tmp_input";
|
||||
tmp.innerHTML = "<span>Hello I am focusable.</span>";
|
||||
|
||||
// Setting tabIndex should make the element focusable
|
||||
// http://dev.w3.org/html5/spec/single-page.html#focus-management
|
||||
document.body.appendChild( tmp );
|
||||
@ -1140,6 +1143,7 @@ QUnit.test( "pseudo - misc", function( assert ) {
|
||||
);
|
||||
|
||||
if ( QUnit.jQuerySelectors ) {
|
||||
|
||||
// Tokenization edge cases
|
||||
assert.t( "Sequential pseudos", "#qunit-fixture p:has(:contains(mark)):has(code)", [ "ap" ] );
|
||||
assert.t( "Sequential pseudos", "#qunit-fixture p:has(:contains(mark)):has(code):contains(This link)", [ "ap" ] );
|
||||
@ -1205,6 +1209,7 @@ QUnit.test( "pseudo - :not", function( assert ) {
|
||||
assert.t( ":not() failing interior", "#qunit-fixture p:not(div#blargh)", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
|
||||
assert.t( ":not() failing interior", "#qunit-fixture p:not(p#blargh)", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
|
||||
} else {
|
||||
|
||||
// Support: Chrome 75+, Firefox 67+
|
||||
// Chrome/Firefox don't support `:not(complex selector)`.
|
||||
assert.ok( "skip", ":not(complex selector) not supported in selector-native" );
|
||||
@ -1225,6 +1230,7 @@ QUnit.test( "pseudo - :not", function( assert ) {
|
||||
assert.t( ":not Multiple", "p:not(p,a)", [] );
|
||||
assert.t( ":not Multiple", "p:not(a,p,b)", [] );
|
||||
} else {
|
||||
|
||||
// Support: Chrome 75+, Firefox 67+
|
||||
// Chrome/Firefox don't support `:not(complex selector)`.
|
||||
assert.ok( "skip", ":not(complex selector) not supported in selector-native" );
|
||||
@ -1254,6 +1260,7 @@ QUnit.test( "pseudo - :not", function( assert ) {
|
||||
if ( QUnit.jQuerySelectors || this.safari ) {
|
||||
assert.t( ":not() Multiple Class", "#foo a:not(.blog.link)", [ "yahoo", "anchor2" ] );
|
||||
} else {
|
||||
|
||||
// Support: Chrome 75+, Firefox 67+
|
||||
// Chrome/Firefox don't support `:not(complex selector)`.
|
||||
assert.ok( "skip", ":not(complex selector) not supported in selector-native" );
|
||||
@ -1830,8 +1837,8 @@ QUnit[
|
||||
"Shadow DOM nodes supported as root", function( assert ) {
|
||||
assert.expect( 2 );
|
||||
|
||||
var shadowHost = jQuery( "<div/>" ).appendTo( "#qunit-fixture" )[ 0 ];
|
||||
var shadowRoot = shadowHost.attachShadow( { mode: "open" } );
|
||||
var shadowHost = jQuery( "<div/>" ).appendTo( "#qunit-fixture" )[ 0 ],
|
||||
shadowRoot = shadowHost.attachShadow( { mode: "open" } );
|
||||
|
||||
shadowRoot.innerHTML = "<div class='vagabond'><p></p></div>";
|
||||
assert.equal( jQuery( shadowRoot ).find( ".vagabond" ).length, 1,
|
||||
@ -1843,7 +1850,7 @@ QUnit[
|
||||
testIframe(
|
||||
"attributes - jQuery.attr",
|
||||
"selector/html5_selector.html",
|
||||
function( assert, jQuery, window, document ) {
|
||||
function( assert, jQuery, _window, document ) {
|
||||
assert.expect( 38 );
|
||||
|
||||
/**
|
||||
@ -1916,7 +1923,7 @@ testIframe(
|
||||
|
||||
// Enumerated attributes (these are not boolean content attributes)
|
||||
jQuery.expandedEach = jQuery.each;
|
||||
jQuery.expandedEach( [ "draggable", "contenteditable", "aria-disabled" ], function( i, val ) {
|
||||
jQuery.expandedEach( [ "draggable", "contenteditable", "aria-disabled" ], function( _i, val ) {
|
||||
t( "Enumerated attribute", "[" + val + "]", [ "div1" ] );
|
||||
} );
|
||||
t( "Enumerated attribute", "[spellcheck]", [ "span1" ] );
|
||||
@ -2123,7 +2130,7 @@ QUnit.test( "uniqueSort()", function( assert ) {
|
||||
testIframe(
|
||||
"jQuery.uniqueSort works cross-window (trac-14381)",
|
||||
"selector/mixed_sort.html",
|
||||
function( assert, jQuery, window, document, actual, expected ) {
|
||||
function( assert, _jQuery, _window, _document, actual, expected ) {
|
||||
assert.expect( 1 );
|
||||
|
||||
assert.deepEqual( actual, expected, "Mixed array was sorted correctly" );
|
||||
@ -2292,10 +2299,12 @@ function testAttr( doc, assert ) {
|
||||
|
||||
var el;
|
||||
if ( doc ) {
|
||||
|
||||
// XML
|
||||
el = doc.createElement( "input" );
|
||||
el.setAttribute( "type", "checkbox" );
|
||||
} else {
|
||||
|
||||
// Set checked on creation by creating with a fragment
|
||||
// See https://jsfiddle.net/8sVgA/1/show/light in oldIE
|
||||
el = jQuery( "<input type='checkbox' checked='checked' />" )[ 0 ];
|
||||
@ -2423,6 +2432,7 @@ QUnit[ QUnit.jQuerySelectors ? "test" : "skip" ]( "backwards-compatible custom p
|
||||
var count = argument == null || argument === "" ? 3 : +argument;
|
||||
return elements.slice( 0, count );
|
||||
};
|
||||
|
||||
// Using TAG as the first token here forces this setMatcher into a fail state
|
||||
// Where the descendent combinator was lost
|
||||
assert.t( "Custom setFilter", "form#form :PODIUM", [ "label-for", "text1", "text2" ] );
|
||||
@ -2550,7 +2560,7 @@ QUnit[ QUnit.jQuerySelectors ? "test" : "skip" ]( "jQuery.find.select with pre-c
|
||||
"#qunit-fixture #first",
|
||||
"ol#listWithTabIndex > li[tabindex]",
|
||||
"#liveSpan1"
|
||||
], function( i, selector ) {
|
||||
], function( _i, selector ) {
|
||||
var compiled = jQuery.find.compile( selector );
|
||||
assert.equal( jQuery.find.select( compiled, document ).length,
|
||||
1, "Should match using a compiled selector function" );
|
||||
|
@ -5,10 +5,10 @@ QUnit.test( "jQuery.param()", function( assert ) {
|
||||
|
||||
var params;
|
||||
|
||||
params = { "foo":"bar", "baz":42, "quux":"All your base are belong to us" };
|
||||
params = { "foo": "bar", "baz": 42, "quux": "All your base are belong to us" };
|
||||
assert.equal( jQuery.param( params ), "foo=bar&baz=42&quux=All%20your%20base%20are%20belong%20to%20us", "simple" );
|
||||
|
||||
params = { "string":"foo", "null":null, "undefined":undefined };
|
||||
params = { "string": "foo", "null": null, "undefined": undefined };
|
||||
assert.equal( jQuery.param( params ), "string=foo&null=&undefined=", "handle nulls and undefineds properly" );
|
||||
|
||||
params = { "someName": [ 1, 2, 3 ], "regularThing": "blah" };
|
||||
@ -23,13 +23,13 @@ QUnit.test( "jQuery.param()", function( assert ) {
|
||||
params = { "foo": { "bar": "baz", "beep": 42, "quux": "All your base are belong to us" } };
|
||||
assert.equal( jQuery.param( params ), "foo%5Bbar%5D=baz&foo%5Bbeep%5D=42&foo%5Bquux%5D=All%20your%20base%20are%20belong%20to%20us", "even more arrays" );
|
||||
|
||||
params = { a:[ 1, 2 ], b:{ c:3, d:[ 4, 5 ], e:{ x:[ 6 ], y:7, z:[ 8, 9 ] }, f:true, g:false, h:undefined }, i:[ 10, 11 ], j:true, k:false, l:[ undefined, 0 ], m:"cowboy hat?" };
|
||||
params = { a: [ 1, 2 ], b: { c: 3, d: [ 4, 5 ], e: { x: [ 6 ], y: 7, z: [ 8, 9 ] }, f: true, g: false, h: undefined }, i: [ 10, 11 ], j: true, k: false, l: [ undefined, 0 ], m: "cowboy hat?" };
|
||||
assert.equal( decodeURIComponent( jQuery.param( params ) ), "a[]=1&a[]=2&b[c]=3&b[d][]=4&b[d][]=5&b[e][x][]=6&b[e][y]=7&b[e][z][]=8&b[e][z][]=9&b[f]=true&b[g]=false&b[h]=&i[]=10&i[]=11&j=true&k=false&l[]=&l[]=0&m=cowboy hat?", "huge structure" );
|
||||
|
||||
params = { "a": [ 0, [ 1, 2 ], [ 3, [ 4, 5 ], [ 6 ] ], { "b": [ 7, [ 8, 9 ], [ { "c": 10, "d": 11 } ], [ [ 12 ] ], [ [ [ 13 ] ] ], { "e": { "f": { "g": [ 14, [ 15 ] ] } } }, 16 ] }, 17 ] };
|
||||
assert.equal( decodeURIComponent( jQuery.param( params ) ), "a[]=0&a[1][]=1&a[1][]=2&a[2][]=3&a[2][1][]=4&a[2][1][]=5&a[2][2][]=6&a[3][b][]=7&a[3][b][1][]=8&a[3][b][1][]=9&a[3][b][2][0][c]=10&a[3][b][2][0][d]=11&a[3][b][3][0][]=12&a[3][b][4][0][0][]=13&a[3][b][5][e][f][g][]=14&a[3][b][5][e][f][g][1][]=15&a[3][b][]=16&a[]=17", "nested arrays" );
|
||||
|
||||
params = { "a":[ 1, 2 ], "b":{ "c":3, "d":[ 4, 5 ], "e":{ "x":[ 6 ], "y":7, "z":[ 8, 9 ] }, "f":true, "g":false, "h":undefined }, "i":[ 10, 11 ], "j":true, "k":false, "l":[ undefined, 0 ], "m":"cowboy hat?" };
|
||||
params = { "a": [ 1, 2 ], "b": { "c": 3, "d": [ 4, 5 ], "e": { "x": [ 6 ], "y": 7, "z": [ 8, 9 ] }, "f": true, "g": false, "h": undefined }, "i": [ 10, 11 ], "j": true, "k": false, "l": [ undefined, 0 ], "m": "cowboy hat?" };
|
||||
assert.equal( jQuery.param( params, true ), "a=1&a=2&b=%5Bobject%20Object%5D&i=10&i=11&j=true&k=false&l=&l=0&m=cowboy%20hat%3F", "huge structure, forced traditional" );
|
||||
|
||||
assert.equal( decodeURIComponent( jQuery.param( { "a": [ 1, 2, 3 ], "b[]": [ 4, 5, 6 ], "c[d]": [ 7, 8, 9 ], "e": { "f": [ 10 ], "g": [ 11, 12 ], "h": 13 } } ) ), "a[]=1&a[]=2&a[]=3&b[]=4&b[]=5&b[]=6&c[d][]=7&c[d][]=8&c[d][]=9&e[f][]=10&e[g][]=11&e[g][]=12&e[h]=13", "Make sure params are not double-encoded." );
|
||||
@ -37,7 +37,7 @@ QUnit.test( "jQuery.param()", function( assert ) {
|
||||
// trac-7945
|
||||
assert.equal( jQuery.param( { "jquery": "1.4.2" } ), "jquery=1.4.2", "Check that object with a jQuery property get serialized correctly" );
|
||||
|
||||
params = { "foo":"bar", "baz":42, "quux":"All your base are belong to us" };
|
||||
params = { "foo": "bar", "baz": 42, "quux": "All your base are belong to us" };
|
||||
assert.equal( jQuery.param( params, true ), "foo=bar&baz=42&quux=All%20your%20base%20are%20belong%20to%20us", "simple" );
|
||||
|
||||
params = { "someName": [ 1, 2, 3 ], "regularThing": "blah" };
|
||||
@ -46,25 +46,27 @@ QUnit.test( "jQuery.param()", function( assert ) {
|
||||
params = { "foo": [ "a", "b", "c" ] };
|
||||
assert.equal( jQuery.param( params, true ), "foo=a&foo=b&foo=c", "with array of strings" );
|
||||
|
||||
params = { "foo[]":[ "baz", 42, "All your base are belong to us" ] };
|
||||
params = { "foo[]": [ "baz", 42, "All your base are belong to us" ] };
|
||||
assert.equal( jQuery.param( params, true ), "foo%5B%5D=baz&foo%5B%5D=42&foo%5B%5D=All%20your%20base%20are%20belong%20to%20us", "more array" );
|
||||
|
||||
params = { "foo[bar]":"baz", "foo[beep]":42, "foo[quux]":"All your base are belong to us" };
|
||||
params = { "foo[bar]": "baz", "foo[beep]": 42, "foo[quux]": "All your base are belong to us" };
|
||||
assert.equal( jQuery.param( params, true ), "foo%5Bbar%5D=baz&foo%5Bbeep%5D=42&foo%5Bquux%5D=All%20your%20base%20are%20belong%20to%20us", "even more arrays" );
|
||||
|
||||
params = { a:[ 1, 2 ], b:{ c:3, d:[ 4, 5 ], e:{ x:[ 6 ], y:7, z:[ 8, 9 ] }, f:true, g:false, h:undefined }, i:[ 10, 11 ], j:true, k:false, l:[ undefined, 0 ], m:"cowboy hat?" };
|
||||
params = { a: [ 1, 2 ], b: { c: 3, d: [ 4, 5 ], e: { x: [ 6 ], y: 7, z: [ 8, 9 ] }, f: true, g: false, h: undefined }, i: [ 10, 11 ], j: true, k: false, l: [ undefined, 0 ], m: "cowboy hat?" };
|
||||
assert.equal( jQuery.param( params, true ), "a=1&a=2&b=%5Bobject%20Object%5D&i=10&i=11&j=true&k=false&l=&l=0&m=cowboy%20hat%3F", "huge structure" );
|
||||
|
||||
params = { "a": [ 0, [ 1, 2 ], [ 3, [ 4, 5 ], [ 6 ] ], { "b": [ 7, [ 8, 9 ], [ { "c": 10, d: 11 } ], [ [ 12 ] ], [ [ [ 13 ] ] ], { "e": { "f": { "g": [ 14, [ 15 ] ] } } }, 16 ] }, 17 ] };
|
||||
assert.equal( jQuery.param( params, true ), "a=0&a=1%2C2&a=3%2C4%2C5%2C6&a=%5Bobject%20Object%5D&a=17", "nested arrays (not possible when traditional == true)" );
|
||||
|
||||
params = { a:[ 1, 2 ], b:{ c:3, d:[ 4, 5 ], e:{ x:[ 6 ], y:7, z:[ 8, 9 ] }, f:true, g:false, h:undefined }, i:[ 10, 11 ], j:true, k:false, l:[ undefined, 0 ], m:"cowboy hat?" };
|
||||
params = { a: [ 1, 2 ], b: { c: 3, d: [ 4, 5 ], e: { x: [ 6 ], y: 7, z: [ 8, 9 ] }, f: true, g: false, h: undefined }, i: [ 10, 11 ], j: true, k: false, l: [ undefined, 0 ], m: "cowboy hat?" };
|
||||
assert.equal( decodeURIComponent( jQuery.param( params ) ), "a[]=1&a[]=2&b[c]=3&b[d][]=4&b[d][]=5&b[e][x][]=6&b[e][y]=7&b[e][z][]=8&b[e][z][]=9&b[f]=true&b[g]=false&b[h]=&i[]=10&i[]=11&j=true&k=false&l[]=&l[]=0&m=cowboy hat?", "huge structure, forced not traditional" );
|
||||
|
||||
params = { "param1": null };
|
||||
assert.equal( jQuery.param( params ), "param1=", "Make sure that null params aren't traversed." );
|
||||
|
||||
params = { "param1": function() {}, "param2": function() { return null; } };
|
||||
params = { "param1": function() {}, "param2": function() {
|
||||
return null;
|
||||
} };
|
||||
assert.equal( jQuery.param( params, false ), "param1=¶m2=", "object with function property that returns null value" );
|
||||
|
||||
params = { "test": { "length": 3, "foo": "bar" } };
|
||||
|
@ -310,7 +310,9 @@ QUnit.test( "filter(Function)", function( assert ) {
|
||||
return !jQuery( "a", this ).length;
|
||||
} ).get(), q( "sndp", "first" ), "filter(Function)" );
|
||||
|
||||
assert.deepEqual( jQuery( "#qunit-fixture p" ).filter( function( i, elem ) { return !jQuery( "a", elem ).length; } ).get(), q( "sndp", "first" ), "filter(Function) using arg" );
|
||||
assert.deepEqual( jQuery( "#qunit-fixture p" ).filter( function( i, elem ) {
|
||||
return !jQuery( "a", elem ).length;
|
||||
} ).get(), q( "sndp", "first" ), "filter(Function) using arg" );
|
||||
} );
|
||||
|
||||
QUnit.test( "filter(Element)", function( assert ) {
|
||||
@ -505,7 +507,9 @@ QUnit.test( "not(Element)", function( assert ) {
|
||||
QUnit.test( "not(Function)", function( assert ) {
|
||||
assert.expect( 1 );
|
||||
|
||||
assert.deepEqual( jQuery( "#qunit-fixture p" ).not( function() { return jQuery( "a", this ).length; } ).get(), q( "sndp", "first" ), "not(Function)" );
|
||||
assert.deepEqual( jQuery( "#qunit-fixture p" ).not( function() {
|
||||
return jQuery( "a", this ).length;
|
||||
} ).get(), q( "sndp", "first" ), "not(Function)" );
|
||||
} );
|
||||
|
||||
QUnit.test( "not(Array)", function( assert ) {
|
||||
|
Loading…
Reference in New Issue
Block a user