首页 > 解决方案 > 如何对从 JSON 呈现的 HTML 进行单元测试?

问题描述

我在解决如何使用 JEST 和 vanilla JS 进行 UNIT 测试时遇到了一些麻烦,因为 nothign 真的要上线了。

我正在调用一个 API 端点,然后将该数据呈现为 HTML - 一组 UL/LI 和一个子菜单(如果有子菜单)。

您将如何分解此功能以对其进行单元测试-我什至不确定从哪里开始

这是数据

   "items":[
      {
         "label":"Work",
         "url":"#/work",
         "items":[
         ]
      },
      {
         "label":"About",
         "url":"#/about",
         "items":[
            {
               "label":"What we do",
               "url":"#/about/what-we-do"
            },
            {
               "label":"How we work",
               "url":"#/about/how-we-work"
            },
            {
               "label":"Leadership",
               "url":"#/about/leadership"
            }
         ]
      },
      {
         "label":"foo",
         "url":"#/foo",
         "items":[
            {
               "label":"Client Services",
               "url":"#/foo/client"
            },
            {
               "label":"Creative",
               "url":"#/foo/creative"
            },
            {
               "label":"Motion & Media",
               "url":"#/foo/motion"
            }


         ]
      }

   ]
}

这是我为创建 DOM 元素而调用的函数——它有点混乱,但它本质上是在创建锚标签和 Ul / Li 的。

  createNavigationMenu: function (data) {
    return data.map((item) => {
      const listElement = document.createElement('li');
      const listElementAnchor = document.createElement('a');
      const subMenuContainer = document.createElement('ul');
      const chevron = document.createElement('span');

      listElementAnchor.setAttribute("href", `${item.url}`);
      listElementAnchor.setAttribute("class", 'navigation__primary-menu-anchor');
      listElementAnchor.innerHTML = item.label;

      listElement.setAttribute("class", "navigation__primary-menu-item");
      listElement.appendChild(listElementAnchor);
      this.navigationContainer.append(listElement);

      subMenuContainer.setAttribute("class", "navigation__submenu");
      item.items.length ? listElement.append(subMenuContainer) : null
      chevron.setAttribute("class", "arrow");
      item.items.length ? listElementAnchor.append(chevron) : null

      return item.items.map(submenuItem => {
        const subMenuContainerItem = document.createElement('li');
        const subMenuContainerItemAnchor = document.createElement('a');
        subMenuContainerItemAnchor.setAttribute("href", `/${submenuItem.url}`);
        subMenuContainerItemAnchor.setAttribute("class", 'navigation__submenu-menu-anchor');
        subMenuContainerItemAnchor.innerHTML = submenuItem.label;
        subMenuContainerItem.setAttribute("class", "navigation__submenu-menu-item");

        subMenuContainerItem.append(subMenuContainerItemAnchor)
        listElement.append(subMenuContainer);
        subMenuContainer.append(subMenuContainerItem)

      })
    })
  }

我已经用 JSDOM 试过了,但它似乎不起作用

const data = {
  "items": [
    {
      "label": "Work",
      "url": "#/work",
      "items": [
      ]
    }
  ]
}
const markup = `<ul id="navigation__primary-menu" class="navigation__primary-menu">
  <li>
    <h1 class="navigation__primary-logo">HUGE </h1> <span id="iconSpan" class="saved"> </span>
  </li>
  <li class="navigation__primary-list-item"></li>
  <li class="navigation__primary-menu-item"><a href="#/work" class="navigation__primary-menu-anchor">Work</a></li>
</ul>`


describe('should map data correctly', () => {
  test('markup entered', () => {
    const { windpw } = new JSDOM(markup);
    const nav = Controller.createNavigationMenu(data)
    expect(dom.serialize()).toMatch(nav)

  });
});

标签: javascriptjestjs

解决方案


此答案仅供参考。它不会“正常工作”。

您的请求很复杂 - 测试通常是用 Node(这是服务器端)编写的,您正在谈论使用文档和 DOM(这是客户端)。

我建议查看https://github.com/jsdom/jsdom,它允许您在 Node.js 中模拟文档。

然后,从他们的文档中,类似:

const dom = new JSDOM();

并像这样更新您的生成器:

createNavigationMenu: function (data, dom) { //pass in your dom object here
  return data.map((item) => {
    const listElement = dom.createElement('li');
    .... //replace all documents with dom

在运行测试时将您的特殊 dom 传递到您的生成器函数中,并在其他时间传递真实文档。

最后,在您的测试中(使用开玩笑的例子):

describe('dom test', () => {
  it('should render like this', () => {
    expect(dom.serialize()).toMatchSnapshot()
  }
}

顺便说一句,如果你想变得超级聪明,DOM 操作通常只有在这个时代才是必要的。我强烈建议(如果您还没有考虑过)尝试使用可以让您的生活更轻松的框架。我使用 React,它还附带测试框架的额外好处,允许您测试渲染。其他框架可用。


推荐阅读