react-i18next#I18nextProvider TypeScript Examples

The following examples show how to use react-i18next#I18nextProvider. 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: InlineDatePicker.tsx    From ant-extensions with MIT License 7 votes vote down vote up
InlineDatePicker: React.FC<DatePickerProps> = React.forwardRef<
  React.Component,
  DatePickerProps
>((props, ref) => {
  const refContainer = useRef<HTMLDivElement>(null);
  const refPicker = useRef<HTMLDivElement>(document.createElement("div"));

  useLayoutEffect(() => {
    if (refContainer.current) {
      refContainer.current.appendChild(refPicker.current);
    }
  }, []);

  return (
    <I18nextProvider i18n={i18next}>
      <div ref={refContainer} className="ant-ext-sd__inlinePicker">
        <DatePicker
          {...props}
          ref={ref}
          open
          inputReadOnly
          getPopupContainer={() => refPicker.current}
        />
      </div>
    </I18nextProvider>
  );
})
Example #2
Source File: index.tsx    From ant-extensions with MIT License 6 votes vote down vote up
I18nProvider: React.FC<{ locale: string }> = ({ children, locale }) => {
  useEffect(() => {
    console.log("=====> change locale", locale);
    i18next.changeLanguage(locale).then(() => {
      document.documentElement.lang = locale;
      document.documentElement.dir = i18next.dir();
    });
  }, [locale]);
  return <I18nextProvider i18n={i18next}>{children}</I18nextProvider>;
}
Example #3
Source File: renderer.tsx    From TidGi-Desktop with Mozilla Public License 2.0 6 votes vote down vote up
function App(): JSX.Element {
  const theme = useThemeObservable();

  return (
    <ThemeProvider theme={theme?.shouldUseDarkColors === true ? darkTheme : lightTheme}>
      <StyledEngineProvider injectFirst>
        <LocalizationProvider dateAdapter={DateFnsUtils}>
          <CssBaseline />
          <React.Suspense fallback={<div />}>
            <I18nextProvider i18n={i18n}>
              <RootStyle>
                <Pages />
              </RootStyle>
            </I18nextProvider>
          </React.Suspense>
        </LocalizationProvider>
      </StyledEngineProvider>
    </ThemeProvider>
  );
}
Example #4
Source File: App.tsx    From metro-fare with MIT License 6 votes vote down vote up
App = () => {
  return (
    <>
      <I18nextProvider i18n={i18n}>
        <BrowserRouter>
          <TripProvider>
            <MapProvider>
              <DrawerProvider>
                <RealApp />
              </DrawerProvider>
            </MapProvider>
          </TripProvider>
        </BrowserRouter>
      </I18nextProvider>
    </>
  );
}
Example #5
Source File: TestContext.tsx    From longwave with MIT License 6 votes vote down vote up
export function TestContext(props: {
  gameState: GameState;
  playerId: string;
  children: ReactChild;
  setState?: (newState: Partial<GameState>) => void;
}) {
  return (
    <GameModelContext.Provider
      value={BuildGameModel(
        props.gameState,
        props.setState || jest.fn(),
        props.playerId,
        () => ["left", "right"],
        () => {}
      )}
    >
      <Suspense fallback={<div>Loading...</div>}>
        <I18nextProvider i18n={i18n}>{props.children}</I18nextProvider>
      </Suspense>
    </GameModelContext.Provider>
  );
}
Example #6
Source File: ReceiveModal.test.tsx    From raspiblitz-web with MIT License 6 votes vote down vote up
describe("ReceiveModal", () => {
  test("Retrieves new on-chain address on click of on-chain button", async () => {
    const { container } = render(
      <I18nextProvider i18n={i18n}>
        <ReceiveModal onClose={() => {}} />
      </I18nextProvider>
    );

    await act(async () => {
      (await screen.findByText("wallet.on_chain")).click();
    });

    await waitFor(() => expect(container.querySelector("svg")).toBeDefined());
  });
});
Example #7
Source File: TransactionCard.test.tsx    From raspiblitz-web with MIT License 6 votes vote down vote up
describe("TransactionCard", () => {
  test("if info is being displayed if transactions are empty", async () => {
    render(
      <I18nextProvider i18n={i18n}>
        <TransactionCard {...props} />
      </I18nextProvider>
    );

    expect(screen.getByText("tx.transactions_none")).toBeInTheDocument();
  });
});
Example #8
Source File: AppCard.test.tsx    From raspiblitz-web with MIT License 6 votes vote down vote up
describe("AppCard", () => {
  test("display install button if installed is false", async () => {
    render(
      <I18nextProvider i18n={i18n}>
        <AppCard {...basicProps} installed={false} />
      </I18nextProvider>
    );
    expect(await screen.findByText("apps.install")).toBeDefined();
  });

  test("display open button if installed & address is available", async () => {
    render(
      <I18nextProvider i18n={i18n}>
        <AppCard {...basicProps} address={"addr"} installed={true} />
      </I18nextProvider>
    );
    expect(await screen.findByText("apps.open")).toBeDefined();
  });

  test("display no_page button if installed & address is not available", async () => {
    render(
      <I18nextProvider i18n={i18n}>
        <AppCard {...basicProps} installed={true} />
      </I18nextProvider>
    );
    expect(await screen.findByText("apps.no_page")).toBeDefined();
  });
});
Example #9
Source File: App.tsx    From BlinkWebUI with GNU General Public License v3.0 6 votes vote down vote up
render(): JSX.Element {
        return (
            <>
                <CssBaseline />
                <ThemeProvider theme={theme}>
                    <I18nextProvider i18n={i18n}>
                        <Router>
                            <MainLayout />
                        </Router>
                    </I18nextProvider>
                </ThemeProvider>
            </>
        );
    }
