.getAttribute不是函数

时间:2019-09-05 14:44:38

标签: javascript reactjs jestjs jsx

你好,我是JS的新手,可能是代码中的错误。 但是我不明白为什么getAttribute不是函数。

测试:

test('TESTING', () => {
    const filterNodes = [
        <div key='1' value='foo' />,
        <div key='2' value='bar' />
    ]
    const filtersKeyValue = {
        key: ['0', '1', '1', '3'],
        value: ['foo', 'bar', 'toto', 'react']
    }

    expect(fillReportSpecFiltersWithValues(filterNodes, filtersKeyValue)).toBe()
})

代码:

export const fillReportSpecFiltersWithValues = (filterNodes, filtersKeyValue = {}) => {
    for (const key in filtersKeyValue) {
        const value = filtersKeyValue[key]
        for (const filterNode of filterNodes) {
            if (filterNode.getAttribute('key') === key) {
                filterNode.setAttribute('value', value)
            }
        }
    }
}

有什么建议值得赞赏吗?

2 个答案:

答案 0 :(得分:1)

此代码

const filterNodes = [
    <div key='1' value='foo' />,
    <div key='2' value='bar' />
]

创建一组代表React节点的对象。在您调用ReactDOM.render()之前,它们实际上并不是HTMLElement或DOM节点。

请考虑以下内容,以打印由JSX表达式表示的Object。它没有您要尝试调用的方法。您需要调整测试以查看对象确实具有或可能将JSX对象呈现给DOM的属性,然后然后将它们视为HTMLElement。

// JSX to construct an anchor with an href
const bar = "http://example.com";
const foo = <a href={bar}>anchor</a>; 

// Prints the JSX Object definition
console.log(foo);

// This will actually populate the DOM with the JSX definition
const dom = ReactDOM.render(foo, document.getElementById("fizz"));

// The rendered DOM node
console.log(dom);

// The attribute pulled from the DOM node
console.log(dom.getAttribute("href"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="fizz"></div>

考虑到这一点,您的代码测试代码应该看起来更像这样,其中您通过map() ReactDOM.render()来使用JSX对象,以便它们成为HTMLElements:

test('TESTING', () => {
  // Make someplace to put the elements that you want converted
  const app = document.getElementById("foo");
  
  // Map them through ReactDOM.render() to make elements
  const filterNodes = [
    <div key='1' value='foo' />,
    <div key='2' value='bar' />
  ].map(n => ReactDOM.render(n, app));

  // Sanity check
  console.log(filterNodes);

  const filtersKeyValue = {
    key: ['0', '1', '1', '3'],
    value: ['foo', 'bar', 'toto', 'react']
  }

  expect(fillReportSpecFiltersWithValues(filterNodes, filtersKeyValue)).toBe()
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="foo"></div>

答案 1 :(得分:1)

听起来你的工作就是测试fillReportSpecFiltersWithValues

它接受具有getAttributesetAttribute属性的对象数组,以及代表键/值对的对象。

与其通过创建模拟的DOM元素进行测试,不如通过创建适当的模拟对象进行测试:

test('fillReportSpecFiltersWithValues', () => {
  const filterNodes = [
    { getAttribute: () => '1', setAttribute: jest.fn() },
    { getAttribute: () => '2', setAttribute: jest.fn() },
    { getAttribute: () => '3', setAttribute: jest.fn() }
  ]
  const filtersKeyValue = {
    '1': 'foo',
    '2': 'bar'
  }

  fillReportSpecFiltersWithValues(filterNodes, filtersKeyValue);

  expect(filterNodes[0].setAttribute).toHaveBeenCalledWith('value', 'foo');  // Success!
  expect(filterNodes[1].setAttribute).toHaveBeenCalledWith('value', 'bar');  // Success!
  expect(filterNodes[2].setAttribute).not.toHaveBeenCalled();  // Success!
});