Skip to content

Commit

Permalink
Merge pull request #5 from Polymer/add-build-support
Browse files Browse the repository at this point in the history
Add support for build config
  • Loading branch information
FredKSchott authored Jan 27, 2017
2 parents 8610325 + 435a7d6 commit 0d5b5a0
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 1 deletion.
45 changes: 44 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,16 @@ function fixDeprecatedOptions(options: any): ProjectOptions {
return options;
}

export interface ProjectBuildOptions {
name?: string;
addServiceWorker?: boolean;
swPrecacheConfig?: string;
insertPrefetchLinks?: boolean;
bundle?: boolean;
html?: {minify?: boolean};
css?: {minify?: boolean};
js?: {minify?: boolean, compile?: boolean};
}

export interface ProjectOptions {
/**
Expand Down Expand Up @@ -97,6 +107,11 @@ export interface ProjectOptions {
* as extraDependencies in the build target.
*/
extraDependencies?: string[];

/**
* List of build option configurations.
*/
builds?: ProjectBuildOptions[];
}

export class ProjectConfig {
Expand All @@ -108,6 +123,7 @@ export class ProjectConfig {
readonly sources: string[];
readonly extraDependencies: string[];

readonly builds: ProjectBuildOptions[];
readonly allFragments: string[];

/**
Expand Down Expand Up @@ -150,7 +166,6 @@ export class ProjectConfig {
*/
constructor(options: ProjectOptions) {
options = (options) ? fixDeprecatedOptions(options) : {};

/**
* root
*/
Expand Down Expand Up @@ -218,6 +233,13 @@ export class ProjectConfig {
if (this.allFragments.length === 0) {
this.allFragments.push(this.entrypoint);
}

/**
* builds
*/
if (options.builds) {
this.builds = options.builds;
}
}

isFragment(filepath: string): boolean {
Expand Down Expand Up @@ -268,6 +290,27 @@ export class ProjectConfig {
// TODO(fks) 11-14-2016: Validate that files actually exist in the file
// system. Potentially become async function for this.

if (this.builds) {
console.assert(
Array.isArray(this.builds),
`${validateErrorPrefix}: "builds" (${this.builds}) ` +
`expected an array of build configurations.`);

if (this.builds.length > 1) {
const buildNames = new Set<string>();
for (const build of this.builds) {
const buildName = build.name;
console.assert(buildName,
`${validateErrorPrefix}: all "builds" require a "name" property ` +
`when there are multiple builds defined.`);
console.assert(!buildNames.has(buildName),
`${validateErrorPrefix}: "builds" duplicate build name ` +
`"${buildName}" found. Build names must be unique.`);
buildNames.add(buildName);
}
}
}

return true;
}

Expand Down
122 changes: 122 additions & 0 deletions test/index_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ suite('Project Config', () => {
test('sets minimum set of defaults when no options are provided', () => {
const absoluteRoot = process.cwd();
const config = new ProjectConfig();
config.validate();

assert.deepEqual(config, {
root: absoluteRoot,
entrypoint: path.resolve(absoluteRoot, 'index.html'),
Expand All @@ -39,6 +41,8 @@ suite('Project Config', () => {
const relativeRoot = 'public';
const absoluteRoot = path.resolve(relativeRoot);
const config = new ProjectConfig({root: relativeRoot});
config.validate();

assert.deepEqual(config, {
root: absoluteRoot,
entrypoint: path.resolve(absoluteRoot, 'index.html'),
Expand All @@ -59,6 +63,8 @@ suite('Project Config', () => {
root: relativeRoot,
entrypoint: 'foo.html'
});
config.validate();

assert.deepEqual(config, {
root: absoluteRoot,
entrypoint: path.resolve(absoluteRoot, 'foo.html'),
Expand All @@ -76,6 +82,8 @@ suite('Project Config', () => {
const config = new ProjectConfig({
shell: 'foo.html'
});
config.validate();

assert.deepEqual(config, {
root: process.cwd(),
entrypoint: path.resolve('index.html'),
Expand All @@ -97,6 +105,8 @@ suite('Project Config', () => {
const config = new ProjectConfig({
fragments: ['foo.html', 'bar.html']
});
config.validate();

assert.deepEqual(config, {
root: process.cwd(),
entrypoint: path.resolve('index.html'),
Expand Down Expand Up @@ -125,6 +135,8 @@ suite('Project Config', () => {
root: relativeRoot,
sources: ['src/**/*', 'images/**/*']
});
config.validate();

assert.deepEqual(config, {
root: absoluteRoot,
entrypoint: path.resolve(absoluteRoot, 'index.html'),
Expand All @@ -149,6 +161,8 @@ suite('Project Config', () => {
'!bower_components/ignore-big-package',
],
});
config.validate();

assert.deepEqual(config, {
root: absoluteRoot,
entrypoint: path.resolve(absoluteRoot, 'index.html'),
Expand All @@ -170,6 +184,8 @@ suite('Project Config', () => {
fragments: ['foo.html', 'bar.html'],
shell: 'baz.html',
});
config.validate();

assert.deepEqual(config, {
root: process.cwd(),
entrypoint: path.resolve('index.html'),
Expand All @@ -194,6 +210,46 @@ suite('Project Config', () => {
});
});

test('builds property is unset when `build` option is not provided', () => {
const absoluteRoot = process.cwd();
const config = new ProjectConfig();
config.validate();

assert.isUndefined(config.builds);
});

test('sets builds property to an array when `build` option is an array', () => {
const absoluteRoot = process.cwd();
const config = new ProjectConfig({
builds: [
{
name: 'bundled',
bundle: true,
insertPrefetchLinks: true,
},
{
name: 'unbundled',
bundle: false,
insertPrefetchLinks: true,
}
]
});
config.validate();

assert.property(config, 'builds');
assert.deepEqual(config.builds, [
{
name: 'bundled',
bundle: true,
insertPrefetchLinks: true,
},
{
name: 'unbundled',
bundle: false,
insertPrefetchLinks: true,
}
]);
});
});

suite('isFragment()', () => {
Expand All @@ -207,6 +263,8 @@ suite('Project Config', () => {
fragments: ['bar.html'],
shell: 'baz.html',
});
config.validate();

assert.isTrue(config.isFragment(config.shell));
assert.isTrue(config.isFragment(path.resolve(absoluteRoot, 'bar.html')));
assert.isTrue(config.isFragment(path.resolve(absoluteRoot, 'baz.html')));
Expand All @@ -228,6 +286,8 @@ suite('Project Config', () => {
fragments: ['bar.html'],
shell: 'baz.html',
});
config.validate();

assert.isFalse(config.isShell(config.entrypoint));
assert.isTrue(config.isShell(config.shell));
assert.isFalse(config.isShell(path.resolve(absoluteRoot, 'foo.html')));
Expand Down Expand Up @@ -332,6 +392,66 @@ suite('Project Config', () => {
assert.throws(() => config.validate(), /AssertionError: Polymer Config Error: shell \(.*bar.html\) does not resolve within root \(.*public\)/);
});

test('returns true when a single, unnamed build is defined', () => {
const relativeRoot = 'public';
const absoluteRoot = path.resolve(relativeRoot);
const config = new ProjectConfig({
root: relativeRoot,
builds: [{
bundle: true,
insertPrefetchLinks: true,
}],
});

const validateResult = config.validate();
assert.isTrue(validateResult);
});

test('throws an exception when builds property was not an array', () => {
const absoluteRoot = process.cwd();
const config = new ProjectConfig({
builds: {
name: 'bundled',
bundle: true,
insertPrefetchLinks: true,
}
});
assert.throws(() => config.validate(), /AssertionError: Polymer Config Error: "builds" \(\[object Object\]\) expected an array of build configurations\./);
});

test('throws an exception when builds array contains duplicate names', () => {
const absoluteRoot = process.cwd();
const config = new ProjectConfig({
builds: [
{
name: 'bundled',
bundle: true,
},
{
name: 'bundled',
bundle: false,
}
]
});
assert.throws(() => config.validate(), /AssertionError: Polymer Config Error: "builds" duplicate build name "bundled" found. Build names must be unique\./);
});

test('throws an exception when builds array contains an unnamed build', () => {
const absoluteRoot = process.cwd();
const config = new ProjectConfig({
builds: [
{
bundle: true,
},
{
name: 'bundled',
bundle: false,
}
]
});
assert.throws(() => config.validate(), /AssertionError: Polymer Config Error: all "builds" require a "name" property when there are multiple builds defined\./);
});

});

});
Expand Down Expand Up @@ -375,6 +495,8 @@ suite('Project Config', () => {

test('creates config instance from config file options', () => {
const config = ProjectConfig.loadConfigFromFile(path.join(__dirname, 'polymer.json'));
config.validate();

const relativeRoot = 'public';
const absoluteRoot = path.resolve(relativeRoot);
assert.deepEqual(config, {
Expand Down

0 comments on commit 0d5b5a0

Please sign in to comment.