diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/App.tsx | 50 | ||||
-rw-r--r-- | src/components/Question.tsx | 16 | ||||
-rw-r--r-- | src/index.tsx | 15 | ||||
-rw-r--r-- | src/tests/pages/CallbackPage.test.tsx | 14 | ||||
-rw-r--r-- | src/tests/pages/FormPage.test.tsx | 14 | ||||
-rw-r--r-- | src/tests/pages/LandingPage.test.tsx | 21 |
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(); + }); }); |