├── .gitignore
├── README.md
├── bundler.js
├── dist
├── index.d.ts
├── index.js
└── typescript-definition-tester.d.ts
├── package.json
├── src
└── index.ts
├── test
├── examples
│ ├── compile.ts
│ ├── compileDirectory.ts
│ ├── test.interface.d.ts
│ └── walk.ts
└── index.ts
├── tsconfig.json
└── wercker.yml
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | test/examples/**/*.js
3 | testOut/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Purpose
2 |
3 | The purpose of this repository is to wrap the TypeScript compiler so that a consumer can easily test their ambient module declarations against example *.ts files.
4 | This module uses chai assertions so that a user can easily add this step to existing unit test infrastructure.
5 |
6 | [](https://app.wercker.com/project/bykey/2ad0ff2e7585e4ff41477e6b6876acad)
7 |
8 | ## Install
9 |
10 | * Add typescript-definition-tester to your devDependencies property in your package.json file
11 | ```
12 | npm install typescript-definition-tester --save-dev
13 | ```
14 | * [optional] Link the typescript-definition-tester.d.ts file using tsd `tsd link --save`
15 |
16 | ## Testing
17 |
18 | The recommended way to test ambient module declarations is to create an "examples" directory in your test folder. Then, you can pull in these *.ts example files
19 | in a single test file that will pass these files to the TypeScript compiler.
20 |
21 | Example:
22 |
23 | ```
24 | ///
25 |
26 | import * as ts from "typescript";
27 | import * as tt from "typescript-definition-tester";
28 | import * as fs from "fs";
29 | import * as chai from "chai";
30 |
31 | describe('ambient declaration tests', () => {
32 | it('should compile examples successfully against my-module.d.ts', (done) => {
33 | tt.compileDirectory(
34 | __dirname + '/examples',
35 | (fileName: string) => fileName.indexOf('.ts') > -1,
36 | () => done()
37 | );
38 | });
39 | });
40 | ```
41 |
42 | You should be able to run this test file with mocha `mocha test/my-test-file.js`. The above example is written in TypeScript. You will need to compile this using `tsc --module commonjs test/my-test-file.js` or you can just write your test using normal JavaScript.
--------------------------------------------------------------------------------
/bundler.js:
--------------------------------------------------------------------------------
1 | var dts = require('dts-bundle');
2 | var pkg = require('./package.json');
3 |
4 | dts.bundle({
5 | name: pkg.name,
6 | main: 'dist/index.d.ts'
7 | });
--------------------------------------------------------------------------------
/dist/index.d.ts:
--------------------------------------------------------------------------------
1 | import * as ts from "typescript";
2 | export declare type DoneFunction = (err: any, results?: string[]) => void;
3 | export declare type FilterFunction = (fileName: string) => boolean;
4 | export declare function compile(fileNames: string[], options: ts.CompilerOptions, done: Function): void;
5 | export declare function compileDirectory(path: string, done: Function): void;
6 | export declare function compileDirectory(path: string, options: ts.CompilerOptions, done: Function): void;
7 | export declare function compileDirectory(path: string, filter: FilterFunction, done: Function): void;
8 | export declare function compileDirectory(path: string, filter: FilterFunction, options: ts.CompilerOptions, done: Function): void;
9 | export declare function walk(dir: string, done: DoneFunction): void;
10 | export declare function walk(dir: string, filter: FilterFunction, done: DoneFunction): void;
11 |
--------------------------------------------------------------------------------
/dist/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | const ts = require("typescript");
4 | const fs = require("fs");
5 | const _ = require("lodash");
6 | const AssertionError = require("assertion-error");
7 | var defaultCompilerOptions = {
8 | noEmitOnError: true,
9 | noImplicitAny: true,
10 | target: ts.ScriptTarget.ES5,
11 | module: ts.ModuleKind.CommonJS
12 | };
13 | function handleDiagnostics(type, diagnostics) {
14 | diagnostics.forEach(diagnostic => {
15 | var { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
16 | var message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
17 | throw new AssertionError(`${type}: ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`, {
18 | actual: diagnostic
19 | });
20 | });
21 | }
22 | function compile(fileNames, options, done) {
23 | try {
24 | const program = ts.createProgram(fileNames, options);
25 | // TODO: this is generating errors so disabling for now. Will continue to investigate.
26 | // handleDiagnostics('Declaration', program.getDeclarationDiagnostics());
27 | handleDiagnostics('Global', program.getGlobalDiagnostics());
28 | console.log('Global finished');
29 | handleDiagnostics('Semantic', program.getSemanticDiagnostics());
30 | console.log('Semantic finished');
31 | handleDiagnostics('Syntactic', program.getSyntacticDiagnostics());
32 | console.log('Syntactic finished');
33 | done();
34 | }
35 | catch (e) {
36 | done(e);
37 | }
38 | }
39 | exports.compile = compile;
40 | function compileDirectory(path, filter, options, done) {
41 | if (!done) {
42 | if (!options) {
43 | done = filter;
44 | filter = undefined;
45 | }
46 | else {
47 | done = options;
48 | if (!_.isFunction(filter)) {
49 | options = filter;
50 | options = undefined;
51 | }
52 | }
53 | }
54 | options = _.merge(defaultCompilerOptions, (options || {}));
55 | walk(path, filter, (err, results) => {
56 | if (err) {
57 | console.log('error error error');
58 | throw new AssertionError('Error while walking directory for files.', {
59 | actual: err
60 | });
61 | }
62 | else {
63 | compile(results, options, done);
64 | }
65 | });
66 | }
67 | exports.compileDirectory = compileDirectory;
68 | function walk(dir, filter, done) {
69 | if (!done) {
70 | done = filter;
71 | filter = undefined;
72 | }
73 | var results = [];
74 | fs.readdir(dir, function (err, list) {
75 | if (err) {
76 | return done(err);
77 | }
78 | var i = 0;
79 | (function next() {
80 | var file = list[i++];
81 | if (!file)
82 | return done(null, results);
83 | file = dir + '/' + file;
84 | fs.stat(file, function (err, stat) {
85 | if (stat && stat.isDirectory()) {
86 | walk(file, function (err, res) {
87 | results = results.concat(res);
88 | next();
89 | });
90 | }
91 | else {
92 | if (!filter || filter(file)) {
93 | results.push(file);
94 | }
95 | next();
96 | }
97 | });
98 | })();
99 | });
100 | }
101 | exports.walk = walk;
102 | ;
103 |
--------------------------------------------------------------------------------
/dist/typescript-definition-tester.d.ts:
--------------------------------------------------------------------------------
1 | // Generated by dts-bundle v0.2.0
2 |
3 | declare module 'typescript-definition-tester' {
4 | import * as ts from "typescript";
5 | export type DoneFunction = (err: any, results?: string[]) => void;
6 | export type FilterFunction = (fileName: string) => boolean;
7 | export function compile(fileNames: string[], options: ts.CompilerOptions, done: Function): void;
8 | export function compileDirectory(path: string, done: Function): void;
9 | export function compileDirectory(path: string, options: ts.CompilerOptions, done: Function): void;
10 | export function compileDirectory(path: string, filter: FilterFunction, done: Function): void;
11 | export function compileDirectory(path: string, filter: FilterFunction, options: ts.CompilerOptions, done: Function): void;
12 | export function walk(dir: string, done: DoneFunction): void;
13 | export function walk(dir: string, filter: FilterFunction, done: DoneFunction): void;
14 | }
15 |
16 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "typescript-definition-tester",
3 | "version": "0.0.6",
4 | "description": "",
5 | "main": "dist/index.js",
6 | "scripts": {
7 | "build": "tsc --module CommonJS --declaration --target ES6 ./src/index.ts --outDir dist/ && tsc --module CommonJS ./test/index.ts --outDir testOut/",
8 | "postbuild": "node bundler.js",
9 | "pretest": "npm run build",
10 | "test": "mocha testOut/test/index.js"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "https://github.com/adamcarr/typescript-definition-tester.git"
15 | },
16 | "keywords": [
17 | "typescript"
18 | ],
19 | "author": {
20 | "name": "Adam Carr",
21 | "email": "adam.carr@gmail.com",
22 | "url": "http://blog.adamcarr.net"
23 | },
24 | "license": "MIT",
25 | "devDependencies": {
26 | "@types/assertion-error": "^1.1.0",
27 | "@types/lodash": "^4.14.108",
28 | "@types/mocha": "^5.2.0",
29 | "@types/node": "8",
30 | "bluebird": "^2.9.24",
31 | "mocha": "^5.1.1"
32 | },
33 | "typescript": {
34 | "definition": "./dist/typescript-definition-tester.d.ts"
35 | },
36 | "dependencies": {
37 | "assertion-error": "^1.0.1",
38 | "dts-bundle": "^0.2.0",
39 | "lodash": "^3.6.0"
40 | },
41 | "peerDependencies": {
42 | "typescript": "1.x || 2.x"
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import * as ts from "typescript";
2 | import * as fs from "fs";
3 | import * as _ from "lodash";
4 | import AssertionError = require("assertion-error");
5 |
6 | var defaultCompilerOptions: ts.CompilerOptions = {
7 | noEmitOnError: true,
8 | noImplicitAny: true,
9 | target: ts.ScriptTarget.ES5,
10 | module: ts.ModuleKind.CommonJS
11 | };
12 |
13 | function handleDiagnostics(type: string, diagnostics: ReadonlyArray) {
14 | diagnostics.forEach(diagnostic => {
15 | var { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
16 | var message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
17 | throw new AssertionError(`${type}: ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`, {
18 | actual: diagnostic
19 | });
20 | });
21 | }
22 |
23 | export type DoneFunction = (err: any, results?: string[]) => void;
24 | export type FilterFunction = (fileName: string) => boolean;
25 |
26 | export function compile(fileNames: string[], options: ts.CompilerOptions, done: Function): void {
27 | try {
28 | const program = ts.createProgram(fileNames, options);
29 |
30 | // TODO: this is generating errors so disabling for now. Will continue to investigate.
31 | // handleDiagnostics('Declaration', program.getDeclarationDiagnostics());
32 | handleDiagnostics('Global', program.getGlobalDiagnostics());
33 | handleDiagnostics('Semantic', program.getSemanticDiagnostics());
34 | handleDiagnostics('Syntactic', program.getSyntacticDiagnostics());
35 | done();
36 | }
37 | catch (e) {
38 | done(e);
39 | }
40 | }
41 |
42 | export function compileDirectory(path: string, done: Function): void;
43 | export function compileDirectory(path: string, options: ts.CompilerOptions, done: Function): void;
44 | export function compileDirectory(path: string, filter: FilterFunction, done: Function): void;
45 | export function compileDirectory(path: string, filter: FilterFunction, options: ts.CompilerOptions, done: Function): void;
46 | export function compileDirectory(path: string, filter?: any, options?: any, done?: Function): void {
47 | if (!done) {
48 | if (!options) {
49 | done = filter;
50 | filter = undefined;
51 | } else {
52 | done = options;
53 | if (!_.isFunction(filter)) {
54 | options = filter;
55 | options = undefined;
56 | }
57 | }
58 | }
59 |
60 | options = _.merge(defaultCompilerOptions, (options || {}));
61 |
62 | walk(path, filter, (err, results) => {
63 | if (err) {
64 | console.log('error error error')
65 | throw new AssertionError('Error while walking directory for files.', {
66 | actual: err
67 | });
68 | } else {
69 | compile(results, options, done);
70 | }
71 | });
72 | }
73 |
74 | export function walk(dir: string, done: DoneFunction): void;
75 | export function walk(dir: string, filter: FilterFunction, done: DoneFunction): void;
76 | export function walk(dir: string, filter: FilterFunction | DoneFunction, done?: DoneFunction): void {
77 | if (!done) {
78 | done = filter;
79 | filter = undefined;
80 | }
81 |
82 | var results = [];
83 | fs.readdir(dir, function(err, list) {
84 | if (err) {
85 | return done(err);
86 | }
87 | var i = 0;
88 | (function next() {
89 | var file = list[i++];
90 | if (!file) return done(null, results);
91 | file = dir + '/' + file;
92 | fs.stat(file, function(err, stat) {
93 | if (stat && stat.isDirectory()) {
94 | walk(file, function(err, res) {
95 | results = results.concat(res);
96 | next();
97 | });
98 | } else {
99 | if (!filter || (filter as FilterFunction)(file)) {
100 | results.push(file);
101 | }
102 | next();
103 | }
104 | });
105 | })();
106 | });
107 | };
108 |
--------------------------------------------------------------------------------
/test/examples/compile.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import * as tt from "typescript-definition-tester";
3 | import * as test from 'test';
4 |
5 | tt.compile(['somefilename'], {}, () => {});
6 |
7 | const person: test.IPerson = {
8 | name: 'Adam'
9 | }
--------------------------------------------------------------------------------
/test/examples/compileDirectory.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import * as tt from "typescript-definition-tester";
3 |
4 | tt.compileDirectory('somePath', () => { });
5 | tt.compileDirectory('somePath', {}, () => { });
6 | tt.compileDirectory('somePath', (fileName) => true, () => { });
7 | tt.compileDirectory('somePath', (fileName) => true, {}, () => { });
--------------------------------------------------------------------------------
/test/examples/test.interface.d.ts:
--------------------------------------------------------------------------------
1 | declare module "test" {
2 | export interface IPerson {
3 | name: string;
4 | }
5 | }
--------------------------------------------------------------------------------
/test/examples/walk.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import * as tt from "typescript-definition-tester";
3 |
4 | tt.walk('dirname', (err, result) => { });
5 | tt.walk('dirname', (fileName) => true, (err, result) => { });
--------------------------------------------------------------------------------
/test/index.ts:
--------------------------------------------------------------------------------
1 | import * as ts from "typescript";
2 | import * as tt from "../src/index";
3 | import * as fs from "fs";
4 |
5 | describe('ambient declaration tests', function () {
6 | this.timeout(5000);
7 | it('should compile examples successfully against typescript-definition-tester.d.ts', (done) => {
8 | tt.compileDirectory(
9 | './test/examples',
10 | (fileName: string) => {
11 | console.log('fileName', fileName);
12 | return fileName.indexOf('.ts') > -1;
13 | },
14 | () => done()
15 | );
16 | });
17 | });
18 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "lib": [
4 | "es6"
5 | ],
6 | "module": "commonjs",
7 | "sourceMap": true,
8 | "target": "es6",
9 | "types": [
10 | "assertion-error",
11 | "lodash",
12 | "node",
13 | "mocha"
14 | ],
15 | "typeRoots": [
16 | "node_modules/@types"
17 | ]
18 | },
19 | "compileOnSave": false
20 | }
--------------------------------------------------------------------------------
/wercker.yml:
--------------------------------------------------------------------------------
1 | box: node
2 | # Build definition
3 | # Build definition
4 | build:
5 | # The steps that will be executed on build
6 | steps:
7 | # A step that executes `npm install` command
8 | - npm-install
9 | # A step that executes `npm test` command
10 | - script:
11 | name: dev-setup
12 | code: |
13 | sudo npm install -g mocha && sudo npm install typescript
14 | - npm-test
15 |
16 | # A custom script step, name value is used in the UI
17 | # and the code value contains the command that get executed
18 | - script:
19 | name: echo nodejs information
20 | code: |
21 | echo "node version $(node -v) running"
22 | echo "npm version $(npm -v) running"
--------------------------------------------------------------------------------