swpp201901-team06 / swpp-project

1 stars 2 forks source link

signUp molecule: Mock a debounced function #55

Closed lionminhu closed 5 years ago

lionminhu commented 5 years ago

For the signIn molecule test, I'm passing a mock function of handleChange as props so that I can simulate an input change event within the email input field and the nickname input field. I see that handleChange is actually called within a debounced function, such that the mock function is called 300 milliseconds after the input change event: https://github.com/swpp201901-team06/swpp-project/blob/19720b3f061d6103dd64715cb9b20bd9bb2b926a/FD_frontend/src/components/pages/SignUpPage/molecules/signUp/index.js#L50-L59

I haven't found a good way to make the test wait for 300 ms before proceeding to check whether the mock function has been called.

theNocturni commented 5 years ago

snapshot testing은 어떻게 되는지 잘 모르겠는데 혹시 https://stackoverflow.com/questions/52224447/jest-unit-test-for-a-debounce-function 에 나오는 이런거 적용 가능해?

lionminhu commented 5 years ago

The stack post uses the useFakeTimers function from sinon. I wonder, however, whether we really want to use Sinon alongside with Jest, since both of them are unit testing frameworks.

By the way, below is my (messy) attempt at simulating the change, if this even works. https://github.com/swpp201901-team06/swpp-project/blob/57cd7f76e55e97f28bb8e1dcb239b388d77b51db/FD_frontend/src/components/pages/SignUpPage/molecules/signUp/index.test.js#L30-L36

theNocturni commented 5 years ago

아 미안 저거 말고

https://stackoverflow.com/questions/54318926/how-can-i-test-a-debounce-function-with-jest-enzyme

lionminhu commented 5 years ago

Tried the following according to that stack post:

      jest.useFakeTimers()
      const wrapper = mount(<SignUp {...props} />)
      const emailInput = wrapper.find('input').at(0)
      emailInput.instance().value = 'test_email@github.com'
      emailInput.simulate('change')
      jest.runTimersToTime(1000)
      expect(mockHandleChange.mock.calls.length).toBe(1)

Note that according to the Enzyme docs, the function advanceTimersByTime was named as something else prior to version 22.0.0:

renamed from runTimersToTime to advanceTimersByTime in Jest 22.0.0

and we're using Jest 19.

The test still fails:

● signUp molecule test › When DCButton is pressed › should call the mock duplicate check function

    expect(received).toBe(expected)

    Expected value to be (using ===):
      1
    Received:
      0

      at Object.<anonymous> (src/components/pages/SignUpPage/molecules/signUp/index.test.js:35:50)
      at handle (node_modules/worker-farm/lib/child/index.js:44:8)
      at process.<anonymous> (node_modules/worker-farm/lib/child/index.js:51:3)
      at process.emit (events.js:196:13)
      at emit (internal/child_process.js:860:12)
      at processTicksAndRejections (internal/process/task_queues.js:84:9)

At this point, I'm suspecting that emailInput.simulate('change') does not actually trigger the onChange attribute.

lionminhu commented 5 years ago

What happens when we just avoid debouncing the handleChange call?

lionminhu commented 5 years ago

Changing

const handleEmailChange = debounce(() => {
    if (email.value) {
      handleChange('email', email.value)
    }
  }, 300)
  const handleNicknameChange = debounce(() => {
    if (nickname.value) {
      handleChange('username', nickname.value)
    }
  }, 300)

to

  const handleEmailChange = () => {
    if (email.value) {
      handleChange('email', email.value)
    }
  }

  const handleNicknameChange = () => {
    if (nickname.value) {
      handleChange('username', nickname.value)
    }
  }

won't change the functionality too much, other than that the email check and the nickname check occurs every time a single character is pressed or removed. This causes backend API to be called excessively many times.

The test passes though, so I'm confident now that it's the matter of mocking the clock tick by 300ms (or longer).

lionminhu commented 5 years ago

I'm thinking of using setTimeout function instead of debouncing the function, since that's what the Jest docs for mocking timers is based on.

lionminhu commented 5 years ago

In the most recent commit (https://github.com/swpp201901-team06/swpp-project/commit/9ebae2f46f2eba1d2b842ab35096636291d4f5d4), I've changed the implementation from debounce to setTimeout: https://github.com/swpp201901-team06/swpp-project/blob/9ebae2f46f2eba1d2b842ab35096636291d4f5d4/FD_frontend/src/components/pages/SignUpPage/molecules/signUp/index.js#L49-L58 and fixed the test accordingly: https://github.com/swpp201901-team06/swpp-project/blob/9ebae2f46f2eba1d2b842ab35096636291d4f5d4/FD_frontend/src/components/pages/SignUpPage/molecules/signUp/index.test.js#L28-L40

The test passes, and I've manually confirmed that the email check/nickname check occurs some time (probably after 300ms) after changing the input form.