Skip to content

Commit 6c522e0

Browse files
committed
Add static file configuration to use the govuk npm directory and update related tests files
1 parent 3ed1c5c commit 6c522e0

File tree

9 files changed

+54
-70
lines changed

9 files changed

+54
-70
lines changed

Diff for: .env.example

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ AUTH_SIGN_OUT_URL=${AUTH_PATH}/?logout=true
44
AWS_ACCESS_KEY_ID=DUMMYIDEXAMPLE
55
AWS_SECRET_ACCESS_KEY=DUMMYEXAMPLEKEY
66
BASE_URL=http://localhost:3000
7-
CDN_HOST=test
7+
CDN_HOST="d3ums2fp3imnyp.cloudfront.net"
88
COOKIE_ID_NAME=github-requests
99
COOKIE_PARSER_SECRET=test
1010
COOKIE_SESSION_SECRET=test

Diff for: README.md

+2-4
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,13 @@ The issue is then reviewed by the team, and further comments may be requested if
7979

8080
### Running local development environment with Docker
8181

82-
Docker is used to run the application in **development** mode, with tooling setup to detect changes in local `src` directory and reload the container's node server.
82+
Docker is used to run the application in **development** mode, with tooling setup to detect changes in local `src` directory and reload the container's node server.
8383

8484
- Ensure that `NODE_ENV=development` is set in the `.env` file.
8585

86-
- In order for static assets to be loaded, the `CDN_HOST` must be set to a CDN domain which serves the GOV.UK static assets.
87-
8886
### Building the application
8987

90-
To build the project, run:
88+
To build the project, run:
9189

