Skip to content

Commit

Permalink
test Typescript type declaration
Browse files Browse the repository at this point in the history
To run the test without those slow test: `npx ava --match ‘!*[slow]’`.
  • Loading branch information
dinoboff committed Dec 11, 2017
1 parent 72638c6 commit f09e945
Show file tree
Hide file tree
Showing 12 changed files with 177 additions and 1 deletion.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"codecov": "^3.0.0",
"delay": "^2.0.0",
"nyc": "^11.3.0",
"pkg-dir": "^2.0.0",
"typescript": "^2.6.2",
"xo": "*"
},
Expand Down
6 changes: 6 additions & 0 deletions test/fixtures/compiles/emit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import Emittery = require('../../..');

const ee = new Emittery();

ee.emit('anEvent');
ee.emit('anEvent', 'some data');
10 changes: 10 additions & 0 deletions test/fixtures/compiles/off.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Emittery = require('../../..');

const ee = new Emittery();
const listener = () => undefined;

ee.off('anEvent', () => undefined);
ee.off('anEvent', () => Promise.resolve());

ee.off('anEvent', data => undefined);
ee.off('anEvent', data => Promise.resolve());
13 changes: 13 additions & 0 deletions test/fixtures/compiles/on.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Emittery = require('../../..');

const ee = new Emittery();

ee.on('anEvent', () => undefined);
ee.on('anEvent', () => Promise.resolve());

ee.on('anEvent', data => undefined);
ee.on('anEvent', data => Promise.resolve());

const off = ee.on('anEvent', () => undefined);

off();
11 changes: 11 additions & 0 deletions test/fixtures/compiles/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"target": "es2017",
"lib": ["es2017"],
"module": "commonjs",
"strict": true,
"moduleResolution": "node",
"allowSyntheticDefaultImports": true
},
"include": ["*.ts"]
}
6 changes: 6 additions & 0 deletions test/fixtures/fails/emit-extra.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import Emittery = require('../../..');

const ee = new Emittery();

ee.emit('anEvent');
ee.emit('anEvent', 'some data', 'and more');
6 changes: 6 additions & 0 deletions test/fixtures/fails/on-extra.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import Emittery = require('../../..');

const ee = new Emittery();

ee.on('anEvent', (data, more) => undefined);

11 changes: 11 additions & 0 deletions test/fixtures/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"target": "es2017",
"lib": ["es2017"],
"module": "commonjs",
"strict": true,
"moduleResolution": "node",
"allowSyntheticDefaultImports": true
},
"include": ["*.ts"]
}
32 changes: 32 additions & 0 deletions test/snapshots/types.js.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Snapshot report for `test/types.js`

The actual snapshot is saved in `types.js.snap`.

Generated by [AVA](https://ava.li).

## Type definition disallows invalid Emittery method calls to compile

> Snapshot 1
`test/fixtures/fails/emit-extra.ts (6,1): Expected 1-2 arguments, but got 3.␊
test/fixtures/fails/on-extra.ts (5,18): Argument of type '(data: any, more: any) => undefined' is not assignable to parameter of type '() => any'.␊
test/fixtures/fails/on-extra.ts (5,19): Parameter 'data' implicitly has an 'any' type.␊
test/fixtures/fails/on-extra.ts (5,25): Parameter 'more' implicitly has an 'any' type.

## Type definition disallows invalid Emittery method calls to compile [slow]

> Snapshot 1
`test/fixtures/fails/emit-extra.ts (6,1): Expected 1-2 arguments, but got 3.␊
test/fixtures/fails/on-extra.ts (5,18): Argument of type '(data: any, more: any) => undefined' is not assignable to parameter of type '() => any'.␊
test/fixtures/fails/on-extra.ts (5,19): Parameter 'data' implicitly has an 'any' type.␊
test/fixtures/fails/on-extra.ts (5,25): Parameter 'more' implicitly has an 'any' type.

## TS warns about invalid Emittery method calls [slow]

> Snapshot 1
`test/fixtures/fails/emit-extra.ts (6,1): Expected 1-2 arguments, but got 3.␊
test/fixtures/fails/on-extra.ts (5,18): Argument of type '(data: any, more: any) => undefined' is not assignable to parameter of type '(eventData?: any) => any'.␊
test/fixtures/fails/on-extra.ts (5,19): Parameter 'data' implicitly has an 'any' type.␊
test/fixtures/fails/on-extra.ts (5,25): Parameter 'more' implicitly has an 'any' type.`
Binary file added test/snapshots/types.js.snap
Binary file not shown.
79 changes: 79 additions & 0 deletions test/types.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import {readdirSync, statSync} from 'fs';
import {resolve as _resolve, join, extname, relative} from 'path';
import pkgUp from 'pkg-dir';

import test from 'ava';
import * as ts from 'typescript';

const resolve = _resolve.bind(null, __dirname);
const validExtension = new Set(['.js', '.ts']);
const compilerOptions = {
target: ts.ScriptTarget.ES2017,
module: ts.ModuleKind.CommonJS,
strict: true,
noEmit: true
};

test('TS can compile valid Emittery method calls [slow]', assertAllCompile, './fixtures/compiles');
test('TS warns about invalid Emittery method calls [slow]', assertEachFail, './fixtures/fails');

function assertAllCompile(t, srcDir) {
const fileNames = listFiles(resolve(srcDir));
const errors = compile(fileNames);

t.is(errors.length, 0, errorMessage(errors));
}

function assertEachFail(t, srcDir) {
const fileNames = listFiles(resolve(srcDir)).sort();
const errors = compile(fileNames);
const filesWithErrors = errors
.map(err => (err.file ? err.file.fileName : null))
.filter(Boolean)
.filter(unique);

t.deepEqual(filesWithErrors, fileNames, 'Some file did not emit any compile error.');
t.snapshot(errorMessage(errors));
}

function listFiles(srcRoot) {
return readdirSync(srcRoot)
.filter(hasValidExtension)
.map(name => join(srcRoot, name))
.filter(isFile);
}

function compile(fileNames, options = compilerOptions) {
const program = ts.createProgram(fileNames, options);
const emitResult = program.emit();

return ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);
}

function errorMessage(diagnosticList) {
const root = pkgUp.sync();

return diagnosticList.map(diagnostic => {
if (!diagnostic.file) {
return `${ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n')}`;
}

const {line, character} = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
const fileName = relative(root, diagnostic.file.fileName);

return `${fileName} (${line + 1},${character + 1}): ${message}`;
}).join('\n');
}

function isFile(path) {
return statSync(path).isFile();
}

function hasValidExtension(path) {
return validExtension.has(extname(path));
}

function unique(value, index, list) {
return list.indexOf(value) === index;
}
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@
"allowSyntheticDefaultImports": true,
"allowJs": true
},
"include": ["**/*.ts"]
"include": ["**/*"],
"exclude": ["test/fixtures/**/*"]
}

0 comments on commit f09e945

Please sign in to comment.