Security News
How Threat Actors are Abusing GitHub’s File Upload Feature to Host Malware
GitHub is susceptible to a CDN flaw that allows attackers to host malware on any public repository.
karma-typescript
Advanced tools
Readme
Karma :heart: Typescript
The easiest way is to keep karma-typescript
as a devDependency in package.json
:
{
"devDependencies": {
"karma": "^6.1.0",
"karma-typescript": "5.5.4"
}
}
Do this by installing the plugin via npm:
npm install --save-dev karma-typescript
Bare minimum configuration can be achieved with the following karma.conf.js
file:
module.exports = function(config) {
config.set({
frameworks: ["jasmine", "karma-typescript"],
files: [
"src/**/*.ts" // *.tsx for React Jsx
],
preprocessors: {
"**/*.ts": "karma-typescript" // *.tsx for React Jsx
},
reporters: ["progress", "karma-typescript"],
browsers: ["Chrome"]
});
};
The above example will compile all Typescript files and run the unit tests, producing remapped coverage in ./coverage
.
The plugin has default settings for the compiler, instrumenting files and creating reports etc, which should suit most needs.
These are the default compiler settings:
karmaTypescriptConfig: {
compilerOptions: {
emitDecoratorMetadata: true,
experimentalDecorators: true,
jsx: "react",
module: "commonjs",
sourceMap: true,
target: "ES5"
},
exclude: ["node_modules"]
}
If the defaults aren't enough, the settings can be configured from karma.conf.js
:
karmaTypescriptConfig.bundlerOptions.addNodeGlobals - Boolean indicating whether the global variables
process
and Buffer
should be added to the bundle.
Defaults to true
.
karmaTypescriptConfig.bundlerOptions.acornOptions - An object literal with keys/values which are passed as configuration
options to the Acorn parser used by the bundler. The most notable of these keys is
ecmaScript
which sets the ECMAScript target used by the parser. If code has dependencies that use a newer version of
ECMAScript than the bundler defaults to (ES5), parsing errors will result when the source-reader tries to bundle dependencies
(e.g. dependencies that use bigint
literals like 1n
will cause an error during code compilation unless this option is
explicitly set to 11(ES2020). A complete list of options can be found in the Acorn documentation.
karmaTypescriptConfig.bundlerOptions.constants - An object literal with keys/values which will be available as global
variables in the bundle. The keys are expected to be strings and any non-string value will be stringified with JSON.stringify
.
Configuration example:
constants: {
__STRING__: JSON.stringify("abc" + 123),
__BOOLEAN__: true,
"process.env": {
"VARIABLE": "value"
}
}
Code example:
declare var __STRING__: string;
declare var __BOOLEAN__: boolean;
console.log(__STRING__, __BOOLEAN__, process.env.VARIABLE);
karmaTypescriptConfig.bundlerOptions.entrypoints - A RegExp
filtering which files loaded by Karma should be executed in
a test run, for example only filenames ending with ".spec.ts": /\.spec\.ts$/
.
This setting can be used to make sure the specs have finished setting up the test environment before other code starts
requiring modules, which otherwise could lead to subtle bugs caused by race conditions.
When filtering file paths, beware that Windows uses \
while UNIX-like systems use /
as path separator.
Defaults to all files, /.*/
.
karmaTypescriptConfig.bundlerOptions.exclude - An array of npm module names that will be excluded from the bundle.
karmaTypescriptConfig.bundlerOptions.ignore - An array of npm module names that will be bundled as stubs, ie module.exports = {};
.
karmaTypescriptConfig.bundlerOptions.noParse - An array of module names that will be bundled without being parsed for dependencies.
karmaTypescriptConfig.bundlerOptions.resolve.alias - An object literal where the key is a module name
and the value is a path that will be used when resolving the module.
The key is a string.
karmaTypescriptConfig.bundlerOptions.resolve.extensions - An array of file extensions to use, in order, when resolving modules.
Defaults to [".js", ".json", ".mjs", ".ts", ".tsx"]
.
karmaTypescriptConfig.bundlerOptions.resolve.directories - An array of directories where modules will be recursively looked up.
Defaults to ["node_modules"]
.
karmaTypescriptConfig.bundlerOptions.sourceMap - A boolean indicating whether source maps should be generated for imported modules in the bundle, useful for debugging in a browser.
For more debugging options, please see karmaTypescriptConfig.coverageOptions.instrumentation
.
Defaults to false
.
karmaTypescriptConfig.bundlerOptions.transforms - An array of functions altering or replacing compiled Typescript code/Javascript
code loaded from node_modules
before bundling it.
For more detailed documentation on transforms, please refer to the Transforms API section in this document.
karmaTypescriptConfig.bundlerOptions.validateSyntax - A boolean indicating whether the syntax of the bundled code should be validated.
Setting this to false
may speed up bundling for large projects with lots of imports from node_modules
.
Defaults to true
.
karmaTypescriptConfig.compilerDelay - The number of milliseconds the compiler waits before compiling the project on each run.
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.
Defaults to 250 ms.
karmaTypescriptConfig.compilerOptions - This setting will override or add to existing compiler options.
Valid options are the same as for the compilerOptions
section in tsconfig.json
, with the
exception of outDir
and outFile
which are ignored since the code is compiled in-memory.
If noEmitOnError
is set to a truthy value, in either tsconfig.json
or in karmaTypescriptConfig.compilerOptions
,
the karma process will exit with ts.ExitStatus.DiagnosticsPresent_OutputsSkipped
if any compilation errors occur.
karmaTypescriptConfig.coverageOptions.instrumentation - A boolean indicating whether the code should be instrumented,
set this property to false
to see the original Typescript code when debugging.
Please note that setting this property to true
requires the Typescript compiler option sourceMap
to also be set to true
.
For more debugging options, please see karmaTypescriptConfig.coverageOptions.sourceMap
.
Defaults to true
.
karmaTypescriptConfig.coverageOptions.instrumenterOptions - Pass options to the istanbul
instrumenter, ie options supported by istanbul-lib-instrument:
{
// Name of global coverage variable.
coverageVariable: '__coverage__',
// Preserve comments in output.
preserveComments: false,
// Generate compact code.
compact: true,
// Set to true to instrument ES6 modules.
esModules: false,
// Set to true to allow `return` statements outside of functions.
autoWrap: false,
// Set to true to produce a source map for the instrumented code.
produceSourceMap: false,
// Set to array of class method names to ignore for coverage.
ignoreClassMethods: [],
// A callback function that is called when a source map URL is found in the original code.
// This function is called with the source file name and the source map URL.
sourceMapUrlCallback: null,
// Turn debugging on.
debug: false,
// Set plugins.
plugins: [
'asyncGenerators',
'bigInt',
'classProperties',
'classPrivateProperties',
'dynamicImport',
'importMeta',
'objectRestSpread',
'optionalCatchBinding',
'flow',
'jsx'
]
};
karmaTypescriptConfig.coverageOptions.exclude - A RegExp
object or an array of RegExp
objects for filtering which files should be excluded from coverage instrumentation.
When filtering file paths, beware that Windows uses \
while UNIX-like systems use /
as path separator.
Defaults to /\.(d|spec|test)\.ts$/i
which excludes *.d.ts, *.spec.ts and *.test.ts (case insensitive).
karmaTypescriptConfig.coverageOptions.threshold - An object with minimum coverage thresholds. The threshold values can be set on
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.
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.
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.
threshold: {
global: {
statements: 100,
branches: 100,
functions: -10,
lines: 100,
excludes: [
"src/foo/**/*.js"
]
},
file: {
statements: -10,
branches: 100,
functions: 100,
lines: 100,
excludes: [
"src/bar/**/*.js"
],
overrides: {
"src/file.js": {
statements: 90
}
}
}
}
karmaTypescriptConfig.coverageOptions.watermarks - An object with custom istanbul watermarks. Each value is an array consisting of 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. If code coverage is below the lower bound, this is considered "unhealthy", and many reports will print output in red. Yellow output is reserved for coverage in between the lower and upper bound.
watermarks: {
lines: [75, 90],
functions: [75, 90],
branches: [75, 90],
statements: [75, 90]
}
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.
{
mode: "merge|replace",
values: ["foo", "bar"]
}
Defaults to ["node_modules"]
.
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.
{
mode: "merge|replace",
values: ["foo", "bar"]
}
This option is available in Typescript ^2.0.0.
karmaTypescriptConfig.reports - The types of coverage reports that should be created when running the tests,
defaults to an html report in the directory ./coverage
.
Reporters are configured as "reporttype": destination
where the destination can be specified in three ways:
string
with a directory path, for example "html": "coverage"
.null
. Writes the output to the console, for example "text-summary": ""
. This is only possible for a subset of the reports available.object
with more fine-grained control over path and filename:"cobertura": {
"directory": "coverage", // optional, defaults to 'coverage'
"subdirectory": "cobertura" // optional, defaults to the name of the browser running the tests
"filename": "coverage.xml", // optional, defaults to the report name
}
// "subdirectory" may also be a function that returns a directory from a given browser
"cobertura": {
"directory": "coverage",
"subdirectory": function(browser) {
// normalizes browser name directories to lowercase without version
// ex: coverage/chrome/coverage.xml
return browser.name.toLowerCase().split(' ')[0];
},
"filename": "coverage.xml"
}
Available report types:
"clover": destination
"cobertura": destination
"html": destination
"html-spa": destination
"json-summary": destination
"json": destination
"lcovonly": destination
"teamcity": destination
(redirects to the console with destination "" or null
)"text-lcov": destination
(redirects to the console with destination "" or null
)"text-summary": destination
(redirects to the console with destination "" or null
)"text": destination
(redirects to the console with destination "" or null
)Example of the three destination types:
karmaTypescriptConfig: {
reports:
{
"cobertura": {
"directory": "coverage",
"filename": "coverage.xml",
"subdirectory": "cobertura"
},
"html": "coverage",
"text-summary": ""
}
}
karmaTypescriptConfig.transformPath - A function for renaming compiled file extensions to .js
.
Defaults to renaming .ts
and .tsx
to .js
.
karmaTypescriptConfig.tsconfig - A path to a tsconfig.json
file.
The default compiler options will be replaced by the options in this file.
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
compiler base path instead.
karmaTypescriptConfig.stopOnFailure - Stop on any compiler error.
By default karma will stop when any typescript compile errors are encountered.
Setting this to false will allow tests to be run when typescript compile errors are present.
Example of a full karmaTypescriptConfig
configuration:
karmaTypescriptConfig: {
bundlerOptions: {
addNodeGlobals: true,
constants: {
__PRODUCTION__: false
},
entrypoints: /\.spec\.(ts|tsx)$/,
exclude: ["react/addons"],
ignore: ["ws"],
noParse: "jquery",
resolve: {
alias: {
"@angular/upgrade/static$": "../bundles/upgrade-static.umd.js"
},
extensions: [".js", ".json"],
directories: ["node_modules"]
},
sourceMap: false,
transforms: [require("karma-typescript-es6-transform")()],
validateSyntax: true
},
compilerDelay: 500,
compilerOptions: {
noImplicitAny: true,
},
coverageOptions: {
instrumentation: true,
instrumenterOptions: {
preserveComments: true
},
exclude: /\.(d|spec|test)\.ts/i,
threshold: {
global: {
statements: 100,
branches: 100,
functions: -10,
lines: 100,
excludes: [
"src/foo/**/*.js"
]
},
file: {
statements: -10,
branches: 100,
functions: 100,
lines: 100,
excludes: [
"src/bar/**/*.js"
],
overrides: {
"src/file.js": {
statements: 90
}
}
}
},
},
exclude: ["broken"],
include: {
mode: "replace",
values: ["**/*.ts"]
},
reports: {
"cobertura": {
"directory": "coverage",
"filename": "cobertura/coverage.xml"
},
"html": "coverage",
"text-summary": ""
},
transformPath: function(filepath) {
return filepath.replace(/\.(ts|tsx)$/, ".js");
},
tsconfig: "./tsconfig.json",
stopOnFailure: false
}
Files executed in the test run are bundled into a main bundle, containing dependencies required from node_modules,
and several smaller standalone bundles containing the Typescript files. All these bundles are tied together by commonjs.js
,
which acts as a hub, loading modules when they are required by other modules.
All files are bundled by being wrapped in a custom CommonJS wrapper, which emulates the Node.js module system by injecting the require function, the module object, the exports object, the __dirname variable and the __filename variable.
For instance, this Typescript sample:
export function exportedFunction(): string {
return "";
}
Would be compiled to the following JavaScript (assuming the compiler option module
is set to commonjs
):
function exportedFunction() {
return "";
}
exports.exportedFunction = exportedFunction;
It would then be wrapped in a CommonJS
wrapper by the bundler:
(function(global){
global.wrappers['/absolutepath/app/src/file.ts']=[function(require,module,exports,__dirname,__filename){
function exportedFunction() {
return "";
}
exports.exportedFunction = exportedFunction;
},'src/file.ts',{}];
})(this);
(In this example, the source map and a few other statements have been omitted for brevity and the wrapper has been formatted for readability)
After compilation, a simple static analysis is performed to find "import" and "require" statements in the code and if any
dependencies are found, for instance import { Component } from "@angular/core";
, it is added to the main bundle file along
with its dependencies.
If no import or require statements are found in any Typescript file included in the test run, or the compiler option module
is set to another value than commonjs
, automatic bundling will not occur.
This means that no Typescript file will be wrapped in the CommonJS wrapper and the reason behind this is the encapsulation that the Node.js module system provides. If no module requests any other module, the test run would contain only isolated islands of code unreachable from the global scope, there would be nothing to execute.
However, this intentional behavior makes it possible to use karma-typescript for projects that use the Typescript module system,
or have the compiler option module
set to another value than commonjs
, or simply put everything on the global scope.
Style files (.css|.less|.sass|.scss) are served as JSON strings to the browser running the tests,
allowing styles to be loaded using the Typescript import statement, ie import "./style/app.scss";
.
This means styles can be imported in order to let, for instance, webpack load the styles with less-loader or scss-loader etc for bundling later on, without breaking the unit test runner.
Note: JSON required by modules in node_modules will be loaded automatically by the bundler.
module: {
exports: {},
id: "project-relative-path/bar.ts",
uri: "/absolute-path/project-relative-path/bar.ts"
}
The module.id
will be calculated from the value of module.uri
, relative to the Karma config basePath
value.
Modules exporting an extensible object such as a function or an object literal will also be decorated with
a non-enumerable default
property if module.exports.default
is undefined.
A full Node.js environment will be provided with global variables and browser shims for builtin core modules:
The plugin uses browser-resolve from the browserify tool chain to load the source code from node_modules.
Imported modules, local or npm packages, can be mocked using karma-typescript-mock. This feature is available in karma-typescript@^3.0.5
.
The bundler has a public API which lets plugins alter or completely replace code before adding it to the bundle.
For example, a plugin could compile ES2015 JavaScript code to to ES5 syntax, making it possible to import an npm
module
written in ES2015 syntax from a Typescript module directly.
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.
The plugin functions in the transforms array are asynchronous and adhere to the Node.js callback convention where the first
argument of the callback function is an Error
object or undefined
and the following parameters contains the result.
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.
Transforms will be executed at two points in the bundling process: right after compilation of the project Typescript files
and when resolving import
and require
statements. This means each transforming function will be called for both
Typescript files and JavaScript files from node_modules
, making each plugin implementation responsible for validating the
context before performing any logic, for example by checking the file name, module name or the existence of an ast object etc.
Each transforming function will be executed before resolving dependencies, which means paths in import
or require
statements
or anywhere in the code can be rewritten before bundling, to fit the Karma execution environment.
Example of a simple inline transforming function replacing the contents of a .css
file, mimicking the behavior of Css Modules:
karmaTypescriptConfig: {
bundlerOptions: {
transforms: [
function(context, callback) {
if(context.module === "./main.css") {
context.source = "module.exports = { color: red };";
return callback(undefined, true);
}
return callback(undefined, false);
}
]
}
}
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:
karmaTypescriptConfig: {
bundlerOptions: {
transforms: [
function(context, callback) {
if(context.ts) {
context.ts.transpiled = "\n/* istanbul ignore next */\n" + context.ts.transpiled;
return callback(undefined, true, false);
}
return callback(undefined, false);
}
]
}
}
The context object, TransformContext
, is defined here.
The callback has two signatures, the "boolean" and the "object".
The boolean callback function has three arguments:
Error
object or undefined
context.source
has changed or not.The object callback function has two arguments:
Error
object or undefined
context.source
has changed or not.Typescript ^1.6.2 is required.
Versions 1.6.2 - 1.7.5 work but aren't as heavily tested as versions 1.8.10 and up.
Users have reported success by simply deleting the node_modules
folder and then running npm install
again.
Note: this error has been fixed in karma-typescript@^3.0.0`.
This error seems to hit mostly users of with older versions of npm
, where all dependencies don't get pulled in automatically by npm
.
There's a workaround reported by users, which is simply adding the missing dependencies explicitly to package.json
:
npm install --save-dev browser-resolve
npm install --save-dev buffer
npm install --save-dev process
Other workarounds are running npm install
twice or, if possible, upgrading to a newer version of npm
.
These are the environments reported failing/working:
Npm | Node.js | OS | Works |
---|---|---|---|
2.5.18 | 4.4.7 | Unknown | No |
2.14.7 | 4.2.1 | Ubuntu 14.04 | No |
2.14.12 | 4.2.6 | OSX 10.11.3 | No |
2.15.9 | 4.5.0 | OSX 10.11.6 | No |
2.15.9 | 4.6.0 | OSX 10.12.3 | No |
2.15.11 | 4.6.2 | Ubuntu 14.04 | No |
2.15.11 | 4.7.0 | Ubuntu 14.04 | Yes |
3.5.3 | 4.2.1 | Windows 10 | Yes |
3.8.6 | 6.10.0 | Windows Server 2012 R2 | Yes |
3.10.3 | 6.4.0 | OSX 10.11.6 | Yes |
3.10.9 | 6.9.2 | Ubuntu 14.04 | Yes |
4.0.5 | 6.4.0 | OSX 10.11.6 | Yes |
4.1.2 | 7.5.0 | OSX 10.12.2 | No |
4.1.2 | 7.7.3 | Ubuntu 14.04 | Yes |
This software is licensed with the MIT license.
© 2016-2021 Erik Barke, Monounity
FAQs
Simplifying running unit tests with coverage for Typescript projects.
The npm package karma-typescript receives a total of 55,826 weekly downloads. As such, karma-typescript popularity was classified as popular.
We found that karma-typescript demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
GitHub is susceptible to a CDN flaw that allows attackers to host malware on any public repository.
Security News
At Node Congress, Socket CEO Feross Aboukhadijeh uncovers the darker aspects of open source, where applications that rely heavily on third-party dependencies can be exploited in supply chain attacks.
Research
Security News
The Socket Research team found this npm package includes code for collecting sensitive developer information, including your operating system username, Git username, and Git email.