mirror of
https://github.com/cypress-io/cypress.git
synced 2026-05-03 13:30:26 -05:00
feat(webpack-preprocessor): Allow specifying typescript path (#9312)
This commit is contained in:
@@ -287,6 +287,7 @@ commands:
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: ~/
|
||||
- check-conditional-ci
|
||||
# make sure the binary and NPM package files are present
|
||||
- run: ls -l
|
||||
- run: ls -l cypress.zip cypress.tgz
|
||||
|
||||
@@ -94,6 +94,7 @@ const quietErrorMessage = (err: Error) => {
|
||||
interface PreprocessorOptions {
|
||||
webpackOptions?: webpack.Configuration
|
||||
watchOptions?: Object
|
||||
typescript?: string
|
||||
additionalEntries?: string[]
|
||||
}
|
||||
|
||||
@@ -201,9 +202,8 @@ const preprocessor: WebpackPreprocessor = (options: PreprocessorOptions = {}): F
|
||||
})
|
||||
.tap((opts) => {
|
||||
if (opts.devtool === false) {
|
||||
// disable any overrides if
|
||||
// we've explictly turned off sourcemaps
|
||||
overrideSourceMaps(false)
|
||||
// disable any overrides if we've explictly turned off sourcemaps
|
||||
overrideSourceMaps(false, options.typescript)
|
||||
|
||||
return
|
||||
}
|
||||
@@ -212,14 +212,15 @@ const preprocessor: WebpackPreprocessor = (options: PreprocessorOptions = {}): F
|
||||
|
||||
opts.devtool = 'inline-source-map'
|
||||
|
||||
// override typescript to always generate
|
||||
// proper source maps
|
||||
overrideSourceMaps(true)
|
||||
// override typescript to always generate proper source maps
|
||||
overrideSourceMaps(true, options.typescript)
|
||||
})
|
||||
.value() as any
|
||||
|
||||
debug('webpackOptions: %o', webpackOptions)
|
||||
debug('watchOptions: %o', watchOptions)
|
||||
if (options.typescript) debug('typescript: %s', options.typescript)
|
||||
|
||||
debug(`input: ${filePath}`)
|
||||
debug(`output: ${outputPath}`)
|
||||
|
||||
|
||||
@@ -3,26 +3,27 @@ const _ = require('lodash')
|
||||
|
||||
import { CompilerOptions, CreateProgramOptions } from 'typescript'
|
||||
|
||||
let sourceMapOverride: null | boolean = null
|
||||
let patched = false
|
||||
|
||||
export const getProgramOptions = (rootNamesOrOptions: CreateProgramOptions, options: CompilerOptions): CompilerOptions => {
|
||||
const getProgramOptions = (rootNamesOrOptions: CreateProgramOptions, options: CompilerOptions): CompilerOptions => {
|
||||
return _.isArray(rootNamesOrOptions) ? options : rootNamesOrOptions.options
|
||||
}
|
||||
|
||||
export const tryRequireTypescript = () => {
|
||||
export const overrideSourceMaps = (sourceMap: boolean, typescriptPath?: string) => {
|
||||
try {
|
||||
// reset each time this is called
|
||||
sourceMapOverride = null
|
||||
if (patched) {
|
||||
debug('typescript.createProgram() already overridden')
|
||||
|
||||
const typescript = require('typescript') as typeof import('typescript')
|
||||
return
|
||||
}
|
||||
|
||||
const typescript = require(typescriptPath || 'typescript') as typeof import('typescript')
|
||||
const { createProgram } = typescript
|
||||
|
||||
debug('typescript found, overriding typescript.createProgram()')
|
||||
|
||||
const { createProgram } = typescript
|
||||
|
||||
typescript.createProgram = (...args: any[]) => {
|
||||
const [rootNamesOrOptions, _options] = args
|
||||
|
||||
const options = getProgramOptions(rootNamesOrOptions, _options)
|
||||
|
||||
debug('typescript unmodified createProgram options %o', options)
|
||||
@@ -30,34 +31,22 @@ export const tryRequireTypescript = () => {
|
||||
// if sourceMap has been set then apply
|
||||
// these overrides to force typescript
|
||||
// to generate the right sourcemaps
|
||||
if (sourceMapOverride !== null) {
|
||||
options.sourceMap = sourceMapOverride
|
||||
options.sourceMap = sourceMap
|
||||
|
||||
delete options.inlineSources
|
||||
delete options.inlineSourceMap
|
||||
delete options.inlineSources
|
||||
delete options.inlineSourceMap
|
||||
|
||||
debug('typescript modified createProgram options %o', options)
|
||||
}
|
||||
debug('typescript modified createProgram options %o', options)
|
||||
|
||||
// @ts-ignore
|
||||
return createProgram.apply(typescript, args)
|
||||
}
|
||||
|
||||
return typescript
|
||||
patched = true
|
||||
} catch (err) {
|
||||
debug('typescript not found')
|
||||
|
||||
// for testing
|
||||
// for testing purposes
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
export const overrideSourceMaps = (val: boolean) => {
|
||||
sourceMapOverride = val
|
||||
}
|
||||
|
||||
export const getSourceMapOverride = () => {
|
||||
return sourceMapOverride
|
||||
}
|
||||
|
||||
tryRequireTypescript()
|
||||
|
||||
@@ -18,7 +18,7 @@ mockery.enable({
|
||||
mockery.registerMock('webpack', webpack)
|
||||
|
||||
const preprocessor = require('../../index')
|
||||
const { getSourceMapOverride } = require('../../lib/typescript-overrides')
|
||||
const typescriptOverrides = require('../../lib/typescript-overrides')
|
||||
|
||||
describe('webpack preprocessor', function () {
|
||||
beforeEach(function () {
|
||||
@@ -152,13 +152,17 @@ describe('webpack preprocessor', function () {
|
||||
})
|
||||
|
||||
describe('devtool', function () {
|
||||
beforeEach((() => {
|
||||
sinon.stub(typescriptOverrides, 'overrideSourceMaps')
|
||||
}))
|
||||
|
||||
it('enables inline source maps', function () {
|
||||
return this.run().then(() => {
|
||||
expect(webpack).to.be.calledWithMatch({
|
||||
devtool: 'inline-source-map',
|
||||
})
|
||||
|
||||
expect(getSourceMapOverride()).to.be.true
|
||||
expect(typescriptOverrides.overrideSourceMaps).to.be.calledWith(true)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -170,7 +174,7 @@ describe('webpack preprocessor', function () {
|
||||
devtool: false,
|
||||
})
|
||||
|
||||
expect(getSourceMapOverride()).to.be.false
|
||||
expect(typescriptOverrides.overrideSourceMaps).to.be.calledWith(false)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -182,7 +186,7 @@ describe('webpack preprocessor', function () {
|
||||
devtool: 'inline-source-map',
|
||||
})
|
||||
|
||||
expect(getSourceMapOverride()).to.be.true
|
||||
expect(typescriptOverrides.overrideSourceMaps).to.be.calledWith(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as sinon from 'sinon'
|
||||
const { expect } = require('chai')
|
||||
const sinon = require('sinon')
|
||||
const proxyquire = require('proxyquire').noPreserveCache()
|
||||
|
||||
type Typescript = {
|
||||
@@ -9,8 +9,6 @@ type Typescript = {
|
||||
let typescript: Typescript
|
||||
let createProgram: Typescript['createProgram']
|
||||
|
||||
import '../../lib/typescript-overrides'
|
||||
|
||||
describe('./lib/typescript-overrides', () => {
|
||||
beforeEach(() => {
|
||||
createProgram = sinon.stub()
|
||||
@@ -19,29 +17,6 @@ describe('./lib/typescript-overrides', () => {
|
||||
}
|
||||
})
|
||||
|
||||
context('.getSourceMapOverride', () => {
|
||||
it('is null by default', () => {
|
||||
const typescriptOverrides = proxyquire('../../lib/typescript-overrides', {
|
||||
typescript,
|
||||
})
|
||||
|
||||
expect(typescriptOverrides.getSourceMapOverride()).to.be.null
|
||||
})
|
||||
})
|
||||
|
||||
context('.tryRequireTypescript', () => {
|
||||
it('gracefully returns error when typescript cannot be required', () => {
|
||||
const typescriptOverrides = proxyquire('../../lib/typescript-overrides', {
|
||||
typescript: null,
|
||||
})
|
||||
|
||||
const err = typescriptOverrides.tryRequireTypescript()
|
||||
|
||||
expect(err).to.be.instanceOf(Error)
|
||||
expect(err.message).to.eq(`Cannot find module 'typescript'`)
|
||||
})
|
||||
})
|
||||
|
||||
context('.overrideSourceMaps', () => {
|
||||
it('it sets sourceMap: true', () => {
|
||||
const typescriptOverrides = proxyquire('../../lib/typescript-overrides', {
|
||||
@@ -50,8 +25,6 @@ describe('./lib/typescript-overrides', () => {
|
||||
|
||||
typescriptOverrides.overrideSourceMaps(true)
|
||||
|
||||
expect(typescriptOverrides.getSourceMapOverride()).to.be.true
|
||||
|
||||
typescript.createProgram({
|
||||
options: {
|
||||
sourceMap: false,
|
||||
@@ -60,7 +33,6 @@ describe('./lib/typescript-overrides', () => {
|
||||
},
|
||||
})
|
||||
|
||||
expect(createProgram).to.be.calledOn(typescript)
|
||||
expect(createProgram).to.be.calledWith({
|
||||
options: {
|
||||
sourceMap: true,
|
||||
@@ -75,8 +47,6 @@ describe('./lib/typescript-overrides', () => {
|
||||
|
||||
typescriptOverrides.overrideSourceMaps(false)
|
||||
|
||||
expect(typescriptOverrides.getSourceMapOverride()).to.be.false
|
||||
|
||||
typescript.createProgram({
|
||||
options: {
|
||||
sourceMap: true,
|
||||
@@ -85,7 +55,6 @@ describe('./lib/typescript-overrides', () => {
|
||||
},
|
||||
})
|
||||
|
||||
expect(createProgram).to.be.calledOn(typescript)
|
||||
expect(createProgram).to.be.calledWith({
|
||||
options: {
|
||||
sourceMap: false,
|
||||
@@ -93,31 +62,6 @@ describe('./lib/typescript-overrides', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('does not override sourcemaps', () => {
|
||||
const typescriptOverrides = proxyquire('../../lib/typescript-overrides', {
|
||||
typescript,
|
||||
})
|
||||
|
||||
expect(typescriptOverrides.getSourceMapOverride()).to.be.null
|
||||
|
||||
typescript.createProgram({
|
||||
options: {
|
||||
sourceMap: true,
|
||||
inlineSources: true,
|
||||
inlineSourceMap: true,
|
||||
},
|
||||
})
|
||||
|
||||
expect(createProgram).to.be.calledOn(typescript)
|
||||
expect(createProgram).to.be.calledWith({
|
||||
options: {
|
||||
sourceMap: true,
|
||||
inlineSources: true,
|
||||
inlineSourceMap: true,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it('sets options when given an array', () => {
|
||||
const typescriptOverrides = proxyquire('../../lib/typescript-overrides', {
|
||||
typescript,
|
||||
@@ -125,7 +69,23 @@ describe('./lib/typescript-overrides', () => {
|
||||
|
||||
typescriptOverrides.overrideSourceMaps(true)
|
||||
|
||||
expect(typescriptOverrides.getSourceMapOverride()).to.be.true
|
||||
typescript.createProgram([], {
|
||||
sourceMap: false,
|
||||
inlineSources: true,
|
||||
inlineSourceMap: true,
|
||||
})
|
||||
|
||||
expect(createProgram).to.be.calledWith([], {
|
||||
sourceMap: true,
|
||||
})
|
||||
})
|
||||
|
||||
it('require "default" typescript if typescript option not specified', () => {
|
||||
const typescriptOverrides = proxyquire('../../lib/typescript-overrides', {
|
||||
typescript,
|
||||
})
|
||||
|
||||
typescriptOverrides.overrideSourceMaps(true)
|
||||
|
||||
typescript.createProgram([], {
|
||||
sourceMap: false,
|
||||
@@ -134,9 +94,60 @@ describe('./lib/typescript-overrides', () => {
|
||||
})
|
||||
|
||||
expect(createProgram).to.be.calledOn(typescript)
|
||||
expect(createProgram).to.be.calledWith([], {
|
||||
sourceMap: true,
|
||||
})
|
||||
|
||||
it('requires typescript from typescript option if specified', () => {
|
||||
const userCreateProgram = sinon.stub()
|
||||
const userTypescript = {
|
||||
createProgram: userCreateProgram,
|
||||
}
|
||||
const typescriptOverrides = proxyquire('../../lib/typescript-overrides', {
|
||||
typescript,
|
||||
'/path/to/user/typescript': userTypescript,
|
||||
})
|
||||
|
||||
typescriptOverrides.overrideSourceMaps(true, '/path/to/user/typescript')
|
||||
|
||||
userTypescript.createProgram([], {
|
||||
sourceMap: false,
|
||||
inlineSources: true,
|
||||
inlineSourceMap: true,
|
||||
})
|
||||
|
||||
expect(userCreateProgram).to.be.calledOn(userTypescript)
|
||||
})
|
||||
|
||||
it('does not run twice', () => {
|
||||
const typescriptOverrides = proxyquire('../../lib/typescript-overrides', {
|
||||
typescript,
|
||||
'/path/to/user/typescript': null,
|
||||
})
|
||||
|
||||
typescriptOverrides.overrideSourceMaps(true)
|
||||
|
||||
typescript.createProgram([], {
|
||||
sourceMap: false,
|
||||
inlineSources: true,
|
||||
inlineSourceMap: true,
|
||||
})
|
||||
|
||||
expect(createProgram).to.be.calledOn(typescript)
|
||||
|
||||
const result = typescriptOverrides.overrideSourceMaps(true, '/path/to/user/typescript')
|
||||
|
||||
// result will be the error if it tries to require typescript again
|
||||
expect(result).to.be.undefined
|
||||
})
|
||||
|
||||
it('gracefully returns error when typescript cannot be required', () => {
|
||||
const typescriptOverrides = proxyquire('../../lib/typescript-overrides', {
|
||||
typescript: null,
|
||||
})
|
||||
|
||||
const err = typescriptOverrides.overrideSourceMaps(true)
|
||||
|
||||
expect(err).to.be.instanceOf(Error)
|
||||
expect(err.message).to.eq(`Cannot find module 'typescript'`)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user