-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP: adds support for expecting on global functions and namespace functions #241
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
63e75d8
adds support for expecting on global functions and namespace functions
georgejecook cfdaf2f
fixes
georgejecook 316e84c
wip
georgejecook 05c379d
fixes error in utils
georgejecook 8a7469a
adds docs
georgejecook 276a73f
reinstates erroneously disabled try catch
georgejecook File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,387 @@ | ||
/* eslint-disable @typescript-eslint/no-confusing-void-expression */ | ||
import { Program, ProgramBuilder, util, standardizePath as s } from 'brighterscript'; | ||
import { expect } from 'chai'; | ||
import PluginInterface from 'brighterscript/dist/PluginInterface'; | ||
import * as fsExtra from 'fs-extra'; | ||
import { RooibosPlugin } from '../../plugin'; | ||
|
||
let tmpPath = s`${process.cwd()}/tmp`; | ||
let _rootDir = s`${tmpPath}/rootDir`; | ||
let _stagingFolderPath = s`${tmpPath}/staging`; | ||
|
||
function trimLeading(text: string) { | ||
return text.split('\n').map((line) => line.trimStart()).join('\n'); | ||
} | ||
|
||
describe('MockUtil', () => { | ||
let program: Program; | ||
let builder: ProgramBuilder; | ||
let plugin: RooibosPlugin; | ||
let options; | ||
|
||
function getContents(filename: string) { | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument | ||
return trimLeading(fsExtra.readFileSync(s`${_stagingFolderPath}/${filename}`).toString()); | ||
} | ||
|
||
describe('MockUtil', () => { | ||
beforeEach(() => { | ||
plugin = new RooibosPlugin(); | ||
options = { | ||
rootDir: _rootDir, | ||
stagingFolderPath: _stagingFolderPath, | ||
rooibos: { | ||
isGlobalMethodMockingEnabled: true, | ||
globalMethodMockingExcludedFiles: [ | ||
'**/*.coverageExcluded.bs' | ||
], | ||
isGlobalMethodMockingEfficientMode: false | ||
}, | ||
allowBrighterScriptInBrightScript: true | ||
}; | ||
fsExtra.ensureDirSync(_stagingFolderPath); | ||
fsExtra.ensureDirSync(_rootDir); | ||
fsExtra.ensureDirSync(tmpPath); | ||
|
||
builder = new ProgramBuilder(); | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument | ||
builder.options = util.normalizeAndResolveConfig(options); | ||
builder.program = new Program(builder.options); | ||
program = builder.program; | ||
program.logger = builder.logger; | ||
builder.plugins = new PluginInterface([plugin], { logger: builder.logger }); | ||
program.plugins = new PluginInterface([plugin], { logger: builder.logger }); | ||
program.createSourceScope(); //ensure source scope is created | ||
plugin.beforeProgramCreate(builder); | ||
|
||
}); | ||
afterEach(() => { | ||
plugin.afterProgramCreate(program); | ||
fsExtra.ensureDirSync(tmpPath); | ||
fsExtra.emptyDirSync(tmpPath); | ||
builder.dispose(); | ||
program.dispose(); | ||
}); | ||
|
||
describe('basic brs tests', () => { | ||
|
||
// This test fails unless `allowBrighterScriptInBrightScript` is set to true when setting up the program | ||
// in `beforeEach`. This is because the compiler normally skips processing .brs files and copies them as-is. | ||
it('adds util code to a brs file', async () => { | ||
program.setFile('source/code.brs', ` | ||
function sayHello(a1, a2) | ||
print "hello" | ||
end function | ||
`); | ||
program.validate(); | ||
expect(program.getDiagnostics()).to.be.empty; | ||
await builder.transpile(); | ||
let a = getContents('source/code.brs'); | ||
let b = trimLeading(`function sayHello(a1, a2) | ||
if RBS_SM_1_getMocksByFunctionName()["sayhello"] <> invalid | ||
result = RBS_SM_1_getMocksByFunctionName()["sayhello"].callback(a1,a2) | ||
return result | ||
end if | ||
print "hello" | ||
end function | ||
|
||
function RBS_SM_1_getMocksByFunctionName() | ||
if m._rMocksByFunctionName = invalid | ||
m._rMocksByFunctionName = {} | ||
end if | ||
return m._rMocksByFunctionName | ||
end function | ||
`); | ||
expect(a).to.equal(b); | ||
|
||
}); | ||
}); | ||
describe('basic bs tests', () => { | ||
|
||
it('enables mocking on global functions', async () => { | ||
program.setFile('source/code.bs', ` | ||
function sayHello(a1, a2) | ||
print "hello" | ||
end function | ||
`); | ||
program.validate(); | ||
expect(program.getDiagnostics()).to.be.empty; | ||
await builder.transpile(); | ||
let a = getContents('source/code.brs'); | ||
let b = trimLeading(`function sayHello(a1, a2) | ||
if RBS_SM_1_getMocksByFunctionName()["sayhello"] <> invalid | ||
result = RBS_SM_1_getMocksByFunctionName()["sayhello"].callback(a1,a2) | ||
return result | ||
end if | ||
print "hello" | ||
end function | ||
|
||
function RBS_SM_1_getMocksByFunctionName() | ||
if m._rMocksByFunctionName = invalid | ||
m._rMocksByFunctionName = {} | ||
end if | ||
return m._rMocksByFunctionName | ||
end function | ||
`); | ||
expect(a).to.equal(b); | ||
|
||
}); | ||
it('weird raletracker task issue I saw', async () => { | ||
program.setFile('source/code.bs', ` | ||
Sub RedLines_SetRulerLines(rulerLines) | ||
For Each line In rulerLines.Items() | ||
RedLines_AddLine(line.key, line.value.position, line.value.coords, m.node, m.childMap) | ||
End For | ||
end Sub | ||
Sub RedLines_AddLine(id, position, coords, node, childMap) as Object | ||
line = CreateObject("roSGNode", "Rectangle") | ||
line.setField("id", id) | ||
end sub | ||
`); | ||
program.validate(); | ||
expect(program.getDiagnostics()).to.be.empty; | ||
await builder.transpile(); | ||
let a = getContents('source/code.brs'); | ||
let b = trimLeading(`Sub RedLines_SetRulerLines(rulerLines) | ||
if RBS_SM_1_getMocksByFunctionName()["redlines_setrulerlines"] <> invalid | ||
result = RBS_SM_1_getMocksByFunctionName()["redlines_setrulerlines"].callback(rulerLines) | ||
return | ||
end if | ||
For Each line In rulerLines.Items() | ||
RedLines_AddLine(line.key, line.value.position, line.value.coords, m.node, m.childMap) | ||
End For | ||
end Sub | ||
|
||
Sub RedLines_AddLine(id, position, coords, node, childMap) as Object | ||
if RBS_SM_1_getMocksByFunctionName()["redlines_addline"] <> invalid | ||
result = RBS_SM_1_getMocksByFunctionName()["redlines_addline"].callback(id,position,coords,node,childMap) | ||
return result | ||
end if | ||
line = CreateObject("roSGNode", "Rectangle") | ||
line.setField("id", id) | ||
end sub | ||
|
||
function RBS_SM_1_getMocksByFunctionName() | ||
if m._rMocksByFunctionName = invalid | ||
m._rMocksByFunctionName = {} | ||
end if | ||
return m._rMocksByFunctionName | ||
end function | ||
`); | ||
expect(a).to.equal(b); | ||
|
||
}); | ||
|
||
it('enables mocking on global sub', async () => { | ||
program.setFile('source/code.bs', ` | ||
sub sayHello(a1, a2) | ||
print "hello" | ||
end sub | ||
`); | ||
program.validate(); | ||
expect(program.getDiagnostics()).to.be.empty; | ||
await builder.transpile(); | ||
let a = getContents('source/code.brs'); | ||
let b = trimLeading(`sub sayHello(a1, a2) | ||
if RBS_SM_1_getMocksByFunctionName()["sayhello"] <> invalid | ||
result = RBS_SM_1_getMocksByFunctionName()["sayhello"].callback(a1,a2) | ||
return | ||
end if | ||
print "hello" | ||
end sub | ||
|
||
function RBS_SM_1_getMocksByFunctionName() | ||
if m._rMocksByFunctionName = invalid | ||
m._rMocksByFunctionName = {} | ||
end if | ||
return m._rMocksByFunctionName | ||
end function | ||
`); | ||
expect(a).to.equal(b); | ||
|
||
}); | ||
|
||
it('enables mocking on namespaced function', async () => { | ||
program.setFile('source/code.bs', ` | ||
namespace person.utils | ||
function sayHello(a1, a2) | ||
print "hello" | ||
end function | ||
end namespace | ||
`); | ||
program.validate(); | ||
expect(program.getDiagnostics()).to.be.empty; | ||
await builder.transpile(); | ||
let a = getContents('source/code.brs'); | ||
let b = trimLeading(`function person_utils_sayHello(a1, a2) | ||
if RBS_SM_1_getMocksByFunctionName()["person_utils_sayhello"] <> invalid | ||
result = RBS_SM_1_getMocksByFunctionName()["person_utils_sayhello"].callback(a1,a2) | ||
return result | ||
end if | ||
print "hello" | ||
end function | ||
|
||
function RBS_SM_1_getMocksByFunctionName() | ||
if m._rMocksByFunctionName = invalid | ||
m._rMocksByFunctionName = {} | ||
end if | ||
return m._rMocksByFunctionName | ||
end function | ||
`); | ||
expect(a).to.equal(b); | ||
|
||
}); | ||
|
||
it('enables mocking on namespaced sub', async () => { | ||
program.setFile('source/code.bs', ` | ||
namespace person.utils | ||
sub sayHello(a1, a2) | ||
print "hello" | ||
end sub | ||
end namespace | ||
`); | ||
program.validate(); | ||
expect(program.getDiagnostics()).to.be.empty; | ||
await builder.transpile(); | ||
let a = getContents('source/code.brs'); | ||
let b = trimLeading(`sub person_utils_sayHello(a1, a2) | ||
if RBS_SM_1_getMocksByFunctionName()["person_utils_sayhello"] <> invalid | ||
result = RBS_SM_1_getMocksByFunctionName()["person_utils_sayhello"].callback(a1,a2) | ||
return | ||
end if | ||
print "hello" | ||
end sub | ||
|
||
function RBS_SM_1_getMocksByFunctionName() | ||
if m._rMocksByFunctionName = invalid | ||
m._rMocksByFunctionName = {} | ||
end if | ||
return m._rMocksByFunctionName | ||
end function | ||
`); | ||
expect(a).to.equal(b); | ||
|
||
}); | ||
|
||
it('does not affect class methods', async () => { | ||
program.setFile('source/code.bs', ` | ||
class Person | ||
sub sayHello(a1, a2) | ||
print "hello" | ||
end sub | ||
end class | ||
`); | ||
program.validate(); | ||
expect(program.getDiagnostics()).to.be.empty; | ||
await builder.transpile(); | ||
let a = getContents('source/code.brs'); | ||
let b = trimLeading(`function __Person_builder() | ||
instance = {} | ||
instance.new = sub() | ||
end sub | ||
instance.sayHello = sub(a1, a2) | ||
print "hello" | ||
end sub | ||
return instance | ||
end function | ||
function Person() | ||
instance = __Person_builder() | ||
instance.new() | ||
return instance | ||
end function`); | ||
expect(a).to.equal(b); | ||
|
||
}); | ||
it('will add stub code to namespace and global methods in a file with a class', async () => { | ||
program.setFile('source/code.bs', ` | ||
namespace beings | ||
class Person | ||
sub sayHello(a1, a2) | ||
print "hello" | ||
end sub | ||
end class | ||
function sayHello() | ||
print "hello2" | ||
end function | ||
end namespace | ||
function sayHello() | ||
print "hello3" | ||
end function | ||
`); | ||
program.validate(); | ||
expect(program.getDiagnostics()).to.be.empty; | ||
await builder.transpile(); | ||
let a = getContents('source/code.brs'); | ||
let b = trimLeading(`function __beings_Person_builder() | ||
instance = {} | ||
instance.new = sub() | ||
end sub | ||
instance.sayHello = sub(a1, a2) | ||
print "hello" | ||
end sub | ||
return instance | ||
end function | ||
function beings_Person() | ||
instance = __beings_Person_builder() | ||
instance.new() | ||
return instance | ||
end function | ||
|
||
function beings_sayHello() | ||
if RBS_SM_1_getMocksByFunctionName()["beings_sayhello"] <> invalid | ||
result = RBS_SM_1_getMocksByFunctionName()["beings_sayhello"].callback() | ||
return result | ||
end if | ||
print "hello2" | ||
end function | ||
|
||
function sayHello() | ||
if RBS_SM_1_getMocksByFunctionName()["sayhello"] <> invalid | ||
result = RBS_SM_1_getMocksByFunctionName()["sayhello"].callback() | ||
return result | ||
end if | ||
print "hello3" | ||
end function | ||
|
||
function RBS_SM_1_getMocksByFunctionName() | ||
if m._rMocksByFunctionName = invalid | ||
m._rMocksByFunctionName = {} | ||
end if | ||
return m._rMocksByFunctionName | ||
end function | ||
`); | ||
expect(a).to.equal(b); | ||
|
||
}); | ||
|
||
}); | ||
|
||
it('excludes files from coverage', async () => { | ||
const source = `sub foo() | ||
x = function(y) | ||
if (true) then | ||
return 1 | ||
end if | ||
return 0 | ||
end function | ||
end sub`; | ||
|
||
program.setFile('source/code.coverageExcluded.bs', source); | ||
program.validate(); | ||
expect(program.getDiagnostics()).to.be.empty; | ||
await builder.transpile(); | ||
|
||
let a = getContents('source/code.coverageExcluded.brs'); | ||
let b = `sub foo() | ||
x = function(y) | ||
if (true) then | ||
return 1 | ||
end if | ||
return 0 | ||
end function | ||
end sub`; | ||
|
||
expect(a).to.equal(b); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you hate proper indentation? :P
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lol. I honestly find if I do anything else, it won't pass the test. Always been too busy to sort it out.