├── .gitignore ├── README.md ├── bundle.js ├── coverage.png ├── index.html ├── index.ts ├── karma.conf.js ├── package.json ├── src ├── app │ ├── app.controller.ts │ ├── app.module.ts │ └── index.ts └── transformer │ ├── index.ts │ ├── transformer.factory.spec.ts │ ├── transformer.factory.ts │ └── transformer.module.ts ├── tsconfig.json ├── typings.json ├── webpack.config.js └── webpack.config.karma.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | *.pid.lock 11 | 12 | # Directory for instrumented libs generated by jscoverage/JSCover 13 | lib-cov 14 | 15 | # Coverage directory used by tools like istanbul 16 | coverage 17 | 18 | # nyc test coverage 19 | .nyc_output 20 | 21 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 22 | .grunt 23 | 24 | # node-waf configuration 25 | .lock-wscript 26 | 27 | # Compiled binary addons (http://nodejs.org/api/addons.html) 28 | build/Release 29 | 30 | # Dependency directories 31 | node_modules 32 | jspm_packages 33 | 34 | # Optional npm cache directory 35 | .npm 36 | 37 | # Optional REPL history 38 | .node_repl_history 39 | 40 | typings -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # angular-webpack-typescript-karma-coverage 2 | An exemplary project using Angular 1.x, Webpack, TypeScript and Karma (with Coverage). 3 | 4 | ![Code coverage report using TypeScript files as the analyzed source](https://raw.githubusercontent.com/zbicin/angular-webpack-typescript-karma-coverage/master/coverage.png) 5 | 6 | ## How to run? 7 | 0. `npm install -g typings` (if you don't have it installed globally yet). 8 | 1. Clone the repository (i.e. `git clone https://github.com/zbicin/angular-webpack-typescript-karma-coverage.git && cd angular-webpack-typescript-karma-coverage`). 9 | 2. `npm install`. 10 | 3. `typings install`. 11 | 4. `npm start` to see the simple app running. 12 | 5. `npm test` to run karma and generate coverage tests. The latter are located in the `coverage/` directory. 13 | 14 | ## The most interesting parts: 15 | * `webpack.config.js` with `devtool` set to `inline-source-map` and an appropriate entry point: 16 | ```javascript 17 | // webpack.config.js 18 | module.exports = { 19 | entry: 'index.ts', 20 | devtool: 'inline-source-map', 21 | 22 | // ... 23 | } 24 | ``` 25 | * `webpack.config.karma.js` - slightly modified webpack config which is used exclusively by karma: 26 | ```javascript 27 | // webpack.config.karma.js 28 | var webpackConfig = require('./webpack.config.js'); 29 | 30 | webpackConfig.entry = {}; 31 | webpackConfig.module.postLoaders = [ 32 | { 33 | test: /\.ts$/, 34 | loader: 'istanbul-instrumenter-loader', 35 | exclude: [ 36 | 'node_modules', 37 | /\.spec\.ts$/ 38 | ] 39 | } 40 | ] 41 | 42 | module.exports = webpackConfig; 43 | ``` 44 | * `karma.conf.js` using `source-map-support` framework and generating a json coverage report: 45 | ```javascript 46 | // karma.conf.js 47 | var webpackKarmaConfig = require('./webpack.config.karma.js'); 48 | 49 | module.exports = function (config) { 50 | config.set({ 51 | frameworks: ['jasmine', 'source-map-support'], 52 | 53 | files: [ 54 | './index.ts', 55 | './node_modules/angular-mocks/angular-mocks.js', 56 | './src/**/*.spec.ts' 57 | ], 58 | 59 | preprocessors: { 60 | './index.ts': ['webpack'], 61 | './src/**/*.spec.ts': ['webpack'] 62 | }, 63 | 64 | reporters: ['progress', 'coverage'], 65 | 66 | webpack: webpackKarmaConfig, 67 | 68 | coverageReporter: { 69 | reporters: [ 70 | { 71 | type: 'html', 72 | dir: 'coverage/html-js', 73 | subdir: '.' 74 | }, 75 | { 76 | type: 'json', 77 | dir: 'coverage/json', 78 | subdir: '.' 79 | } 80 | ] 81 | } 82 | 83 | // ... 84 | }) 85 | } 86 | ``` 87 | * `tsconfig.json` with `inlineSourceMap` set to `true` and `sourceMap` set to `false`: 88 | ```javascript 89 | // tsconfig.json 90 | { 91 | "compilerOptions": { 92 | "inlineSourceMap": true, 93 | "sourceMap": false 94 | }, 95 | 96 | // ... 97 | } 98 | 99 | ``` 100 | * `remap-istanbul -i coverage/json/coverage-final.json -o coverage/html-ts -t html` being run by `npm test`. It generates an HTML report containing original TypeScript source files, basing on the json report generated by karma-coverage: 101 | ```javascript 102 | // package.json 103 | { 104 | "scripts": { 105 | "start": "http-server -o", 106 | "test": "npm run karma && npm run ts-coverage-remap", 107 | "karma": "karma start", 108 | "ts-coverage-remap": "remap-istanbul -i coverage/json/coverage-final.json -o coverage/html-ts -t html" 109 | }, 110 | 111 | // ... 112 | } 113 | ``` 114 | 115 | ## License 116 | [WTFPL](http://www.wtfpl.net/) 117 | 118 | 119 | -------------------------------------------------------------------------------- /coverage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zbicin/angular-webpack-typescript-karma-coverage/ffdc3eef7bcf182b78160b3fad5555ea4bcf801e/coverage.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | An exemplary project using Angular 1.x, Webpack, TypeScript and Karma (with Coverage) 7 | 8 | 9 | 10 |
11 |

