ajax-запрос не выполняется при запуске теста с диаграммами мрамора - PullRequest
0 голосов
/ 18 октября 2018

Я использую rxjs v6 и redux-observable v1

У меня есть эпик, который отправляет запрос на сервер и пытаюсь протестировать эпик как в doc .Когда я запускаю тестовую эпопею перед отправкой запроса, посылаю 3 действия, и это видно по результату теста, но когда эпопея подходит к концу теста вызова ajax.Чтобы смоделировать запрос, я использую nock lib.

Epic:

import { ofType } from 'redux-observable'
import { of, merge, from } from 'rxjs'
import {
  switchMap,
  catchError
} from 'rxjs/operators'

import { apiRequest, handleAsyncError$ } from '../../async/lib'
import { actions as asyncActions } from '../../async'
import { LOADING_TYPES } from '../../async/constants'
import { actions as authActions } from '../reducer'

const setSignInLoading = (status) => of(asyncActions.setLoading({ type: LOADING_TYPES.signIn, status }))

const emitSignInPending = () => merge(
  setSignInLoading(true),
  of(authActions.signInPending())
)

const emitSignInSuccess = (payload) => merge(
  setSignInLoading(false),
  of(authActions.signInSuccess(payload))
)

const emitSignInFailed = (payload) => merge(
  setSignInLoading(false),
  handleAsyncError$({
    action: authActions.signInFailure,
    payload
  })
)

// --------- ajax call -----------
const startSignIn = (payload) => apiRequest({
  path: '/auth/signin/manager',
  method: 'post',
  body: payload
})

const mapSignInAction$ = ({ payload }) => merge(
  // --------- emit 3 actions -----------
  emitSignInPending(),
  // --------- finish test -----------
  startSignIn(payload)
    .pipe(
      switchMap((emitSignInSuccess)),
      catchError(emitSignInFailed)
    )
)

const signInEpic = action$ =>
  action$
    .pipe(
      ofType(authActions.signIn),
      switchMap(mapSignInAction$)
    )

export default signInEpic

apiRequest:

import { get } from 'lodash'
import { throwError } from 'rxjs'
import { ajax } from 'rxjs/ajax'
import { map, catchError } from 'rxjs/operators'

import { API } from '../../../../config'

const apiRequest = ({ token, path, method, body }) => {
  const settings = {
    url: `${API}${path}`,
    headers: { 'Content-Type': 'application/json' },
    responseType: 'json',
    crossDomain: true,
    method,
    body
  }

  if (token) {
    settings.headers['Authorization'] = `Bearer: ${token}`
  }

  return ajax(settings)
    .pipe(
      catchError((request) => {
        const error = get(request, 'response.error')

        return throwError({ error, request })
      }),
      map(({ response }) => response)
    )
}

export default apiRequest

Тест: nock (API) .post('/ auth / signin / manager') .reply (200, ответ)

  scheduler.run(({ hot, expectObservable }) => {
    const source = hot('-a|', { a: authActions.signIn({ email: 'manager', password: '123123' }) })
    const output$ = epic(source)

    expectObservable(output$).toBe('-(bcde)', {
      b: asyncAction.setLoading({ type: 'signIn', status: true }),
      c: authActions.signInPending(),
      d: asyncAction.setLoading({ type: 'signIn', status: false }),
      e: authActions.signInSuccess(response)
    })
  })

Результат:

Expected:

    [{"frame": 1, "notification": {"error": undefined, "hasValue": true, "kind": "N", "value": {"error": false, "payload": {"status": true, "type": "signIn"}, "type": "[8] async/setLoading"}}}, {"frame": 1, "notification": {"error": undefined, "hasValue": true, "kind": "N", "value": {"error": false, "payload": undefined, "type": "[3] [2] auth/signIn/pending"}}}, {"frame": 1, "notification": {"error": undefined, "hasValue": true, "kind": "N", "value": {"error": false, "payload": {"status": false, "type": "signIn"}, "type": "[8] async/setLoading"}}}, {"frame": 1, "notification": {"error": undefined, "hasValue": true, "kind": "N", "value": {"error": false, "payload": {"data": {"token": "skldjf", "user": {"email": "manager", "id": 2, "passwordHash": "asdf", "passwordSalt": "6819c23dc7", "role": {"name": "user"}, "roleId": 1}}}, "type": "[4] [2] auth/signIn/success"}}}]

Received:

    [{"frame": 1, "notification": {"error": undefined, "hasValue": true, "kind": "N", "value": {"error": false, "payload": {"status": true, "type": "signIn"}, "type": "[8] async/setLoading"}}}, {"frame": 1, "notification": {"error": undefined, "hasValue": true, "kind": "N", "value": {"error": false, "payload": undefined, "type": "[3] [2] auth/signIn/pending"}}}]

1 Ответ

0 голосов
/ 19 октября 2018

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

it('return token and user 2', async (done) => {
  const response = {...}

  nock(API)
    .post('/auth/signin/manager')
    .reply(200, response)

  const source = authActions.signIn({ email: 'manager', password: '123123' })
  const action$ = ActionsObservable.of(source)

  epic(action$).pipe(toArray()).subscribe((actions) => {
    expect(actions).toEqual([
      asyncAction.setLoading({ type: 'signIn', status: true }),
      authActions.signInPending(),
      asyncAction.setLoading({ type: 'signIn', status: false }),
      authActions.signInSuccess(response)
    ])

    done()
  })

})

Пожалуйста, напишите, если вы нашли, как это сделать с помощью мраморных диаграмм.

...