├── .codecov.yml
├── .github
└── FUNDING.yml
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── cli-main.js
├── cli.js
├── index.js
├── jest.config.js
├── lib
├── json-formatter.js
├── options-manager.js
└── project-init.js
├── media
├── demo.png
├── logo.png
└── logo.svg
├── package-lock.json
├── package.json
└── test
├── fixtures
├── default
│ ├── bar.js
│ ├── foo.js
│ └── package.json
├── gitignore
│ ├── .gitignore
│ ├── bar.js
│ └── foo.js
├── negative-gitignore
│ ├── .gitignore
│ ├── bar.js
│ └── foo.js
└── pkgConf
│ ├── bar.js
│ ├── baz.js
│ ├── foo.js
│ └── package.json
├── index.test.js
├── options-manager.test.js
└── test-setup.js
/.codecov.yml:
--------------------------------------------------------------------------------
1 | comment: off
2 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: matchai
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # TypeScript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | # parcel-bundler cache (https://parceljs.org/)
61 | .cache
62 |
63 | # next.js build output
64 | .next
65 |
66 | # nuxt.js build output
67 | .nuxt
68 |
69 | # vuepress build output
70 | .vuepress/dist
71 |
72 | # Serverless directories
73 | .serverless/
74 |
75 | # FuseBox cache
76 | .fusebox/
77 |
78 | #DynamoDB Local files
79 | .dynamodb/
80 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 |
3 | node_js:
4 | - "node"
5 | - "10"
6 | - "9"
7 | - "8"
8 |
9 | script:
10 | - npm test -- --coverage
11 | - npx codecov
12 |
13 | deploy:
14 | - provider: script
15 | skip_cleanup: true
16 | script: npx travis-deploy-once "npx semantic-release"
17 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | ISC License
2 |
3 | Copyright (c) 2018 Matan Kushner
4 |
5 | Permission to use, copy, modify, and/or distribute this software for any
6 | purpose with or without fee is hereby granted, provided that the above
7 | copyright notice and this permission notice appear in all copies.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
ts-quick️
4 | Zero-configuration JavaScript static analysis tool
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | ---
14 |
15 | Easily catch bugs and enforce JSDoc types throughout your JavaScript project using the proven power of TypeScript.
16 | Either use it as a standalone CLI, or add it to your test script to ensure that your JS the best it can be.
17 |
18 | 
19 |
20 | ## Install
21 |
22 | ```
23 | $ npm install --global ts-quick
24 | ```
25 |
26 | ## Usage
27 |
28 | ```
29 | $ ts-quick --help
30 |
31 | Usage
32 | $ ts-quick [ ...]
33 |
34 | Options
35 | --init Add ts-quick to your project
36 | --implicitAny Allow variables to implicitly have the "any" type
37 | --ignore Additional paths to ignore [Can be set multiple times]
38 | --cwd= Working directory for files
39 |
40 | Examples
41 | $ ts-quick
42 | $ ts-quick index.js
43 | $ ts-quick *.js !foo.js
44 | $ ts-quick --init
45 | $ ts-quick --implicitAny
46 |
47 | Tips
48 | Put options in package.json instead of using flags so other tools can read it.
49 | ```
50 |
51 | ## Workflow
52 |
53 | The recommended workflow is to add ts-quick locally to your project to have it run with tests.
54 |
55 | Simply run `$ ts-quick --init` to add ts-quick to your package.json.
56 |
57 | ### Before
58 |
59 | ```json
60 | {
61 | "name": "example-package",
62 | "scripts": {
63 | "test": "jest"
64 | },
65 | "devDependencies": {
66 | "jest": "^23.0.0"
67 | }
68 | }
69 | ```
70 |
71 | ### After
72 |
73 | ```json
74 | {
75 | "name": "example-package",
76 | "scripts": {
77 | "test": "ts-quick && jest"
78 | },
79 | "devDependencies": {
80 | "jest": "^23.0.0",
81 | "ts-quick": "^1.1.0"
82 | }
83 | }
84 | ```
85 |
86 | Then just run `$ npm test` and ts-quick will be run before your tests.
87 |
88 | ## Config
89 |
90 | You can configure options in ts-quick by putting them in package.json:
91 |
92 | ```json
93 | {
94 | "name": "example-package",
95 | "ts-quick": {
96 | "implicitAny": true,
97 | "ignores": ["./test", "foo.js"]
98 | }
99 | }
100 | ```
101 |
102 | ### implicitAny
103 |
104 | Type: `boolean`
105 | Default: `false` _(types are required)_
106 |
107 | If enabled, ts-quick allows expressions and declarations to have an implied `any` type.
108 |
109 | ### ignores
110 |
111 | Type: `Array`
112 |
113 | Some [paths](lib/options-manager.js) are ignored by default, including paths in `.gitignore`. Additional ignores can be added here.
114 |
115 | ## License
116 |
117 | ISC © [Matan Kushner](https://matchai.me/)
118 |
119 | ### Attribution
120 |
121 | The ts-quick logo is a derivative of the "flash-outline" icon in [Typicons](https://github.com/stephenhutchings/typicons.font) by [stephenhutchings](https://github.com/stephenhutchings), used under [CC BY-SA](https://creativecommons.org/licenses/by-sa/3.0/).
The ts-quick logo is licensed under [CC BY-SA](https://creativecommons.org/licenses/by-sa/3.0/) by [Matan Kushner](https://matchai.me/).
122 |
--------------------------------------------------------------------------------
/cli-main.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | "use strict";
3 | const ts = require("typescript");
4 | const meow = require("meow");
5 | const tsQuick = require(".");
6 | const projectInit = require("./lib/project-init");
7 |
8 | const cli = meow(
9 | `
10 | Usage
11 | $ ts-quick [ ...]
12 |
13 | Options
14 | --init Add ts-quick to your project
15 | --implicitAny Allow variables to implicitly have the "any" type
16 | --ignore Additional paths to ignore [Can be set multiple times]
17 | --cwd= Working directory for files
18 |
19 | Examples
20 | $ ts-quick
21 | $ ts-quick index.js
22 | $ ts-quick *.js !foo.js
23 | $ ts-quick --init
24 | $ ts-quick --implicitAny
25 |
26 | Tips
27 | Put options in package.json instead of using flags so other tools can read it.
28 | `,
29 | {
30 | booleanDefault: undefined,
31 | flags: {
32 | init: {
33 | type: "boolean"
34 | },
35 | implicitAny: {
36 | type: "boolean"
37 | },
38 | ignore: {
39 | type: "string"
40 | },
41 | cwd: {
42 | type: "string"
43 | },
44 | // WIP: Only present for testing
45 | reporter: {
46 | type: "string"
47 | }
48 | }
49 | }
50 | );
51 |
52 | const { input, flags: options } = cli;
53 |
54 | /**
55 | * Format and log the reported results.
56 | * @param {ts.Diagnostic[]} diagnostics - A list of reported diagnostics from TypeScript
57 | */
58 | function log(diagnostics) {
59 | let reporter = tsQuick.typescriptFormatter;
60 |
61 | if (options.reporter === "json") {
62 | reporter = require("./lib/json-formatter");
63 | }
64 |
65 | process.stdout.write(reporter(diagnostics));
66 | process.exit(diagnostics.length === 0 ? 0 : 1);
67 | }
68 |
69 | async function main() {
70 | if (options.init) {
71 | await projectInit(options);
72 | } else {
73 | const diagnostics = await tsQuick.analyzeFiles(input, options);
74 | log(diagnostics);
75 | }
76 | }
77 |
78 | main();
79 |
--------------------------------------------------------------------------------
/cli.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | "use strict";
3 | // @ts-ignore: No type declaration exists
4 | const resolveCwd = require("resolve-cwd");
5 |
6 | const localCLI = resolveCwd.silent("ts-quick/cli");
7 |
8 | if (localCLI && localCLI !== __filename) {
9 | const debug = require("debug")("ts-quick");
10 | debug("Using local install of ts-quick");
11 | require(localCLI);
12 | } else {
13 | require("./cli-main");
14 | }
15 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | const ts = require("typescript");
2 | const globby = require("globby");
3 | const arrify = require("arrify");
4 | const optionsManager = require("./lib/options-manager");
5 |
6 | /**
7 | * Statically analyze the provided fileNames with TypeScript.
8 | * @param {string[]} patterns - A list of glob patterns.
9 | * @param {object} options - The compiler options which should be used by TypeScript.
10 | */
11 | async function analyzeFiles(patterns, options) {
12 | options = optionsManager.buildConfig(options);
13 |
14 | const isEmptyPatterns = patterns.length === 0;
15 | const defaultPattern = `**/*.{js,jsx,ts,tsx}`;
16 |
17 | const paths = await globby(
18 | isEmptyPatterns ? [defaultPattern] : arrify(patterns),
19 | {
20 | ignore: options.ignores,
21 | gitignore: true,
22 | cwd: options.cwd
23 | }
24 | );
25 |
26 | let program = ts.createProgram(paths, options.config);
27 | let emitResult = program.emit();
28 |
29 | let allDiagnostics = ts
30 | .getPreEmitDiagnostics(program)
31 | .concat(emitResult.diagnostics);
32 |
33 | return allDiagnostics;
34 | }
35 |
36 | /**
37 | * Format all provided diagnostics with the TypeScript-provided formatter.
38 | * @param {ts.Diagnostic[]} allDiagnostics - A list of all reported diagnostics from TypeScript.
39 | */
40 | function typescriptFormatter(allDiagnostics) {
41 | return ts.formatDiagnosticsWithColorAndContext(allDiagnostics, {
42 | getCanonicalFileName: fileName => fileName,
43 | getCurrentDirectory: () => process.cwd(),
44 | getNewLine: () => ts.sys.newLine
45 | });
46 | }
47 |
48 | module.exports.analyzeFiles = analyzeFiles;
49 | module.exports.typescriptFormatter = typescriptFormatter;
50 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | setupFilesAfterEnv: ["/test/test-setup.js"]
3 | };
4 |
--------------------------------------------------------------------------------
/lib/json-formatter.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Format TypeScript diagnostics as a JSON object
3 | * @param {Object[]} diagnostics - The list of diagnostics from TypeScript
4 | */
5 | function jsonFormatter(diagnostics) {
6 | // TODO: The bulk of the output is stripped until circular references are solved
7 | return JSON.stringify(diagnostics, (key, val) => {
8 | if (key !== "file") {
9 | return val;
10 | }
11 | const { fileName } = val;
12 | return { fileName };
13 | });
14 | }
15 |
16 | module.exports = jsonFormatter;
17 |
--------------------------------------------------------------------------------
/lib/options-manager.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 | const ts = require("typescript");
3 | const arrify = require("arrify");
4 | const pkgConf = require("pkg-conf");
5 |
6 | const DEFAULT_IGNORE = [
7 | "**/node_modules/**",
8 | "**/bower_components/**",
9 | "flow-typed/**",
10 | "coverage/**",
11 | "{tmp,temp}/**",
12 | "**/*.min.js",
13 | "vendor/**",
14 | "dist/**"
15 | ];
16 |
17 | const DEFAULT_CONFIG = {
18 | allowJs: true,
19 | checkJs: true,
20 | noEmit: true,
21 | noImplicitAny: true,
22 | target: ts.ScriptTarget.Latest,
23 | jsx: true,
24 | module: ts.ModuleKind.CommonJS
25 | };
26 |
27 | const defaultOptions = {
28 | config: DEFAULT_CONFIG
29 | };
30 |
31 | /**
32 | * Normalize all options with plural versions of their option names.
33 | * @param {Object} options - Options provided by the user as cli flags
34 | */
35 | function normalizeOptions(options) {
36 | options = Object.assign({}, options);
37 |
38 | const aliases = ["ignore"];
39 |
40 | for (const singular of aliases) {
41 | const plural = singular + "s";
42 | let value = options[plural] || options[singular];
43 |
44 | delete options[singular];
45 |
46 | if (value === undefined) {
47 | continue;
48 | }
49 |
50 | options[plural] = arrify(value);
51 | }
52 |
53 | return options;
54 | }
55 |
56 | /**
57 | * Merge the options provided as flags with the options in package.json
58 | * @param {Object} options - Options provided by the user as cli flags
59 | */
60 | function mergeWithPkgConf(options) {
61 | options = { cwd: process.cwd(), ...options };
62 | options.cwd = path.resolve(options.cwd);
63 | const config = pkgConf.sync("ts-quick", {
64 | cwd: options.cwd,
65 | skipOnFalse: true
66 | });
67 | return { ...config, ...options };
68 | }
69 |
70 | /**
71 | * Restructure user-provided options and merge them with default options to
72 | * build a config, as required by the TypeScript compiler.
73 | * @param {Object} options - Options provided by the user as cli flags
74 | */
75 | function buildConfig(options) {
76 | options = mergeWithPkgConf(options);
77 | options = normalizeOptions(options);
78 | options = { ...defaultOptions, ...options };
79 |
80 | if (options.implicitAny) {
81 | options.config.noImplicitAny = !options.implicitAny;
82 | }
83 |
84 | options.ignores = DEFAULT_IGNORE.concat(options.ignores || []);
85 | return options;
86 | }
87 |
88 | module.exports.buildConfig = buildConfig;
89 | module.exports.mergeWithPkgConf = mergeWithPkgConf;
90 | module.exports.normalizeOptions = normalizeOptions;
91 |
--------------------------------------------------------------------------------
/lib/project-init.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 | const readPkgUp = require("read-pkg-up");
3 | const writePkg = require("write-pkg");
4 | // @ts-ignore: No type declaration exists
5 | const hasYarn = require("has-yarn");
6 | const execa = require("execa");
7 |
8 | const DEFAULT_TEST_SCRIPT = 'echo "Error: no test specified" && exit 1';
9 |
10 | /**
11 | * Create a new test script, prepending ts-quick as a test step
12 | * @param {string} test - The previous test script from package.json
13 | */
14 | function buildTestScript(test) {
15 | if (test && test !== DEFAULT_TEST_SCRIPT) {
16 | // Don't add if it's already there
17 | if (!/^ts-quick( |$)/.test(test)) {
18 | return `ts-quick && ${test}`;
19 | }
20 |
21 | return test;
22 | }
23 |
24 | return "ts-quick";
25 | }
26 |
27 | /**
28 | * Initialize a project by installing ts-script and adding it to the test script
29 | * @param {Object} options - An object containing the CLI flags
30 | */
31 | async function projectInit(options = {}) {
32 | const pkgData = await readPkgUp({
33 | cwd: options.cwd,
34 | normalize: false
35 | });
36 | const pkg = pkgData.pkg || {};
37 | const pkgPath =
38 | pkgData.path || path.resolve(options.cwd || "", "package.json");
39 | const pkgCwd = path.dirname(pkgPath);
40 |
41 | pkg.scripts = pkg.scripts || {};
42 | pkg.scripts.test = buildTestScript(pkg.scripts.test);
43 |
44 | await writePkg(pkgPath, pkg);
45 |
46 | if (hasYarn(pkgCwd)) {
47 | return execa(
48 | "yarn",
49 | ["add", "--dev", "--ignore-workspace-root-check", "ts-quick"],
50 | { cwd: pkgCwd }
51 | );
52 | }
53 |
54 | return execa("npm", ["install", "--save-dev", "ts-quick"], { cwd: pkgCwd });
55 | }
56 |
57 | module.exports = projectInit;
58 |
--------------------------------------------------------------------------------
/media/demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matchai/ts-quick/947e6980bb2eb95db759e65b362baec2727ca576/media/demo.png
--------------------------------------------------------------------------------
/media/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matchai/ts-quick/947e6980bb2eb95db759e65b362baec2727ca576/media/logo.png
--------------------------------------------------------------------------------
/media/logo.svg:
--------------------------------------------------------------------------------
1 |
34 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ts-quick",
3 | "version": "0.0.0-semantic-release",
4 | "description": "⚡️ Zero configuration static analysis using TypeScript",
5 | "license": "ISC",
6 | "repository": "matchai/ts-quick",
7 | "author": "Matan Kushner ",
8 | "bin": "cli.js",
9 | "engines": {
10 | "node": ">=8"
11 | },
12 | "scripts": {
13 | "test": "./cli.js && jest"
14 | },
15 | "files": [
16 | "lib",
17 | "*.js"
18 | ],
19 | "keywords": [
20 | "typescript",
21 | "static",
22 | "analysis",
23 | "javascript",
24 | "precommit",
25 | "cli",
26 | "check",
27 | "checker",
28 | "code",
29 | "quality",
30 | "verify"
31 | ],
32 | "dependencies": {
33 | "arrify": "2.0.1",
34 | "debug": "4.1.1",
35 | "execa": "2.0.3",
36 | "globby": "10.0.1",
37 | "has-yarn": "2.1.0",
38 | "meow": "5.0.0",
39 | "pkg-conf": "3.1.0",
40 | "read-pkg-up": "5.0.0",
41 | "resolve-cwd": "3.0.0",
42 | "typescript": "3.5.3",
43 | "write-pkg": "4.0.0"
44 | },
45 | "devDependencies": {
46 | "@types/arrify": "1.0.4",
47 | "@types/debug": "4.1.4",
48 | "@types/execa": "0.9.0",
49 | "@types/meow": "5.0.0",
50 | "@types/node": "10.14.12",
51 | "@types/pkg-conf": "2.1.0",
52 | "@types/read-pkg-up": "3.0.1",
53 | "@types/write-pkg": "3.1.0",
54 | "husky": "2.7.0",
55 | "jest": "24.8.0",
56 | "prettier": "1.18.2",
57 | "pretty-quick": "1.11.1"
58 | },
59 | "ts-quick": {
60 | "ignore": "./test"
61 | },
62 | "husky": {
63 | "hooks": {
64 | "pre-commit": "pretty-quick --staged"
65 | }
66 | },
67 | "renovate": {
68 | "extends": [
69 | "config:base",
70 | ":rebaseStalePrs",
71 | ":automergeMinor"
72 | ]
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/test/fixtures/default/bar.js:
--------------------------------------------------------------------------------
1 | add(1, 2);
2 |
--------------------------------------------------------------------------------
/test/fixtures/default/foo.js:
--------------------------------------------------------------------------------
1 | function square(n) {
2 | return n * n;
3 | }
4 |
--------------------------------------------------------------------------------
/test/fixtures/default/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "default",
3 | "version": "1.0.0"
4 | }
5 |
--------------------------------------------------------------------------------
/test/fixtures/gitignore/.gitignore:
--------------------------------------------------------------------------------
1 | foo.js
2 | !bar.js
3 |
--------------------------------------------------------------------------------
/test/fixtures/gitignore/bar.js:
--------------------------------------------------------------------------------
1 | function square(n) {
2 | return n * n;
3 | }
4 |
--------------------------------------------------------------------------------
/test/fixtures/gitignore/foo.js:
--------------------------------------------------------------------------------
1 | function square(n) {
2 | return n * n;
3 | }
4 |
--------------------------------------------------------------------------------
/test/fixtures/negative-gitignore/.gitignore:
--------------------------------------------------------------------------------
1 | *.js
2 | !foo.js
3 |
--------------------------------------------------------------------------------
/test/fixtures/negative-gitignore/bar.js:
--------------------------------------------------------------------------------
1 | function square(n) {
2 | return n * n;
3 | }
4 |
--------------------------------------------------------------------------------
/test/fixtures/negative-gitignore/foo.js:
--------------------------------------------------------------------------------
1 | function square(n) {
2 | return n * n;
3 | }
4 |
--------------------------------------------------------------------------------
/test/fixtures/pkgConf/bar.js:
--------------------------------------------------------------------------------
1 | add(1, 2);
2 |
--------------------------------------------------------------------------------
/test/fixtures/pkgConf/baz.js:
--------------------------------------------------------------------------------
1 | add(1, 2);
2 |
--------------------------------------------------------------------------------
/test/fixtures/pkgConf/foo.js:
--------------------------------------------------------------------------------
1 | function square(n) {
2 | return n * n;
3 | }
4 |
--------------------------------------------------------------------------------
/test/fixtures/pkgConf/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pkg-conf",
3 | "version": "1.0.0",
4 | "ts-quick": {
5 | "ignore": "bar.js",
6 | "implicitAny": false
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/test/index.test.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 | const execa = require("execa");
3 |
4 | const main = (args, options) =>
5 | execa(path.join(__dirname, "../cli-main.js"), args, options);
6 |
7 | test("the default configuration finds errors", async () => {
8 | const cwd = path.join(__dirname, "fixtures/default");
9 |
10 | let error;
11 | try {
12 | await main(["--reporter=json"], { cwd });
13 | } catch (err) {
14 | error = err;
15 | }
16 |
17 | const diagnostics = JSON.parse(error.stdout);
18 | expect(diagnostics).toHaveLength(2);
19 | expect(diagnostics[0]).toHaveProperty("file.fileName", "bar.js");
20 | expect(diagnostics[0]).toHaveProperty(
21 | "messageText",
22 | "Cannot find name 'add'."
23 | );
24 | expect(diagnostics[1]).toHaveProperty("file.fileName", "foo.js");
25 | expect(diagnostics[1]).toHaveProperty(
26 | "messageText",
27 | "Parameter 'n' implicitly has an 'any' type."
28 | );
29 | });
30 |
31 | test("implicitAny ignores missing type annotations", async () => {
32 | const cwd = path.join(__dirname, "fixtures/default");
33 |
34 | let error;
35 | try {
36 | await main(["--reporter=json", "--implicitAny"], { cwd });
37 | } catch (err) {
38 | error = err;
39 | }
40 |
41 | const diagnostics = JSON.parse(error.stdout);
42 | expect(diagnostics).toHaveLength(1);
43 | expect(diagnostics[0]).toHaveProperty("file.fileName", "bar.js");
44 | expect(diagnostics[0]).toHaveProperty(
45 | "messageText",
46 | "Cannot find name 'add'."
47 | );
48 | });
49 |
50 | test("correctly ignores files in .gitignore", async () => {
51 | const cwd = path.join(__dirname, "fixtures/gitignore");
52 |
53 | let error;
54 | try {
55 | await main(["--reporter=json"], { cwd });
56 | } catch (err) {
57 | error = err;
58 | }
59 |
60 | const diagnostics = JSON.parse(error.stdout);
61 | expect(diagnostics).toHaveLength(1);
62 | expect(diagnostics[0]).toHaveProperty("file.fileName", "bar.js");
63 | expect(diagnostics[0]).toHaveProperty(
64 | "messageText",
65 | "Parameter 'n' implicitly has an 'any' type."
66 | );
67 | });
68 |
69 | test("correctly ignores files explicitly called when also in .gitignore", async () => {
70 | const cwd = path.join(__dirname, "fixtures/gitignore");
71 |
72 | let error;
73 | try {
74 | await main(["test/foo.js", "--reporter=json"], { cwd });
75 | } catch (err) {
76 | error = err;
77 | }
78 |
79 | expect(error).toBeUndefined();
80 | });
81 |
82 | test("correctly locates negative gitignores", async () => {
83 | const cwd = path.join(__dirname, "fixtures/negative-gitignore");
84 |
85 | let error;
86 | try {
87 | await main(["--reporter=json"], { cwd });
88 | } catch (err) {
89 | error = err;
90 | }
91 |
92 | const diagnostics = JSON.parse(error.stdout);
93 | expect(diagnostics).toHaveLength(1);
94 | expect(diagnostics[0]).toHaveProperty("file.fileName", "foo.js");
95 | expect(diagnostics[0]).toHaveProperty(
96 | "messageText",
97 | "Parameter 'n' implicitly has an 'any' type."
98 | );
99 | });
100 |
--------------------------------------------------------------------------------
/test/options-manager.test.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 | const manager = require("../lib/options-manager");
3 |
4 | describe("normalizeOptions", () => {
5 | it("makes all the options plural and arrays", () => {
6 | const options = manager.normalizeOptions({
7 | ignore: "test.js"
8 | });
9 |
10 | expect(options).toEqual({
11 | ignores: ["test.js"]
12 | });
13 | });
14 |
15 | it("keeps falsey values as falsey", () => {
16 | expect(manager.normalizeOptions({})).toEqual({});
17 | });
18 | });
19 |
20 | describe("buildConfig", () => {
21 | it("correctly outputs the defaults", () => {
22 | const cwd = path.join(__dirname, "fixtures/default");
23 | const options = manager.buildConfig({ cwd });
24 | expect(options.cwd).toMatch(/test\/fixtures\/default$/);
25 | expect(options.config).toEqual({
26 | allowJs: true,
27 | checkJs: true,
28 | noEmit: true,
29 | noImplicitAny: true,
30 | target: 8,
31 | jsx: true,
32 | module: 1
33 | });
34 | expect(options.ignores).toEqual([
35 | "**/node_modules/**",
36 | "**/bower_components/**",
37 | "flow-typed/**",
38 | "coverage/**",
39 | "{tmp,temp}/**",
40 | "**/*.min.js",
41 | "vendor/**",
42 | "dist/**"
43 | ]);
44 | });
45 |
46 | it("correctly accepts implicitAny", () => {
47 | const cwd = path.join(__dirname, "fixtures/default");
48 | const options = manager.buildConfig({ cwd, implicitAny: true });
49 | expect(options.cwd).toMatch(/test\/fixtures\/default$/);
50 | expect(options.config).toEqual({
51 | allowJs: true,
52 | checkJs: true,
53 | noEmit: true,
54 | noImplicitAny: false,
55 | target: 8,
56 | jsx: true,
57 | module: 1
58 | });
59 | expect(options.ignores).toEqual([
60 | "**/node_modules/**",
61 | "**/bower_components/**",
62 | "flow-typed/**",
63 | "coverage/**",
64 | "{tmp,temp}/**",
65 | "**/*.min.js",
66 | "vendor/**",
67 | "dist/**"
68 | ]);
69 | });
70 | });
71 |
72 | describe("mergeWithPkgConf", () => {
73 | it("correctly formats package config", () => {
74 | const cwd = path.join(__dirname, "fixtures/pkgConf");
75 | const options = manager.mergeWithPkgConf({ cwd });
76 | expect(options).toEqual({
77 | cwd: expect.stringMatching(/test\/fixtures\/pkgConf$/),
78 | ignore: "bar.js",
79 | implicitAny: false
80 | });
81 | });
82 |
83 | it("merges options with the package config and flags", () => {
84 | const cwd = path.join(__dirname, "fixtures/pkgConf");
85 | const options = manager.mergeWithPkgConf({ cwd, implicitAny: true });
86 | expect(options).toEqual({
87 | cwd: expect.stringMatching(/test\/fixtures\/pkgConf$/),
88 | ignore: "bar.js",
89 | implicitAny: true
90 | });
91 | });
92 |
93 | it("ignores missing package config", () => {
94 | const cwd = path.join(__dirname, "fixtures/default");
95 | const options = manager.mergeWithPkgConf({ cwd });
96 | expect(options).toEqual({
97 | cwd: expect.stringMatching(/test\/fixtures\/default$/)
98 | });
99 | });
100 | });
101 |
--------------------------------------------------------------------------------
/test/test-setup.js:
--------------------------------------------------------------------------------
1 | jest.setTimeout(15000);
2 |
--------------------------------------------------------------------------------