Skip to content

Instantly share code, notes, and snippets.

@eheikes
Last active October 28, 2023 14:51
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eheikes/83b04b336de05ae793367385980712e4 to your computer and use it in GitHub Desktop.
Save eheikes/83b04b336de05ae793367385980712e4 to your computer and use it in GitHub Desktop.
Karma test runner with Jasmine + TypeScript + browser

This is an example setup for using the Karma test runner with a browser-based project written in TypeScript, using Jasmine as the test framework.

Known Issues:

  • Jasmine's fdescribe/fit doesn't work as expected; see note and workaround in the karma.conf.js below.
  • Karma won't restart if a declaration in types changes.
// test/file.spec.ts
// Example of mocking using karma-typescript-mock
import { JasmineKarmaTypeScriptMocker as mock } from 'karma-typescript-mock'
import { readFile } from '../../src/file'
import { sampleTransactions } from '../fixtures/transactions'
describe('readFile()', () => {
describe('when the file is read successfully', () => {
let file: File
mock('./file-loaders/csv-loader', {
loadCsv: () => () => Promise.resolve(sampleTransactions)
})
beforeEach(async () => {
file = new File(['test file'], 'test.csv', { type: 'text/csv' })
results = await readFile(file)
})
it('should resolve with an array of transactions', () => {
expect(results).toEqual(sampleTransactions)
})
})
})
// types/jasmine-matchers.d.ts
declare namespace jasmine {
interface Matchers<T> {
// Add custom matchers to the definition.
toBeTransaction(): boolean
}
}
// types/karma-typescript-mock.d.ts
// karma-typescript-mock doesn't have built-in or DT types
declare module 'karma-typescript-mock'
// test/karma.conf.js
module.exports = config => {
config.set({
frameworks: ['jasmine', 'karma-typescript'],
basePath: '..',
files: [
'src/**/*.ts',
'src/**/*.tsx',
'test/helpers/*.ts',
'test/*.ts'
],
exclude: [
'src/index.ts' // untestable main "boot" file
],
preprocessors: {
'**/*.ts': 'karma-typescript',
'**/*.tsx': 'karma-typescript'
},
karmaTypescriptConfig: {
tsconfig: 'tsconfig.json',
bundlerOptions: {
// Because of the way Karma works, Jasmine's focus specs (fdescribe, fit)
// will only focus tests for their own file.
// Use the "entrypoints" property to restrict the test files that are run.
// entrypoints: /date\.spec\.ts$/
},
// Modify the "coverageOptions" and "reports" as desired.
coverageOptions: {
threshold: {
global: {
statements: 95,
branches: 95,
functions: 95,
lines: 95
}
},
exclude: [/^test[\/\\]/], // forward slash on *nix/Mac, backslash on Windows
},
reports: {
html: 'coverage',
'text-summary': ''
}
},
// Use the karma-spec-reporter for results, and include karma-typescript to see the coverage results.
reporters: ['spec', 'karma-typescript'],
// Enable the following line to debug Karma problems.
// logLevel: config.LOG_DEBUG,
// Create a custom Chrome launcher that removes the sandbox security (which is okay for testing).
browsers: ['ChromeHeadlessNoSandbox'],
customLaunchers: {
ChromeHeadlessNoSandbox: {
base: 'ChromeHeadless',
flags: ['--no-sandbox']
}
}
// Enable the following section to hide console.log() output from the browser.
/*
browserConsoleLogOptions: {
level: 'info',
terminal: false
}
*/
})
}
// test/helpers/matchers.ts
// Example of Jasmine custom matcher
export const toBeTransaction: jasmine.CustomMatcherFactory = () => {
return {
compare: (actual: any) => {
// implementation here
}
}
}
{
"name": "example-project",
"version": "1.0.0",
"scripts": {
"test": "karma start test/karma.conf.js --single-run",
"test:watch": "karma start test/karma.conf.js --auto-watch"
},
"devDependencies": {
"@types/jasmine": "^2.8.6",
"cross-env": "^5.1.5",
"jasmine-core": "^3.1.0",
"karma": "^2.0.2",
"karma-chrome-launcher": "^2.2.0",
"karma-jasmine": "^1.1.1",
"karma-spec-reporter": "^0.0.32",
"karma-typescript": "^3.0.12",
"karma-typescript-mock": "^1.0.1",
}
}
{
"compilerOptions": {
"outDir": "./dist/",
"module": "commonjs", // required for tests
"target": "es5",
"strict": true,
"sourceMap": true,
"jsx": "react",
"lib": [
"es2015",
"es2016",
"es2017",
"dom"
]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment