1

Suppose I have an API that return user detail: /api/get_user/1

{
  "status": 200,
  "data": {
    "username": "username1",
    "email": "username@email.com"
  }
}

And a "main function" like this:

function main (sources) {
  const request$ = sources.ACTIONS
    .filter(action => action.type === 'GET_USER_REQUEST')
    .map(action => action.payload)
    .map(payload => ({
      category: 'GET_USER_REQUEST',
      url: `${BASE_URL}/api/get_user/${payload.userId}`,
      method: 'GET'
    }))

  const action$ = sources.HTTP
    .select('GET_USER_REQUEST')
    .flatten()
    .map(response => response.data)

  const sinks = {
    HTTP: request$,
    LOG: action$
  }
  return sinks
}

For testing the "ACTION" source, I can simply made an xstream observable

test.cb('Test main function', t => {

  const actionStream$ = xs.of({
    type: 'GET_USER_REQUEST',
    payload: { userId: 1 }
  })
  const sources = { ACTION: actionStream$ }
  const expectedResult = {
    category: 'GET_USER_REQUEST',
    url: `${BASE_URL}/api/get_user/${payload.userId}`,
    method: 'GET'
  }

  main(sources).HTTP.addEventListener({
    next: (data) => {
      t.deepEqual(data, expectedResult)
    },
    error: (error) => {
      t.fail(error)
    },
    complete: () => {
      t.end()
    }
  })

})

The question is. Is it possible to do the same thing (using plan xstream observable) to test cycle-http driver without a helper from something like nock? Or is there a better way to test something like this?

apiep
  • 25
  • 6

1 Answers1

1

You can mock out the HTTP source like so:

test.cb('Test main function', t => {
  const actionStream$ = xs.of({
    type: 'GET_USER_REQUEST',
    payload: { userId: 1 }
  })

  const response$ = xs.of({
    data: {
      status: 200,
      data: {
        username: "username1",
        email: "username@email.com"
      }
    }
  });

  const HTTP = {
    select (category) {
      // if you have multiple categories you could return different streams depending on the category
      return xs.of(response$);
    }
  }

  const sources = { ACTION: actionStream$, HTTP }

  const expectedResult = {
    category: 'GET_USER_REQUEST',
    url: `${BASE_URL}/api/get_user/${payload.userId}`,
    method: 'GET'
  }

  main(sources).HTTP.addEventListener({
    next: (data) => {
      t.deepEqual(data, expectedResult)
    },
    error: (error) => {
      t.fail(error)
    },
    complete: () => {
      t.end()
    }
  })

})

Really, we should have a mockHTTPSource helper to make this a bit easier. I have opened an issue to that effect. https://github.com/cyclejs/cyclejs/issues/567

If you want to test that certain things happen at the correct time, you could use this pattern in conjunction with @cycle/time.

http://github.com/cyclejs/time

Widdershin
  • 316
  • 3
  • 10