From d408f4c0fe34fbbcc0c0584f2acdd3fe4b117187 Mon Sep 17 00:00:00 2001 From: Sheogorath Date: Sat, 19 Jan 2019 04:57:18 +0100 Subject: [PATCH] Add tests for csp.js Since we lack of tests but got some great point to start, let's write more tests. This patch provides some basic tests for our CSP library. It's more an integration than a unit test, but gets the job done. Signed-off-by: Sheogorath --- package.json | 1 + test/csp.js | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 test/csp.js diff --git a/package.json b/package.json index 30c4bf8..f2811fe 100644 --- a/package.json +++ b/package.json @@ -184,6 +184,7 @@ "less-loader": "^4.1.0", "mini-css-extract-plugin": "^0.4.1", "mocha": "^5.2.0", + "mock-require": "^3.0.3", "optimize-css-assets-webpack-plugin": "^5.0.0", "script-loader": "^0.7.2", "string-loader": "^0.0.1", diff --git a/test/csp.js b/test/csp.js new file mode 100644 index 0000000..a6de68a --- /dev/null +++ b/test/csp.js @@ -0,0 +1,124 @@ +/* eslint-env node, mocha */ +'use strict' + +const assert = require('assert') +const crypto = require('crypto') +const fs = require('fs') +const path = require('path') +const mock = require('mock-require') + +describe('Content security policies', function () { + let defaultConfig, csp + + before(function () { + csp = require('../lib/csp') + }) + + beforeEach(function () { + // Reset config to make sure we don't influence other tests + defaultConfig = { + csp: { + enable: true, + directives: { + }, + addDefaults: true, + addDisqus: true, + addGoogleAnalytics: true, + upgradeInsecureRequests: 'auto', + reportURI: undefined + }, + useCDN: true + } + }) + + afterEach(function () { + mock.stop('../lib/config') + csp = mock.reRequire('../lib/csp') + }) + + after(function () { + mock.stopAll() + csp = mock.reRequire('../lib/csp') + }) + + // beginnging Tests + it('Disable CDN', function () { + let testconfig = defaultConfig + testconfig.useCDN = false + mock('../lib/config', testconfig) + csp = mock.reRequire('../lib/csp') + + assert(!csp.computeDirectives().scriptSrc.includes('https://cdnjs.cloudflare.com')) + assert(!csp.computeDirectives().scriptSrc.includes('https://cdn.mathjax.org')) + assert(!csp.computeDirectives().styleSrc.includes('https://cdnjs.cloudflare.com')) + assert(!csp.computeDirectives().styleSrc.includes('https://fonts.googleapis.com')) + assert(!csp.computeDirectives().fontSrc.includes('https://cdnjs.cloudflare.com')) + assert(!csp.computeDirectives().fontSrc.includes('https://fonts.gstatic.com')) + }) + + it('Disable Google Analytics', function () { + let testconfig = defaultConfig + testconfig.csp.addGoogleAnalytics = false + mock('../lib/config', testconfig) + csp = mock.reRequire('../lib/csp') + + assert(!csp.computeDirectives().scriptSrc.includes('https://www.google-analytics.com')) + }) + + it('Disable Disqus', function () { + let testconfig = defaultConfig + testconfig.csp.addDisqus = false + mock('../lib/config', testconfig) + csp = mock.reRequire('../lib/csp') + + assert(!csp.computeDirectives().scriptSrc.includes('https://disqus.com')) + assert(!csp.computeDirectives().scriptSrc.includes('https://*.disqus.com')) + assert(!csp.computeDirectives().scriptSrc.includes('https://*.disquscdn.com')) + assert(!csp.computeDirectives().styleSrc.includes('https://*.disquscdn.com')) + assert(!csp.computeDirectives().fontSrc.includes('https://*.disquscdn.com')) + }) + + it('Set ReportURI', function () { + let testconfig = defaultConfig + testconfig.csp.reportURI = 'https://example.com/reportURI' + mock('../lib/config', testconfig) + csp = mock.reRequire('../lib/csp') + + assert.strictEqual(csp.computeDirectives().reportUri, 'https://example.com/reportURI') + }) + + it('Set own directives', function () { + let testconfig = defaultConfig + mock('../lib/config', defaultConfig) + csp = mock.reRequire('../lib/csp') + const unextendedCSP = csp.computeDirectives() + testconfig.csp.directives = { + defaultSrc: ['https://default.example.com'], + scriptSrc: ['https://script.example.com'], + imgSrc: ['https://img.example.com'], + styleSrc: ['https://style.example.com'], + fontSrc: ['https://font.example.com'], + objectSrc: ['https://object.example.com'], + mediaSrc: ['https://media.example.com'], + childSrc: ['https://child.example.com'], + connectSrc: ['https://connect.example.com'] + } + mock('../lib/config', testconfig) + csp = mock.reRequire('../lib/csp') + + const variations = ['default', 'script', 'img', 'style', 'font', 'object', 'media', 'child', 'connect'] + + for (let i = 0; i < variations.length; i++) { + assert.strictEqual(csp.computeDirectives()[variations[i] + 'Src'].toString(), ['https://' + variations[i] + '.example.com'].concat(unextendedCSP[variations[i] + 'Src']).toString()) + } + }) + + /* + * This test reminds us to update the CSP hash for the speaker notes + */ + it('Unchanged hash for reveal.js speaker notes plugin', function () { + const hash = crypto.createHash('sha1') + hash.update(fs.readFileSync(path.resolve(__dirname, '../node_modules/reveal.js/plugin/notes/notes.html'), 'utf8'), 'utf8') + assert.strictEqual(hash.digest('hex'), '471f3826880fac884a4a14faabc492bc854ae994') + }) +})