Skip to content

Commit afb8d27

Browse files
committed
test: e2e tests for autoCsp
1 parent c170768 commit afb8d27

File tree

2 files changed

+132
-0
lines changed

2 files changed

+132
-0
lines changed

tests/legacy-cli/e2e.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ WEBPACK_IGNORE_TESTS = [
5050
"tests/build/prerender/error-with-sourcemaps.js",
5151
"tests/build/server-rendering/server-routes-*",
5252
"tests/build/wasm-esm.js",
53+
"tests/build/auto-csp*",
5354
]
5455

5556
def _to_glob(patterns):
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import assert from 'node:assert';
2+
import { getGlobalVariable } from '../../utils/env';
3+
import { expectFileToMatch, rimraf, writeMultipleFiles } from '../../utils/fs';
4+
import { findFreePort } from '../../utils/network';
5+
import { installWorkspacePackages } from '../../utils/packages';
6+
import { execAndWaitForOutputToMatch, ng } from '../../utils/process';
7+
import { updateJsonFile, updateServerFileForWebpack, useSha } from '../../utils/project';
8+
9+
const MULTI_HASH_CSP =
10+
/script-src 'strict-dynamic' (?:'sha256-[^']+' )+https: 'unsafe-inline';object-src 'none';base-uri 'self';/;
11+
12+
export default async function () {
13+
assert(
14+
getGlobalVariable('argv')['esbuild'],
15+
'This test should not be called in the Webpack suite.',
16+
);
17+
// forcibly remove in case another test doesn't clean itself up
18+
// await rimraf('node_modules/@angular/ssr');
19+
// We don't need SSR yet but eventually for when Auto-CSP will also have a SSR implementation.
20+
// await ng('add', '@angular/ssr', '--skip-confirmation', '--skip-install');
21+
22+
await useSha();
23+
await installWorkspacePackages();
24+
25+
// Turn on auto-CSP
26+
await updateJsonFile('angular.json', (json) => {
27+
const build = json['projects']['test-project']['architect']['build'];
28+
build.options = {
29+
...build.options,
30+
security: { autoCsp: true },
31+
};
32+
});
33+
34+
await writeMultipleFiles({
35+
'serve.js': `
36+
const express = require('express');
37+
const path = require('path');
38+
39+
const app = express();
40+
const PORT = process.env.PORT || 3000;
41+
42+
app.use(express.static(path.join(__dirname, 'dist/test-project/browser')));
43+
44+
app.listen(PORT, () => {
45+
console.log('Node Express server listening on ' + PORT);
46+
});
47+
`,
48+
'src/index.html': `
49+
<!doctype html>
50+
<html lang="en">
51+
<head>
52+
<meta charset="utf-8">
53+
<base href="/">
54+
<script>console.log("Inline Script Head");</script>
55+
</head>
56+
<body>
57+
<app-root></app-root>
58+
<script>console.log("Inline Script Body");</script>
59+
</body>
60+
</html>
61+
`,
62+
'e2e/src/app.e2e-spec.ts': `
63+
import { browser, by, element } from 'protractor';
64+
import * as webdriver from 'selenium-webdriver';
65+
66+
function verifyNoBrowserErrors() {
67+
return browser
68+
.manage()
69+
.logs()
70+
.get('browser')
71+
.then(function (browserLog: any[]) {
72+
const errors: any[] = [];
73+
browserLog.filter((logEntry) => {
74+
const msg = logEntry.message;
75+
console.log('>> ' + msg);
76+
if (logEntry.level.value >= webdriver.logging.Level.INFO.value) {
77+
errors.push(msg);
78+
}
79+
});
80+
expect(errors).toEqual([]);
81+
});
82+
}
83+
84+
describe('Hello world E2E Tests', () => {
85+
beforeAll(async () => {
86+
await browser.waitForAngularEnabled(true);
87+
});
88+
89+
it('should display: Welcome', async () => {
90+
// Load the page without waiting for Angular since it is not bootstrapped automatically.
91+
await browser.driver.get(browser.baseUrl);
92+
93+
// expect(
94+
// await element(by.css('style[ng-app-id="ng"]')).getText()
95+
// ).not.toBeNull();
96+
97+
// Test the contents.
98+
expect(await element(by.css('h1')).getText()).toMatch('Hello');
99+
100+
// Make sure the server styles got replaced by client side ones.
101+
expect(
102+
await element(by.css('style[ng-app-id="ng"]')).isPresent()
103+
).toBeFalsy();
104+
expect(await element(by.css('style')).getText()).toMatch('');
105+
106+
// Make sure there were no client side errors.
107+
await verifyNoBrowserErrors();
108+
});
109+
});
110+
`,
111+
});
112+
113+
async function spawnServer(): Promise<number> {
114+
const port = await findFreePort();
115+
116+
await execAndWaitForOutputToMatch('node', ['serve.js'], /Node Express server listening on/, {
117+
'PORT': String(port),
118+
});
119+
120+
return port;
121+
}
122+
123+
await ng('build');
124+
125+
// Make sure the output files have auto-CSP as a result of `ng build`
126+
await expectFileToMatch('dist/test-project/browser/index.html', MULTI_HASH_CSP);
127+
128+
// Make sure that our e2e protractor tests run to confirm that our angular project runs.
129+
const port = await spawnServer();
130+
await ng('e2e', `--base-url=http://localhost:${port}`, '--dev-server-target=');
131+
}

0 commit comments

Comments
 (0)