Skip to content

Commit e4a8846

Browse files
feat: add RandomMocker class to mock Math.random
1 parent 05a85d7 commit e4a8846

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

lib/__tests__/curriculum-helper.test.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,51 @@ const {
2222
jsCodeWithCommentedCall,
2323
} = jsTestValues;
2424

25+
describe("RandomMocker", () => {
26+
let random: () => number;
27+
28+
beforeEach(() => {
29+
random = Math.random;
30+
});
31+
32+
afterEach(() => {
33+
Math.random = random;
34+
});
35+
36+
describe("mock", () => {
37+
it('should replace "Math.random" with a mock function', () => {
38+
const mocker = new helper.RandomMocker();
39+
mocker.mock();
40+
expect(Math.random).not.toBe(random);
41+
});
42+
43+
it('should mock "Math.random" with a pseudorandom function', () => {
44+
const mocker = new helper.RandomMocker();
45+
mocker.mock();
46+
// Predictable random values:
47+
expect(Math.random()).toBe(0.2523451747838408);
48+
expect(Math.random()).toBe(0.08812504541128874);
49+
});
50+
51+
it("should reset the pseudorandom function when called multiple times", () => {
52+
const mocker = new helper.RandomMocker();
53+
mocker.mock();
54+
expect(Math.random()).toBe(0.2523451747838408);
55+
mocker.mock();
56+
expect(Math.random()).toBe(0.2523451747838408);
57+
});
58+
});
59+
60+
describe("restore", () => {
61+
it('should restore "Math.random" to its original function', () => {
62+
const mocker = new helper.RandomMocker();
63+
mocker.mock();
64+
mocker.restore();
65+
expect(Math.random).toBe(random);
66+
});
67+
});
68+
});
69+
2570
describe("removeWhiteSpace", () => {
2671
const { removeWhiteSpace } = helper;
2772
it("returns a string", () => {

lib/index.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,37 @@
11
import { strip } from "./strip";
22
import astHelpers from "../python/py_helpers.py";
33

4+
/**
5+
* The `RandomMocker` class provides functionality to mock and restore the global `Math.random` function.
6+
* It replaces the default random number generator with a deterministic pseudo-random number generator.
7+
*/
8+
export class RandomMocker {
9+
private random: () => number;
10+
11+
constructor() {
12+
this.random = Math.random;
13+
}
14+
15+
private createRandom() {
16+
let seed = 42;
17+
const a = 1664525;
18+
const c = 1013904223;
19+
const mod = 2 ** 32;
20+
return () => {
21+
seed = (a * seed + c) % mod;
22+
return seed / mod;
23+
};
24+
}
25+
26+
mock(): void {
27+
globalThis.Math.random = this.createRandom();
28+
}
29+
30+
restore(): void {
31+
globalThis.Math.random = this.random;
32+
}
33+
}
34+
435
/**
536
* Removes every HTML-comment from the string that is provided
637
* @param {String} str a HTML-string where the comments need to be removed of

0 commit comments

Comments
 (0)