Search code examples
unit-testingreduxredux-saga

Redux Saga: Throw and stop generator


I'm writing a generator. I'm testing it with RITEway. It checks if window.ethereum is defined. If its not, it should throw and stop. Basically it should satisfy the following tests:

describe('handle initialize Web3 saga', async assert => {
  global.window = {}

  assert({
    given: 'nothing, the window object',
    should: 'have no property called Web3',
    actual: window.web3,
    expected: undefined
  })

  const gen = cloneableGenerator(handleInitializeWeb3)()

  {
    // The important parts are in this block scope
    const clone = gen.clone()

    assert({
      given: 'window.ethereum undefined',
      should: 'throw',
      actual: clone.next().value.message,
      expected: '[WARNING]: window.ethereum has no provider!'
    })

    assert({
      given: 'nothing',
      should: 'be done',
      actual: clone.next().done,
      expected: true
    })
  }

  class Provider {}

  window.ethereum = new Provider()

  // ... more tests
})

Here is how I tried implementing it.

function* handleInitializeWeb3() {
  if (!window.ethereum) {
    yield new Error('[WARNING]: window.ethereum has no provider!')
  }
  // ... more yields
}

but this saga doesn't stop. The test where it should: 'be done' fails and the saga gives back the values from the yields outside of the if statement. How can I have these tests pass and the saga stop when the error is thrown?


Solution

  • yielding an error instance acts the same as yielding any other value (i.e. the generator keeps running). If you want to stop the generator you should throw new Error(... like in a normal function.

    If for some reason you don't want to throw and do in fact want to yield an error instance and then stop, simply return; after you've yielded the error.