redux-saga/effects#select TypeScript Examples

The following examples show how to use redux-saga/effects#select. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.ts    From camus with GNU Affero General Public License v3.0 6 votes vote down vote up
function* doSetIceServers() {
    const manager: Manager = yield getContext('manager');
    const iceServers: IceServer[] = yield select((state) => state.iceServers);
    const servers = iceServers
        .filter((server) => {
            return server.enabled;
        })
        .map((server) => {
            return {
                urls: server.urls,
                username: server.username,
                credential: server.credential,
            };
        }) as IceServer[];

    try {
        yield apply(manager, manager.setIceServers, [servers]);
        yield put({ type: 'MANAGER_UPDATED' });
    } catch (err) {
        console.log(err);
        yield put({ type: 'MANAGER_ERROR', payload: err });
    }
}
Example #2
Source File: utils.ts    From marina with MIT License 6 votes vote down vote up
// create a saga "selector" (a generator) from a redux selector function
export function newSagaSelector<R>(selectorFn: (state: RootReducerState) => R) {
  return function* (): SagaGenerator<R> {
    const result = yield select(selectorFn);
    return customSagaParser(result);
  };
}
Example #3
Source File: sagas.ts    From waifusion-site with MIT License 6 votes vote down vote up
/* ACTIONS */
function* loadWaifusAction() {
  const waifus: Waifu[] = yield select(selectWaifus);
  const waifusCopy = [...waifus];
  const contractHelper = new ContractHelper();
  yield contractHelper.init();
  const _ownedWaifus: Waifu[] = yield contractHelper.getWaifus();
  yield put(setWaifuIndexes(_ownedWaifus.map((waifu: Waifu) => waifu.id)));
  for (let i = 0; i < _ownedWaifus.length; i++) {
    const waifuIds = waifus.map((waifu: Waifu) => waifu.id);
    if (waifuIds.indexOf(_ownedWaifus[i].id) === -1)
      waifusCopy.push(_ownedWaifus[i]);
    else waifusCopy[i] = _ownedWaifus[i];
  }
  waifusCopy.reverse();
  yield put(setWaifus(waifusCopy));
  yield put(completeLoadWaifus());
}
Example #4
Source File: saga.ts    From react-boilerplate-cra-template with MIT License 6 votes vote down vote up
/**
 * Github repos request/response handler
 */
