main.spec.js 14.3 KB
"use strict";
/**
 * @license
 * Copyright Google Inc. All Rights Reserved.
 *
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file at https://angular.io/license
 */
Object.defineProperty(exports, "__esModule", { value: true });
var fs = require("fs");
var path = require("path");
var main_1 = require("../src/main");
var test_support_1 = require("./test_support");
describe('tsc-wrapped', function () {
    var basePath;
    var write;
    beforeEach(function () {
        basePath = test_support_1.makeTempDir();
        write = function (fileName, content) {
            fs.writeFileSync(path.join(basePath, fileName), content, { encoding: 'utf-8' });
        };
        write('decorators.ts', '/** @Annotation */ export var Component: Function;');
        fs.mkdirSync(path.join(basePath, 'dep'));
        write('dep/index.ts', "\n      export const A = 1;\n      export const B = 2;\n    ");
        write('test.ts', "\n      import {Component} from './decorators';\n      export * from './dep';\n\n      @Component({})\n      export class Comp {\n        /**\n         * Comment that is\n         * multiple lines\n         */\n        method(x: string): void {}\n      }\n    ");
    });
    function readOut(ext) {
        return fs.readFileSync(path.join(basePath, 'built', "test." + ext), { encoding: 'utf-8' });
    }
    it('should report error if project not found', function () {
        main_1.main('not-exist', null)
            .then(function () { return fail('should report error'); })
            .catch(function (e) { return expect(e.message).toContain('ENOENT'); });
    });
    it('should pre-process sources', function (done) {
        write('tsconfig.json', "{\n      \"compilerOptions\": {\n        \"experimentalDecorators\": true,\n        \"types\": [],\n        \"outDir\": \"built\",\n        \"declaration\": true,\n        \"moduleResolution\": \"node\",\n        \"target\": \"es2015\"\n      },\n      \"angularCompilerOptions\": {\n        \"annotateForClosureCompiler\": true\n      },\n      \"files\": [\"test.ts\"]\n    }");
        main_1.main(basePath, { basePath: basePath })
            .then(function () {
            var out = readOut('js');
            // No helpers since decorators were lowered
            expect(out).not.toContain('__decorate');
            // Expand `export *` and fix index import
            expect(out).toContain("export { A, B } from './dep/index'");
            // Annotated for Closure compiler
            expect(out).toContain('* @param {?} x');
            // Comments should stay multi-line
            expect(out).not.toContain('Comment that is multiple lines');
            // Decorator is now an annotation
            expect(out).toMatch(/Comp.decorators = \[\s+\{ type: Component/);
            var decl = readOut('d.ts');
            expect(decl).toContain('declare class Comp');
            var metadata = readOut('metadata.json');
            expect(metadata).toContain('"Comp":{"__symbolic":"class"');
            done();
        })
            .catch(function (e) { return done.fail(e); });
    });
    it('should pre-process sources using config from vinyl like object', function (done) {
        var config = {
            path: basePath + '/tsconfig.json',
            contents: new Buffer(JSON.stringify({
                compilerOptions: {
                    experimentalDecorators: true,
                    types: [],
                    outDir: 'built',
                    declaration: true,
                    moduleResolution: 'node',
                    target: 'es2015'
                },
                angularCompilerOptions: { annotateForClosureCompiler: true },
                files: ['test.ts']
            }))
        };
        main_1.main(config, { basePath: basePath })
            .then(function () {
            var out = readOut('js');
            // Expand `export *` and fix index import
            expect(out).toContain("export { A, B } from './dep/index'");
            // Annotated for Closure compiler
            expect(out).toContain('* @param {?} x');
            done();
        })
            .catch(function (e) { return done.fail(e); });
    });
    it('should allow all options disabled', function (done) {
        write('tsconfig.json', "{\n      \"compilerOptions\": {\n        \"experimentalDecorators\": true,\n        \"types\": [],\n        \"outDir\": \"built\",\n        \"declaration\": false,\n        \"module\": \"es2015\",\n        \"moduleResolution\": \"node\"\n      },\n      \"angularCompilerOptions\": {\n        \"annotateForClosureCompiler\": false,\n        \"annotationsAs\": \"decorators\",\n        \"skipMetadataEmit\": true,\n        \"skipTemplateCodegen\": true\n      },\n      \"files\": [\"test.ts\"]\n    }");
        main_1.main(basePath, { basePath: basePath })
            .then(function () {
            var out = readOut('js');
            // TypeScript's decorator emit
            expect(out).toContain('__decorate');
            // Not annotated for Closure compiler
            expect(out).not.toContain('* @param {?} x');
            expect(function () { return fs.accessSync(path.join(basePath, 'built', 'test.metadata.json')); }).toThrow();
            expect(function () { return fs.accessSync(path.join(basePath, 'built', 'test.d.ts')); }).toThrow();
            done();
        })
            .catch(function (e) { return done.fail(e); });
    });
    it('should allow all options disabled with metadata emit', function (done) {
        write('tsconfig.json', "{\n      \"compilerOptions\": {\n        \"experimentalDecorators\": true,\n        \"types\": [],\n        \"outDir\": \"built\",\n        \"declaration\": false,\n        \"module\": \"es2015\",\n        \"moduleResolution\": \"node\"\n      },\n      \"angularCompilerOptions\": {\n        \"annotateForClosureCompiler\": false,\n        \"annotationsAs\": \"decorators\",\n        \"skipMetadataEmit\": false,\n        \"skipTemplateCodegen\": true\n      },\n      \"files\": [\"test.ts\"]\n    }");
        main_1.main(basePath, { basePath: basePath })
            .then(function () {
            var out = readOut('js');
            // TypeScript's decorator emit
            expect(out).toContain('__decorate');
            // Not annotated for Closure compiler
            expect(out).not.toContain('* @param {?} x');
            expect(function () { return fs.accessSync(path.join(basePath, 'built', 'test.d.ts')); }).toThrow();
            var metadata = readOut('metadata.json');
            expect(metadata).toContain('"Comp":{"__symbolic":"class"');
            done();
        })
            .catch(function (e) { return done.fail(e); });
    });
    it('should allow JSDoc annotations without decorator downleveling', function (done) {
        write('tsconfig.json', "{\n      \"compilerOptions\": {\n        \"experimentalDecorators\": true,\n        \"types\": [],\n        \"outDir\": \"built\",\n        \"declaration\": true\n      },\n      \"angularCompilerOptions\": {\n        \"annotateForClosureCompiler\": true,\n        \"annotationsAs\": \"decorators\"\n      },\n      \"files\": [\"test.ts\"]\n    }");
        main_1.main(basePath, { basePath: basePath }).then(function () { return done(); }).catch(function (e) { return done.fail(e); });
    });
    xit('should run quickly (performance baseline)', function (done) {
        for (var i = 0; i < 1000; i++) {
            write("input" + i + ".ts", "\n        import {Component} from './decorators';\n        @Component({})\n        export class Input" + i + " {\n          private __brand: string;\n        }\n      ");
        }
        write('tsconfig.json', "{\n      \"compilerOptions\": {\n        \"experimentalDecorators\": true,\n        \"types\": [],\n        \"outDir\": \"built\",\n        \"declaration\": true,\n        \"diagnostics\": true\n      },\n      \"angularCompilerOptions\": {\n        \"annotateForClosureCompiler\": false,\n        \"annotationsAs\": \"decorators\",\n        \"skipMetadataEmit\": true\n      },\n      \"include\": [\"input*.ts\"]\n    }");
        console.time('BASELINE');
        main_1.main(basePath, { basePath: basePath })
            .then(function () {
            console.timeEnd('BASELINE');
            done();
        })
            .catch(function (e) { return done.fail(e); });
    });
    xit('should run quickly (performance test)', function (done) {
        for (var i = 0; i < 1000; i++) {
            write("input" + i + ".ts", "\n        import {Component} from './decorators';\n        @Component({})\n        export class Input" + i + " {\n          private __brand: string;\n        }\n      ");
        }
        write('tsconfig.json', "{\n      \"compilerOptions\": {\n        \"experimentalDecorators\": true,\n        \"types\": [],\n        \"outDir\": \"built\",\n        \"declaration\": true,\n        \"diagnostics\": true,\n        \"skipLibCheck\": true\n      },\n      \"angularCompilerOptions\": {\n        \"annotateForClosureCompiler\": true\n      },\n      \"include\": [\"input*.ts\"]\n    }");
        console.time('TSICKLE');
        main_1.main(basePath, { basePath: basePath })
            .then(function () {
            console.timeEnd('TSICKLE');
            done();
        })
            .catch(function (e) { return done.fail(e); });
    });
    it('should produce valid source maps', function (done) {
        write('tsconfig.json', "{\n      \"compilerOptions\": {\n        \"experimentalDecorators\": true,\n        \"types\": [],\n        \"outDir\": \"built\",\n        \"declaration\": true,\n        \"moduleResolution\": \"node\",\n        \"target\": \"es2015\",\n        \"sourceMap\": true\n      },\n      \"angularCompilerOptions\": {\n        \"annotateForClosureCompiler\": true\n      },\n      \"files\": [\"test.ts\"]\n    }");
        main_1.main(basePath, { basePath: basePath })
            .then(function () {
            var out = readOut('js.map');
            expect(out).toContain('"sources":["../test.ts"]');
            done();
        })
            .catch(function (e) { return done.fail(e); });
    });
    it('should accept input source maps', function (done) {
        write('tsconfig.json', "{\n      \"compilerOptions\": {\n        \"experimentalDecorators\": true,\n        \"types\": [],\n        \"outDir\": \"built\",\n        \"declaration\": true,\n        \"moduleResolution\": \"node\",\n        \"target\": \"es2015\",\n        \"sourceMap\": true\n      },\n      \"angularCompilerOptions\": {\n        \"annotateForClosureCompiler\": true\n      },\n      \"files\": [\"test.ts\"]\n    }");
        // Provide a file called test.ts that has an inline source map
        // which says that it was transpiled from a file other_test.ts
        // with exactly the same content.
        var inputSourceMap = "{\"version\":3,\"sources\":[\"other_test.ts\"],\"names\":[],\"mappings\":\"AAAA,MAAM,EAAE,EAAE,CAAC\",\"file\":\"../test.ts\",\"sourceRoot\":\"\"}";
        var encodedSourceMap = new Buffer(inputSourceMap, 'utf8').toString('base64');
        write('test.ts', "const x = 3;\n//# sourceMappingURL=data:application/json;base64," + encodedSourceMap);
        main_1.main(basePath, { basePath: basePath })
            .then(function () {
            var out = readOut('js.map');
            expect(out).toContain('"sources":["other_test.ts"]');
            done();
        })
            .catch(function (e) { return done.fail(e); });
    });
    it("should accept input source maps that don't match the file name", function (done) {
        write('tsconfig.json', "{\n      \"compilerOptions\": {\n        \"experimentalDecorators\": true,\n        \"types\": [],\n        \"outDir\": \"built\",\n        \"declaration\": true,\n        \"moduleResolution\": \"node\",\n        \"target\": \"es2015\",\n        \"sourceMap\": true\n      },\n      \"angularCompilerOptions\": {\n        \"annotateForClosureCompiler\": true\n      },\n      \"files\": [\"test.ts\"]\n    }");
        // Provide a file called test.ts that has an inline source map
        // which says that it was transpiled from a file other_test.ts
        // with exactly the same content.
        var inputSourceMap = "{\"version\":3,\"sources\":[\"other_test.ts\"],\"names\":[],\"mappings\":\"AAAA,MAAM,EAAE,EAAE,CAAC\",\"file\":\"test.ts\",\"sourceRoot\":\"\"}";
        var encodedSourceMap = new Buffer(inputSourceMap, 'utf8').toString('base64');
        write('test.ts', "const x = 3;\n//# sourceMappingURL=data:application/json;base64," + encodedSourceMap);
        main_1.main(basePath, { basePath: basePath })
            .then(function () {
            var out = readOut('js.map');
            expect(out).toContain('"sources":["other_test.ts"]');
            done();
        })
            .catch(function (e) { return done.fail(e); });
    });
    it('should expand shorthand imports for ES2015 modules', function (done) {
        write('tsconfig.json', "{\n      \"compilerOptions\": {\n        \"experimentalDecorators\": true,\n        \"types\": [],\n        \"outDir\": \"built\",\n        \"declaration\": true,\n        \"moduleResolution\": \"node\",\n        \"target\": \"es2015\",\n        \"module\": \"es2015\"\n      },\n      \"angularCompilerOptions\": {\n        \"annotateForClosureCompiler\": true\n      },\n      \"files\": [\"test.ts\"]\n    }");
        main_1.main(basePath, { basePath: basePath })
            .then(function () {
            var fileOutput = readOut('js');
            expect(fileOutput).toContain("export { A, B } from './dep/index'");
            done();
        })
            .catch(function (e) { return done.fail(e); });
    });
    it('should expand shorthand imports for ES5 CommonJS modules', function (done) {
        write('tsconfig.json', "{\n      \"compilerOptions\": {\n        \"experimentalDecorators\": true,\n        \"types\": [],\n        \"outDir\": \"built\",\n        \"declaration\": true,\n        \"moduleResolution\": \"node\",\n        \"target\": \"es5\",\n        \"module\": \"commonjs\"\n      },\n      \"angularCompilerOptions\": {\n        \"annotateForClosureCompiler\": true\n      },\n      \"files\": [\"test.ts\"]\n    }");
        main_1.main(basePath, { basePath: basePath })
            .then(function () {
            var fileOutput = readOut('js');
            expect(fileOutput).toContain("var index_1 = require(\"./dep/index\");");
            done();
        })
            .catch(function (e) { return done.fail(e); });
    });
});
//# sourceMappingURL=main.spec.js.map