diff --git a/.gitignore b/.gitignore index 3598db9..636f55f 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -test/**/*.js +/node_modules +test/test-outdir/**/*.js diff --git a/guess.js b/guess.js index d626a76..e6bea39 100644 --- a/guess.js +++ b/guess.js @@ -1,21 +1,42 @@ 'use strict'; const path = require('path'); +const ts = require('typescript'); -let pattern = 'test/**/*.@(ts|tsx)'; const cwd = process.cwd(); -const packageData = require(path.join(cwd, 'package.json')); +const compilerOptions = loadCompilerOptions(cwd) || {}; +const extensions = ['ts', 'tsx']; +if (compilerOptions.allowJs) { + extensions.push('js'); + extensions.push('jsx'); +} +let testDir = 'test'; +const packageData = require(path.join(cwd, 'package.json')); if ( packageData && typeof packageData.directories === 'object' && typeof packageData.directories.test === 'string' ) { - const testDir = packageData.directories.test; - pattern = `${testDir + (testDir.lastIndexOf('/', 0) === 0 ? '' : '/')}**/*.@(ts|tsx)`; + testDir = packageData.directories.test; } +const pattern = path.join(testDir, `**/*.@(${extensions.join('|')})`); -require('./index')({ - cwd: cwd, - pattern: pattern, -}); +require('./index')({cwd, pattern, extensions}); + +function loadCompilerOptions(cwd) { + const tsconfigPath = ts.findConfigFile(cwd, ts.sys.fileExists); + if (!tsconfigPath) { + return null; + } + const result = ts.readConfigFile(tsconfigPath, ts.sys.readFile); + if (result.error) { + throw new Error(result.error.messageText); + } + if (result.config && result.config.compilerOptions) { + const basepath = path.dirname(tsconfigPath); + const {options} = ts.parseJsonConfigFileContent(result.config, ts.sys, basepath); + return options; + } + return null; +} diff --git a/index.js b/index.js index fe16a98..2bd5c46 100644 --- a/index.js +++ b/index.js @@ -2,20 +2,22 @@ 'use strict'; +const path = require('path'); const espowerSource = require('espower-source'); const minimatch = require('minimatch'); const tsNodeRegister = require('ts-node').register; -function espowerTypeScript(options) { - tsNodeRegister(options.tsNode); - espowerTsRegister('.ts', options); - espowerTsRegister('.tsx', options); +function espowerTypeScript(options, tsNodeOptions) { + tsNodeRegister(tsNodeOptions); + const {extensions = ['ts', 'tsx']} = options; + extensions.forEach(ext => { + espowerTsRegister(`.${ext}`, options); + }); } function espowerTsRegister(ext, options) { const cwd = options.cwd || process.cwd(); - const separator = options.pattern.lastIndexOf('/', 0) === 0 ? '' : '/'; - const pattern = cwd + separator + options.pattern; + const pattern = path.join(cwd, options.pattern); const originalExtension = require.extensions[ext]; require.extensions[ext] = (module, filepath) => { diff --git a/package-lock.json b/package-lock.json index 26d0695..876c85f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2208,7 +2208,8 @@ "typescript": { "version": "2.9.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", - "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==" + "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==", + "dev": true }, "ua-parser-js": { "version": "0.7.18", diff --git a/package.json b/package.json index 51a5ff9..4b59809 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "demo": "mocha --require './guess' test/demo.ts", "lint": "eslint *.js", "test": "run-s lint test:*", + "test:allow-js": "cd test/test-allow-js && mocha --require ../../guess test/*_test.js", "test:outdir": "cd test/test-outdir && mocha --require ../../guess test/*_test.ts", "test:ts": "mocha --require './guess' test/*_test.ts", "test:tsx": "mocha --require './guess' test/*_test.tsx" diff --git a/test/lib/expectPowerAssertMessage.ts b/test/lib/expectPowerAssertMessage.ts index b064317..c467057 100644 --- a/test/lib/expectPowerAssertMessage.ts +++ b/test/lib/expectPowerAssertMessage.ts @@ -1,10 +1,11 @@ -import assert = require('assert'); +// don't use `assert` not to instrument +import ass = require('assert'); export default function expectPowerAssertMessage(body: () => void, expectedLines: string) { try { body(); - assert.fail('AssertionError should be thrown'); + ass.fail('AssertionError should be thrown'); } catch(e) { - assert.equal(e.message.split('\n').slice(2, -1).join('\n'), expectedLines); + ass.equal(e.message.split('\n').slice(2, -1).join('\n'), expectedLines); } }; diff --git a/test/test-allow-js/package.json b/test/test-allow-js/package.json new file mode 100644 index 0000000..4f1f787 --- /dev/null +++ b/test/test-allow-js/package.json @@ -0,0 +1,9 @@ +{ + "name": "test-allow-js", + "version": "1.0.0", + "description": "This is a dummy file. See ../../package.json", + "devDependencies": { + }, + "dependencies": { + } +} diff --git a/test/test-allow-js/test/to_be_instrumented_test.js b/test/test-allow-js/test/to_be_instrumented_test.js new file mode 100644 index 0000000..5054126 --- /dev/null +++ b/test/test-allow-js/test/to_be_instrumented_test.js @@ -0,0 +1,34 @@ +'use strict'; + +const assert = require('assert'); + +describe('test for allowJs option', () => { + beforeEach(function() { + // don't use `assert` not to instrument + const ass = assert; + this.expectPowerAssertMessage = (body, expectedLines) => { + try { + body(); + ass.fail('AssertionError should be thrown'); + } catch (e) { + ass.equal( + e.message + .split('\n') + .slice(2, -1) + .join('\n'), + expectedLines + ); + } + }; + }); + + it('equal with Literal and Identifier: assert.equal(1, minusOne)', function() { + const minusOne = -1; + const expected = ` assert.equal(1, minusOne) + | + -1 `; + this.expectPowerAssertMessage(() => { + assert.equal(1, minusOne); + }, expected); + }); +}); diff --git a/test/test-allow-js/tsconfig.json b/test/test-allow-js/tsconfig.json new file mode 100644 index 0000000..b92d6a6 --- /dev/null +++ b/test/test-allow-js/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "allowJs": true, + "outDir": "build", + "module": "commonjs", + "target": "ES5", + "noImplicitAny": true, + "jsx": "react" + }, + "exclude": [ + "node_modules" + ] +}