From e29152329e02fcc15cba03d0570397d3ec2cadea Mon Sep 17 00:00:00 2001 From: sidiousvic Date: Wed, 22 Jul 2020 21:48:23 +0900 Subject: [PATCH 01/17] x script --- package-lock.json | 6 +++--- package.json | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 367ed5a..2de15cf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10776,9 +10776,9 @@ } }, "registry-auth-token": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.1.1.tgz", - "integrity": "sha512-9bKS7nTl9+/A1s7tnPeGrUpRcVY+LUh7bfFgzpndALdPfXQBfQV77rQVtqgUV3ti4vc/Ik81Ex8UJDWDQ12zQA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.0.tgz", + "integrity": "sha512-P+lWzPrsgfN+UEpDS3U8AQKg/UjZX6mQSJueZj3EK+vNESoqBSpBUD3gmu4sF9lOsjXWjF11dQKUqemf3veq1w==", "dev": true, "requires": { "rc": "^1.2.8" diff --git a/package.json b/package.json index 0df02b6..f49cc12 100644 --- a/package.json +++ b/package.json @@ -35,10 +35,12 @@ "build": "rollup -c", "preversion": "npm test", "postversion": "git push origin --tags --no-verify", - "test": "jest && tsc spec/types.test.ts --noEmit", + "test": "jest && npm run test-types", + "test-types": "tsc spec/types.test.ts --noEmit", "example/pizza": "webpack --config examples/pizza/webpack.config.js && webpack-dev-server --mode development --hot --watch-stdin --config examples/pizza/webpack.config.js", "example/todo": "webpack --config examples/todo/webpack.config.js && webpack-dev-server --mode development --hot --watch-stdin --config examples/todo/webpack.config.js", "example/calculator": "webpack --config examples/calculator/webpack.config.js && webpack-dev-server --mode development --hot --watch-stdin --config examples/calculator/webpack.config.js", + "x": "webpack --config x/webpack.config.js && webpack-dev-server --mode development --hot --watch-stdin --config x/webpack.config.js", "pretest": "npm run build" }, "keywords": [ From 50feb11c2e7c611a315d8a5f2d368b9907801712 Mon Sep 17 00:00:00 2001 From: sidiousvic Date: Wed, 22 Jul 2020 21:49:12 +0900 Subject: [PATCH 02/17] upgraded tests --- spec/dom.test.js | 135 +++++++++++++++++++--------------------- spec/exorciser.test.js | 39 ++++++++++++ spec/interfaces.test.js | 48 ++++++++------ spec/xss.test.js | 33 ---------- 4 files changed, 130 insertions(+), 125 deletions(-) create mode 100644 spec/exorciser.test.js delete mode 100644 spec/xss.test.js diff --git a/spec/dom.test.js b/spec/dom.test.js index 7b88865..affe62f 100644 --- a/spec/dom.test.js +++ b/spec/dom.test.js @@ -2,88 +2,79 @@ import phantom from "../lib/phantom"; import phantomStore from "./utils/phantomStore"; /* - * Test Phantom's DOM output + * Test Phantom and its interactions with the DOM */ -test("The PHANTOM element is rendered and wraps around the application", () => { - // init phantomElement - const { appear } = phantom(phantomStore, phantomElement); - function phantomElement() { - return ` -
-

PHANTOM

-
- `; - } - appear(); - - const PHANTOMEl = document.body.firstChild; - - expect(PHANTOMEl.id).toBe("PHANTOM"); -}); +describe("Phantom and the DOM", () => { + test("The PHANTOM element is rendered and wraps around the application", () => { + // init phantomComponent + const { appear } = phantom(phantomStore, phantomComponent); + function phantomComponent() { + return ` +
+

PHANTOM

+
+ `; + } + appear(); + + const PHANTOMEl = document.body.firstChild; -test("DOM is updated after firing a state change", () => { - // init phantomElement - const { fire, data, appear } = phantom(phantomStore, phantomElement); - function phantomElement() { - const { title } = data(); - return ` -
-

${title}

-
- `; - } - appear(); - - // add listener - document.addEventListener("click", justDoShit); - function justDoShit(e) { - if (e.target.id === "title-h1") { - fire({ type: "TOGGLE_TITLE" }); + expect(PHANTOMEl.id).toBe("PHANTOM"); + }); + + test("DOM is updated after firing a state change", () => { + // init phantomComponent + const { fire, data, appear } = phantom(phantomStore, phantomComponent); + function phantomComponent() { + const { title } = data(); + return ` +
+

${title}

+
+ `; } - } - // click title element - const toBeSwappedOut = document.getElementById("title-h1"); - toBeSwappedOut.click(); - const swappedIn = document.getElementById("title-h1"); + appear(); - expect(swappedIn.innerHTML).toBe("JUST DO SHIT"); -}); + // add click listener + document.addEventListener("click", justDoShit); + function justDoShit(e) { + if (e.target.id === "title-h1") { + fire({ type: "TOGGLE_TITLE" }); + } + } + + const toBeSwappedOut = document.getElementById("title-h1"); + + // simulate click + toBeSwappedOut.click(); + + const swappedIn = document.getElementById("title-h1"); + + expect(swappedIn.innerHTML).toBe("JUST DO SHIT"); + }); + + test("PHANTOM element is properly rendered", () => { + // init phantomComponent + const { data, appear } = phantom(phantomStore, phantomComponent); -test("PHANTOM DOM is properly rendered", () => { - // init phantomElement - const { fire, data, appear } = phantom(phantomStore, phantomElement); - function phantomElement() { - const { title } = data(); - return ` -
-

${title}

-
- `; - } - - appear(); - - // add listener - document.addEventListener("click", justDoShit); - function justDoShit(e) { - if (e.target.id === "title-h1") { - fire({ type: "TOGGLE_TITLE" }); + function phantomComponent() { + return ` +
+ `; } - } - // get dom element's innerHTML, trim() - const domElementInnerHTML = document - .getElementById("PHANTOM") - .innerHTML.trim(); + appear(); - // click title element - const titleH1 = document.getElementById("title-h1"); - titleH1.click(); + // get dom element's innerHTML, trim() + const domElementInnerHTML = document + .getElementById("PHANTOM") + .innerHTML.trim(); - // get phantomElement's (as returned by phantomElement) HTML, trim() - const phantomElementHTML = phantomElement().trim(); + // get phantomComponent's HTML string, trim() + const phantomElementHTML = phantomComponent().trim(); - expect(domElementInnerHTML).toBe(phantomElementHTML); + expect(domElementInnerHTML).toBe(phantomElementHTML); + }); }); diff --git a/spec/exorciser.test.js b/spec/exorciser.test.js new file mode 100644 index 0000000..6841f9e --- /dev/null +++ b/spec/exorciser.test.js @@ -0,0 +1,39 @@ +import phantom from "../lib/phantom"; +import phantomStore from "./utils/phantomStore"; + +/* + * Test the internal Phantom Exorciser and its HTML sanitization vs XSS injection + */ + +describe("The Phantom Exorciser", () => { + test(" is sanitized", () => { + // init phantom + const { appear } = phantom(phantomStore, phantomComponent); + + // define a component + function phantomComponent() { + return ` + + `; // ^ dangerous tag + } + + const sanitized = ``; + const shouldBeSanitized = appear().innerHTML.trim(); + // ^ appear returns the DOM node. innerHTML is trimmed for control + + expect(shouldBeSanitized).toBe(sanitized); + }); + + test("Attempting to render