UNPKG

rooibos-roku

Version:

simple, flexible, fun brightscript test framework for roku scenegraph apps - roku brighterscript plugin

188 lines 9.41 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MockUtil = void 0; const brighterscript_1 = require("brighterscript"); const undent_1 = require("undent"); const Diagnostics_1 = require("../utils/Diagnostics"); const Utils_1 = require("./Utils"); class MockUtil { constructor(builder, session) { this.brsFileAdditions = ` function RBS_SM_#ID#_getMocksByFunctionName() if m._rMocksByFunctionName = invalid m._rMocksByFunctionName = {} end if return m._rMocksByFunctionName end function `; this.config = builder.options.rooibos || {}; this.filePathMap = {}; this.fileId = 0; this.session = session; } enableGlobalMethodMocks(file, astEditor) { if (this.config.isGlobalMethodMockingEnabled) { this._processFile(file, astEditor); } } _processFile(file, astEditor) { this.fileId++; this.processedStatements = new Set(); this.astEditor = astEditor; // console.log('processing global methods on ', file.pkgPath); for (let functionStatement of file.parser.references.functionStatements) { this.enableMockOnFunction(file, functionStatement); } this.filePathMap[this.fileId] = file.pkgPath; if (this.processedStatements.size > 0) { this.addBrsAPIText(file); } } enableMockOnFunction(file, functionStatement) { var _a, _b, _c; if ((0, brighterscript_1.isClassStatement)((_a = functionStatement.parent) === null || _a === void 0 ? void 0 : _a.parent)) { // console.log('skipping class', functionStatement.parent?.parent?.name?.text); return; } if (this.processedStatements.has(functionStatement)) { // console.log('skipping processed expression'); return; } const methodName = (functionStatement === null || functionStatement === void 0 ? void 0 : functionStatement.getName(brighterscript_1.ParseMode.BrightScript).toLowerCase()) || ''; // console.log('MN', methodName); if (this.config.isGlobalMethodMockingEfficientMode && !this.session.globalStubbedMethods.has(methodName)) { // console.log('skipping method that is not stubbed', methodName); return; } let isDisabledFoMocking = (_b = functionStatement.annotations) === null || _b === void 0 ? void 0 : _b.find(x => x.name.toLowerCase() === 'disablemocking'); let parentNamespace = functionStatement.findAncestor(brighterscript_1.isNamespaceStatement); while (parentNamespace && !isDisabledFoMocking) { if (parentNamespace) { isDisabledFoMocking = (_c = parentNamespace.annotations) === null || _c === void 0 ? void 0 : _c.find(x => x.name.toLowerCase() === 'disablemocking'); parentNamespace = parentNamespace.findAncestor(brighterscript_1.isNamespaceStatement); } } if (isDisabledFoMocking) { // The developer has stated that this function is not safe to be mocked return; } // console.log('processing stubbed method', methodName); // TODO check if the user has actually mocked or stubbed this function, otherwise leave it alone! for (let param of functionStatement.func.parameters) { param.asToken = null; } const paramNames = functionStatement.func.parameters.map((param) => param.name.text).join(','); const requiresReturnValue = (0, Utils_1.functionRequiresReturnValue)(functionStatement); const globalAaName = '__stubs_globalAa'; const resultName = '__stubOrMockResult'; const storageName = '__globalStubs'; const template = (0, undent_1.default) ` ${globalAaName} = getGlobalAa() if RBS_SM_${this.fileId}_getMocksByFunctionName()["${methodName}"] <> invalid ${resultName} = RBS_SM_${this.fileId}_getMocksByFunctionName()["${methodName}"].callback(${paramNames}) return${requiresReturnValue ? ` ${resultName}` : ''} else if type(${globalAaName}?.${storageName}?.${methodName}).endsWith("Function") __stubFunction = ${globalAaName}.${storageName}.${methodName} ${resultName} = __stubFunction(${paramNames}) return${requiresReturnValue ? ` ${resultName}` : ''} else if ${globalAaName}?.${storageName} <> invalid and ${globalAaName}.${storageName}.doesExist("${methodName}") value = ${globalAaName}.${storageName}.${methodName} return${requiresReturnValue ? ` value` : ''} end if `; const astCodeToInject = brighterscript_1.Parser.parse(template).ast.statements; this.astEditor.arrayUnshift(functionStatement.func.body.statements, ...astCodeToInject); this.processedStatements.add(functionStatement); file.needsTranspiled = true; } addBrsAPIText(file) { const func = brighterscript_1.Parser.parse(this.brsFileAdditions.replace(/\#ID\#/g, this.fileId.toString().trim())).ast.statements; this.astEditor.arrayPush(file.ast.statements, ...func); } gatherGlobalMethodMocks(testSuite) { // console.log('gathering global method mocks for testSuite', testSuite.name); for (let group of [...testSuite.testGroups.values()].filter((tg) => tg.isIncluded)) { for (let testCase of [...group.testCases].filter((tc) => tc.isIncluded)) { this.gatherMockedGlobalMethods(testSuite, testCase); } } } gatherMockedGlobalMethods(testSuite, testCase) { try { let func = testSuite.classStatement.methods.find((m) => m.name.text.toLowerCase() === testCase.funcName.toLowerCase()); func.walk((0, brighterscript_1.createVisitor)({ ExpressionStatement: (expressionStatement, parent, owner) => { let callExpression = expressionStatement.expression; if ((0, brighterscript_1.isCallExpression)(callExpression) && (0, brighterscript_1.isDottedGetExpression)(callExpression.callee)) { let dge = callExpression.callee; let assertRegex = /(?:fail|assert(?:[a-z0-9]*)|expect(?:[a-z0-9]*)|stubCall)/i; if (dge && assertRegex.test(dge.name.text)) { if (dge.name.text === 'stubCall') { this.processGlobalStubbedMethod(callExpression, testSuite); return expressionStatement; } else { if (dge.name.text === 'expectCalled' || dge.name.text === 'expectNotCalled') { this.processGlobalStubbedMethod(callExpression, testSuite); } } } } } }), { walkMode: brighterscript_1.WalkMode.visitStatementsRecursive }); } catch (e) { console.log(e); (0, Diagnostics_1.diagnosticErrorProcessingFile)(testSuite.file, e.message); } } processGlobalStubbedMethod(callExpression, testSuite) { let isStubCall = false; const scope = (0, Utils_1.getScopeForSuite)(testSuite); if ((0, brighterscript_1.isDottedGetExpression)(callExpression.callee)) { const nameText = callExpression.callee.name.text; isStubCall = nameText === 'stubCall'; } //modify args let arg0 = callExpression.args[0]; if (isStubCall) { let functionName = this.getGlobalFunctionName(arg0, scope); if (functionName) { this.session.globalStubbedMethods.add(functionName.toLowerCase()); return; } } if ((0, brighterscript_1.isCallExpression)(arg0)) { let functionName = this.getGlobalFunctionName(arg0.callee, scope); if (functionName) { this.session.globalStubbedMethods.add(functionName.toLowerCase()); } } } getGlobalFunctionName(expression, scope) { let result; if ((0, brighterscript_1.isDottedGetExpression)(expression)) { let nameParts = (0, Utils_1.getAllDottedGetParts)(expression); let functionName = nameParts.join('.'); let callable = scope.getCallableByName(functionName); if (callable) { result = callable.getName(brighterscript_1.ParseMode.BrightScript); } } else if ((0, brighterscript_1.isVariableExpression)(expression)) { let functionName = expression.getName(brighterscript_1.ParseMode.BrightScript); if (scope.symbolTable.hasSymbol(functionName)) { result = functionName; } functionName = expression.getName(brighterscript_1.ParseMode.BrighterScript); if (scope.getCallableByName(functionName)) { result = functionName; } } return result; } } exports.MockUtil = MockUtil; //# sourceMappingURL=MockUtil.js.map