Example #10
Source File: UnlockModal.test.tsx    From raspiblitz-web with MIT License 5 votes vote down vote up
describe("UnlockModal", () => {
  const setup = () => {
    render(
      <I18nextProvider i18n={i18n}>
        <UnlockModal onClose={handleClose} />
      </I18nextProvider>
    );
  };

  test("renders", () => {
    setup();

    const input = screen.getByPlaceholderText("forms.validation.unlock.pass_c");
    expect(input).toHaveClass("input-underline");
    expect(input).toBeInTheDocument();
  });

  // https://github.com/cstenglein/raspiblitz-web/issues/234
  // skipped due to react v18 update
  test.skip("should enable button if input is not empty", async () => {
    setup();

    const input = screen.getByPlaceholderText("forms.validation.unlock.pass_c");

    const button = screen.getByRole("button");

    expect(button).toBeDisabled();

    userEvent.type(input, "1234");
    expect(await screen.findByRole("button")).toBeEnabled();
  });

  // https://github.com/cstenglein/raspiblitz-web/issues/234
  // skipped due to react v18 update
  test.skip("should show text on wrong password", async () => {
    server.use(
      rest.post("/api/v1/lightning/unlock-wallet", (_, res, ctx) => {
        return res(ctx.status(401));
      })
    );

    setup();

    const input = screen.getByPlaceholderText("forms.validation.unlock.pass_c");
    userEvent.type(input, "1234");
    userEvent.click(screen.getByText("wallet.unlock"));

    expect(await screen.findByText("login.invalid_pass")).toBeInTheDocument();
  });

  // https://github.com/cstenglein/raspiblitz-web/issues/234
  // skipped due to react v18 update
  test.skip("should display unlocking text on unlock", async () => {
    server.use(
      rest.post("/api/v1/lightning/unlock-wallet", (_, res, ctx) => {
        return res(ctx.status(200));
      })
    );

    setup();

    const input = screen.getByPlaceholderText("forms.validation.unlock.pass_c");
    userEvent.type(input, "1234");
    userEvent.click(await screen.findByText("wallet.unlock"));

    expect(await screen.findByText("wallet.unlocking")).toBeInTheDocument();
  });
});
Example #11
Source File: index.tsx    From landy-react-template with MIT License 5 votes vote down vote up
App = () => (
  <BrowserRouter>
    <I18nextProvider i18n={i18n}>
      <Router />
    </I18nextProvider>
  </BrowserRouter>
)
Example #12
Source File: index.tsx    From website-docs with MIT License 5 votes vote down vote up
export default function NotFoundPage({ data }: { data: AllLocales }) {
  const { docInfo, searchValue } = useSelector(state => state) as any
  const dispatch = useDispatch()

  const handleSetSearchValue = (value: string) =>
    dispatch(setSearchValue(value))

  const pathname = typeof window === 'undefined' ? '' : window.location.pathname
  const context = useContext(I18nextContext)
  const language = useMemo(() => {
    const lang = pathname.slice(1)?.split('/')?.pop() || ''
    switch (lang) {
      case 'zh':
        return 'zh'
      case 'ja':
        return 'ja'
      default:
        break
    }
    return 'en'
  }, [pathname])
  const i18n = useMemo(() => {
    const i18n = i18next.createInstance()

    const resources = data.locales.edges.reduce((acc, cur) => {
      acc[cur.node.language] = { [cur.node.ns]: JSON.parse(cur.node.data) }
      return acc
    }, {} as Record<string, Record<string, any>>)

    i18n.init({
      resources,
      lng: language,
      fallbackLng: 'en',
      react: {
        useSuspense: false,
      },
    })
    return i18n
  }, [language, data])

  return (
    <I18nextProvider i18n={i18n}>
      <I18nextContext.Provider value={{ ...context, language }}>
        <Layout>
          <Seo title="404 Not Found" noindex />
          <div className={styles.container}>
            <div className={clsx('markdown-body', styles.left)}>
              <h1 className={clsx(styles.title)}>
                {<Trans i18nKey="doc404.title" />}
              </h1>
              <div>{<Trans i18nKey="doc404.youMayWish" />}</div>
              <ul className={clsx(styles.optionsContainer)}>
                <li>
                  {
                    <Trans
                      i18nKey="doc404.goToDocHome"
                      components={[<Link to="/" />]}
                    />
                  }
                </li>
                <li>{<Trans i18nKey="doc404.searchDoc" />}</li>
              </ul>
              <div className={styles.searchInput}>
                <SearchInput
                  docInfo={docInfo}
                  searchValue={searchValue}
                  setSearchValue={handleSetSearchValue}
                />
              </div>
            </div>
            <div className={clsx(styles.right)}></div>
          </div>
        </Layout>
      </I18nextContext.Provider>
    </I18nextProvider>
  )
}
Example #13
Source File: _app.tsx    From nextclade with MIT License 5 votes vote down vote up
export function MyApp({ Component, pageProps, router }: AppProps) {
  const queryClient = useMemo(() => new QueryClient(), [])
  const { store } = useMemo(() => configureStore(), [])
  const fallback = useMemo(() => <Loading />, [])

  useEffect(() => {
    if (process.env.NODE_ENV !== 'development' && router.pathname === '/results') {
      void router.replace('/') // eslint-disable-line no-void
    }

    void router.prefetch('/') // eslint-disable-line no-void
    void router.prefetch('/results') // eslint-disable-line no-void
  }, [router])

  return (
    <Suspense fallback={fallback}>
      <ReactReduxProvider store={store}>
        <RecoilRoot>
          <ThemeProvider theme={theme}>
            <MDXProvider components={mdxComponents}>
              <Plausible domain={DOMAIN_STRIPPED} />
              <QueryClientProvider client={queryClient}>
                <I18nextProvider i18n={i18n}>
                  <ErrorBoundary>
                    <Suspense>
                      <RecoilStateInitializer />
                    </Suspense>
                    <Suspense fallback={fallback}>
                      <SEO />
                      <Component {...pageProps} />
                      <ErrorPopup />
                      <ReactQueryDevtools initialIsOpen={false} />
                    </Suspense>
                  </ErrorBoundary>
                </I18nextProvider>
              </QueryClientProvider>
            </MDXProvider>
          </ThemeProvider>
        </RecoilRoot>
      </ReactReduxProvider>
    </Suspense>
  )
}
Example #14
Source File: TreePage.tsx    From nextclade with MIT License 5 votes vote down vote up
function TreePageDisconnected({ treeMeta }: TreePageProps) {
  const isDataFromGisaid = useMemo(
    () => treeMeta?.dataProvenance?.some((provenance) => provenance.name?.toLowerCase() === 'gisaid'),
    [treeMeta],
  )

  return (
    <LayoutResults>
      <Container>
        <Header>
          <HeaderLeft>
            <ButtonBack />
          </HeaderLeft>

          <HeaderCenter />
        </Header>

        <MainContent>
          <AuspiceContainer>
            <I18nextProvider i18n={i18nAuspice}>
              <SidebarContainer>
                <Sidebar />
              </SidebarContainer>
              <TreeContainer>
                <TreeTopPanel>
                  <FiltersSummaryWrapper>
                    <FiltersSummary />
                  </FiltersSummaryWrapper>
                  {isDataFromGisaid && (
                    <LogoGisaidWrapper>
                      <LogoGisaid />
                    </LogoGisaidWrapper>
                  )}
                </TreeTopPanel>
                <Tree />
              </TreeContainer>
            </I18nextProvider>
          </AuspiceContainer>
        </MainContent>
      </Container>
    </LayoutResults>
  )
}
Example #15
Source File: wrapPageElement.tsx    From gatsby-plugin-react-i18next with MIT License 5 votes vote down vote up
withI18next = (i18n: I18n, context: I18NextContext) => (children: any) => {
  return (
    <I18nextProvider i18n={i18n}>
      <I18nextContext.Provider value={context}>{children}</I18nextContext.Provider>
    </I18nextProvider>
  );
}
Example #16
Source File: TestWrapper.tsx    From ant-extensions with MIT License 5 votes vote down vote up
TestWrapper: React.FC = ({ children }) => {
  return <I18nextProvider i18n={i18next}>{children}</I18nextProvider>;
}
Example #17
Source File: FronteggProvider.tsx    From frontegg-react with MIT License 5 votes vote down vote up
FeState: FC<FeProviderProps> = (props) => {
  const history = useHistory();
  const storeRef = useRef<any>({});
  const location = useLocation();
  const baseName = isSSR
    ? ''
    : window.location.pathname.substring(0, window.location.pathname.lastIndexOf(location.pathname));

  const onRedirectTo =
    props.onRedirectTo ??
    ((_path: string, opts?: RedirectOptions) => {
      let path = _path;
      if (path.startsWith(baseName)) {
        path = path.substring(baseName.length);
      }
      if (opts?.preserveQueryParams) {
        path = `${path}${window.location.search}`;
      }
      if (opts?.refresh && !isSSR) {
        window.Cypress ? history.push(path) : (window.location.href = path);
      } else {
        opts?.replace ? history.replace(path) : history.push(path);
      }
    });
  ContextHolder.setOnRedirectTo(onRedirectTo);

  const store = useMemo(
    () =>
      props.store ??
      createFronteggStore(
        { context: props.context },
        storeRef.current,
        false,
        {
          ...(props.plugins?.find((n) => n.storeName === authStoreName)?.preloadedState ?? {}),
          onRedirectTo,
        },
        {
          audits: {
            context: props.context,
            ...props.context.auditsOptions,
            ...(props.plugins?.find((n) => n.storeName === 'audits')?.preloadedState ?? {}),
          } as any,
        }
      ),
    [props.store]
  );

  useEffect(
    () => () => {
      try {
        (storeRef.current as any)?.store.destroy?.();
      } catch (e) {}
    },
    []
  );

  /* for Cypress tests */
  if (!isSSR && window.Cypress) {
    window.cypressHistory = history;
  }

  return (
    <Provider context={FronteggStoreContext} store={store}>
      <I18nextProvider i18n={i18n}>
        <FePlugins {...props} />
      </I18nextProvider>
    </Provider>
  );
}
Example #18
Source File: Provider.tsx    From nosgestesclimat-site with MIT License 5 votes vote down vote up
export default function Provider({
	tracker = new Tracker(),
	reduxMiddlewares,
	initialStore,
	onStoreCreated,
	children,
	sitePaths = {} as SitePaths,
	dataBranch,
	rulesURL,
}: ProviderProps) {
	const history = useMemo(() => createBrowserHistory(), [])
	useEffect(() => {
		tracker?.connectToHistory(history)
		return () => {
			tracker?.disconnectFromHistory()
		}
	})

	const storeEnhancer = composeEnhancers(
		applyMiddleware(
			// Allows us to painlessly do route transition in action creators
			thunk.withExtraArgument({
				history,
				sitePaths,
			}),
			...(reduxMiddlewares ?? [])
		)
	)

	// Hack: useMemo is used to persist the store across hot reloads.
	const store = useMemo(() => {
		return createStore(reducers, initialStore, storeEnhancer)
	}, [])
	onStoreCreated?.(store)

	const iframeCouleur =
		new URLSearchParams(document?.location.search.substring(1)).get(
			'couleur'
		) ?? undefined

	return (
		// If IE < 11 display nothing
		<ReduxProvider store={store}>
			<RulesProvider dataBranch={dataBranch} rulesURL={rulesURL}>
				<ThemeColorsProvider
					color={iframeCouleur && decodeURIComponent(iframeCouleur)}
				>
					<IframeOptionsProvider tracker={tracker}>
						<TrackerProvider value={tracker}>
							<SitePathProvider value={sitePaths}>
								<I18nextProvider i18n={i18next}>
									<Router history={history}>
										<>{children}</>
									</Router>
								</I18nextProvider>
							</SitePathProvider>
						</TrackerProvider>
					</IframeOptionsProvider>
				</ThemeColorsProvider>
			</RulesProvider>
		</ReduxProvider>
	)
}
Example #19
Source File: SwitchTxType.test.tsx    From raspiblitz-web with MIT License 5 votes vote down vote up
describe("SwitchTxType", () => {
  test("txType: lightning", async () => {
    const handeTxTypeChangeMock = jest.fn();

    render(
      <I18nextProvider i18n={i18n}>
        <SwitchTxType
          invoiceType={TxType.LIGHTNING}
          onTxTypeChange={handeTxTypeChangeMock}
        />
      </I18nextProvider>
    );

    const buttonLn = screen.getByText("home.lightning");
    const buttonOnChain = screen.getByText("wallet.on_chain");

    expect(buttonLn).toBeDisabled();
    expect(buttonOnChain).not.toBeDisabled();
    buttonOnChain.click();

    expect(handeTxTypeChangeMock).toHaveBeenCalledTimes(1);
    expect(handeTxTypeChangeMock).toHaveBeenCalledWith(TxType.ONCHAIN);
  });

  test("txType: onchain", async () => {
    const handeTxTypeChangeMock = jest.fn();

    render(
      <I18nextProvider i18n={i18n}>
        <SwitchTxType
          invoiceType={TxType.ONCHAIN}
          onTxTypeChange={handeTxTypeChangeMock}
        />
      </I18nextProvider>
    );

    const buttonLn = screen.getByText("home.lightning");
    const buttonOnChain = screen.getByText("wallet.on_chain");

    expect(buttonLn).not.toBeDisabled();
    expect(buttonOnChain).toBeDisabled();
    buttonLn.click();

    expect(handeTxTypeChangeMock).toHaveBeenCalledTimes(1);
    expect(handeTxTypeChangeMock).toHaveBeenCalledWith(TxType.LIGHTNING);
  });
});
Example #20
Source File: SendLN.test.tsx    From raspiblitz-web with MIT License 5 votes vote down vote up
setup = () => {
  render(
    <I18nextProvider i18n={i18n}>
      <SendLN {...basicProps} />
    </I18nextProvider>
  );
}
Example #21
Source File: InlineRangePicker.tsx    From ant-extensions with MIT License 5 votes vote down vote up
InlineRangePicker: React.FC<RangePickerProps> = React.forwardRef<
  React.Component,
  RangePickerProps
