text: /**
   * Test injectors
   */
  
  import { memoryHistory } from 'react-router-dom';
  import { put } from 'redux-saga/effects';
  
  import configureStore from '../../configureStore';
  import getInjectors, { ejectSagaFactory, injectSagaFactory } from '../sagaInjectors';
  import { DAEMON, ONCE_TILL_UNMOUNT, RESTART_ON_REMOUNT } from '../constants';
  
  function* testSaga() {
    yield put({ type: 'TEST', payload: 'yup' });
  }
  
  describe('injectors', () => {
    const originalNodeEnv = process.env.NODE_ENV;
    let store;
    let injectSaga;
    let ejectSaga;
  
    describe('getInjectors', () => {
      beforeEach(() => {
        store = configureStore({}, memoryHistory);
      });
  
      it('should return injectors', () => {
        expect(getInjectors(store)).toEqual(
          expect.objectContaining({
            injectSaga: expect.any(Function),
            ejectSaga: expect.any(Function),
          }),
        );
      });
  
      it('should throw if passed invalid store shape', () => {
        Reflect.deleteProperty(store, 'dispatch');
  
        expect(() => getInjectors(store)).toThrow();
      });
    });
  
    describe('ejectSaga helper', () => {
      beforeEach(() => {
        store = configureStore({}, memoryHistory);
        injectSaga = injectSagaFactory(store, true);
        ejectSaga = ejectSagaFactory(store, true);
      });
  
      it('should check a store if the second argument is falsy', () => {
        const eject = ejectSagaFactory({});
  
        expect(() => eject('test')).toThrow();
      });
  
      it('should not check a store if the second argument is true', () => {
        Reflect.deleteProperty(store, 'dispatch');
        injectSaga('test', { saga: testSaga });
  
        expect(() => ejectSaga('test')).not.toThrow();
      });
  
      it("should validate saga's key", () => {
        expect(() => ejectSaga('')).toThrow();
        expect(() => ejectSaga(1)).toThrow();
      });
  
      it('should cancel a saga in RESTART_ON_REMOUNT mode', () => {
        const cancel = jest.fn();
        store.injectedSagas.test = { task: { cancel }, mode: RESTART_ON_REMOUNT };
        ejectSaga('test');
  
        expect(cancel).toHaveBeenCalled();
      });
  
      it('should not cancel a daemon saga', () => {
        const cancel = jest.fn();
        store.injectedSagas.test = { task: { cancel }, mode: DAEMON };
        ejectSaga('test');
  
        expect(cancel).not.toHaveBeenCalled();
      });
  
      it('should ignore saga that was not previously injected', () => {
        expect(() => ejectSaga('test')).not.toThrow();
      });
  
      it("should remove non daemon saga's descriptor in production", () => {
        process.env.NODE_ENV = 'production';
        injectSaga('test', { saga: testSaga, mode: RESTART_ON_REMOUNT });
        injectSaga('test1', { saga: testSaga, mode: ONCE_TILL_UNMOUNT });
  
        ejectSaga('test');
        ejectSaga('test1');
  
        expect(store.injectedSagas.test).toBe('done');
        expect(store.injectedSagas.test1).toBe('done');
        process.env.NODE_ENV = originalNodeEnv;
      });
  
      it("should not remove daemon saga's descriptor in production", () => {
        process.env.NODE_ENV = 'production';
        injectSaga('test', { saga: testSaga, mode: DAEMON });
        ejectSaga('test');
  
        expect(store.injectedSagas.test.saga).toBe(testSaga);
        process.env.NODE_ENV = originalNodeEnv;
      });
  
      it("should not remove daemon saga's descriptor in development", () => {
        injectSaga('test', { saga: testSaga, mode: DAEMON });
        ejectSaga('test');
  
        expect(store.injectedSagas.test.saga).toBe(testSaga);
      });
    });
  
    describe('injectSaga helper', () => {
      beforeEach(() => {
        store = configureStore({}, memoryHistory);
        injectSaga = injectSagaFactory(store, true);
        ejectSaga = ejectSagaFactory(store, true);
      });
  
      it('should check a store if the second argument is falsy', () => {
        const inject = injectSagaFactory({});
  
        expect(() => inject('test', testSaga)).toThrow();
      });
  
      it('it should not check a store if the second argument is true', () => {
        Reflect.deleteProperty(store, 'dispatch');
  
        expect(() => injectSaga('test', { saga: testSaga })).not.toThrow();
      });
  
      it("should validate saga's key", () => {
        expect(() => injectSaga('', { saga: testSaga })).toThrow();
        expect(() => injectSaga(1, { saga: testSaga })).toThrow();
      });
  
      it("should validate saga's descriptor", () => {
        expect(() => injectSaga('test')).toThrow();
        expect(() => injectSaga('test', { saga: 1 })).toThrow();
        expect(() => injectSaga('test', { saga: testSaga, mode: 'testMode' })).toThrow();
        expect(() => injectSaga('test', { saga: testSaga, mode: 1 })).toThrow();
        expect(() => injectSaga('test', { saga: testSaga, mode: RESTART_ON_REMOUNT })).not.toThrow();
        expect(() => injectSaga('test', { saga: testSaga, mode: DAEMON })).not.toThrow();
        expect(() => injectSaga('test', { saga: testSaga, mode: ONCE_TILL_UNMOUNT })).not.toThrow();
      });
  
      it('should pass args to saga.run', () => {
        const args = {};
        store.runSaga = jest.fn();
        injectSaga('test', { saga: testSaga }, args);
  
        expect(store.runSaga).toHaveBeenCalledWith(testSaga, args);
      });
  
      it('should not start daemon and once-till-unmount sagas if were started before', () => {
        store.runSaga = jest.fn();
  
        injectSaga('test1', { saga: testSaga, mode: DAEMON });
        injectSaga('test1', { saga: testSaga, mode: DAEMON });
        injectSaga('test2', { saga: testSaga, mode: ONCE_TILL_UNMOUNT });
        injectSaga('test2', { saga: testSaga, mode: ONCE_TILL_UNMOUNT });
  
        expect(store.runSaga).toHaveBeenCalledTimes(2);
      });
  
      it('should start any saga that was not started before', () => {
        store.runSaga = jest.fn();
  
        injectSaga('test1', { saga: testSaga });
        injectSaga('test2', { saga: testSaga, mode: DAEMON });
        injectSaga('test3', { saga: testSaga, mode: ONCE_TILL_UNMOUNT });
  
        expect(store.runSaga).toHaveBeenCalledTimes(3);
      });
  
      it('should restart a saga if different implementation for hot reloading', () => {
        const cancel = jest.fn();
        store.injectedSagas.test = { saga: testSaga, task: { cancel } };
        store.runSaga = jest.fn();
  
        function* testSaga1() {
          yield put({ type: 'TEST', payload: 'yup' });
        }
  
        injectSaga('test', { saga: testSaga1 });
  
        expect(cancel).toHaveBeenCalledTimes(1);
        expect(store.runSaga).toHaveBeenCalledWith(testSaga1, undefined);
      });
  
      it('should not cancel saga if different implementation in production', () => {
        process.env.NODE_ENV = 'production';
        const cancel = jest.fn();
        store.injectedSagas.test = {
          saga: testSaga,
          task: { cancel },
          mode: RESTART_ON_REMOUNT,
        };
  
        function* testSaga1() {
          yield put({ type: 'TEST', payload: 'yup' });
        }
  
        injectSaga('test', { saga: testSaga1, mode: DAEMON });
  
        expect(cancel).toHaveBeenCalledTimes(0);
        process.env.NODE_ENV = originalNodeEnv;
      });
  
      it('should save an entire descriptor in the saga registry', () => {
        injectSaga('test', { saga: testSaga, foo: 'bar' });
        expect(store.injectedSagas.test.foo).toBe('bar');
      });
    });
  });
  