-
Notifications
You must be signed in to change notification settings - Fork 241
/
stryker-karma.conf.ts
177 lines (156 loc) · 6.55 KB
/
stryker-karma.conf.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
import * as path from 'path';
import { Logger, LoggerFactoryMethod } from '@stryker-mutator/api/logging';
import { Config, ConfigOptions, ClientOptions, InlinePluginType } from 'karma';
import { noopLogger, requireResolve } from '@stryker-mutator/util';
import StrykerReporter from '../karma-plugins/stryker-reporter';
import TestHooksMiddleware, { TEST_HOOKS_FILE_NAME } from '../karma-plugins/test-hooks-middleware';
function setDefaultOptions(config: Config) {
config.set({
browsers: ['ChromeHeadless'],
frameworks: ['jasmine'],
});
}
function setUserKarmaConfigFile(config: Config, log: Logger) {
if (globalSettings.karmaConfigFile && typeof globalSettings.karmaConfigFile === 'string') {
const configFileName = path.resolve(globalSettings.karmaConfigFile);
log.debug('Importing config from "%s"', configFileName);
try {
const userConfig = requireResolve(configFileName);
if (typeof userConfig !== 'function') {
throw new TypeError(`Karma config file "${configFileName}" should export a function! Found: ${typeof userConfig}`);
}
userConfig(config);
config.configFile = configFileName; // override config to ensure karma is as user-like as possible
} catch (error) {
if (error.code === 'MODULE_NOT_FOUND') {
log.error(
`Unable to find karma config at "${globalSettings.karmaConfigFile}" (tried to load from ${configFileName}). Please check your stryker config. You might need to make sure the file is included in the sandbox directory.`
);
} else {
log.error(`Could not read karma configuration from ${globalSettings.karmaConfigFile}.`, error);
}
}
}
}
/**
* Sets configuration that is needed to control the karma life cycle. Namely it shouldn't watch files and not quit after first test run.
* @param config The config to use
*/
function setLifeCycleOptions(config: Config) {
config.set({
// No auto watch, stryker will inform us when we need to test
autoWatch: false,
// Override browserNoActivityTimeout. Default value 10000 might not enough to send perTest coverage results
browserNoActivityTimeout: 1000000,
// Never detach, always run in this same process (is already a separate process)
detached: false,
// Don't stop after first run
singleRun: false,
});
}
/**
* Sets configuration that is needed to control client scripts in karma.
* @param config The config to use
* @see https://github.com/stryker-mutator/stryker/issues/2049
*/
function setClientOptions(config: Config) {
// Disable clearContext because of issue #2049 (race condition in Karma)
// Enabling clearContext (default true) will load "about:blank" in the iFrame after a test run.
// As far as I can see clearing the context only has a visible effect (you don't see the result of the last test).
// If this is true, disabling it is safe to do and solves the race condition issue.
const clientOptions: Partial<ClientOptions> = { clearContext: false };
// Disable randomized tests with using jasmine. Stryker doesn't play nice with a random test order, since spec id's tent to move around
// Also set failFast, so that we're not waiting on more than 1 failed test
if (config.frameworks?.includes('jasmine')) {
(clientOptions as any).jasmine = {
random: false,
failFast: true,
};
}
if (config.frameworks?.includes('mocha')) {
(clientOptions as any).mocha = { bail: true };
}
config.set({ client: clientOptions });
}
function setUserKarmaConfig(config: Config) {
if (globalSettings.karmaConfig) {
config.set(globalSettings.karmaConfig);
}
}
function setBasePath(config: Config) {
if (!config.basePath) {
// We need to set the base path, so karma won't use this file to base everything of
if (globalSettings.karmaConfigFile) {
config.basePath = path.resolve(path.dirname(globalSettings.karmaConfigFile));
} else {
config.basePath = process.cwd();
}
}
}
function addPlugin(karmaConfig: ConfigOptions, karmaPlugin: string | Record<string, InlinePluginType>) {
karmaConfig.plugins = karmaConfig.plugins || ['karma-*'];
karmaConfig.plugins.push(karmaPlugin);
}
/**
* Configures the test hooks middleware.
* It adds a non-existing file to the top `files` array.
* Further more it configures a middleware that serves the file.
*/
function configureTestHooksMiddleware(config: Config) {
// Add test run middleware file
config.files = config.files || [];
config.files.unshift({ pattern: TEST_HOOKS_FILE_NAME, included: true, watched: false, served: false, nocache: true }); // Add a custom hooks file to provide hooks
const middleware: string[] = config.beforeMiddleware || (config.beforeMiddleware = []);
middleware.unshift(TestHooksMiddleware.name);
TestHooksMiddleware.instance.configureTestFramework(config.frameworks);
addPlugin(config, { [`middleware:${TestHooksMiddleware.name}`]: ['value', TestHooksMiddleware.instance.handler] });
}
function configureStrykerMutantCoverageAdapter(config: Config) {
config.files = config.files || [];
config.files.unshift({
pattern: require.resolve('../karma-plugins/stryker-mutant-coverage-adapter'),
included: true,
watched: false,
served: true,
nocache: true,
});
}
function configureStrykerReporter(config: Config) {
addPlugin(config, { [`reporter:${StrykerReporter.name}`]: ['value', StrykerReporter.instance] });
if (!config.reporters) {
config.reporters = [];
}
config.reporters.push(StrykerReporter.name);
}
const globalSettings: {
karmaConfig?: ConfigOptions;
karmaConfigFile?: string;
getLogger: LoggerFactoryMethod;
} = {
getLogger() {
return noopLogger;
},
};
function configureKarma(config: Config) {
const log = globalSettings.getLogger(path.basename(__filename));
setDefaultOptions(config);
setUserKarmaConfigFile(config, log);
setUserKarmaConfig(config);
setBasePath(config);
setLifeCycleOptions(config);
setClientOptions(config);
configureTestHooksMiddleware(config);
configureStrykerMutantCoverageAdapter(config);
configureStrykerReporter(config);
}
/**
* Provide global settings for next configuration
* This is the only way we can pass through any values between the `KarmaTestRunner` and the stryker-karma.conf file.
* (not counting environment variables)
*/
configureKarma.setGlobals = (globals: { karmaConfig?: ConfigOptions; karmaConfigFile?: string; getLogger?: LoggerFactoryMethod }) => {
globalSettings.karmaConfig = globals.karmaConfig;
globalSettings.karmaConfigFile = globals.karmaConfigFile;
globalSettings.getLogger = globals.getLogger || (() => noopLogger);
};
export = configureKarma;