测试获取数据查询到组件反应

时间:2021-06-26 14:12:27

标签: reactjs jestjs next.js enzyme react-testing-library

当我使用 fetch 从响应页面获取和发布数据时,我正在尝试使用 jest 编写测试。

当前的测试是这样的 - 我对如何确保正确的数据通过特定组件感到困惑。

测试本身目前看起来像这样,

import React from 'react';
import '@testing-library/jest-dom';
import { render } from '@testing-library/react';

import getSettings from 'components/onboarding/stages/useGetSettingsData.js'
import updateSettings from 'components/onboarding/stages/useUpdateSettings.js'
import Settings from 'components/onboarding/stages/useUpdateSettings.js'


describe('get settings', () => {
    it('should load settings with no issues', () => {
       getSettings().mockResolvedValueOnce({
        power: 'magical',
        potion: 'magilin',
        potion_times: '[]',
        potion_activity_times: '',
        gender: 'Male',
        age: '30',
      });
      const {getByText, getByLabelText,debug} = render( <Settings/> )
  
      expect(heading).toBeInTheDocument();

      expect(GetSettings)
    });
  });

测试这个获取用户数据的功能,

import { useEffect, useState } from 'react';

export default function getSettings(auth) {
  const [settings, setSettings] = useState(false);

  useEffect(() => {
    try {
      const idToken = auth.getIdToken();

      const response = fetch('/api/dashboard/get-settings', {
        method: 'GET',
        headers: new Headers({
          Authorization: `Bearer ${idToken}`,
          'Content-Type': 'application/x-www-form-urlencoded',
        }),
      });
      const jsonReponse = response.json();

      if (!jsonReponse.error) {
        setSettings(jsonReponse.settings);
      } else {
        setSettings({
          power: 'magical',
        potion: 'magilin',
        potion_times: '[]',
        potion_activity_times: '',
        gender: 'Male',
        age: '30',
        });
      }
    } catch (error) {
      console.log('Error happened in decrypting token', error);
    }
  }, [settings]);
  return settings;
};

这是设置设置,

import { loadingReducer } from 'components/onboarding/stages/loadingReducer';

export default function updateSettings({ newSettings, auth, initialState }) {
  const [state, dispatch] = loadingReducer(loadingReducer, initialState);

  dispatch({ type: 'LOADING' });
  try {
    const idToken = auth.getIdToken();

    const response = fetch('/api/dashboard/set-settings', {
      method: 'POST',
      headers: new Headers({
        Authorization: `Bearer ${idToken}`,
        'Content-Type': 'application/json',
      }),
      body: JSON.stringify(newSettings),
    });

    // const jsonReponse = response.json();

    // TODO: Create Notification Toast
  } catch (error) {
    console.log('Error happened in decrypting token', error);
  }
  dispatch({ type: 'FINISHED' });
  return { isLoading: state.isLoading };
}

变成这样的组件,

function SettingsDetails() {
  const auth = useAuth();
  const { register, handleSubmit, errors } = useForm();
  const initialState = {
    isLoading: false,
  };
  // const settings = false
  const settings = getSettings(auth);

  const onSubmit = (data) => {
    console.log('Submitting..');
    const isLoading =updateSettings(data,initialState);
    return isLoading
  };  
 
  
  return (

    <div className="md:grid md:grid-cols-3 md:gap-6">
  <div className="md:col-span-1">
    <h3 className="text-lg font-medium leading-6 text-gray-900">
      Preferences
    </h3>
    <p className="mt-1 text-sm leading-5 text-gray-500">
      Set your Personal Preferences
    </p>
  </div>
  <div className="mt-5 md:mt-0 md:col-span-2">
    <form onSubmit={handleSubmit(onSubmit)}>
      <Dropdown
        data-testid = "power"
        registerInput={register}
        optionLabel="power"
        selectedOption={settings.power}
        optionName="power"
        allOptions={['ice', 'fire', 'Both']}
      />
.....
  <button
            className="inline-flex items-center justify-center px-5 py-2 border border-transparent text-base leading-6 font-medium rounded-md text-indigo-700 bg-indigo-100 hover:text-indigo-600 hover:bg-indigo-50 focus:outline-none focus:shadow-outline focus:border-indigo-300 transition duration-150 ease-in-out"
            // variant={props.buttonColor}
            // size={props.inputSize}
            type="submit"
            disabled={initialState.isLoading}
          >
            {initialState.isLoading ? (
              <>
                <span>Saving</span>
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  viewBox="0 0 24 24"
                  className="animate-spin h-4 w-4 ml-3 fill-current"
                >
                  <path d="M0 11c.511-6.158 5.685-11 12-11s11.489 4.842 12 11h-2.009c-.506-5.046-4.793-9-9.991-9s-9.485 3.954-9.991 9h-2.009zm21.991 2c-.506 5.046-4.793 9-9.991 9s-9.485-3.954-9.991-9h-2.009c.511 6.158 5.685 11 12 11s11.489-4.842 12-11h-2.009z" />
                </svg>
              </>
            ) : (
              <span>Save</span>
            )}
          </button>

我对尝试模拟此获取数据功能的最佳方法有点迷茫 - 有什么最佳实践吗?

我只想确保页面呈现,呈现来自 getdata 函数的数据,并在提交到表单时正确保存数据。真的很难在网上找到任何资源来通过这种方式。

目前我在运行测试时遇到此错误,

   Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
    1. You might have mismatching versions of React and the renderer (such as React DOM)
    2. You might be breaking the Rules of Hooks
    3. You might have more than one copy of React in the same app
    See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.

提前致谢,

使用新错误更新到当前测试(感谢到目前为止的帮助!)。模拟这些函数的测试现在可以工作了!我希望能够模拟函数本身以确保它们也能正常工作。

用于更新设置的加载减速器是这个 btw,

export default function loadingReducer(state, action) {
  switch (action.type) {
    case 'LOADING':
      return { isLoading: true };
    case 'FINISHED':
      return { isLoading: false };
    default:
      return state;
  }
}

1 个答案:

答案 0 :(得分:1)

我想尝试的是在我的测试中不导入 getSettings,而是模拟整个文件和钩子。 所以代替

import getSettings from 'components/onboarding/stages/useGetSettingsData.js'

做类似的事情

jest.mock('components/onboarding/stages/useGetSettingsData.js', () => {
      return {
          getSettings: jest.fn(() => {
            return {
              power: 'magical',
              potion: 'magilin',
              potion_times: '[]',
              potion_activity_times: '',
              gender: 'Male',
              age: '30',
             };
            });
          };
        });
    }

通过这种方式,您只需模拟整个 useGetSettingsData.js 文件,就可以测试您的组件更改。我希望这对你有用。