aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Hassan Abouelela <[email protected]>2021-01-03 05:47:07 +0300
committerGravatar Hassan Abouelela <[email protected]>2021-01-03 05:47:07 +0300
commitd664ddc9b84b25922239e3bbc253b35ea54f2533 (patch)
treef1892f7e9b0880826b28a503aea312a97b0ea3a2
parentAdds EsLint (diff)
Fixes Preexisting Linting Issues
Fixes all errors, and most warnings generated by eslint. Most were fixed by eslint automatically such as indentation and quotes. Signed-off-by: Hassan Abouelela <[email protected]>
-rw-r--r--.eslintrc.json17
-rw-r--r--src/App.tsx76
-rw-r--r--src/api/client.ts2
-rw-r--r--src/api/forms.ts8
-rw-r--r--src/colors.ts14
-rw-r--r--src/components/FormListing.tsx26
-rw-r--r--src/components/HeaderBar/index.tsx26
-rw-r--r--src/components/Loading.tsx4
-rw-r--r--src/components/OAuth2Button.tsx66
-rw-r--r--src/components/Tag.tsx2
-rw-r--r--src/index.tsx72
-rw-r--r--src/pages/CallbackPage.tsx2
-rw-r--r--src/pages/FormPage.tsx10
-rw-r--r--src/pages/LandingPage.tsx48
-rw-r--r--src/react-app-env.d.ts30
-rw-r--r--src/serviceWorker.ts216
-rw-r--r--src/setupTests.ts2
-rw-r--r--src/tests/App.test.tsx6
-rw-r--r--src/tests/api/forms.test.ts6
-rw-r--r--src/tests/components/FormListing.test.tsx24
-rw-r--r--src/tests/components/HeaderBar.test.tsx10
-rw-r--r--src/tests/components/OAuth2Button.test.tsx10
-rw-r--r--src/tests/components/Tag.test.tsx12
-rw-r--r--src/tests/globalStyles.test.ts2
-rw-r--r--src/tests/pages/CallbackPage.test.tsx20
-rw-r--r--src/tests/pages/FormPage.test.tsx14
-rw-r--r--src/tests/pages/LandingPage.test.tsx14
27 files changed, 378 insertions, 361 deletions
diff --git a/.eslintrc.json b/.eslintrc.json
index 4e55622..5c7c77a 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -37,5 +37,20 @@
"error",
"always"
]
- }
+ },
+ "settings": {
+ "react": {
+ "pragma": "jsx",
+ "version": "detect",
+ "flowVersion": "0.53"
+ }
+ },
+ "overrides": [
+ {
+ "files": "*.test.ts*",
+ "rules": {
+ "react/react-in-jsx-scope": "off"
+ }
+ }
+ ]
}
diff --git a/src/App.tsx b/src/App.tsx
index b1b2184..523e583 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -4,9 +4,9 @@ import React, { Suspense } from "react";
import { jsx, css, Global } from "@emotion/react";
import {
- BrowserRouter as Router,
- Route,
- Switch
+ BrowserRouter as Router,
+ Route,
+ Switch
} from "react-router-dom";
import { PropagateLoader } from "react-spinners";
@@ -20,48 +20,48 @@ const FormPage = React.lazy(() => import("./pages/FormPage"));
const CallbackPage = React.lazy(() => import("./pages/CallbackPage"));
const routes = [
- { path: "/", Component: LandingPage },
- { path: "/form/:id", Component: FormPage},
- { path: "/callback", Component: CallbackPage }
-]
+ { path: "/", Component: LandingPage },
+ { path: "/form/:id", Component: FormPage},
+ { path: "/callback", Component: CallbackPage }
+];
function PageLoading() {
- return <div css={css`
+ return <div css={css`
display: flex;
justify-content: center;
margin-top: 50px;
`}>
- <PropagateLoader color="white" size={100}/>
- </div>
+ <PropagateLoader color="white" size={100}/>
+ </div>;
}
-function App() {
- 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>
- </div>
- );
-};
+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>
+ </div>
+ );
+}
export default App;
diff --git a/src/api/client.ts b/src/api/client.ts
index 32c1993..b534938 100644
--- a/src/api/client.ts
+++ b/src/api/client.ts
@@ -3,4 +3,4 @@ import axios from "axios";
export default axios.create({
baseURL: process.env.BACKEND_URL
-})
+});
diff --git a/src/api/forms.ts b/src/api/forms.ts
index 724d6b7..aec4b99 100644
--- a/src/api/forms.ts
+++ b/src/api/forms.ts
@@ -1,4 +1,4 @@
-import { Question, QuestionType } from "./question"
+import { Question, QuestionType } from "./question";
import ApiClient from "./client";
export enum FormFeatures {
@@ -36,8 +36,8 @@ export function getForm(id: string): Promise<Form> {
data: {}
}
]
- }
+ };
return new Promise((resolve) => {
- setTimeout(() => resolve(data), 1500)
- })
+ setTimeout(() => resolve(data), 1500);
+ });
}
diff --git a/src/colors.ts b/src/colors.ts
index 2107987..e9c74b1 100644
--- a/src/colors.ts
+++ b/src/colors.ts
@@ -1,8 +1,8 @@
export default {
- blurple: '#7289DA',
- darkButNotBlack: '#2C2F33',
- notQuiteBlack: '#23272A',
- greyple: '#99AAB5',
- error: '#f04747',
- success: '#43b581'
-}
+ blurple: "#7289DA",
+ darkButNotBlack: "#2C2F33",
+ notQuiteBlack: "#23272A",
+ greyple: "#99AAB5",
+ error: "#f04747",
+ success: "#43b581"
+};
diff --git a/src/components/FormListing.tsx b/src/components/FormListing.tsx
index f53efe2..0905903 100644
--- a/src/components/FormListing.tsx
+++ b/src/components/FormListing.tsx
@@ -2,7 +2,7 @@
import { css, jsx } from "@emotion/react";
import { Link } from "react-router-dom";
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faArrowRight } from "@fortawesome/free-solid-svg-icons";
import Tag from "./Tag";
@@ -15,8 +15,8 @@ interface FormListingProps {
form: Form
}
-function FormListing({ form }: FormListingProps) {
- const listingStyle = css`
+function FormListing({ form }: FormListingProps): JSX.Element {
+ const listingStyle = css`
background-color: ${form.features.includes(FormFeatures.Open) ? colors.success : colors.darkButNotBlack};
width: 60%;
padding: 20px;
@@ -37,18 +37,18 @@ function FormListing({ form }: FormListingProps) {
}
`;
- let closedTag;
+ let closedTag;
- if (!form.features.includes(FormFeatures.Open)) {
- closedTag = <Tag text="CLOSED" color={colors.error}/>
- };
+ if (!form.features.includes(FormFeatures.Open)) {
+ closedTag = <Tag text="CLOSED" color={colors.error}/>;
+ }
- return <Link to={`/form/${form.id}`} css={listingStyle}>
- <div>
- <h3 css={{fontSize: "1.5em", marginBottom: "0"}}>{closedTag}{form.name} <FontAwesomeIcon icon={faArrowRight} css={{fontSize: "0.75em", paddingBottom: "1px"}}/></h3>
- <p css={{marginTop: "5px"}}>{form.description}</p>
- </div>
- </Link>
+ return <Link to={`/form/${form.id}`} css={listingStyle}>
+ <div>
+ <h3 css={{fontSize: "1.5em", marginBottom: "0"}}>{closedTag}{form.name} <FontAwesomeIcon icon={faArrowRight} css={{fontSize: "0.75em", paddingBottom: "1px"}}/></h3>
+ <p css={{marginTop: "5px"}}>{form.description}</p>
+ </div>
+ </Link>;
}
export default FormListing;
diff --git a/src/components/HeaderBar/index.tsx b/src/components/HeaderBar/index.tsx
index b789ddb..dfe3957 100644
--- a/src/components/HeaderBar/index.tsx
+++ b/src/components/HeaderBar/index.tsx
@@ -16,17 +16,17 @@ width: 100%;
transition: height 1s;
`;
-function HeaderBar({ title }: HeaderBarProps) {
- if (!title) {
- title = "Python Discord Forms";
- };
+function HeaderBar({ title }: HeaderBarProps): JSX.Element {
+ if (!title) {
+ title = "Python Discord Forms";
+ }
- return <div>
- <div>
- <Header1 css={headerImageStyles}/>
- <Header2 css={headerImageStyles}/>
- </div>
- <h1 css={css`
+ return <div>
+ <div>
+ <Header1 css={headerImageStyles}/>
+ <Header2 css={headerImageStyles}/>
+ </div>
+ <h1 css={css`
font-size: 4vw;
margin: 0;
margin-top: 30px;
@@ -51,9 +51,9 @@ function HeaderBar({ title }: HeaderBarProps) {
margin-left: 0;
}
`}>
- {title}
- </h1>
- </div>
+ {title}
+ </h1>
+ </div>;
}
export default HeaderBar;
diff --git a/src/components/Loading.tsx b/src/components/Loading.tsx
index 8454366..8dd5474 100644
--- a/src/components/Loading.tsx
+++ b/src/components/Loading.tsx
@@ -5,13 +5,13 @@ import { PropagateLoader } from "react-spinners";
import HeaderBar from "../components/HeaderBar";
-function Loading() {
+function Loading(): JSX.Element {
return <div>
<HeaderBar title={"Loading..."}/>
<div css={{display: "flex", justifyContent: "center", paddingTop: "40px"}}>
<PropagateLoader color="white"/>
</div>
- </div>
+ </div>;
}
export default Loading;
diff --git a/src/components/OAuth2Button.tsx b/src/components/OAuth2Button.tsx
index c364369..4fa3f61 100644
--- a/src/components/OAuth2Button.tsx
+++ b/src/components/OAuth2Button.tsx
@@ -1,7 +1,7 @@
/** @jsx jsx */
import { css, jsx } from "@emotion/react";
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faDiscord } from "@fortawesome/free-brands-svg-icons";
import colors from "../colors";
@@ -40,49 +40,49 @@ span {
`;
function doLogin(disableFunction: (newState: boolean) => void) {
- disableFunction(true);
+ disableFunction(true);
- const redirectURI = encodeURIComponent(document.location.protocol + "//" + document.location.host + "/callback");
+ const redirectURI = encodeURIComponent(document.location.protocol + "//" + document.location.host + "/callback");
- const windowRef = window.open(
- `https://discord.com/api/oauth2/authorize?client_id=${OAUTH2_CLIENT_ID}&response_type=code&scope=identify&redirect_uri=${redirectURI}&prompt=none`,
- "Discord_OAuth2",
- "height=700,width=500,location=no,menubar=no,resizable=no,status=no,titlebar=no,left=300,top=300"
- )
+ const windowRef = window.open(
+ `https://discord.com/api/oauth2/authorize?client_id=${OAUTH2_CLIENT_ID}&response_type=code&scope=identify&redirect_uri=${redirectURI}&prompt=none`,
+ "Discord_OAuth2",
+ "height=700,width=500,location=no,menubar=no,resizable=no,status=no,titlebar=no,left=300,top=300"
+ );
- const interval = setInterval(() => {
- if (windowRef?.closed) {
- clearInterval(interval);
- disableFunction(false);
- }
- }, 500)
+ const interval = setInterval(() => {
+ if (windowRef?.closed) {
+ clearInterval(interval);
+ disableFunction(false);
+ }
+ }, 500);
- window.onmessage = (code: MessageEvent) => {
- if (code.data.source) {
- // React DevTools has a habit of sending messages, ignore them.
- return;
- }
+ window.onmessage = (code: MessageEvent) => {
+ if (code.data.source) {
+ // React DevTools has a habit of sending messages, ignore them.
+ return;
+ }
- if (code.isTrusted) {
- windowRef?.close();
+ if (code.isTrusted) {
+ windowRef?.close();
- console.log("Code received:", code.data);
+ console.log("Code received:", code.data);
- disableFunction(false);
- clearInterval(interval);
+ disableFunction(false);
+ clearInterval(interval);
- window.onmessage = null;
- }
- };
+ window.onmessage = null;
+ }
+ };
}
-function OAuth2Button() {
- const [disabled, setDisabled] = useState<boolean>(false);
+function OAuth2Button(): JSX.Element {
+ const [disabled, setDisabled] = useState<boolean>(false);
- return <button disabled={disabled} onClick={() => doLogin(setDisabled)} css={buttonStyling}>
- <span css={{marginRight: "10px"}}><FontAwesomeIcon icon={faDiscord} css={{fontSize: "2em", marginTop: "3px"}}/></span>
- <span>Sign in with Discord</span>
- </button>;
+ return <button disabled={disabled} onClick={() => doLogin(setDisabled)} css={buttonStyling}>
+ <span css={{marginRight: "10px"}}><FontAwesomeIcon icon={faDiscord} css={{fontSize: "2em", marginTop: "3px"}}/></span>
+ <span>Sign in with Discord</span>
+ </button>;
}
export default OAuth2Button;
diff --git a/src/components/Tag.tsx b/src/components/Tag.tsx
index 0c55348..3e5b1f5 100644
--- a/src/components/Tag.tsx
+++ b/src/components/Tag.tsx
@@ -7,7 +7,7 @@ interface TagProps {
fontSize?: string
}
-function Tag(props: TagProps) {
+function Tag(props: TagProps): JSX.Element {
return <span css={css`
font-size: ${props.fontSize ? props.fontSize : "0.75em"};
background-color: ${props.color};
diff --git a/src/index.tsx b/src/index.tsx
index 73e8120..871eb40 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -1,50 +1,52 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-import App from './App';
-import * as serviceWorker from './serviceWorker';
+import React from "react";
+import ReactDOM from "react-dom";
+import App from "./App";
+import * as serviceWorker from "./serviceWorker";
import * as Sentry from "@sentry/react";
import colors from "./colors";
if (process.env.NODE_ENV === "production") {
- Sentry.init({
- dsn: process.env.REACT_APP_SENTRY_DSN,
- tracesSampleRate: 0.25,
- release: `forms-frontend@${process.env.REACT_APP_SHA}`,
- environment: process.env.CONTEXT
- });
+ Sentry.init({
+ dsn: process.env.REACT_APP_SENTRY_DSN,
+ tracesSampleRate: 0.25,
+ release: `forms-frontend@${process.env.REACT_APP_SHA}`,
+ environment: process.env.CONTEXT
+ });
}
-console.log("%c Python Discord Forms ", `font-size: 6em; font-family: "Hind", "Arial"; font-weight: 900; background-color: ${colors.blurple}; border-radius: 10px;`)
-console.log("%cWelcome to Python Discord Forms", `font-size: 3em; font-family: "Hind", "Arial";`)
+console.log("%c Python Discord Forms ", `font-size: 6em; font-family: "Hind", "Arial"; font-weight: 900; background-color: ${colors.blurple}; border-radius: 10px;`);
+console.log("%cWelcome to Python Discord Forms", "font-size: 3em; font-family: \"Hind\", \"Arial\";");
-console.log(` Environment: %c ${process.env.NODE_ENV} `, `padding: 2px; border-radius: 5px; background-color: ${process.env.NODE_ENV === "production" ? colors.success : colors.error}`)
-console.log(` Context: %c ${process.env.CONTEXT} `, `padding: 2px; border-radius: 5px; background-color: ${process.env.CONTEXT === "production" ? colors.success : colors.error}`)
-console.log(` Location: %c ${document.location.pathname + document.location.search + document.location.hash} `, `padding: 2px; border-radius: 5px; background-color: ${colors.success}`)
-console.log(` User Agent: %c ${navigator.userAgent} `, `padding: 2px; border-radius: 5px; background-color: ${colors.success}`)
-console.log(` Branch: %c ${process.env.REACT_APP_BRANCH} `, `padding: 2px; border-radius: 5px; background-color: ${process.env.REACT_APP_BRANCH === "main" ? colors.success : colors.error}`)
-console.log(` SHA: %c ${process.env.REACT_APP_SHA} `, `padding: 2px; border-radius: 5px; background-color: ${colors.success}`)
+console.log(` Environment: %c ${process.env.NODE_ENV} `, `padding: 2px; border-radius: 5px; background-color: ${process.env.NODE_ENV === "production" ? colors.success : colors.error}`);
+console.log(` Context: %c ${process.env.CONTEXT} `, `padding: 2px; border-radius: 5px; background-color: ${process.env.CONTEXT === "production" ? colors.success : colors.error}`);
+console.log(` Location: %c ${document.location.pathname + document.location.search + document.location.hash} `, `padding: 2px; border-radius: 5px; background-color: ${colors.success}`);
+console.log(` User Agent: %c ${navigator.userAgent} `, `padding: 2px; border-radius: 5px; background-color: ${colors.success}`);
+console.log(` Branch: %c ${process.env.REACT_APP_BRANCH} `, `padding: 2px; border-radius: 5px; background-color: ${process.env.REACT_APP_BRANCH === "main" ? colors.success : colors.error}`);
+console.log(` SHA: %c ${process.env.REACT_APP_SHA} `, `padding: 2px; border-radius: 5px; background-color: ${colors.success}`);
-console.log("%cCome join us on Discord! https://discord.gg/python", `font-size: 1.5em; font-family: "Hind", "Arial"; color: ${colors.blurple}`)
+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(
- <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>}
- showDialog={true}
- dialogOptions={{
- title: "You've found a bug in PyDis forms!"
- }}
- onError={(err) => {
- if(process.env.NODE_ENV === "development")
- console.log(err)
- }}
- >
- <App />
- </Sentry.ErrorBoundary>
- </React.StrictMode>,
- document.getElementById('root')
+ <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>}
+ showDialog={true}
+ dialogOptions={{
+ title: "You've found a bug in PyDis forms!"
+ }}
+ onError={(err) => {
+ if(process.env.NODE_ENV === "development")
+ console.log(err);
+ }}
+ >
+ <App />
+ </Sentry.ErrorBoundary>
+ </React.StrictMode>,
+ document.getElementById("root")
);
+/* eslint-enable react/react-in-jsx-scope */
serviceWorker.unregister();
diff --git a/src/pages/CallbackPage.tsx b/src/pages/CallbackPage.tsx
index 691a3e4..fab2086 100644
--- a/src/pages/CallbackPage.tsx
+++ b/src/pages/CallbackPage.tsx
@@ -2,7 +2,7 @@
import { jsx } from "@emotion/react";
import { useState } from "react";
-export default function CallbackPage() {
+export default function CallbackPage(): JSX.Element {
const [hasSent, setHasSent] = useState(false);
const params = new URLSearchParams(location.search);
diff --git a/src/pages/FormPage.tsx b/src/pages/FormPage.tsx
index 97ff24d..1805897 100644
--- a/src/pages/FormPage.tsx
+++ b/src/pages/FormPage.tsx
@@ -12,7 +12,7 @@ interface PathParams {
id: string
}
-function FormPage() {
+function FormPage(): JSX.Element {
const { id } = useParams<PathParams>();
const [form, setForm] = useState<Form>();
@@ -20,11 +20,11 @@ function FormPage() {
useEffect(() => {
getForm(id).then(form => {
setForm(form);
- })
- })
+ });
+ });
if (!form) {
- return <Loading/>
+ return <Loading/>;
}
return <div>
@@ -33,7 +33,7 @@ function FormPage() {
<h1>{form.description}</h1>
<Link to="/" css={{color: "white"}}>Return home</Link>
</div>
- </div>
+ </div>;
}
export default FormPage;
diff --git a/src/pages/LandingPage.tsx b/src/pages/LandingPage.tsx
index 1320c14..124bbcf 100644
--- a/src/pages/LandingPage.tsx
+++ b/src/pages/LandingPage.tsx
@@ -9,40 +9,40 @@ import { getForms, Form } from "../api/forms";
import OAuth2Button from "../components/OAuth2Button";
import Loading from "../components/Loading";
-function LandingPage() {
- const [forms, setForms] = useState<Form[]>();
-
- useEffect(() => {
- const fetchForms = async () => {
- setForms(await getForms());
+function LandingPage(): JSX.Element {
+ const [forms, setForms] = useState<Form[]>();
+
+ useEffect(() => {
+ const fetchForms = async () => {
+ setForms(await getForms());
+ };
+ fetchForms();
+ }, []);
+
+ if (!forms) {
+ return <Loading/>;
}
- fetchForms();
- }, []);
-
- if (!forms) {
- return <Loading/>;
- }
- return <div>
- <HeaderBar/>
- <div>
+ return <div>
+ <HeaderBar/>
+ <div>
- <div css={css`
+ <div css={css`
display: flex;
align-items: center;
flex-direction: column;
`}>
- <h1>Available Forms</h1>
+ <h1>Available Forms</h1>
- <OAuth2Button/>
+ <OAuth2Button/>
- {forms.map(form => (
- <FormListing key={form.id} form={form}/>
- ))}
- </div>
- </div>
- </div>
+ {forms.map(form => (
+ <FormListing key={form.id} form={form}/>
+ ))}
+ </div>
+ </div>
+ </div>;
}
export default LandingPage;
diff --git a/src/react-app-env.d.ts b/src/react-app-env.d.ts
index 981cd73..d7e3ac4 100644
--- a/src/react-app-env.d.ts
+++ b/src/react-app-env.d.ts
@@ -1,46 +1,46 @@
-/// <reference types="node" />
-/// <reference types="react" />
-/// <reference types="react-dom" />
+import("node");
+import("react");
+import("react-dom");
declare namespace NodeJS {
interface ProcessEnv {
- readonly NODE_ENV: 'development' | 'production' | 'test';
+ readonly NODE_ENV: "development" | "production" | "test";
readonly PUBLIC_URL: string;
}
}
-declare module '*.bmp' {
+declare module "*.bmp" {
const src: string;
export default src;
}
-declare module '*.gif' {
+declare module "*.gif" {
const src: string;
export default src;
}
-declare module '*.jpg' {
+declare module "*.jpg" {
const src: string;
export default src;
}
-declare module '*.jpeg' {
+declare module "*.jpeg" {
const src: string;
export default src;
}
-declare module '*.png' {
+declare module "*.png" {
const src: string;
export default src;
}
-declare module '*.webp' {
+declare module "*.webp" {
const src: string;
export default src;
}
-declare module '*.svg' {
- import * as React from 'react';
+declare module "*.svg" {
+ import * as React from "react";
export const ReactComponent: React.FunctionComponent<React.SVGProps<
SVGSVGElement
@@ -50,17 +50,17 @@ declare module '*.svg' {
export default src;
}
-declare module '*.module.css' {
+declare module "*.module.css" {
const classes: { readonly [key: string]: string };
export default classes;
}
-declare module '*.module.scss' {
+declare module "*.module.scss" {
const classes: { readonly [key: string]: string };
export default classes;
}
-declare module '*.module.sass' {
+declare module "*.module.sass" {
const classes: { readonly [key: string]: string };
export default classes;
}
diff --git a/src/serviceWorker.ts b/src/serviceWorker.ts
index 2b4d2b5..600d89d 100644
--- a/src/serviceWorker.ts
+++ b/src/serviceWorker.ts
@@ -1,10 +1,10 @@
const isLocalhost = Boolean(
- window.location.hostname === 'localhost' ||
+ window.location.hostname === "localhost" ||
// [::1] is the IPv6 localhost address.
- window.location.hostname === '[::1]' ||
+ window.location.hostname === "[::1]" ||
// 127.0.0.0/8 are considered localhost for IPv4.
window.location.hostname.match(
- /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
+ /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);
@@ -13,125 +13,125 @@ type Config = {
onUpdate?: (registration: ServiceWorkerRegistration) => void;
};
-export function register(config?: Config) {
- if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
+export function register(config?: Config): void {
+ if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
// The URL constructor is available in all browsers that support SW.
- const publicUrl = new URL(
- process.env.PUBLIC_URL,
- window.location.href
- );
- if (publicUrl.origin !== window.location.origin) {
- // Our service worker won't work if PUBLIC_URL is on a different origin
- // from what our page is served on. This might happen if a CDN is used to
- // serve assets; see https://github.com/facebook/create-react-app/issues/2374
- return;
- }
+ const publicUrl = new URL(
+ process.env.PUBLIC_URL,
+ window.location.href
+ );
+ if (publicUrl.origin !== window.location.origin) {
+ // Our service worker won't work if PUBLIC_URL is on a different origin
+ // from what our page is served on. This might happen if a CDN is used to
+ // serve assets; see https://github.com/facebook/create-react-app/issues/2374
+ return;
+ }
- window.addEventListener('load', () => {
- const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
+ window.addEventListener("load", () => {
+ const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
- if (isLocalhost) {
- // This is running on localhost. Let's check if a service worker still exists or not.
- checkValidServiceWorker(swUrl, config);
+ if (isLocalhost) {
+ // This is running on localhost. Let's check if a service worker still exists or not.
+ checkValidServiceWorker(swUrl, config);
- // Add some additional logging to localhost, pointing developers to the
- // service worker/PWA documentation.
- navigator.serviceWorker.ready.then(() => {
- console.log(
- 'This web app is being served cache-first by a service ' +
- 'worker. To learn more, visit https://bit.ly/CRA-PWA'
- );
+ // Add some additional logging to localhost, pointing developers to the
+ // service worker/PWA documentation.
+ navigator.serviceWorker.ready.then(() => {
+ console.log(
+ "This web app is being served cache-first by a service " +
+ "worker. To learn more, visit https://bit.ly/CRA-PWA"
+ );
+ });
+ } else {
+ // Is not localhost. Just register service worker
+ registerValidSW(swUrl, config);
+ }
});
- } else {
- // Is not localhost. Just register service worker
- registerValidSW(swUrl, config);
- }
- });
- }
+ }
}
function registerValidSW(swUrl: string, config?: Config) {
- navigator.serviceWorker
- .register(swUrl)
- .then(registration => {
- registration.onupdatefound = () => {
- const installingWorker = registration.installing;
- if (installingWorker == null) {
- return;
- }
- installingWorker.onstatechange = () => {
- if (installingWorker.state === 'installed') {
- if (navigator.serviceWorker.controller) {
- // At this point, the updated precached content has been fetched,
- // but the previous service worker will still serve the older
- // content until all client tabs are closed.
- console.log(
- 'New content is available and will be used when all ' +
- 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
- );
+ navigator.serviceWorker
+ .register(swUrl)
+ .then(registration => {
+ registration.onupdatefound = () => {
+ const installingWorker = registration.installing;
+ if (installingWorker == null) {
+ return;
+ }
+ installingWorker.onstatechange = () => {
+ if (installingWorker.state === "installed") {
+ if (navigator.serviceWorker.controller) {
+ // At this point, the updated precached content has been fetched,
+ // but the previous service worker will still serve the older
+ // content until all client tabs are closed.
+ console.log(
+ "New content is available and will be used when all " +
+ "tabs for this page are closed. See https://bit.ly/CRA-PWA."
+ );
- // Execute callback
- if (config && config.onUpdate) {
- config.onUpdate(registration);
- }
- } else {
- // At this point, everything has been precached.
- // It's the perfect time to display a
- // "Content is cached for offline use." message.
- console.log('Content is cached for offline use.');
+ // Execute callback
+ if (config && config.onUpdate) {
+ config.onUpdate(registration);
+ }
+ } else {
+ // At this point, everything has been precached.
+ // It's the perfect time to display a
+ // "Content is cached for offline use." message.
+ console.log("Content is cached for offline use.");
- // Execute callback
- if (config && config.onSuccess) {
- config.onSuccess(registration);
- }
- }
- }
- };
- };
- })
- .catch(error => {
- console.error('Error during service worker registration:', error);
- });
+ // Execute callback
+ if (config && config.onSuccess) {
+ config.onSuccess(registration);
+ }
+ }
+ }
+ };
+ };
+ })
+ .catch(error => {
+ console.error("Error during service worker registration:", error);
+ });
}
function checkValidServiceWorker(swUrl: string, config?: Config) {
- // Check if the service worker can be found. If it can't reload the page.
- fetch(swUrl, {
- headers: { 'Service-Worker': 'script' }
- })
- .then(response => {
- // Ensure service worker exists, and that we really are getting a JS file.
- const contentType = response.headers.get('content-type');
- if (
- response.status === 404 ||
- (contentType != null && contentType.indexOf('javascript') === -1)
- ) {
- // No service worker found. Probably a different app. Reload the page.
- navigator.serviceWorker.ready.then(registration => {
- registration.unregister().then(() => {
- window.location.reload();
- });
- });
- } else {
- // Service worker found. Proceed as normal.
- registerValidSW(swUrl, config);
- }
+ // Check if the service worker can be found. If it can't reload the page.
+ fetch(swUrl, {
+ headers: { "Service-Worker": "script" }
})
- .catch(() => {
- console.log(
- 'No internet connection found. App is running in offline mode.'
- );
- });
+ .then(response => {
+ // Ensure service worker exists, and that we really are getting a JS file.
+ const contentType = response.headers.get("content-type");
+ if (
+ response.status === 404 ||
+ (contentType != null && contentType.indexOf("javascript") === -1)
+ ) {
+ // No service worker found. Probably a different app. Reload the page.
+ navigator.serviceWorker.ready.then(registration => {
+ registration.unregister().then(() => {
+ window.location.reload();
+ });
+ });
+ } else {
+ // Service worker found. Proceed as normal.
+ registerValidSW(swUrl, config);
+ }
+ })
+ .catch(() => {
+ console.log(
+ "No internet connection found. App is running in offline mode."
+ );
+ });
}
-export function unregister() {
- if ('serviceWorker' in navigator) {
- navigator.serviceWorker.ready
- .then(registration => {
- registration.unregister();
- })
- .catch(error => {
- console.error(error.message);
- });
- }
+export function unregister(): void {
+ if ("serviceWorker" in navigator) {
+ navigator.serviceWorker.ready
+ .then(registration => {
+ registration.unregister();
+ })
+ .catch(error => {
+ console.error(error.message);
+ });
+ }
}
diff --git a/src/setupTests.ts b/src/setupTests.ts
index 4dc2c73..5018a42 100644
--- a/src/setupTests.ts
+++ b/src/setupTests.ts
@@ -1,2 +1,2 @@
-import '@testing-library/jest-dom/extend-expect';
+import "@testing-library/jest-dom/extend-expect";
diff --git a/src/tests/App.test.tsx b/src/tests/App.test.tsx
index e050d4f..4765f87 100644
--- a/src/tests/App.test.tsx
+++ b/src/tests/App.test.tsx
@@ -1,9 +1,9 @@
-import React from 'react';
-import { render } from '@testing-library/react';
+import React from "react";
+import { render } from "@testing-library/react";
import App from "../App";
-test('renders app to body', () => {
+test("renders app to body", () => {
const { container } = render(<App />);
expect(container).toBeInTheDocument();
});
diff --git a/src/tests/api/forms.test.ts b/src/tests/api/forms.test.ts
index 6e63965..10ccaa3 100644
--- a/src/tests/api/forms.test.ts
+++ b/src/tests/api/forms.test.ts
@@ -1,7 +1,7 @@
-import { getForm, getForms } from "../../api/forms";
+import { getForm } from "../../api/forms";
-test('fetch a specific form', () => {
- expect(getForm("ban-appeals")).resolves.toHaveProperty("name", "Ban Appeals")
+test("fetch a specific form", () => {
+ expect(getForm("ban-appeals")).resolves.toHaveProperty("name", "Ban Appeals");
});
export default null;
diff --git a/src/tests/components/FormListing.test.tsx b/src/tests/components/FormListing.test.tsx
index 0afe10c..ad76381 100644
--- a/src/tests/components/FormListing.test.tsx
+++ b/src/tests/components/FormListing.test.tsx
@@ -1,11 +1,11 @@
-import React from 'react';
-import { render } from '@testing-library/react';
-import '@testing-library/jest-dom/extend-expect';
+import React from "react";
+import { render } from "@testing-library/react";
+import "@testing-library/jest-dom/extend-expect";
import FormListing from "../../components/FormListing";
-import { BrowserRouter as Router } from 'react-router-dom';
-import { Form, FormFeatures } from '../../api/forms';
-import { QuestionType } from '../../api/question';
+import { BrowserRouter as Router } from "react-router-dom";
+import { Form, FormFeatures } from "../../api/forms";
+import { QuestionType } from "../../api/question";
const openFormListing: Form = {
name: "Example form listing",
@@ -20,7 +20,7 @@ const openFormListing: Form = {
"data": {}
}
]
-}
+};
const closedFormListing: Form = {
name: "Example form listing",
@@ -35,28 +35,28 @@ const closedFormListing: Form = {
"data": {}
}
]
-}
+};
-test('renders form listing with specified title', () => {
+test("renders form listing with specified title", () => {
const { getByText } = render(<Router><FormListing form={openFormListing} /></Router>);
const formListing = getByText(/Example form listing/i);
expect(formListing).toBeInTheDocument();
});
-test('renders form listing with specified description', () => {
+test("renders form listing with specified description", () => {
const { getByText } = render(<Router><FormListing form={openFormListing} /></Router>);
const formListing = getByText(/My form listing/i);
expect(formListing).toBeInTheDocument();
});
-test('renders form listing with background green colour for open', () => {
+test("renders form listing with background green colour for open", () => {
const { container } = render(<Router><FormListing form={openFormListing} /></Router>);
const elem = container.querySelector("a");
const style = window.getComputedStyle(elem);
expect(style.backgroundColor).toBe("rgb(67, 181, 129)");
});
-test('renders form listing with background dark colour for closed', () => {
+test("renders form listing with background dark colour for closed", () => {
const { container } = render(<Router><FormListing form={closedFormListing} /></Router>);
const elem = container.querySelector("a");
const style = window.getComputedStyle(elem);
diff --git a/src/tests/components/HeaderBar.test.tsx b/src/tests/components/HeaderBar.test.tsx
index 6963859..9c232ad 100644
--- a/src/tests/components/HeaderBar.test.tsx
+++ b/src/tests/components/HeaderBar.test.tsx
@@ -1,15 +1,15 @@
-import React from 'react';
-import { render } from '@testing-library/react';
-import '@testing-library/jest-dom/extend-expect'
+import React from "react";
+import { render } from "@testing-library/react";
+import "@testing-library/jest-dom/extend-expect";
import HeaderBar from "../../components/HeaderBar";
-test('renders header bar with title', () => {
+test("renders header bar with title", () => {
const { getByText } = render(<HeaderBar />);
const formListing = getByText(/Python Discord Forms/i);
expect(formListing).toBeInTheDocument();
});
-test('renders header bar with custom title', () => {
+test("renders header bar with custom title", () => {
const { getByText } = render(<HeaderBar title="Testing title"/>);
const formListing = getByText(/Testing title/i);
expect(formListing).toBeInTheDocument();
diff --git a/src/tests/components/OAuth2Button.test.tsx b/src/tests/components/OAuth2Button.test.tsx
index 53875dc..f05159f 100644
--- a/src/tests/components/OAuth2Button.test.tsx
+++ b/src/tests/components/OAuth2Button.test.tsx
@@ -1,8 +1,8 @@
-import React from 'react';
-import { render } from '@testing-library/react';
+import React from "react";
+import { render } from "@testing-library/react";
import OAuth2Button from "../../components/OAuth2Button";
-test('renders oauth2 sign in button text', () => {
+test("renders oauth2 sign in button text", () => {
const { getByText } = render(<OAuth2Button />);
const button = getByText(/Sign in with Discord/i);
expect(button).toBeInTheDocument();
@@ -10,6 +10,6 @@ test('renders oauth2 sign in button text', () => {
test("renders fontawesome discord icon", () => {
const { container } = render(<OAuth2Button/>);
- const icon = container.querySelector(`[data-icon="discord"]`)
+ const icon = container.querySelector("[data-icon=\"discord\"]");
expect(icon).toBeInTheDocument();
-})
+});
diff --git a/src/tests/components/Tag.test.tsx b/src/tests/components/Tag.test.tsx
index 67f2a85..50b3b0e 100644
--- a/src/tests/components/Tag.test.tsx
+++ b/src/tests/components/Tag.test.tsx
@@ -1,28 +1,28 @@
-import React from 'react';
-import { render } from '@testing-library/react';
+import React from "react";
+import { render } from "@testing-library/react";
import Tag from "../../components/Tag";
-test('renders tag with specified text', () => {
+test("renders tag with specified text", () => {
const { getByText } = render(<Tag text="Test" color="#f0f0f0" />);
const tag = getByText(/Test/i);
expect(tag).toBeInTheDocument();
});
-test('renders tag with specified color', () => {
+test("renders tag with specified color", () => {
const { getByText } = render(<Tag text="Test" color="#f0f0f0" />);
const tag = getByText(/Test/i);
const style = window.getComputedStyle(tag);
expect(style.backgroundColor).toBe("rgb(240, 240, 240)");
});
-test('renders tag with specified font size', () => {
+test("renders tag with specified font size", () => {
const { getByText } = render(<Tag text="Test" color="#f0f0f0" fontSize="2em" />);
const tag = getByText(/Test/i);
const style = window.getComputedStyle(tag);
expect(style.fontSize).toBe("2em");
});
-test('defaults to 0.75em when no tag font size is passed', () => {
+test("defaults to 0.75em when no tag font size is passed", () => {
const { getByText } = render(<Tag text="Test" color="#f0f0f0" />);
const tag = getByText(/Test/i);
const style = window.getComputedStyle(tag);
diff --git a/src/tests/globalStyles.test.ts b/src/tests/globalStyles.test.ts
index d44cc51..a7017c8 100644
--- a/src/tests/globalStyles.test.ts
+++ b/src/tests/globalStyles.test.ts
@@ -2,4 +2,4 @@ import globalStyles from "../globalStyles";
test("global styles emotion css compiles", () => {
expect(globalStyles.styles).not.toBeUndefined();
-})
+});
diff --git a/src/tests/pages/CallbackPage.test.tsx b/src/tests/pages/CallbackPage.test.tsx
index e878577..9049ca3 100644
--- a/src/tests/pages/CallbackPage.test.tsx
+++ b/src/tests/pages/CallbackPage.test.tsx
@@ -1,23 +1,23 @@
-import React from 'react';
-import { render } from '@testing-library/react';
+import React from "react";
+import { render } from "@testing-library/react";
-import CallbackPage from '../../pages/CallbackPage';
+import CallbackPage from "../../pages/CallbackPage";
-test('callback page renders provided code', () => {
+test("callback page renders provided code", () => {
global.opener = {
postMessage: jest.fn()
- }
+ };
- let mockLocation = new URL("https://forms.pythondiscord.com/authorize?code=abcdef");
+ const mockLocation = new URL("https://forms.pythondiscord.com/authorize?code=abcdef");
- Object.defineProperty(global, "location", {value: mockLocation})
+ Object.defineProperty(global, "location", {value: mockLocation});
- let comp = <CallbackPage />;
+ const comp = <CallbackPage />;
const { getByText } = render(comp);
- let codeText = getByText(/Code is abcdef/);
+ const codeText = getByText(/Code is abcdef/);
expect(codeText).toBeInTheDocument();
- expect(global.opener.postMessage).toBeCalledTimes(1)
+ expect(global.opener.postMessage).toBeCalledTimes(1);
});
diff --git a/src/tests/pages/FormPage.test.tsx b/src/tests/pages/FormPage.test.tsx
index 7bfc763..f7ecc32 100644
--- a/src/tests/pages/FormPage.test.tsx
+++ b/src/tests/pages/FormPage.test.tsx
@@ -1,28 +1,28 @@
-import React from 'react';
-import { render } from '@testing-library/react';
+import React from "react";
+import { render } from "@testing-library/react";
import { createMemoryHistory } from "history";
import { Route, BrowserRouter as Router } from "react-router-dom";
-import FormPage from '../../pages/FormPage';
+import FormPage from "../../pages/FormPage";
import * as forms from "../../api/forms";
-test('renders specific form page with loading bar', () => {
+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>);
// If we rendered the headerbar we rendered the forms page.
- let headerBar = getByText(/Loading.../);
+ const headerBar = getByText(/Loading.../);
expect(headerBar).toBeInTheDocument();
});
-test('calls api method to load form', () => {
+test("calls api method to load form", () => {
const history = createMemoryHistory();
history.push("/form/ban-appeals");
- let oldImpl = forms.getForm;
+ const oldImpl = forms.getForm;
Object.defineProperty(forms, "getForm", {value: jest.fn(oldImpl)});
diff --git a/src/tests/pages/LandingPage.test.tsx b/src/tests/pages/LandingPage.test.tsx
index 23195bd..5635e63 100644
--- a/src/tests/pages/LandingPage.test.tsx
+++ b/src/tests/pages/LandingPage.test.tsx
@@ -1,11 +1,11 @@
-import React from 'react';
-import { render } from '@testing-library/react';
+import React from "react";
+import { render } from "@testing-library/react";
import LandingPage from "../../pages/LandingPage";
import * as forms from "../../api/forms";
import { BrowserRouter as Router } from "react-router-dom";
-import { QuestionType } from '../../api/question';
+import { QuestionType } from "../../api/question";
const testingForm: forms.Form = {
"id": "testing-form",
@@ -20,15 +20,15 @@ const testingForm: forms.Form = {
"data": {}
}
]
-}
+};
-test('renders landing page', () => {
+test("renders landing page", () => {
const setForms = jest.fn(() => [testingForm]);
Object.defineProperty(forms, "getForms", setForms);
const handleForms = jest.spyOn(React, "useState");
- handleForms.mockImplementation(_value => [[testingForm], setForms]);
+ handleForms.mockImplementation(() => [[testingForm], setForms]);
const { getByText } = render(<Router><LandingPage /></Router>);
// If we rendered the headerbar we rendered the landing page.
- let headerBar = getByText(/Python Discord Forms/);
+ const headerBar = getByText(/Python Discord Forms/);
expect(headerBar).toBeInTheDocument();
});