Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(tests): add global scripts in karma plugin #3543

Merged
merged 2 commits into from
Dec 22, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 20 additions & 0 deletions packages/angular-cli/plugins/karma.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const init = (config) => {
}
const angularCliConfig = require(path.join(config.basePath, config.angularCli.config));
const appConfig = angularCliConfig.apps[0];
const appRoot = path.join(config.basePath, appConfig.root);
const environment = config.angularCli.environment || 'dev';
const testConfig = {
codeCoverage: config.angularCli.codeCoverage || false,
Expand Down Expand Up @@ -66,6 +67,25 @@ const init = (config) => {
.filter((file) => config.preprocessors[file].indexOf('angular-cli') !== -1)
.map((file) => config.preprocessors[file])
.map((arr) => arr.splice(arr.indexOf('angular-cli'), 1, 'webpack', 'sourcemap'));

// Add global scripts
if (appConfig.scripts && appConfig.scripts.length > 0) {
const globalScriptPatterns = appConfig.scripts
.map(script => typeof script === 'string' ? { input: script } : script)
// Neither renamed nor lazy scripts are currently supported
.filter(script => !(script.output || script.lazy))
.map(script => ({
pattern: path.resolve(appRoot, script.input),
included: true,
served: true,
watched: true
}));

// Unshift elements onto the beginning of the files array.
// It's important to not replace the array, because
// karma already has a reference to the existing array.
Array.prototype.unshift.apply(config.files, globalScriptPatterns);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

config.files.unshift(...globalScriptsPatterns) is simpler.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't do that in the karma plugin since it's not preprocessed and node4 does not support the spread operator (without a flag).

I hope to tackle that in #3605 by making the plugin be in TypeScript.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good.

}
}

init.$inject = ['config'];
Expand Down
49 changes: 49 additions & 0 deletions tests/e2e/tests/test/test-assets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { writeMultipleFiles } from '../../utils/fs';
import { ng } from '../../utils/process';
import { updateJsonFile } from '../../utils/project';
import { expectToFail } from '../../utils/utils';
import { stripIndent } from 'common-tags';

// Make sure asset files are served
export default function () {
return Promise.resolve()
.then(() => writeMultipleFiles({
'src/assets/file.txt': 'assets-folder-content',
'src/file.txt': 'file-content',
// Not using `async()` in tests as it seemed to swallow `fetch()` errors
'src/app/app.component.spec.ts': stripIndent`
describe('Test Runner', () => {
const fetch = global['fetch'];
it('should serve files in assets folder', (done) => {
fetch('/assets/file.txt')
.then(response => response.text())
.then(fileText => {
expect(fileText).toMatch('assets-folder-content');
done();
});
});
it('should serve files explicitly added to assets array', (done) => {
fetch('/file.txt')
.then(response => response.text())
.then(fileText => {
expect(fileText).toMatch('file-content');
done();
});
});
});
`
}))
// Test failure condition (no assets in angular-cli.json)
.then(() => updateJsonFile('angular-cli.json', configJson => {
const app = configJson['apps'][0];
app['assets'] = [];
}))
.then(() => expectToFail(() => ng('test', '--single-run'),
'Should fail because the assets to serve were not in the angular-cli config'))
// Test passing condition (assets are included)
.then(() => updateJsonFile('angular-cli.json', configJson => {
const app = configJson['apps'][0];
app['assets'] = ['assets', 'file.txt'];
}))
.then(() => ng('test', '--single-run'));
}
71 changes: 71 additions & 0 deletions tests/e2e/tests/test/test-scripts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { writeMultipleFiles } from '../../utils/fs';
import { ng } from '../../utils/process';
import { updateJsonFile } from '../../utils/project';
import { expectToFail } from '../../utils/utils';
import { stripIndent } from 'common-tags';

export default function () {
return Promise.resolve()
.then(() => ng('test', '--watch=false'))
// prepare global scripts test files
.then(() => writeMultipleFiles({
'src/string-script.js': `stringScriptGlobal = 'string-scripts.js';`,
'src/input-script.js': `inputScriptGlobal = 'input-scripts.js';`,
'src/typings.d.ts': stripIndent`
declare var stringScriptGlobal: any;
declare var inputScriptGlobal: any;
`,
'src/app/app.component.ts': stripIndent`
import { Component } from '@angular/core';

@Component({ selector: 'app-root', template: '' })
export class AppComponent {
stringScriptGlobalProp = stringScriptGlobal;
inputScriptGlobalProp = inputScriptGlobal;
}
`,
'src/app/app.component.spec.ts': stripIndent`
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';

describe('AppComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({ declarations: [ AppComponent ] });
TestBed.compileComponents();
});

it('should have access to string-script.js', async(() => {
let app = TestBed.createComponent(AppComponent).debugElement.componentInstance;
expect(app.stringScriptGlobalProp).toEqual('string-scripts.js');
}));

it('should have access to input-script.js', async(() => {
let app = TestBed.createComponent(AppComponent).debugElement.componentInstance;
expect(app.inputScriptGlobalProp).toEqual('input-scripts.js');
}));
});

describe('Spec', () => {
it('should have access to string-script.js', async(() => {
expect(stringScriptGlobal).toBe('string-scripts.js');
}));

it('should have access to input-script.js', async(() => {
expect(inputScriptGlobal).toBe('input-scripts.js');
}));
});
`
}))
// should fail because the global scripts were not added to scripts array
.then(() => expectToFail(() => ng('test', '--single-run')))
.then(() => updateJsonFile('angular-cli.json', configJson => {
const app = configJson['apps'][0];
app['scripts'] = [
'string-script.js',
{ input: 'input-script.js' }
];
}))
// should pass now
.then(() => ng('test', '--single-run'));
}

60 changes: 1 addition & 59 deletions tests/e2e/tests/test/test.ts
Original file line number Diff line number Diff line change
@@ -1,65 +1,7 @@
import { writeMultipleFiles } from '../../utils/fs';
import { ng } from '../../utils/process';
import { updateJsonFile } from '../../utils/project';
import { expectToFail } from '../../utils/utils';
import { stripIndent } from 'common-tags';


export default function () {
// Each test function returns PromiseLike<Something_Different>,
// which would throw normally
// but resolve() normalizes this to <any> from the start
return Promise.resolve()
.then(() => testWatchFalseAndSingleRun())
.then(() => testAssetsAreServed());
}

// Make sure both --watch=false and --single-run work
function testWatchFalseAndSingleRun() {
// make sure both --watch=false and --single-run work
return ng('test', '--single-run')
.then(() => ng('test', '--watch=false'));
}

// Make sure asset files are served
function testAssetsAreServed() {
return Promise.resolve()
.then(() => writeMultipleFiles({
'src/assets/file.txt': 'assets-folder-content',
'src/file.txt': 'file-content',
// Not using `async()` in tests as it seemed to swallow `fetch()` errors
'src/app/app.component.spec.ts': stripIndent`
describe('Test Runner', () => {
const fetch = global['fetch'];
it('should serve files in assets folder', (done) => {
fetch('/assets/file.txt')
.then(response => response.text())
.then(fileText => {
expect(fileText).toMatch('assets-folder-content');
done();
});
});
it('should serve files explicitly added to assets array', (done) => {
fetch('/file.txt')
.then(response => response.text())
.then(fileText => {
expect(fileText).toMatch('file-content');
done();
});
});
});
`
}))
// Test failure condition (no assets in angular-cli.json)
.then(() => updateJsonFile('angular-cli.json', configJson => {
const app = configJson['apps'][0];
app['assets'] = [];
}))
.then(() => expectToFail(() => ng('test', '--single-run'),
'Should fail because the assets to serve were not in the angular-cli config'))
// Test passing condition (assets are included)
.then(() => updateJsonFile('angular-cli.json', configJson => {
const app = configJson['apps'][0];
app['assets'] = ['assets', 'file.txt'];
}))
.then(() => ng('test', '--single-run'));
}