javascriptjestjsstenciljs

Stencil.js Jest: mock FileReader 'not defined' unless use window.FileReader


I have a util.ts module with a utility class that reads files after an input has uploaded them:

// utils/utils.ts

export class JsonFileProcessor {

   process(files) {
     // ReferenceError: FileReader is not defined
     const reader = new FileReader();
   }
}

In my utils.spec.ts I mock the window.FileReader (which is undefined up to this point)

import { JsonFileProcessor } from "./utils";

describe("JsonFileProcessor", () => {

 it("processes the files", () => {
   // createMockFileReader returns a `class MockFileReader`
   // that replicates the methods of FileReader
   window.FileReader = createMockFileReader(files)
   const processor = new JsonFileProcessor();
   processor.process(someFiles);

I get an error in the JsonFileProcessor.process method ReferenceError: FileReader is not defined, but if I replace new FileReader() with new window.FileReader() it works

I've been stuck on this for ages now! I'm using Stencil.js and running the Jest setup that it comes with. There are other window properties that are available (as I've debugged it and console.log'd it)

I know I have to mock FileReader myself, but I'm stumped as to why the util class isn't finding the mocked class unless I specifically use new window.FileReader()


Solution

  • It turns out that Stencil's jest setup does not include jsdom. Stencil uses a slimmed down version of Puppeteer for unit tests - the window and document properties of which can be accessed via the page object returned from Stencil's newSpecPage()

    As my tests are running without newSpecPage I needed to use the global object instead e.g. global.FileReader = createMockFileReader(files)