Skip to content

Commit

Permalink
Fix error messages when tsd fails (#189)
Browse files Browse the repository at this point in the history
  • Loading branch information
tommy-mitchell committed Mar 21, 2023
1 parent 58b85ce commit c785d9c
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 6 deletions.
6 changes: 6 additions & 0 deletions source/cli.ts
@@ -1,5 +1,6 @@
#!/usr/bin/env node
import meow from 'meow';
import {TsdError} from './lib/interfaces';
import formatter from './lib/formatter';
import tsd from './lib';

Expand Down Expand Up @@ -75,6 +76,11 @@ const exit = (message: string, {isError = true}: {isError?: boolean} = {}) => {
}
} catch (error: unknown) {
const potentialError = error as Error | undefined;

if (potentialError instanceof TsdError) {
exit(potentialError.message);
}

const errorMessage = potentialError?.stack ?? potentialError?.message ?? 'tsd unexpectedly crashed.';

exit(`Error running tsd:\n${errorMessage}`);
Expand Down
10 changes: 5 additions & 5 deletions source/lib/index.ts
Expand Up @@ -5,7 +5,7 @@ import globby from 'globby';
import {getDiagnostics as getTSDiagnostics} from './compiler';
import loadConfig from './config';
import getCustomDiagnostics from './rules';
import {Context, Config, Diagnostic, PackageJsonWithTsdConfig} from './interfaces';
import {Context, Config, Diagnostic, PackageJsonWithTsdConfig, TsdError} from './interfaces';

export interface Options {
cwd: string;
Expand All @@ -25,7 +25,7 @@ const findTypingsFile = async (pkg: PackageJsonWithTsdConfig, options: Options):
const typingsExist = await pathExists(typingsPath);

if (!typingsExist) {
throw new Error(`The type definition \`${typings}\` does not exist at \`${typingsPath}\`. Is the path correct? Create one and try again.`);
throw new TsdError(`The type definition \`${typings}\` does not exist at \`${typingsPath}\`. Is the path correct? Create one and try again.`);
}

return typings;
Expand All @@ -43,7 +43,7 @@ const findCustomTestFiles = async (testFilesPattern: readonly string[], cwd: str
const testFiles = await globby(testFilesPattern, {cwd});

if (testFiles.length === 0) {
throw new Error('Could not find any test files with the given pattern(s). Create one and try again.');
throw new TsdError('Could not find any test files with the given pattern(s). Create one and try again.');
}

return testFiles.map(file => path.join(cwd, file));
Expand All @@ -65,7 +65,7 @@ const findTestFiles = async (typingsFilePath: string, options: Options & {config
const testDirExists = await pathExists(path.join(options.cwd, testDir));

if (testFiles.length === 0 && !testDirExists) {
throw new Error(`The test file \`${testFile}\` or \`${tsxTestFile}\` does not exist in \`${options.cwd}\`. Create one and try again.`);
throw new TsdError(`The test file \`${testFile}\` or \`${tsxTestFile}\` does not exist in \`${options.cwd}\`. Create one and try again.`);
}

if (testFiles.length === 0) {
Expand All @@ -84,7 +84,7 @@ export default async (options: Options = {cwd: process.cwd()}): Promise<Diagnost
const pkgResult = await readPkgUp({cwd: options.cwd});

if (!pkgResult) {
throw new Error(`No \`package.json\` file found in \`${options.cwd}\`. Make sure you are running the command in a Node.js project.`);
throw new TsdError(`No \`package.json\` file found in \`${options.cwd}\`. Make sure you are running the command in a Node.js project.`);
}

const pkg = pkgResult.packageJson as PackageJsonWithTsdConfig;
Expand Down
7 changes: 7 additions & 0 deletions source/lib/interfaces.ts
Expand Up @@ -71,3 +71,10 @@ export interface Location {
start: number;
end: number;
}

export class TsdError extends Error {
constructor(message: string) {
super(message);
this.name = this.constructor.name;
}
}
9 changes: 9 additions & 0 deletions source/test/cli.ts
Expand Up @@ -191,3 +191,12 @@ test('warnings are reported with errors', async t => {
'1 error',
]);
});

test('tsd failures (not crashes) report only the message', async t => {
const cwd = path.join(__dirname, 'fixtures/no-tsd');

const {exitCode, stderr} = await t.throwsAsync<ExecaError>(execa('../../../cli.js', {cwd}));

t.is(exitCode, 1);
t.is(stderr, `The type definition \`index.d.ts\` does not exist at \`${cwd}/index.d.ts\`. Is the path correct? Create one and try again.`);
});
13 changes: 12 additions & 1 deletion source/test/test.ts
Expand Up @@ -2,7 +2,7 @@ import path from 'path';
import test from 'ava';
import {verify, verifyWithFileName} from './fixtures/utils';
import tsd from '..';
import {Diagnostic} from '../lib/interfaces';
import {Diagnostic, TsdError} from '../lib/interfaces';

test('throw if no type definition was found', async t => {
const cwd = path.join(__dirname, 'fixtures/no-tsd');
Expand Down Expand Up @@ -427,3 +427,14 @@ test('parsing undefined symbol should not fail', async t => {

verify(t, diagnostics, []);
});

test('custom tsd errors are created correctly', t => {
const tsdError = t.throws<TsdError>(() => {
throw new TsdError('foo');
});

t.true(tsdError instanceof Error);
t.true(tsdError instanceof TsdError);
t.is(tsdError.name, 'TsdError');
t.is(tsdError.message, 'foo');
});

0 comments on commit c785d9c

Please sign in to comment.