Как проверить, что window.open вызывается из реагирующего компонента - PullRequest
0 голосов
/ 03 февраля 2020

У меня есть компонент реагирования, который отображает ряд других компонентов, каждый со своим собственным флажком.

Существует ловушка состояния rulesToDownload, которая начинается с пустого массива и в него добавляются / удаляются идентификаторы, поскольку флажки отмечены / не отмечены.

Когда нажата кнопка «скачать», массив rulesToDownload передается в функцию данных DownloadFundDataById, которая forEach пересекает массив и вызывает window.open для каждого значения с помощью вызова API с добавленным идентификатором. Функция данных импортируется в компонент, а не передается в качестве реквизита.

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

Я хочу завершить тестовое покрытие, и мне нужно проверить, что функция вызывается при нажатии кнопки и выполняет ли она то, что должна.

Любая помощь приветствуется.

Код ниже:

Summary.test. js:

 it(`should create correct download array when some rules are selected`, async () => {
        global.open = sandbox.spy();

        fetch.mockResponseOnce(JSON.stringify(selectedRules));

        wrapper = mount(<Summary/>);
        await act(async () => {} );
        wrapper.update();

        wrapper.find('ReportProgressSummary').first().find('input').last().simulate('change', {target: {checked: true}});

        wrapper.find('button').first().simulate('click');
        expect(global.open).to.have.been.called();

    });

Я могу подтвердить, что все операторы 'find' верны, и правильно обновить проверенный значение.

Сводка. js:

const Summary = () => {
    const [expand, setExpand] = useState(false);
    const [buttonText, setButtonText] = useState("expand other rules");
    const [rulesToDownload, setRulesToDownload] = useState([]);
    const [data, setData] = useState([]);
    const [dataLoadComplete, setDataLoadComplete] = useState(false);
    const [dataLoadFailed, setDataLoadFailed] = useState(false);

    useEffect(() => {
            loadData();
    }, []);

    const loadData = async () => {
        try {
            let importedData = await ExecuteRules();
            setData(importedData);
            setDataLoadComplete(true);
        } catch (_) {
            setDataLoadFailed(true);
        }
    };

    const onButtonClick = () => {
        setExpand(!expand);
        if(!expand) setButtonText("hide other rules");
        else setButtonText("expand other rules");
    };

    const modifyDownloadArray = (id, checked) => {
        let tempArray;
        if(checked) tempArray = [...rulesToDownload, id];
        else tempArray = [...rulesToDownload.filter(ruleId => ruleId !== id)];
        setRulesToDownload([...tempArray]);
    };

    const dataFilter = (inputData, isFavouriteValue) => {
        return inputData.filter(rule => rule.isFavourite === isFavouriteValue)
                 .sort((a, b) => a.percentage - b.percentage)
                 .map((rule, i) => {
                    return <ReportProgressSummary
                                result={rule.percentage}
                                id={rule.id}
                                title={rule.name} key={i}
                                modifyDownloadArray={modifyDownloadArray}
                            />
                    })
    };

    return (
        <div className="test">
            {
                dataLoadFailed &&
                <div>Rule load failed</div>
            }
            {
                !dataLoadComplete &&
                    <LoadingSpinnerTitle holdingTitle="Loading rule data..."/>
            }
            {
                dataLoadComplete &&
                <Fragment>
                    <PageTitle title="System Overview"/>
                    <LineAndButtonContainerStyled>
                        <ContainerStyled>
                            {
                                dataFilter(data, true)
                            }
                        </ContainerStyled>
                        <ContainerStyled>
                            <ButtonStyled
                                    disabled={!rulesToDownload.length}
                                    onClick={() => DownloadFundDataById(rulesToDownload)}>
                                download
                            </ButtonStyled>
                        </ContainerStyled>
                    </LineAndButtonContainerStyled>

                    <LineBreakStyled/>

                    <ButtonStyled onClick={() => onButtonClick()}>{buttonText}</ButtonStyled>
                    {
                        expand &&
                        <ContainerStyled>
                            {
                                dataFilter(data, false)
                            }
                        </ContainerStyled>
                    }
                </Fragment>
            }
        </div>
    )
};

export default Summary;

DataMethod. js:

export function DownloadFundDataById(downloadArray) {
    downloadArray.forEach(id => window.open(baseApiUrl + '/xxxx/xxxx/' + id));
}

Я могу подтвердить, что URL-адрес в порядке, только что заменен на данный момент

TestSetup:

const doc = jsdom.jsdom('<!doctype html><html><body></body></html>')

global.document = doc;

global.window = doc.defaultView;

configure({ adapter: new Adapter() });

global.expect = expect;
global.sandbox = sinon.createSandbox();
global.React = React;
global.mount = mount;
global.shallow = shallow;
global.render = render;
global.fetch = jestFetchMock;
global.act = act;

chai.use(chaiAsPromised);
chai.use(sinonChai);
chai.use(chaiEnzyme());
chai.use(chaiJestDiff());

console.error = () => {};
console.warn = () => {};

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

1 Ответ

0 голосов
/ 03 февраля 2020

Удалось заставить это работать с парой обновлений моего тестового файла:

it(`should create correct download array when some rules are selected`, async () => {
        global.open = sandbox.stub(window, "open");

        fetch.mockResponseOnce(JSON.stringify(selectedRules));

        wrapper = mount(<Summary/>);
        await act(async () => {} );
        wrapper.update();

        wrapper.find('ReportProgressSummary').first().find('input').last().simulate('change', {target: {checked: true}});

        wrapper.find('button').first().simulate('click');
        expect(global.open).to.have.been.called;

    });

sandbox.spy () был обновлен до sandbox.stub () с (window, "open")

спасибо этой статье за ​​помощь!
https://github.com/mrdulin/mocha-chai-sinon-codelab/blob/master/src/stackoverflow/53524524/index.spec.js

Кроме того, оператор ожидания с использованием to.be.called () на самом деле не является функцией и поэтому был обновлен до .be.called

...