@@ -1,299 +1,311 @@
1const compileToString = require("node-elm-compiler").compileToString;
1const compileToString = require("node-elm-compiler").compileToString;
2−const { Builder, By, Key, until } = require('selenium-webdriver');
2+const { Builder, By, Key, until } = require("selenium-webdriver");
3−const chrome = require('selenium-webdriver/chrome');
3+const chrome = require("selenium-webdriver/chrome");
4−const firefox = require('selenium-webdriver/firefox');
4+const firefox = require("selenium-webdriver/firefox");
5−const fs = require('fs');
5+const fs = require("fs");
6−const program = require('commander');
6+const program = require("commander");
7const path = require("path");
7const path = require("path");
8−const chalk = require('chalk');
8+const chalk = require("chalk");
9−const childProcess = require('child_process')
9+const childProcess = require("child_process");
11−program.option('-s, --sauce', 'run tests on sauce labs')
12+ .option("-s, --sauce", "run tests on sauce labs")
12− .option('--chrome', 'run chrome tests (default)')
13+ .option("--chrome", "run chrome tests (default)")
13− .option('--firefox', 'run firefox tests')
14+ .option("--firefox", "run firefox tests")
14− .option('--ie', 'run ie tests')
15+ .option("--ie", "run ie tests")
15− .option('--edge', 'run edge tests')
16+ .option("--edge", "run edge tests")
16− .option('--build [value]', 'Set build number for sauce labs')
17+ .option("--build [value]", "Set build number for sauce labs")
17− .option('--name [value]', 'Set run name for sauce labs')
18+ .option("--name [value]", "Set run name for sauce labs")
18− .option('--verbose', 'Print out all test results')
19+ .option("--verbose", "Print out all test results")
19− .parse(process.argv)
20+ .parse(process.argv);
22// 'Windows 10'
22// 'Windows 10'
25const windows = {
24const windows = {
26− chrome: {
25+ chrome: {
27− platform: "Windows 10"
26+ platform: "Windows 10",
28− , browser: "chrome"
27+ browser: "chrome",
29− , browserVersion: "latest"
28+ browserVersion: "latest",
31− firefox: {
30+ firefox: {
32− platform: "Windows 10"
31+ platform: "Windows 10",
33− , browser: "firefox"
32+ browser: "firefox",
34− , browserVersion: "latest"
33+ browserVersion: "latest",
37− platform: "Windows 10"
36+ platform: "Windows 10",
38− , browser: "MicrosoftEdge"
37+ browser: "MicrosoftEdge",
39− , browserVersion: "latest"
38+ browserVersion: "latest",
42− platform: "Windows 10"
41+ platform: "Windows 10",
43− , browser: "internet explorer"
42+ browser: "internet explorer",
44− , browserVersion: "latest"
43+ browserVersion: "latest",
48const all_windows = [
47const all_windows = [
49− windows.chrome
48+ windows.chrome,
50− , windows.firefox
49+ windows.firefox,
51− , windows.edge
50+ windows.edge,
52− // i.e. takes forever and seems to make selenium timeout :/
51+ // i.e. takes forever and seems to make selenium timeout :/
53− // not really sure how to extend the timeout.
52+ // not really sure how to extend the timeout.
54− // , windows.ie
53+ // , windows.ie
57// "macOS 10.14"
56// "macOS 10.14"
58const osx = {
57const osx = {
59− chrome: {
58+ chrome: {
60− platform: "macOS 10.14"
59+ platform: "macOS 10.14",
61− , browser: "chrome"
60+ browser: "chrome",
62− , browserVersion: "latest"
61+ browserVersion: "latest",
64− firefox: {
63+ firefox: {
65− platform: "macOS 10.14"
64+ platform: "macOS 10.14",
66− , browser: "firefox"
65+ browser: "firefox",
67− , browserVersion: "latest"
66+ browserVersion: "latest",
69− safari: {
68+ safari: {
70− platform: "macOS 10.14"
69+ platform: "macOS 10.14",
71− , browser: "safari"
70+ browser: "safari",
72− , browserVersion: "latest"
71+ browserVersion: "latest",
76−const all_osx = [
75+const all_osx = [osx.safari];
83− all_windows.concat(all_osx)
77+const all_browsers = all_windows.concat(all_osx);
85function prepare_all_envs(config) {
79function prepare_all_envs(config) {
86− var envs = []
80+ var envs = [];
88− for (i = 0; i < all_windows.length; i++) {
82+ for (i = 0; i < all_browsers.length; i++) {
89− envs.push({
83+ envs.push({
90− browser: all_windows[i].browser,
84+ browser: all_browsers[i].browser,
91− browserVersion: all_windows[i].browserVersion,
85+ browserVersion: all_browsers[i].browserVersion,
92− platform: all_windows[i].platform,
86+ platform: all_browsers[i].platform,
93− build: config.build,
87+ build: config.build,
94− name: config.name
88+ name: config.name,
98− // for (i = 0; i < osx.length; i++) {
92+ // for (i = 0; i < osx.length; i++) {
99− // envs.push({
93+ // envs.push({
100− // browser: osx[i].browser,
94+ // browser: osx[i].browser,
101− // browserVersion: osx[i].browserVersion,
95+ // browserVersion: osx[i].browserVersion,
102− // platform: "macOS 10.14",
96+ // platform: "macOS 10.14",
103− // build: config.build,
97+ // build: config.build,
104− // name: config.name
98+ // name: config.name,
108− return envs
102+ return envs;
111async function compile_and_embed(config) {
105async function compile_and_embed(config) {
112− var template = fs.readFileSync(config.template)
106+ var template = fs.readFileSync(config.template);
113− // we embed the compiled js to avoid having to start a server to read the app.
107+ // we embed the compiled js to avoid having to start a server to read the app.
114− await compileToString(config.elm, config.elmOptions).then(function (compiled_elm_code) {
108+ await compileToString(config.elm, config.elmOptions).then(function (
115− const compiled = eval(`\`${template}\``)
111+ const compiled = eval(`\`${template}\``);
116− fs.writeFileSync(config.target, compiled)
112+ fs.writeFileSync(config.target, compiled);
123function prepare_sauce_driver(env) {
116function prepare_sauce_driver(env) {
124− const username = process.env.SAUCE_USERNAME;
117+ const username = process.env.SAUCE_USERNAME;
125− const accessKey = process.env.SAUCE_ACCESS_KEY;
118+ const accessKey = process.env.SAUCE_ACCESS_KEY;
127− driver = new Builder().withCapabilities({
120+ driver = new Builder()
128− 'browserName': env.browser,
122+ browserName: env.browser,
129− 'platformName': env.platform,
123+ platformName: env.platform,
130− 'browserVersion': env.browserVersion,
124+ browserVersion: env.browserVersion,
131− /* Pass Sauce User Name and Access Key */
125+ /* Pass Sauce User Name and Access Key */
132− 'sauce:options': {
126+ "sauce:options": {
133− 'username': username,
127+ username: username,
134− 'accessKey': accessKey,
128+ accessKey: accessKey,
135− 'build': env.build,
129+ build: env.build,
136− 'name': env.name
130+ name: env.name,
138− }).usingServer("https://@ondemand.saucelabs.com:443/wd/hub").build();
133+ .usingServer("https://@ondemand.saucelabs.com:443/wd/hub")
140− return driver;
136+ return driver;
143async function prepare_local_driver(env) {
139async function prepare_local_driver(env) {
144− const firefoxOptions = new firefox.Options().headless()
140+ const firefoxOptions = new firefox.Options().headless();
145− const chromeOptions = new chrome.Options().headless()
141+ const chromeOptions = new chrome.Options().headless();
147− let driver = await new Builder()
143+ let driver = await new Builder()
148− .forBrowser(env.browser)
144+ .forBrowser(env.browser)
149− .setChromeOptions(chromeOptions)
145+ .setChromeOptions(chromeOptions)
150− .setFirefoxOptions(firefoxOptions)
146+ .setFirefoxOptions(firefoxOptions)
151− .build();
147+ .build();
153− return driver;
149+ return driver;
156async function run_test(driver, url) {
152async function run_test(driver, url) {
157− var results = null
153+ var results = null;
159− await driver.manage().window().setRect({ width: 1200, height: 800, x: 0, y: 0 });
158+ .setRect({ width: 1200, height: 800, x: 0, y: 0 });
160− await driver.get(url);
159+ await driver.get(url);
161− await driver.wait(until.titleIs('tests finished'), 240 * 1000);
160+ await driver.wait(until.titleIs("tests finished"), 240 * 1000);
162− results = await driver.executeScript("return test_results")
161+ results = await driver.executeScript("return test_results");
163− } finally {
162+ } finally {
164− await driver.quit();
163+ await driver.quit();
166− return results
165+ return results;
171(async () => {
168(async () => {
172− var dir = "tmp"
169+ var dir = "tmp";
173− if (!fs.existsSync(dir)) {
170+ if (!fs.existsSync(dir)) {
174− fs.mkdirSync(dir);
171+ fs.mkdirSync(dir);
173+ console.log("Compiling tests");
174+ await compile_and_embed({
175+ template: "./tests-rendering/automation/templates/gather-styles.html",
176+ target: "./tmp/test.html",
177+ elm: ["src/Tests/Run.elm"],
178+ elmOptions: { cwd: "./tests-rendering" },
180+ console.log("Done compiling");
182+ if (program.sauce) {
183+ const build = program.build;
184+ const name = program.name;
186+ if (build == null || name == null) {
187+ throw "A Build and a Name must be specified.";
176− console.log("Compiling tests")
177− await compile_and_embed({
178− template: "./tests-rendering/automation/templates/gather-styles.html",
179− target: "./tmp/test.html",
180− elm: ["src/Tests/Run.elm"],
181− elmOptions: { cwd: "./tests-rendering" }
183− console.log("Done compiling")
185− if (program.sauce) {
186− const build = program.build
187− const name = program.name
189− if (build == null || name == null) {
190− throw ("A Build and a Name must be specified.");
193− var results = []
190+ var results = [];
195− // Publish to netlify
192+ // Publish to netlify
196− childProcess.execSync("sh tests-rendering/automation/publish-file.sh", {
193+ childProcess.execSync("sh tests-rendering/automation/publish-file.sh", {
198− FILE: "test.html",
195+ FILE: "test.html",
199− BUILD: program.build,
196+ BUILD: program.build,
200− NAME: program.name,
197+ NAME: program.name,
201− GIT_EMAIL: "automation@elm-ui.com",
198+ GIT_EMAIL: "automation@elm-ui.com",
202− GIT_NAME: "Elm UI Automation",
199+ GIT_NAME: "Elm UI Automation",
203− HOME: process.env.HOME,
200+ HOME: process.env.HOME,
204− SSH_AUTH_SOCK: process.env.SSH_AUTH_SOCK,
201+ SSH_AUTH_SOCK: process.env.SSH_AUTH_SOCK,
205− SSH_AGENT_PID: process.env.SSH_AGENT_PID
202+ SSH_AGENT_PID: process.env.SSH_AGENT_PID,
209− var url = `http://elm-ui-testing.netlify.com/tests/${program.build}/${program.name}/`
210− console.log(`Running sauce labs test:`)
211− console.log(` ${url}`)
213− const envs = prepare_all_envs({ build: build, name: name })
215− var test_labels = []
216− for (i = 0; i < envs.length; i++) {
217− var driver = prepare_sauce_driver(envs[i])
218− test_runs.push(run_test(driver, url))
219− test_labels.push(envs[i])
222− var results = await Promise.all(test_runs)
223− for (i = 0; i < results.length; i++) {
224− print_results(renderEnvName(test_labels[i]), results[i]);
206+ var url = `http://elm-ui-testing.netlify.com/tests/${program.build}/${program.name}/`;
207+ console.log(`Running sauce labs test:`);
208+ console.log(` ${url}`);
210+ const envs = prepare_all_envs({ build: build, name: name });
213+ var test_labels = [];
214+ for (i = 0; i < envs.length; i++) {
215+ var driver = prepare_sauce_driver(envs[i]);
216+ test_runs.push(run_test(driver, url));
217+ test_labels.push(envs[i]);
219+ var results = await Promise.all(test_runs);
220+ for (i = 0; i < results.length; i++) {
221+ print_results(renderEnvName(test_labels[i]), results[i]);
227− } else {
223+ } else {
228− // Run chrome if nothing else is selected
224+ // Run chrome if nothing else is selected
229− if (program.chrome || (!program.chrome && !program.firefox)) {
225+ if (program.chrome || (!program.chrome && !program.firefox)) {
230− console.log("Running locally on Chrome...")
226+ console.log("Running locally on Chrome...");
231− const driver = await prepare_local_driver(osx.chrome)
227+ const driver = await prepare_local_driver(osx.chrome);
228+ var results = await run_test(
232− var results = await run_test(driver, "file://" + path.resolve('./tmp/test.html'))
230+ "file://" + path.resolve("./tmp/test.html")
233− print_results("Local Chrome", results);
232+ print_results("Local Chrome", results);
235− if (program.firefox) {
234+ if (program.firefox) {
236− console.log("Running locally on Firefox...")
235+ console.log("Running locally on Firefox...");
237− const driver = await prepare_local_driver(osx.firefox)
236+ const driver = await prepare_local_driver(osx.firefox);
237+ var results = await run_test(
238− var results = await run_test(driver, "file://" + path.resolve('./tmp/test.html'))
239+ "file://" + path.resolve("./tmp/test.html")
239− print_results("Local Firefox", results);
241+ print_results("Local Firefox", results);
241− if (program.ie) {
243+ if (program.ie) {
242− console.log("Running locally on IE...")
244+ console.log("Running locally on IE...");
243− const driver = await prepare_local_driver(windows.ie)
245+ const driver = await prepare_local_driver(windows.ie);
244− var results = await run_test(driver, "file://" + path.resolve('./tmp/test.html'))
246+ var results = await run_test(
245− print_results("Local IE", results);
247+ driver,
248− console.log("Running locally on Edge...")
249− const driver = await prepare_local_driver(windows.edge)
250− var results = await run_test(driver, "file://" + path.resolve('./tmp/test.html'))
248+ "file://" + path.resolve("./tmp/test.html")
251− print_results("Local Edge", results);
250+ print_results("Local IE", results);
253+ console.log("Running locally on Edge...");
254+ const driver = await prepare_local_driver(windows.edge);
255+ var results = await run_test(
257+ "file://" + path.resolve("./tmp/test.html")
259+ print_results("Local Edge", results);
256function renderEnvName(env) {
264function renderEnvName(env) {
257− return `${env.platform}, ${env.browser} ${env.browserVersion}`
265+ return `${env.platform}, ${env.browser} ${env.browserVersion}`;
260function print_results(label, results) {
268function print_results(label, results) {
261− var total_passed = 0
269+ var total_passed = 0;
262− var total_failed = 0
270+ var total_failed = 0;
264− if (program.verbose) {
272+ if (program.verbose) {
265− console.log(label)
273+ console.log(label);
267− for (i = 0; i < results.length; i++) {
275+ for (i = 0; i < results.length; i++) {
268− var passed = 0
276+ var passed = 0;
269− var failed = 0
277+ var failed = 0;
270− for (j = 0; j < results[i].results.length; j++) {
278+ for (j = 0; j < results[i].results.length; j++) {
271− if (results[i].results[j][1] == null) {
279+ if (results[i].results[j][1] == null) {
272− passed = passed + 1
280+ passed = passed + 1;
273− } else {
281+ } else {
274− if (failed == 0) {
282+ if (failed == 0) {
275− if (!program.verbose) {
283+ if (!program.verbose) {
276− console.log(label)
284+ console.log(label);
278− console.log(results[i].label)
281− console.log(" " + chalk.red("fail") + " -> " + results[i].results[j][0])
282− console.log(" " + results[i].results[j][1].description)
285− total_passed = total_passed + passed
286− total_failed = total_failed + failed
289− console.log(chalk.green(` ${passed} tests passed`))
290− console.log(chalk.red(` ${failed} tests failed`))
292− } else if (program.verbose) {
293− console.log(results[i].label + chalk.green(` ${passed} tests passed`))
286+ console.log(results[i].label);
288+ failed = failed + 1;
290+ " " + chalk.red("fail") + " -> " + results[i].results[j][0]
292+ console.log(" " + results[i].results[j][1].description);
296− if (total_failed == 0) {
295+ total_passed = total_passed + passed;
296+ total_failed = total_failed + failed;
299+ console.log(chalk.green(` ${passed} tests passed`));
300+ console.log(chalk.red(` ${failed} tests failed`));
302+ } else if (program.verbose) {
297− console.log(`${label} -> ` + chalk.green(`All ${total_passed} tests passed`))
303+ console.log(results[i].label + chalk.green(` ${passed} tests passed`));
306+ if (total_failed == 0) {
308+ `${label} -> ` + chalk.green(`All ${total_passed} tests passed`)