Skip to content

Commit

Permalink
Feature/accept expect once with function param (#157)
Browse files Browse the repository at this point in the history
* adds support for function pointers in expectCalled functions

* adds expectCalled and expectNotCalled

* Fixes for stubbing - still is borked in some way though

* Fixes callfunc issues with new expect syntax
  • Loading branch information
georgejecook authored Apr 1, 2022
1 parent 5e42076 commit 6c80fdd
Show file tree
Hide file tree
Showing 6 changed files with 1,227 additions and 222 deletions.
83 changes: 69 additions & 14 deletions bsc-plugin/src/lib/rooibos/TestGroup.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { CallExpression } from 'brighterscript';
import { createVisitor, WalkMode, isDottedGetExpression, isCallExpression } from 'brighterscript';
import type { CallExpression, DottedGetExpression } from 'brighterscript';
import { ArrayLiteralExpression, createInvalidLiteral, createStringLiteral, createToken, isDottedGetExpression, TokenKind } from 'brighterscript';
import * as brighterscript from 'brighterscript';
import { BrsTranspileState } from 'brighterscript/dist/parser/BrsTranspileState';
import { TranspileState } from 'brighterscript/dist/parser/TranspileState';
import { diagnosticErrorProcessingFile } from '../utils/Diagnostics';
Expand Down Expand Up @@ -51,30 +52,84 @@ export class TestGroup extends TestBlock {
const transpileState = new BrsTranspileState(this.file);
try {
let func = this.testSuite.classStatement.methods.find((m) => m.name.text.toLowerCase() === testCase.funcName.toLowerCase());
func.walk(createVisitor({
ExpressionStatement: (es) => {
let ce = es.expression as CallExpression;
if (isCallExpression(ce) && isDottedGetExpression(ce.callee)) {
let dge = ce.callee;
let assertRegex = /(?:fail|assert(?:[a-z0-9]*)|expect(?:[a-z0-9]*))/i;
func.walk(brighterscript.createVisitor({
ExpressionStatement: (expressionStatement) => {
let callExpression = expressionStatement.expression as CallExpression;
if (brighterscript.isCallExpression(callExpression) && brighterscript.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)) {
return new RawCodeStatement(`
m.currentAssertLineNumber = ${ce.range.start.line}
${ce.transpile(transpileState).join('')}
${noEarlyExit ? '' : 'if m.currentResult.isFail then return invalid'}
`, this.file, ce.range);
if (dge.name.text === 'stubCall') {
this.modifyModernRooibosExpectCallExpression(callExpression);
return expressionStatement;

} else {

if (dge.name.text === 'expectCalled' || dge.name.text === 'expectNotCalled') {
this.modifyModernRooibosExpectCallExpression(callExpression);
}
return new RawCodeStatement(`
m.currentAssertLineNumber = ${callExpression.range.start.line}
${callExpression.transpile(transpileState).join('')}
${noEarlyExit ? '' : 'if m.currentResult.isFail then return invalid'}
`, this.file, callExpression.range);
}
}
}
}
}), {
walkMode: WalkMode.visitStatementsRecursive
walkMode: brighterscript.WalkMode.visitStatementsRecursive
});
} catch (e) {
// console.log(e);
diagnosticErrorProcessingFile(this.testSuite.file, e.message);
}
}

private modifyModernRooibosExpectCallExpression(callExpression: CallExpression) {
let isNotCalled = false;
let isStubCall = false;
if (isDottedGetExpression(callExpression.callee)) {
const nameText = callExpression.callee.name.text;
callExpression.callee.name.text = `_${nameText}`;
isNotCalled = nameText === 'expectNotCalled';
isStubCall = nameText === 'stubCall';
}
//modify args
let arg0 = callExpression.args[0];
if (brighterscript.isCallExpression(arg0) && isDottedGetExpression(arg0.callee)) {
let functionName = arg0.callee.name.text;
callExpression.args.shift();
if (!isNotCalled && !isStubCall) {
const expectedArgs = new ArrayLiteralExpression(arg0.args, createToken(TokenKind.LeftSquareBracket), createToken(TokenKind.RightSquareBracket));
callExpression.args.unshift(expectedArgs);
}
callExpression.args.unshift(createStringLiteral(functionName));
callExpression.args.unshift(arg0.callee.obj);
} else if (brighterscript.isDottedGetExpression(arg0)) {
let functionName = arg0.name.text;
arg0 = callExpression.args.shift() as DottedGetExpression;
if (!isNotCalled && !isStubCall) {
callExpression.args.unshift(createInvalidLiteral());
}
callExpression.args.unshift(createStringLiteral(functionName));
callExpression.args.unshift((arg0 as DottedGetExpression).obj);
} else if (brighterscript.isCallfuncExpression(arg0)) {
let functionName = arg0.methodName.text;
callExpression.args.shift();
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));
// callExpression.args.unshift(expectedArgs);
} else {
const expectedArgs = new ArrayLiteralExpression([createStringLiteral(functionName), ...arg0.args], createToken(TokenKind.LeftSquareBracket), createToken(TokenKind.RightSquareBracket));
callExpression.args.unshift(expectedArgs);
}
callExpression.args.unshift(createStringLiteral('callFunc'));
callExpression.args.unshift(arg0.callee);
}
}

public asText(): string {
let testCaseText = [...this.testCases.values()].filter((tc) => tc.isIncluded).map((tc) => tc.asText());

Expand Down
Loading

0 comments on commit 6c80fdd

Please sign in to comment.