0

Math.random() always giving random values instead of mocked ones.

index.test.js

jest.spyOn(global.Math, "random").mockReturnValue(0.123456789);

const html = fs.readFileSync(path.resolve(__dirname, "./index.html"), "utf8");

let dom;
let container;

describe("index.html", () => {
  beforeEach(() => {
    dom = new JSDOM(html, { runScripts: "dangerously" });
    container = dom.window.document.body;
  });

  it("renders body paragraph", () => {
    expect(container.querySelector("p")).toBeInTheDocument();
  });
});

index.html

<html lang="en">
  <body>
    <p>title</p>
    <script>
      // not showing mocked value
      console.log(Math.random())
    </script>
  </body>
</html>

Is it possible a new instance is created when loading hence mock isn't picked? Interesting enough mocking setInterval works.

Also tried .mockImplementation(() => 0.123456789) to no avail.

enter image description here

EugenSunic
  • 13,162
  • 13
  • 64
  • 86
  • This happens because of Math.random() is always a random nr every time you run the test. Look at this https://stackoverflow.com/questions/41570273/how-to-test-a-function-that-output-is-random-using-jest – Cyrus Zei Apr 03 '22 at 18:02
  • @CyrusZei what did you just say? I used this and even setup a jest.setup.js file wich runs first, considered beforeAll but still, to no avail. It should not be random after it is caught. – EugenSunic Apr 03 '22 at 18:04
  • oh, my bad, I did not see your first line of code where you do address this. – Cyrus Zei Apr 04 '22 at 10:15

1 Answers1

2

It doesn't look like the mock carries over to JSDOM. To get around this issue, I would personally recommend splitting the script into its own file and then running your test against the script file like the below example. Once you've split them out, just include the script file in your HTML file.

script.js

Math.random();

script.spec.js

describe("script.js", () => {
    let spyOnMathRandom;

    beforeEach(() => {
        spyOnMathRandom = jest.spyOn(global.Math, 'random').mockReturnValue(1);
        require('./script');
    });

    it("calls math random", () => {
        expect(spyOnMathRandom).toReturnWith(1);
    });
});

index.html

<html lang="en">
<body>
<p>title</p>
<script src="script.js"></script>
</body>
</html>
Win
  • 5,498
  • 2
  • 15
  • 20
  • Yep that worked. Just needed to add the js file which is gonna get consumed in the appropriate field. ```setupFilesAfterEnv: ["./jest.setup.js", ".script.js"]``` – EugenSunic Apr 04 '22 at 11:55