WedX - журнал о программировании и компьютерных науках

Невозможно протестировать фиктивный метод onChange с помощью мелкого и ферментного

Я не могу справиться с тестированием onChange, также имел дело с проблемами с onClick, но каким-то образом мне это удалось.
Я следовал документам Enzyme и Jest, и это не сработало, прошел 2 курса по Pluralsight и но результат был тот же, читал много статей и решений здесь, но все равно это не пройдет. Я узнал об устаревании .simulate() и попробовал props.onChange.

Буду рад любой помощи.

Это компонент, который я хотел бы протестировать:

    const [details, setdetails] = useState(
        {
            fullName: '',
            email: '',
            phone: ''
        }
    )
    const [errors, setErrors] = useState({});
    const [isValid, setValid] = useState(false);

    const handleChange = event => {
        let { name, value } = event.target;
        console.log(value, name, event.target);
        event.preventDefault();
        setdetails(prevDetails => ({
            ...prevDetails,
            [name]: value
        }));

    }
   return (
        <div className="contact" id="contact">
            <div className="logo"></div>
            <div className="contact-title">
                <h6>PLEASE LEAVE YOUR DETAILS BELOW AND WE’LL CONTACT YOU</h6>
            </div>
            <div className="fields">
                <form>
                    <div className="input-field">
                       <label>Full Name:</label>
                       <input name="fullName" placeholder="Full Name" onChange={handleChange}
                   />
                       <div className="text-danger">{errors.fullName}</div>
                  </div>
                  <div className="input-field">
                    <label>Email:</label>
                    <input name="email" placeholder="Email" onChange={handleChange} 
                  />
                    <div className="text-danger">{errors.email}</div></div>
                 <div className="input-field">
                     <label>Phone:</label> 
                     <input name="phone" placeholder="Phone Number" onChange={handleChange} 
                 />
                     <div className="text-danger">{errors.phone}</div>
                </div>
                <div>
                        <button type="submmit" 
                          className="btn-dark button"
                          onClick={handleClick}
                        >Submit</button>
                </div>
             </form>
            </div>
        </div>
    )

Попытки тестирования:

describe('', () => {
    it('', () => {
        let mockOnChange = jest.fn();
        const props = {
            mockOnChange: mockOnChange
        }
        let wrapper = shallow(<Contact {...props} />)
        console.log(wrapper.debug());
        let event = {
            preventDefault: () => { },
            name: 'fullName',
            target: {
                value: 'test'
            }

        }
        wrapper.find('input').at(0).props().onChange({ event })
        expect(mockOnChange).toHaveBeenCalledWith('test');
    })
    it('second assertion', () => {
        let mockOnChange = jest.fn();
        let name = 'fullName';
        let value = 'test';
        let wrapper = shallow(<Contact onChange={mockOnChange} />)
        console.warn(mockOnChange);
        wrapper.instance().onChange({ target: { name, value } });
        expect(mockOnChange).toHaveBeenCalled('test');
    })
    it('', () => {
        let handleChange = jest.fn();
        let mockName = 'fullName';
        let mockValue = 'test';
        let wrapper;
        wrapper = shallow(<Contact onChange={handleChange} />);
        wrapper.find('input').at(0).simulate('change', {
            preventDefault: () => { },
            target: {
                name: mockName,
                value: mockValue
            }
        })
        expect(handleChange).toHaveBeenCalledWith("test");

    })
})


describe("simulate onchange input fileds", () => {
    let wrapper;
    let mockOnChange;
    beforeEach(() => {
        mockOnChange = jest.fn();
        const props = {
            mockOnChange: mockOnChange
        }
        wrapper = shallow(<Contact {...props} />);
    });
    it('first assertion', () => {

        wrapper.find('input').at(0).simulate('change', {
            preventDefault: () => { },
            target: { value: 'test' }
        })
        expect(mockOnChange).toBeCalledWith("test");
    })

    it('should call onChange prop', () => {
        const event = {
            preventDefault: () => { },
            target: {
                name: 'fullName',
                value: 'test'
            }
        };
        const component = shallow(<Contact onChange={mockOnChange} />);
        component.find('input').at(0).props().onChange('change', event);
        expect(mockOnChange).toBeCalledWith('test');
    });
})
12.01.2020

Ответы:


1

Ваш компонент не вызывает props.mockOnChange или props.handleChange или что-то подобное. Он просто берет новое значение из события, сохраняет его в своем состоянии и отображает как значение для соответствующего ввода.

Также в настоящее время ваш компонент вообще не использует details для рендеринга. я ожидаю, что это выглядит так

<input 
  name="fullName" 
  placeholder="Full Name" 
  onChange={handleChange}
  value={details.fullName}
/>

И тогда мы сможем проверить это поведение (также обратите внимание на структуру event, в вашем коде вы устанавливаете свойство name вне подобъекта target):

it('', () => {
    let wrapper = shallow(<Contact {...props} />)
    let event = {
        preventDefault: jest.fn(),
        target: {
            name: 'fullName',
            value: 'test'
        }

    }
    wrapper.find('input[name="fullName"]').simulate('change', event)
    expect(wrapper.find('input[name="fullName"]').prop('value')).toBe('test');
    expect(wrapper.find('input[name="email"]').prop('value')).toBe('');
    expect(event.preventDefault).toHaveBeenCalled();
13.01.2020
  • Эй, скайбойер, прежде всего спасибо за ответы и за важные замечания. плохо, даже после того, как я внес изменения, которые вы написали, он все еще не прошел тест. Не удалось разобрать селектор: input[name=fullName] wrapper.find('input[name=fullName]').simulate('change', event) ^ expect(wrapper.find('input[name=fullName]'). prop('value')).toBe('test'); ожидать (wrapper.find ('input [name = email]'). prop ('value')). toBe (''); ожидать(event.preventDefault).toHaveBeenCalled(); 13.01.2020
  • Когда я попробовал это с помощью метода at, вывод был неопределенным. 13.01.2020
  • наверное надо с кавычками input[name="fullName"]. или вы можете попробовать .find("input").filter({name: "fullName"}) 13.01.2020
  • Я очень ценю вашу готовность и тот факт, что выre answering so fast. I have tried both but, it все еще подали заявку, утверждая, что значение не определено. есть идеи, почему? может я что-то не так декларирую? 13.01.2020
  • не вижу причин :( так prop('value') undefined? или .find() возвращает undefined? 13.01.2020
  • expect(received).toBe(expected) // Object.is равенство Expected: test Получено: undefined › 96 | ожидать(обертка.найти(ввод).фильтр({имя: полноеИмя}).prop('значение')).toBe('тест'); | ^ 13.01.2020
  • не знаю что еще делать 13.01.2020
  • Я пропустил действительно основную вещь: ваш компонент не отображает details.fullName в атрибут value. Вот почему он не работал в тесте. Кроме того, поначалу это может работать для вас, текущая версия никогда не позволит вам устанавливать значение программно без изменения кода. Так что лучше сделайте это прямо сейчас. 13.01.2020
  • Еще раз, спасибо за исправление и за каждый ответ, сделал то, что вы написали, но все еще не прошел тест, но теперь это потому, что значение не меняется. это странно, потому что функция работает, не могу понять, почему тест не работает 14.01.2020
  • о, только сегодня я смог запустить его с помощью отладчика и обнаружил, что вы поместили name в неправильное место внутри event (не в target, а как опору 1-го уровня). Обновленный ответ, проверьте его. Испытание прошло для меня. 14.01.2020
  • Новые материалы

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..


    Для любых предложений по сайту: [email protected]