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