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 |
|
17 | The 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 |
|
28 | Do this by installing the plugin via npm:
|
29 |
|
30 | ```
|
31 | npm install --save-dev karma-typescript
|
32 | ```
|
33 |
|
34 | ## Configuration
|
35 |
|
36 | Bare minimum configuration can be achieved with the following `karma.conf.js` file:
|
37 |
|
38 | ```javascript
|
39 | module.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 |
|
54 | The 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 |
|
92 | The plugin has default settings for the compiler, instrumenting files and creating reports etc, which should suit most needs.
|
93 |
|
94 | These are the default compiler settings:
|
95 |
|
96 | ```javascript
|
97 | karmaTypescriptConfig: {
|
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 |
|
110 | If 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 *.d.ts, *.spec.ts and *.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 |
|
382 | Example of a full `karmaTypescriptConfig` configuration:
|
383 |
|
384 | ```javascript
|
385 | karmaTypescriptConfig: {
|
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 |
|
465 | Files executed in the test run are bundled into a main bundle, containing dependencies required from node_modules,
|
466 | and several smaller standalone bundles containing the Typescript files. All these bundles are tied together by `commonjs.js`,
|
467 | which acts as a hub, loading modules when they are required by other modules.
|
468 |
|
469 | All files are bundled by being wrapped in a custom [CommonJS](https://en.wikipedia.org/wiki/CommonJS) wrapper,
|
470 | which emulates the Node.js module system by injecting the require function, the module object, the exports object,
|
471 | the __dirname variable and the __filename variable.
|
472 |
|
473 | For instance, this Typescript sample:
|
474 |
|
475 | ```javascript
|
476 | export function exportedFunction(): string {
|
477 | return "";
|
478 | }
|
479 | ```
|
480 |
|
481 | Would be compiled to the following JavaScript (assuming the compiler option `module` is set to `commonjs`):
|
482 |
|
483 | ```javascript
|
484 | function exportedFunction() {
|
485 | return "";
|
486 | }
|
487 | exports.exportedFunction = exportedFunction;
|
488 | ```
|
489 |
|
490 | It 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 |
|
505 | After compilation, a simple static analysis is performed to find "import" and "require" statements in the code and if any
|
506 | dependencies are found, for instance `import { Component } from "@angular/core";`, it is added to the main bundle file along
|
507 | with its dependencies.
|
508 |
|
509 | If no import or require statements are found in any Typescript file included in the test run, or the compiler option `module`
|
510 | is set to another value than `commonjs`, *automatic bundling will not occur*.
|
511 |
|
512 | This means that no Typescript file will be wrapped in the CommonJS wrapper and the reason behind this is the encapsulation that
|
513 | the Node.js module system provides. If no module requests any other module, the test run would contain only isolated islands of
|
514 | code unreachable from the global scope, there would be nothing to execute.
|
515 |
|
516 | However, this intentional behavior makes it possible to use karma-typescript for projects that use the Typescript module system,
|
517 | or 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 |
|
521 | Style files (.css|.less|.sass|.scss) are served as JSON strings to the browser running the tests,
|
522 | allowing styles to be loaded using the Typescript import statement, ie `import "./style/app.scss";`.
|
523 |
|
524 | This means styles can be imported in order to let, for instance, webpack load the styles with
|
525 | less-loader or scss-loader etc for bundling later on, without breaking the unit test runner.
|
526 |
|
527 | Note: JSON required by modules in node_modules will be loaded automatically by the bundler.
|
528 |
|
529 | ### The module object
|
530 |
|
531 | ```javascript
|
532 | module: {
|
533 | exports: {},
|
534 | id: "project-relative-path/bar.ts",
|
535 | uri: "/absolute-path/project-relative-path/bar.ts"
|
536 | }
|
537 | ```
|
538 |
|
539 | The `module.id` will be calculated from the value of `module.uri`, relative to the Karma config `basePath` value.
|
540 |
|
541 | Modules exporting an extensible object such as a *function* or an *object literal* will also be decorated with
|
542 | a non-enumerable `default` property if `module.exports.default` is undefined.
|
543 |
|
544 | ### Globals
|
545 |
|
546 | A full Node.js environment will be provided with global variables and browser shims for builtin core modules:
|
547 |
|
548 | * __dirname
|
549 | * __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 |
|
577 | The 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
|
580 | Imported 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 |
|
584 | The bundler has a public API which lets plugins alter or completely replace code before adding it to the bundle.
|
585 | For example, a plugin could compile ES2015 JavaScript code to to ES5 syntax, making it possible to import an `npm` module
|
586 | written in ES2015 syntax from a Typescript module directly.
|
587 |
|
588 | The 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 |
|
590 | The plugin functions in the transforms array are asynchronous and adhere to the Node.js callback convention where the first
|
591 | argument of the callback function is an `Error` object or `undefined` and the following parameters contains the result.
|
592 | However, 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 |
|
594 | Transforms will be executed at two points in the bundling process: right after compilation of the project Typescript files
|
595 | and when resolving `import` and `require` statements. This means each transforming function will be called for both
|
596 | Typescript files and JavaScript files from `node_modules`, making each plugin implementation responsible for validating the
|
597 | context before performing any logic, for example by checking the file name, module name or the existence of an ast object etc.
|
598 |
|
599 | Each transforming function will be executed before resolving dependencies, which means paths in `import` or `require` statements
|
600 | or anywhere in the code can be rewritten before bundling, to fit the Karma execution environment.
|
601 |
|
602 | Example of a simple inline transforming function replacing the contents of a `.css` file, mimicking the behavior of Css Modules:
|
603 |
|
604 | ```javascript
|
605 | karmaTypescriptConfig: {
|
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 |
|
620 | It 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
|
623 | karmaTypescriptConfig: {
|
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
|
639 | The context object, `TransformContext`, is defined [here](https://github.com/monounity/karma-typescript/blob/master/src/api/transforms.ts).
|
640 |
|
641 | ### Callback
|
642 |
|
643 | The callback has two signatures, the "boolean" and the "object".
|
644 |
|
645 | The boolean callback function has three arguments:
|
646 | 1. An `Error` object or `undefined`
|
647 | 2. A boolean indicating whether the value of `context.source` has changed or not.
|
648 | 3. A boolean indicating whether the transformed source should be recompiled. Defaults to true and can be omitted.
|
649 |
|
650 | The object callback function has two arguments:
|
651 |
|
652 | 1. An `Error` object or `undefined`
|
653 | 2. 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 |
|
660 | Typescript ^1.6.2 is required.
|
661 |
|
662 | Versions 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 |
|
668 | Users 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 |
|
674 | This error seems to hit mostly users of with older versions of `npm`, where all dependencies don't get pulled in automatically by `npm`.
|
675 |
|
676 | There'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 |
|
682 | Other workarounds are running `npm install` twice or, if possible, upgrading to a newer version of `npm`.
|
683 |
|
684 | These 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 |
|
705 | This software is licensed with the MIT license.
|
706 |
|
707 | © 2016-2021 Erik Barke, Monounity
|