首页 > 解决方案 > e.target.getAttribute is not a function

问题描述

I am trying to test onChange event and I am getting the following error:

TypeError: e.target.getAttribute is not a function

Here is the method:

handleChange = e => {
  const key = e.target.name;
  const value = e.target.getAttribute('value');
  const otherValue = e.target.value;
  const localState = {};
  let chartObj = {};
  if (value == null && otherValue != undefined) {
    localState[key] = otherValue;
    chartObj = this.buildChartObj({ switchValue: key, chartObjValue: otherValue });
  } else {
    localState[key] = value;
    chartObj = this.buildChartObj({ switchValue: key, chartObjValue: value });
  }
  this.props.updateViewXMLValue(chartObj);
  this.setState(localState);
};

Part of the code where onChange is calling handleChange

  buildCategoryDropdown = () => {

 <div className='tab-input-container'>
   <select className='shape-dropdown' onChange={this.handleChange} name='category' defaultValue={!this.props.defaultData.category.$.id ? 'default' : this.props.defaultData.category.$.id}>
       {categories}

test file: There are 3 classNames: shape-dropdown', the test passes for simulating at (0) but not for 1 and 2. I tried to add an Id as well but still getting the same error

it('should call onChange event', () => {
  baseProps.onChange.mockClear();
  wrapper.setState({ localState: {} });
  wrapper.update();
  wrapper
    .find('.shape-dropdown')
    .at(0)
    .simulate('change', { target: { name: 'value' }, value: 'value' });
  expect(wrapper.state('localState')).toEqual('value');
});

标签: javascriptjestjsenzyme

解决方案


您需要创建一个模拟getAttribute方法来target.

index.ts

import React, { Component } from 'react';

export class SomeComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      animal: '',
      fruit: '',
      language: ''
    };
    this.handleChange = this.handleChange.bind(this);
  }
  public render() {
    return (
      <div className="tab-input-container">
        <select className="shape-dropdown" onChange={this.handleChange} name="animal">
          <option value="">--select option 1--</option>
          <option value="dog">Dog</option>
          <option value="cat">Cat</option>
        </select>
        <select className="shape-dropdown" onChange={this.handleChange} name="fruit">
          <option value="">--select option 2--</option>
          <option value="apple">Dog</option>
          <option value="orange">Cat</option>
        </select>
        <select className="shape-dropdown" onChange={this.handleChange} name="language">
          <option value="">--select option 3--</option>
          <option value="jest">Dog</option>
          <option value="ts">Cat</option>
        </select>
      </div>
    );
  }

  private handleChange(e: React.ChangeEvent<HTMLSelectElement>) {
    const key = e.target.name;
    const value = e.target.getAttribute('value');
    const otherValue = e.target.value;

    this.setState({ [key]: value });
  }
}

单元测试:

import React from 'react';
import { shallow } from 'enzyme';
import { SomeComponent } from './';

describe('SomeComponent', () => {
  const getAttribute = jest.fn();
  it('t1', () => {
    const selectedOptions = [
      { name: 'animal', value: 'dog' },
      { name: 'fruit', value: 'apple' },
      { name: 'language', value: 'jest' }
    ];
    const wrapper = shallow(<SomeComponent></SomeComponent>);
    expect(wrapper.find('.shape-dropdown')).toHaveLength(3);

    getAttribute.mockReturnValueOnce(selectedOptions[0].value);
    wrapper
      .find('.shape-dropdown')
      .at(0)
      .simulate('change', { target: { name: selectedOptions[0].name, getAttribute, value: selectedOptions[0].value } });
    expect(wrapper.state()).toEqual({ animal: 'dog', fruit: '', language: '' });

    getAttribute.mockReturnValueOnce(selectedOptions[1].value);
    wrapper
      .find('.shape-dropdown')
      .at(1)
      .simulate('change', { target: { name: selectedOptions[1].name, getAttribute, value: selectedOptions[1].value } });
    expect(wrapper.state()).toEqual({ animal: 'dog', fruit: 'apple', language: '' });

    getAttribute.mockReturnValueOnce(selectedOptions[2].value);
    wrapper
      .find('.shape-dropdown')
      .at(2)
      .simulate('change', { target: { name: selectedOptions[2].name, getAttribute, value: selectedOptions[2].value } });
    expect(wrapper.state()).toEqual({ animal: 'dog', fruit: 'apple', language: 'jest' });
  });
});

覆盖率 100% 的单元测试结果:

 PASS  src/stackoverflow/55049522/index.spec.tsx
  SomeComponent
    ✓ t1 (19ms)

-----------|----------|----------|----------|----------|-------------------|
File       |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files  |      100 |      100 |      100 |      100 |                   |
 index.tsx |      100 |      100 |      100 |      100 |                   |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        6.535s

这是完成的演示: https ://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/55049522


推荐阅读