Update git submodules
[mediawiki.git] / Gruntfile.js
blob72eca79f1660196f6e1470fb413d4de37491811e
1 'use strict';
2 module.exports = function ( grunt ) {
3         grunt.loadNpmTasks( 'grunt-banana-checker' );
4         grunt.loadNpmTasks( 'grunt-contrib-copy' );
5         grunt.loadNpmTasks( 'grunt-eslint' );
6         grunt.loadNpmTasks( 'grunt-karma' );
7         grunt.loadNpmTasks( 'grunt-stylelint' );
9         const fs = require( 'fs' );
10         const path = require( 'path' );
11         const wgServer = process.env.MW_SERVER;
12         const wgScriptPath = process.env.MW_SCRIPT_PATH;
13         const karmaProxy = {};
15         let qunitPattern = wgServer + wgScriptPath + '/index.php?title=Special:JavaScriptTest/qunit/export';
17         // "MediaWiki" for core, or extension/skin name (e.g. "GrowthExperiments")
18         const qunitComponent = grunt.option( 'qunit-component' );
19         const qunitWatch = grunt.option( 'qunit-watch' ) || false;
20         const qunitWatchFiles = [];
21         if ( qunitComponent ) {
22                 let qunitWatchSourcePattern;
23                 let qunitWatchTestPattern;
24                 qunitPattern = qunitPattern + '&component=' + qunitComponent;
25                 if ( qunitWatch ) {
26                         // Special-case MediaWiki core.
27                         if ( qunitComponent === 'MediaWiki' ) {
28                                 qunitWatchTestPattern = 'tests/qunit/**/*.js';
29                                 qunitWatchSourcePattern = 'resources/**/*.js';
30                         } else {
31                                 let settingsJson,
32                                         basePath;
33                                 try {
34                                         basePath = 'extensions';
35                                         // eslint-disable-next-line security/detect-non-literal-fs-filename
36                                         settingsJson = fs.readFileSync(
37                                                 path.resolve( __dirname + '/' + basePath + '/' + qunitComponent + '/extension.json' )
38                                         );
39                                 } catch ( e ) {
40                                         basePath = 'skins';
41                                         // eslint-disable-next-line security/detect-non-literal-fs-filename
42                                         settingsJson = fs.readFileSync(
43                                                 path.resolve( __dirname + '/' + basePath + '/' + qunitComponent + '/skin.json' )
44                                         );
45                                 }
46                                 settingsJson = JSON.parse( settingsJson );
47                                 qunitWatchSourcePattern =
48                                         path.resolve( __dirname + '/' + basePath + '/' + qunitComponent + '/' + settingsJson.ResourceFileModulePaths.localBasePath + '/**/*.js' );
49                                 qunitWatchTestPattern = path.resolve( __dirname + '/' + basePath + '/' + qunitComponent + '/tests/qunit/**/*.js' );
50                         }
51                         qunitWatchFiles.push( {
52                                 pattern: qunitWatchSourcePattern,
53                                 type: 'js',
54                                 watched: true,
55                                 included: false,
56                                 served: false
57                         } );
58                         qunitWatchFiles.push( {
59                                 pattern: qunitWatchTestPattern,
60                                 type: 'js',
61                                 watched: true,
62                                 included: false,
63                                 served: false
64                         } );
65                 }
66         }
68         karmaProxy[ wgScriptPath ] = {
69                 target: wgServer + wgScriptPath,
70                 changeOrigin: true
71         };
73         grunt.initConfig( {
74                 eslint: {
75                         options: {
76                                 extensions: [ '.js', '.json', '.vue' ],
77                                 cache: true,
78                                 fix: grunt.option( 'fix' )
79                         },
80                         all: '.'
81                 },
82                 banana: {
83                         options: {
84                                 requireLowerCase: false,
85                                 disallowBlankTranslations: false
86                         },
87                         core: 'languages/i18n/',
88                         exif: 'languages/i18n/exif/',
89                         api: 'includes/api/i18n/',
90                         rest: 'includes/Rest/i18n/',
91                         installer: 'includes/installer/i18n/',
92                         paramvalidator: 'includes/libs/ParamValidator/i18n/'
93                 },
94                 stylelint: {
95                         options: {
96                                 reportNeedlessDisables: true
97                         },
98                         src: '{resources/src,mw-config}/**/*.{css,less,vue}'
99                 },
100                 watch: {
101                         files: [
102                                 '.{stylelintrc,eslintrc}.json',
103                                 '**/*',
104                                 '!{extensions,node_modules,skins,vendor}/**'
105                         ],
106                         tasks: 'test'
107                 },
108                 karma: {
109                         options: {
110                                 customLaunchers: {
111                                         ChromeCustom: {
112                                                 base: 'ChromeHeadless',
113                                                 // Chrome requires --no-sandbox in Docker/CI.
114                                                 // WMF CI images expose CHROMIUM_FLAGS which sets that.
115                                                 flags: process.env.CHROMIUM_FLAGS ? ( process.env.CHROMIUM_FLAGS || '' ).split( ' ' ) : []
116                                         }
117                                 },
118                                 proxies: karmaProxy,
119                                 files: [ {
120                                         pattern: qunitPattern,
121                                         type: 'js',
122                                         watched: false,
123                                         included: true,
124                                         served: false
125                                 }, ...qunitWatchFiles ],
126                                 logLevel: ( process.env.ZUUL_PROJECT ? 'DEBUG' : 'INFO' ),
127                                 frameworks: [ 'qunit' ],
128                                 reporters: [ 'mocha' ],
129                                 singleRun: !qunitWatch,
130                                 autoWatch: qunitWatch,
131                                 // Some tests in extensions don't yield for more than the default 10s (T89075)
132                                 browserNoActivityTimeout: 60 * 1000,
133                                 // Karma requires Same-Origin (or CORS) by default since v1.1.1
134                                 // for better stacktraces. But we load the first request from wgServer
135                                 crossOriginAttribute: false
136                         },
137                         main: {
138                                 browsers: [ 'ChromeCustom' ]
139                         },
140                         firefox: {
141                                 browsers: [ 'FirefoxHeadless' ]
142                         }
143                 },
144                 copy: {
145                         jsduck: {
146                                 src: 'resources/**/*',
147                                 dest: 'docs/js/modules',
148                                 expand: true,
149                                 rename: function ( dest, src ) {
150                                         return require( 'path' ).join( dest, src.replace( 'resources/', '' ) );
151                                 }
152                         }
153                 }
154         } );
156         grunt.registerTask( 'assert-mw-env', function () {
157                 let ok = true;
158                 if ( !process.env.MW_SERVER ) {
159                         grunt.log.error( 'Environment variable MW_SERVER must be set.\n' +
160                                 'Set this like $wgServer, e.g. "http://localhost"'
161                         );
162                         ok = false;
163                 }
164                 if ( !process.env.MW_SCRIPT_PATH ) {
165                         grunt.log.error( 'Environment variable MW_SCRIPT_PATH must be set.\n' +
166                                 'Set this like $wgScriptPath, e.g. "/w"' );
167                         ok = false;
168                 }
169                 return ok;
170         } );
172         grunt.registerTask( 'lint', [ 'eslint', 'banana', 'stylelint' ] );
173         grunt.registerTask( 'qunit', [ 'assert-mw-env', 'karma:main' ] );