-
Notifications
You must be signed in to change notification settings - Fork 247
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(core): add ability to override file headers (#2363)
Add the ability to override the file headers inside a sandbox. This allows users to opt-out of the default header, as well as add custom headers. You can configure it like this: ```json { "sandboxFileHeaders": { "**/*.ts": "// Hello world\n" } } ``` The key here is a [glob expression](https://globster.xyz/), where the value points to the header to be used for matching files.
- Loading branch information
Showing
20 changed files
with
304 additions
and
63 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { tokens, Injector, commonTokens, OptionsContext } from '@stryker-mutator/api/plugin'; | ||
|
||
import { SandboxTSConfigPreprocessor } from './sandbox-tsconfig-preprocessor'; | ||
import { SandboxFileHeaderPreprocessor } from './sandbox-file-header-preprocessor'; | ||
import { FilePreprocessor } from './file-preprocessor'; | ||
import { MultiPreprocessor } from './multi-preprocessor'; | ||
|
||
createPreprocessor.inject = tokens(commonTokens.injector); | ||
export function createPreprocessor(injector: Injector<OptionsContext>): FilePreprocessor { | ||
return new MultiPreprocessor([injector.injectClass(SandboxTSConfigPreprocessor), injector.injectClass(SandboxFileHeaderPreprocessor)]); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { File } from '@stryker-mutator/api/core'; | ||
|
||
/** | ||
* A preprocessor changes files before writing them to the sandbox. | ||
* Stuff like rewriting references tsconfig.json files or adding // @ts-nocheck | ||
* This is a private api that we might want to open up in the future. | ||
*/ | ||
export interface FilePreprocessor { | ||
preprocess(file: File[]): Promise<File[]>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export type { FilePreprocessor } from './file-preprocessor'; | ||
export * from './sandbox'; | ||
export * from './sandbox-tsconfig-rewriter'; | ||
export * from './create-preprocessor'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { File } from '@stryker-mutator/api/core'; | ||
|
||
import { FilePreprocessor } from './file-preprocessor'; | ||
|
||
export class MultiPreprocessor implements FilePreprocessor { | ||
constructor(private readonly preprocessors: FilePreprocessor[]) {} | ||
|
||
public async preprocess(files: File[]): Promise<File[]> { | ||
for await (const preprocessor of this.preprocessors) { | ||
files = await preprocessor.preprocess(files); | ||
} | ||
return files; | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
packages/core/src/sandbox/sandbox-file-header-preprocessor.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import path = require('path'); | ||
|
||
import { File, StrykerOptions } from '@stryker-mutator/api/core'; | ||
import { tokens, commonTokens } from '@stryker-mutator/api/plugin'; | ||
import minimatch = require('minimatch'); | ||
|
||
import { FilePreprocessor } from './file-preprocessor'; | ||
|
||
/** | ||
* https://github.com/stryker-mutator/stryker/issues/2276 | ||
*/ | ||
export class SandboxFileHeaderPreprocessor implements FilePreprocessor { | ||
public static readonly inject = tokens(commonTokens.options); | ||
|
||
constructor(private readonly options: StrykerOptions) {} | ||
|
||
public async preprocess(files: File[]): Promise<File[]> { | ||
return files.map((file) => { | ||
Object.entries(this.options.sandboxFileHeaders).forEach(([pattern, header]) => { | ||
if (minimatch(path.resolve(file.name), path.resolve(pattern))) { | ||
file = new File(file.name, `${header}${file.textContent}`); | ||
} | ||
}); | ||
return file; | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
packages/core/test/integration/sandbox/create-preprocessor.it.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import path = require('path'); | ||
|
||
import { testInjector, assertions } from '@stryker-mutator/test-helpers'; | ||
import { File } from '@stryker-mutator/api/core'; | ||
|
||
import { FilePreprocessor, createPreprocessor } from '../../../src/sandbox'; | ||
|
||
describe('File preprocessor integration', () => { | ||
let sut: FilePreprocessor; | ||
|
||
beforeEach(() => { | ||
sut = testInjector.injector.injectFunction(createPreprocessor); | ||
}); | ||
|
||
it('should rewrite tsconfig files', async () => { | ||
const output = await sut.preprocess([new File(path.resolve('tsconfig.json'), '{"extends": "../tsconfig.settings.json" }')]); | ||
assertions.expectTextFilesEqual(output, [new File(path.resolve('tsconfig.json'), '{\n "extends": "../../../tsconfig.settings.json"\n}')]); | ||
}); | ||
|
||
it('should add a header to .ts files', async () => { | ||
const output = await sut.preprocess([new File(path.resolve('app.ts'), 'foo.bar()')]); | ||
assertions.expectTextFilesEqual(output, [new File(path.resolve('app.ts'), '/* eslint-disable */\n// @ts-nocheck\nfoo.bar()')]); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
36 changes: 36 additions & 0 deletions
36
packages/core/test/unit/sandbox/multi-preprocessor.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import sinon = require('sinon'); | ||
import { File } from '@stryker-mutator/api/core'; | ||
import { expect } from 'chai'; | ||
|
||
import { MultiPreprocessor } from '../../../src/sandbox/multi-preprocessor'; | ||
import { FilePreprocessor } from '../../../src/sandbox'; | ||
|
||
describe(MultiPreprocessor.name, () => { | ||
describe(MultiPreprocessor.prototype.preprocess.name, () => { | ||
it('should call preprocess on each preprocessor in order', async () => { | ||
// Arrange | ||
const input = [new File('foo.js', 'input')]; | ||
const firstResult = [new File('foo.js', 'first')]; | ||
const secondResult = [new File('foo.js', 'second')]; | ||
const first = createFilePreprocessorMock(); | ||
const second = createFilePreprocessorMock(); | ||
first.preprocess.resolves(firstResult); | ||
second.preprocess.resolves(secondResult); | ||
const sut = new MultiPreprocessor([first, second]); | ||
|
||
// Act | ||
const actual = await sut.preprocess(input); | ||
|
||
// Assert | ||
expect(actual).eq(secondResult); | ||
expect(first.preprocess).calledWith(input); | ||
expect(second.preprocess).calledWith(firstResult); | ||
}); | ||
}); | ||
|
||
function createFilePreprocessorMock(): sinon.SinonStubbedInstance<FilePreprocessor> { | ||
return { | ||
preprocess: sinon.stub(), | ||
}; | ||
} | ||
}); |
Oops, something went wrong.