rooibos-roku
Version:
simple, flexible, fun brightscript test framework for roku scenegraph apps - roku brighterscript plugin
212 lines • 13.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TestGroup = void 0;
const brighterscript_1 = require("brighterscript");
const brighterscript = require("brighterscript");
const BrsTranspileState_1 = require("brighterscript/dist/parser/BrsTranspileState");
const Diagnostics_1 = require("../utils/Diagnostics");
const TestSuite_1 = require("./TestSuite");
const Utils_1 = require("./Utils");
class TestGroup extends TestSuite_1.TestBlock {
constructor(testSuite, annotation) {
super(annotation);
this.testCases = [];
this.testSuite = testSuite;
this.setupFunctionName = this.setupFunctionName || this.testSuite.setupFunctionName;
this.tearDownFunctionName = this.tearDownFunctionName || this.testSuite.tearDownFunctionName;
this.beforeEachFunctionName = this.beforeEachFunctionName || this.testSuite.beforeEachFunctionName;
this.afterEachFunctionName = this.afterEachFunctionName || this.testSuite.afterEachFunctionName;
}
addTestCase(testCase) {
this.testCases.push(testCase);
this.hasIgnoredTests = this.hasIgnoredTests || testCase.isIgnored;
this.hasSoloTests = this.hasSoloTests || testCase.isSolo;
this.hasAsyncTests = this.hasAsyncTests || testCase.isAsync;
}
modifyAssertions(testCase, noEarlyExit, editor, namespaceLookup, scope) {
//for each method
//if assertion
//wrap with if is not fail
//add line number as last param
const transpileState = new BrsTranspileState_1.BrsTranspileState(this.file);
try {
let func = this.testSuite.classStatement.methods.find((m) => m.name.text.toLowerCase() === testCase.funcName.toLowerCase());
func.walk(brighterscript.createVisitor({
ExpressionStatement: (expressionStatement, parent, owner, key) => {
var _a;
let callExpression = expressionStatement.expression;
if (brighterscript.isCallExpression(callExpression) && brighterscript.isDottedGetExpression(callExpression.callee)) {
let dge = callExpression.callee;
let isSub = ((_a = callExpression.findAncestor(brighterscript_1.isFunctionExpression)) === null || _a === void 0 ? void 0 : _a.functionType.kind) === brighterscript_1.TokenKind.Sub;
let assertRegex = /(?:fail|assert(?:[a-z0-9]*)|expect(?:[a-z0-9]*)|stubCall)/i;
if (dge && assertRegex.test(dge.name.text)) {
// get the path to the call expression
// `m`.assert*(...)
// `m.testSuite`.assert*(...)
// `someMagicVar`.assert*(...)
const callPath = brighterscript_1.util.getAllDottedGetParts(callExpression.callee.obj).map((part) => part.text).join('.');
if (dge.name.text === 'stubCall') {
this.modifyModernRooibosExpectCallExpression(callExpression, editor, namespaceLookup, scope);
return expressionStatement;
}
else {
if (dge.name.text === 'expectCalled' || dge.name.text === 'expectNotCalled') {
this.modifyModernRooibosExpectCallExpression(callExpression, editor, namespaceLookup, scope);
}
if (dge.name.text === 'expectCalled' || dge.name.text === 'expectNotCalled') {
this.modifyModernRooibosExpectCallExpression(callExpression, editor, namespaceLookup, scope);
}
if (!noEarlyExit) {
const trailingLine = brighterscript_1.Parser.parse(`if ${callPath}.currentResult?.isFail = true then ${callPath}.done() : return ${isSub ? '' : 'invalid'}`).ast.statements[0];
editor.arraySplice(owner, key + 1, 0, trailingLine);
}
const leadingLine = brighterscript_1.Parser.parse(`${callPath}.currentAssertLineNumber = ${callExpression.range.start.line + 1}`).ast.statements[0];
editor.arraySplice(owner, key, 0, leadingLine);
}
}
}
}
}), {
walkMode: brighterscript.WalkMode.visitStatementsRecursive
});
}
catch (e) {
console.error(e);
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
(0, Diagnostics_1.diagnosticErrorProcessingFile)(this.testSuite.file, e.message);
}
}
modifyModernRooibosExpectCallExpression(callExpression, editor, namespaceLookup, scope) {
let isNotCalled = false;
let isStubCall = false;
//modify args
let arg0 = callExpression.args[0];
let arg1 = callExpression.args[1];
if ((0, brighterscript_1.isDottedGetExpression)(callExpression.callee)) {
const nameText = callExpression.callee.name.text;
isNotCalled = nameText === 'expectNotCalled';
isStubCall = nameText === 'stubCall';
if (isStubCall && this.shouldNotModifyStubCall(arg0, namespaceLookup, scope)) {
return;
}
editor.setProperty(callExpression.callee.name, 'text', `_${nameText}`);
}
if (brighterscript.isCallExpression(arg0) && (0, brighterscript_1.isDottedGetExpression)(arg0.callee)) {
//is it a namespace?
let dg = arg0.callee;
let nameParts = (0, Utils_1.getAllDottedGetParts)(dg);
let name = nameParts.pop();
if (name) {
//is a namespace?
if (nameParts[0] && namespaceLookup.has(nameParts[0].toLowerCase())) {
//then this must be a namespace method
let fullPathName = nameParts.join('.').toLowerCase();
let ns = namespaceLookup.get(fullPathName);
if (!ns) {
//TODO this is an error condition!
}
nameParts.push(name);
let functionName = nameParts.join('_').toLowerCase();
editor.removeFromArray(callExpression.args, 0);
if (!isNotCalled && !isStubCall) {
const expectedArgs = new brighterscript_1.ArrayLiteralExpression(arg0.args, (0, brighterscript_1.createToken)(brighterscript_1.TokenKind.LeftSquareBracket), (0, brighterscript_1.createToken)(brighterscript_1.TokenKind.RightSquareBracket));
editor.addToArray(callExpression.args, 0, expectedArgs);
}
editor.addToArray(callExpression.args, 0, (0, brighterscript_1.createInvalidLiteral)());
editor.addToArray(callExpression.args, 0, (0, brighterscript_1.createInvalidLiteral)());
editor.addToArray(callExpression.args, 0, (0, brighterscript_1.createStringLiteral)(functionName));
editor.addToArray(callExpression.args, 0, brighterscript.createVariableExpression(functionName));
this.testSuite.session.globalStubbedMethods.add(functionName);
}
else {
let functionName = arg0.callee.name.text;
let fullPath = (0, Utils_1.getStringPathFromDottedGet)(arg0.callee.obj);
editor.removeFromArray(callExpression.args, 0);
if (!isNotCalled && !isStubCall) {
const expectedArgs = new brighterscript_1.ArrayLiteralExpression(arg0.args, (0, brighterscript_1.createToken)(brighterscript_1.TokenKind.LeftSquareBracket), (0, brighterscript_1.createToken)(brighterscript_1.TokenKind.RightSquareBracket));
editor.addToArray(callExpression.args, 0, expectedArgs);
}
editor.addToArray(callExpression.args, 0, fullPath !== null && fullPath !== void 0 ? fullPath : (0, brighterscript_1.createInvalidLiteral)());
editor.addToArray(callExpression.args, 0, (0, Utils_1.getRootObjectFromDottedGet)(arg0.callee));
editor.addToArray(callExpression.args, 0, (0, brighterscript_1.createStringLiteral)(functionName));
editor.addToArray(callExpression.args, 0, arg0.callee.obj);
}
}
}
else if (brighterscript.isDottedGetExpression(arg0)) {
let functionName = arg0.name.text;
let fullPath = (0, Utils_1.getStringPathFromDottedGet)(arg0.obj);
arg0 = callExpression.args[0];
editor.removeFromArray(callExpression.args, 0);
if (!isNotCalled && !isStubCall) {
editor.addToArray(callExpression.args, 0, (0, brighterscript_1.createInvalidLiteral)());
}
editor.addToArray(callExpression.args, 0, fullPath !== null && fullPath !== void 0 ? fullPath : (0, brighterscript_1.createInvalidLiteral)());
editor.addToArray(callExpression.args, 0, (0, Utils_1.getRootObjectFromDottedGet)(arg0));
editor.addToArray(callExpression.args, 0, (0, brighterscript_1.createStringLiteral)(functionName));
editor.addToArray(callExpression.args, 0, arg0.obj);
}
else if (brighterscript.isCallfuncExpression(arg0)) {
let functionName = arg0.methodName.text;
editor.removeFromArray(callExpression.args, 0);
if (isNotCalled || isStubCall) {
//TODO in future we can improve is notCalled to know which callFunc function it is
// const expectedArgs = new ArrayLiteralExpression([createStringLiteral(functionName)], createToken(TokenKind.LeftSquareBracket), createToken(TokenKind.RightSquareBracket));
// editor.addToArray(callExpression.args, 0, expectedArgs);
}
else {
const expectedArgs = new brighterscript_1.ArrayLiteralExpression([(0, brighterscript_1.createStringLiteral)(functionName), ...arg0.args], (0, brighterscript_1.createToken)(brighterscript_1.TokenKind.LeftSquareBracket), (0, brighterscript_1.createToken)(brighterscript_1.TokenKind.RightSquareBracket));
editor.addToArray(callExpression.args, 0, expectedArgs);
}
let fullPath = (0, Utils_1.getStringPathFromDottedGet)(arg0.callee);
editor.addToArray(callExpression.args, 0, fullPath !== null && fullPath !== void 0 ? fullPath : (0, brighterscript_1.createInvalidLiteral)());
editor.addToArray(callExpression.args, 0, (0, Utils_1.getRootObjectFromDottedGet)(arg0.callee));
editor.addToArray(callExpression.args, 0, (0, brighterscript_1.createStringLiteral)('callFunc'));
editor.addToArray(callExpression.args, 0, arg0.callee);
}
else if (brighterscript.isCallExpression(arg0) && brighterscript.isVariableExpression(arg0.callee)) {
let functionName = arg0.callee.getName(brighterscript.ParseMode.BrightScript);
editor.removeFromArray(callExpression.args, 0);
if (!isNotCalled && !isStubCall) {
const expectedArgs = new brighterscript_1.ArrayLiteralExpression(arg0.args, (0, brighterscript_1.createToken)(brighterscript_1.TokenKind.LeftSquareBracket), (0, brighterscript_1.createToken)(brighterscript_1.TokenKind.RightSquareBracket));
editor.addToArray(callExpression.args, 0, expectedArgs);
}
editor.addToArray(callExpression.args, 0, (0, brighterscript_1.createInvalidLiteral)());
editor.addToArray(callExpression.args, 0, (0, brighterscript_1.createInvalidLiteral)());
editor.addToArray(callExpression.args, 0, (0, brighterscript_1.createStringLiteral)(functionName));
editor.addToArray(callExpression.args, 0, brighterscript.createVariableExpression(functionName));
this.testSuite.session.globalStubbedMethods.add(functionName);
}
}
shouldNotModifyStubCall(arg0, namespaceLookup, scope) {
if (brighterscript.isDottedGetExpression(arg0)) {
let nameParts = (0, Utils_1.getAllDottedGetParts)(arg0);
let functionName = nameParts.join('.');
return scope.getCallableByName(functionName);
}
else if (brighterscript.isVariableExpression(arg0)) {
return (scope.symbolTable.hasSymbol(arg0.getName(brighterscript_1.ParseMode.BrightScript)) ||
scope.getCallableByName(arg0.getName(brighterscript_1.ParseMode.BrighterScript)));
}
return false;
}
asText() {
let testCaseText = [...this.testCases].filter((tc) => tc.isIncluded).map((tc) => tc.asText());
return `
{
name: ${(0, Utils_1.sanitizeBsJsonString)(this.name)}
isSolo: ${this.isSolo}
isIgnored: ${this.isIgnored}
isAsync: ${this.isAsync}
filename: "${this.pkgPath}"
lineNumber: "${this.annotation.annotation.range.start.line + 1}"
setupFunctionName: "${this.setupFunctionName || ''}"
tearDownFunctionName: "${this.tearDownFunctionName || ''}"
beforeEachFunctionName: "${this.beforeEachFunctionName || ''}"
afterEachFunctionName: "${this.afterEachFunctionName || ''}"
testCases: [${testCaseText.join(',\n')}]
}`;
}
}
exports.TestGroup = TestGroup;
//# sourceMappingURL=TestGroup.js.map