angular-webpack-typescript-karma-coverage

12 |

An exemplary project using Angular 1.x, Webpack, TypeScript and Karma (with Coverage)

13 | 14 |
15 | 16 |
17 |
18 |
19 |
20 | 21 |
22 |
23 | 24 |
25 |
26 | 27 |
28 | 29 |

Result: {{ vm.result }}.

30 |
31 |
32 |
33 | 34 |
35 | 36 |

37 | View on GitHub 38 |

39 |
40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | import './node_modules/angular/angular.js'; 2 | import './node_modules/bootstrap/dist/css/bootstrap.css'; 3 | 4 | let requireAll = (requireContext) => requireContext.keys().map(requireContext); 5 | requireAll(require.context("./src", true, /index\.ts$/)); -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | var webpackKarmaConfig = require('./webpack.config.karma.js'); 2 | 3 | module.exports = function (config) { 4 | config.set({ 5 | 6 | // base path that will be used to resolve all patterns (eg. files, exclude) 7 | basePath: '', 8 | 9 | 10 | // frameworks to use 11 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter 12 | frameworks: ['jasmine', 'source-map-support'], 13 | 14 | 15 | // list of files / patterns to load in the browser 16 | files: [ 17 | './index.ts', 18 | './node_modules/angular-mocks/angular-mocks.js', 19 | './src/**/*.spec.ts' 20 | ], 21 | 22 | 23 | // list of files to exclude 24 | exclude: [ 25 | ], 26 | 27 | 28 | // preprocess matching files before serving them to the browser 29 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor 30 | preprocessors: { 31 | './index.ts': ['webpack'], 32 | './src/**/*.spec.ts': ['webpack'] 33 | }, 34 | 35 | 36 | // test results reporter to use 37 | // possible values: 'dots', 'progress' 38 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter 39 | reporters: ['progress', 'coverage'], 40 | 41 | 42 | // web server port 43 | port: 9876, 44 | 45 | 46 | // enable / disable colors in the output (reporters and logs) 47 | colors: true, 48 | 49 | 50 | // level of logging 51 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 52 | logLevel: config.LOG_WARN, 53 | 54 | 55 | // enable / disable watching file and executing tests whenever any file changes 56 | autoWatch: false, 57 | 58 | 59 | // start these browsers 60 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 61 | browsers: ['PhantomJS'], 62 | 63 | 64 | // Continuous Integration mode 65 | // if true, Karma captures browsers, runs the tests and exits 66 | singleRun: true, 67 | 68 | // Concurrency level 69 | // how many browser should be started simultaneous 70 | concurrency: Infinity, 71 | 72 | webpack: webpackKarmaConfig, 73 | 74 | // optionally, configure the reporter 75 | coverageReporter: { 76 | reporters: [ 77 | { 78 | type: 'html', 79 | dir: 'coverage/html-js', 80 | subdir: '.' 81 | }, 82 | { 83 | type: 'json', 84 | dir: 'coverage/json', 85 | subdir: '.' 86 | } 87 | ] 88 | } 89 | }) 90 | } 91 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-webpack-typescript-karma-coverage", 3 | "version": "1.0.0", 4 | "description": "An exemplary project using Angular 1.x, Webpack, TypeScript and Karma (with Coverage).", 5 | "scripts": { 6 | "start": "http-server -o", 7 | "test": "npm run karma && npm run ts-coverage-remap", 8 | "karma": "karma start", 9 | "ts-coverage-remap": "remap-istanbul -i coverage/json/coverage-final.json -o coverage/html-ts -t html" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/zbicin/angular-webpack-typescript-karma-coverage.git" 14 | }, 15 | "keywords": [ 16 | "angular", 17 | "webpack", 18 | "typescript", 19 | "karma", 20 | "coverage" 21 | ], 22 | "author": "Krzysztof Zbiciński ", 23 | "license": "WTFPL", 24 | "bugs": { 25 | "url": "https://github.com/zbicin/angular-webpack-typescript-karma-coverage/issues" 26 | }, 27 | "homepage": "https://github.com/zbicin/angular-webpack-typescript-karma-coverage#readme", 28 | "dependencies": { 29 | "http-server": "^0.9.0" 30 | }, 31 | "devDependencies": { 32 | "angular": "^1.5.8", 33 | "angular-mocks": "^1.5.8", 34 | "bootstrap": "^3.3.7", 35 | "css-loader": "^0.23.1", 36 | "file-loader": "^0.9.0", 37 | "istanbul-instrumenter-loader": "^0.2.0", 38 | "jasmine": "^2.4.1", 39 | "karma": "^1.1.2", 40 | "karma-coverage": "^1.1.1", 41 | "karma-jasmine": "^1.0.2", 42 | "karma-phantomjs-launcher": "^1.0.1", 43 | "karma-source-map-support": "^1.1.0", 44 | "karma-webpack": "^1.7.0", 45 | "remap-istanbul": "^0.6.4", 46 | "style-loader": "^0.13.1", 47 | "ts-loader": "^0.8.2", 48 | "typescript": "^1.8.10", 49 | "typings": "^1.3.2", 50 | "url-loader": "^0.5.7", 51 | "webpack": "^1.13.1" 52 | 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/app/app.controller.ts: -------------------------------------------------------------------------------- 1 | import * as Transformer from '../transformer'; 2 | 3 | export class AppController { 4 | private input: string; 5 | private method: string; 6 | private result: string; 7 | 8 | public constructor(private transformer: Transformer.ITransformerService) { 9 | this.method = 'toLowerCase'; 10 | this.input = 'Input some chars'; 11 | } 12 | 13 | public transform() { 14 | if (this.method === 'toLowerCase') { 15 | this.result = this.transformer.toLowerCase(this.input); 16 | } 17 | else if (this.method === 'toUpperCase') { 18 | this.result = this.transformer.toUpperCase(this.input); 19 | } 20 | } 21 | } 22 | 23 | angular.module('app') 24 | .controller('AppController', AppController); -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import {} from '../transformer'; 2 | 3 | angular.module('app', ['app.transformer']); -------------------------------------------------------------------------------- /src/app/index.ts: -------------------------------------------------------------------------------- 1 | import './app.module.ts'; 2 | export * from './app.controller.ts'; -------------------------------------------------------------------------------- /src/transformer/index.ts: -------------------------------------------------------------------------------- 1 | import './transformer.module.ts'; 2 | export * from './transformer.factory.ts'; -------------------------------------------------------------------------------- /src/transformer/transformer.factory.spec.ts: -------------------------------------------------------------------------------- 1 | describe('transformer', () => { 2 | let factory; 3 | 4 | beforeEach(() => { 5 | angular.mock.module('app.transformer'); 6 | 7 | angular.mock.inject((transformer) => { 8 | factory = transformer; 9 | }); 10 | }); 11 | 12 | it('should transform to upper case correctly', () => { 13 | let result = factory.toUpperCase('foo'); 14 | 15 | expect(result).toEqual('FOO'); 16 | }); 17 | }); -------------------------------------------------------------------------------- /src/transformer/transformer.factory.ts: -------------------------------------------------------------------------------- 1 | export interface ITransformerService { 2 | toLowerCase(input: string): string; 3 | toUpperCase(input: string): string; 4 | } 5 | 6 | export class TransformerService { 7 | constructor() { } 8 | 9 | toLowerCase(input: string): string { 10 | return input.toLowerCase(); 11 | } 12 | 13 | toUpperCase(input: string): string { 14 | return input.toUpperCase(); 15 | } 16 | } 17 | 18 | angular.module('app.transformer') 19 | .factory('transformer', () => new TransformerService()); 20 | -------------------------------------------------------------------------------- /src/transformer/transformer.module.ts: -------------------------------------------------------------------------------- 1 | angular.module('app.transformer', []); -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "inlineSourceMap": true, 4 | "sourceMap": false 5 | }, 6 | "exclude": [ 7 | "node_modules" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "globalDependencies": { 3 | "angular": "registry:dt/angular#1.5.0+20160802155123", 4 | "angular-mocks": "registry:dt/angular-mocks#1.5.0+20160608104721", 5 | "jasmine": "registry:dt/jasmine#2.2.0+20160621224255", 6 | "jquery": "registry:dt/jquery#1.10.0+20160704162008", 7 | "webpack-env": "registry:dt/webpack-env#1.12.2+20160316155526" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: "./index.ts", 3 | devtool: 'inline-source-map', 4 | output: { 5 | path: __dirname, 6 | filename: "bundle.js" 7 | }, 8 | module: { 9 | loaders: [ 10 | { test: /\.css$/, loader: "style-loader!css-loader" }, 11 | { test: /\.ts$/, loader: "ts-loader" }, 12 | { test: /\.(png|woff|woff2|eot|ttf|svg)$/, loader: 'url-loader' } 13 | ] 14 | } 15 | }; -------------------------------------------------------------------------------- /webpack.config.karma.js: -------------------------------------------------------------------------------- 1 | var webpackConfig = require('./webpack.config.js'); 2 | 3 | webpackConfig.entry = {}; 4 | webpackConfig.module.postLoaders = [ 5 | { 6 | test: /\.ts$/, 7 | loader: 'istanbul-instrumenter-loader', 8 | exclude: [ 9 | 'node_modules', 10 | /\.spec\.ts$/ 11 | ] 12 | } 13 | ] 14 | 15 | module.exports = webpackConfig; --------------------------------------------------------------------------------