rooibos-roku
Version:
simple, flexible, fun brightscript test framework for roku scenegraph apps - roku brighterscript plugin
245 lines (244 loc) • 12.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RooibosSession = void 0;
const path = require("path");
const brighterscript_1 = require("brighterscript");
const RooibosSessionInfo_1 = require("./RooibosSessionInfo");
const TestSuiteBuilder_1 = require("./TestSuiteBuilder");
const Diagnostics_1 = require("../utils/Diagnostics");
const undent_1 = require("undent");
const fsExtra = require("fs-extra");
// eslint-disable-next-line
const pkg = require('../../../package.json');
class RooibosSession {
constructor(builder, fileFactory) {
this.globalStubbedMethods = new Set();
this.fileFactory = fileFactory;
this.config = builder.options ? builder.options.rooibos || {} : {};
this._builder = builder;
this._suiteBuilder = new TestSuiteBuilder_1.TestSuiteBuilder(this);
this.reset();
}
reset() {
this.sessionInfo = new RooibosSessionInfo_1.SessionInfo(this.config);
}
prepareForTranspile(editor, program, mockUtil) {
this.addTestRunnerMetadata(editor);
this.addLaunchHookToExistingMain(editor);
// Make sure to create the node files before running the global mock logic
// We realy on them in order to check the component scope for the global functions
for (let testSuite of this.sessionInfo.testSuitesToRun) {
if (testSuite.isNodeTest) {
this.createNodeFile(program, testSuite);
}
}
if (this.config.isGlobalMethodMockingEnabled && this.config.isGlobalMethodMockingEfficientMode) {
console.log('Efficient global stubbing is enabled');
this.namespaceLookup = this.getNamespaces(program);
for (let testSuite of this.sessionInfo.testSuitesToRun) {
mockUtil.gatherGlobalMethodMocks(testSuite);
}
}
else {
this.namespaceLookup = new Map();
}
}
updateSessionStats() {
this.sessionInfo.updateInfo();
}
processFile(file) {
let testSuites = this._suiteBuilder.processFile(file);
return testSuites;
}
addLaunchHookToExistingMain(editor) {
var _a, _b;
let mainFunction;
const files = this._builder.program.getScopeByName('source').getOwnFiles();
for (let file of files) {
if ((0, brighterscript_1.isBrsFile)(file)) {
const mainFunc = file.parser.references.functionStatements.find((f) => f.name.text.toLowerCase() === 'main');
if (mainFunc) {
mainFunction = mainFunc;
break;
}
}
}
if (mainFunction) {
const initCall = mainFunction.func.body.findChild(f => (0, brighterscript_1.isCallExpression)(f) && (0, brighterscript_1.isVariableExpression)(f.callee) && f.callee.name.text.toLowerCase() === 'rooibos_init', {
walkMode: brighterscript_1.WalkMode.visitAllRecursive
});
if (!initCall) {
editor.addToArray(mainFunction.func.body.statements, 0, brighterscript_1.Parser.parse(`Rooibos_init("${(_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.testSceneName) !== null && _b !== void 0 ? _b : 'RooibosScene'}")`).ast.statements[0]);
}
}
}
addLaunchHookFileIfNotPresent() {
var _a, _b, _c;
let mainFunction;
const files = this._builder.program.getScopeByName('source').getOwnFiles();
for (let file of files) {
if ((0, brighterscript_1.isBrsFile)(file)) {
const mainFunc = file.parser.references.functionStatements.find((f) => f.name.text.toLowerCase() === 'main');
if (mainFunc) {
mainFunction = mainFunc;
break;
}
}
}
if (!mainFunction) {
(0, Diagnostics_1.diagnosticErrorNoMainFound)(files[0]);
if (!this._builder.options.stagingDir && !this._builder.options.stagingFolderPath) {
console.error('this plugin requires that stagingDir or the deprecated stagingFolderPath bsconfig option is set');
(0, Diagnostics_1.diagnosticNoStagingDir)(files[0]);
}
else {
const filePath = path.join((_a = this._builder.options.stagingDir) !== null && _a !== void 0 ? _a : this._builder.options.stagingFolderPath, 'source/rooibosMain.brs');
fsExtra.writeFileSync(filePath, `function main()\n Rooibos_init("${(_c = (_b = this.config) === null || _b === void 0 ? void 0 : _b.testSceneName) !== null && _c !== void 0 ? _c : 'RooibosScene'}")\nend function`);
}
}
}
addTestRunnerMetadata(editor) {
var _a;
let runtimeConfig = this._builder.program.getFile('source/rooibos/RuntimeConfig.bs');
const classStatement = (_a = runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.ast) === null || _a === void 0 ? void 0 : _a.findChild((node) => {
var _a, _b;
return (0, brighterscript_1.isClassStatement)(node) && ((_b = (_a = node.name) === null || _a === void 0 ? void 0 : _a.text) === null || _b === void 0 ? void 0 : _b.toLowerCase()) === 'runtimeconfig';
});
if (classStatement) {
this.updateRunTimeConfigFunction(classStatement, editor);
this.updateVersionTextFunction(classStatement, editor);
this.updateClassMapFunction(classStatement, editor);
this.createIgnoredTestsInfoFunction(classStatement, editor);
}
}
updateRunTimeConfigFunction(classStatement, editor) {
var _a;
let method = classStatement.methods.find((m) => m.name.text === 'getRuntimeConfig');
if (method) {
editor.addToArray(method.func.body.statements, method.func.body.statements.length, brighterscript_1.Parser.parse((0, undent_1.default) `
return {
"reporters": ${this.getReportersList()}
"failFast": ${this.config.failFast ? 'true' : 'false'}
"sendHomeOnFinish": ${this.config.sendHomeOnFinish ? 'true' : 'false'}
"logLevel": ${(_a = this.config.logLevel) !== null && _a !== void 0 ? _a : 0}
"showOnlyFailures": ${this.config.showOnlyFailures ? 'true' : 'false'}
"printTestTimes": ${this.config.printTestTimes ? 'true' : 'false'}
"lineWidth": ${this.config.lineWidth || 60}
"printLcov": ${this.config.printLcov ? 'true' : 'false'}
"port": "${this.config.port || 'invalid'}"
"catchCrashes": ${this.config.catchCrashes ? 'true' : 'false'}
"colorizeOutput": ${this.config.colorizeOutput ? 'true' : 'false'}
"throwOnFailedAssertion": ${this.config.throwOnFailedAssertion ? 'true' : 'false'}
"keepAppOpen": ${this.config.keepAppOpen === undefined || this.config.keepAppOpen ? 'true' : 'false'}
"isRecordingCodeCoverage": ${this.config.isRecordingCodeCoverage ? 'true' : 'false'}
}
`).ast.statements[0]);
}
}
getReportersList() {
let reporters = this.config.reporters;
if (!Array.isArray(reporters)) {
reporters = [];
}
if (this.config.reporter) {
// @todo: warn that `reporter` is deprecated and to use `reporters` instead
reporters.push(this.config.reporter);
}
if (reporters.length < 1) {
reporters.push('console');
}
return `[${reporters.map(this.sanitiseReporterName).toString()}]`;
}
sanitiseReporterName(name) {
switch (name.toLowerCase()) {
case 'console': return 'rooibos_ConsoleTestReporter';
case 'junit': return 'rooibos_JUnitTestReporter';
case 'mocha': return 'rooibos_MochaTestReporter';
}
// @todo: check if function name is valid
return name;
}
updateVersionTextFunction(classStatement, editor) {
let method = classStatement.methods.find((m) => m.name.text === 'getVersionText');
if (method) {
editor.addToArray(method.func.body.statements, method.func.body.statements.length, brighterscript_1.Parser.parse(`return "${pkg.version}"`).ast.statements[0]);
}
}
updateClassMapFunction(classStatement, editor) {
let method = classStatement.methods.find((m) => m.name.text === 'getTestSuiteClassMap');
if (method) {
editor.arrayPush(method.func.body.statements, ...brighterscript_1.Parser.parse((0, undent_1.default) `
return {${this.sessionInfo.testSuitesToRun.map(suite => `
"${suite.name}": ${suite.classStatement.getName(brighterscript_1.ParseMode.BrightScript)}`).join('')}
}
`).ast.statements);
}
}
createNodeFiles(program) {
for (let suite of this.sessionInfo.testSuitesToRun.filter((s) => s.isNodeTest)) {
this.createNodeFile(program, suite);
}
}
createNodeFile(program, suite) {
let xmlText = this.getNodeTestXmlText(suite);
this.fileFactory.addFile(program, suite.xmlPkgPath, xmlText);
let bsFile = program.getFile(suite.bsPkgPath);
if (bsFile) {
bsFile.parser.statements.push();
bsFile.needsTranspiled = true;
}
let brsFile = this.fileFactory.addFile(program, suite.bsPkgPath, (0, undent_1.default) `
function init()
m.top.addField("rooibosRunSuite", "boolean", false)
m.top.observeFieldScoped("rooibosRunSuite", "rooibosRunSuite")
end function
function rooibosRunSuite()
m.top.unobserveFieldScoped("rooibosRunSuite")
nodeRunner = Rooibos_TestRunner(m.top.getScene(), m)
m.top.rooibosTestResult = nodeRunner.runInNodeMode("${suite.name}")
end function
`);
brsFile.parser.invalidateReferences();
}
getNodeTestXmlText(suite) {
return this.fileFactory.createTestXML(suite.generatedNodeName, suite.nodeName, suite);
}
getNamespaceLookup(scope) {
// eslint-disable-next-line @typescript-eslint/dot-notation
return scope['cache'].getOrAdd('namespaceLookup', () => scope.buildNamespaceLookup());
}
getNamespaces(program) {
let scopeNamespaces = new Map();
let processedScopes = new Set();
for (const file of Object.values(program.files)) {
for (let scope of program.getScopesForFile(file)) {
if (processedScopes.has(scope.dependencyGraphKey)) {
// Skip this scope if it has already been processed
continue;
}
let scopeMap = this.getNamespaceLookup(scope);
// scopeNamespaces = new Map<string, NamespaceContainer>([...Array.from(scopeMap.entries())]);
for (let [key, value] of scopeMap.entries()) {
scopeNamespaces.set(key, value);
}
processedScopes.add(scope.dependencyGraphKey);
}
}
return scopeNamespaces;
}
createIgnoredTestsInfoFunction(cs, editor) {
let method = cs.methods.find((m) => m.name.text === 'getIgnoredTestInfo');
if (method) {
editor.arrayPush(method.func.body.statements, ...brighterscript_1.Parser.parse([
'return {',
` "count": ${this.sessionInfo.ignoredCount}`,
` "items": [`,
...this.sessionInfo.ignoredTestNames.map((name) => `"${name}"`),
` ]`,
`}`
].join('\n')).ast.statements);
}
}
}
exports.RooibosSession = RooibosSession;
//# sourceMappingURL=RooibosSession.js.map