Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow specifying the test files and typings file manually #74

Merged
merged 23 commits into from
Dec 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
0122488
Remove VSCode config folder and add source code generation in TS build
smartclash Jun 24, 2020
e706b63
Allow passing of path to type definiton file manually
smartclash Jun 24, 2020
43ac091
Update README.md
smartclash Jun 24, 2020
1282ce6
Refactor code to check definition file existence if specified manually
smartclash Jun 24, 2020
8185162
Fix the checking of type file existence
smartclash Jun 24, 2020
35063ce
Use expect error instead of ignoring it
smartclash Jun 24, 2020
4d23908
Allow specifing test files manually
smartclash Jun 25, 2020
c7e427b
Allow passing relative path of typing def file
smartclash Jul 2, 2020
4cf8cb4
Allow passing relative path to test files
smartclash Jul 2, 2020
ea3961a
Make changes according to suggestions
smartclash Jul 23, 2020
134b88c
Fixed README alignment
smartclash Jul 24, 2020
64409b3
Add tests for new typingsFile option
smartclash Aug 7, 2020
6d24bca
Fixed tests file resolving issue when typingsFile option is set
smartclash Aug 7, 2020
1d391ae
Add tests for testFiles option
smartclash Aug 7, 2020
d925296
Add tests to check cases where typings file is not found in specified…
smartclash Aug 7, 2020
59670d6
Use globby for testFiles option
smartclash Aug 9, 2020
41e9e0c
Remove .vscode entry in gitignore
smartclash Oct 4, 2020
02927f0
Update docs
smartclash Oct 4, 2020
285c6cb
Make testFiles property readonly
smartclash Oct 4, 2020
59c5f4b
Fix grammar
smartclash Oct 4, 2020
9ece40e
Grammar in README
smartclash Oct 5, 2020
44c066e
Update readme.md
smartclash Dec 3, 2020
c549587
Improve readme
smartclash Dec 3, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,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 @@ -65,11 +64,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 @@ -220,3 +220,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.');
});