Skip to content

Commit

Permalink
fix(shebang): support shebang in in files (#2510)
Browse files Browse the repository at this point in the history
Support shebang (i.e. `#!/usr/bin/env node`) in javascript files.
  • Loading branch information
nicojs committed Sep 28, 2020
1 parent 66c2444 commit 7d2dd80
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 2 deletions.
1 change: 1 addition & 0 deletions e2e/test/mocha-javascript/src/Add.js
@@ -1,3 +1,4 @@
#! /usr/bin/env node
module.exports.add = function(num1, num2) {
return num1 + num2;
};
Expand Down
12 changes: 11 additions & 1 deletion packages/instrumenter/src/disable-type-checks.ts
Expand Up @@ -35,7 +35,17 @@ function disableTypeCheckingInBabelAst(ast: JSAst | TSAst): string {
}

function prefixWithNoCheck(code: string): string {
return `// @ts-nocheck\n${code}`;
if (code.startsWith('#')) {
// first line has a shebang (#!/usr/bin/env node)
const newLineIndex = code.indexOf('\n');
if (newLineIndex > 0) {
return `${code.substr(0, newLineIndex)}\n// @ts-nocheck\n${code.substr(newLineIndex + 1)}`;
} else {
return code;
}
} else {
return `// @ts-nocheck\n${code}`;
}
}

function disableTypeCheckingInHtml(ast: HtmlAst): string {
Expand Down
Expand Up @@ -20,7 +20,7 @@ const resolveTestResource = path.resolve.bind(
);

describe(`${disableTypeChecks.name} integration`, () => {
it('should be able disable type checks of a type script file', async () => {
it('should be able disable type checks of a typescript file', async () => {
await arrangeAndActAssert('app.component.ts');
});
it('should be able disable type checks of an html file', async () => {
Expand Down
Expand Up @@ -46,6 +46,9 @@ describe('instrumenter integration', () => {
it('should be able to instrument super calls', async () => {
await arrangeAndActAssert('super-call.ts');
});
it('should be able to instrument js files with a shebang in them', async () => {
await arrangeAndActAssert('shebang.js');
});

describe('type declarations', () => {
it('should not produce mutants for TS type definitions', async () => {
Expand Down
13 changes: 13 additions & 0 deletions packages/instrumenter/test/unit/disable-type-checks.spec.ts
Expand Up @@ -14,6 +14,19 @@ describe(disableTypeChecks.name, () => {
assertions.expectTextFileEqual(actual, new File('foo.js', '// @ts-nocheck\nfoo.bar();'));
});

describe('with shebang (`#!/usr/bin/env node`)', () => {
it('should insert `// @ts-nocheck` after the new line', async () => {
const inputFile = new File('foo.js', '#!/usr/bin/env node\nfoo.bar();');
const actual = await disableTypeChecks(inputFile, { plugins: null });
assertions.expectTextFileEqual(actual, new File('foo.js', '#!/usr/bin/env node\n// @ts-nocheck\nfoo.bar();'));
});
it('should not insert if there is no code', async () => {
const inputFile = new File('foo.js', '#!/usr/bin/env node');
const actual = await disableTypeChecks(inputFile, { plugins: null });
assertions.expectTextFileEqual(actual, new File('foo.js', '#!/usr/bin/env node'));
});
});

it('should not even parse the file if "@ts-" can\'t be found anywhere in the file (performance optimization)', async () => {
const createParserSpy = sinon.spy(parsers, 'createParser');
const inputFile = new File('foo.js', 'foo.bar();');
Expand Down
Expand Up @@ -65,3 +65,36 @@ export class AppComponent {
}
"
`;

exports[`disableTypeChecks integration should be able disable type checks of a typescript file 1`] = `
"// @ts-nocheck
import {Component, HostListener, Inject} from '@angular/core';
import {DOCUMENT} from '@angular/common';
@Component({
selector: 'ksw-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'Kantishop';
constructor(@Inject(DOCUMENT) document) {
}
@HostListener('window:scroll', ['$event'])
onWindowScroll(e) {
//
if (window.pageYOffset > document.getElementById('banner').offsetHeight) {
const element = document.getElementById('kanti-menu');
element.classList.add('kanti-sticky');
document.getElementsByTagName('main').item(0).setAttribute('style', 'margin-top: 50px');
} else {
const element = document.getElementById('kanti-menu');
element.classList.remove('kanti-sticky');
document.getElementsByTagName('main').item(0).removeAttribute('style');
}
}
}
"
`;
3 changes: 3 additions & 0 deletions packages/instrumenter/testResources/instrumenter/shebang.js
@@ -0,0 +1,3 @@
#! /usr/bin/env node

console.log('test');
@@ -0,0 +1,61 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`instrumenter integration should be able to instrument js files with a shebang in them 1`] = `
"#! /usr/bin/env node
function stryNS_9fa48() {
var g = new Function(\\"return this\\")();
var ns = g.__stryker__ || (g.__stryker__ = {});
if (ns.activeMutant === undefined && g.process && g.process.env && g.process.env.__STRYKER_ACTIVE_MUTANT__) {
ns.activeMutant = Number(g.process.env.__STRYKER_ACTIVE_MUTANT__);
}
function retrieveNS() {
return ns;
}
stryNS_9fa48 = retrieveNS;
return retrieveNS();
}
stryNS_9fa48();
function stryCov_9fa48() {
var ns = stryNS_9fa48();
var cov = ns.mutantCoverage || (ns.mutantCoverage = {
static: {},
perTest: {}
});
function cover() {
var c = cov.static;
if (ns.currentTestId) {
c = cov.perTest[ns.currentTestId] = cov.perTest[ns.currentTestId] || {};
}
var a = arguments;
for (var i = 0; i < a.length; i++) {
c[a[i]] = (c[a[i]] || 0) + 1;
}
}
stryCov_9fa48 = cover;
cover.apply(null, arguments);
}
function stryMutAct_9fa48(id) {
var ns = stryNS_9fa48();
function isActive(id) {
return ns.activeMutant === id;
}
stryMutAct_9fa48 = isActive;
return isActive(id);
}
console.log(stryMutAct_9fa48(0) ? \\"\\" : (stryCov_9fa48(0), 'test'));"
`;

0 comments on commit 7d2dd80

Please sign in to comment.