Skip to content

Commit

Permalink
fix(preprocessor): Support CoffeeScript when using RequireJS
Browse files Browse the repository at this point in the history
Adds support for using RequireJS with CoffeeScript code by changing
the file extension from `.coffee` to `.js`. RequireJS automatically
adds the `.js` suffix to files and it doesn't seem possible to change
it.

Closes karma-runner#177
  • Loading branch information
Lloyd Smith II committed Nov 14, 2015
1 parent d1d7087 commit e941e0c
Show file tree
Hide file tree
Showing 11 changed files with 166 additions and 2 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,11 @@ module.exports = function(config) {
### CoffeeScript

For an example on how to use with [CoffeeScript](http://coffeescript.org/)
see [examples/coffee](examples/coffee).
see [examples/coffee](examples/coffee). For an example of how to use with
CoffeeScript and the RequireJS module loader, see
[examples/coffee-requirejs](examples/coffee-requirejs) (and also see
the `useJSExtensionForCoffeeScript` option in
[docs/configuration.md](docs/configuration.md)).

### Advanced, multiple reporters

Expand Down
23 changes: 23 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,3 +220,26 @@ coverageReporter: {
}
}
```

### `useJSExtensionForCoffeeScript`

**Type:** boolean

**Description:** If set to `true`, then CoffeeScript files instrumented
with [Ibrik](https://github.com/Constellation/ibrik) will use the `.js`
extension for the transpiled source (without this option, the JavaScript
files will keep the original `.coffee` extension). This option is required
if you use a module loader such as [RequireJS](http://requirejs.org/) that
expects files to use a `.js` extension.

Example of using RequireJS with CoffeeScript:

```coffeescript
coverageReporter:
useJSExtensionForCoffeeScript: true
instrumenters:
ibrik : require('ibrik')
instrumenter:
'**/*.coffee': 'ibrik'
# ...
```
9 changes: 9 additions & 0 deletions examples/coffee-requirejs/calculator.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
define [], ->

# Some code under test
plus: (a, b) ->
a + b

# not covered
minus: (a, b) ->
a - b
53 changes: 53 additions & 0 deletions examples/coffee-requirejs/karma.conf.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
module.exports = (config) ->
config.set
frameworks: ['mocha', 'requirejs']

files: [
# We do not want any files to execute automatically
{pattern: 'calculator.coffee', included: false}
{pattern: 'test.coffee', included: false}

# Except for this one. This one shall execute.
'requirejs.karma.coffee'
]

browsers: ['Firefox']

coffeePreprocessor:
options:
sourceMap: true

preprocessors:
# source files, that you wanna generate coverage for
# do not include tests or libraries
# (these files will be instrumented by Istanbul via Ibrik unless
# specified otherwise in coverageReporter.instrumenter)
'calculator.coffee': 'coverage'

# note: project files will already be converted to
# JavaScript via coverage preprocessor.
# Thus, you'll have to limit the CoffeeScript preprocessor
# to uncovered files.
'test.coffee': 'coffee'
'requirejs.karma.coffee': 'coffee'

coverageReporter:
type: 'text-summary'
useJSExtensionForCoffeeScript: true
instrumenters:
ibrik : require('ibrik')
instrumenter:
'**/*.coffee': 'ibrik'

# coverage reporter generates the coverage
reporters: ['dots', 'coverage']

plugins: [
require('../../lib/index')
'karma-mocha'
'karma-requirejs'
'karma-coffee-preprocessor'
'karma-firefox-launcher'
]

singleRun: true
22 changes: 22 additions & 0 deletions examples/coffee-requirejs/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "karma-coverage-coffee-example",
"version": "1.0.0",
"description": "Demonstrate the usage of karma-coverage with CoffeeScript",
"main": "",
"scripts": {
"test": "./node_modules/karma/bin/karma start"
},
"author": "Lloyd Smith II <lloyd.smith@gmail.com>",
"license": "MIT",
"dependencies": {},
"devDependencies": {
"coffee-script": "latest",
"ibrik": "^2.0.0",
"karma": "^0.13.9",
"karma-coffee-preprocessor": "latest",
"karma-firefox-launcher": "latest",
"karma-mocha": "latest",
"karma-requirejs": "^0.2.2",
"requirejs": "^2.1.20"
}
}
6 changes: 6 additions & 0 deletions examples/coffee-requirejs/requirejs.karma.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# A minimal requirejs configuration
require.config
baseUrl: '/base'
deps: ['test']
callback: ->
window.__karma__.start()
9 changes: 9 additions & 0 deletions examples/coffee-requirejs/test.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
define ['calculator'], (calculator) ->

describe 'calculator', ->

it 'should pass', ->
true is true

it 'should work', ->
calculator.plus(1, 2) is 3
3 changes: 3 additions & 0 deletions gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ module.exports = function (grunt) {
karma: {
coffee: {
configFile: 'examples/coffee/karma.conf.coffee'
},
coffeeRequireJS: {
configFile: 'examples/coffee-requirejs/karma.conf.coffee'
}
},
eslint: {
Expand Down
7 changes: 7 additions & 0 deletions lib/preprocessor.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@ function createCoveragePreprocessor (logger, helper, basePath, reporters, covera
var instrumenterOverrides = {}
var instrumenters = {istanbul: istanbul}
var includeAllSources = false
var useJSExtensionForCoffeeScript = false

if (coverageReporter) {
instrumenterOverrides = coverageReporter.instrumenter
instrumenters = extend({istanbul: istanbul}, coverageReporter.instrumenters)
includeAllSources = coverageReporter.includeAllSources === true
useJSExtensionForCoffeeScript = coverageReporter.useJSExtensionForCoffeeScript === true
}

var sourceCache = globalSourceCache.get(basePath)
Expand Down Expand Up @@ -137,6 +139,11 @@ function createCoveragePreprocessor (logger, helper, basePath, reporters, covera
}
}

// RequireJS expects JavaScript files to end with `.js`
if (useJSExtensionForCoffeeScript && instrumenterLiteral === 'ibrik') {
file.path = file.path.replace(/\.coffee$/, '.js')
}

done(instrumentedCode)
})
}
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@
"mocha": "^2.2.5",
"mocks": "0.0.15",
"sinon": "^1.14.1",
"sinon-chai": "^2.8.0"
"sinon-chai": "^2.8.0",
"karma-requirejs": "^0.2.2",
"requirejs": "^2.1.20"
},
"contributors": [
"dignifiedquire <dignifiedquire@gmail.com>",
Expand Down
26 changes: 26 additions & 0 deletions test/preprocessor.spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,29 @@ describe 'preprocessor', ->
process ORIGINAL_CODE, file, (preprocessedCode) ->
expect(coverageMap.get()['./file.js']).to.not.exist
done()

it 'should change extension of CoffeeScript files when given `useJSExtensionForCoffeeScript`', (done) ->

ibrikInstrumenter = ->
ibrikInstrumenter::instrument = (_a, _b, callback) ->
callback()
return

process = createPreprocessor mockLogger, helper, '/base/path', ['coverage', 'progress'],
instrumenters:
ibrik :
Instrumenter : ibrikInstrumenter
instrumenter:
'**/*.coffee': 'ibrik'
useJSExtensionForCoffeeScript: true

file = new File '/base/path/file.coffee'

process ORIGINAL_COFFEE_CODE, file, (preprocessedCode) ->
sandbox =
a: true
something: ->

vm.runInNewContext preprocessedCode, sandbox
expect(file.path).to.equal '/base/path/file.js'
done()

0 comments on commit e941e0c

Please sign in to comment.