>(({ value, ...props }, ref) => {
  const refContainer = useRef<HTMLDivElement>(null);
  const refRangePicker = useRef<AnyObject>(null);
  const refPicker = useRef<HTMLDivElement>(document.createElement("div"));

  useEffect(() => {
    if (typeof ref === "function") {
      ref(refRangePicker.current);
    } else if (ref) {
      ref.current = refRangePicker.current;
    }
  }, [ref]);

  useLayoutEffect(() => {
    if (refContainer.current) {
      refContainer.current.appendChild(refPicker.current);
    }
  }, []);

  const [_value, setValue] = useState<AnyObject>([null, null]);
  useEffect(() => {
    setValue(value || [null, null]);
  }, [value]);
  const doUpdate = useCallback((v) => {
    setValue(v);
  }, []);

  const resetValue = useCallback(
    (e: AnyObject) => {
      if (
        _value[0] &&
        _value[1] &&
        (e.target.classList.contains("ant-picker-content") ||
          e.target.classList.contains("ant-picker-cell-inner"))
      ) {
        setValue([null, null]);
        setTimeout(() => refRangePicker.current && refRangePicker.current.focus(), 10);
      }
      return true;
    },
    [_value]
  );

  return (
    <I18nextProvider i18n={i18next}>
      <div ref={refContainer} className="ant-ext-sd__inlinePicker" onMouseDownCapture={resetValue}>
        <RangePicker
          {...props}
          open
          ref={refRangePicker}
          inputReadOnly
          value={_value as AnyObject}
          onCalendarChange={doUpdate}
          getPopupContainer={() => refPicker.current}
        />
      </div>
    </I18nextProvider>
  );
})
Example #22
Source File: InputField.test.tsx    From raspiblitz-web with MIT License 5 votes vote down vote up
describe("InputField", () => {
  test("render with placeholder", async () => {
    render(
      <I18nextProvider i18n={i18n}>
        <InputField {...basicProps} placeholder="A yellow fruit" />
      </I18nextProvider>
    );

    const input = await screen.findByLabelText("Banana Label");
    await waitFor(() => expect(input).toHaveClass("input-underline"));
    expect(input).toBeInTheDocument();
    expect(screen.getByPlaceholderText("A yellow fruit")).toBeInTheDocument();
  });

  test("render with error-message", async () => {
    render(
      <I18nextProvider i18n={i18n}>
        <InputField
          {...basicProps}
          errorMessage={{ type: "required", message: "Banana required!" }}
        />
      </I18nextProvider>
    );

    const input = await screen.findByLabelText("Banana Label");
    await waitFor(() => expect(input).toHaveClass("input-error"));
    expect(input).toBeInTheDocument();
    expect(screen.getByText("Banana required!")).toBeInTheDocument();
  });

  test("prop inputRightAddon", async () => {
    render(
      <I18nextProvider i18n={i18n}>
        <InputField {...basicProps} inputRightAddon="Right add-on text" />
      </I18nextProvider>
    );

    expect(screen.getByText("Right add-on text")).toBeInTheDocument();
  });

  test("prop inputRightElement", async () => {
    render(
      <I18nextProvider i18n={i18n}>
        <InputField
          {...basicProps}
          inputRightElement={<button>Click me!</button>}
        />
      </I18nextProvider>
    );

    expect(screen.getByText("Click me!")).toBeInTheDocument();
  });
});
Example #23
Source File: TagPicker.tsx    From ant-extensions with MIT License 5 votes vote down vote up
TagPicker: React.FC<AnyObject> = ({
  value,
  onChange,
  onVisibleChange,
  readOnly,
  disabled,
  pickerEl: E
}) => {
  const {
    i18n: { language }
  } = useTranslation(I18nKey);

  const refDropdown = useRef<typeof Popover>(null);
  const [visible, setVisible] = useState(false);

  const [_value, setValue] = useState(value);

  const isDisabled = useMemo(() => disabled || readOnly, [disabled, readOnly]);

  useEffect(() => {
    setValue(value);
  }, [value]);
  const doUpdate = useCallback(
    (v: DateValue) => {
      setValue(v);
      setVisible(false);
      onChange && onChange(v);
    },
    [onChange]
  );

  const toggleVisible = useCallback(
    (v) => {
      if (!isDisabled) {
        setVisible(v);
        onVisibleChange && onVisibleChange(v);
      }
    },
    [onVisibleChange, isDisabled]
  );
  const displayLabel = useMemo(
    () => (value && !!language ? parseDateLabel(value.toString()) : ""),
    [value, language]
  );

  return (
    <I18nextProvider i18n={i18next}>
      <Tooltip overlayClassName="ant-ext-sd__tooltip" title={DateUtils.toString(_value)}>
        <Popover
          ref={refDropdown}
          visible={visible}
          destroyTooltipOnHide
          onVisibleChange={toggleVisible}
          overlayClassName="ant-ext-sd__popover"
          content={!readOnly && <E dropdown={refDropdown} value={value} onChange={doUpdate} />}
          trigger="click"
          placement="bottomLeft"
        >
          <Tag
            color="blue"
            icon={<FieldTimeOutlined />}
            className="ant-ext-sd__tag"
            data-testid="input-el"
          >
            {displayLabel}
          </Tag>
        </Popover>
      </Tooltip>
    </I18nextProvider>
  );
}
Example #24
Source File: App.test.tsx    From raspiblitz-web with MIT License 5 votes vote down vote up
describe("App", () => {
  afterEach(() => {
    server.resetHandlers();
  });

  test("should route to /setup if setup is not done", async () => {
    server.use(
      rest.get("/api/v1/setup/status", (_, res, ctx) => {
        return res(
          ctx.status(200),
          ctx.json({
            setupPhase: "STARTING",
            state: "",
            message: "",
          })
        );
      })
    );

    render(
      <I18nextProvider i18n={i18n}>
        <BrowserRouter>
          <App />
        </BrowserRouter>
      </I18nextProvider>
    );
    await waitFor(() => expect(mockedUsedNavigate).toHaveBeenCalledTimes(1));
  });

  test("should route to /login if setup is done", async () => {
    server.use(
      rest.get("/api/v1/setup/status", (_, res, ctx) => {
        return res(
          ctx.status(200),
          ctx.json({
            setupPhase: "DONE",
            state: "",
            message: "",
          })
        );
      })
    );
    render(
      <I18nextProvider i18n={i18n}>
        <BrowserRouter>
          <App />
        </BrowserRouter>
      </I18nextProvider>
    );
    await waitFor(() => expect(mockedUsedNavigate).toHaveBeenCalledTimes(0));
  });
});
Example #25
Source File: Main.tsx    From clearflask with Apache License 2.0 4 votes vote down vote up
render() {
    const Router = (windowIso.isSsr ? StaticRouter : BrowserRouter) as React.ElementType;

    // Redirect www to homepage
    if (windowIso.location.hostname.startsWith('www.')) {
      return (<RedirectIso to={windowIso.location.origin.replace(`www.`, '')} />);
    }

    const isSelfHost = detectEnv() === Environment.PRODUCTION_SELF_HOST;
    const isParentDomain = windowIso.location.hostname === windowIso.parentDomain
      || (!isProd() && windowIso.location.hostname === 'localhost');

    const showSite = isParentDomain && !isSelfHost;
    const showProject = !showSite;
    const showDashboard = isParentDomain || isSelfHost;

    if (showSite || showDashboard) {
      trackingImplicitConsent();
    }

    return (
      <ErrorBoundary showDialog>
        <React.StrictMode>
          <I18nextProvider i18n={this.props.i18n}>
            <StylesProvider injectFirst>
              <MuiThemeProvider theme={this.theme}>
                <MuiSnackbarProvider notistackRef={notistackRef}>
                  <CssBaseline />
                  <ServerErrorNotifier />
                  <CaptchaChallenger />
                  <RemoveSsrCss />
                  <CrowdInInlineEditing />
                  <div style={{
                    minHeight: windowIso.isSsr ? undefined : this.theme.vh(100),
                    display: 'flex',
                    flexDirection: 'column',
                    background: this.theme.palette.background.default,
                  }}>
                    <Router
                      {...(windowIso.isSsr ? {
                        location: this.props.ssrLocation,
                        context: this.props.ssrStaticRouterContext,
                      } : {})}
                    >
                      <ScrollAnchor scrollOnNavigate />
                      <Route path='/' render={routeProps => {
                        trackingBlock(() => {
                          ReactGA.set({ page: routeProps.location.pathname + routeProps.location.search });
                          ReactGA.pageview(routeProps.location.pathname + routeProps.location.search);
                        });
                        return null;
                      }} />
                      <Route render={routeProps => routeProps.location.pathname.startsWith('/embed-status') ? null : (
                        <EnvironmentNotifier key='env-notifier' />
                      )} />
                      <Switch>
                        {[
                          (
                            <Route key='api-docs' path='/api' render={props => (
                              <NoSsr>
                                <ApiDocs />
                              </NoSsr>
                            )} />
                          ),
                          ...(!isProd() ? [(
                            <Route key='mock-oauth-provider-bathtub' path='/bathtub/authorize' render={props => (
                              <Provider store={ServerAdmin.get().getStore()}>
                                <BathtubOauthProvider />
                              </Provider>
                            )} />
                          )] : []),
                          ...(showDashboard ? [(
                            <Route key='dashboard' path="/dashboard/:path?/:subPath*" render={props => (
                              <Provider store={ServerAdmin.get().getStore()}>
                                <SentryIdentifyAccount />
                                <SetMaxAge val={0 /* If you want to cache, don't cache if auth is present in URL */} />
                                <NoSsr>
                                  <Dashboard {...props} />
                                </NoSsr>
                                <IntercomWrapperMain suppressBind />
                                <HotjarWrapperMain />
                              </Provider>
                            )} />
                          ), (
                            <Route key='invoice' path="/invoice/:invoiceId" render={props => (
                              <Provider store={ServerAdmin.get().getStore()}>
                                <SentryIdentifyAccount />
                                <SetMaxAge val={0} />
                                <Invoice invoiceId={props.match.params['invoiceId']} />
                              </Provider>
                            )} />
                          ), (
                            <Route key='enter' exact path='/:type(login|signup|invitation|coupon)/:id([a-z0-9]*)?' render={props => (
                              <Provider store={ServerAdmin.get().getStore()}>
                                <SetMaxAge val={0} />
                                <SetTitle title={props.match.params['type'] === 'login'
                                  ? 'Login'
                                  : (props.match.params['type'] === 'signup'
                                    ? 'Sign up'
                                    : (props.match.params['type'] === 'invitation'
                                      ? 'Invitation'
                                      : 'Coupon'))} />
                                <AccountEnterPage
                                  type={props.match.params['type']}
                                  invitationId={props.match.params['type'] === 'invitation' ? props.match.params['id'] : undefined}
                                  couponId={props.match.params['type'] === 'coupon' ? props.match.params['id'] : undefined}
                                />
                              </Provider>
                            )} />
                          )] : []),
                          ...(showProject ? [(
                            <Route key='embed-status' path="/embed-status/post/:postId" render={props => (
                              <>
                                <SetMaxAge val={24 * 60 * 60} />
                                <PostStatus
                                  {...props}
                                  postId={props.match.params['postId'] || ''}
                                />
                              </>
                            )} />
                          ), (
                            <Route key='app' path='/' render={props => (
                              <>
                                <SetMaxAge val={60} />
                                <App slug={windowIso.location.hostname} {...props} />
                              </>
                            )} />
                          )] : []),
                          ...(showSite ? [(
                            <Route key='site' path='/' render={props => (
                              <Provider store={ServerAdmin.get().getStore()}>
                                <SentryIdentifyAccount />
                                <SetMaxAge val={24 * 60 * 60} />
                                <Site {...props} />
                                <IntercomWrapperMain />
                                <HotjarWrapperMain />
                              </Provider>
                            )} />
                          )] : []),
                        ]}
                      </Switch>
                    </Router>
                  </div>
                </MuiSnackbarProvider>
              </MuiThemeProvider>
            </StylesProvider>
          </I18nextProvider>
        </React.StrictMode>
      </ErrorBoundary>
    );
  }
