Подтвердить что ты не робот

Как протестировать PropTypes через Jest?

Я пишу тесты Jest для моего кода React и надеюсь использовать/проверить проверки PropType. Я совершенно новичок в юниверсе Javascript. Я использую npm для установки react-0.11.2 и имею простой:

var React = require('react/addons');

В моих тестах. Мой тест очень похож на пример шутки/реакции с кодом, например:

var eventCell = TestUtils.renderIntoDocument(
  <EventCell
    slot={slot}
    weekId={weekId}
    day={day}
    eventTypes={eventTypes}
    />
);

var time = TestUtils.findRenderedDOMComponentWithClass(eventCell, 'time');
expect(time.getDOMNode().textContent).toEqual('19:00 ');

Однако кажется, что проверки PropType в компоненте EventCell не запускаются. Я понимаю, что проверки выполняются только в режиме разработки, но потом я также подумал, что получение react через npm дает вам версию для разработки. Триггер проверки в моем браузере, когда я создаю компонент с функцией watchify.

Что мне не хватает?

4b9b3361

Ответ 1

Основная проблема Как протестировать console.log?

Короткий ответ заключается в том, что вы должны заменить console.{method} на время теста. Общий подход заключается в использовании spies. В этом конкретном случае вы можете использовать stubs, чтобы предотвратить выход.

Вот пример реализации с использованием Sinon.js (Sinon.js предоставляет автономные шпионы, заглушки и макеты):

import {
    expect
} from 'chai';
import DateName from './../../src/app/components/DateName';
import createComponent from './create-component';
import sinon from 'sinon';

describe('DateName', () => {
    it('throws an error if date input does not represent 12:00:00 AM UTC', () => {
        let stub;

        stub = sinon.stub(console, 'error');

        createComponent(DateName, {date: 1470009600000});

        expect(stub.calledOnce).to.equal(true);
        expect(stub.calledWithExactly('Warning: Failed propType: Date unix timestamp must represent 00:00:00 (HH:mm:ss) time.')).to.equal(true);

        console.error.restore();
    });
});

В этом примере компонент DataName будет вызывать ошибку при инициализации с отметкой времени, которая не соответствует точной дате (12:00:00 AM).

Я завершаю метод console.error (это то, что модуль Facebook warning использует внутренне для генерации ошибки). Я гарантирую, что заглушка была вызвана один раз и точно одним параметром, представляющим ошибку.

Ответ 2

Введение

Ответ от @Gajus определенно помог мне (так, спасибо Gajus). Тем не менее, я думал, что дам ответ:

  • Использует более обновленный (v15.4.1)
  • Использует Jest (который поставляется с React)
  • Позволяет тестировать несколько значений поддержки для одиночной прокрутки
  • более общий

Резюме

Как и подход, предложенный здесь Гаюсом и другими людьми другими, основной подход, который я предлагаю, также должен определить, используется ли console.error Реакт в ответ на недопустимое значение прокрутки теста. В частности, этот подход включает в себя выполнение следующего для каждого значения теста:

  • mocking и clearing console.error (для обеспечения того, чтобы предыдущие вызовы console.error не мешали),
  • создание компонента с использованием значения тестового значения и
  • , подтверждающий, был ли запущен console.error, как ожидалось.

Функция testPropTypes

Следующий код может быть размещен либо внутри теста, либо как отдельный импортированный/требуемый модуль/файл:

const testPropTypes = (component, propName, arraysOfTestValues, otherProps) => {
    console.error = jest.fn();
    const _test = (testValues, expectError) => {
        for (let propValue of testValues) {
            console.error.mockClear();
            React.createElement(component, {...otherProps, [propName]: propValue});
            expect(console.error).toHaveBeenCalledTimes(expectError ? 1 : 0);
        }
    };
    _test(arraysOfTestValues[0], false);
    _test(arraysOfTestValues[1], true);
};

Вызов функции

Любое тестирование propTypes может вызвать testPropTypes, используя три или четыре параметра :

  • component, React компонент, который модифицируется prop;
  • propName, строка имя тестируемого;
  • arraysOfTestValues, массив массивов всех требуемых тестовых значений тестируемого проспекта:
    • первая подматрица содержит все значения приемлемые, а
    • вторая подматрица содержит все неприемлемые значения test prop; и
  • необязательно otherProps, объект, содержащий пары prop name/value для любых других необходимых реквизитов этого компонента.

    Объект otherProps необходим для обеспечения того, чтобы React не делал нерелевантные вызовы console.error, потому что другие требуемые реквизиты непреднамеренно отсутствуют. Просто включите одно приемлемое значение для любых необходимых реквизитов, например. {requiredPropName1: anyAcceptableValue, requiredPropName2: anyAcceptableValue}.

