Build: Only install Playwright dependencies when needed
[jquery.git] / Gruntfile.js
blobf24e8a4485a2e3a9c9ae14eed7a67c935390102e
1 "use strict";
3 module.exports = function( grunt ) {
4         function readOptionalJSON( filepath ) {
5                 const stripJSONComments = require( "strip-json-comments" );
6                 let data = {};
7                 try {
8                         data = JSON.parse( stripJSONComments(
9                                 fs.readFileSync( filepath, { encoding: "utf8" } )
10                         ) );
11                 } catch ( e ) {}
12                 return data;
13         }
15         const fs = require( "fs" );
16         const gzip = require( "gzip-js" );
17         const nodeV14OrNewer = !/^v1[0-3]\./.test( process.version );
18         const nodeV17OrNewer = !/^v1[0-6]\./.test( process.version );
19         const customBrowsers = process.env.BROWSERS && process.env.BROWSERS.split( "," );
21         // Support: Node.js <14
22         // Skip running tasks that dropped support for Node.js 10 or 12
23         // in this Node version.
24         function runIfNewNode( task ) {
25                 return nodeV14OrNewer ? task : "print_old_node_message:" + task;
26         }
28         if ( nodeV14OrNewer ) {
29                 const playwright = require( "playwright-webkit" );
30                 process.env.WEBKIT_HEADLESS_BIN = playwright.webkit.executablePath();
31         }
33         if ( !grunt.option( "filename" ) ) {
34                 grunt.option( "filename", "jquery.js" );
35         }
37         grunt.initConfig( {
38                 pkg: grunt.file.readJSON( "package.json" ),
39                 dst: readOptionalJSON( "dist/.destination.json" ),
40                 compare_size: {
41                         files: [ "dist/jquery.js", "dist/jquery.min.js" ],
42                         options: {
43                                 compress: {
44                                         gz: function( contents ) {
45                                                 return gzip.zip( contents, {} ).length;
46                                         }
47                                 },
48                                 cache: "build/.sizecache.json"
49                         }
50                 },
51                 babel: {
52                         options: {
53                                 sourceMap: "inline",
54                                 retainLines: true,
55                                 plugins: [ "@babel/transform-for-of" ]
56                         },
57                         tests: {
58                                 files: {
59                                         "test/data/core/jquery-iterability-transpiled.js":
60                                                 "test/data/core/jquery-iterability-transpiled-es6.js"
61                                 }
62                         }
63                 },
64                 build: {
65                         all: {
66                                 dest: "dist/jquery.js",
67                                 minimum: [
68                                         "core"
69                                 ],
71                                 // Exclude specified modules if the module matching the key is removed
72                                 removeWith: {
73                                         ajax: [ "manipulation/_evalUrl", "deprecated/ajax-event-alias" ],
74                                         callbacks: [ "deferred" ],
75                                         css: [ "effects", "dimensions", "offset" ],
76                                         "css/showHide": [ "effects" ],
77                                         deferred: {
78                                                 remove: [ "ajax", "effects", "queue", "core/ready" ],
79                                                 include: [ "core/ready-no-deferred" ]
80                                         },
81                                         event: [ "deprecated/ajax-event-alias", "deprecated/event" ],
82                                         selector: [ "css/hiddenVisibleSelectors", "effects/animatedSelector" ]
83                                 }
84                         }
85                 },
86                 npmcopy: {
87                         all: {
88                                 options: {
89                                         destPrefix: "external"
90                                 },
91                                 files: {
92                                         "core-js-bundle/core-js-bundle.js": "core-js-bundle/minified.js",
93                                         "core-js-bundle/LICENSE": "core-js-bundle/LICENSE",
95                                         "npo/npo.js": "native-promise-only/lib/npo.src.js",
97                                         "qunit/qunit.js": "qunit/qunit/qunit.js",
98                                         "qunit/qunit.css": "qunit/qunit/qunit.css",
99                                         "qunit/LICENSE.txt": "qunit/LICENSE.txt",
101                                         "requirejs/require.js": "requirejs/require.js",
103                                         "sinon/sinon.js": "sinon/pkg/sinon.js",
104                                         "sinon/LICENSE.txt": "sinon/LICENSE"
105                                 }
106                         }
107                 },
108                 jsonlint: {
109                         pkg: {
110                                 src: [ "package.json" ]
111                         }
112                 },
113                 eslint: {
114                         options: {
115                                 maxWarnings: 0
116                         },
118                         // We have to explicitly declare "src" property otherwise "newer"
119                         // task wouldn't work properly :/
120                         dist: {
121                                 src: [ "dist/jquery.js", "dist/jquery.min.js" ]
122                         },
123                         dev: {
124                                 src: [
125                                         "src/**/*.js",
126                                         "Gruntfile.js",
127                                         "test/**/*.js",
128                                         "build/**/*.js",
130                                         // Ignore files from .eslintignore
131                                         // See https://github.com/sindresorhus/grunt-eslint/issues/119
132                                         ...fs
133                                                 .readFileSync( `${ __dirname }/.eslintignore`, "utf-8" )
134                                                 .split( "\n" )
135                                                 .filter( filePath => filePath )
136                                                 .map( filePath => filePath[ 0 ] === "!" ?
137                                                         filePath.slice( 1 ) :
138                                                         `!${ filePath }`
139                                                 )
140                                 ]
141                         }
142                 },
143                 testswarm: {
144                         tests: [
146                                 // A special module with basic tests, meant for not fully
147                                 // supported environments like jsdom. We run it everywhere,
148                                 // though, to make sure tests are not broken.
149                                 "basic",
151                                 "ajax",
152                                 "animation",
153                                 "attributes",
154                                 "callbacks",
155                                 "core",
156                                 "css",
157                                 "data",
158                                 "deferred",
159                                 "deprecated",
160                                 "dimensions",
161                                 "effects",
162                                 "event",
163                                 "manipulation",
164                                 "offset",
165                                 "queue",
166                                 "selector",
167                                 "serialize",
168                                 "support",
169                                 "traversing",
170                                 "tween"
171                         ]
172                 },
173                 karma: {
174                         options: {
175                                 customContextFile: "test/karma.context.html",
176                                 customDebugFile: "test/karma.debug.html",
177                                 customLaunchers: {
178                                         ChromeHeadlessNoSandbox: {
179                                                 base: "ChromeHeadless",
180                                                 flags: [ "--no-sandbox" ]
181                                         }
182                                 },
183                                 frameworks: [ "qunit" ],
184                                 middleware: [ "mockserver" ],
185                                 plugins: [
186                                         "karma-*",
187                                         {
188                                                 "middleware:mockserver": [
189                                                         "factory",
190                                                         require( "./test/middleware-mockserver.js" )
191                                                 ]
192                                         }
193                                 ],
194                                 client: {
195                                         qunit: {
197                                                 // We're running `QUnit.start()` ourselves via `loadTests()`
198                                                 // in test/jquery.js
199                                                 autostart: false
200                                         }
201                                 },
202                                 files: [
203                                         "test/data/jquery-1.9.1.js",
204                                         "external/sinon/sinon.js",
205                                         "external/npo/npo.js",
206                                         "external/requirejs/require.js",
207                                         "test/data/testinit.js",
209                                         "test/jquery.js",
211                                         {
212                                                 pattern: "dist/jquery.*",
213                                                 included: false,
214                                                 served: true,
215                                                 nocache: true
216                                         },
217                                         {
218                                                 pattern: "src/**",
219                                                 type: "module",
220                                                 included: false,
221                                                 served: true,
222                                                 nocache: true
223                                         },
224                                         {
225                                                 pattern: "amd/**",
226                                                 included: false,
227                                                 served: true,
228                                                 nocache: true
229                                         },
230                                         { pattern: "external/**", included: false, served: true },
231                                         {
232                                                 pattern: "test/**/*.@(js|css|jpg|html|xml|svg)",
233                                                 included: false,
234                                                 served: true,
235                                                 nocache: true
236                                         }
237                                 ],
238                                 reporters: [ "dots" ],
239                                 autoWatch: false,
241                                 // 2 minutes; has to be longer than QUnit.config.testTimeout
242                                 browserNoActivityTimeout: 120e3,
244                                 concurrency: 3,
245                                 captureTimeout: 20 * 1000,
246                                 singleRun: true
247                         },
248                         main: {
249                                 browsers: customBrowsers ||
250                                         [ "ChromeHeadless", "FirefoxHeadless", "WebkitHeadless" ]
251                         },
252                         esmodules: {
253                                 browsers: customBrowsers || [ "ChromeHeadless" ],
254                                 options: {
255                                         client: {
256                                                 qunit: {
258                                                         // We're running `QUnit.start()` ourselves via `loadTests()`
259                                                         // in test/jquery.js
260                                                         autostart: false,
262                                                         esmodules: true
263                                                 }
264                                         }
265                                 }
266                         },
267                         amd: {
268                                 browsers: customBrowsers || [ "ChromeHeadless" ],
269                                 options: {
270                                         client: {
271                                                 qunit: {
273                                                         // We're running `QUnit.start()` ourselves via `loadTests()`
274                                                         // in test/jquery.js
275                                                         autostart: false,
277                                                         amd: true
278                                                 }
279                                         }
280                                 }
281                         },
283                         jsdom: {
284                                 options: {
285                                         files: [
286                                                 "test/data/jquery-1.9.1.js",
287                                                 "test/data/testinit-jsdom.js",
289                                                 // We don't support various loading methods like esmodules,
290                                                 // choosing a version etc. for jsdom.
291                                                 "dist/jquery.js",
293                                                 // A partial replacement for testinit.js#loadTests()
294                                                 "test/data/testrunner.js",
296                                                 // jsdom only runs basic tests
297                                                 "test/unit/basic.js",
299                                                 {
300                                                         pattern: "test/**/*.@(js|css|jpg|html|xml|svg)",
301                                                         included: false,
302                                                         served: true
303                                                 }
304                                         ]
305                                 },
306                                 browsers: [ "jsdom" ]
307                         },
309                         // To debug tests with Karma:
310                         // 1. Run 'grunt karma:chrome-debug' or 'grunt karma:firefox-debug'
311                         //    (any karma subtask that has singleRun=false)
312                         // 2. Press "Debug" in the opened browser window to start
313                         //    the tests. Unlike the other karma tasks, the debug task will
314                         //    keep the browser window open.
315                         "chrome-debug": {
316                                 browsers: [ "Chrome" ],
317                                 singleRun: false
318                         },
319                         "firefox-debug": {
320                                 browsers: [ "Firefox" ],
321                                 singleRun: false
322                         },
323                         "ie-debug": {
324                                 browsers: [ "IE" ],
325                                 singleRun: false
326                         }
327                 },
328                 watch: {
329                         files: [ "<%= eslint.dev.src %>" ],
330                         tasks: [ "dev" ]
331                 },
332                 uglify: {
333                         all: {
334                                 files: {
335                                         "dist/<%= grunt.option('filename').replace('.js', '.min.js') %>":
336                                                 "dist/<%= grunt.option('filename') %>"
337                                 },
338                                 options: {
339                                         preserveComments: false,
340                                         sourceMap: true,
341                                         sourceMapName:
342                                                 "dist/<%= grunt.option('filename').replace('.js', '.min.map') %>",
343                                         report: "min",
344                                         output: {
345                                                 "ascii_only": true
346                                         },
347                                         banner: "/*! jQuery v<%= pkg.version %> | " +
348                                                 "(c) OpenJS Foundation and other contributors | jquery.org/license */",
349                                         compress: {
350                                                 "hoist_funs": false,
351                                                 loops: false
352                                         }
353                                 }
354                         }
355                 }
356         } );
358         // Load grunt tasks from NPM packages
359         require( "load-grunt-tasks" )( grunt, {
360                 pattern: nodeV14OrNewer ? [ "grunt-*" ] : [ "grunt-*", "!grunt-eslint" ]
361         } );
363         // Integrate jQuery specific tasks
364         grunt.loadTasks( "build/tasks" );
366         grunt.registerTask( "print_old_node_message", ( ...args ) => {
367                 var task = args.join( ":" );
368                 grunt.log.writeln( "Old Node.js detected, running the task \"" + task + "\" skipped..." );
369         } );
371         grunt.registerTask( "print_jsdom_message", () => {
372                 grunt.log.writeln( "Node.js 17 or newer detected, skipping jsdom tests..." );
373         } );
375         grunt.registerTask( "lint", [
376                 "jsonlint",
378                 // Running the full eslint task without breaking it down to targets
379                 // would run the dist target first which would point to errors in the built
380                 // file, making it harder to fix them. We want to check the built file only
381                 // if we already know the source files pass the linter.
382                 runIfNewNode( "eslint:dev" ),
383                 runIfNewNode( "eslint:dist" )
384         ] );
386         grunt.registerTask( "lint:newer", [
387                 "newer:jsonlint",
389                 // Don't replace it with just the task; see the above comment.
390                 runIfNewNode( "newer:eslint:dev" ),
391                 runIfNewNode( "newer:eslint:dist" )
392         ] );
394         grunt.registerTask( "test:fast", runIfNewNode( "node_smoke_tests" ) );
395         grunt.registerTask( "test:slow", [
396                 runIfNewNode( "promises_aplus_tests" ),
398                 // Support: Node.js 17+
399                 // jsdom fails to connect to the Karma server in Node 17+.
400                 // Until we figure out a fix, skip jsdom tests there.
401                 nodeV17OrNewer ? "print_jsdom_message" : runIfNewNode( "karma:jsdom" )
402         ] );
404         grunt.registerTask( "test:prepare", [
405                 "npmcopy",
406                 "qunit_fixture",
407                 "babel:tests"
408         ] );
410         grunt.registerTask( "test", [
411                 "test:prepare",
412                 "test:fast",
413                 "test:slow"
414         ] );
416         grunt.registerTask( "dev", [
417                 "build:*:*",
418                 runIfNewNode( "newer:eslint:dev" ),
419                 "newer:uglify",
420                 "remove_map_comment",
421                 "dist:*",
422                 "qunit_fixture",
423                 "compare_size"
424         ] );
426         grunt.registerTask( "default", [
427                 runIfNewNode( "eslint:dev" ),
428                 "build:*:*",
429                 "amd",
430                 "uglify",
431                 "remove_map_comment",
432                 "dist:*",
433                 "test:prepare",
434                 runIfNewNode( "eslint:dist" ),
435                 "test:fast",
436                 "compare_size"
437         ] );