Dynamic test data for test.each Jest - jestjs

Is it possible to assign values at runtime for below Jest test.each example:
describe('jb-tests', () => {
jest.setTimeout(700000);
let table: Array<number[][]> = [[]];
beforeAll(() => {
//Below lines are just hardcoded values
table = [];
let test = [[1,2,3],[4,5,6],[7,8,9]]
table.push(test);
});
test.each(table)('.add(%i, %i)', (a, b, expected) => {
console.log("inside");
});
});
This test case is stuck and not showing any output. If I remove the jest.setTimeout then it fails with message "Exceeded timeout of 5000 ms for a test."

Building on the comment from #jonrsharpe, you can however specify values in the test.each() call.
describe('jb-tests', () => {
jest.setTimeout(700000);
test.each([
[1,2,3],
[4,5,6],
[7,8,9],
])('.add(%i, %i)', (a, b, expected) => {
expect(a + b).toBe(Expected);
});
});
However, if you really need data from an external source, and want to process it, you can load it in the test code, or a beforeAll(). Note that the beforeAll() is evaluated at the very start, so what is loaded there is done at the start of processing the file, not as each test is run.
import * as NodeJSFS from 'fs/promises';
describe('jb-tests', () => {
jest.setTimeout(700000);
let table: Array<number[][]> = [[]];
beforeAll(async () => {
const FileContent$: Buffer = await NodeJSFSPromises.readFile('testdata.txt');
// Loop through FileContent$ (map, etc.) and load your table (table.push)
...
});
describe('adding addition describe for this section', () => {
for (const data of table) {
... // Parse data (one element of table)
it(`should add ${a} + ${b} to be ${Expected}', () => {
expect(a + b).toBe(Expected);
});
}
});

Just found an alternate solution: Populate the test data dynamically and then use describe block to execute test cases using test.each.
let test_data: Array<number[]> = [];
for(let i=0;i<3;i++){
test_data.push([i+0,i+1,i+2]);
}
describe('jb-tests', () => {
test.each(test_data)('.add(%i, %i, %i)', (a, b, c) => {
expect(a + b + c).toBeGreaterThan(0);
});
});

Related

Ramda.when always return true using fs

I am trying to use Ramda.when to execute only if a condition is true but it's always returning true:
const bla2 = path => () => R.when(fs.existsSync(path()), console.log(path()))
Is there anyway to use Ramda.when with fs.existsSync?
edit:
Even set false this is not working:
const bla3 => () => R.when(false, console.log('bla'))
This is the real code:
const moveEnvironmentVarsFile = (oldPath, newPath) => () => R.when(fs.existsSync(oldPath()), fs.renameSync(oldPath(), newPath()))
I don't think R.when is appropriate for what you're trying to do. R.when's purpose is to transform a value, but only if that value matches a condition. It expects you to pass in three things:
A function which checks the condition
A function which does the transformation
A value that you want to send through this process
fs.existsSync can conceivably be used as argument 1, such as the following contrived example which appends "exists" to a string if the file exists:
const result = R.when(
fs.existsSync,
(val) => val + "exists",
"some/file"
);
// result is either some/file or some/fileexists
In real word, I am trying to rename a file using fs. How can I do it using ramda or any functional way in JS?
Honestly, i would just use an if/else and not use Ramda:
const myFunc = (filename) => {
if (fs.existsSync(filename) {
// do something
} else {
// do something else
}
}
If you really want to use ramda to create that code for you, you could use R.ifElse:
const myFunc = R.ifElse(
fs.existsSync,
(filename) => { /* do something */ },
(filename) => { /* do someething else */ }
);

If I am unit testing what happens inside an if-clause, should I mock everything up to the if-clause?

The scenario
I am writing unit tests for a module similar to the one below
service.js
const client = require("./../client");
let managedData = {};
function manageData(dataId) {
let users = client.retrieveUsers(); //Will return an array of strings. For example: a list of user names
let user = client.retrieveCurrentUser(); //Will return a string. For example: one user name
let userIsPresentInList = users.includes(user); //Check if the user is present in a broader user list
if(userIsPresentInList) {
managedData[dataId] = client.retrieveDataWithId(dataId);
}
}
function unmanageData(dataId) {
client.doSomethingToTheDataWithId(dataId)
delete managedData[dataId]
}
module.exports = {
manageData,
unmanageData
}
Some of my unit tests target what happens when the user is present in the list of users, i.e., what happens inside the if-clause
The questions is: if I am unit testing an if-clause, should I mock everything up to the clause (option 1 below)? Or should I create an way of "directly" ending up in the if-clause (option 2 below)?
The test
Option 1) Group the tests via describe blocks and mock in beforeEach/beforeAll:: Scenarios that concern what's inside the if-clause are grouped in a describe block and mocks are done for all statements up until the if-clause
Option 2) Mock intermediate functions inside module: service.js is refactored. The code that checks whether the user is in the list of users is extracted in a new function inside the module. This function then is mocked. In this way anything before the if-clause does not really matter and the test only concerns what is inside the if-clause is working
service.test.js
const service = require("./service");
const client = require("./../client");
jest.mock("./../client");
beforeEach(() => {
jest.clearAllMocks();
});
describe('Sucesful management', () => {
//OPTION 1
beforeEach(() => {
client.retrieveUsers = jest.fn(() => ["a", "b", "c"]);
client.retrieveCurrentUser = jest.fn(() => "a");
})
//OPTION 2
beforeEach(() => {
service.isUserPresentInUsersList = jest.fn(() => true);
})
afterEach(() => {
service.isUserPresentInUsersList.mockRestore();
})
it("Given the user belongs to the user list, should retrieve the data calleing manageData", async () => {
//Act
service.manageData("D");
//Assert
expect(client.retrieveDataWithId).toHaveBeenCalledWith("D");
});
it("Given the user belongs to the user list, should do something with the data when calling unmanageData", async () => {
//Act
service.manageData("D");
service.unmanageData("D");
//Assert
expect(client.doSomethingToTheDataWithId).toHaveBeenCalledWith("D");
});
})
Is there preferable one in this case? Is any of those approaches terrible?
An extended question would be: what are open source projects that have good testing practices that I can get inspiration from?

node js normal callback scenario for blocking code

I am getting into callbacks(do not want to use promise and async-await right now) and wrote code in node.js to sum a, b and c where I have created three functions for getting values of a, b and c.
// getting value of a
const getA = () => 10
// getting for value b
const getB = () => 20
// This function has to wait for 2 seconds to
const getC = (callback) => {
setTimeout(() => {
callback(30)
}, 2000);
}
const sum = (a, b, c, callback) => {
callback(a + b + c)
}
sum(getA(), getB(), getC((c) => c), (sum) => console.log(sum))
I want output 60 after waiting for getC() to finish execution, but didn't get any
I really suggest to use promises. I know there are some corner cases, where you can't. Why? Because we used to think in a way that the code is linear, and it is easier to the brain to process.
But for your question I would give a solution.
// getting value of a
const getA = () => 10;
// getting for value b
const getB = () => 20;
// This function has to wait for 2 seconds to
const getC = (callback) => {
setTimeout(() => {
callback(30);
}, 2000);
};
getC((val) => console.log(getA() + getB() + val));
So you wait until getC has finished, and use the callback to consume the c result.

How to delay event emission with rxpy/rxjs?

I've got two event streams. One is from an inductance loop, the other is an IP camera. Cars will drive over the loop and then hit the camera. I want to combine them if the events are within N milliseconds of each other (car will always hit the loop first), but I also want the unmatched events from each stream (either hardware can fail) all merged into a single stream. Something like this:
---> (only unmatched a's, None)
/ \
stream_a (loop) \
\ \
--> (a, b) ---------------------------> (Maybe a, Maybe b)
/ /
stream_b (camera) /
\ /
--> (None, only unmatched b's)
Now certainly I can hack my way around by doing the good ole Subject anti-pattern:
unmatched_a = Subject()
def noop():
pass
pending_as = [[]]
def handle_unmatched(a):
if a in pending_as[0]:
pending_as[0].remove(a)
print("unmatched a!")
unmatched_a.on_next((a, None))
def handle_a(a):
pending_as[0].append(a)
t = threading.Timer(some_timeout, handle_unmatched)
t.start()
return a
def handle_b(b):
if len(pending_as[0]):
a = pending_as[0].pop(0)
return (a, b)
else:
print("unmatched b!")
return (None, b)
stream_a.map(handle_a).subscribe(noop)
stream_b.map(handle_b).merge(unmatched_a).subscribe(print)
Not only is this rather hacky, but although I've not observed it I'm pretty sure there's a race condition when I check the pending queue using threading.Timer. Given the plethora of rx operators, I'm pretty sure some combination of them will let you do this without using Subject, but I can't figure it out. How does one accomplish this?
Edit
Although for organizational and operational reasons I'd prefer to stick to Python, I'll take a JavaScript rxjs answer and either port it or even possibly rewrite the entire script in node.
You should be able to solve the problem using auditTime and buffer. Like this:
function matchWithinTime(a$, b$, N) {
const merged$ = Rx.Observable.merge(a$, b$);
// Use auditTime to compose a closing notifier for the buffer.
const audited$ = merged$.auditTime(N);
// Buffer emissions within an audit and filter out empty buffers.
return merged$
.buffer(audited$)
.filter(x => x.length > 0);
}
const a$ = new Rx.Subject();
const b$ = new Rx.Subject();
matchWithinTime(a$, b$, 50).subscribe(x => console.log(JSON.stringify(x)));
setTimeout(() => a$.next("a"), 0);
setTimeout(() => b$.next("b"), 0);
setTimeout(() => a$.next("a"), 100);
setTimeout(() => b$.next("b"), 125);
setTimeout(() => a$.next("a"), 200);
setTimeout(() => b$.next("b"), 275);
setTimeout(() => a$.next("a"), 400);
setTimeout(() => b$.next("b"), 425);
setTimeout(() => a$.next("a"), 500);
setTimeout(() => b$.next("b"), 575);
setTimeout(() => b$.next("b"), 700);
setTimeout(() => b$.next("a"), 800);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://unpkg.com/rxjs#5/bundles/Rx.min.js"></script>
If it's possible for b values to be closely followed by a values and you do not want them to be matched, you could use a more specific audit, like this:
const audited$ = merged$.audit(x => x === "a" ?
// If an `a` was received, audit upcoming values for `N` milliseconds.
Rx.Observable.timer(N) :
// If a `b` was received, don't audit the upcoming values.
Rx.Observable.of(0, Rx.Scheduler.asap)
);
I have developed a different strategy than Cartant, and clearly much less elegant, which may give you somehow a different result. I apologize if I have not understood the question and if my answer turns out to be useless.
My strategy is based on using switchMap on a$ and then bufferTime on b$.
This code emits at every timeInterval and it emits an object which contains the last a received and an array of bs representing the bs received during the time interval.
a$.pipe(
switchMap(a => {
return b$.pipe(
bufferTime(timeInterval),
mergeMap(arrayOfB => of({a, arrayOfB})),
)
})
)
If arrayOfB is empty, than it means that the last a in unmatched.
If arrayOfB has just one element, than it means that the last a has been matched by the b of the array.
If arrayOfB has more than one element, than it means that the last a has been matched by the first b of the array while all other bs are unmatched.
Now it is a matter of avoiding the emission of the same a more than
once and this is where the code gets a bit messy.
In summary, the code could look like the following
const a$ = new Subject();
const b$ = new Subject();
setTimeout(() => a$.next("a1"), 0);
setTimeout(() => b$.next("b1"), 0);
setTimeout(() => a$.next("a2"), 100);
setTimeout(() => b$.next("b2"), 125);
setTimeout(() => a$.next("a3"), 200);
setTimeout(() => b$.next("b3"), 275);
setTimeout(() => a$.next("a4"), 400);
setTimeout(() => b$.next("b4"), 425);
setTimeout(() => b$.next("b4.1"), 435);
setTimeout(() => a$.next("a5"), 500);
setTimeout(() => b$.next("b5"), 575);
setTimeout(() => b$.next("b6"), 700);
setTimeout(() => b$.next("b6.1"), 701);
setTimeout(() => b$.next("b6.2"), 702);
setTimeout(() => a$.next("a6"), 800);
setTimeout(() => a$.complete(), 1000);
setTimeout(() => b$.complete(), 1000);
let currentA;
a$.pipe(
switchMap(a => {
currentA = a;
return b$.pipe(
bufferTime(50),
mergeMap(arrayOfB => {
let aVal = currentA ? currentA : null;
if (arrayOfB.length === 0) {
const ret = of({a: aVal, b: null})
currentA = null;
return ret;
}
if (arrayOfB.length === 1) {
const ret = of({a: aVal, b: arrayOfB[0]})
currentA = null;
return ret;
}
const ret = from(arrayOfB)
.pipe(
map((b, _indexB) => {
aVal = _indexB > 0 ? null : aVal;
return {a: aVal, b}
})
)
currentA = null;
return ret;
}),
filter(data => data.a !== null || data.b !== null)
)
})
)
.subscribe(console.log);

How to mock curry function with Jest?

add.js
export default a => b => a+b;
module.js
import add from './add';
export default {
add1: n => add(1)(n),
};
test/module.js
import add from '../add';
import module from '../module';
jest.mock('../add', () => () => jest.fn());
module.add1(6);
expect(add.mock.calls).toHaveLength(1);
this can be called, but add wouldn't be a mock function, instead add() is a mock function, but the call params were not recorded correctly.
jest.mock('../add', () => () => jest.fn(a => b => a+b));
has also tried this, which doesn't seem to work correctly as well.
jest.mock('../add', jest.fn(a => b => a+b));
this would throw the inline function error
Is there a correct way to mock curry function at the moment?
Simple version should look like this
jest.mock('../add', () => (a) => jest.fn(b => a+b));
So you mock add module with a function that return that when gets called it returns the spy, problem you can't test anything on the spy.
So we need to refactor it so you have the add1 think as a spy in scope of the test
import add from '../add'
jest.mock('../add', () => jest.fn)
const addC = jest.fn()
add.mockImplemetation((a) => {
addC.mockImplementation((b => a+b)
return addC
})
I know this is a bit old but with the following answer I would have saved so much time...
import module from "./module";
const mockOperation = {
add: jest.fn()
};
jest.mock("./add", () => () => {
return mockOperation.add;
});
describe("add ", () => {
it("is called at least once", () => {
module.add1(6);
expect(mockOperation.add.mock.calls).toHaveLength(1);
});
});
A very importante thing: the constant function that you want to mock must start with the word mock. Otherwise it will throw an error.
const mockOperation = {
add: jest.fn()
};
With the mockOperation constant assigned to the add file, by reference is calling to it's add method which is a jest.fn()
I've had to do this a lot recently so I wrote a helper function to help me out.
curryMock = (baseFn, maxCurries) => {
var callIndex = 0
var curries = []
let returnFn
baseFn.mockImplementation((arg) => {
curries[callIndex] = 0
const fn = returnFn(callIndex)
callIndex++
return fn
})
returnFn = (index: number) => {
if (curries[index] < maxCurries) {
curries[index]++
return (arg: any) => {
baseFn.mock.calls[index].push(arg)
return returnFn(index)
}
}
}
}
You pass the function a jest.fn() and curryMock modifies it's implementation so that all the arguments return functions are called with will be added to the original jest.fn().mock.calls array. The second argument specifies how many times to return a function. maxCurries = 0 is for a regular function () => {},
maxCurries = 1is for a regular function() => => {}`, etc.
In your case:
import add from '../add';
import module from '../module';
jest.mock('../add');
curryMock(add)
module.add1(6);
expect(add).toHaveBeenCalledWith(1, 6);
//equivalent to
//expect(add).toHaveBeenNthCalledWith(1, 1, 6);
//if you others to test..
module.add7(4)
expect(add).toHaveBeenNthCalledWith(2, 7, 4)
curryMock is a quick utility function that I wrote for personal use. I will likely clean it up and extend it later, but I hope you get the idea: testing curried functions does not have to laborious.

Resources