/* global before session */
"use strict";
/**
* Makes tests root session.
*
* - runner loads root `conftest.js` if it is located on one level with
* each of `CONF.test.dirs`;
* - if each of `CONF.test.dirs` is file with tests, runner loads and executes it;
* - if each of `CONF.test.dirs` is folder runner loads files inside recursive if
* file name starts with `test` and ends with `.js`;
* - inside each subfolder of each of `CONF.test.dirs` runner loads `conftest.js`
* file if it is present;
*
* @module
*/
const fs = require("fs");
const path = require("path");
const _ = require("lodash");
const expect = require("chai").expect;
const U = require("glace-utils");
require("./globals");
const CONF = require("./config");
const ConfigError = require("./error").ConfigError;
/**
* Loads special `preloads` files before main conftests and test files.
*
* Preloads are specified in `CONF.preloads` array. It may be managed only
* programmatically and needs as extension point to load some custom files
* before tests.
*
* After preloads it loads root (the mainest) conftest file, which may be set
* via CLI.
*/
const preloads = () => {
const pre = _.clone(CONF.session.preloads);
if (CONF.session.rootConftest && !pre.includes(CONF.session.rootConftest)) {
pre.push(CONF.session.rootConftest);
}
for (const preload of pre) {
expect(
fs.existsSync(preload) && fs.statSync(preload).isFile(),
`Preloader '${preload}' isn't a file or doesn't exist`
).to.be.true;
require(preload);
}
};
/**
* Main conftests are loaded before tests session creation and may used for
* objects management, for example to created custom instance of global `SS`.
*
* Main conftest is `conftest.js` file which is located on one hierarchy level
* with each specified tests folder or file.
*/
const mainConftests = () => {
for (const testDir of CONF.test.dirs) {
if (!fs.existsSync(testDir)) {
throw new ConfigError(
`Tests file or folder '${testDir}' doesn't exist`);
}
const siblingConftest = path.resolve(path.dirname(testDir), "conftest.js");
if (fs.existsSync(siblingConftest)) {
require(siblingConftest);
}
}
};
/**
* Callback to create tests session.
*
* It kills some processes before all if they are specified.
*/
const sessFunc = () => {
if (CONF.session.killProcs) {
before(async () => {
for (const procName of CONF.session.killProcs) {
await U.killProcs(procName);
}
});
}
for (const testDir of CONF.test.dirs) {
if (!fs.statSync(testDir).isDirectory()) {
reload(testDir);
continue;
}
loadTests(testDir);
}
};
/**
* Loads test files recursively. Test file name should start with `test` and
* end with `.js`.
*
* @function
* @arg {string} dir - Folder with test files.
*/
const loadTests = dir => {
for (const fileName of fs.readdirSync(dir)) {
const filePath = path.resolve(dir, fileName);
const fileStat = fs.statSync(filePath);
if (fileStat.isDirectory()) {
loadTests(filePath);
}
if (fileStat.isFile()) {
if (fileName === "conftest.js") require(filePath);
if (fileName.startsWith("test") && fileName.endsWith(".js")) {
reload(filePath);
}
}
}
};
const reload = filePath => {
const fullPath = path.resolve(filePath);
delete require.cache[fullPath];
return require(fullPath);
};
preloads();
mainConftests();
session(sessFunc);