aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/App.tsx50
-rw-r--r--src/components/Question.tsx16
-rw-r--r--src/index.tsx15
-rw-r--r--src/tests/pages/CallbackPage.test.tsx14
-rw-r--r--src/tests/pages/FormPage.test.tsx14
-rw-r--r--src/tests/pages/LandingPage.test.tsx21
6 files changed, 66 insertions, 64 deletions
diff --git a/src/App.tsx b/src/App.tsx
index 523e583..752a6c6 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -3,11 +3,7 @@
import React, { Suspense } from "react";
import { jsx, css, Global } from "@emotion/react";
-import {
- BrowserRouter as Router,
- Route,
- Switch
-} from "react-router-dom";
+import { BrowserRouter, Route, Routes } from "react-router-dom";
import { PropagateLoader } from "react-spinners";
@@ -35,31 +31,33 @@ function PageLoading() {
</div>;
}
+function Routing(): JSX.Element {
+ const renderedRoutes = routes.map(({path, Component}) => (
+ <Route key={path} path={path} element={
+ <Suspense fallback={<PageLoading/>}><Component/></Suspense>
+ }/>
+ ));
+
+ return (
+ <Routes location={location}>
+ {renderedRoutes}
+ </Routes>
+ );
+}
+
function App(): JSX.Element {
return (
<div>
<Global styles={globalStyles}/>
- <Router>
- <Route render={({ location }) => (
- <TransitionGroup>
- <CSSTransition
- key={location.pathname}
- classNames="fade"
- timeout={300}
- >
- <Switch location={location}>
- {routes.map(({path, Component}) => (
- <Route exact key={path} path={path}>
- <Suspense fallback={<PageLoading/>}>
- <Component/>
- </Suspense>
- </Route>
- ))}
- </Switch>
- </CSSTransition>
- </TransitionGroup>
- )}/>
- </Router>
+ <TransitionGroup>
+ <CSSTransition key={location.pathname} classNames="fade" timeout={300}>
+ <BrowserRouter>
+ <Routes>
+ <Route path="*" element={<Routing/>}/>
+ </Routes>
+ </BrowserRouter>
+ </CSSTransition>
+ </TransitionGroup>
</div>
);
}
diff --git a/src/components/Question.tsx b/src/components/Question.tsx
index ebacb4a..61e66e0 100644
--- a/src/components/Question.tsx
+++ b/src/components/Question.tsx
@@ -35,14 +35,22 @@ class RenderedQuestion extends React.Component<QuestionProp> {
}
this.blurHandler = this.blurHandler.bind(this);
- this.setPublicState("valid", true);
- this.setPublicState("error", "");
+ const _state: {[key: string]: string | boolean | null} = {
+ "valid": true,
+ "error": "",
+ };
+
if (props.question.type === QuestionType.Code) {
- this.setPublicState("unittestsFailed", false);
+ _state["unittestsFailed"] = false;
}
if (!skip_normal_state.includes(props.question.type)) {
- this.setPublicState("value", "");
+ _state["value"] = "";
+ }
+
+ this.state = _state;
+ for (const [key, value] of Object.entries(_state)) {
+ this.props.public_state.set(key, value);
}
}
diff --git a/src/index.tsx b/src/index.tsx
index 4bce5a4..2565964 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -1,5 +1,7 @@
+/** @jsx jsx */
+import { jsx } from "@emotion/react";
import React from "react";
-import ReactDOM from "react-dom";
+import { createRoot } from "react-dom/client";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
@@ -33,8 +35,10 @@ console.log(` SHA: %c ${process.env.COMMIT_REF} `, `padding: 2px; border-radiu
console.log("%cCome join us on Discord! https://discord.gg/python", `font-size: 1.5em; font-family: "Hind", "Arial"; color: ${colors.blurple}`);
-/* eslint-disable react/react-in-jsx-scope */
-ReactDOM.render(
+const rootDocument = document.getElementById("root");
+// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+const root = createRoot(rootDocument!);
+root.render(
<React.StrictMode>
<Sentry.ErrorBoundary
fallback={<p>An error has occurred with Python Discord Forms. Please let us know in the Discord server at <a href="https://discord.gg/python">discord.gg/python</a></p>}
@@ -47,10 +51,9 @@ ReactDOM.render(
console.log(err);
}}
>
- <App />
+ <App/>
</Sentry.ErrorBoundary>
- </React.StrictMode>,
- document.getElementById("root")
+ </React.StrictMode>
);
/* eslint-enable react/react-in-jsx-scope */
diff --git a/src/tests/pages/CallbackPage.test.tsx b/src/tests/pages/CallbackPage.test.tsx
index 70f2fed..37fb932 100644
--- a/src/tests/pages/CallbackPage.test.tsx
+++ b/src/tests/pages/CallbackPage.test.tsx
@@ -1,9 +1,9 @@
import React from "react";
-import { render } from "@testing-library/react";
+import { render, waitFor } from "@testing-library/react";
import CallbackPage from "../../pages/CallbackPage";
-test("callback page sends provided code", () => {
+test("callback page sends provided code", async () => {
global.opener = {
postMessage: jest.fn()
};
@@ -14,9 +14,11 @@ test("callback page sends provided code", () => {
render(<CallbackPage/>);
- expect(global.opener.postMessage).toBeCalledTimes(1);
- expect(global.opener.postMessage).toBeCalledWith({
- code: "abcde_code",
- state: "abcde_state"
+ await waitFor(() => {
+ expect(global.opener.postMessage).toBeCalledTimes(1);
+ expect(global.opener.postMessage).toBeCalledWith({
+ code: "abcde_code",
+ state: "abcde_state"
+ });
});
});
diff --git a/src/tests/pages/FormPage.test.tsx b/src/tests/pages/FormPage.test.tsx
index 947c075..3a906f3 100644
--- a/src/tests/pages/FormPage.test.tsx
+++ b/src/tests/pages/FormPage.test.tsx
@@ -1,18 +1,13 @@
import React from "react";
import { render } from "@testing-library/react";
-import { createMemoryHistory } from "history";
-
-import { Route, BrowserRouter as Router } from "react-router-dom";
+import { MemoryRouter } from "react-router-dom";
import FormPage from "../../pages/FormPage";
import * as forms from "../../api/forms";
test("renders specific form page with loading bar", () => {
- const history = createMemoryHistory();
- history.push("/form/route");
-
- const { getByText } = render(<Router><Route history={history} ><FormPage /></Route></Router>);
+ const { getByText } = render(<FormPage/>, {wrapper: MemoryRouter});
// If we rendered the headerbar we rendered the forms page.
const headerBar = getByText(/Loading.../);
expect(headerBar).toBeInTheDocument();
@@ -20,14 +15,11 @@ test("renders specific form page with loading bar", () => {
/* TODO: Find why this test spits out promise errors that fail CI */
test.skip("calls api method to load form", () => {
- const history = createMemoryHistory();
- history.push("/form/ban-appeals");
-
const oldImpl = forms.getForm;
Object.defineProperty(forms, "getForm", {value: jest.fn(oldImpl)});
- render(<Router><Route history={history}><FormPage /></Route></Router>);
+ render(<FormPage/>, {wrapper: MemoryRouter});
expect(forms.getForm).toBeCalled();
});
diff --git a/src/tests/pages/LandingPage.test.tsx b/src/tests/pages/LandingPage.test.tsx
index 6f8a530..727b922 100644
--- a/src/tests/pages/LandingPage.test.tsx
+++ b/src/tests/pages/LandingPage.test.tsx
@@ -1,10 +1,10 @@
import React from "react";
-import { render } from "@testing-library/react";
+import { render, waitFor } from "@testing-library/react";
import LandingPage from "../../pages/LandingPage";
import * as forms from "../../api/forms";
-import { BrowserRouter as Router } from "react-router-dom";
+import { MemoryRouter } from "react-router-dom";
import { QuestionType } from "../../api/question";
const testingForm: forms.Form = {
@@ -25,13 +25,12 @@ const testingForm: forms.Form = {
submitted_text: null
};
-test("renders landing page", () => {
- const setForms = jest.fn(() => [testingForm]);
- Object.defineProperty(forms, "getForms", setForms);
- const handleForms = jest.spyOn(React, "useState");
- handleForms.mockImplementation(() => [[testingForm], setForms]);
- const { getByText } = render(<Router><LandingPage /></Router>);
- // If we rendered the headerbar we rendered the landing page.
- const headerBar = getByText(/Python Discord Forms/);
- expect(headerBar).toBeInTheDocument();
+test("renders landing page", async () => {
+ jest.spyOn(forms, "getForms").mockImplementation(() => Promise.resolve([testingForm]));
+
+ const { getByText } = render(<LandingPage/>, {wrapper: MemoryRouter});
+ await waitFor(() => {
+ const headerBar = getByText(/Python Discord Forms/);
+ expect(headerBar).toBeInTheDocument();
+ });
});