export function* getRepos() {
  yield delay(500);
  // Select username from store
  const username: string = yield select(selectUsername);
  if (username.length === 0) {
    yield put(actions.repoError(RepoErrorType.USERNAME_EMPTY));
    return;
  }
  const requestURL = `https://api.github.com/users/${username}/repos?type=all&sort=updated`;

  try {
    // Call our request helper (see 'utils/request')
    const repos: Repo[] = yield call(request, requestURL);
    if (repos?.length > 0) {
      yield put(actions.reposLoaded(repos));
    } else {
      yield put(actions.repoError(RepoErrorType.USER_HAS_NO_REPO));
    }
  } catch (err: any) {
    if (err.response?.status === 404) {
      yield put(actions.repoError(RepoErrorType.USER_NOT_FOUND));
    } else if (err.message === 'Failed to fetch') {
      yield put(actions.repoError(RepoErrorType.GITHUB_RATE_LIMIT));
    } else {
      yield put(actions.repoError(RepoErrorType.RESPONSE_ERROR));
    }
  }
}
Example #5
Source File: index.ts    From slice-machine with Apache License 2.0 6 votes vote down vote up
function* trackOpenSetupDrawerSaga() {
  const framework: Frameworks = (yield select(getFramework)) as ReturnType<
    typeof getFramework
  >;
  const version: string = (yield select(getCurrentVersion)) as ReturnType<
    typeof getCurrentVersion
  >;

  void Tracker.get().trackSliceSimulatorSetup(framework, version);
}
Example #6
Source File: index.ts    From slice-machine with Apache License 2.0 6 votes vote down vote up
export function* failCheckSetupSaga() {
  const framework = (yield select(getFramework)) as ReturnType<
    typeof getFramework
  >;
  const isPreviewAvailableForFramework = (yield select(
    selectIsSimulatorAvailableForFramework
  )) as ReturnType<typeof selectIsSimulatorAvailableForFramework>;

  if (!isPreviewAvailableForFramework) {
    return;
  }

  const { length } = getStepperConfigurationByFramework(framework).steps;

  yield put(
    openSetupDrawerCreator({
      stepToOpen: length,
    })
  );
}
Example #7
Source File: sagas.ts    From slice-machine with Apache License 2.0 6 votes vote down vote up
export function* saveCustomTypeSaga() {
  try {
    const currentCustomType = (yield select(
      selectCurrentCustomType
    )) as ReturnType<typeof selectCurrentCustomType>;
    const currentMockConfig = (yield select(
      selectCurrentMockConfig
    )) as ReturnType<typeof selectCurrentMockConfig>;

    if (!currentCustomType || !currentMockConfig) {
      return;
    }

    yield call(saveCustomType, currentCustomType, currentMockConfig);
    void Tracker.get().trackCustomTypeSaved({
      id: currentCustomType.id,
      name: currentCustomType.label || currentCustomType.id,
      type: currentCustomType.repeatable ? "repeatable" : "single",
    });
    yield put(saveCustomTypeCreator.success());
    yield put(
      openToasterCreator({
        message: "Model & mocks have been generated successfully!",
        type: ToasterType.SUCCESS,
      })
    );
  } catch (e) {
    // Unknown errors
    yield put(
      openToasterCreator({
        message: "Internal Error: Custom type not saved",
        type: ToasterType.ERROR,
      })
    );
  }
}
Example #8
Source File: sagas.ts    From orangehrm-os-mobile with GNU General Public License v3.0 6 votes vote down vote up
function* setMultiAsyncStorage(action: SetMultiAction) {
  try {
    const initialStorageLoaded = yield select(selectStorageLoaded);
    // Avoid update async storage when executing `loadAsyncStorage` when application starts
    if (initialStorageLoaded.loaded) {
      const keys = Object.keys(action.keyValuePairs);
      yield all(
        keys.map((keyName) => {
          const key = <keyof Partial<StorageState>>keyName;
          storage.set(key, action.keyValuePairs[key]);
        }),
      );
    }
  } catch (error) {}
}
Example #9
Source File: saga.ts    From react-js-tutorial with MIT License 6 votes vote down vote up
export function* watchAndLog() {
  while (true) {
    const action = yield take("*");
    const state = yield select();

    // eslint-disable-next-line no-console
    console.log("action", action);
    // eslint-disable-next-line no-console
    console.log("state after", state);
  }
}
Example #10
Source File: saga.ts    From react-js-tutorial with MIT License 6 votes vote down vote up
export function* gameStateWatcher() {
  const data = yield select(selectors.game);

  const { moves, gameField } = data;

  const gameFieldLength = gameField.length * gameField[0].length;

  if (moves === 1) {
    yield put(actions.changeStatus(GameStatus.Play));
  }

  if (moves >= 5) {
    const firstPlayerWinCheck = getInfoAboutGameField(
      gameField,
      firstPlayerMark
    ).find(winChecker);

    if (firstPlayerWinCheck) {
      yield put(actions.changeStatus(GameStatus.GameOver));
      yield put(actions.setWinner(firstPlayerMark));
    }

    const secondPlayerWinCheck = getInfoAboutGameField(
      gameField,
      secondPlayerMark
    ).find(winChecker);

    if (secondPlayerWinCheck) {
      yield put(actions.changeStatus(GameStatus.GameOver));
      yield put(actions.setWinner(secondPlayerMark));
    }
  }

  if (moves === gameFieldLength) {
    yield put(actions.changeStatus(GameStatus.GameOver));
  }
}
Example #11
Source File: index.ts    From camus with GNU Affero General Public License v3.0 6 votes vote down vote up
function* doSetResolution({ payload }: PayloadAction<number>) {
    const resolution = payload;

    try {
        const localFeed: Feed = yield select((state) =>
            state.feeds.find((feed: Feed) => feed.id === 'local')
        );

        if (localFeed.videoStream) {
            const track = localFeed.videoStream.getVideoTracks()[0];
            const constraints = {
                height: { ideal: resolution },
                width: { ideal: (resolution * 4) / 3 },
            };
            yield apply(track, track.applyConstraints, [constraints]);
        }
        yield put({ type: 'RESOLUTION_UPDATED' });
    } catch (err) {
        console.error(err);
        yield put({ type: 'ERROR', payload: err });
    }
}
Example #12
Source File: sagas.ts    From orangehrm-os-mobile with GNU General Public License v3.0 5 votes vote down vote up
function* fetchApiDefinition(
  action: FetchMyInfoAction | FetchNewTokenFinishedAction,
) {
  try {
    // only continue generator if `INSTANCE_API_VERSION` key not available in storage
    if (action.type === FETCH_MY_INFO) {
      const apiDetails: ApiDetails = yield select(selectApiDetails);
      if (
        apiDetails[INSTANCE_API_VERSION] !== null ||
        apiDetails[INSTANCE_API_VERSION] !== undefined
      ) {
        return;
      }
    }

    const instanceUrl: string = yield selectInstanceUrl();
    const response: Response = yield call(getOpenApiDefinition, instanceUrl);
    const apiDefinition = yield call([response, response.json]);

    checkInstanceCompatibility(apiDefinition);
    checkRemovedEndpoints(apiDefinition);
    const usingDeprecatedEndpoints = checkDeprecatedEndpoints(apiDefinition);
    if (usingDeprecatedEndpoints) {
      yield showSnackMessage('Please Update the Application.', TYPE_WARN);
    }

    const apiVersion = apiDefinition?.info?.version;
    const apiPaths = Object.keys(getOpenApiDefinitionPaths(apiDefinition));
    yield storageSetMulti({
      [INSTANCE_API_VERSION]: apiVersion ? apiVersion : null,
      [INSTANCE_API_PATHS]: apiPaths ? JSON.stringify(apiPaths) : null,
    });
  } catch (error) {
    yield showSnackMessage(
      getMessageAlongWithGenericErrors(
        error,
        'Failed to Fetch API Definition.',
      ),
      TYPE_ERROR,
    );
  }
}
Example #13
Source File: auth.ts    From orangehrm-os-mobile with GNU General Public License v3.0 5 votes vote down vote up
selectEnabledModules = () => {
  return select(enabledModulesSelector);
}
Example #14
Source File: auth.ts    From orangehrm-os-mobile with GNU General Public License v3.0 5 votes vote down vote up
selectMyInfo = () => {
  return select(selectMyInfoSelector);
}
Example #15
Source File: storage.ts    From orangehrm-os-mobile with GNU General Public License v3.0 5 votes vote down vote up
selectInstanceUrl = () => {
  return select(instanceUrlSelector);
}
Example #16
Source File: storage.ts    From orangehrm-os-mobile with GNU General Public License v3.0 5 votes vote down vote up
selectAuthParams = () => {
  return select(authParamSelector);
}
Example #17
Source File: sagas.ts    From orangehrm-os-mobile with GNU General Public License v3.0 5 votes vote down vote up
function* fetchAttendanceConfiguration() {
  let attendanceConfigFetched: boolean = false;
  try {
    attendanceConfigFetched = yield select(
      selectAttendanceConfigurationFetched,
    );
    // To avoid unnecessary API fetches to get api configurations
    // Since the configurations does not change frequently
    if (attendanceConfigFetched) {
      const attendanceConfig: AttendanceConfiguration = yield select(
        selectAttendanceConfiguration,
      );
      yield put(fetchAttendanceConfigurationFinished({...attendanceConfig}));
      return;
    }

    yield openLoader();
    const response = yield apiCall(
      apiGetCall,
      prepare(API_ENDPOINT_ATTENDANCE_CONFIGURATION),
    );
    if (response.data) {
      yield put(fetchAttendanceConfigurationFinished(response.data));
    } else {
      yield showSnackMessage(
        getMessageAlongWithResponseErrors(
          response,
          'Failed to Fetch Attendance Configuration.',
        ),
        TYPE_ERROR,
      );
    }
  } catch (error) {
    yield showSnackMessage(
      getMessageAlongWithGenericErrors(
        error,
        'Failed to Fetch Attendance Configuration.',
      ),
      TYPE_ERROR,
    );
  } finally {
    if (!attendanceConfigFetched) {
      yield closeLoader();
    }
  }
}
Example #18
Source File: sagas.ts    From slice-machine with Apache License 2.0 5 votes vote down vote up
export function* pushCustomTypeSaga() {
  try {
    const currentCustomType = (yield select(
      selectCurrentCustomType
    )) as ReturnType<typeof selectCurrentCustomType>;

    if (!currentCustomType) {
      return;
    }

    yield call(pushCustomType, currentCustomType.id);
    void Tracker.get().trackCustomTypePushed({
      id: currentCustomType.id,
      name: currentCustomType.label || currentCustomType.id,
      type: currentCustomType.repeatable ? "repeatable" : "single",
    });
    yield put(pushCustomTypeCreator.success());
    yield put(
      openToasterCreator({
        message: "Model was correctly saved to Prismic!",
        type: ToasterType.SUCCESS,
      })
    );
  } catch (e) {
    if (axios.isAxiosError(e) && e.response) {
      // Auth error
      if (e.response.status === 403) {
        yield put(modalOpenCreator({ modalKey: ModalKeysEnum.LOGIN }));
        return;
      }
      // Other server errors
      if (e.response.status > 209) {
        yield put(
          openToasterCreator({
            // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
            message: e.response.data.reason,
            type: ToasterType.ERROR,
          })
        );
        return;
      }
    }

    // Unknown errors
    yield put(
      openToasterCreator({
        message: "Internal Error: Custom type not pushed",
        type: ToasterType.ERROR,
      })
    );
  }
}
Example #19
Source File: saga.ts    From mamori-i-japan-admin-panel with BSD 2-Clause "Simplified" License 5 votes vote down vote up
function* updateMessageSaga() {
  yield takeEvery(actionTypes.UPDATE_MESSAGE, function* _({
    payload,
  }: {
    type: string;
    payload: UpdatePrefectureRequestDto;
  }) {
    const { url, id } = payload;

    yield put({ type: loadingActionTypes.START_LOADING });

    yield call(getAccessTokenSaga);

    try {
      yield call(patchPrefecture, {
        id,
        message: url ? url : '',
      });

      const { listData } = yield select((state) => state.prefectureMessage);
      const { userAdminRole } = yield select((state) => state.auth);

      if (userAdminRole === 'PREFECTURE_ADMIN_ROLE') {
        listData[0].url = payload.url;
      } else {
        listData[parseInt(payload.id, 10)].url = payload.url;
      }

      yield put({
        type: actionTypes.UPDATE_MESSAGE_SUCCESS,
        payload: { listData },
      });

      yield put({
        type: feedbackActionTypes.SHOW_SUCCESS_MESSAGE,
        payload: { successMessage: 'submitSuccess' },
      });
    } catch (error) {
      yield put({
        type: feedbackActionTypes.SHOW_ERROR_MESSAGE,
        payload: { errorCode: error.status, errorMessage: error.error },
      });
    }

    yield put({ type: loadingActionTypes.END_LOADING });
  });
}
Example #20
Source File: authSaga.ts    From foodie with MIT License 5 votes vote down vote up
function* authSaga({ type, payload }: IAuthSaga) {
    switch (type) {
        case LOGIN_START:
            try {
                yield put(isAuthenticating(true));
                const { auth } = yield call(login, payload.email, payload.password);
                socket.emit('userConnect', auth.id);
                yield put(clearNewsFeed());
                yield put(loginSuccess(auth));
                yield put(isAuthenticating(false));
            } catch (e) {
                console.log(e);

                yield handleError(e);
            }
            break;
        case CHECK_SESSION:
            try {
                yield put(isAuthenticating(true));
                const { auth } = yield call(checkAuthSession);

                console.log('SUCCESS ', auth);
                yield put(loginSuccess(auth));
                yield put(isAuthenticating(false));
            } catch (e) {
                yield handleError(e);
            }
            break;
        case LOGOUT_START:
            try {
                const { auth } = yield select();
                yield put(isAuthenticating(true));
                yield call(logout);

                payload.callback && payload.callback();

                yield put(logoutSuccess());
                yield put(isAuthenticating(false));
                yield put(clearNewsFeed());
                yield put(clearChat());
                history.push(LOGIN);
                socket.emit('userDisconnect', auth.id);
            } catch (e) {
                yield handleError(e);
            }
            break;
        case REGISTER_START:
            try {
                yield put(isAuthenticating(true));

                const user: IUser = yield call(register, payload);

                socket.emit('userConnect', user.id);
                yield put(registerSuccess(user));
                yield put(isAuthenticating(false));
            }
            catch (e) {
                console.log('ERR', e);
                yield handleError(e);
            }
            break;
        default:
            return;
    }
}
Example #21
Source File: saga.test.ts    From oasis-wallet-web with Apache License 2.0 4 votes vote down vote up
describe('Wallet Sagas', () => {
  const validMnemonic =
    'abuse gown claw final toddler wedding sister parade useful typical spatial skate decrease bulk student manual cloth shove fat car little swamp tag ginger'
  const validPrivateKeyHex =
    '5f48e5a6fb243f5abc13aac7c56449afbc93be90ae38f10a0465bc82db954f17e75624c8d2cd9f062ce0331373a3be50ef0eccc5d257b4e2dea83a05506c7132'
  const addressHex = 'oasis1qz0k5q8vjqvu4s4nwxyj406ylnflkc4vrcjghuwk'
  // const addressMnemonic = 'oasis1qq5t7f2gecsjsdxmp5zxtwgck6pzpjmkvc657z6l'

  const providers: (EffectProviders | StaticProvider)[] = [[matchers.call.fn(getBalance), {}]]

  describe('Root Saga', () => {
    it('Should fork once open', () => {
      return expectSaga(rootWalletSaga)
        .withState({})
        .provide(providers)
        .dispatch(walletActions.openWalletFromMnemonic(validMnemonic))
        .fork(walletSaga)
        .silentRun(50)
    })

    it('Should open from mnemonic', () => {
      return expectSaga(rootWalletSaga)
        .provide(providers)
        .withState({})
        .dispatch(walletActions.openWalletFromMnemonic(validMnemonic))
        .fork(walletSaga)
        .put.actionType(walletActions.walletOpened.type)
        .put.actionType(walletActions.selectWallet.type)
        .silentRun(200)
    })

    it('Should open from private key', () => {
      return expectSaga(rootWalletSaga)
        .provide(providers)
        .withState({})
        .dispatch(walletActions.openWalletFromPrivateKey(validPrivateKeyHex))
        .fork(walletSaga)
        .put.actionType(walletActions.selectWallet.type)
        .silentRun(50)
    })

    it('Should open from ledger', () => {
      return expectSaga(rootWalletSaga)
        .provide(providers)
        .withState({})
        .dispatch(
          walletActions.openWalletsFromLedger([
            {
              address: addressHex,
              balance: { available: '0', debonding: '0', escrow: '0', total: '0' },
              path: [44, 474, 0, 0, 0],
              publicKey: '00',
              selected: true,
            },
          ]),
        )
        .fork(walletSaga)
        .put.actionType(walletActions.selectWallet.type)
        .silentRun(50)
    })

    it('Should close the wallet and wait for another open attempt', () => {
      return expectSaga(rootWalletSaga)
        .provide(providers)
        .withState({})
        .dispatch(walletActions.openWalletFromPrivateKey(validPrivateKeyHex))
        .fork(walletSaga)
        .put.actionType(walletActions.selectWallet.type)
        .dispatch(walletActions.closeWallet())
        .put(walletActions.walletClosed())
        .take(walletActions.openWalletFromMnemonic)
        .silentRun(50)
    })
  })

  it('Should redirect user when selecting a wallet', () => {
    return expectSaga(selectWallet, { type: '', payload: 1 })
      .provide([...providers, [select(selectActiveWallet), { address: addressHex } as Partial<Wallet>]])
      .put({ type: walletActions.walletSelected.type, payload: 1 })
      .run()
    // See `useRouteRedirects` tests for redirect after selectedWallet.
  })

  it('Should allow opening multiple wallets', () => {
    return expectSaga(rootWalletSaga)
      .provide(providers)
      .withState({})
      .dispatch(walletActions.openWalletFromPrivateKey(validPrivateKeyHex))
      .put.actionType(walletActions.walletOpened.type)
      .put.actionType(walletActions.walletSelected.type)
      .dispatch(walletActions.openWalletFromMnemonic(validMnemonic))
      .put.actionType(walletActions.walletOpened.type)
      .put.actionType(walletActions.walletSelected.type)
      .silentRun(50)
  })

  it('Should refresh balances on matching transaction', () => {
    return expectSaga(rootWalletSaga)
      .provide(providers)
      .withState({
        account: { address: 'sender' },
        wallet: {
          selectedWallet: 0,
          wallets: [{ address: 'sender', publicKey: '00' } as Partial<Wallet>],
        } as Partial<WalletState>,
      } as Partial<RootState>)
      .dispatch(transactionActions.transactionSent({ amount: 1, type: 'transfer', to: 'receiver' }))
      .call.fn(getBalance)
      .put.actionType(walletActions.updateBalance.type)
      .silentRun(50)
  })
})
Example #22
Source File: saga.test.ts    From oasis-wallet-web with Apache License 2.0 4 votes vote down vote up
describe('Staking Sagas', () => {
  const getAllValidators = jest.fn()
  const getDelegations = jest.fn()
  const nic = {
    stakingAccount: jest.fn(),
    stakingDebondingDelegationInfosFor: jest.fn(),
    stakingDelegationInfosFor: jest.fn(),
    schedulerGetValidators: jest.fn(),
  }

  const providers: (EffectProviders | StaticProvider)[] = [
    [matchers.call.fn(getExplorerAPIs), { getAllValidators, getDelegations }],
    [matchers.call.fn(getOasisNic), nic],
    [matchers.call.fn(now), new Date('2022').getTime()],
  ]
  const validAddress = 'oasis1qqty93azxp4qeft3krvv23ljyj57g3tzk56tqhqe'

  afterEach(() => {
    jest.resetAllMocks()
  })

  describe('Fetch Account', () => {
    it('Should load the delegations and validators', () => {
      getAllValidators.mockResolvedValue([
        { address: 'oasis1qqzz2le7nua2hvrkjrc9kc6n08ycs9a80chejmr7', escrow: 1000 },
        { address: 'dummy', escrow: 2000 },
      ] as Validator[])

      getDelegations.mockResolvedValue({
        delegations: fixtureDelegation,
        debonding: fixtureDebondingDelegation,
      })

      return (
        expectSaga(fetchAccount, stakingActions.fetchAccount(validAddress))
          .withState({})
          .provide(providers)
          .put.actionType(stakingActions.updateValidators.type)
          //@TODO check that we're loading everything in state
          .run()
      )
    })
  })

  describe('Validator details', () => {
    it('Should load the details regarding the selected validator', () => {
      nic.stakingAccount.mockResolvedValue({})

      return expectSaga(stakingSaga)
        .withState({})
        .provide(providers)
        .dispatch(stakingActions.validatorSelected('oasis1qqzz2le7nua2hvrkjrc9kc6n08ycs9a80chejmr7'))
        .put.actionType(stakingActions.updateValidatorDetails.type)
        .silentRun()
    })

    it('Should keep and augment relevant bounds', async () => {
      nic.stakingAccount.mockResolvedValue({
        escrow: {
          commission_schedule: {
            bounds: [
              {
                rate_min: qty(1000),
                rate_max: qty(2000),
                start: 500,
              },
              {
                rate_min: qty(1000),
                rate_max: qty(2000),
                start: 200,
              },
              {
                rate_min: qty(1000),
                rate_max: qty(2000),
                start: 0,
              },
            ],
          },
        },
      })

      const result = await expectSaga(stakingSaga)
        .withState(initialState)
        .withReducer(stakingReducer)
        .provide([...providers, [select(selectEpoch), 300]])
        .dispatch(stakingActions.validatorSelected('oasis1qqzz2le7nua2hvrkjrc9kc6n08ycs9a80chejmr7'))
        .put.actionType(stakingActions.updateValidatorDetails.type)
        .silentRun()

      const finalState: StakingState = result.storeState
      const bounds = finalState.selectedValidatorDetails!.scheduledCommissionBounds

      // The "older" 0-200 bounds should have been filtered out
      expect(bounds).toHaveLength(2)
      expect(bounds).toEqual([
        { epochEnd: 499, epochStart: 200, lower: 0.01, upper: 0.02 },
        { epochEnd: undefined, epochStart: 500, lower: 0.01, upper: 0.02 },
      ])
    })
  })

  describe('Fetch validators fallbacks', () => {
    it('should load validators when switching network', () => {
      getAllValidators.mockResolvedValue([{ address: 'fromApi' }] as Validator[])
      return expectSaga(refreshValidators)
        .withState({
          network: { selectedNetwork: 'testnet' },
          staking: { validators: { network: 'mainnet', list: [{ address: 'existing' }] } },
        } as RootState)
        .provide(providers)
        .put(
          stakingActions.updateValidators({
            timestamp: new Date('2022').getTime(),
            network: 'testnet',
            list: [{ address: 'fromApi' }] as Validator[],
          }),
        )
        .run()
    })

    it('should use fallback on mainnet', () => {
      getAllValidators.mockRejectedValue('apiFailed')
      const getMainnetDumpValidatorsMock = {
        dump_timestamp: 1647996761337,
        dump_timestamp_iso: '2022-03-23T00:52:41.337Z',
        list: [
          {
            rank: 1,
            address: 'oasis1qq3xrq0urs8qcffhvmhfhz4p0mu7ewc8rscnlwxe',
            name: 'stakefish',
            nodeAddress: 'oasis1qrg52ccz4ts6cct2qu4retxn7kkdlusjh5pe74ar',
            status: 'active',
            _expectedStatus: 'active' as const,
          },
          {
            rank: 2,
            address: 'oasis1qqekv2ymgzmd8j2s2u7g0hhc7e77e654kvwqtjwm',
            name: 'BinanceStaking',
            nodeAddress: 'oasis1qqp0h2h92eev7nsxgqctvuegt8ge3vyg0qyluc4k',
            status: 'active',
            _expectedStatus: 'inactive' as const,
          },
        ],
      }
      nic.schedulerGetValidators.mockResolvedValue([
        {
          // oasis1qrg52ccz4ts6cct2qu4retxn7kkdlusjh5pe74ar
          id: oasis.misc.fromHex('91e7768ae47cd1641d6f883b97e3ea6d0286240bc3e3e2953c5c2e0dce6753a3'),
          voting_power: 1,
        },
      ] as oasis.types.SchedulerValidator[])
      jest
        .spyOn(console, 'error')
        .mockImplementationOnce(message => expect(message).toBe('get validators list failed'))

      return expectSaga(refreshValidators)
        .withState({
          network: { selectedNetwork: 'mainnet' },
        } as RootState)
        .provide([...providers, [matchers.call.fn(getMainnetDumpValidators), getMainnetDumpValidatorsMock]])
        .put(
          stakingActions.updateValidatorsError({
            error: 'apiFailed',
            validators: {
              timestamp: getMainnetDumpValidatorsMock.dump_timestamp,
              network: 'mainnet',
              list: getMainnetDumpValidatorsMock.list.map((v, ix) => ({
                ...v,
                status: v._expectedStatus,
              })),
            },
          }),
        )
        .run()
    })
  })
})
Example #23
Source File: saga.test.ts    From react-js-tutorial with MIT License 4 votes vote down vote up
describe("Game saga", () => {
  it("gameStateWatcher detect the first move", () => {
    return expectSaga(gameStateWatcher)
      .provide([
        [
          select(selectors.game),
          {
            moves: 1,
            gameField: [
              ["", "", ""],
              ["", firstPlayerMark, ""],
              ["", "", ""],
            ],
          },
        ],
      ])
      .put(actions.changeStatus(GameStatus.Play))
      .run();
  });
  it("gameStateWatcher detect the full field", () => {
    return expectSaga(gameStateWatcher)
      .provide([
        [
          select(selectors.game),
          {
            moves: 9,
            gameField: [
              [firstPlayerMark, firstPlayerMark, secondPlayerMark],
              [secondPlayerMark, secondPlayerMark, firstPlayerMark],
              [firstPlayerMark, secondPlayerMark, firstPlayerMark],
            ],
          },
        ],
      ])
      .put(actions.changeStatus(GameStatus.GameOver))
      .run();
  });
  it("gameStateWatcher started to check winner", () => {
    return expectSaga(gameStateWatcher)
      .provide([
        [
          select(selectors.game),
          {
            moves: 5,
            gameField: [
              ["", secondPlayerMark, firstPlayerMark],
              ["", secondPlayerMark, firstPlayerMark],
              ["", secondPlayerMark, ""],
            ],
          },
        ],
      ])
      .put(actions.changeStatus(GameStatus.GameOver))
      .put(actions.setWinner(secondPlayerMark))
      .run();
  });
  it("watchAndLog", () => {
    const saga = testSaga(watchAndLog);
    saga
      .next()
      .take("*")
      .next()
      .select()
      .restart()
      .next()
      .take("*")
      .next()
      .select()
      .back(2)
      .next()
      .take("*")
      .next()
      .select()
      .next()
      .finish();
  });
  it("watchFirstThreeAction", () => {
    const saga = testSaga(watchFirstThreeAction);
    saga.next().take("*").next().take("*").next().take("*").next().isDone();
  });
});