git.iko.soy/typeable/elm-ui
on master help sign in
make test viewer script
commit17b3a5ffb1b240f262f567b7e1eabf491c88979e authorElm UI Automation <automation@elm-ui.com> dateSat 9 May 2020, 11:37 (6 years ago) parent5f880a7
7 files changed+258−256
package.json+1 tests-rendering/automation/build.js+62 tests-rendering/automation/run.js+2−13 tests-rendering/automation/templates/gather-styles.html+143−67 tests-rendering/automation/view.js+50 tests-rendering/make.sh−2 tests-rendering/view/view.html−174
package.json+1
@@ -5,6 +5,7 @@
55 "main": "index.js",
66 "scripts": {
77 "test": "elm-test",
8+ "view-test": "node tests-rendering/automation/view.js",
89 "test-render": "node tests-rendering/automation/run.js --chrome",
910 "test-render-sauce": "source sauce.env; node tests-rendering/automation/run.js --sauce",
1011 "test-render-sauce-automated": "node tests-rendering/automation/run.js --sauce",
tests-rendering/automation/build.jsnew file+62
@@ -0,0 +1,62 @@
1+const fs = require("fs");
2+const path = require("path");
3+const compileToString = require("node-elm-compiler").compileToString;
4+
5+// {
6+// template: "./tests-rendering/automation/templates/gather-styles.html",
7+// target: "./tmp/test.html",
8+// elm: "src/Tests/Run.elm",
9+// elmOptions: { cwd: "./tests-rendering" },
10+// }
11+
12+async function compile_and_embed(config) {
13+ const template = fs.readFileSync(config.template);
14+
15+ const elm_entry_module = fs.readFileSync(
16+ path.join(config.elmOptions.cwd, config.elm),
17+ "utf8"
18+ );
19+ // console.log(elm_entry_module);
20+ const module_name = elm_entry_module
21+ .split(/[\r\n]+/)[0]
22+ .match(/module ([A-Za-z0-9\.]+)/i)[1];
23+ // console.log(module_name);
24+
25+ // throw "Ugh";
26+
27+ // we embed the compiled js to avoid having to start a server to read the app.
28+ await compileToString([config.elm], config.elmOptions).then(function (
29+ compiled_elm_code
30+ ) {
31+ const compiled = eval(`\`${template}\``);
32+ fs.writeFileSync(config.target, compiled);
33+ });
34+}
35+
36+async function compile_to_string(config) {
37+ const template = fs.readFileSync(config.template);
38+
39+ const elm_entry_module = fs.readFileSync(
40+ path.join(config.elmOptions.cwd, config.elm),
41+ "utf8"
42+ );
43+ // console.log(elm_entry_module);
44+ const module_name = elm_entry_module
45+ .split(/[\r\n]+/)[0]
46+ .match(/module ([A-Za-z0-9\.]+)/i)[1];
47+ // console.log(module_name);
48+
49+ // throw "Ugh";
50+
51+ // we embed the compiled js to avoid having to start a server to read the app.
52+ const compiled = await compileToString([config.elm], config.elmOptions).then(
53+ function (compiled_elm_code) {
54+ return eval(`\`${template}\``);
55+ }
56+ );
57+ return compiled;
58+}
59+
60+exports.compile_and_embed = compile_and_embed;
61+
62+exports.compile_to_string = compile_to_string;
tests-rendering/automation/run.js+2−13
@@ -1,4 +1,3 @@
1−const compileToString = require("node-elm-compiler").compileToString;
21const { Builder, By, Key, until } = require("selenium-webdriver");
32const chrome = require("selenium-webdriver/chrome");
43const firefox = require("selenium-webdriver/firefox");
@@ -7,6 +6,7 @@ const program = require("commander");
76const path = require("path");
87const chalk = require("chalk");
98const childProcess = require("child_process");
9+const compile_and_embed = require("./build.js").compile_and_embed;
1010
1111program
1212 .option("-s, --sauce", "run tests on sauce labs")
@@ -102,17 +102,6 @@ function prepare_all_envs(config) {
102102 return envs;
103103}
104104
105−async function compile_and_embed(config) {
106− var template = fs.readFileSync(config.template);
107− // we embed the compiled js to avoid having to start a server to read the app.
108− await compileToString(config.elm, config.elmOptions).then(function (
109− compiled_elm_code
110− ) {
111− const compiled = eval(`\`${template}\``);
112− fs.writeFileSync(config.target, compiled);
113− });
114−}
115−
116105function prepare_sauce_driver(env) {
117106 const username = process.env.SAUCE_USERNAME;
118107 const accessKey = process.env.SAUCE_ACCESS_KEY;
@@ -174,7 +163,7 @@ async function run_test(driver, url) {
174163 await compile_and_embed({
175164 template: "./tests-rendering/automation/templates/gather-styles.html",
176165 target: "./tmp/test.html",
177− elm: ["src/Tests/Run.elm"],
166+ elm: "src/Tests/Run.elm",
178167 elmOptions: { cwd: "./tests-rendering" },
179168 });
180169 console.log("Done compiling");
tests-rendering/automation/templates/gather-styles.html+143−67
@@ -6,17 +6,149 @@
66 <script>
77 ${compiled_elm_code}
88 </script>
9+ <script>
10+ // Helpers
11+ // Calculations for canvas
12+ var PIXEL_RATIO = (function () {
13+ var ctx = document.createElement("canvas").getContext("2d"),
14+ dpr = window.devicePixelRatio || 1,
15+ bsr =
16+ ctx.webkitBackingStorePixelRatio ||
17+ ctx.mozBackingStorePixelRatio ||
18+ ctx.msBackingStorePixelRatio ||
19+ ctx.oBackingStorePixelRatio ||
20+ ctx.backingStorePixelRatio ||
21+ 1;
22+
23+ return dpr / bsr;
24+ })();
25+
26+ function createHiDPICanvas(w, h, id, ratio) {
27+ if (!ratio) {
28+ ratio = PIXEL_RATIO;
29+ }
30+ let can = document.getElementById(id);
31+ can.width = w * ratio;
32+ can.height = h * ratio;
33+ can.style.width = w + "px";
34+ can.style.height = h + "px";
35+ can.getContext("2d").setTransform(ratio, 0, 0, ratio, 0, 0);
36+ return can;
37+ }
38+
39+ function isVisible(id, bbox) {
40+ var current = document.getElementById(id);
41+ var result = 0;
42+ if (current == document.elementFromPoint(bbox["left"], bbox["top"])) {
43+ result++;
44+ }
45+ if (
46+ current == document.elementFromPoint(bbox["left"], bbox["bottom"] - 1)
47+ ) {
48+ result++;
49+ }
50+ if (
51+ current == document.elementFromPoint(bbox["right"] - 1, bbox["top"])
52+ ) {
53+ result++;
54+ }
55+ if (
56+ current ==
57+ document.elementFromPoint(bbox["right"] - 1, bbox["bottom"] - 1)
58+ ) {
59+ result++;
60+ }
61+
62+ if (result == 4) {
63+ return true;
64+ } else {
65+ return false;
66+ }
67+ }
68+
69+ function getStyle(element) {
70+ var props = [];
71+ var style = window.getComputedStyle(element);
72+ for (var i = style.length; i--; ) {
73+ var name = style.item(i);
74+ var value = style.getPropertyValue(name);
75+ props.push([name, value]);
76+ }
77+ return props;
78+ }
79+
80+ function getBoundingBox(element) {
81+ var bbox = element.getBoundingClientRect();
82+ var style = window.getComputedStyle(element, null);
83+
84+ var padding = {
85+ top: parseFloat(style.getPropertyValue("padding-top")),
86+ bottom: parseFloat(style.getPropertyValue("padding-bottom")),
87+ left: parseFloat(style.getPropertyValue("padding-left")),
88+ right: parseFloat(style.getPropertyValue("padding-right")),
89+ };
90+
91+ return {
92+ top: bbox.top,
93+ bottom: bbox.bottom,
94+ left: bbox.left,
95+ right: bbox.right,
96+ width: bbox.width,
97+ height: bbox.height,
98+ padding: padding,
99+ };
100+ }
101+ function getTextMetrics(element) {
102+ // Given our element, we want to return the text metrics on the text within.
103+ // If it is an element we want to measure:
104+ // we want to get the font family
105+ // and the font size.
106+ // We're going to presume that the font is loaded.
107+ let childrenTextMetrics = [];
108+ for (i = 0; i < element.children.length; i++) {
109+ if (element.children[i].classList.contains("t")) {
110+ let style = window.getComputedStyle(element, null);
111+ let fontSize = style.getPropertyValue("font-size");
112+ let fontFamily = style.getPropertyValue("font-family");
113+ let ctx = canvas.getContext("2d");
114+
115+ ctx.font = fontSize + " " + fontFamily; //"16px Roboto";
116+ let text = ctx.measureText(element.children[i].innerText);
117+
118+ childrenTextMetrics.push({
119+ actualBoundingBoxAscent: text.actualBoundingBoxAscent,
120+ actualBoundingBoxDescent: text.actualBoundingBoxDescent,
121+ actualBoundingBoxLeft: text.actualBoundingBoxLeft,
122+ actualBoundingBoxRight: text.actualBoundingBoxRight,
123+ width: text.width,
124+ });
125+ }
126+ }
127+ return childrenTextMetrics;
128+ }
129+ </script>
9130 </head>
10131 <style></style>
11− <body id="root"></body>
132+ <body id="root">
133+ <body id="root">
134+ <div id="elm-home"></div>
135+ <canvas id="canvas"></canvas>
136+ </body>
137+ </body>
12138
13139 <script type="text/javascript">
14− var app = Elm.Tests.Run.init();
140+ // Starting Elm App,
141+ var app = Elm.${module_name}.init({
142+ node: document.getElementById("elm-home"),
143+ });
144+
145+
146+ // create a canvas for text measurements
147+ let canvas = createHiDPICanvas(200, 100, "canvas");
15148
16149 var test_results = "waiting..";
17150
18151 app.ports.report.subscribe(function (results) {
19− // these are extracted by the script that runs the browser automation.
20152 test_results = results;
21153 });
22154
@@ -32,76 +164,20 @@
32164 }
33165 var style = getStyle(element);
34166 var bbox = getBoundingBox(element);
167+ var metrics = getTextMetrics(element);
35168
36169 var visible = isVisible(id, bbox);
37170
38− var result = { bbox: bbox, style: style, id: id, isVisible: visible };
171+ var result = {
172+ textMetrics: metrics,
173+ bbox: bbox,
174+ style: style,
175+ id: id,
176+ isVisible: visible,
177+ };
39178 results.push(result);
40179 }
41180 app.ports.styles.send(results);
42181 });
43−
44− function isVisible(id, bbox) {
45− var current = document.getElementById(id);
46− var result = 0;
47− if (current == document.elementFromPoint(bbox["left"], bbox["top"])) {
48− result++;
49− }
50− if (
51− current == document.elementFromPoint(bbox["left"], bbox["bottom"] - 1)
52− ) {
53− result++;
54− }
55− if (
56− current == document.elementFromPoint(bbox["right"] - 1, bbox["top"])
57− ) {
58− result++;
59− }
60− if (
61− current ==
62− document.elementFromPoint(bbox["right"] - 1, bbox["bottom"] - 1)
63− ) {
64− result++;
65− }
66−
67− if (result == 4) {
68− return true;
69− } else {
70− return false;
71− }
72− }
73−
74− function getStyle(element) {
75− var props = [];
76− var style = window.getComputedStyle(element);
77− for (var i = style.length; i--; ) {
78− var name = style.item(i);
79− var value = style.getPropertyValue(name);
80− props.push([name, value]);
81− }
82− return props;
83− }
84−
85− function getBoundingBox(element) {
86− var bbox = element.getBoundingClientRect();
87− var style = window.getComputedStyle(element, null);
88−
89− var padding = {
90− top: parseFloat(style.getPropertyValue("padding-top")),
91− bottom: parseFloat(style.getPropertyValue("padding-bottom")),
92− left: parseFloat(style.getPropertyValue("padding-left")),
93− right: parseFloat(style.getPropertyValue("padding-right")),
94− };
95−
96− return {
97− top: bbox.top,
98− bottom: bbox.bottom,
99− left: bbox.left,
100− right: bbox.right,
101− width: bbox.width,
102− height: bbox.height,
103− padding: padding,
104− };
105− }
106182 </script>
107183</html>
tests-rendering/automation/view.jsnew file+50
@@ -0,0 +1,50 @@
1+const fs = require("fs");
2+const program = require("commander");
3+const path = require("path");
4+const chalk = require("chalk");
5+const childProcess = require("child_process");
6+const build = require("./build.js");
7+const chokidar = require("chokidar");
8+const http = require("http");
9+
10+var filepath = null;
11+program
12+
13+ .arguments("<filepath>")
14+ .action(function (p) {
15+ filepath = p;
16+ })
17+ .parse(process.argv);
18+
19+(async () => {
20+ var dir = "tmp";
21+ if (!fs.existsSync(dir)) {
22+ fs.mkdirSync(dir);
23+ }
24+
25+ console.log("Compiling tests");
26+ let content = await build.compile_to_string({
27+ template: "./tests-rendering/automation/templates/gather-styles.html",
28+ elm: filepath,
29+ elmOptions: { cwd: "./tests-rendering" },
30+ });
31+ console.log("Finished compiling");
32+ // console.log(content);
33+
34+ chokidar.watch("./tests-rendering/*.elm").on("all", (event, path) => {
35+ console.log("Changes detected, refresh!");
36+ content = build.compile_to_string({
37+ template: "./tests-rendering/automation/templates/gather-styles.html",
38+ elm: filepath,
39+ elmOptions: { cwd: "./tests-rendering" },
40+ });
41+ });
42+ console.log("Serving on http://localhost:8080");
43+ http
44+ .createServer(function (req, res) {
45+ res.writeHead(200, { "Content-Type": "text/html" });
46+ res.write(content);
47+ res.end();
48+ })
49+ .listen(8080);
50+})();
tests-rendering/make.shdeleted−2
@@ -1,2 +0,0 @@
1−
2−elm-live cases/open/WeirdCentering.elm --dir=view -- --output=view/elm.js --debug
tests-rendering/view/view.htmldeleted−174
@@ -1,174 +0,0 @@
1−<!DOCTYPE html>
2−<html>
3− <head>
4− <meta charset="UTF-8" />
5− <title>Rendering Benchmark Viewer</title>
6− <script type="text/javascript" src="./elm.js"></script>
7− </head>
8− <style></style>
9− <body id="root">
10− <div id="elm-home"></div>
11− <canvas id="canvas"></canvas>
12− </body>
13−
14− <script type="text/javascript">
15− // Calculations for canvas
16− var PIXEL_RATIO = (function () {
17− var ctx = document.createElement("canvas").getContext("2d"),
18− dpr = window.devicePixelRatio || 1,
19− bsr =
20− ctx.webkitBackingStorePixelRatio ||
21− ctx.mozBackingStorePixelRatio ||
22− ctx.msBackingStorePixelRatio ||
23− ctx.oBackingStorePixelRatio ||
24− ctx.backingStorePixelRatio ||
25− 1;
26−
27− return dpr / bsr;
28− })();
29−
30− function createHiDPICanvas(w, h, id, ratio) {
31− if (!ratio) {
32− ratio = PIXEL_RATIO;
33− }
34− let can = document.getElementById(id);
35− can.width = w * ratio;
36− can.height = h * ratio;
37− can.style.width = w + "px";
38− can.style.height = h + "px";
39− can.getContext("2d").setTransform(ratio, 0, 0, ratio, 0, 0);
40− return can;
41− }
42− // create a canvas for text measurements
43− let canvas = createHiDPICanvas(200, 100, "canvas");
44− // Starting Elm App,
45− var app = Elm.WeirdCentering.init({
46− node: document.getElementById("elm-home"),
47− });
48−
49− var test_results = "waiting..";
50−
51− app.ports.report.subscribe(function (results) {
52− test_results = results;
53− });
54−
55− app.ports.analyze.subscribe(function (ids) {
56− // ids : List String
57− var idsLength = ids.length;
58− var results = [];
59− for (var i = 0; i < idsLength; i++) {
60− var id = ids[i];
61− var element = document.getElementById(id);
62− if (element == null) {
63− console.log("id " + id + " not found");
64− }
65− var style = getStyle(element);
66− var bbox = getBoundingBox(element);
67− var metrics = getTextMetrics(element);
68−
69− var visible = isVisible(id, bbox);
70−
71− var result = {
72− textMetrics: metrics,
73− bbox: bbox,
74− style: style,
75− id: id,
76− isVisible: visible,
77− };
78− results.push(result);
79− }
80− app.ports.styles.send(results);
81− });
82−
83− function isVisible(id, bbox) {
84− var current = document.getElementById(id);
85− var result = 0;
86− if (current == document.elementFromPoint(bbox["left"], bbox["top"])) {
87− result++;
88− }
89− if (
90− current == document.elementFromPoint(bbox["left"], bbox["bottom"] - 1)
91− ) {
92− result++;
93− }
94− if (
95− current == document.elementFromPoint(bbox["right"] - 1, bbox["top"])
96− ) {
97− result++;
98− }
99− if (
100− current ==
101− document.elementFromPoint(bbox["right"] - 1, bbox["bottom"] - 1)
102− ) {
103− result++;
104− }
105−
106− if (result == 4) {
107− return true;
108− } else {
109− return false;
110− }
111− }
112−
113− function getStyle(element) {
114− var props = [];
115− var style = window.getComputedStyle(element);
116− for (var i = style.length; i--; ) {
117− var name = style.item(i);
118− var value = style.getPropertyValue(name);
119− props.push([name, value]);
120− }
121− return props;
122− }
123−
124− function getBoundingBox(element) {
125− var bbox = element.getBoundingClientRect();
126− var style = window.getComputedStyle(element, null);
127−
128− var padding = {
129− top: parseFloat(style.getPropertyValue("padding-top")),
130− bottom: parseFloat(style.getPropertyValue("padding-bottom")),
131− left: parseFloat(style.getPropertyValue("padding-left")),
132− right: parseFloat(style.getPropertyValue("padding-right")),
133− };
134−
135− return {
136− top: bbox.top,
137− bottom: bbox.bottom,
138− left: bbox.left,
139− right: bbox.right,
140− width: bbox.width,
141− height: bbox.height,
142− padding: padding,
143− };
144− }
145− function getTextMetrics(element) {
146− // Given our element, we want to return the text metrics on the text within.
147− // If it is an element we want to measure:
148− // we want to get the font family
149− // and the font size.
150− // We're going to presume that the font is loaded.
151− let childrenTextMetrics = [];
152− for (i = 0; i < element.children.length; i++) {
153− if (element.children[i].classList.contains("t")) {
154− let style = window.getComputedStyle(element, null);
155− let fontSize = style.getPropertyValue("font-size");
156− let fontFamily = style.getPropertyValue("font-family");
157− let ctx = canvas.getContext("2d");
158−
159− ctx.font = fontSize + " " + fontFamily; //"16px Roboto";
160− let text = ctx.measureText(element.children[i].innerText);
161−
162− childrenTextMetrics.push({
163− actualBoundingBoxAscent: text.actualBoundingBoxAscent,
164− actualBoundingBoxDescent: text.actualBoundingBoxDescent,
165− actualBoundingBoxLeft: text.actualBoundingBoxLeft,
166− actualBoundingBoxRight: text.actualBoundingBoxRight,
167− width: text.width,
168− });
169− }
170− }
171− return childrenTextMetrics;
172− }
173− </script>
174−</html>