Skip to content

Commit

Permalink
Allow specifying the test files and typings file manually (#74)
Browse files Browse the repository at this point in the history
  • Loading branch information
smartclash authored Dec 3, 2020
1 parent 95174e9 commit 0e9228a
Show file tree
Hide file tree
Showing 12 changed files with 111 additions and 10 deletions.
13 changes: 13 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,19 @@ Default: `process.cwd()`

Current working directory of the project to retrieve the diagnostics for.

##### typingsFile

Type: `string`<br>
Default: The `types` property in `package.json`.

Path to the type definition file you want to test. This can be useful when using a test runner to test specific type definitions per test.

##### testFiles

Type: `string[]`<br>
Default: Finds files with `.test-d.ts` or `.test-d.tsx` extension.

An array of test files with their path. Uses [globby](https://github.com/sindresorhus/globby) under the hood so that you can fine tune test file discovery.

## License

Expand Down
5 changes: 1 addition & 4 deletions source/lib/compiler.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import * as path from 'path';
import {
flattenDiagnosticMessageText,
createProgram,
Expand Down Expand Up @@ -66,11 +65,9 @@ const ignoreDiagnostic = (diagnostic: TSDiagnostic, expectedErrors: Map<Location
* @returns List of diagnostics
*/
export const getDiagnostics = (context: Context): Diagnostic[] => {
const fileNames = context.testFiles.map(fileName => path.join(context.cwd, fileName));

const diagnostics: Diagnostic[] = [];

const program = createProgram(fileNames, context.config.compilerOptions);
const program = createProgram(context.testFiles, context.config.compilerOptions);

const tsDiagnostics = program
.getSemanticDiagnostics()
Expand Down
36 changes: 30 additions & 6 deletions source/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ import {Context, Config} from './interfaces';

export interface Options {
cwd: string;
typingsFile?: string;
testFiles?: readonly string[];
}

const findTypingsFile = async (pkg: any, options: Options) => {
const typings = pkg.types || pkg.typings || 'index.d.ts';

const typings = options.typingsFile || pkg.types || pkg.typings || 'index.d.ts';
const typingsExist = await pathExists(path.join(options.cwd, typings));

if (!typingsExist) {
Expand All @@ -23,13 +24,37 @@ const findTypingsFile = async (pkg: any, options: Options) => {
return typings;
};

const findTestFiles = async (typingsFile: string, options: Options & {config: Config}) => {
const normalizeTypingsFilePath = (typingsFilePath: string, options: Options) => {
if (options.typingsFile) {
return path.basename(typingsFilePath);
}

return typingsFilePath;
};

const findCustomTestFiles = async (testFilesPattern: readonly string[], cwd: string) => {
const testFiles = await globby(testFilesPattern, {cwd});

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

return testFiles.map(file => path.join(cwd, file));
};

const findTestFiles = async (typingsFilePath: string, options: Options & {config: Config}) => {
if (options.testFiles?.length) {
return findCustomTestFiles(options.testFiles, options.cwd);
}

// Return only the filename if the `typingsFile` option is used.
const typingsFile = normalizeTypingsFilePath(typingsFilePath, options);

const testFile = typingsFile.replace(/\.d\.ts$/, '.test-d.ts');
const tsxTestFile = typingsFile.replace(/\.d\.ts$/, '.test-d.tsx');
const testDir = options.config.directory;

let testFiles = await globby([testFile, tsxTestFile], {cwd: options.cwd});

const testDirExists = await pathExists(path.join(options.cwd, testDir));

if (testFiles.length === 0 && !testDirExists) {
Expand All @@ -40,7 +65,7 @@ const findTestFiles = async (typingsFile: string, options: Options & {config: Co
testFiles = await globby([`${testDir}/**/*.ts`, `${testDir}/**/*.tsx`], {cwd: options.cwd});
}

return testFiles;
return testFiles.map(fileName => path.join(options.cwd, fileName));
};

/**
Expand All @@ -56,7 +81,6 @@ export default async (options: Options = {cwd: process.cwd()}) => {
}

const pkg = pkgResult.packageJson;

const config = loadConfig(pkg as any, options.cwd);

// Look for a typings file, otherwise use `index.d.ts` in the root directory. If the file is not found, throw an error.
Expand Down
6 changes: 6 additions & 0 deletions source/test/fixtures/specify-test-files/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
declare const one: {
(foo: string, bar: string): string;
(foo: number, bar: number): number;
};

export default one;
3 changes: 3 additions & 0 deletions source/test/fixtures/specify-test-files/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports.default = (foo, bar) => {
return foo + bar;
};
3 changes: 3 additions & 0 deletions source/test/fixtures/specify-test-files/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"name": "foo"
}
5 changes: 5 additions & 0 deletions source/test/fixtures/specify-test-files/unknown.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import {expectType} from '../../..';
import one from '.';

expectType<string>(one('foo', 'bar'));
expectType<string>(one(1, 2));
3 changes: 3 additions & 0 deletions source/test/fixtures/typings-custom-dir/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports.default = (foo, bar) => {
return foo + bar;
};
5 changes: 5 additions & 0 deletions source/test/fixtures/typings-custom-dir/index.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import {expectType} from '../../..';
import one from './utils';

expectType<string>(one('foo', 'bar'));
expectType<string>(one(1, 2));
3 changes: 3 additions & 0 deletions source/test/fixtures/typings-custom-dir/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"name": "foo"
}
6 changes: 6 additions & 0 deletions source/test/fixtures/typings-custom-dir/utils/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
declare const one: {
(foo: string, bar: string): string;
(foo: number, bar: number): number;
};

export default one;
33 changes: 33 additions & 0 deletions source/test/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,3 +244,36 @@ test('strict types', async t => {

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

test('typings in custom directory', async t => {
const diagnostics = await tsd({
cwd: path.join(__dirname, 'fixtures/typings-custom-dir'),
typingsFile: 'utils/index.d.ts'
});

verify(t, diagnostics, [
[5, 19, 'error', 'Argument of type \'number\' is not assignable to parameter of type \'string\'.']
]);
});

test('specify test files manually', async t => {
const diagnostics = await tsd({
cwd: path.join(__dirname, 'fixtures/specify-test-files'),
testFiles: [
'unknown.test.ts'
]
});

verify(t, diagnostics, [
[5, 19, 'error', 'Argument of type \'number\' is not assignable to parameter of type \'string\'.']
]);
});

test('fails if typings file is not found in the specified path', async t => {
const error = await t.throwsAsync(tsd({
cwd: path.join(__dirname, 'fixtures/typings-custom-dir'),
typingsFile: 'unknown.d.ts'
}));

t.is(error.message, 'The type definition `unknown.d.ts` does not exist. Create one and try again.');
});

0 comments on commit 0e9228a

Please sign in to comment.