ReactJS состояние компонента возвращает пустые данные даже после успешной установки в тестах шут / фермент - PullRequest
1 голос
/ 03 марта 2020

У меня есть простой метод для извлечения данных из API и обновления состояния в компоненте Grid

//in the constructor
this.state = {
    blogs: []
};

//method here
updateBlogsTable() {
    Axios.get("/api/blogs").then(response => {
        this.setState({ blogs: response.data.data });
    });
    //omitting catch block for brevity
}

Этот метод вызывается из обработчика componentDidMount и Refre sh кнопки click

componentDidMount() {
    this.updateBlogsTable();
}

и

<Button
    id="refreshBlog"
    icon="pi pi-refresh"
    style={{ float: "right" }}
    onClick={this.updateBlogsTable}
/>

Тест на Refre sh Кнопка не пройдена

describe("Blog Grid", () => {
  let response = {
      data: {
          data: [
              {
                  title: "title one",
                  published: false,
                  publish_date: null,
                  slug: "title-one"
              },
              {
                  title: "title two",
                  published: false,
                  publish_date: null,
                  slug: "title-two"
              }
          ],
          links: {
              self: "link-value",
              first: "http://adminpanel.test/api/blogs?page=1",
              last: null,
              prev: null,
              next: null
          },
          meta: {
              current_page: 1,
              from: 1,
              path: "http://adminpanel.test/api/blogs",
              per_page: 20,
              to: 2
          }
      }
  };

  it("refreshes blogs", () => {
      axios.get.mockImplementationOnce(() => Promise.resolve(response));
      const grid = mount(<Grid />);
      let refreshResponse = Object.assign({}, response);
      refreshResponse.data.data.push({
          title: "title three",
          published: true,
          publish_date: null,
          slug: "title-three"
      });
      axios.get.mockImplementationOnce(() =>
          Promise.resolve(refreshResponse)
      );
      grid.find("#refreshBlog")
          .at(0)
          .simulate("click");
      expect(grid.state().blogs).toEqual(refreshResponse.data.data);
  });


});

grid.state().blogs возвращает [], что не проходит тест.

FAIL resources/js/tests/Blogs/Grid.test.js (5.765s)

  Blog Grid
    ✓ renders without errors (235ms)
    ✕ refreshes blogs (161ms)

  ● Blog Grid › refreshes blogs

    expect(received).toEqual(expected) // deep equality

Когда я добавляю console.log(this.state.blogs); к методу updateBlogsTable(); Я вижу

console.log resources/js/views/Blogs/Grid/Grid.js:25
[ { title: 'title one',
    published: false,
    publish_date: null,
    slug: 'title-one' },
  { title: 'title two',
    published: false,
    publish_date: null,
    slug: 'title-two' },
  { title: 'title three',
    published: true,
    publish_date: null,
    slug: 'title-three' } ]

Почему grid.state().blogs все еще пустой массив в тесте?

1 Ответ

1 голос
/ 03 марта 2020

Поскольку promise.gets вызывается асинхронно, как только вы имитируете нажатие кнопки, ваше состояние не будет обновляться.

Я сталкивался с аналогичной проблемой при тестировании своих компонентов, и я мог подумать об устранении этой проблемы одним способом - вернуть обещание от вашего updateBlogTable и подписаться на then в своем тесте и получить утверждение в пределах это then.

Как-то так -

updateBlogsTable() {
  let p = Axios.get("/api/blogs").then(response => {
      this.setState({ blogs: response.data.data });
  });
  return p;
}

grid.instance().updateBlogsTable().then(() => {
  expect(grid.state().blogs).toEqual(refreshResponse.data.data);
})

Даже я хочу знать, можно ли проверить это напрямую, имитируя нажатие кнопки.

Дайте мне знать, если это поможет.

...