9290
```sh
9391
make build

Diff for: src/app.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@ const app = express();
2121

2222
app.disable('x-powered-by');
2323

24-
const assetsPath = path.join(__dirname, '../assets');
25-
app.use('/assets', express.static(assetsPath));
24+
const govukPath = path.join(__dirname, '../node_modules/govuk-frontend/dist/govuk');
25+
26+
app.use('/assets', express.static(`${govukPath}/assets`));
27+
app.use('/govuk-frontend.min.css', express.static(`${govukPath}/govuk-frontend.min.css`));
28+
app.use('/govuk-frontend.min.js', express.static(`${govukPath}/govuk-frontend.min.js`));
2629

2730
app.use(express.json());
2831
app.use(express.urlencoded({ extended: false }));

Diff for: src/config/helmet.ts

+34-25
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,40 @@
11
import express from 'express';
2-
import helmet from 'helmet';
2+
import helmet, { HelmetOptions } from 'helmet';
33

44
import * as config from '../config';
55

6-
export const configureHelmet = (app: express.Application) => {
7-
app.use(helmet({
8-
referrerPolicy: {
9-
policy: 'strict-origin-when-cross-origin'
6+
export const HELMET_OPTIONS: HelmetOptions = {
7+
referrerPolicy: {
8+
policy: 'strict-origin-when-cross-origin'
9+
},
10+
contentSecurityPolicy: {
11+
useDefaults: true,
12+
directives: {
13+
defaultSrc: ["'self'"],
14+
fontSrc: ["'self'", config.CDN_HOST],
15+
styleSrc: [
16+
"'self'",
17+
"'unsafe-hashes'",
18+
"'sha256-6FWIojjtZwiNizws7ImlHjGH3DA5yMh5x4c+/4UVpXk='",
19+
config.CDN_HOST
20+
],
21+
scriptSrc: [
22+
"'self'",
23+
"'sha256-pOe+O2hOZnTvxPXzgAfiocCoHgEZxBBgg+a66TylmHw='",
24+
"'sha256-GUQ5ad8JK5KmEWmROf3LZd9ge94daqNvd8xy9YS1iDw='",
25+
"'sha256-rDMP7u4Lf+tIufrYmUZIhcf2T3WBD4Pweu0EXe+qaLA='",
26+
"'sha256-wJphCpPdstup3Ojta3HnXJ3EOilATTTWg5oi4S9oi4s='",
27+
config.CDN_HOST
28+
],
29+
imgSrc: ["'self'", 'data:', config.CDN_HOST],
30+
connectSrc: ["'self'"],
31+
formAction: ["'self'"],
32+
objectSrc: ["'none'"]
1033
},
11-
contentSecurityPolicy: {
12-
useDefaults: true,
13-
directives: {
14-
defaultSrc: ["'self'"],
15-
fontSrc: ["'self'", config.CDN_HOST],
16-
styleSrc: ["'self'", "'unsafe-hashes'", "'sha256-6FWIojjtZwiNizws7ImlHjGH3DA5yMh5x4c+/4UVpXk='", config.CDN_HOST],
17-
scriptSrc: [
18-
"'self'",
19-
"'sha256-GUQ5ad8JK5KmEWmROf3LZd9ge94daqNvd8xy9YS1iDw='",
20-
"'sha256-rDMP7u4Lf+tIufrYmUZIhcf2T3WBD4Pweu0EXe+qaLA='",
21-
config.CDN_HOST
22-
],
23-
imgSrc: ["'self'", 'data:', config.CDN_HOST],
24-
connectSrc: ["'self'"],
25-
formAction: ["'self'"],
26-
objectSrc: ["'none'"]
27-
},
28-
reportOnly: false
29-
}
30-
}));
34+
reportOnly: false
35+
}
36+
};
37+
38+
export const configureHelmet = (app: express.Application) => {
39+
app.use(helmet(HELMET_OPTIONS));
3140
};

Diff for: src/config/nunjucks.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export const configureNunjucks = (app: express.Application, viewsPath: string) =
88
log.info(`Set nunjucks configurations and where nunjucks templates should resolve to: ${viewsPath}`);
99

1010
const nunjucksEnv = nunjucks.configure(
11-
[viewsPath, 'node_modules/govuk-frontend/dist', 'node_modules/govuk-frontend/dist/components'],
11+
[viewsPath, 'node_modules/govuk-frontend/dist'],
1212
{
1313
autoescape: true,
1414
express: app

Diff for: src/views/layout.html

+6-7
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@
2020
{% from "govuk/components/notification-banner/macro.njk" import govukNotificationBanner %}
2121

2222
{% block head %}
23-
<link rel="stylesheet" type="text/css" media="all" href="//{{CDN_HOST}}/govuk-frontend/v5.3.0/govuk-frontend-5.3.0.min.css">
23+
<link rel="stylesheet" type="text/css" media="all" href="/govuk-frontend.min.css">
2424

25-
<link rel="SHORTCUT ICON" href="//{{CDN_HOST}}/images/favicon.ico"/>
26-
<link rel="icon" href="//{{CDN_HOST}}/images/favicon.ico" type="image/x-icon"/>
25+
<link rel="SHORTCUT ICON" href="/assets/images/favicon.ico"/>
26+
<link rel="icon" href="/assets/images/favicon.ico" type="image/x-icon"/>
2727
{% endblock %}
2828

2929
{% block header %}
@@ -85,11 +85,10 @@
8585

8686
{% block bodyEnd %}
8787
{% if FEATURE_FLAG_ENABLE_COOKIE_BANNER == "true" %}
88-
<script src="/assets/javascripts/cookies.js"></script>
88+
<script src="//{{CDN_HOST}}/app/github-requests-app/javascripts/cookies.js"></script>
8989
{% endif %}
90-
<script type="module" src="//{{CDN_HOST}}/govuk-frontend/v5.3.0/govuk-frontend-5.3.0.min.js"></script>
9190
<script type="module">
92-
import { initAll } from '//{{CDN_HOST}}/govuk-frontend/v5.3.0/govuk-frontend.min.js'
91+
import { initAll } from '/govuk-frontend.min.js'
9392
initAll()
9493
</script>
95-
{% endblock %}
94+
{% endblock %}

Diff for: test/mock/data.ts

-25
Original file line numberDiff line numberDiff line change
@@ -98,31 +98,6 @@ export const MOCK_ERROR = {
9898
message: 'Error message'
9999
} as Error;
100100

101-
export const MOCK_HELMET_VALUE = {
102-
referrerPolicy: {
103-
policy: 'strict-origin-when-cross-origin'
104-
},
105-
contentSecurityPolicy: {
106-
useDefaults: true,
107-
directives: {
108-
defaultSrc: ["'self'"],
109-
fontSrc: ["'self'", config.CDN_HOST],
110-
styleSrc: ["'self'", "'unsafe-hashes'", "'sha256-6FWIojjtZwiNizws7ImlHjGH3DA5yMh5x4c+/4UVpXk='", config.CDN_HOST],
111-
scriptSrc: [
112-
"'self'",
113-
"'sha256-GUQ5ad8JK5KmEWmROf3LZd9ge94daqNvd8xy9YS1iDw='",
114-
"'sha256-rDMP7u4Lf+tIufrYmUZIhcf2T3WBD4Pweu0EXe+qaLA='",
115-
config.CDN_HOST
116-
],
117-
imgSrc: ["'self'", 'data:', config.CDN_HOST],
118-
connectSrc: ["'self'"],
119-
formAction: ["'self'"],
120-
objectSrc: ["'none'"]
121-
},
122-
reportOnly: false
123-
}
124-
};
125-
126101
export const MOCK_RATE_LIMIT_VALUE = {
127102
windowMs: 15 * 60 * 1000,
128103
limit: 100,

Diff for: test/unit/config/helmet.spec.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ jest.mock('helmet');
33
import { describe, expect, test, jest, afterEach } from '@jest/globals';
44
import helmet from 'helmet';
55

6-
import { configureHelmet } from '../../../src/config/helmet';
7-
import { MOCK_HELMET_VALUE, MOCK_EXPRESS_APP } from '../../mock/data';
6+
import { configureHelmet, HELMET_OPTIONS } from '../../../src/config/helmet';
7+
import { MOCK_EXPRESS_APP } from '../../mock/data';
88

99
describe('Helmet Config test suites', () => {
1010
afterEach(() => {
@@ -17,7 +17,7 @@ describe('Helmet Config test suites', () => {
1717
configureHelmet(MOCK_EXPRESS_APP);
1818

1919
expect(mockHelmet).toHaveBeenCalledTimes(1);
20-
expect(mockHelmet).toHaveBeenCalledWith(MOCK_HELMET_VALUE);
20+
expect(mockHelmet).toHaveBeenCalledWith(HELMET_OPTIONS);
2121
expect(MOCK_EXPRESS_APP.use).toHaveBeenCalled();
2222
});
2323
});

Diff for: test/unit/config/nunjucks.spec.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
jest.mock('nunjucks');
22
jest.mock('../../../src/utils/logger');
33

4-
import { describe, expect, test, jest } from '@jest/globals';
4+
import { describe, expect, afterEach, test, jest } from '@jest/globals';
55

66
import * as nunjucks from 'nunjucks';
77

@@ -32,7 +32,7 @@ describe('Nunjucks Configuration test suites', () => {
3232
configureNunjucks(MOCK_EXPRESS_APP, MOCK_VIEWS_PATH);
3333

3434
expect(nunjucks.configure).toHaveBeenCalledWith(
35-
[MOCK_VIEWS_PATH, 'node_modules/govuk-frontend/dist', 'node_modules/govuk-frontend/dist/components'],
35+
[MOCK_VIEWS_PATH, 'node_modules/govuk-frontend/dist'],
3636
{
3737
autoescape: true,
3838
express: MOCK_EXPRESS_APP

0 commit comments

Comments
 (0)