From 09dfb13a0703d77d513b23c596c7e2eeb08123da Mon Sep 17 00:00:00 2001 From: pietervdvn <pietervdvn@posteo.net> Date: Fri, 8 Apr 2022 04:39:17 +0200 Subject: [PATCH] Add --ignore as option --- package-lock.json | 17 ++++++++++++++--- package.json | 6 ++++-- src/ScriptExtraction.ts | 17 ++++++++++++++++- src/UnitTest.ts | 5 +++-- src/main.ts | 35 +++++++++++++++++++++++++++++++---- tests/ExtractScript.spec.ts | 8 ++++---- yarn.lock | 5 +++++ 7 files changed, 77 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index 414b514..fc1b091 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,22 +1,23 @@ { "name": "doctest-ts-improved", - "version": "0.6.0", + "version": "0.8.5", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "doctest-ts-improved", - "version": "0.6.0", + "version": "0.8.5", "license": "MIT", "dependencies": { "@types/chai": "^4.3.0", "chai": "^4.3.6", "global": "^4.3.2", "mocha": "^9.2.2", + "process-yargs-parser": "^2.1.0", "typescript": "^4.6.2" }, "bin": { - "doctest-ts": "dist/src/main.js" + "doctest-ts-improved": "dist/main.js" }, "devDependencies": { "@types/chokidar": "^1.7.5", @@ -1372,6 +1373,11 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "node_modules/process-yargs-parser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/process-yargs-parser/-/process-yargs-parser-2.1.0.tgz", + "integrity": "sha512-tzMsZn3lKksICtEhICR/k+Qv1UmQNVtzm0FaL10OiGJtw0ixgw0woNefcREDc6ZjqXOKBSruRagyULuwZ4FK4Q==" + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -3014,6 +3020,11 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "process-yargs-parser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/process-yargs-parser/-/process-yargs-parser-2.1.0.tgz", + "integrity": "sha512-tzMsZn3lKksICtEhICR/k+Qv1UmQNVtzm0FaL10OiGJtw0ixgw0woNefcREDc6ZjqXOKBSruRagyULuwZ4FK4Q==" + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", diff --git a/package.json b/package.json index 04cbdc7..854fc47 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "$schema": "http://json.schemastore.org/package", "name": "doctest-ts-improved", - "version": "0.8.5", + "version": "0.8.6", "description": "doctest support for typescript with Mocha", "main": "src/main.ts", "bin": { @@ -9,9 +9,10 @@ }, "scripts": { "build": "tsc && chmod 755 dist/main.js", + "gen": "ts-node src/main.ts", "test": "ts-node src/main.ts examples/ && ts-node src/main.ts src/ && mocha --require ts-node/register examples/*.ts src/*.ts", "prettier": "rm -v -f {src,test}/*doctest.ts && prettier --list-different --write src/*ts* test/*ts*", - "publish": "npm run build && npm publish" + "publish": "npm run test && npm run build && npm publish" }, "repository": { "type": "git", @@ -33,6 +34,7 @@ "chai": "^4.3.6", "global": "^4.3.2", "mocha": "^9.2.2", + "process-yargs-parser": "^2.1.0", "typescript": "^4.6.2" }, "devDependencies": { diff --git a/src/ScriptExtraction.ts b/src/ScriptExtraction.ts index 3d55652..a741400 100644 --- a/src/ScriptExtraction.ts +++ b/src/ScriptExtraction.ts @@ -58,9 +58,22 @@ export class ScriptExtraction { * ScriptExtraction.extractScript('s; e // => 1', 0) // => [{tag: 'Statement', stmt: 's;'}, {tag: '==', lhs: 'e', rhs: '1', line: 1}] */ private static extractScript(s: string, linestart: number): Script { + function getLineNumber(pos: number) { + let line = 0; + for (let i = 0; i < pos; i++) { + if (s === "\n") { + line++ + } + } + return line; + } + const pwoc = ts.createPrinter({removeComments: true}) const ast = ts.createSourceFile('_.ts', s, ts.ScriptTarget.Latest) return ast.statements.map((stmt, i): Statement | Equality => { + + + if (ts.isExpressionStatement(stmt)) { const next = ast.statements[i + 1] // zip with next const [a, z] = next ? [next.pos, next.end] : [stmt.end, ast.end] @@ -69,7 +82,9 @@ export class ScriptExtraction { if (m && m[1]) { const lhs = pwoc.printNode(ts.EmitHint.Expression, stmt.expression, ast) const rhs = m[1].trim() - return {tag: '==', lhs, rhs, line: linestart + i} + + + return {tag: '==', lhs, rhs, line: linestart + getLineNumber(stmt.pos)} } } diff --git a/src/UnitTest.ts b/src/UnitTest.ts index c0a9cd3..a0981aa 100644 --- a/src/UnitTest.ts +++ b/src/UnitTest.ts @@ -6,6 +6,7 @@ export interface Equality { tag: '==' lhs: string rhs: string, + // Line number in the single script line: number } @@ -35,7 +36,7 @@ export default class UnitTest { return ScriptExtraction.extractScripts(comment).map(({script, line, name}, i) => new UnitTest(script, { ...context, - linenumber: (context.linenumber ?? 0) + line, + linenumber: (context.linenumber ?? 0) , testname: name ?? 'doctest ' + i },imports)) } @@ -62,7 +63,7 @@ export default class UnitTest { if (s.tag == 'Statement') { return s.stmt } else { - return `__expect(${s.lhs}, "failed at ${this.context.functionname} (${this.context.filepath}:${s.line}:1)").to.deep.equal(${s.rhs})` + return `__expect(${s.lhs}, "failed at ${this.context.functionname} (${this.context.filepath}:${s.line + (this.context.linenumber ?? 0)}:1)").to.deep.equal(${s.rhs})` } }) .map(x => '\n ' + x) diff --git a/src/main.ts b/src/main.ts index 4f65d74..e2b363c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -31,28 +31,55 @@ function main() { console.error("Probably running the testsuite, detects '--require' as second argument. Quitting now") return; } + + const argv = require('process-yargs-parser')(process.argv.slice(2), { "duplicate-arguments-array": true}) if (directory === undefined) { - console.log("Usage: doctest-ts-improved <directory under test>. This will automatically scan recursively for '.ts'-files, excluding 'node_modules' '*.doctest.ts'-files") + console.log("Usage: doctest-ts-improved <directory under test> [--ignore regexp]. This will automatically scan recursively for '.ts'-files, excluding 'node_modules' and '*.doctest.ts'-files.") } - const files = readDirRecSync(directory) + let blacklistPatterns: string | string[] = argv["ignore"] + + let files = readDirRecSync(argv._[0]) .filter(p => p.endsWith(".ts")) .filter(p => p.indexOf("/node_modules/") < 0 && !p.endsWith(".doctest.ts")) + + if (blacklistPatterns !== undefined) { + if(typeof blacklistPatterns === "string"){ + blacklistPatterns = [blacklistPatterns] + } + const ignored: string[] = [] + files = files.filter(p => { + const isIgnored = (<string[]>blacklistPatterns).some(blacklistPattern => p.match(new RegExp(blacklistPattern)) !== null); + if (isIgnored) { + ignored.push(p) + } + return !isIgnored + }) + if(argv.verbose){ + console.log("Ignored the following files as they match the ignore pattern",blacklistPatterns.join(","),"\n", ignored.join(", ")) + } + } + const noTests: string[] = [] - for (let i = 0; i < files.length; i++){ + let totalTests = 0 + let totalFilesWithTests = 0 + for (let i = 0; i < files.length; i++) { const file = files[i]; process.stdout.write(`\r (${i}/${files.length}) inspecting ${file} \r`) const generated = new TestCreator(file).createTest() if (generated === 0) { noTests.push(file) } else { + totalFilesWithTests++ + totalTests += generated console.log("Generated tests for " + file + " (" + generated + " tests found)") } } + console.log(`Generated tests for ${totalFilesWithTests} containing ${totalTests} tests in total. ${Math.round(100 * totalFilesWithTests / (totalFilesWithTests + noTests.length))}% of the files have test`) if (noTests.length > 0) { const i = Math.round(Math.random() * noTests.length) const randomFile = noTests[i] - console.log(`No tests found in ${noTests.length} files. Why not add a test to ${randomFile}?`) + console.log(`No tests found in ${noTests.length} files. We suggest making a test for ${randomFile} - it'll benefit from it?`) } } diff --git a/tests/ExtractScript.spec.ts b/tests/ExtractScript.spec.ts index cfbeac2..e3a192f 100644 --- a/tests/ExtractScript.spec.ts +++ b/tests/ExtractScript.spec.ts @@ -61,24 +61,24 @@ A.x() // => 21 * 2` expect(scripts.length).eq(3) const [doctest0, doctest1, doctest2shouldEqual] = scripts; expect(doctest0).to.deep.eq({ - script: [{tag: '==', lhs: 'A.x()', rhs: "42", line: 2}], + script: [{tag: '==', lhs: 'A.x()', rhs: "42", line: 0}], name: undefined, line: 2 }) expect(doctest1).to.deep.eq({ - script: [{tag: '==', lhs: 'A.x() + 1', rhs: "43", line: 4}, { + script: [{tag: '==', lhs: 'A.x() + 1', rhs: "43", line: 0}, { tag: '==', lhs: 'A.x() - 1', rhs: "41", - line: 5 + line: 1 }], name: undefined, line: 4 }) expect(doctest2shouldEqual).to.deep.eq({ - script: [{tag: '==', lhs: 'A.x()', rhs: "21 * 2", line: 7}], + script: [{tag: '==', lhs: 'A.x()', rhs: "21 * 2", line: 0}], name: "should equal 2 * 21", line: 7 }) diff --git a/yarn.lock b/yarn.lock index a4151b3..87656b1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -868,6 +868,11 @@ "resolved" "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" "version" "2.0.1" +"process-yargs-parser@^2.1.0": + "integrity" "sha512-tzMsZn3lKksICtEhICR/k+Qv1UmQNVtzm0FaL10OiGJtw0ixgw0woNefcREDc6ZjqXOKBSruRagyULuwZ4FK4Q==" + "resolved" "https://registry.npmjs.org/process-yargs-parser/-/process-yargs-parser-2.1.0.tgz" + "version" "2.1.0" + "process@^0.11.10": "integrity" "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" "resolved" "https://registry.npmjs.org/process/-/process-0.11.10.tgz"