Skip to content

Commit 1153c92

Browse files
authored
fix(tests): add global scripts in karma plugin (#3543)
Note: renamed and lazy global scripts are not supported. Fix #2897
1 parent 290c6e7 commit 1153c92

File tree

4 files changed

+141
-59
lines changed

4 files changed

+141
-59
lines changed

packages/angular-cli/plugins/karma.js

+20
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const init = (config) => {
1111
}
1212
const angularCliConfig = require(path.join(config.basePath, config.angularCli.config));
1313
const appConfig = angularCliConfig.apps[0];
14+
const appRoot = path.join(config.basePath, appConfig.root);
1415
const environment = config.angularCli.environment || 'dev';
1516
const testConfig = {
1617
codeCoverage: config.angularCli.codeCoverage || false,
@@ -66,6 +67,25 @@ const init = (config) => {
6667
.filter((file) => config.preprocessors[file].indexOf('angular-cli') !== -1)
6768
.map((file) => config.preprocessors[file])
6869
.map((arr) => arr.splice(arr.indexOf('angular-cli'), 1, 'webpack', 'sourcemap'));
70+
71+
// Add global scripts
72+
if (appConfig.scripts && appConfig.scripts.length > 0) {
73+
const globalScriptPatterns = appConfig.scripts
74+
.map(script => typeof script === 'string' ? { input: script } : script)
75+
// Neither renamed nor lazy scripts are currently supported
76+
.filter(script => !(script.output || script.lazy))
77+
.map(script => ({
78+
pattern: path.resolve(appRoot, script.input),
79+
included: true,
80+
served: true,
81+
watched: true
82+
}));
83+
84+
// Unshift elements onto the beginning of the files array.
85+
// It's important to not replace the array, because
86+
// karma already has a reference to the existing array.
87+
Array.prototype.unshift.apply(config.files, globalScriptPatterns);
88+
}
6989
}
7090

7191
init.$inject = ['config'];

tests/e2e/tests/test/test-assets.ts

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { writeMultipleFiles } from '../../utils/fs';
2+
import { ng } from '../../utils/process';
3+
import { updateJsonFile } from '../../utils/project';
4+
import { expectToFail } from '../../utils/utils';
5+
import { stripIndent } from 'common-tags';
6+
7+
// Make sure asset files are served
8+
export default function () {
9+
return Promise.resolve()
10+
.then(() => writeMultipleFiles({
11+
'src/assets/file.txt': 'assets-folder-content',
12+
'src/file.txt': 'file-content',
13+
// Not using `async()` in tests as it seemed to swallow `fetch()` errors
14+
'src/app/app.component.spec.ts': stripIndent`
15+
describe('Test Runner', () => {
16+
const fetch = global['fetch'];
17+
it('should serve files in assets folder', (done) => {
18+
fetch('/assets/file.txt')
19+
.then(response => response.text())
20+
.then(fileText => {
21+
expect(fileText).toMatch('assets-folder-content');
22+
done();
23+
});
24+
});
25+
it('should serve files explicitly added to assets array', (done) => {
26+
fetch('/file.txt')
27+
.then(response => response.text())
28+
.then(fileText => {
29+
expect(fileText).toMatch('file-content');
30+
done();
31+
});
32+
});
33+
});
34+
`
35+
}))
36+
// Test failure condition (no assets in angular-cli.json)
37+
.then(() => updateJsonFile('angular-cli.json', configJson => {
38+
const app = configJson['apps'][0];
39+
app['assets'] = [];
40+
}))
41+
.then(() => expectToFail(() => ng('test', '--single-run'),
42+
'Should fail because the assets to serve were not in the angular-cli config'))
43+
// Test passing condition (assets are included)
44+
.then(() => updateJsonFile('angular-cli.json', configJson => {
45+
const app = configJson['apps'][0];
46+
app['assets'] = ['assets', 'file.txt'];
47+
}))
48+
.then(() => ng('test', '--single-run'));
49+
}

tests/e2e/tests/test/test-scripts.ts

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { writeMultipleFiles } from '../../utils/fs';
2+
import { ng } from '../../utils/process';
3+
import { updateJsonFile } from '../../utils/project';
4+
import { expectToFail } from '../../utils/utils';
5+
import { stripIndent } from 'common-tags';
6+
7+
export default function () {
8+
return Promise.resolve()
9+
.then(() => ng('test', '--watch=false'))
10+
// prepare global scripts test files
11+
.then(() => writeMultipleFiles({
12+
'src/string-script.js': `stringScriptGlobal = 'string-scripts.js';`,
13+
'src/input-script.js': `inputScriptGlobal = 'input-scripts.js';`,
14+
'src/typings.d.ts': stripIndent`
15+
declare var stringScriptGlobal: any;
16+
declare var inputScriptGlobal: any;
17+
`,
18+
'src/app/app.component.ts': stripIndent`
19+
import { Component } from '@angular/core';
20+
21+
@Component({ selector: 'app-root', template: '' })
22+
export class AppComponent {
23+
stringScriptGlobalProp = stringScriptGlobal;
24+
inputScriptGlobalProp = inputScriptGlobal;
25+
}
26+
`,
27+
'src/app/app.component.spec.ts': stripIndent`
28+
import { TestBed, async } from '@angular/core/testing';
29+
import { AppComponent } from './app.component';
30+
31+
describe('AppComponent', () => {
32+
beforeEach(() => {
33+
TestBed.configureTestingModule({ declarations: [ AppComponent ] });
34+
TestBed.compileComponents();
35+
});
36+
37+
it('should have access to string-script.js', async(() => {
38+
let app = TestBed.createComponent(AppComponent).debugElement.componentInstance;
39+
expect(app.stringScriptGlobalProp).toEqual('string-scripts.js');
40+
}));
41+
42+
it('should have access to input-script.js', async(() => {
43+
let app = TestBed.createComponent(AppComponent).debugElement.componentInstance;
44+
expect(app.inputScriptGlobalProp).toEqual('input-scripts.js');
45+
}));
46+
});
47+
48+
describe('Spec', () => {
49+
it('should have access to string-script.js', async(() => {
50+
expect(stringScriptGlobal).toBe('string-scripts.js');
51+
}));
52+
53+
it('should have access to input-script.js', async(() => {
54+
expect(inputScriptGlobal).toBe('input-scripts.js');
55+
}));
56+
});
57+
`
58+
}))
59+
// should fail because the global scripts were not added to scripts array
60+
.then(() => expectToFail(() => ng('test', '--single-run')))
61+
.then(() => updateJsonFile('angular-cli.json', configJson => {
62+
const app = configJson['apps'][0];
63+
app['scripts'] = [
64+
'string-script.js',
65+
{ input: 'input-script.js' }
66+
];
67+
}))
68+
// should pass now
69+
.then(() => ng('test', '--single-run'));
70+
}
71+

tests/e2e/tests/test/test.ts

+1-59
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,7 @@
1-
import { writeMultipleFiles } from '../../utils/fs';
21
import { ng } from '../../utils/process';
3-
import { updateJsonFile } from '../../utils/project';
4-
import { expectToFail } from '../../utils/utils';
5-
import { stripIndent } from 'common-tags';
6-
72

83
export default function () {
9-
// Each test function returns PromiseLike<Something_Different>,
10-
// which would throw normally
11-
// but resolve() normalizes this to <any> from the start
12-
return Promise.resolve()
13-
.then(() => testWatchFalseAndSingleRun())
14-
.then(() => testAssetsAreServed());
15-
}
16-
17-
// Make sure both --watch=false and --single-run work
18-
function testWatchFalseAndSingleRun() {
4+
// make sure both --watch=false and --single-run work
195
return ng('test', '--single-run')
206
.then(() => ng('test', '--watch=false'));
217
}
22-
23-
// Make sure asset files are served
24-
function testAssetsAreServed() {
25-
return Promise.resolve()
26-
.then(() => writeMultipleFiles({
27-
'src/assets/file.txt': 'assets-folder-content',
28-
'src/file.txt': 'file-content',
29-
// Not using `async()` in tests as it seemed to swallow `fetch()` errors
30-
'src/app/app.component.spec.ts': stripIndent`
31-
describe('Test Runner', () => {
32-
const fetch = global['fetch'];
33-
it('should serve files in assets folder', (done) => {
34-
fetch('/assets/file.txt')
35-
.then(response => response.text())
36-
.then(fileText => {
37-
expect(fileText).toMatch('assets-folder-content');
38-
done();
39-
});
40-
});
41-
it('should serve files explicitly added to assets array', (done) => {
42-
fetch('/file.txt')
43-
.then(response => response.text())
44-
.then(fileText => {
45-
expect(fileText).toMatch('file-content');
46-
done();
47-
});
48-
});
49-
});
50-
`
51-
}))
52-
// Test failure condition (no assets in angular-cli.json)
53-
.then(() => updateJsonFile('angular-cli.json', configJson => {
54-
const app = configJson['apps'][0];
55-
app['assets'] = [];
56-
}))
57-
.then(() => expectToFail(() => ng('test', '--single-run'),
58-
'Should fail because the assets to serve were not in the angular-cli config'))
59-
// Test passing condition (assets are included)
60-
.then(() => updateJsonFile('angular-cli.json', configJson => {
61-
const app = configJson['apps'][0];
62-
app['assets'] = ['assets', 'file.txt'];
63-
}))
64-
.then(() => ng('test', '--single-run'));
65-
}

0 commit comments

Comments
 (0)