UNPKG

30.8 kBMarkdownView Raw
1# karma-typescript
2
3<a href="https://www.npmjs.com/package/karma-typescript"><img alt="Npm Version" src="https://img.shields.io/npm/v/karma-typescript.svg"></a>
4<a href="https://www.npmjs.com/package/karma-typescript"><img alt="Npm Total Downloads" src="https://img.shields.io/npm/dt/karma-typescript.svg"></a>
5<a href="https://www.npmjs.com/package/karma-typescript"><img alt="Npm Monthly Downloads" src="https://img.shields.io/npm/dm/karma-typescript.svg"></a>
6<a href="https://travis-ci.org/monounity/karma-typescript"><img alt="Travis Status" src="https://img.shields.io/travis/monounity/karma-typescript/master.svg?label=travis"></a>
7<a href="https://ci.appveyor.com/project/monounity/karma-typescript"><img alt="Appveyor Status" src="https://img.shields.io/appveyor/ci/monounity/karma-typescript/master.svg?label=appveyor"></a>
8
9> Karma :heart: Typescript
10
11* Run unit tests written in Typescript with full type checking, seamlessly without extra build steps or scripts.
12* Get remapped test coverage with [Istanbul](https://istanbul.js.org).
13* Use plain Typescript or a framework: Angular, AngularJS, React, Sinon, any framework of choice.
14
15## Installation
16
17The easiest way is to keep `karma-typescript` as a devDependency in `package.json`:
18
19```json
20{
21 "devDependencies": {
22 "karma": "^6.1.0",
23 "karma-typescript": "5.5.4"
24 }
25}
26```
27
28Do this by installing the plugin via npm:
29
30```
31npm install --save-dev karma-typescript
32```
33
34## Configuration
35
36Bare minimum configuration can be achieved with the following `karma.conf.js` file:
37
38```javascript
39module.exports = function(config) {
40 config.set({
41 frameworks: ["jasmine", "karma-typescript"],
42 files: [
43 "src/**/*.ts" // *.tsx for React Jsx
44 ],
45 preprocessors: {
46 "**/*.ts": "karma-typescript" // *.tsx for React Jsx
47 },
48 reporters: ["progress", "karma-typescript"],
49 browsers: ["Chrome"]
50 });
51};
52```
53
54The above example will compile all Typescript files and run the unit tests, producing remapped coverage in `./coverage`.
55
56## Examples
57
58[Cookbook](https://github.com/monounity/karma-typescript/blob/master/packages/karma-typescript/cookbook.md)
59
60### Frameworks and Integrations
61
62- [Angular](https://github.com/monounity/karma-typescript/tree/master/examples/angular2)
63- [AngularJS](https://github.com/monounity/karma-typescript/tree/master/examples/angularjs)
64- [Docker](https://github.com/monounity/karma-typescript/tree/master/examples/docker)
65- [Gulp](https://github.com/monounity/karma-typescript/tree/master/examples/gulp)
66- [Mocha](https://github.com/monounity/karma-typescript/tree/master/examples/mocha)
67
68### Other examples
69
70- Typescript [@latest](https://github.com/monounity/karma-typescript/tree/master/examples/typescript-latest)
71- Typescript [1.8.10](https://github.com/monounity/karma-typescript/tree/master/examples/typescript-1.8.10)
72- Typescript [1.6.2](https://github.com/monounity/karma-typescript/tree/master/examples/typescript-1.6.2)
73
74### Sample applications by users
75- [Hybrid app, code in JavaScript and tests in Typescript](https://github.com/adrianmarinica/karma-typescript-angularjs-sample)
76
77## Transforms:
78- [karma-typescript-angular2-transform](https://github.com/monounity/karma-typescript/tree/master/packages/karma-typescript-angular2-transform)
79- [karma-typescript-cssmodules-transform](https://github.com/monounity/karma-typescript/tree/master/packages/karma-typescript-cssmodules-transform)
80- [karma-typescript-es6-transform](https://github.com/monounity/karma-typescript/tree/master/packages/karma-typescript-es6-transform)
81- [karma-typescript-postcss-transform](https://github.com/monounity/karma-typescript/tree/master/packages/karma-typescript-postcss-transform)
82
83### Example output
84
85<img src="http://i.imgur.com/sc4Mswh.png" width="580" height="280" />
86
87- [Angular2 screenshot](https://github.com/monounity/karma-typescript/blob/master/assets/angular2.png)
88- [React screenshot](https://github.com/monounity/karma-typescript/blob/master/assets/react.png)
89
90## Advanced configuration
91
92The plugin has default settings for the compiler, instrumenting files and creating reports etc, which should suit most needs.
93
94These are the default compiler settings:
95
96```javascript
97karmaTypescriptConfig: {
98 compilerOptions: {
99 emitDecoratorMetadata: true,
100 experimentalDecorators: true,
101 jsx: "react",
102 module: "commonjs",
103 sourceMap: true,
104 target: "ES5"
105 },
106 exclude: ["node_modules"]
107}
108```
109
110If the defaults aren't enough, the settings can be configured from `karma.conf.js`:
111
112* **karmaTypescriptConfig.bundlerOptions.addNodeGlobals** - Boolean indicating whether the global variables
113 `process` and `Buffer` should be added to the bundle.<br/>
114 Defaults to `true`.
115
116* **karmaTypescriptConfig.bundlerOptions.acornOptions** - An object literal with keys/values which are passed as configuration
117 options to the [Acorn](https://github.com/acornjs/acorn) parser used by the bundler. The most notable of these keys is
118 `ecmaScript` which sets the ECMAScript target used by the parser. If code has dependencies that use a newer version of
119 ECMAScript than the bundler defaults to (ES5), parsing errors will result when the source-reader tries to bundle dependencies
120 (e.g. dependencies that use `bigint` literals like `1n` will cause an error during code compilation unless this option is
121 explicitly set to 11(ES2020). A complete list of options can be found in the [Acorn documentation](https://github.com/acornjs/acorn/tree/master/acorn#interface).
122
123* **karmaTypescriptConfig.bundlerOptions.constants** - An object literal with keys/values which will be available as global
124 variables in the bundle. The keys are expected to be strings and any non-string value will be stringified with `JSON.stringify`.
125
126 Configuration example:
127 ```javascript
128 constants: {
129 __STRING__: JSON.stringify("abc" + 123),
130 __BOOLEAN__: true,
131 "process.env": {
132 "VARIABLE": "value"
133 }
134 }
135 ```
136 Code example:
137 ```javascript
138 declare var __STRING__: string;
139 declare var __BOOLEAN__: boolean;
140
141 console.log(__STRING__, __BOOLEAN__, process.env.VARIABLE);
142 ```
143
144* **karmaTypescriptConfig.bundlerOptions.entrypoints** - A `RegExp` filtering which files loaded by Karma should be executed in
145 a test run, for example only filenames ending with ".spec.ts": `/\.spec\.ts$/`.<br/>
146 This setting can be used to make sure the specs have finished setting up the test environment before other code starts
147 requiring modules, which otherwise could lead to subtle bugs caused by race conditions.<br/>
148 When filtering file paths, beware that Windows uses `\` while UNIX-like systems use `/` as path separator.<br/>
149 Defaults to all files, `/.*/`.
150
151* **karmaTypescriptConfig.bundlerOptions.exclude** - An array of npm module names that will be excluded from the bundle.
152
153* **karmaTypescriptConfig.bundlerOptions.ignore** - An array of npm module names that will be bundled as stubs, ie `module.exports = {};`.
154
155* **karmaTypescriptConfig.bundlerOptions.noParse** - An array of module names that will be bundled without being parsed for dependencies.
156
157* **karmaTypescriptConfig.bundlerOptions.resolve.alias** - An object literal where the key is a module name
158 and the value is a path that will be used when resolving the module.<br/>
159 The key is a string.
160
161* **karmaTypescriptConfig.bundlerOptions.resolve.extensions** - An array of file extensions to use, in order, when resolving modules.<br/>
162 Defaults to `[".js", ".json", ".mjs", ".ts", ".tsx"]`.
163
164* **karmaTypescriptConfig.bundlerOptions.resolve.directories** - An array of directories where modules will be recursively looked up.<br/>
165 Defaults to `["node_modules"]`.
166
167* **karmaTypescriptConfig.bundlerOptions.sourceMap** - A boolean indicating whether source maps should be generated for imported modules in the bundle, useful for debugging in a browser.
168 For more debugging options, please see `karmaTypescriptConfig.coverageOptions.instrumentation`.</br>
169 Defaults to `false`.
170
171* **karmaTypescriptConfig.bundlerOptions.transforms** - An array of functions altering or replacing compiled Typescript code/Javascript
172 code loaded from `node_modules` before bundling it.
173 For more detailed documentation on transforms, please refer to the [Transforms API section](#transforms-api) in this document.<br/>
174
175* **karmaTypescriptConfig.bundlerOptions.validateSyntax** - A boolean indicating whether the syntax of the bundled code should be validated.
176 Setting this to `false` may speed up bundling for large projects with lots of imports from `node_modules`.<br/>
177 Defaults to `true`.
178
179* **karmaTypescriptConfig.compilerDelay** - The number of milliseconds the compiler waits before compiling the project on each run.</br>
180 For projects with a large number of files it might be necessary to increase this value to make sure the compiler has collected all files before firing.</br>
181 Defaults to 250 ms.
182
183* **karmaTypescriptConfig.compilerOptions** - This setting will override or add to existing compiler options.<br/>
184 Valid options are the same as for the `compilerOptions` section in `tsconfig.json`, with the
185 exception of `outDir`and `outFile` which are ignored since the code is compiled in-memory.
186
187 If `noEmitOnError` is set to a truthy value, in either `tsconfig.json` or in `karmaTypescriptConfig.compilerOptions`,
188 the karma process will exit with `ts.ExitStatus.DiagnosticsPresent_OutputsSkipped` if any compilation errors occur.
189
190* **karmaTypescriptConfig.coverageOptions.instrumentation** - A boolean indicating whether the code should be instrumented,
191 set this property to `false` to see the original Typescript code when debugging.
192 Please note that setting this property to `true` requires the Typescript compiler option `sourceMap` to also be set to `true`.
193 For more debugging options, please see `karmaTypescriptConfig.coverageOptions.sourceMap`.<br/>
194 Defaults to `true`.
195
196* **karmaTypescriptConfig.coverageOptions.instrumenterOptions** - Pass options to the `istanbul` instrumenter, ie options supported by [istanbul-lib-instrument](https://github.com/istanbuljs/istanbuljs/blob/master/packages/istanbul-lib-instrument/src/instrumenter.js):
197
198 ```js
199 {
200 // Name of global coverage variable.
201 coverageVariable: '__coverage__',
202
203 // Preserve comments in output.
204 preserveComments: false,
205
206 // Generate compact code.
207 compact: true,
208
209 // Set to true to instrument ES6 modules.
210 esModules: false,
211
212 // Set to true to allow `return` statements outside of functions.
213 autoWrap: false,
214
215 // Set to true to produce a source map for the instrumented code.
216 produceSourceMap: false,
217
218 // Set to array of class method names to ignore for coverage.
219 ignoreClassMethods: [],
220
221 // A callback function that is called when a source map URL is found in the original code.
222 // This function is called with the source file name and the source map URL.
223 sourceMapUrlCallback: null,
224
225 // Turn debugging on.
226 debug: false,
227
228 // Set plugins.
229 plugins: [
230 'asyncGenerators',
231 'bigInt',
232 'classProperties',
233 'classPrivateProperties',
234 'dynamicImport',
235 'importMeta',
236 'objectRestSpread',
237 'optionalCatchBinding',
238 'flow',
239 'jsx'
240 ]
241 };
242 ```
243
244* **karmaTypescriptConfig.coverageOptions.exclude** - A `RegExp` object or an array of `RegExp` objects for filtering which files should be excluded from coverage instrumentation.<br/>
245 When filtering file paths, beware that Windows uses `\` while UNIX-like systems use `/` as path separator.<br/>
246 Defaults to `/\.(d|spec|test)\.ts$/i` which excludes &ast;.d.ts, &ast;.spec.ts and &ast;.test.ts (case insensitive).
247
248* **karmaTypescriptConfig.coverageOptions.threshold** - An object with minimum coverage thresholds. The threshold values can be set on
249 a global level and on a per-file level, with options to exclude files and directories, and override settings on a per-file basis using globbing patterns.<br/>
250 A positive value will be used as a minimum percentage, for example `statements: 50` means that at least 50% of the statements should be covered by a test.<br/>
251 A negative value will be used as a maximum number of uncovered items, for example `lines: 10` means that no more than 10 uncovered lines are allowed.
252 ```javascript
253 threshold: {
254 global: {
255 statements: 100,
256 branches: 100,
257 functions: -10,
258 lines: 100,
259 excludes: [
260 "src/foo/**/*.js"
261 ]
262 },
263 file: {
264 statements: -10,
265 branches: 100,
266 functions: 100,
267 lines: 100,
268 excludes: [
269 "src/bar/**/*.js"
270 ],
271 overrides: {
272 "src/file.js": {
273 statements: 90
274 }
275 }
276 }
277 }
278 ```
279
280* **karmaTypescriptConfig.coverageOptions.watermarks** - An object with custom istanbul watermarks. Each value is an array consisting of
281 a lower and upper bound. If code coverage is above the upper bound, this is considered "healthy", and many reports will print output in green.
282 If code coverage is below the lower bound, this is considered "unhealthy", and many reports will print output in red. Yellow output is reserved
283 for coverage in between the lower and upper bound.
284 ```javascript
285 watermarks: {
286 lines: [75, 90],
287 functions: [75, 90],
288 branches: [75, 90],
289 statements: [75, 90]
290 }
291 ```
292
293* **karmaTypescriptConfig.exclude** - File string patterns to be excluded by the compiler. This property may be an `array` or an `object` for more fine-grained control.
294 * Array: The string values will be merged with existing options.
295 * Object: The string values will be merged with or replace existing options:
296 ```javascript
297 {
298 mode: "merge|replace",
299 values: ["foo", "bar"]
300 }
301 ```
302 Defaults to `["node_modules"]`.
303
304* **karmaTypescriptConfig.include** - File string patterns to be included by the compiler. This property may be an `array` or an `object` for more fine-grained control.
305 * Array: The string values will be merged with existing options.
306 * Object: The string values will be merged with or replace existing options:
307 ```javascript
308 {
309 mode: "merge|replace",
310 values: ["foo", "bar"]
311 }
312 ```
313 This option is available in Typescript ^2.0.0.
314
315* **karmaTypescriptConfig.reports** - The types of coverage reports that should be created when running the tests,
316 defaults to an html report in the directory `./coverage`.
317 Reporters are configured as `"reporttype": destination` where the destination can be specified in three ways:
318
319 * A `string` with a directory path, for example `"html": "coverage"`.
320 * An empty string or `null`. Writes the output to the console, for example `"text-summary": ""`. This is only possible for a subset of the reports available.
321 * An `object` with more fine-grained control over path and filename:
322 ```javascript
323 "cobertura": {
324 "directory": "coverage", // optional, defaults to 'coverage'
325 "subdirectory": "cobertura" // optional, defaults to the name of the browser running the tests
326 "filename": "coverage.xml", // optional, defaults to the report name
327 }
328
329 // "subdirectory" may also be a function that returns a directory from a given browser
330 "cobertura": {
331 "directory": "coverage",
332 "subdirectory": function(browser) {
333 // normalizes browser name directories to lowercase without version
334 // ex: coverage/chrome/coverage.xml
335 return browser.name.toLowerCase().split(' ')[0];
336 },
337 "filename": "coverage.xml"
338 }
339 ```
340
341 * Available report types:
342 * `"clover": destination`
343 * `"cobertura": destination`
344 * `"html": destination`
345 * `"html-spa": destination`
346 * `"json-summary": destination`
347 * `"json": destination`
348 * `"lcovonly": destination`
349 * `"teamcity": destination` (redirects to the console with destination "" or `null`)
350 * `"text-lcov": destination` (redirects to the console with destination "" or `null`)
351 * `"text-summary": destination` (redirects to the console with destination "" or `null`)
352 * `"text": destination` (redirects to the console with destination "" or `null`)
353
354 * Example of the three destination types:
355 ```javascript
356 karmaTypescriptConfig: {
357 reports:
358 {
359 "cobertura": {
360 "directory": "coverage",
361 "filename": "coverage.xml",
362 "subdirectory": "cobertura"
363 },
364 "html": "coverage",
365 "text-summary": ""
366 }
367 }
368 ```
369
370* **karmaTypescriptConfig.transformPath** - A function for renaming compiled file extensions to `.js`.<br/>
371 Defaults to renaming `.ts` and `.tsx` to `.js`.
372
373* **karmaTypescriptConfig.tsconfig** - A path to a `tsconfig.json` file.<br/>
374 The default compiler options will be replaced by the options in this file.<br/>
375 The directory of the `tsconfig.json` file will be used as the base path for the Typescript compiler, and if `karmaTypescriptConfig.tsconfig` isn't set, the `basePath` property of the Karma config will be used as the
376 compiler base path instead.
377
378* **karmaTypescriptConfig.stopOnFailure** - Stop on any compiler error.<br/>
379 By default karma will stop when any typescript compile errors are encountered.<br/>
380 Setting this to false will allow tests to be run when typescript compile errors are present.
381
382Example of a full `karmaTypescriptConfig` configuration:
383
384```javascript
385karmaTypescriptConfig: {
386 bundlerOptions: {
387 addNodeGlobals: true,
388 constants: {
389 __PRODUCTION__: false
390 },
391 entrypoints: /\.spec\.(ts|tsx)$/,
392 exclude: ["react/addons"],
393 ignore: ["ws"],
394 noParse: "jquery",
395 resolve: {
396 alias: {
397 "@angular/upgrade/static$": "../bundles/upgrade-static.umd.js"
398 },
399 extensions: [".js", ".json"],
400 directories: ["node_modules"]
401 },
402 sourceMap: false,
403 transforms: [require("karma-typescript-es6-transform")()],
404 validateSyntax: true
405 },
406 compilerDelay: 500,
407 compilerOptions: {
408 noImplicitAny: true,
409 },
410 coverageOptions: {
411 instrumentation: true,
412 instrumenterOptions: {
413 preserveComments: true
414 },
415 exclude: /\.(d|spec|test)\.ts/i,
416 threshold: {
417 global: {
418 statements: 100,
419 branches: 100,
420 functions: -10,
421 lines: 100,
422 excludes: [
423 "src/foo/**/*.js"
424 ]
425 },
426 file: {
427 statements: -10,
428 branches: 100,
429 functions: 100,
430 lines: 100,
431 excludes: [
432 "src/bar/**/*.js"
433 ],
434 overrides: {
435 "src/file.js": {
436 statements: 90
437 }
438 }
439 }
440 },
441 },
442 exclude: ["broken"],
443 include: {
444 mode: "replace",
445 values: ["**/*.ts"]
446 },
447 reports: {
448 "cobertura": {
449 "directory": "coverage",
450 "filename": "cobertura/coverage.xml"
451 },
452 "html": "coverage",
453 "text-summary": ""
454 },
455 transformPath: function(filepath) {
456 return filepath.replace(/\.(ts|tsx)$/, ".js");
457 },
458 tsconfig: "./tsconfig.json",
459 stopOnFailure: false
460}
461```
462
463## Automatic bundling
464
465Files executed in the test run are bundled into a main bundle, containing dependencies required from node_modules,
466and several smaller standalone bundles containing the Typescript files. All these bundles are tied together by `commonjs.js`,
467which acts as a hub, loading modules when they are required by other modules.
468
469All files are bundled by being wrapped in a custom [CommonJS](https://en.wikipedia.org/wiki/CommonJS) wrapper,
470which emulates the Node.js module system by injecting the require function, the module object, the exports object,
471the &#95;&#95;dirname variable and the &#95;&#95;filename variable.
472
473For instance, this Typescript sample:
474
475```javascript
476export function exportedFunction(): string {
477 return "";
478}
479```
480
481Would be compiled to the following JavaScript (assuming the compiler option `module` is set to `commonjs`):
482
483```javascript
484function exportedFunction() {
485 return "";
486}
487exports.exportedFunction = exportedFunction;
488```
489
490It would then be wrapped in a `CommonJS` wrapper by the bundler:
491
492```javascript
493(function(global){
494 global.wrappers['/absolutepath/app/src/file.ts']=[function(require,module,exports,__dirname,__filename){
495 function exportedFunction() {
496 return "";
497 }
498 exports.exportedFunction = exportedFunction;
499 },'src/file.ts',{}];
500})(this);
501```
502
503*(In this example, the source map and a few other statements have been omitted for brevity and the wrapper has been formatted for readability)*
504
505After compilation, a simple static analysis is performed to find "import" and "require" statements in the code and if any
506dependencies are found, for instance `import { Component } from "@angular/core";`, it is added to the main bundle file along
507with its dependencies.
508
509If no import or require statements are found in any Typescript file included in the test run, or the compiler option `module`
510is set to another value than `commonjs`, *automatic bundling will not occur*.
511
512This means that no Typescript file will be wrapped in the CommonJS wrapper and the reason behind this is the encapsulation that
513the Node.js module system provides. If no module requests any other module, the test run would contain only isolated islands of
514code unreachable from the global scope, there would be nothing to execute.
515
516However, this intentional behavior makes it possible to use karma-typescript for projects that use the Typescript module system,
517or have the compiler option `module` set to another value than `commonjs`, or simply put everything on the global scope.
518
519### Importing stylesheets and bundling for production
520
521Style files (.css|.less|.sass|.scss) are served as JSON strings to the browser running the tests,
522allowing styles to be loaded using the Typescript import statement, ie `import "./style/app.scss";`.
523
524This means styles can be imported in order to let, for instance, webpack load the styles with
525less-loader or scss-loader etc for bundling later on, without breaking the unit test runner.
526
527Note: JSON required by modules in node_modules will be loaded automatically by the bundler.
528
529### The module object
530
531```javascript
532module: {
533 exports: {},
534 id: "project-relative-path/bar.ts",
535 uri: "/absolute-path/project-relative-path/bar.ts"
536}
537```
538
539The `module.id` will be calculated from the value of `module.uri`, relative to the Karma config `basePath` value.
540
541Modules exporting an extensible object such as a *function* or an *object literal* will also be decorated with
542a non-enumerable `default` property if `module.exports.default` is undefined.
543
544### Globals
545
546A full Node.js environment will be provided with global variables and browser shims for builtin core modules:
547
548* &#95;&#95;dirname
549* &#95;&#95;filename
550* Buffer
551* global
552* process
553
554### Browser shims
555* [assert](https://www.npmjs.com/package/assert)
556* [buffer](https://www.npmjs.com/package/buffer)
557* [console](https://www.npmjs.com/package/console-browserify)
558* [constants](https://www.npmjs.com/package/constants-browserify)
559* [crypto](https://www.npmjs.com/package/crypto-browserify)
560* [domain](https://www.npmjs.com/package/domain-browser)
561* [events](https://www.npmjs.com/package/events)
562* [http](https://www.npmjs.com/package/stream-http)
563* [https](https://www.npmjs.com/package/https-browserify)
564* [os](https://www.npmjs.com/package/os-browserify)
565* [path](https://www.npmjs.com/package/path-browserify)
566* [punycode](https://www.npmjs.com/package/punycode)
567* [querystring](https://www.npmjs.com/package/querystring-es3)
568* [stream](https://www.npmjs.com/package/stream-browserify)
569* [string_decoder](https://www.npmjs.com/package/string_decoder)
570* [timers](https://www.npmjs.com/package/timers-browserify)
571* [tty](https://www.npmjs.com/package/tty-browserify)
572* [url](https://www.npmjs.com/package/url)
573* [util](https://www.npmjs.com/package/util)
574* [vm](https://www.npmjs.com/package/vm-browserify)
575* [zlib](https://www.npmjs.com/package/browserify-zlib)
576
577The plugin uses [browser-resolve](https://github.com/defunctzombie/node-browser-resolve) from the [browserify](https://github.com/substack/node-browserify) tool chain to load the source code from node_modules.
578
579### Mocking
580Imported modules, local or npm packages, can be mocked using [karma-typescript-mock](https://www.npmjs.com/package/karma-typescript-mock). This feature is available in `karma-typescript@^3.0.5`.
581
582## Transforms API
583
584The bundler has a public API which lets plugins alter or completely replace code before adding it to the bundle.
585For example, a plugin could compile ES2015 JavaScript code to to ES5 syntax, making it possible to import an `npm` module
586written in ES2015 syntax from a Typescript module directly.
587
588The interface between the bundler and the plugins is a plain array of functions, specified in the configuration property `karmaTypescriptConfig.bundlerOptions.transforms`, where each function is considered a transforming plugin.
589
590The plugin functions in the transforms array are asynchronous and adhere to the Node.js callback convention where the first
591argument of the callback function is an `Error` object or `undefined` and the following parameters contains the result.
592However, although each function is asynchronous, all functions will be called *synchronously* one by one in the order they were added to the array, and each function will be called with the result of the previous function, enabling transforms plugin chaining.
593
594Transforms will be executed at two points in the bundling process: right after compilation of the project Typescript files
595and when resolving `import` and `require` statements. This means each transforming function will be called for both
596Typescript files and JavaScript files from `node_modules`, making each plugin implementation responsible for validating the
597context before performing any logic, for example by checking the file name, module name or the existence of an ast object etc.
598
599Each transforming function will be executed before resolving dependencies, which means paths in `import` or `require` statements
600or anywhere in the code can be rewritten before bundling, to fit the Karma execution environment.
601
602Example of a simple inline transforming function replacing the contents of a `.css` file, mimicking the behavior of Css Modules:
603
604```javascript
605karmaTypescriptConfig: {
606 bundlerOptions: {
607 transforms: [
608 function(context, callback) {
609 if(context.module === "./main.css") {
610 context.source = "module.exports = { color: red };";
611 return callback(undefined, true);
612 }
613 return callback(undefined, false);
614 }
615 ]
616 }
617}
618```
619
620It is also possible to change the transpiled Typescript (ie the plain JavaScript code) code by using the third callback parameter to tell the Transforms API not to recompile the transpiled code:
621
622```javascript
623karmaTypescriptConfig: {
624 bundlerOptions: {
625 transforms: [
626 function(context, callback) {
627 if(context.ts) {
628 context.ts.transpiled = "\n/* istanbul ignore next */\n" + context.ts.transpiled;
629 return callback(undefined, true, false);
630 }
631 return callback(undefined, false);
632 }
633 ]
634 }
635}
636```
637
638### Context
639The context object, `TransformContext`, is defined [here](https://github.com/monounity/karma-typescript/blob/master/src/api/transforms.ts).
640
641### Callback
642
643The callback has two signatures, the "boolean" and the "object".
644
645The boolean callback function has three arguments:
6461. An `Error` object or `undefined`
6472. A boolean indicating whether the value of `context.source` has changed or not.
6483. A boolean indicating whether the transformed source should be recompiled. Defaults to true and can be omitted.
649
650The object callback function has two arguments:
651
6521. An `Error` object or `undefined`
6532. An object literal, which has the following properties:
654 1. A boolean indicating whether the value of `context.source` has changed or not.
655 2. A boolean indicating whether the transformed source should be recompiled (Typescript only!).
656 3. A boolean indicating whether a new AST should be created for the transformed source (JavaScript only!).
657
658## Requirements
659
660Typescript ^1.6.2 is required.
661
662Versions 1.6.2 - 1.7.5 work but aren't as heavily tested as versions 1.8.10 and up.
663
664## Troubleshooting
665
666### Error: Can not load "karma-typescript", it is not registered!
667
668Users have reported success by simply deleting the `node_modules` folder and then running `npm install` again.
669
670### Error: Cannot find module 'buffer/' from '.'
671
672*Note: this error has been fixed in karma-typescript@^3.0.0`.*
673
674This error seems to hit mostly users of with older versions of `npm`, where all dependencies don't get pulled in automatically by `npm`.
675
676There's a workaround reported by users, which is simply adding the missing dependencies explicitly to `package.json`:
677
678 * `npm install --save-dev browser-resolve`
679 * `npm install --save-dev buffer`
680 * `npm install --save-dev process`
681
682Other workarounds are running `npm install` twice or, if possible, upgrading to a newer version of `npm`.
683
684These are the environments reported failing/working:
685
686|Npm|Node.js|OS|Works|
687|---|---|---|---|
688|2.5.18|4.4.7|Unknown|No|
689|2.14.7|4.2.1|Ubuntu 14.04|No|
690|2.14.12|4.2.6|OSX 10.11.3|No|
691|2.15.9|4.5.0|OSX 10.11.6|No|
692|2.15.9|4.6.0|OSX 10.12.3|No|
693|2.15.11|4.6.2|Ubuntu 14.04|No|
694|2.15.11|4.7.0|Ubuntu 14.04|Yes|
695|3.5.3|4.2.1|Windows 10|Yes|
696|3.8.6|6.10.0|Windows Server 2012 R2|Yes|
697|3.10.3|6.4.0|OSX 10.11.6|Yes|
698|3.10.9|6.9.2|Ubuntu 14.04|Yes|
699|4.0.5|6.4.0|OSX 10.11.6|Yes|
700|4.1.2|7.5.0|OSX 10.12.2|No|
701|4.1.2|7.7.3|Ubuntu 14.04|Yes|
702
703## Licensing
704
705This software is licensed with the MIT license.
706
707© 2016-2021 Erik Barke, Monounity