Skip to content

Commit dd6cd09

Browse files
committed
EIWFY23Q4-1 Add unit test for HTML sanitization
1 parent 4494566 commit dd6cd09

File tree

8 files changed

+1229
-41
lines changed

8 files changed

+1229
-41
lines changed

.babelrc

-12
This file was deleted.

.github/workflows/node-lint.yml

+1
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,5 @@ jobs:
3030
cache: 'yarn'
3131
- run: yarn install --frozen-lockfile
3232
- run: yarn lint
33+
- run: yarn test
3334
- run: yarn build-prod

babel.config.js

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const config = {
2+
presets: [
3+
'@babel/preset-env',
4+
'@babel/preset-typescript',
5+
'@babel/preset-react',
6+
],
7+
plugins: [
8+
'@babel/plugin-proposal-class-properties',
9+
'@compiled/babel-plugin',
10+
'@babel/transform-runtime',
11+
],
12+
env: {
13+
test: {
14+
plugins: ['@babel/plugin-transform-modules-commonjs'],
15+
},
16+
},
17+
};
18+
module.exports = config;

jest.config.js

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const config = {
2+
testEnvironment: 'jsdom',
3+
transform: {
4+
'\\.[jt]sx?$': 'babel-jest',
5+
},
6+
// https://stackoverflow.com/questions/49263429/jest-gives-an-error-syntaxerror-unexpected-token-export
7+
transformIgnorePatterns: ['node_modules/jest-runner'],
8+
};
9+
module.exports = config;

package.json

+8
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
},
4040
"devDependencies": {
4141
"@babel/core": "^7.22.5",
42+
"@babel/plugin-transform-modules-commonjs": "^7.22.5",
4243
"@babel/plugin-transform-runtime": "^7.22.5",
4344
"@babel/preset-env": "^7.22.5",
4445
"@babel/preset-react": "^7.22.5",
@@ -49,18 +50,24 @@
4950
"@storybook/addon-links": "^7.0.22",
5051
"@storybook/cli": "^7.0.22",
5152
"@storybook/react-webpack5": "^7.0.22",
53+
"@testing-library/jest-dom": "^5.16.5",
54+
"@testing-library/react": "^11.2.7",
55+
"@types/jest": "^29.5.2",
5256
"@types/js-yaml": "^4.0.0",
5357
"@types/react": "^16.8",
5458
"@types/react-copy-to-clipboard": "^5.0.0",
5559
"@types/react-dom": "^16.8",
5660
"@types/react-router-dom": "^5.1.7",
61+
"babel-jest": "^29.5.0",
5762
"babel-loader": "^8.2.2",
5863
"babel-plugin-transform-class-properties": "^6.24.1",
5964
"csp-html-webpack-plugin": "^5.1.0",
6065
"css-loader": "^5.0.1",
6166
"favicons": "^7.1.3",
6267
"favicons-webpack-plugin": "^6.0.0",
6368
"html-webpack-plugin": "^5.5.3",
69+
"jest": "^29.5.0",
70+
"jest-environment-jsdom": "^29.5.0",
6471
"json-schema-to-typescript": "^10.1.2",
6572
"npm-run-all": "^4.1.5",
6673
"prettier": "^2.8.8",
@@ -75,6 +82,7 @@
7582
"scripts": {
7683
"start": "webpack serve -c webpack.dev.js",
7784
"lint": "tsc --noEmit",
85+
"test": "jest",
7886
"postinstall": "npm run gen-schema",
7987
"build-dev": "webpack -c webpack.dev.js",
8088
"build-prod": "webpack -c webpack.prod.js",

src/test/markdown-renderer.test.tsx

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import React from 'react';
2+
import { render, screen } from '@testing-library/react';
3+
import '@testing-library/jest-dom';
4+
import { Markdown } from '../markdown';
5+
6+
describe('markdown renderer', () => {
7+
test('safely displays HTML but protects against XSS', async () => {
8+
render(
9+
<Markdown
10+
source={`
11+
# Hello world
12+
<p title="para">This is some safe text!</p>
13+
<img title="xssimg" src="test.png" onerror="alert('XSS');">
14+
<script title="xss">alert("XSS")</script>
15+
<style title="xsscss">* { display: none; }</style>
16+
`}
17+
/>
18+
);
19+
20+
// It renders markdown
21+
expect(screen.getByText('Hello world')).toBeTruthy();
22+
// and paragraphs
23+
expect(screen.getByTitle('para')).toHaveTextContent('This is some safe text!');
24+
// but blocks attributes that can run code
25+
expect(screen.getByTitle('xssimg')).not.toHaveAttribute('onerror');
26+
// and blocks script and style tags outright
27+
expect(screen.queryByTitle('xss')).toBeNull();
28+
expect(screen.queryByTitle('xsscss')).toBeNull();
29+
});
30+
})

tsconfig.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
5151
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
5252
// "typeRoots": [], /* List of folders to include type definitions from. */
53-
// "types": [], /* Type declaration files to be included in compilation. */
53+
"types": ["jest"], /* Type declaration files to be included in compilation. */
5454
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
5555
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
5656
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */

0 commit comments

Comments
 (0)