Merge pull request #2887 from solgenomics/topic/ona
[sgn.git] / js / run-tests.js
blob9342087aa66be3867942553b4cfdf24510814e8a
1 'use strict';
3 const process = require('process');
4 process.chdir( __dirname );
6 const webpack = require('webpack');
7 const JSDOM = require("jsdom").JSDOM;
8 const test = require('tape');
9 const { Console } = require('console');
10 var fs = require('fs');
11 const del = require('del');
12 const path = require('path');
13 const glob = require("glob");
14 const nock = require('nock');
15 const node_fetch = require('node-fetch');
17 const { JSAN_to_src_path } = require("./webpack_util/utils.js");
19 const webpackConfig = require('./test.webpack.config');
20 const buildPath = webpackConfig.output.path;
21 const legacyPath = path.resolve(__dirname, "./source/legacy/");
23 // Default DOM contents within which a test script is excecuted in.
24 const empty_html = `
25   <!DOCTYPE html>
26   <html lang="en">
27   <head>
28     <meta charset="utf-8">
29     <title></title>
30   </head>
31   <body></body>
32   </html>
35 // If the user provided globs, use them instead of running all tests.
36 if(process.argv.length>2){
37   var targets = [].concat(...process.argv.slice(2).map(gt=>glob.sync(gt)))
38     .map(p=>path.resolve(p));
39   if(!targets.length) return console.error("No tests specified.");
40   webpackConfig.entry = targets.reduce((dict,elt)=>{
41     dict[elt] = elt
42     return dict;
43   },{});
46 // First test is always that the scripts build!
47 test('Webpack Build '+Object.keys(webpackConfig.entry).join(", "), function (t) {
48   t.plan(1);
49   // Remove old built tests
50   del.sync([path.resolve(buildPath)]);
51   // Run webpack
52   webpack(webpackConfig).run((err,stats)=>{
53     if(err) t.fail(err);
54     else {
55       var st = JSON.stringify(stats.toJson("minimal"));
56       if(st.errors) t.fail(st);
57       t.pass(st);
58       // Once the scripts build, we can run the rest of the tests.
59       runTests(JSON.parse(fs.readFileSync(path.resolve(buildPath,'./mapping.json'))));
60     }
61   });
62 });
64 // Run each test file in a mapping (generated from webpack-filemap-plugin.js)
65 function runTests(mapping){
66   // For each test file:
67   Object.entries(mapping).map(kv=>{
68     // Make unique list of all JSAN Deps resolved to their paths and chunk files
69     return [...new Set(kv[1].legacy
70       .map(jsan=>JSAN_to_src_path(legacyPath,jsan))
71       .concat(kv[1].files.map(fn=>path.resolve(buildPath,fn))))];
72   }).forEach(scrptList=>{
73     // Run a JSDOM Virtual instance with all scripts and deps for each test file
74     const dom = new JSDOM(empty_html, {
75       url:"https://cassavabase.org/test.html",
76       contentType: "text/html",
77       includeNodeLocations: true,
78       runScripts: "dangerously"
79     });
80     // Reference tape from the JSDOM window, by name defined in test.webpack.config
81     dom.window[webpackConfig.externals.tape] = test;
82     // Reference nock from the JSDOM window, by name defined in test.webpack.config
83     // also clean up current mocked responses from previous tests
84     dom.window[webpackConfig.externals.nock] = nock;
85     nock.cleanAll();
86     nock.disableNetConnect();
87     // Polyfill JSDOM fetch using node-fetch
88     dom.window.fetch = node_fetch;
89     // Ensure console.log/info/debug statements inside virtual DOM print to stderr
90     // by replacing the default console with one which routes to stderr
91     // This ensures "pure" tap stdout
92     dom.window.console = new Console({ stdout: process.stderr, stderr: process.stderr });
93     // Add script tags to JSDOM, these excute upon insertion (thereby running
94     // the contained tests).
95     scrptList.forEach(file=>{
96       var src = fs.readFileSync(file)+'';
97       var scrpt = dom.window.document.createElement('script');
98       scrpt.innerHTML = src;
99       dom.window.document.head.appendChild(scrpt);
100     })
101   });