0
# karma-coveralls
1
2
karma-coveralls is a Karma plugin that automatically uploads code coverage reports generated by karma-coverage to the coveralls.io service. It acts as a bridge between the Karma test runner ecosystem and the Coveralls coverage tracking platform, enabling continuous monitoring of test coverage in JavaScript projects.
3
4
## Package Information
5
6
- **Package Name**: karma-coveralls
7
- **Package Type**: npm
8
- **Language**: JavaScript
9
- **Installation**: `npm install karma-coveralls --save-dev`
10
11
## Core Imports
12
13
Since this is a Karma plugin, it's registered via Karma's plugin system rather than imported directly:
14
15
```javascript
16
// karma.conf.js
17
module.exports = function(config) {
18
config.set({
19
plugins: [
20
'karma-coverage',
21
'karma-coveralls'
22
],
23
reporters: ['coverage', 'coveralls']
24
});
25
};
26
```
27
28
## Basic Usage
29
30
```javascript
31
// karma.conf.js
32
module.exports = function(config) {
33
config.set({
34
// Basic reporter configuration
35
reporters: ['coverage', 'coveralls'],
36
37
// Coverage reporter setup (required)
38
coverageReporter: {
39
type: 'lcov',
40
dir: 'coverage/'
41
},
42
43
// Optional coveralls-specific configuration
44
coverallsReporter: {
45
repoToken: process.env.COVERALLS_REPO_TOKEN
46
}
47
});
48
};
49
```
50
51
Environment variable configuration:
52
53
```bash
54
# Set repository token
55
export COVERALLS_REPO_TOKEN=your_repo_token_here
56
57
# Run Karma tests
58
npm test
59
```
60
61
## Capabilities
62
63
### Coveralls Reporter
64
65
The main functionality provided by karma-coveralls is the coveralls reporter that processes LCOV coverage data and uploads it to coveralls.io.
66
67
```javascript { .api }
68
/**
69
* Coveralls reporter constructor for Karma
70
* Registered as 'reporter:coveralls' in Karma's plugin system
71
* @param rootConfig - Karma configuration object
72
* @param helper - Karma helper utilities
73
* @param logger - Karma logger instance
74
*/
75
function CoverallsReporter(rootConfig, helper, logger): void;
76
77
// Plugin registration
78
module.exports = {
79
'reporter:coveralls': ['type', CoverallsReporter]
80
};
81
```
82
83
The reporter includes dependency injection configuration:
84
85
```javascript { .api }
86
CoverallsReporter.$inject = ['config', 'helper', 'logger'];
87
```
88
89
### Configuration Options
90
91
#### Karma Configuration
92
93
The plugin integrates with standard Karma configuration:
94
95
```javascript { .api }
96
interface KarmaConfig {
97
/** Array of reporters including 'coveralls' */
98
reporters: string[];
99
/** Coverage reporter configuration (required) */
100
coverageReporter?: CoverageReporterConfig;
101
/** Coverage Istanbul reporter configuration (alternative) */
102
coverageIstanbulReporter?: CoverageIstanbulReporterConfig;
103
/** Coveralls-specific configuration */
104
coverallsReporter?: CoverallsReporterConfig;
105
/** Base path for resolving coverage files */
106
basePath?: string;
107
/** Auto-watch mode (disables coveralls reporter) */
108
autoWatch?: boolean;
109
}
110
```
111
112
#### Coverage Reporter Configuration
113
114
```javascript { .api }
115
interface CoverageReporterConfig {
116
/** Coverage report type - must include 'lcov', 'lcovonly', or 'html' */
117
type?: 'lcov' | 'lcovonly' | 'html' | string;
118
/** Directory for coverage files */
119
dir?: string;
120
/** Array of reporter configurations */
121
reporters?: Array<{
122
/** Reporter type - must include 'lcov', 'lcovonly', or 'html' for coveralls */
123
type: 'lcov' | 'lcovonly' | 'html' | string;
124
/** Directory path for this reporter's output */
125
dir?: string;
126
}>;
127
}
128
```
129
130
#### Coverage Istanbul Reporter Configuration
131
132
```javascript { .api }
133
interface CoverageIstanbulReporterConfig {
134
/** Directory for coverage files */
135
dir?: string;
136
/** Array of reporter types - must include 'lcov' for coveralls */
137
reporters?: Array<'lcov' | 'lcovonly' | 'html' | 'text' | string>;
138
/** Report directory structure */
139
reports?: Array<{
140
type: 'lcov' | 'lcovonly' | 'html' | 'text' | string;
141
dir?: string;
142
}>;
143
}
144
```
145
146
#### Coveralls Reporter Configuration
147
148
```javascript { .api }
149
interface CoverallsReporterConfig {
150
/** Repository token for Coveralls authentication */
151
repoToken?: string;
152
}
153
```
154
155
### Reporter Methods
156
157
The CoverallsReporter class provides the following methods:
158
159
```javascript { .api }
160
/**
161
* Called when Karma exits, handles coverage upload
162
* @param done - Callback function to signal completion
163
*/
164
onExit(done: () => void): void;
165
```
166
167
### Internal Functions
168
169
The plugin includes several internal utility functions:
170
171
```javascript { .api }
172
/**
173
* Resolves which coverage reporter configuration to use
174
* @returns CoverageReporterConfig or CoverageIstanbulReporterConfig
175
* @throws Error if coverage reporter doesn't precede coveralls reporter
176
*/
177
function resolve_coverage_reporter(): CoverageReporterConfig | CoverageIstanbulReporterConfig;
178
179
/**
180
* Attempts to read LCOV files from the specified directory
181
* @param basepath - Directory path to search for lcov.info files
182
* @param retry - Callback function for retry attempts
183
* @param done - Completion callback with LCOV content
184
*/
185
function try_read_lcov(
186
basepath: string,
187
retry: () => void,
188
done: (content?: string) => void
189
): void;
190
191
/**
192
* Reads LCOV files with retry logic (up to 5 attempts)
193
* @param basepath - Directory path to search for lcov.info files
194
* @param finish - Completion callback with LCOV content
195
*/
196
function read_lcov(basepath: string, finish: (content?: string) => void): void;
197
198
/**
199
* Handles response from Coveralls API and logs results
200
* @param done - Karma completion callback
201
* @param err - Error from Coveralls API
202
* @param response - HTTP response object
203
* @param body - Response body content
204
*/
205
function send_to_coveralls(
206
done: () => void,
207
err: Error | null,
208
response: { statusCode: number } | undefined,
209
body: string
210
): void;
211
212
/**
213
* Formats success response from Coveralls API
214
* @param body - Response body (string or parsed JSON)
215
* @returns Formatted success message
216
*/
217
function success(body: string | { message?: string; url?: string }): string;
218
```
219
220
## Configuration Requirements
221
222
### Reporter Order
223
224
The coverage reporter must precede the coveralls reporter in the reporters array:
225
226
```javascript
227
// Correct
228
reporters: ['coverage', 'coveralls']
229
reporters: ['coverage-istanbul', 'coveralls']
230
231
// Incorrect - will throw error
232
reporters: ['coveralls', 'coverage']
233
```
234
235
### Coverage Format
236
237
The coverage reporter must generate LCOV format output:
238
239
```javascript
240
coverageReporter: {
241
type: 'lcov', // or 'lcovonly'
242
dir: 'coverage/'
243
}
244
```
245
246
### Authentication
247
248
Repository token can be provided via:
249
250
1. Environment variable:
251
```bash
252
export COVERALLS_REPO_TOKEN=your_token
253
```
254
255
2. Karma configuration:
256
```javascript
257
coverallsReporter: {
258
repoToken: 'your_token'
259
}
260
```
261
262
3. `.coveralls.yml` file:
263
```yaml
264
repo_token: your_token
265
```
266
267
## File System Behavior
268
269
### LCOV File Discovery
270
271
The plugin automatically discovers LCOV files using the following logic:
272
273
1. Searches for `lcov.info` files in the coverage directory
274
2. Uses the first matching coverage reporter configuration:
275
- HTML, LCOV, or LCOVONLY reporter with explicit `dir` property
276
- Falls back to `coverageReporter.dir` or `coverageIstanbulReporter.dir`
277
- Defaults to `./coverage` if no directory specified
278
279
### File Processing
280
281
```javascript { .api }
282
/**
283
* LCOV file processing workflow:
284
* 1. Discovers lcov.info files using vinyl-fs glob pattern: '**\/lcov.info'
285
* 2. Merges multiple LCOV files using lcov-result-merger through stream processing
286
* 3. Converts merged LCOV to Coveralls format via coveralls.convertLcovToCoveralls()
287
* 4. Uploads to Coveralls API via coveralls.sendToCoveralls()
288
*
289
* Stream processing chain:
290
* vfs.src() -> through2.obj() -> lcovResultMerger() -> through2.obj() -> done()
291
*/
292
293
/**
294
* LCOV file discovery logic priority order:
295
* 1. First reporter in coverageReporter.reporters[] with type 'html', 'lcov', or 'lcovonly' and dir property
296
* 2. coverageReporter.dir (if no specific reporter dir found)
297
* 3. './coverage' (default fallback)
298
*/
299
interface LcovDiscoveryConfig {
300
/** Resolved path to directory containing lcov.info files */
301
filepath: string;
302
/** Source configuration that provided the path */
303
source: 'reporter' | 'coverage' | 'default';
304
}
305
```
306
307
### Retry Logic
308
309
The plugin includes retry logic when LCOV files are not immediately available:
310
311
- Retries up to 5 times with 200ms delays
312
- Handles timing issues when coverage files are being written
313
314
## Error Handling
315
316
### Configuration Errors
317
318
```javascript { .api }
319
/**
320
* Configuration validation errors thrown by the plugin:
321
*/
322
interface ConfigurationError extends Error {
323
message: "coverage or coverage-istanbul reporter should precede coveralls";
324
}
325
326
/**
327
* Thrown when coveralls reporter appears before coverage reporter in config
328
* @throws ConfigurationError
329
*/
330
function validateReporterOrder(): void;
331
```
332
333
### Runtime Behavior
334
335
- **Auto-watch mode**: Reporter disables itself automatically with info log "disabled due to --auto-watch"
336
- **Missing LCOV files**: Completes without error (no upload), retries up to 5 times with 200ms delays
337
- **API errors**: Logged but don't cause Karma to fail
338
- **Network issues**: Handled gracefully with error logging
339
340
### HTTP Response Handling
341
342
```javascript { .api }
343
/**
344
* HTTP response status codes and handling:
345
* - 200-299 with valid JSON: Success, logs formatted message
346
* - Other status codes: Error, logs status code and raw response body
347
* - Missing response object: Creates default response with statusCode: 0
348
* - Invalid JSON in response: Treated as error response
349
*/
350
interface CoverallsResponse {
351
statusCode: number;
352
body?: string;
353
}
354
355
/**
356
* Success response format from Coveralls API
357
*/
358
interface CoverallsSuccessBody {
359
message?: string;
360
url?: string;
361
}
362
```
363
364
### Logging Behavior
365
366
The plugin provides detailed logging through Karma's logger:
367
368
```javascript { .api }
369
/**
370
* Log levels and messages used by the plugin:
371
* - log.info('disabled due to --auto-watch') - When auto-watch is enabled
372
* - log.debug('use lcov.info in %s', filepath) - Coverage directory path
373
* - log.info('uploading...') - Before sending to Coveralls
374
* - log.info('%d --- %s', statusCode, message) - Upload result
375
*/
376
interface LoggerMethods {
377
info(message: string, ...args: any[]): void;
378
debug(message: string, ...args: any[]): void;
379
}
380
```
381
382
## Dependencies
383
384
The plugin relies on the following dependencies:
385
386
```javascript { .api }
387
/**
388
* Required dependencies and their usage:
389
* - coveralls: ~3.0.0 - Coveralls.io API client for authentication and upload
390
* - lcov-result-merger: ^3.0.0 - Merges multiple LCOV files into single stream
391
* - through2: ^2.0.0 - Stream transformation utilities for file processing
392
* - vinyl-fs: ^3.0.2 - File system operations with vinyl objects for glob patterns
393
*
394
* Core Node.js modules used:
395
* - fs: File system operations for checking file existence
396
* - path: Path manipulation for resolving coverage directories
397
*/
398
399
/**
400
* Dependency injection pattern used by Karma
401
*/
402
interface KarmaDependencyInjection {
403
/** Configuration object containing all Karma settings */
404
config: KarmaConfig;
405
/** Karma helper utilities for type checking and validation */
406
helper: KarmaHelper;
407
/** Karma logger factory for creating named loggers */
408
logger: KarmaLogger;
409
}
410
411
interface KarmaHelper {
412
/** Checks if a value is defined (not null or undefined) */
413
isDefined(value: any): boolean;
414
}
415
416
interface KarmaLogger {
417
/** Creates a named logger instance */
418
create(name: string): LoggerMethods;
419
}
420
```
421
422
## Integration Points
423
424
### Karma Plugin System
425
426
The plugin registers with Karma as a reporter:
427
428
```javascript { .api }
429
// Plugin exports
430
module.exports = {
431
'reporter:coveralls': ['type', CoverallsReporter]
432
};
433
```
434
435
### Coverage Reporters
436
437
Works with both karma-coverage and karma-coverage-istanbul:
438
439
- karma-coverage: Uses `coverageReporter` configuration
440
- karma-coverage-istanbul: Uses `coverageIstanbulReporter` configuration
441
442
### Coveralls.io API
443
444
Integrates with the Coveralls service for:
445
446
- Authentication via repository tokens
447
- LCOV data conversion and formatting
448
- Coverage report upload and processing
449
- Response handling and error reporting
450
451
```javascript { .api }
452
/**
453
* Coveralls API integration workflow:
454
* 1. coveralls.getBaseOptions() - Gets base configuration and authentication
455
* 2. coveralls.convertLcovToCoveralls() - Converts LCOV to Coveralls format
456
* 3. coveralls.sendToCoveralls() - Uploads coverage data to Coveralls API
457
*/
458
459
/**
460
* Coveralls API options configuration
461
*/
462
interface CoverallsOptions {
463
/** Always set to "." by the plugin */
464
filepath: string;
465
/** Repository token from config or environment */
466
repo_token?: string;
467
/** Additional options provided by coveralls.getBaseOptions() */
468
[key: string]: any;
469
}
470
471
/**
472
* Coveralls API methods used by the plugin
473
*/
474
interface CoverallsAPI {
475
/** Gets base options including authentication from environment/config */
476
getBaseOptions(callback: (err: Error | null, options: CoverallsOptions) => void): void;
477
478
/** Converts LCOV format to Coveralls API format */
479
convertLcovToCoveralls(
480
lcovData: string,
481
options: CoverallsOptions,
482
callback: (err: Error | null, postData: any) => void
483
): void;
484
485
/** Sends formatted data to Coveralls API */
486
sendToCoveralls(
487
postData: any,
488
callback: (err: Error | null, response: CoverallsResponse, body: string) => void
489
): void;
490
}
491
```