3

I have an LWC that updloads a file:

<lightning-input type="file" label={label.AttachInvoice} accept="image/png, image/jpg, image/gif, application/pdf" onchange={invoiceUploadHandler}></lightning-input>

Question: How do you set up a JEST test for this onchange handler? Where do you inject a test file?

Adding my handler:

    invoiceUploadHandler(event) {

    let theFile = event.target.files[0];
    let reader = new FileReader();
    let temp = this;

    reader.onload = function() {

        let theContents = this.result.split(/,/)[1]; 

        temp.invoiceUploads = temp.invoiceUploads.slice();
        temp.invoiceUploads.push('Carrier Invoice');

        doUploadFile({ loadId: temp.recordId, filename: 'Carrier Invoice', contentType: theFile.type, contents: theContents })

        .then(result => {             
            LightningUtil.processMessagesAndErrors2(temp, result);   
        })
        .catch(error => {
            LightningUtil.logError(temp, error);
        });    
    }

    reader.readAsDataURL(theFile);
}

Thanks.

2 Answers 2

2

You would need to dispatch a change event with the details of the file within it so your handler can run (and be tested). Unsure how complicated your component is, I'd recommend adding an easy way to grab the input you're looking for by setting a data attribute (data-testid).

<lightning-input 
    type="file" 
    label={label.AttachInvoice} 
    accept="image/png, image/jpg, image/gif, application/pdf" 
    onchange={invoiceUploadHandler} 
    data-testid="file-upload-input">
</lightning-input>

Once you grab the input you're after, you set the details of the event (files) and then dispatch the "change" event on the element

const fileName = "testFile.docx";
const documentId = "01010101001";

const uploadedFile = [{ name: fileName, documentId: documentId }];

const uploadElement = component.shadowRoot.querySelector('[data-testid="file-upload-input"]');

uploadElement.dispatchEvent(
    new CustomEvent("change", {
        detail: { files: uploadedFile },
    })
);

Just a note, FileReader will need to be stubbed as you won't be able to have it run in a jest test. There's some questions around that

Not to mention you'll want to mock return data for your doUploadFile call. Something like below could at confirm the reader method was called.

let readerOnLoadMock = jest.spyOn(FileReader.prototype, 'onload').mockImplementation(() => null);

//dispatch change event for file input

//then, assert the onload method was called
expect(readerOnLoadMock).toHaveBeenCalled();
2
  • Thank you, Kris!
    – Dave C
    Commented Feb 21, 2022 at 17:25
  • Thank you @Kris, Can you please suggest how to stub the FileReader in this example. I get following error - TypeError: 'get onload' called on an object that is not a valid instance of FileReader.
    – kumar
    Commented Jul 19, 2023 at 22:41
0

You just need to follow two steps:

//Mock FileReader
    Object.defineProperty(global, "FileReader", {
      writable: true,
      value: jest.fn().mockImplementation(() => {
        return {
          readAsDataURL: jest.fn(function () {
            // Directly set the result on the FileReader instance
            this.result = "data:image/jpeg;base64,base64string";
            // Trigger the onload method correctly
            this.onload({ target: this });
          }),
          onload: jest.fn()
        };
      })
    });

Second: Calling the change event to upload the file

    const uploadedFile = new File(["dummy,content"], "test.jpeg", {
      type: "image/jpeg"
    });
    const uploadElement = element.shadowRoot.querySelector(
      '[data-id="uploadProfilePhoto"]'
    );
    const changeEvent = new CustomEvent("change", { bubbles: true });
    Object.defineProperty(changeEvent, "target", {
      value: { files: [uploadedFile] },
      enumerable: true
    });
    uploadElement.dispatchEvent(changeEvent);
   

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .