diff --git a/lib/config.js b/lib/config.js index 1192afbac..4972587cd 100644 --- a/lib/config.js +++ b/lib/config.js @@ -411,34 +411,59 @@ function parseConfig (configFilePath, cliOptions, parseOptions) { // add the user's configuration in config.set(cliOptions) + let configModuleReturn try { - configModule(config) + configModuleReturn = configModule(config) } catch (e) { return fail('Error in config file!\n', e) } + function finalizeConfig (config) { + // merge the config from config file and cliOptions (precedence) + config.set(cliOptions) - // merge the config from config file and cliOptions (precedence) - config.set(cliOptions) - - // if the user changed listenAddress, but didn't set a hostname, warn them - if (config.hostname === null && config.listenAddress !== null) { - log.warn(`ListenAddress was set to ${config.listenAddress} but hostname was left as the default: ` + + // if the user changed listenAddress, but didn't set a hostname, warn them + if (config.hostname === null && config.listenAddress !== null) { + log.warn(`ListenAddress was set to ${config.listenAddress} but hostname was left as the default: ` + `${defaultHostname}. If your browsers fail to connect, consider changing the hostname option.`) - } - // restore values that weren't overwritten by the user - if (config.hostname === null) { - config.hostname = defaultHostname - } - if (config.listenAddress === null) { - config.listenAddress = defaultListenAddress - } + } + // restore values that weren't overwritten by the user + if (config.hostname === null) { + config.hostname = defaultHostname + } + if (config.listenAddress === null) { + config.listenAddress = defaultListenAddress + } - // configure the logger as soon as we can - logger.setup(config.logLevel, config.colors, config.loggers) + // configure the logger as soon as we can + logger.setup(config.logLevel, config.colors, config.loggers) - log.debug(configFilePath ? `Loading config ${configFilePath}` : 'No config file specified.') + log.debug(configFilePath ? `Loading config ${configFilePath}` : 'No config file specified.') - return normalizeConfig(config, configFilePath) + return normalizeConfig(config, configFilePath) + } + const returnIsThenable = configModuleReturn != null && typeof configModuleReturn === 'object' && typeof configModuleReturn.then === 'function' + const promiseConfig = parseOptions && parseOptions.promiseConfig === true + if (returnIsThenable) { + if (promiseConfig !== true) { + const errorMessage = + 'The `parseOptions.promiseConfig` option must be set to `true` to ' + + 'enable promise return values from configuration files.' + return fail(errorMessage) + } + return configModuleReturn.then(function onKarmaConfigModuleFulfilled (/* ignoredResolutionValue */) { + return finalizeConfig(config) + }) + } else { + if (promiseConfig) { + try { + return Promise.resolve(finalizeConfig(config)) + } catch (exception) { + return Promise.reject(exception) + } + } else { + return finalizeConfig(config) + } + } } // PUBLIC API diff --git a/lib/server.js b/lib/server.js index a6ae81dab..bace88622 100644 --- a/lib/server.js +++ b/lib/server.js @@ -55,22 +55,36 @@ function createSocketIoServer (webServer, executor, config) { } class Server extends KarmaEventEmitter { - constructor (cliOptions, done) { + constructor (cliOptionsOrConfig, done) { super() - logger.setupFromConfig(cliOptions) + logger.setupFromConfig({ + colors: cliOptionsOrConfig.colors, + logLevel: cliOptionsOrConfig.logLevel + }) this.log = logger.create('karma-server') this.loadErrors = [] let config - try { - config = cfg.parseConfig(cliOptions.configFile, cliOptions, { throwErrors: true }) - } catch (parseConfigError) { - // TODO: change how `done` falls back to exit in next major version - // SEE: https://github.com/karma-runner/karma/pull/3635#discussion_r565399378 - (done || process.exit)(1) - return + if (cliOptionsOrConfig instanceof cfg.Config) { + config = cliOptionsOrConfig + } else { + try { + config = cfg.parseConfig( + cliOptionsOrConfig.configFile, + cliOptionsOrConfig, + { + promiseConfig: false, + throwErrors: true + } + ) + } catch (parseConfigError) { + // TODO: change how `done` falls back to exit in next major version + // SEE: https://github.com/karma-runner/karma/pull/3635#discussion_r565399378 + (done || process.exit)(1) + return + } } this.log.debug('Final config', util.inspect(config, false, /** depth **/ null))