0

I've got a function, which I need to be tested because of code coverage.

const downloadPdfDataContent = (title: string, url: string): void => {
  const link = document.createElement('a');
  link.target = title;
  link.href = url;
  link.download = title;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
  URL.revokeObjectURL(url);
};

How can I accomplish to test the assigments to the variable and the document object? I think I will need to use spyOn .. but I do not know exactly how, as the variable only lives in the function scope. I thought about simply returning the variable, but if it's possible id like to prevent that.

3
  • Where does fileURL come from? And why you try to appendChild a url string? Commented May 21, 2021 at 10:19
  • 1
    Should it be removeChild(link)? Commented May 21, 2021 at 11:58
  • Yes! edited second time ... im sorry, kind of tired :) Commented May 21, 2021 at 12:03

2 Answers 2

1

You can use jest.spyOn() to mock every DOM manipulation.

E.g.

index.ts:

export const downloadPdfDataContent = (title: string, url: string): void => {
  const link = document.createElement('a');
  link.target = title;
  link.href = url;
  link.download = title;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
  URL.revokeObjectURL(url);
};

index.test.ts:

import { downloadPdfDataContent } from '.';

describe('67634069', () => {
  afterEach(() => {
    jest.restoreAllMocks();
  });
  it('should pass', () => {
    const mAnchor = ({
      target: '',
      href: '',
      download: '',
      click: jest.fn(),
    } as unknown) as HTMLAnchorElement;
    const createElementSpy = jest.spyOn(document, 'createElement').mockReturnValueOnce(mAnchor);
    const appendChildSpy = jest.spyOn(document.body, 'appendChild').mockImplementation();
    const removeChildSpy = jest.spyOn(document.body, 'removeChild').mockImplementation();
    URL.revokeObjectURL = jest.fn();
    downloadPdfDataContent('teresa teng', 'example.com');
    expect(createElementSpy).toBeCalledWith('a');
    expect(appendChildSpy).toBeCalledWith(
      expect.objectContaining({
        target: 'teresa teng',
        href: 'example.com',
        download: 'teresa teng',
      })
    );
    expect(mAnchor.click).toBeCalledTimes(1);
    expect(removeChildSpy).toBeCalledWith(
      expect.objectContaining({
        target: 'teresa teng',
        href: 'example.com',
        download: 'teresa teng',
      })
    );
    expect(URL.revokeObjectURL).toBeCalledWith('example.com');
  });
});

test result:

 PASS  examples/67634069/index.test.ts (8.691 s)
  67634069
    ✓ should pass (4 ms)

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |     100 |      100 |     100 |     100 |                   
 index.ts |     100 |      100 |     100 |     100 |                   
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        9.612 s
Sign up to request clarification or add additional context in comments.

Comments

0

One way is to set up an onclick handler for the actual global document as part of your test.

If you introduce something distinctive and testable about your link element (e.g. a unique ID), then you could prove that a click was made on it by checking the click event target is the ID of the transient link.

Additionally you can check that the URL it has aligns with the correct values.

Probably even getting ANY click event would be a legitimate test, assuming this is a unit test.

If the test suite is running in a browser context and you would ideally prevent the navigation, then your event handler can use preventDefault to stop any navigation from actually happening.

1 Comment

thank you! sadly that will not be possible for me, as I may not parse the elements in the DOM and can not register any additional click handlers. Ill need a way with jest, jasmine and spyOn :/ it would be interesting if its possible to spy on an object via an mock, and then verify by accessing it's properties

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.