Функциональная логика

Функция выполняет следующие действия:

  • Он устанавливает макет console.error, что и используется Реагтом для сообщения реквизитов неправильного типа.

  • Для каждого вспомогательного массива значений prop prop при условии, что он проходит через каждое тестовое значение поддержки в каждой подгруппе для проверки типа prop:

    • Первый из двух подматриц должен быть списком допустимых значений прогона.
    • Второй должен состоять из неприемлемых значений значений прокрутки.
  • Внутри цикла для каждого отдельного значения прокрутки теста макет console.error сначала очищается, так что любые обнаруженные сообщения об ошибках могут считаться полученными из этого теста.

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

  • Наконец, делается проверка на , было ли предупреждение вызвано, что должно произойти, если ваш тест попытался создать компонент с использованием несоответствующей или отсутствующей прокрутки.

Тестирование для необязательных и требуемых реквизитов

Обратите внимание, что присвоение null (или undefined) значению prop является, с точки зрения реактивов, по существу тем же самым, что и не дает никакого значения для этой опоры. По определению это приемлемо для опционной опоры, но неприемлемо для требуемого. Таким образом, , поместив null в массив допустимых или неприемлемых значений, вы проверяете, является ли эта поддержка необязательной или требуется соответственно.

Пример кода

MyComponent.js(только propTypes):

MyComponent.propTypes = {
    myProp1: React.PropTypes.number,      // optional number
    myProp2: React.PropTypes.oneOfType([  // required number or array of numbers
        React.PropTypes.number,
        React.PropTypes.arrayOf(React.PropTypes.number)
    ]).isRequired

MyComponent.test.js:

describe('MyComponent', () => {

    it('should accept an optional number for myProp1', () => {
        const testValues = [
            [0, null],   // acceptable values; note: null is acceptable
            ['', []] // unacceptable values
        ];
        testPropTypes(MyComponent, 'myProp1', testValues, {myProp2: 123});
    });

    it('should require a number or an array of numbers for myProp2', () => {
        const testValues = [
            [0, [0]], // acceptable values
            ['', null] // unacceptable values; note: null is unacceptable
        ];
        testPropTypes(MyComponent, 'myProp2', testValues);
    });
});

Ограничение этого подхода (ВАЖНО)

В настоящее время существуют некоторые существенные ограничения в отношении того, как вы можете использовать этот подход, который, если бы он перешагнул, мог бы стать источником некоторых труднопробных тестовых ошибок. Причины и последствия этих ограничений объясняются в этом другом SO-вопросе/ответе., Таким образом, для простых типов прокрутки, например, для myProp1, вы можете протестировать как можно больше недопустимых значений null test prop, поскольку они представляют собой все разные типы данных. Для некоторых сложных типов prop, например, для myProp2, вы можете проверить только одно неприемлемое значение non null prop любого типа. См. Этот другой вопрос/ответ для более углубленного обсуждения.

Ответ 3

Mocking console.error не подходит для использования в модульных тестах! @AndrewWillems, связанный с другим вопросом SO в комментарии выше, который описывает проблемы с этим подходом.

Откажитесь от эту проблему в facebook/prop-types для обсуждения возможности для этой библиотеки бросать вместо регистрации ошибок propType (at время написания, оно не поддерживается).

Я опубликовал вспомогательную библиотеку, чтобы обеспечить это поведение в среднем времени check-prop-types. Вы можете использовать его следующим образом:

import PropTypes from 'prop-types';
import checkPropTypes from 'check-prop-types';

const HelloComponent = ({ name }) => (
  <h1>Hi, {name}</h1>
);

HelloComponent.propTypes = {
  name: PropTypes.string.isRequired,
};

let result = checkPropTypes(HelloComponent.propTypes, { name: 'Julia' }, 'prop', HelloComponent.name);
assert(`result` === null);

result = checkPropTypes(HelloComponent.propTypes, { name: 123 }, 'prop', HelloComponent.name);
assert(`result` === 'Failed prop type: Invalid prop `name` of type `number` supplied to `HelloComponent`, expected `string`.');

Ответ 4

Так как ReactJS будет отправлять предупреждения только на консоль, но на самом деле не выдает ошибку, я проверяю значения prop таким образом:

var myTestElement = TestUtils.renderIntoDocument(
<MyTestElement height={100} /> );

it("check MyTestElement props", function() {

   expect( typeof myTestElement.props.height ).toEqual ( 'number' );

});