Example #26
Source File: index.tsx    From ant-extensions with MIT License 4 votes vote down vote up
ContextProvider: React.FC<Partial<ISearchProps & IFilterProps>> = ({
  children,
  fields = [],
  filters: _filters = [],
  query: _query = "",
  onQueryChange,
  onFilterAdded,
  onFilterUpdate,
  onFilterRemoved,
  onFilterChanged,
  onSearch
}) => {
  const [filters, setFilters] = useState<IFilterObject[]>([]);
  const [query, setQuery] = useState<string>("");

  useEffect(() => {
    Array.isArray(_filters) && setFilters(_filters);
  }, [_filters]);
  useEffect(() => {
    setQuery(_query);
  }, [_query]);

  const updateQuery = useCallback(
    (q: string) => {
      setQuery(q);
      onQueryChange && onQueryChange(q);
    },
    [onQueryChange]
  );

  const doSearch = () => {
    onSearch &&
      onSearch({
        filters,
        query
      });
  };

  const addFilter = (filter: IFilterObject) => {
    const newFilters = [...filters, filter];
    setFilters([...filters, filter]);
    onFilterAdded && onFilterAdded(filter);
    onFilterChanged && onFilterChanged(newFilters);
  };

  const updateFilter = (index: number, filter: Partial<IFilterObject>) => {
    const newFilters = [...filters];
    const oldFilter = filters[index];
    newFilters.splice(index, 1, {
      ...oldFilter,
      ...filter
    } as AnyObject);
    setFilters(newFilters);
    onFilterUpdate &&
      onFilterUpdate({
        ...oldFilter,
        ...filter
      } as AnyObject);
    onFilterChanged && onFilterChanged(newFilters);
  };

  const removeFilter = (index: number) => {
    const newFilters = [...filters];
    const [filter] = newFilters.splice(index, 1);
    setFilters(newFilters);
    onFilterRemoved && onFilterRemoved(filter);
    onFilterChanged && onFilterChanged(newFilters);
  };

  const enableAll = (value: boolean) => {
    const newFilters = filters.map((f) => (f.required ? f : { ...f, active: value }));
    setFilters(newFilters);
    onFilterChanged && onFilterChanged(newFilters);
  };

  const toggleExclude = () => {
    const newFilters = filters.map((f) => (f.required ? f : { ...f, negative: !f.negative }));
    setFilters(newFilters);
    onFilterChanged && onFilterChanged(newFilters);
  };

  const removeAll = () => {
    const newFilters = filters.filter((f) => f.required);
    setFilters(newFilters);
    onFilterChanged && onFilterChanged(newFilters);
  };

  return (
    <I18nextProvider i18n={i18next}>
      <Context.Provider
        value={{
          filters,
          fields,
          query,
          updateQuery,
          doSearch,
          addFilter,
          updateFilter,
          removeFilter,
          enableAll,
          toggleExclude,
          removeAll
        }}
      >
        {children}
      </Context.Provider>
    </I18nextProvider>
  );
}
Example #27
Source File: SendOnChain.test.tsx    From raspiblitz-web with MIT License 4 votes vote down vote up
describe("SendOnChain", () => {
  const setup = () => {
    render(
      <I18nextProvider i18n={i18n}>
        <SendOnChain {...basicProps} />
      </I18nextProvider>
    );
  };

  test("render", async () => {
    setup();

    expect(screen.getByText("wallet.send_onchain")).toBeInTheDocument();

    expect(screen.getByLabelText("wallet.address")).toBeInTheDocument();
    expect(screen.getByLabelText("wallet.amount")).toBeInTheDocument();
    expect(screen.getByLabelText("tx.fee")).toBeInTheDocument();
    expect(screen.getByLabelText("tx.comment")).toBeInTheDocument();

    expect(
      screen.getByRole("button", { name: "wallet.confirm" })
    ).not.toBeDisabled();
  });

  // https://github.com/cstenglein/raspiblitz-web/issues/234
  // skipped due to react v18 update
  test.skip("validates the input for empty value", async () => {
    setup();

    expect(
      screen.getByRole("button", { name: "wallet.confirm" })
    ).not.toBeDisabled();

    userEvent.click(screen.getByRole("button", { name: "wallet.confirm" }));

    await waitFor(() =>
      expect(screen.getByLabelText("wallet.address")).toHaveClass("input-error")
    );
    expect(
      screen.getByText("forms.validation.chainAddress.required")
    ).toBeInTheDocument();
    await waitFor(() =>
      expect(screen.getByLabelText("tx.fee")).toHaveClass("input-error")
    );
    expect(
      screen.getByText("forms.validation.chainFee.required")
    ).toBeInTheDocument();
  });

  // https://github.com/cstenglein/raspiblitz-web/issues/234
  // skipped due to react v18 update
  test.skip("validates the address-input for BTC address format", async () => {
    setup();

    let addressInput = screen.getByLabelText("wallet.address");

    userEvent.clear(addressInput);
    userEvent.type(addressInput, "abc123456789");

    addressInput = await screen.findByLabelText("wallet.address");

    await waitFor(() => expect(addressInput).toHaveClass("input-error"));
    expect(
      screen.getByText("forms.validation.chainAddress.patternMismatch")
    ).toBeInTheDocument();

    userEvent.clear(addressInput);
    userEvent.type(addressInput, "bc1");

    await waitFor(() => expect(addressInput).toHaveClass("input-error"));
    expect(
      screen.getByText("forms.validation.chainAddress.patternMismatch")
    ).toBeInTheDocument();
  });

  // https://github.com/cstenglein/raspiblitz-web/issues/234
  // skipped due to react v18 update
  test.skip("validates amount is lower than balance", async () => {
    setup();

    const amountInput = screen.getByLabelText(
      "wallet.amount"
    ) as HTMLInputElement;

    userEvent.clear(amountInput);
    userEvent.type(amountInput, "999");

    userEvent.click(await screen.findByText("wallet.confirm"));

    await waitFor(() => expect(amountInput).toHaveClass("input-error"));
    expect(
      await screen.findByText("forms.validation.chainAmount.max")
    ).toBeInTheDocument();
  });

  // https://github.com/cstenglein/raspiblitz-web/issues/234
  // skipped due to react v18 update
  test.skip("validates amount is bigger than zero", async () => {
    setup();

    const amountInput = screen.getByLabelText(
      "wallet.amount"
    ) as HTMLInputElement;

    userEvent.clear(amountInput);
    userEvent.type(amountInput, "0");
    await waitFor(() => expect(amountInput).toHaveClass("input-error"));

    expect(
      screen.getByText("forms.validation.chainAmount.required")
    ).toBeInTheDocument();
  });

  // https://github.com/cstenglein/raspiblitz-web/issues/234
  // skipped due to react v18 update
  test.skip("valid form passes", async () => {
    setup();

    const addressInput = screen.getByLabelText(
      "wallet.address"
    ) as HTMLInputElement;
    const feeInput = screen.getByLabelText("tx.fee") as HTMLInputElement;

    userEvent.type(addressInput, "bc1123456789");
    await waitFor(() => expect(addressInput).not.toHaveClass("input-error"));

    userEvent.type(feeInput, "1");
    await waitFor(() => expect(feeInput).not.toHaveClass("input-error"));

    expect(
      screen.getByRole("button", { name: "wallet.confirm" })
    ).not.toBeDisabled();
  });
});
Example #28
Source File: ConfirmSendModal.test.tsx    From raspiblitz-web with MIT License 4 votes vote down vote up
describe("ConfirmSendModal", () => {
  describe("ln-invoice with zero amount", () => {
    const setup = () => {
      render(
        <I18nextProvider i18n={i18n}>
          <ConfirmSendModal {...basicProps} />
        </I18nextProvider>
      );
    };

    test("validates amount is lower than balance", async () => {
      setup();

      let amountInput = screen.getByLabelText("wallet.amount");

      userEvent.clear(amountInput);
      userEvent.type(amountInput, "999");

      amountInput = await screen.findByLabelText("wallet.amount");

      await waitFor(() => expect(amountInput).toHaveClass("input-error"));

      expect(
        await screen.findByText("forms.validation.chainAmount.max")
      ).toBeInTheDocument();
    });

    test("validates amount is bigger than zero", async () => {
      setup();

      let amountInput = screen.getByLabelText("wallet.amount");

      userEvent.clear(amountInput);

      userEvent.type(amountInput, "0");

      amountInput = await screen.findByLabelText("wallet.amount");

      await waitFor(() => expect(amountInput).toHaveClass("input-error"));

      expect(
        screen.getByText("forms.validation.chainAmount.required")
      ).toBeInTheDocument();
    });

    test("valid form passes", async () => {
      setup();

      const amountInput = screen.getByLabelText(
        "wallet.amount"
      ) as HTMLInputElement;

      userEvent.type(amountInput, "100");
      await waitFor(() => expect(amountInput).not.toHaveClass("input-error"));

      expect(
        screen.getByRole("button", { name: "check.svg settings.confirm" })
      ).not.toBeDisabled();
    });
  });

  describe("ln-invoice with amount above zero", () => {
    test("show error if invoice is expired", async () => {
      render(
        <I18nextProvider i18n={i18n}>
          <ConfirmSendModal
            {...basicProps}
            timestamp={1640995200000} // "Sat Jan 01 2022 08:00:00
            expiry={36000}
          />
        </I18nextProvider>
      );

      expect(
        screen.getByText(
          "forms.validation.lnInvoice.expired",
          { exact: false } /* exclude displayed date */
        )
      ).toBeInTheDocument();
      expect(
        screen.getByRole("button", { name: "check.svg settings.confirm" })
      ).toBeDisabled();
    });

    test("show error if amount is bigger than balance", async () => {
      render(
        <I18nextProvider i18n={i18n}>
          <ConfirmSendModal {...basicProps} invoiceAmount={111} />
        </I18nextProvider>
      );

      expect(
        await screen.findByText("forms.validation.lnInvoice.max")
      ).toBeInTheDocument();
      expect(
        screen.getByRole("button", { name: "check.svg settings.confirm" })
      ).toBeDisabled();
    });

    test("valid form passes", async () => {
      render(
        <I18nextProvider i18n={i18n}>
          <ConfirmSendModal {...basicProps} invoiceAmount={100} />
        </I18nextProvider>
      );

      const submitButton = screen.queryByText("wallet.amount");
      expect(submitButton).not.toBeInTheDocument();

      expect(
        await screen.findByRole("button", {
          name: "check.svg settings.confirm",
        })
      ).not.toBeDisabled();
    });
  });
});