javascript - 如何对从 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)
});
});
解决方案
此答案仅供参考。它不会“正常工作”。
您的请求很复杂 - 测试通常是用 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,它还附带测试框架的额外好处,允许您测试渲染。其他框架可用。
推荐阅读
- r - 如何在内部启用 Shiny(通过 LAN)托管 R Markdown 文档
- parameters - 如何参数化 Hspice 子电路的模型类型?
- javascript - 以计数为值迭代对象
- ios - 为 WKInterfaceImage 着色?
- java - 当多个客户端套接字尝试同时连接时,连接顺序是否保持不变?
- javascript - 使用 html 按钮按箭头键或直接按下
- cuda - 将指向多个设备的指针数组传递给 Cuda C 内核
- angular - 如何解决Angular 7“尝试区分时出错......只允许数组和可迭代”错误?
- flutter - 将 GDPR 同意对话框添加到 Flutter 应用程序
- python - 如何重构代码以使源代码中的每个列表都排序?