Skip to content

Commit

Permalink
feature(stubs): rooibos will now automtically convert any object that…
Browse files Browse the repository at this point in the history
… requires stubbing into a stubbable object (#176)
  • Loading branch information
georgejecook authored Jun 7, 2022
1 parent 3e23360 commit 4f20292
Show file tree
Hide file tree
Showing 9 changed files with 337 additions and 60 deletions.
5 changes: 4 additions & 1 deletion bsc-plugin/.vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,8 @@
"editor.tabSize": 4,
"editor.insertSpaces": true,
"typescript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": true,
"files.trimTrailingWhitespace": true
"files.trimTrailingWhitespace": true,
"cSpell.words": [
"undent"
]
}
65 changes: 63 additions & 2 deletions bsc-plugin/src/lib/rooibos/TestGroup.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { AstEditor, CallExpression, DottedGetExpression } from 'brighterscript';
import { ArrayLiteralExpression, createInvalidLiteral, createStringLiteral, createToken, isDottedGetExpression, TokenKind } from 'brighterscript';
import type { AstEditor, CallExpression, DottedGetExpression, Expression } from 'brighterscript';
import { isCallExpression, isCallfuncExpression, isIndexedGetExpression, ArrayLiteralExpression, createInvalidLiteral, createStringLiteral, createToken, isDottedGetExpression, TokenKind, isLiteralExpression, isVariableExpression } from 'brighterscript';
import * as brighterscript from 'brighterscript';
import { BrsTranspileState } from 'brighterscript/dist/parser/BrsTranspileState';
import { TranspileState } from 'brighterscript/dist/parser/TranspileState';
Expand Down Expand Up @@ -101,20 +101,26 @@ export class TestGroup extends TestBlock {
let arg0 = callExpression.args[0];
if (brighterscript.isCallExpression(arg0) && isDottedGetExpression(arg0.callee)) {
let functionName = arg0.callee.name.text;
let fullPath = this.getStringPathFromDottedGet(arg0.callee.obj as DottedGetExpression);
editor.removeFromArray(callExpression.args, 0);
if (!isNotCalled && !isStubCall) {
const expectedArgs = new ArrayLiteralExpression(arg0.args, createToken(TokenKind.LeftSquareBracket), createToken(TokenKind.RightSquareBracket));
editor.addToArray(callExpression.args, 0, expectedArgs);
}
editor.addToArray(callExpression.args, 0, fullPath ?? createInvalidLiteral());
editor.addToArray(callExpression.args, 0, this.getRootObjectFromDottedGet(arg0.callee));
editor.addToArray(callExpression.args, 0, createStringLiteral(functionName));
editor.addToArray(callExpression.args, 0, arg0.callee.obj);
} else if (brighterscript.isDottedGetExpression(arg0)) {
let functionName = arg0.name.text;
let fullPath = this.getStringPathFromDottedGet(arg0.obj as DottedGetExpression);
arg0 = callExpression.args[0] as DottedGetExpression;
editor.removeFromArray(callExpression.args, 0);
if (!isNotCalled && !isStubCall) {
editor.addToArray(callExpression.args, 0, createInvalidLiteral());
}
editor.addToArray(callExpression.args, 0, fullPath ?? createInvalidLiteral());
editor.addToArray(callExpression.args, 0, this.getRootObjectFromDottedGet(arg0 as DottedGetExpression));
editor.addToArray(callExpression.args, 0, createStringLiteral(functionName));
editor.addToArray(callExpression.args, 0, (arg0 as DottedGetExpression).obj);
} else if (brighterscript.isCallfuncExpression(arg0)) {
Expand All @@ -128,6 +134,9 @@ export class TestGroup extends TestBlock {
const expectedArgs = new ArrayLiteralExpression([createStringLiteral(functionName), ...arg0.args], createToken(TokenKind.LeftSquareBracket), createToken(TokenKind.RightSquareBracket));
editor.addToArray(callExpression.args, 0, expectedArgs);
}
let fullPath = this.getStringPathFromDottedGet(arg0.callee as DottedGetExpression);
editor.addToArray(callExpression.args, 0, fullPath ?? createInvalidLiteral());
editor.addToArray(callExpression.args, 0, this.getRootObjectFromDottedGet(arg0.callee as DottedGetExpression));
editor.addToArray(callExpression.args, 0, createStringLiteral('callFunc'));
editor.addToArray(callExpression.args, 0, arg0.callee);
}
Expand All @@ -151,4 +160,56 @@ export class TestGroup extends TestBlock {
}`;
}

private getStringPathFromDottedGet(value: DottedGetExpression) {
let parts = [this.getPathValuePartAsString(value)];
let root;
root = value.obj;
while (root) {
if (isCallExpression(root) || isCallfuncExpression(root)) {
return undefined;
}
parts.push(`${this.getPathValuePartAsString(root)}`);
root = root.obj;
}
let joinedParts = parts.reverse().join('.');
return joinedParts === '' ? undefined : createStringLiteral(joinedParts);
}


private getPathValuePartAsString(expr: Expression) {
if (isCallExpression(expr) || isCallfuncExpression(expr)) {
return undefined;
}
if (isVariableExpression(expr)) {
return expr.name.text;
}
if (!expr) {
return undefined;
}
if (isDottedGetExpression(expr)) {
return expr.name.text;
} else if (isIndexedGetExpression(expr)) {
if (isLiteralExpression(expr.index)) {
return `${expr.index.token.text.replace(/^"/, '').replace(/"$/, '')}`;
} else if (isVariableExpression(expr.index)) {
return `${expr.index.name.text}`;
}
}
}

private getRootObjectFromDottedGet(value: DottedGetExpression) {
let root;
if (isDottedGetExpression(value) || isIndexedGetExpression(value)) {

root = value.obj;
while (root.obj) {
root = root.obj;
}
} else {
root = value;
}

return root;
}

}
90 changes: 45 additions & 45 deletions bsc-plugin/src/plugin.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -498,21 +498,21 @@ describe('RooibosPlugin', () => {
getTestFunctionContents(true)
).to.eql(undent`
m.currentAssertLineNumber = 6
m._expectCalled(m.thing, "callFunc", [
m._expectCalled(m.thing, "callFunc", m, "m.thing", [
"getFunction"
])
if m.currentResult.isFail then return invalid
m.currentAssertLineNumber = 7
m._expectCalled(m.thing, "callFunc", [
m._expectCalled(m.thing, "callFunc", m, "m.thing", [
"getFunction"
], "return")
if m.currentResult.isFail then return invalid
m.currentAssertLineNumber = 8
m._expectCalled(m.thing, "callFunc", [
m._expectCalled(m.thing, "callFunc", m, "m.thing", [
"getFunction"
"a"
"b"
Expand All @@ -521,7 +521,7 @@ describe('RooibosPlugin', () => {
m.currentAssertLineNumber = 9
m._expectCalled(m.thing, "callFunc", [
m._expectCalled(m.thing, "callFunc", m, "m.thing", [
"getFunction"
"a"
"b"
Expand Down Expand Up @@ -550,12 +550,12 @@ describe('RooibosPlugin', () => {
getTestFunctionContents()
).to.eql(undent`
m.currentAssertLineNumber = 6
m._expectCalled(m.thing, "getFunctionField", invalid)
m._expectCalled(m.thing, "getFunctionField", m, "m.thing", invalid)
if m.currentResult.isFail then return invalid
m.currentAssertLineNumber = 7
m._expectCalled(m.thing, "getFunctionField", invalid, "return")
m._expectCalled(m.thing, "getFunctionField", m, "m.thing", invalid, "return")
if m.currentResult.isFail then return invalid
`);
});
Expand All @@ -582,25 +582,25 @@ describe('RooibosPlugin', () => {
getTestFunctionContents(true)
).to.eql(undent`
m.currentAssertLineNumber = 6
m._expectCalled(m.thing, "getFunction", [])
m._expectCalled(m.thing, "getFunction", m, "m.thing", [])
if m.currentResult.isFail then return invalid
m.currentAssertLineNumber = 7
m._expectCalled(m.thing, "getFunction", [], "return")
m._expectCalled(m.thing, "getFunction", m, "m.thing", [], "return")
if m.currentResult.isFail then return invalid
m.currentAssertLineNumber = 8
m._expectCalled(m.thing, "getFunction", [
m._expectCalled(m.thing, "getFunction", m, "m.thing", [
"arg1"
"arg2"
])
if m.currentResult.isFail then return invalid
m.currentAssertLineNumber = 9
m._expectCalled(m.thing, "getFunction", [
m._expectCalled(m.thing, "getFunction", m, "m.thing", [
"arg1"
"arg2"
], "return")
Expand Down Expand Up @@ -670,25 +670,25 @@ describe('RooibosPlugin', () => {
}
m.currentAssertLineNumber = 7
m._expectCalled(item, "getFunction", [])
m._expectCalled(item, "getFunction", item, "item", [])
if m.currentResult.isFail then return invalid
m.currentAssertLineNumber = 8
m._expectCalled(item, "getFunction", [], "return")
m._expectCalled(item, "getFunction", item, "item", [], "return")
if m.currentResult.isFail then return invalid
m.currentAssertLineNumber = 9
m._expectCalled(item, "getFunction", [
m._expectCalled(item, "getFunction", item, "item", [
"arg1"
"arg2"
])
if m.currentResult.isFail then return invalid
m.currentAssertLineNumber = 10
m._expectCalled(item, "getFunction", [
m._expectCalled(item, "getFunction", item, "item", [
"arg1"
"arg2"
], "return")
Expand Down Expand Up @@ -719,10 +719,10 @@ describe('RooibosPlugin', () => {
expect(
getTestFunctionContents()
).to.eql(undent`
m._stubCall(m.thing, "callFunc")
m._stubCall(m.thing, "callFunc", "return")
m._stubCall(m.thing, "callFunc")
m._stubCall(m.thing, "callFunc", "return")
m._stubCall(m.thing, "callFunc", m, "m.thing")
m._stubCall(m.thing, "callFunc", m, "m.thing", "return")
m._stubCall(m.thing, "callFunc", m, "m.thing")
m._stubCall(m.thing, "callFunc", m, "m.thing", "return")
`);
});

Expand All @@ -745,8 +745,8 @@ describe('RooibosPlugin', () => {
expect(
getTestFunctionContents()
).to.eql(undent`
m._stubCall(m.thing, "getFunctionField")
m._stubCall(m.thing, "getFunctionField", "return")
m._stubCall(m.thing, "getFunctionField", m, "m.thing")
m._stubCall(m.thing, "getFunctionField", m, "m.thing", "return")
`);
});

Expand All @@ -773,8 +773,8 @@ describe('RooibosPlugin', () => {
item = {
id: "item"
}
m._stubCall(item, "getFunctionField")
m._stubCall(item, "getFunctionField", "return")
m._stubCall(item, "getFunctionField", item, "item")
m._stubCall(item, "getFunctionField", item, "item", "return")
`);
});

Expand All @@ -799,10 +799,10 @@ describe('RooibosPlugin', () => {
expect(
getTestFunctionContents()
).to.eql(undent`
m._stubCall(m.thing, "getFunction")
m._stubCall(m.thing, "getFunction", "return")
m._stubCall(m.thing, "getFunction")
m._stubCall(m.thing, "getFunction", "return")
m._stubCall(m.thing, "getFunction", m, "m.thing")
m._stubCall(m.thing, "getFunction", m, "m.thing", "return")
m._stubCall(m.thing, "getFunction", m, "m.thing")
m._stubCall(m.thing, "getFunction", m, "m.thing", "return")
`);
});

Expand Down Expand Up @@ -831,10 +831,10 @@ describe('RooibosPlugin', () => {
item = {
id: "item"
}
m._stubCall(item, "getFunction")
m._stubCall(item, "getFunction", "return")
m._stubCall(item, "getFunction")
m._stubCall(item, "getFunction", "return")
m._stubCall(item, "getFunction", item, "item")
m._stubCall(item, "getFunction", item, "item", "return")
m._stubCall(item, "getFunction", item, "item")
m._stubCall(item, "getFunction", item, "item", "return")
`);
});
});
Expand Down Expand Up @@ -862,22 +862,22 @@ describe('RooibosPlugin', () => {
getTestFunctionContents()
).to.eql(undent`
m.currentAssertLineNumber = 6
m._expectNotCalled(m.thing, "callFunc")
m._expectNotCalled(m.thing, "callFunc", m, "m.thing")
if m.currentResult.isFail then return invalid
m.currentAssertLineNumber = 7
m._expectNotCalled(m.thing, "callFunc", "return")
m._expectNotCalled(m.thing, "callFunc", m, "m.thing", "return")
if m.currentResult.isFail then return invalid
m.currentAssertLineNumber = 8
m._expectNotCalled(m.thing, "callFunc")
m._expectNotCalled(m.thing, "callFunc", m, "m.thing")
if m.currentResult.isFail then return invalid
m.currentAssertLineNumber = 9
m._expectNotCalled(m.thing, "callFunc", "return")
m._expectNotCalled(m.thing, "callFunc", m, "m.thing", "return")
if m.currentResult.isFail then return invalid
`);
});
Expand All @@ -902,12 +902,12 @@ describe('RooibosPlugin', () => {
getTestFunctionContents()
).to.eql(undent`
m.currentAssertLineNumber = 6
m._expectNotCalled(thing, "callFunc")
m._expectNotCalled(thing, "callFunc", thing, "thing")
if m.currentResult.isFail then return invalid
m.currentAssertLineNumber = 7
m._expectNotCalled(thing, "callFunc")
m._expectNotCalled(thing, "callFunc", thing, "thing")
if m.currentResult.isFail then return invalid
`);
//verify original code does not remain modified after the transpile cycle
Expand Down Expand Up @@ -944,7 +944,7 @@ describe('RooibosPlugin', () => {
getTestFunctionContents()
).to.eql(undent`
m.currentAssertLineNumber = 6
m._expectNotCalled(m.thing, "getFunctionField")
m._expectNotCalled(m.thing, "getFunctionField", m, "m.thing")
if m.currentResult.isFail then return invalid
`);
//verify original code does not remain modified after the transpile cycle
Expand Down Expand Up @@ -978,22 +978,22 @@ describe('RooibosPlugin', () => {
getTestFunctionContents()
).to.eql(undent`
m.currentAssertLineNumber = 6
m._expectNotCalled(m.thing, "getFunction")
m._expectNotCalled(m.thing, "getFunction", m, "m.thing")
if m.currentResult.isFail then return invalid
m.currentAssertLineNumber = 7
m._expectNotCalled(m.thing, "getFunction", "return")
m._expectNotCalled(m.thing, "getFunction", m, "m.thing", "return")
if m.currentResult.isFail then return invalid
m.currentAssertLineNumber = 8
m._expectNotCalled(m.thing, "getFunction")
m._expectNotCalled(m.thing, "getFunction", m, "m.thing")
if m.currentResult.isFail then return invalid
m.currentAssertLineNumber = 9
m._expectNotCalled(m.thing, "getFunction", "return")
m._expectNotCalled(m.thing, "getFunction", m, "m.thing", "return")
if m.currentResult.isFail then return invalid
`);
});
Expand Down Expand Up @@ -1023,12 +1023,12 @@ describe('RooibosPlugin', () => {
}
m.currentAssertLineNumber = 7
m._expectNotCalled(item, "getFunction")
m._expectNotCalled(item, "getFunction", item, "item")
if m.currentResult.isFail then return invalid
m.currentAssertLineNumber = 8
m._expectNotCalled(item, "getFunction")
m._expectNotCalled(item, "getFunction", item, "item")
if m.currentResult.isFail then return invalid
`);
});
Expand Down Expand Up @@ -1213,12 +1213,12 @@ describe('RooibosPlugin', () => {
}
m.currentAssertLineNumber = 7
m._expectNotCalled(item, "getFunction")
m._expectNotCalled(item, "getFunction", item, "item")
if m.currentResult.isFail then return invalid
m.currentAssertLineNumber = 8
m._expectNotCalled(item, "getFunction")
m._expectNotCalled(item, "getFunction", item, "item")
if m.currentResult.isFail then return invalid
`);

Expand Down
Loading

0 comments on commit 4f20292

Please sign in to comment.