polymer-build
Version:
A library of Gulp build tasks
381 lines (380 loc) • 16.1 kB
JavaScript
"use strict";
/**
* @license
* Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
* This code may only be used under the BSD style license found at
* http://polymer.github.io/LICENSE.txt The complete set of authors may be found
* at http://polymer.github.io/AUTHORS.txt The complete set of contributors may
* be found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by
* Google as part of the polymer project is also subject to an additional IP
* rights grant found at http://polymer.github.io/PATENTS.txt
*/
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const chai_1 = require("chai");
const path = require("path");
const stripIndent = require("strip-indent");
const stream = require("stream");
const Vinyl = require("vinyl");
const optimize_streams_1 = require("../optimize-streams");
const html_splitter_1 = require("../html-splitter");
const streams_1 = require("../streams");
const util_1 = require("./util");
function createFakeFileStream(files) {
const srcStream = new stream.Readable({ objectMode: true });
srcStream._read = function () {
for (const file of files) {
this.push(new Vinyl({
contents: new Buffer(file.contents),
cwd: file.cwd,
base: file.base,
path: file.path
}));
}
this.push(null);
};
return srcStream;
}
suite('optimize-streams', () => {
const fixtureRoot = path.join(__dirname, '..', '..', 'test-fixtures', 'npm-modules');
function getOnlyFile(stream) {
return __awaiter(this, void 0, void 0, function* () {
const fileMap = yield getFileMap(stream);
if (fileMap.size !== 1) {
throw new Error(`Expected 1 file in the stream, got ${fileMap.size}.`);
}
return fileMap.values().next().value;
});
}
function getFileMap(stream) {
return __awaiter(this, void 0, void 0, function* () {
const fileMap = new Map();
return new Promise((resolve, reject) => {
stream.on('data', (file) => fileMap.set(file.path, file.contents.toString()));
stream.on('end', () => resolve(fileMap));
stream.on('error', reject);
});
});
}
suite('JS compilation', () => {
test('compiles to ES5 if compile=true', () => __awaiter(this, void 0, void 0, function* () {
const expected = `var apple = 'apple';\nvar banana = 'banana';`;
const sourceStream = createFakeFileStream([
{
path: 'foo.js',
contents: `const apple = 'apple'; let banana = 'banana';`,
},
]);
const op = streams_1.pipeStreams([sourceStream, optimize_streams_1.getOptimizeStreams({ js: { compile: true } })]);
chai_1.assert.equal(yield getOnlyFile(op), expected);
}));
test('compiles ES2017 to ES2015', () => __awaiter(this, void 0, void 0, function* () {
const sourceStream = createFakeFileStream([
{
path: 'foo.js',
contents: `async function test() { await 0; }`,
},
]);
const op = streams_1.pipeStreams([sourceStream, optimize_streams_1.getOptimizeStreams({ js: { compile: 'es2015' } })]);
const result = yield getOnlyFile(op);
chai_1.assert.include(result, 'asyncToGenerator');
chai_1.assert.notInclude(result, 'async function test');
chai_1.assert.notInclude(result, 'regeneratorRuntime');
}));
test('does not compile webcomponents.js files (windows)', () => __awaiter(this, void 0, void 0, function* () {
const es6Contents = `const apple = 'apple';`;
const sourceStream = createFakeFileStream([
{
path: 'A:\\project\\bower_components\\webcomponentsjs\\webcomponents-es5-loader.js',
contents: es6Contents,
},
]);
const op = streams_1.pipeStreams([sourceStream, optimize_streams_1.getOptimizeStreams({ js: { compile: true } })]);
chai_1.assert.equal(yield getOnlyFile(op), es6Contents);
}));
test('does not compile webcomponents.js files (unix)', () => __awaiter(this, void 0, void 0, function* () {
const es6Contents = `const apple = 'apple';`;
const sourceStream = createFakeFileStream([
{
path: '/project/bower_components/webcomponentsjs/webcomponents-es5-loader.js',
contents: es6Contents,
},
]);
const op = streams_1.pipeStreams([sourceStream, optimize_streams_1.getOptimizeStreams({ js: { compile: true } })]);
chai_1.assert.equal(yield getOnlyFile(op), es6Contents);
}));
});
suite('rewrites bare module specifiers to paths', () => {
test('in js files', () => __awaiter(this, void 0, void 0, function* () {
const filePath = path.join(fixtureRoot, 'foo.js');
const contents = stripIndent(`
import { dep1 } from 'dep1';
import { dep2 } from 'dep2';
import { dep2A } from 'dep2/a';
`);
const expected = stripIndent(`
import { dep1 } from "./node_modules/dep1/index.js";
import { dep2 } from "./node_modules/dep2/dep2.js";
import { dep2A } from "./node_modules/dep2/a.js";
`);
const result = yield getOnlyFile(streams_1.pipeStreams([
createFakeFileStream([{ path: filePath, contents }]),
optimize_streams_1.getOptimizeStreams({ js: { moduleResolution: 'node' } }),
]));
chai_1.assert.deepEqual(result.trim(), expected.trim());
}));
test('in html inline scripts', () => __awaiter(this, void 0, void 0, function* () {
const filePath = path.join(fixtureRoot, 'foo.html');
const contents = stripIndent(`
<html>
<head>
<script type="module">
import { dep1 } from 'dep1';
import { dep2 } from 'dep2';
import { dep2A } from 'dep2/a';
</script>
</head>
<body></body>
</html>
`);
// Note we do some quite ugly re-formatting of HTML!
const expected = stripIndent(`
<html><head>
<script type="module">import { dep1 } from "./node_modules/dep1/index.js";
import { dep2 } from "./node_modules/dep2/dep2.js";
import { dep2A } from "./node_modules/dep2/a.js";</script>
</head>
<body>
</body></html>
`);
const htmlSplitter = new html_splitter_1.HtmlSplitter();
const result = yield getOnlyFile(streams_1.pipeStreams([
createFakeFileStream([{ path: filePath, contents }]),
htmlSplitter.split(),
optimize_streams_1.getOptimizeStreams({ js: { moduleResolution: 'node' } }),
htmlSplitter.rejoin()
]));
chai_1.assert.deepEqual(result.trim(), expected.trim());
}));
});
suite('transforms ES modules to AMD', () => __awaiter(this, void 0, void 0, function* () {
test('inline and external script tags', () => __awaiter(this, void 0, void 0, function* () {
const files = [
{
path: 'index.html',
contents: `
<html><head></head><body>
<script>// not a module</script>
<script type="module">import { depA } from './depA.js';</script>
<script type="module" src="./depB.js"></script>
<script type="module">import { depC } from './depC.js';</script>
</body></html>
`,
expected: `
<html><head></head><body>
<script>// not a module</script>
<script>define(["./depA.js"], function (_depA) {"use strict";});</script>
<script>define(['./depB.js']);</script>
<script>define(["./depC.js"], function (_depC) {"use strict";});</script>
</body></html>
`,
},
];
const opts = {
js: {
transformModulesToAmd: true,
},
rootDir: fixtureRoot,
};
const expected = new Map(files.map((file) => [file.path, file.expected]));
const htmlSplitter = new html_splitter_1.HtmlSplitter();
const result = yield getFileMap(streams_1.pipeStreams([
createFakeFileStream(files),
htmlSplitter.split(),
optimize_streams_1.getOptimizeStreams(opts),
htmlSplitter.rejoin()
]));
util_1.assertMapEqualIgnoringWhitespace(result, expected);
}));
test('auto-detects when to transform external js', () => __awaiter(this, void 0, void 0, function* () {
const files = [
{
path: 'has-import-statement.js',
contents: `
import {foo} from './foo.js';
`,
expected: `
define(["./foo.js"], function (_foo) {
"use strict";
});
`,
},
{
path: 'has-export-statement.js',
contents: `
export const foo = 'foo';
`,
expected: `
define(["exports"], function (_exports) {
"use strict";
Object.defineProperty(_exports, "__esModule", {value: true});
_exports.foo = void 0;
const foo = 'foo';
_exports.foo = foo;
});
`,
},
{
path: 'not-a-module.js',
contents: `
const foo = 'import export';
`,
expected: `
const foo = 'import export';
`,
},
];
const opts = {
js: {
transformModulesToAmd: true,
},
rootDir: fixtureRoot,
};
const expected = new Map(files.map((file) => [file.path, file.expected]));
const htmlSplitter = new html_splitter_1.HtmlSplitter();
const result = yield getFileMap(streams_1.pipeStreams([
createFakeFileStream(files),
htmlSplitter.split(),
optimize_streams_1.getOptimizeStreams(opts),
htmlSplitter.rejoin()
]));
util_1.assertMapEqualIgnoringWhitespace(result, expected);
}));
}));
test('minify js', () => __awaiter(this, void 0, void 0, function* () {
const sourceStream = createFakeFileStream([
{
path: 'foo.js',
contents: 'var foo = 3',
},
]);
const op = streams_1.pipeStreams([sourceStream, optimize_streams_1.getOptimizeStreams({ js: { minify: true } })]);
chai_1.assert.equal(yield getOnlyFile(op), 'var foo=3;');
}));
test('minify js (es6)', () => __awaiter(this, void 0, void 0, function* () {
const sourceStream = createFakeFileStream([
{
path: 'foo.js',
contents: '[1,2,3].map(n => n + 1);',
},
]);
const op = streams_1.pipeStreams([sourceStream, optimize_streams_1.getOptimizeStreams({ js: { minify: true } })]);
chai_1.assert.equal(yield getOnlyFile(op), '[1,2,3].map(n=>n+1);');
}));
test('js exclude permutations', () => __awaiter(this, void 0, void 0, function* () {
const files = [
{
path: 'minify.js',
contents: 'const foo = 3;',
expected: 'const foo=3;',
},
{
path: 'compile.js',
contents: 'const foo = 3;',
expected: 'var foo = 3;',
},
{
path: 'minify-compile.js',
contents: 'const foo = 3;',
expected: 'var foo=3;',
},
{
path: 'neither.js',
// Even with no transform plugins, Babel will make minor code formatting
// changes, such as trimming newlines. This newline remaining shows that
// Babel did not run at all.
contents: 'const foo = 3;\n',
expected: 'const foo = 3;\n',
},
];
const opts = {
js: {
compile: { exclude: ['minify.js', 'neither.js'] },
minify: { exclude: ['compile.js', 'neither.js'] },
},
};
const expected = new Map(files.map((file) => [file.path, file.expected]));
const result = yield getFileMap(streams_1.pipeStreams([
createFakeFileStream(files),
optimize_streams_1.getOptimizeStreams(opts),
]));
chai_1.assert.deepEqual([...result.entries()], [...expected.entries()]);
}));
test('minify html', () => __awaiter(this, void 0, void 0, function* () {
const expected = `<!DOCTYPE html><style>foo {
background: blue;
}</style><script>document.registerElement(\'x-foo\', XFoo);</script><x-foo>bar</x-foo>`;
const sourceStream = createFakeFileStream([
{
path: 'foo.html',
contents: `
<!doctype html>
<style>
foo {
background: blue;
}
</style>
<script>
document.registerElement('x-foo', XFoo);
</script>
<x-foo>
bar
</x-foo>
`,
},
]);
const op = streams_1.pipeStreams([sourceStream, optimize_streams_1.getOptimizeStreams({ html: { minify: true } })]);
chai_1.assert.equal(yield getOnlyFile(op), expected);
}));
test('minify css', () => __awaiter(this, void 0, void 0, function* () {
const sourceStream = createFakeFileStream([
{
path: 'foo.css',
contents: '/* comment */ selector { property: value; }',
},
]);
const op = streams_1.pipeStreams([sourceStream, optimize_streams_1.getOptimizeStreams({ css: { minify: true } })]);
chai_1.assert.equal(yield getOnlyFile(op), 'selector{property:value;}');
}));
test('minify css (inlined)', () => __awaiter(this, void 0, void 0, function* () {
const expected = `<style>foo{background:blue;}</style>`;
const sourceStream = createFakeFileStream([
{
path: 'foo.html',
contents: `
<!doctype html>
<html>
<head>
<style>
foo {
background: blue;
}
</style>
</head>
<body></body>
</html>
`,
},
]);
const op = streams_1.pipeStreams([sourceStream, optimize_streams_1.getOptimizeStreams({ css: { minify: true } })]);
chai_1.assert.include(yield getOnlyFile(op), expected);
}));
});
//# sourceMappingURL=optimize-streams_test.js.map