Jest: модульное тестирование создания документа Excel после http-ответа Blob-ответа - PullRequest
0 голосов
/ 13 января 2020

Я работаю над реагирующим приложением, используя Jest

Мне нужно загрузить Excel, который я получаю в виде BLOB-объекта из HTTP-вызова. Я должен соблюдать охват 90% модульных тестов, и я в беде с этой частью кода:

downloadExcel = () => {
  templateService.getTemplate().then(
    response => {
      const url = window.URL.createObjectURL(new Blob([response.data]));
      const link = document.createElement("a");
      link.href = url;
      link.setAttribute("download", "Project_register_template_PMB.xlsx");
      document.body.appendChild(link);
      link.click();
    },
    error => {
      this.setState({
        errors: { api: `API error:${error}, please contact an administrator` }
      });
    }
  );
};

Вот мой сервис шаблонов:

const getTemplate = async () => {
  const options = {
    responseType: "blob",
    headers: handleHeaders()
  };
  return await axios.get(downloadUrl, options).catch(handleResponse);
};

const uploadTemplate = async formData => {
  return await axios.post(uploadUrl, formData, { headers: handleHeaders() });
};

export const templateService = { getTemplate, uploadTemplate };

Я очень недавно разработчик реагирования и, возможно, я делаю это неправильно, я был бы рад изменить мой код, следуя любому совету

Спасибо за вашу помощь

1 Ответ

1 голос
/ 13 января 2020

Вот решение для модульного тестирования:

index.tsx:

import React, { Component } from 'react';
import * as templateService from './templateService';

class SomeComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      errors: {
        api: '',
      },
    };
  }
  downloadExcel = () => {
    templateService.getTemplate().then(
      (response) => {
        const url = window.URL.createObjectURL(new Blob([response.data]));
        const link = document.createElement('a');
        link.href = url;
        link.setAttribute('download', 'Project_register_template_PMB.xlsx');
        document.body.appendChild(link);
        link.click();
      },
      (error) => {
        this.setState({
          errors: { api: `API error:${error}, please contact an administrator` },
        });
      },
    );
  };

  render() {
    return <button onClick={() => this.downloadExcel()}>Download</button>;
  }
}

export default SomeComponent;

templateService.ts:

export const getTemplate = async () => {
  return { data: 'real data' };
};

index.test.ts:

import SomeComponent from './';
import React from 'react';
import { mount, ReactWrapper, shallow } from 'enzyme';
import * as templateService from './templateService';
import { act } from 'react-dom/test-utils';

const whenStable = async () => {
  await act(async () => {
    await new Promise((resolve) => setTimeout(resolve, 0));
  });
};

describe('59715038', () => {
  let wrapper;
  beforeEach(() => {
    wrapper = shallow(<SomeComponent></SomeComponent>);
  });
  afterEach(() => {
    jest.restoreAllMocks();
  });
  describe('#downloadExcel', () => {
    it('should download excel correctly', async () => {
      const url = 'https://github.com';
      const mResponse = { data: 'fake data' };
      jest.spyOn(templateService, 'getTemplate').mockResolvedValueOnce(mResponse);
      window.URL.createObjectURL = jest.fn().mockReturnValueOnce(url);
      const mLink = { href: '', setAttribute: jest.fn(), click: jest.fn() };
      document.createElement = jest.fn().mockReturnValueOnce(mLink);
      document.body.appendChild = jest.fn();
      wrapper.find('button').simulate('click');
      await whenStable();
      expect(window.URL.createObjectURL).toBeCalledWith(new Blob([mResponse.data]));
      expect(document.createElement).toBeCalledWith('a');
      expect(mLink.href).toBe(url);
      expect(mLink.setAttribute).toBeCalledWith('download', 'Project_register_template_PMB.xlsx');
      expect(document.body.appendChild).toBeCalledWith(mLink);
      expect(mLink.click).toBeCalledTimes(1);
    });

    it('should set errors if get template failure', async () => {
      const mError = new Error('some error');
      jest.spyOn(templateService, 'getTemplate').mockRejectedValueOnce(mError);
      wrapper.find('button').simulate('click');
      await whenStable();
      expect(wrapper.state()).toEqual({ errors: { api: `API error:${mError}, please contact an administrator` } });
    });
  });
});

Результаты модульных испытаний с отчетом о покрытии:

 PASS  src/stackoverflow/59715038/index.test.tsx (5.098s)
  59715038
    #downloadExcel
      ✓ should download excel correctly (30ms)
      ✓ should set errors if get template failure (12ms)

--------------------|----------|----------|----------|----------|-------------------|
File                |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
--------------------|----------|----------|----------|----------|-------------------|
All files           |    91.67 |      100 |     87.5 |       95 |                   |
 index.tsx          |      100 |      100 |      100 |      100 |                   |
 templateService.ts |    33.33 |      100 |        0 |       50 |                 2 |
--------------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        8.485s

Исходный код: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/59715038

...