diff --git a/lib/simple_tsify.js b/lib/simple_tsify.js index 394fe02..d80b0b2 100644 --- a/lib/simple_tsify.js +++ b/lib/simple_tsify.js @@ -15,9 +15,10 @@ const isJson = (code) => { // It means it should check types whenever spec file is changed // and it slows down the test speed a lot. // We skip this slow type-checking process by using transpileModule() api. -module.exports = function (filePath, opts) { +module.exports = function (fileName, opts) { + const ts = opts.typescript const chunks = [] - const ext = path.extname(filePath) + const ext = path.extname(fileName) return through( (buf, enc, next) => { @@ -25,19 +26,30 @@ module.exports = function (filePath, opts) { next() }, function (next) { - const ts = opts.typescript const text = chunks.join('') if (isJson(text)) { this.push(text) } else { - this.push(ts.transpileModule(text, { - compilerOptions: { - esModuleInterop: true, - jsx: ext === '.tsx' || ext === '.jsx' || ext === '.js' ? 'react' : undefined, - downlevelIteration: true, - }, - }).outputText) + this.push( + ts.transpileModule(text, { + // explicitly name the file here + // for sourcemaps + fileName, + compilerOptions: { + esModuleInterop: true, + // inline the source maps into the file + // https://github.com/cypress-io/cypress-browserify-preprocessor/issues/48 + inlineSourceMap: true, + inlineSources: true, + jsx: + ext === '.tsx' || ext === '.jsx' || ext === '.js' + ? 'react' + : undefined, + downlevelIteration: true, + }, + }).outputText, + ) } next() diff --git a/test/e2e/e2e_spec.js b/test/e2e/e2e_spec.js index 2145be3..685a673 100644 --- a/test/e2e/e2e_spec.js +++ b/test/e2e/e2e_spec.js @@ -1,6 +1,8 @@ +const _ = require('lodash') const chai = require('chai') const path = require('path') const snapshot = require('snap-shot-it') +const Bluebird = require('bluebird') process.env.__TESTING__ = true @@ -10,6 +12,8 @@ const preprocessor = require('../../index') /* eslint-disable-next-line no-unused-vars */ const expect = chai.expect +const typescript = require.resolve('typescript') + beforeEach(() => { fs.removeSync(path.join(__dirname, '_test-output')) preprocessor.reset() @@ -21,13 +25,37 @@ const DEFAULT_OPTIONS = { browserifyOptions: { debug: false } } const bundle = (fixtureName, options = DEFAULT_OPTIONS) => { const on = () => {} const filePath = path.join(__dirname, '..', 'fixtures', fixtureName) - const outputPath = path.join(__dirname, '..', '_test-output', 'output.js') + const outputPath = path.join(__dirname, '..', '_test-output', fixtureName) return preprocessor(options)({ filePath, outputPath, on }).then(() => { return fs.readFileSync(outputPath).toString() }) } +const parseSourceMap = (output) => { + return _ + .chain(output) + .split('//# sourceMappingURL=data:application/json;charset=utf-8;base64,') + .last() + .thru((str) => { + const base64 = Buffer.from(str, 'base64').toString() + + return JSON.parse(base64) + }) + .value() +} + +const verifySourceContents = ({ sources, sourcesContent }) => { + const zippedArrays = _.zip(sources, sourcesContent) + + return Bluebird.map(zippedArrays, ([sourcePath, sourceContent]) => { + return fs.readFileAsync(sourcePath, 'utf8') + .then((str) => { + expect(str).to.eq(sourceContent) + }) + }) +} + describe('browserify preprocessor - e2e', () => { it('correctly preprocesses the file', () => { return bundle('example_spec.js').then((output) => { @@ -50,7 +78,6 @@ describe('browserify preprocessor - e2e', () => { }) }) - it('handles module.exports and import', () => { return bundle('sub_spec.js').then((output) => { // check that bundled tests work @@ -88,16 +115,45 @@ describe('browserify preprocessor - e2e', () => { describe('typescript', () => { it('handles .ts file when the path is given', () => { return bundle('typescript/math_spec.ts', { - typescript: require.resolve('typescript'), + typescript, }).then((output) => { // check that bundled tests work eval(output) + + const sourceMap = parseSourceMap(output) + + expect(sourceMap.sources).to.deep.eq([ + 'node_modules/browser-pack/_prelude.js', + 'test/fixtures/typescript/math.ts', + 'test/fixtures/typescript/math_spec.ts', + ]) + + return verifySourceContents(sourceMap) + }) + }) + + it('handles simple .tsx file with imports', () => { + return bundle('typescript/simple.spec.tsx', { + typescript, + }).then((output) => { + // check that bundled tests work + eval(output) + + const sourceMap = parseSourceMap(output) + + expect(sourceMap.sources).to.deep.eq([ + 'node_modules/browser-pack/_prelude.js', + 'test/fixtures/typescript/math.ts', + 'test/fixtures/typescript/simple.spec.tsx', + ]) + + return verifySourceContents(sourceMap) }) }) it('handles .tsx file when the path is given', () => { return bundle('typescript/react_spec.tsx', { - typescript: require.resolve('typescript'), + typescript, }).then((output) => { // check that bundled tests work eval(output) diff --git a/test/fixtures/typescript/math.ts b/test/fixtures/typescript/math.ts index 0568956..3b6773a 100644 --- a/test/fixtures/typescript/math.ts +++ b/test/fixtures/typescript/math.ts @@ -1,3 +1,7 @@ +export const multiply = (a: number, b: number): number => { + return a * b +} + export default { add: (a: number, b: number) => { return a + b diff --git a/test/fixtures/typescript/simple.spec.tsx b/test/fixtures/typescript/simple.spec.tsx new file mode 100644 index 0000000..317271d --- /dev/null +++ b/test/fixtures/typescript/simple.spec.tsx @@ -0,0 +1,12 @@ +import { multiply } from './math' + +describe('simple .tsx spec', () => { + it('can import another module and add', () => { + const EXPECTED = 6 + const result = multiply(2, 3) + + if (result !== EXPECTED) { + throw new Error(`multiplying 2*3 did not equal ${EXPECTED}. received: ${result}`) + } + }) +}) diff --git a/test/unit/index_spec.js b/test/unit/index_spec.js index 2c2fab7..2ae712c 100644 --- a/test/unit/index_spec.js +++ b/test/unit/index_spec.js @@ -19,7 +19,9 @@ mockery.enable({ mockery.registerMock('browserify', browserify) const streamApi = { - pipe () { return streamApi }, + pipe () { + return streamApi + }, } streamApi.on = sandbox.stub().returns(streamApi) @@ -35,7 +37,9 @@ describe('browserify preprocessor', function () { const bundlerApi = this.bundlerApi = { bundle: sandbox.stub().returns(streamApi), - external () { return bundlerApi }, + external () { + return bundlerApi + }, close: sandbox.spy(), plugin: sandbox.stub(), }