Browse Source

Redoing unit tests, starting with ApiInfo

Kirk Trombley 3 years ago
parent
commit
00919aeac3
69 changed files with 139 additions and 11278 deletions
  1. 2 1
      README.md
  2. 2 1
      client/package.json
  3. 6 8
      client/src/components/util/ApiInfo.jsx
  4. 1 5
      client/src/setupTests.js
  5. 22 12
      client/src/tests/ApiInfo.test.js
  6. 0 42
      client/src/tests/App.test.js
  7. 0 22
      client/src/tests/ClickMarkerMap.test.js
  8. 0 62
      client/src/tests/ClickToCopy.test.js
  9. 0 93
      client/src/tests/DelayedButton.test.js
  10. 0 535
      client/src/tests/Dropdown.test.js
  11. 0 24
      client/src/tests/ErrorModal.test.js
  12. 0 134
      client/src/tests/GameCreationForm.test.js
  13. 0 194
      client/src/tests/GamePanel.hooks.test.js
  14. 0 70
      client/src/tests/GamePanel.test.js
  15. 0 35
      client/src/tests/GameSummary.test.js
  16. 0 100
      client/src/tests/GuessPane.hooks.test.js
  17. 0 105
      client/src/tests/GuessPane.test.js
  18. 0 50
      client/src/tests/HomePage.test.js
  19. 0 79
      client/src/tests/JoinForm.test.js
  20. 0 40
      client/src/tests/LinkedGame.test.js
  21. 0 10
      client/src/tests/Loading.test.js
  22. 0 217
      client/src/tests/Lobby.test.js
  23. 0 70
      client/src/tests/PositionedStreetView.test.js
  24. 0 33
      client/src/tests/RaceMode.test.js
  25. 0 77
      client/src/tests/RoundSummary.test.js
  26. 0 20
      client/src/tests/RoundTimer.test.js
  27. 0 135
      client/src/tests/Scoreboard.test.js
  28. 0 21
      client/src/tests/StartGame.test.js
  29. 0 252
      client/src/tests/SummaryMap.test.js
  30. 6 6
      client/src/tests/__snapshots__/ApiInfo.test.js.snap
  31. 0 134
      client/src/tests/__snapshots__/App.test.js.snap
  32. 0 7
      client/src/tests/__snapshots__/ClickMarkerMap.test.js.snap
  33. 0 189
      client/src/tests/__snapshots__/ClickToCopy.test.js.snap
  34. 0 45
      client/src/tests/__snapshots__/DelayedButton.test.js.snap
  35. 0 512
      client/src/tests/__snapshots__/Dropdown.test.js.snap
  36. 0 70
      client/src/tests/__snapshots__/ErrorModal.test.js.snap
  37. 0 2258
      client/src/tests/__snapshots__/GameCreationForm.test.js.snap
  38. 0 103
      client/src/tests/__snapshots__/GamePanel.hooks.test.js.snap
  39. 0 49
      client/src/tests/__snapshots__/GamePanel.test.js.snap
  40. 0 35
      client/src/tests/__snapshots__/GameSummary.test.js.snap
  41. 0 508
      client/src/tests/__snapshots__/GuessPane.test.js.snap
  42. 0 99
      client/src/tests/__snapshots__/HomePage.test.js.snap
  43. 0 313
      client/src/tests/__snapshots__/JoinForm.test.js.snap
  44. 0 25
      client/src/tests/__snapshots__/LinkedGame.test.js.snap
  45. 0 12
      client/src/tests/__snapshots__/Loading.test.js.snap
  46. 0 372
      client/src/tests/__snapshots__/Lobby.test.js.snap
  47. 0 69
      client/src/tests/__snapshots__/PositionedStreetView.test.js.snap
  48. 0 27
      client/src/tests/__snapshots__/RaceMode.test.js.snap
  49. 0 79
      client/src/tests/__snapshots__/RoundSummary.test.js.snap
  50. 0 18
      client/src/tests/__snapshots__/RoundTimer.test.js.snap
  51. 0 562
      client/src/tests/__snapshots__/Scoreboard.test.js.snap
  52. 0 51
      client/src/tests/__snapshots__/StartGame.test.js.snap
  53. 0 238
      client/src/tests/__snapshots__/SummaryMap.test.js.snap
  54. 0 878
      client/src/tests/__snapshots__/apiMethods.test.js.snap
  55. 0 13
      client/src/tests/__snapshots__/flagLookup.test.js.snap
  56. 0 256
      client/src/tests/__snapshots__/gameStore.test.js.snap
  57. 0 13
      client/src/tests/__snapshots__/getColorGenerator.test.js.snap
  58. 0 514
      client/src/tests/__snapshots__/localStorageMethods.test.js.snap
  59. 0 102
      client/src/tests/__snapshots__/markers.test.js.snap
  60. 0 53
      client/src/tests/__snapshots__/store.test.js.snap
  61. 0 564
      client/src/tests/apiMethods.test.js
  62. 0 12
      client/src/tests/flagLookup.test.js
  63. 0 263
      client/src/tests/gameStore.test.js
  64. 0 60
      client/src/tests/geocoding.test.js
  65. 0 13
      client/src/tests/getColorGenerator.test.js
  66. 0 192
      client/src/tests/localStorageMethods.test.js
  67. 0 38
      client/src/tests/markers.test.js
  68. 0 74
      client/src/tests/store.test.js
  69. 100 5
      client/yarn.lock

+ 2 - 1
README.md

@@ -150,10 +150,11 @@ POST /game/{game_id}/round/{round}/timeout/{player_id}
 
 ## Local Dev
 
-Change the proxy line in package.json to point to live server
+Change the proxy line in package.json to point to live vs local server
 
 ```json
   "proxy": "https://hiram.services/",
+  "proxy": "http://localhost:5000/",
 ```
 
 ## Next Steps

+ 2 - 1
client/package.json

@@ -30,7 +30,7 @@
     "eject": "react-scripts eject",
     "deploy": "scp -r build hiram:/opt/terrassumptions/srv/build-$(date +'%Y-%m-%dT%H:%M:%S')"
   },
-  "proxy": "http://localhost:5000/",
+  "proxy": "https://hiram.services/",
   "prettier": {
     "arrowParens": "avoid"
   },
@@ -53,6 +53,7 @@
     ]
   },
   "devDependencies": {
+    "@testing-library/jest-dom": "^5.16.4",
     "@testing-library/react": "^13.0.0",
     "eslint-config-airbnb": "^18.2.1",
     "eslint-config-prettier": "^8.2.0",

+ 6 - 8
client/src/components/util/ApiInfo.jsx

@@ -1,13 +1,6 @@
 import { useEffect, useState } from "react";
 import { getStatus } from "../../domain/apiMethods";
 
-export const PureApiInfo = ({ status, version }) =>
-  status === "healthy" ? (
-    <p>API Version: {version}</p>
-  ) : (
-    <p>Unable to communicate with API server! Error: {status}</p>
-  );
-
 const ApiInfo = () => {
   const [data, setData] = useState(null);
   useEffect(() => {
@@ -19,7 +12,12 @@ const ApiInfo = () => {
   }
 
   const { status, version } = data;
-  return <PureApiInfo status={status} version={version} />;
+  
+  return status === "healthy" ? (
+    <p>API Version: {version}</p>
+  ) : (
+    <p>Unable to communicate with API server! Error: {status}</p>
+  );
 };
 
 export default ApiInfo;

+ 1 - 5
client/src/setupTests.js

@@ -1,8 +1,4 @@
-import { configure } from 'enzyme';
-import Adapter from '@wojtekmaj/enzyme-adapter-react-17';
-import 'jest-enzyme';
-
-configure({ adapter: new Adapter() });
+import '@testing-library/jest-dom'
 
 global.localStorage = {
   getItem: jest.fn(),

+ 22 - 12
client/src/tests/ApiInfo.test.js

@@ -1,24 +1,34 @@
 import React from "react";
-import { shallow } from "enzyme";
-import ApiInfo, { PureApiInfo } from "../components/util/ApiInfo";
+import { render, waitFor } from "@testing-library/react";
+import ApiInfo from "../components/util/ApiInfo";
+import { getStatus } from "../domain/apiMethods";
 
 jest.mock("../domain/apiMethods");
 
 describe("ApiInfo", () => {
-  it("renders", () => {
-    const rendered = shallow(<ApiInfo />);
-    expect(rendered).toMatchSnapshot();
+  it("renders and matches snapshot", () => {
+    getStatus.mockResolvedValue(null);
+    const { container } = render(<ApiInfo />);
+    expect(container.firstChild).toMatchSnapshot();
   });
 
-  describe("PureApiInfo", () => {
-    it("renders", () => {
-      const rendered = shallow(<PureApiInfo status="healthy" version="test" />);
-      expect(rendered).toMatchSnapshot();
+  it("renders and matches healthy snapshot", async () => {
+    getStatus.mockResolvedValue({
+      status: "healthy",
+      version: "test",
     });
+    const { container, getByText } = render(<ApiInfo />);
+    await waitFor(() => expect(getByText("API Version: test")).toBeInTheDocument())
+    expect(container.firstChild).toMatchSnapshot();
+  });
 
-    it("renders for unhealthy", () => {
-      const rendered = shallow(<PureApiInfo status="bad" version="test" />);
-      expect(rendered).toMatchSnapshot();
+  it("renders and matches unhealthy snapshot", async () => {
+    getStatus.mockResolvedValue({
+      status: "unhealthy",
+      version: "test",
     });
+    const { container, getByText } = render(<ApiInfo />);
+    await waitFor(() => expect(getByText("Unable to communicate with API server! Error: unhealthy")).toBeInTheDocument())
+    expect(container.firstChild).toMatchSnapshot();
   });
 });

+ 0 - 42
client/src/tests/App.test.js

@@ -1,42 +0,0 @@
-import React from "react";
-import { shallow } from "enzyme";
-import App, { Header, Footer, paramRouter, State } from "../App";
-
-jest.mock("../domain/gameStore");
-
-import { dispatch } from "../domain/gameStore";
-
-describe("App", () => {
-  it("renders", () => {
-    const rendered = shallow(<App />);
-    expect(rendered).toMatchSnapshot();
-  });
-
-  describe("Header", () => {
-    it("renders", () => {
-      const rendered = shallow(<Header />);
-      expect(rendered).toMatchSnapshot();
-    });
-  });
-
-  describe("Footer", () => {
-    it("renders", () => {
-      const rendered = shallow(<Footer />);
-      expect(rendered).toMatchSnapshot();
-    });
-  });
-
-  describe("paramRouter", () => {
-    it("routes summary param", () => {
-      paramRouter.summary("test-game-id");
-      expect(dispatch.goToSummary).toMatchSnapshot();
-    });
-  });
-
-  describe("State", () => {
-    it("renders", () => {
-      const rendered = shallow(<State>Test</State>);
-      expect(rendered).toMatchSnapshot();
-    });
-  });
-});

+ 0 - 22
client/src/tests/ClickMarkerMap.test.js

@@ -1,22 +0,0 @@
-import React from "react";
-import { shallow } from "enzyme";
-import ClickMarkerMap from "../components/screens/GamePanel/GuessPane/ClickMarkerMap";
-
-jest.mock("../hooks/useMapBounds");
-jest.mock("../hooks/useMap");
-jest.mock("../hooks/useClickMarker");
-jest.mock("../hooks/useGameInfo");
-
-import { useGameConfig } from "../hooks/useGameInfo";
-import useMapBounds from "../hooks/useMapBounds";
-import useMap from "../hooks/useMap";
-
-describe("ClickMarkerMap", () => {
-  it("renders", () => {
-    useMap.mockReturnValue("map");
-    useGameConfig.mockReturnValue({ countryLock: "lock" });
-    const rendered = shallow(<ClickMarkerMap />);
-    expect(rendered).toMatchSnapshot();
-    expect(useMapBounds).toHaveBeenCalledWith("map", "lock");
-  });
-});

+ 0 - 62
client/src/tests/ClickToCopy.test.js

@@ -1,62 +0,0 @@
-import React from "react";
-import { shallow, mount } from "enzyme";
-import ClickToCopy from "../components/util/ClickToCopy";
-
-describe("ClickToCopy", () => {
-  it("renders without crashing", () => {
-    const rendered = shallow(<ClickToCopy text="test-text" />);
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("renders children", () => {
-    const inner = <span>other text</span>;
-    const rendered = shallow(
-      <ClickToCopy text="test-text">{inner}</ClickToCopy>
-    );
-    expect(rendered).toMatchSnapshot();
-    expect(rendered).toContainReact(inner);
-  });
-
-  it("uses children if no text provided", () => {
-    const inner = <span>other text</span>;
-    const rendered = shallow(<ClickToCopy>{inner}</ClickToCopy>);
-    expect(rendered).toMatchSnapshot();
-    expect(rendered).toContainReact(inner);
-  });
-
-  it("copies text when clicked", () => {
-    document.execCommand = jest.fn();
-    const rendered = mount(<ClickToCopy text="test-text" />);
-    rendered.find("span").first().simulate("click");
-    expect(document.execCommand).toBeCalledWith("copy");
-  });
-
-  it("copies text when receives keydown Enter", () => {
-    document.execCommand = jest.fn();
-    const rendered = mount(<ClickToCopy text="test-text" />);
-    rendered.find("span").first().simulate("keydown", { key: "Enter" });
-    expect(document.execCommand).toBeCalledWith("copy");
-  });
-
-  it("does not copy text when receives other keydowns", () => {
-    document.execCommand = jest.fn();
-    const rendered = mount(<ClickToCopy text="test-text" />);
-    rendered.find("span").first().simulate("keydown", { key: "Escape" });
-    expect(document.execCommand).not.toHaveBeenCalled();
-  });
-
-  it("shows tooltip when hovered", () => {
-    const rendered = mount(<ClickToCopy text="test-text" />);
-    rendered.find("span").first().simulate("mouseover");
-    expect(rendered).toMatchSnapshot();
-    rendered.find("span").first().simulate("click");
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("resets when focused", () => {
-    const rendered = mount(<ClickToCopy text="test-text" />);
-    rendered.find("span").first().simulate("click");
-    rendered.find("span").first().simulate("focus");
-    expect(rendered).toMatchSnapshot();
-  });
-});

+ 0 - 93
client/src/tests/DelayedButton.test.js

@@ -1,93 +0,0 @@
-import React from "react";
-import { shallow } from "enzyme";
-import DelayedButton, {
-  CountdownButton,
-} from "../components/util/DelayedButton";
-
-describe("DelayedButton", () => {
-  it("renders", () => {
-    const onEnd = jest.fn();
-    const countDownFormatter = jest.fn();
-    const seconds = 10;
-    const buttonClass = "test-button";
-    const rendered = shallow(
-      <DelayedButton
-        autoFocus
-        {...{ onEnd, countDownFormatter, seconds, buttonClass }}
-      >
-        test
-      </DelayedButton>
-    );
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("starts timer after click", () => {
-    const onEnd = jest.fn();
-    const countDownFormatter = jest.fn();
-    const seconds = 10;
-    const buttonClass = "test-button";
-    const rendered = shallow(
-      <DelayedButton
-        autoFocus
-        {...{ onEnd, countDownFormatter, seconds, buttonClass }}
-      >
-        test
-      </DelayedButton>
-    );
-    rendered.find("button").first().simulate("click");
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("resets self after second click", () => {
-    const onEnd = jest.fn();
-    const countDownFormatter = jest.fn();
-    const seconds = 10;
-    const buttonClass = "test-button";
-    const rendered = shallow(
-      <DelayedButton
-        autoFocus
-        {...{ onEnd, countDownFormatter, seconds, buttonClass }}
-      >
-        test
-      </DelayedButton>
-    );
-    rendered.find("button").first().simulate("click");
-    rendered.find("CountdownButton").first().prop("onCancelled")();
-    expect(rendered).toMatchSnapshot();
-  });
-
-  describe("CountdownButton", () => {
-    it("renders", () => {
-      const onCancelled = jest.fn();
-      const onEnd = jest.fn();
-      const formatter = jest.fn();
-      formatter.mockReturnValue("formatted");
-      const seconds = 10;
-      const buttonClass = "test-button";
-      const rendered = shallow(
-        <CountdownButton
-          autoFocus
-          {...{ onCancelled, onEnd, formatter, seconds, buttonClass }}
-        />
-      );
-      expect(formatter).toHaveBeenCalled();
-      expect(rendered).toMatchSnapshot();
-    });
-
-    it("cancels on click", () => {
-      const onCancelled = jest.fn();
-      const onEnd = jest.fn();
-      const formatter = jest.fn();
-      const seconds = 10;
-      const buttonClass = "test-button";
-      const rendered = shallow(
-        <CountdownButton
-          autoFocus
-          {...{ onCancelled, onEnd, formatter, seconds, buttonClass }}
-        />
-      );
-      rendered.find("button").first().simulate("click");
-      expect(onCancelled).toHaveBeenCalled();
-    });
-  });
-});

+ 0 - 535
client/src/tests/Dropdown.test.js

@@ -1,535 +0,0 @@
-import React from "react";
-import { shallow } from "enzyme";
-import {
-  CountryDropdown,
-  CountryItem,
-  Dropdown,
-  DropdownGroup,
-  findSelectedDisplay,
-  Item,
-} from "../components/util/GameCreationForm/Dropdown";
-
-jest.mock("../domain/flagLookup");
-
-import flagLookup from "../domain/flagLookup";
-
-describe("DropdownGroup", () => {
-  it("renders with no dropdowns", () => {
-    const rendered = shallow(<DropdownGroup />);
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("renders with dropdowns", () => {
-    const rendered = shallow(
-      <DropdownGroup>
-        <Dropdown open="dd1" />
-        <Dropdown open="dd2" />
-        <Dropdown open="dd3" />
-      </DropdownGroup>
-    );
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("can have a dropdown opened", () => {
-    const rendered = shallow(
-      <DropdownGroup>
-        <Dropdown open="dd1" />
-        <Dropdown open="dd2" />
-        <Dropdown open="dd3" />
-      </DropdownGroup>
-    );
-    rendered.find("Dropdown").at(1).prop("onClick")();
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("can have a dropdown closed after opening", () => {
-    const rendered = shallow(
-      <DropdownGroup>
-        <Dropdown open="dd1" />
-        <Dropdown open="dd2" />
-        <Dropdown open="dd3" />
-      </DropdownGroup>
-    );
-    rendered.find("Dropdown").at(1).prop("onClick")();
-    rendered.find("Dropdown").at(1).prop("onClick")();
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("selecting a dropdown re-closes it", () => {
-    const onSelect = jest.fn();
-    const rendered = shallow(
-      <DropdownGroup>
-        <Dropdown open="dd1" />
-        <Dropdown open="dd2" onSelect={onSelect} />
-        <Dropdown open="dd3" />
-      </DropdownGroup>
-    );
-    rendered.find("Dropdown").at(1).prop("onClick")();
-    rendered.find("Dropdown").at(1).prop("onSelect")("test");
-    expect(rendered).toMatchSnapshot();
-    expect(onSelect).toHaveBeenCalledWith("test");
-  });
-});
-
-describe("Dropdown", () => {
-  it("renders closed", () => {
-    const onSelect = jest.fn();
-    const onClick = jest.fn();
-    const rendered = shallow(<Dropdown {...{ onSelect, onClick }} />);
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("passes button class", () => {
-    const onSelect = jest.fn();
-    const onClick = jest.fn();
-    const rendered = shallow(
-      <Dropdown buttonClass="test-button-class" {...{ onSelect, onClick }} />
-    );
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("renders with no items", () => {
-    const onSelect = jest.fn();
-    const onClick = jest.fn();
-    const rendered = shallow(<Dropdown open {...{ onSelect, onClick }} />);
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("renders with items", () => {
-    const onSelect = jest.fn();
-    const onClick = jest.fn();
-    const rendered = shallow(
-      <Dropdown open {...{ onSelect, onClick }}>
-        <Item value="test1" />
-        <Item value="test2" />
-      </Dropdown>
-    );
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("can be clicked", () => {
-    const onSelect = jest.fn();
-    const onClick = jest.fn();
-    const rendered = shallow(
-      <Dropdown {...{ onSelect, onClick }}>
-        <Item value="test1" />
-        <Item value="test2" />
-      </Dropdown>
-    );
-    rendered.find("div.button").first().simulate("click");
-    expect(onClick).toHaveBeenCalled();
-  });
-
-  it("can be selected with Enter", () => {
-    const onSelect = jest.fn();
-    const onClick = jest.fn();
-    const rendered = shallow(
-      <Dropdown {...{ onSelect, onClick }}>
-        <Item value="test1" />
-        <Item value="test2" />
-      </Dropdown>
-    );
-    rendered.find("div.button").first().simulate("keydown", { key: "Enter" });
-    expect(onClick).toHaveBeenCalled();
-  });
-
-  it("cannot be selected with other keydowns", () => {
-    const onSelect = jest.fn();
-    const onClick = jest.fn();
-    const rendered = shallow(
-      <Dropdown {...{ onSelect, onClick }}>
-        <Item value="test1" />
-        <Item value="test2" />
-      </Dropdown>
-    );
-    rendered.find("div.button").first().simulate("keydown", { key: "Escape" });
-    expect(onClick).not.toHaveBeenCalled();
-  });
-
-  it("responds to item selection", () => {
-    const onSelect = jest.fn();
-    const onClick = jest.fn();
-    const rendered = shallow(
-      <Dropdown open {...{ onSelect, onClick }}>
-        <Item value="test1" />
-        <Item value="test2" />
-      </Dropdown>
-    );
-    rendered.find("Item").first().prop("onSelect")("value", "display");
-    expect(onSelect).toHaveBeenCalledWith("value");
-    expect(rendered).toMatchSnapshot();
-  });
-
-  describe("findSelectedDisplay", () => {
-    it("returns null when nothing is selected", () => {
-      expect(findSelectedDisplay()).toBeNull();
-    });
-
-    it("extracts the display of the selected element", () => {
-      expect(
-        findSelectedDisplay("two", [
-          <Item display="1" value="one" />,
-          <Item display="2" value="two" />,
-          <Item display="3" value="three" />,
-        ])
-      ).toBe("2");
-    });
-
-    it("extracts the value of the selected element if there is no display", () => {
-      expect(
-        findSelectedDisplay("two", [
-          <Item value="one" />,
-          <Item value="two" />,
-          <Item value="three" />,
-        ])
-      ).toBe("two");
-    });
-
-    it("returns null if there is no matching element", () => {
-      expect(
-        findSelectedDisplay("four", [
-          <Item value="one" />,
-          <Item value="two" />,
-          <Item value="three" />,
-        ])
-      ).toBeNull();
-    });
-
-    it("returns the first display found if there is more than one matching element", () => {
-      expect(
-        findSelectedDisplay("two", [
-          <Item display="1" value="one" />,
-          <Item display="2" value="two" />,
-          <Item display="3" value="three" />,
-          <Item display="4" value="two" />,
-        ])
-      ).toBe("2");
-    });
-  });
-});
-
-describe("CountryItem", () => {
-  it("renders", () => {
-    flagLookup.mockReturnValue("flag");
-    const rendered = shallow(
-      <CountryItem code="test-code" country="test-country" />
-    );
-    expect(rendered).toMatchSnapshot();
-    expect(flagLookup).toHaveBeenCalledWith("test-code");
-  });
-
-  it("responds to click", () => {
-    flagLookup.mockReturnValue("flag");
-    const onSelect = jest.fn();
-    const rendered = shallow(
-      <CountryItem
-        onSelect={onSelect}
-        code="test-code"
-        country="test-country"
-      />
-    );
-    rendered.simulate("click");
-    expect(onSelect).toHaveBeenCalledWith("test-code");
-  });
-
-  it("responds to keydown Enter", () => {
-    flagLookup.mockReturnValue("flag");
-    const onSelect = jest.fn();
-    const rendered = shallow(
-      <CountryItem
-        onSelect={onSelect}
-        code="test-code"
-        country="test-country"
-      />
-    );
-    rendered.simulate("keydown", { key: "Enter" });
-    expect(onSelect).toHaveBeenCalledWith("test-code");
-  });
-
-  it("responds to click", () => {
-    flagLookup.mockReturnValue("flag");
-    const onSelect = jest.fn();
-    const rendered = shallow(
-      <CountryItem
-        onSelect={onSelect}
-        code="test-code"
-        country="test-country"
-      />
-    );
-    rendered.simulate("keydown", { key: "Escape" });
-    expect(onSelect).not.toHaveBeenCalled();
-  });
-});
-
-describe("CountryDropdown", () => {
-  it("renders closed", () => {
-    flagLookup.mockReturnValue("flag");
-    const countryLookup = jest.fn();
-    const selected = "selected";
-    const onSelect = jest.fn();
-    const onClick = jest.fn();
-    const rendered = shallow(
-      <CountryDropdown {...{ countryLookup, selected, onSelect, onClick }} />
-    );
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("renders", () => {
-    flagLookup.mockReturnValue("flag");
-    const countryLookup = jest.fn();
-    const selected = "selected";
-    const onSelect = jest.fn();
-    const onClick = jest.fn();
-    const rendered = shallow(
-      <CountryDropdown
-        open
-        {...{ countryLookup, selected, onSelect, onClick }}
-      />
-    );
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("renders with countries", () => {
-    flagLookup.mockReturnValue("flag");
-    const countryLookup = jest.fn();
-    countryLookup.mockReturnValue([
-      { item: { country: "c1", alpha2: "a21" } },
-      { item: { country: "c2", alpha2: "a22" } },
-      { item: { country: "c3", alpha2: "a23" } },
-    ]);
-    const selected = "selected";
-    const onSelect = jest.fn();
-    const onClick = jest.fn();
-    const rendered = shallow(
-      <CountryDropdown
-        open
-        {...{ countryLookup, selected, onSelect, onClick }}
-      />
-    );
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("can be clicked", () => {
-    flagLookup.mockReturnValue("flag");
-    const countryLookup = jest.fn();
-    countryLookup.mockReturnValue([
-      { item: { country: "c1", alpha2: "a21" } },
-      { item: { country: "c2", alpha2: "a22" } },
-      { item: { country: "c3", alpha2: "a23" } },
-    ]);
-    const selected = "selected";
-    const onSelect = jest.fn();
-    const onClick = jest.fn();
-    const rendered = shallow(
-      <CountryDropdown
-        open
-        {...{ countryLookup, selected, onSelect, onClick }}
-      />
-    );
-    rendered.find("div.button").first().simulate("click");
-    expect(onClick).toHaveBeenCalled();
-  });
-
-  it("can be selected with Enter", () => {
-    flagLookup.mockReturnValue("flag");
-    const countryLookup = jest.fn();
-    countryLookup.mockReturnValue([
-      { item: { country: "c1", alpha2: "a21" } },
-      { item: { country: "c2", alpha2: "a22" } },
-      { item: { country: "c3", alpha2: "a23" } },
-    ]);
-    const selected = "selected";
-    const onSelect = jest.fn();
-    const onClick = jest.fn();
-    const rendered = shallow(
-      <CountryDropdown
-        open
-        {...{ countryLookup, selected, onSelect, onClick }}
-      />
-    );
-    rendered.find("div.button").first().simulate("keydown", { key: "Enter" });
-    expect(onClick).toHaveBeenCalled();
-  });
-
-  it("cannot be selected with other keydowns", () => {
-    flagLookup.mockReturnValue("flag");
-    const countryLookup = jest.fn();
-    countryLookup.mockReturnValue([
-      { item: { country: "c1", alpha2: "a21" } },
-      { item: { country: "c2", alpha2: "a22" } },
-      { item: { country: "c3", alpha2: "a23" } },
-    ]);
-    const selected = "selected";
-    const onSelect = jest.fn();
-    const onClick = jest.fn();
-    const rendered = shallow(
-      <CountryDropdown
-        open
-        {...{ countryLookup, selected, onSelect, onClick }}
-      />
-    );
-    rendered.find("div.button").first().simulate("keydown", { key: "Escape" });
-    expect(onClick).not.toHaveBeenCalled();
-  });
-
-  it("can have a country selected", () => {
-    flagLookup.mockReturnValue("flag");
-    const countryLookup = jest.fn();
-    countryLookup.mockReturnValue([
-      { item: { country: "c1", alpha2: "a21" } },
-      { item: { country: "c2", alpha2: "a22" } },
-      { item: { country: "c3", alpha2: "a23" } },
-    ]);
-    const selected = "selected";
-    const onSelect = jest.fn();
-    const onClick = jest.fn();
-    const rendered = shallow(
-      <CountryDropdown
-        open
-        {...{ countryLookup, selected, onSelect, onClick }}
-      />
-    );
-    rendered.find("CountryItem").first().prop("onSelect")();
-    expect(onSelect).toHaveBeenCalled();
-  });
-
-  it("selects country based on searchbox", () => {
-    flagLookup.mockReturnValue("flag");
-    const countryLookup = jest.fn();
-    countryLookup.mockReturnValue([
-      { item: { country: "c1", alpha2: "a21" } },
-      { item: { country: "c2", alpha2: "a22" } },
-      { item: { country: "c3", alpha2: "a23" } },
-    ]);
-    const selected = "selected";
-    const onSelect = jest.fn();
-    const onClick = jest.fn();
-    const rendered = shallow(
-      <CountryDropdown
-        open
-        {...{ countryLookup, selected, onSelect, onClick }}
-      />
-    );
-    rendered
-      .find("input")
-      .first()
-      .simulate("change", { target: { value: "changed" } });
-    expect(countryLookup).toHaveBeenCalledWith("changed");
-  });
-
-  it("can have first option selected with Enter", () => {
-    flagLookup.mockReturnValue("flag");
-    const countryLookup = jest.fn();
-    countryLookup.mockReturnValue([
-      { item: { country: "c1", alpha2: "a21" } },
-      { item: { country: "c2", alpha2: "a22" } },
-      { item: { country: "c3", alpha2: "a23" } },
-    ]);
-    const selected = "selected";
-    const onSelect = jest.fn();
-    const onClick = jest.fn();
-    const rendered = shallow(
-      <CountryDropdown
-        open
-        {...{ countryLookup, selected, onSelect, onClick }}
-      />
-    );
-    rendered.find("input").first().simulate("keydown", { key: "Enter" });
-    expect(onSelect).toHaveBeenCalledWith("a21");
-  });
-
-  it("can have previously selected option selected with Escape", () => {
-    flagLookup.mockReturnValue("flag");
-    const countryLookup = jest.fn();
-    countryLookup.mockReturnValue([
-      { item: { country: "c1", alpha2: "a21" } },
-      { item: { country: "c2", alpha2: "a22" } },
-      { item: { country: "c3", alpha2: "a23" } },
-    ]);
-    const selected = "selected";
-    const onSelect = jest.fn();
-    const onClick = jest.fn();
-    const rendered = shallow(
-      <CountryDropdown
-        open
-        {...{ countryLookup, selected, onSelect, onClick }}
-      />
-    );
-    rendered.find("input").first().simulate("keydown", { key: "Escape" });
-    expect(onSelect).toHaveBeenCalledWith("selected");
-  });
-
-  it("does not select from other keydowns", () => {
-    flagLookup.mockReturnValue("flag");
-    const countryLookup = jest.fn();
-    countryLookup.mockReturnValue([
-      { item: { country: "c1", alpha2: "a21" } },
-      { item: { country: "c2", alpha2: "a22" } },
-      { item: { country: "c3", alpha2: "a23" } },
-    ]);
-    const selected = "selected";
-    const onSelect = jest.fn();
-    const onClick = jest.fn();
-    const rendered = shallow(
-      <CountryDropdown
-        open
-        {...{ countryLookup, selected, onSelect, onClick }}
-      />
-    );
-    rendered.find("input").first().simulate("keydown", { key: "Tab" });
-    expect(onSelect).not.toHaveBeenCalled();
-  });
-});
-
-describe("Item", () => {
-  it("renders with no text", () => {
-    const onSelect = jest.fn();
-    const display = "display";
-    const value = "value";
-    const rendered = shallow(<Item {...{ onSelect, display, value }} />);
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("responds to click", () => {
-    const onSelect = jest.fn();
-    const display = "display";
-    const value = "value";
-    const rendered = shallow(<Item {...{ onSelect, display, value }} />);
-    rendered.simulate("click");
-    expect(onSelect).toHaveBeenCalledWith(value, display);
-  });
-
-  it("responds to enter", () => {
-    const onSelect = jest.fn();
-    const display = "display";
-    const value = "value";
-    const rendered = shallow(<Item {...{ onSelect, display, value }} />);
-    rendered.simulate("keydown", { key: "Enter" });
-    expect(onSelect).toHaveBeenCalledWith(value, display);
-  });
-
-  it("does not respond to other keydowns", () => {
-    const onSelect = jest.fn();
-    const display = "display";
-    const value = "value";
-    const rendered = shallow(<Item {...{ onSelect, display, value }} />);
-    rendered.simulate("keydown", { key: "Escape" });
-    expect(onSelect).not.toHaveBeenCalled();
-  });
-
-  it("responds to click with value when no display", () => {
-    const onSelect = jest.fn();
-    const value = "value";
-    const rendered = shallow(<Item {...{ onSelect, value }} />);
-    rendered.simulate("click");
-    expect(onSelect).toHaveBeenCalledWith(value, value);
-  });
-
-  it("responds to click with children when no display or value", () => {
-    const onSelect = jest.fn();
-    const child = <div>child</div>;
-    const rendered = shallow(<Item {...{ onSelect }}>{child}</Item>);
-    rendered.simulate("click");
-    expect(onSelect).toHaveBeenCalledWith(child, child);
-  });
-});

+ 0 - 24
client/src/tests/ErrorModal.test.js

@@ -1,24 +0,0 @@
-import React from "react";
-import { shallow } from "enzyme";
-import ErrorModal from "../components/util/GameCreationForm/ErrorModal";
-
-describe("ErrorModal", () => {
-  it("renders", () => {
-    const onClose = jest.fn();
-    const rendered = shallow(<ErrorModal onClose={onClose} />);
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("renders when open", () => {
-    const onClose = jest.fn();
-    const rendered = shallow(<ErrorModal open onClose={onClose} />);
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("calls onClose when closed", () => {
-    const onClose = jest.fn();
-    const rendered = shallow(<ErrorModal open onClose={onClose} />);
-    rendered.find("button").first().simulate("click");
-    expect(onClose).toHaveBeenCalled();
-  });
-});

+ 0 - 134
client/src/tests/GameCreationForm.test.js

@@ -1,134 +0,0 @@
-import { shallow } from "enzyme";
-import React from "react";
-import GameCreationForm from "../components/util/GameCreationForm";
-import { LastSettingsButton } from "../components/util/GameCreationForm/GameCreationForm";
-import { createGame } from "../domain/apiMethods";
-import { COUNTRY_RACE, FROZEN, NORMAL, URBAN } from "../domain/constants";
-import useCountryLookup from "../hooks/useCountryLookup";
-
-jest.mock("../domain/apiMethods");
-jest.mock("../hooks/useCountryLookup");
-
-describe("GameCreationForm", () => {
-  it("renders", () => {
-    useCountryLookup.mockReturnValue("country-lookup");
-    const afterCreate = jest.fn();
-    const rendered = shallow(<GameCreationForm afterCreate={afterCreate} />);
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("creates a game", async () => {
-    useCountryLookup.mockReturnValue("country-lookup");
-    createGame.mockReturnValue("test-game-id");
-    const afterCreate = jest.fn();
-    const rendered = shallow(<GameCreationForm afterCreate={afterCreate} />);
-    await rendered.find("button").first().simulate("click");
-    expect(createGame).toHaveBeenCalled();
-    expect(afterCreate).toHaveBeenCalledWith("test-game-id");
-  });
-
-  it("does nothing after creating a game if no afterCreate given", async () => {
-    useCountryLookup.mockReturnValue("country-lookup");
-    createGame.mockReturnValue("test-game-id");
-    const rendered = shallow(<GameCreationForm />);
-    await rendered.find("button").first().simulate("click");
-    expect(createGame).toHaveBeenCalled();
-  });
-
-  it("handles error creating a game", async () => {
-    useCountryLookup.mockReturnValue("country-lookup");
-    createGame.mockImplementation(() => {
-      throw new Error();
-    });
-    const afterCreate = jest.fn();
-    const rendered = shallow(<GameCreationForm afterCreate={afterCreate} />);
-    await rendered.find("button").first().simulate("click");
-    expect(createGame).toHaveBeenCalled();
-    expect(afterCreate).not.toHaveBeenCalled();
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("can have the error modal closed", async () => {
-    useCountryLookup.mockReturnValue("country-lookup");
-    createGame.mockImplementation(() => {
-      throw new Error();
-    });
-    const rendered = shallow(<GameCreationForm />);
-    await rendered.find("button").first().simulate("click");
-    rendered.find("ErrorModal").first().prop("onClose")();
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("can have the preset dropdown opened", () => {
-    useCountryLookup.mockReturnValue("country-lookup");
-    const rendered = shallow(<GameCreationForm />);
-    rendered.find("Dropdown").first().prop("onClick")();
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("can have presets selected", () => {
-    useCountryLookup.mockReturnValue("country-lookup");
-    const rendered = shallow(<GameCreationForm />);
-    rendered.find("Dropdown").first().prop("onSelect")({
-      timer: 30,
-      rounds: 3,
-      countryLock: "us",
-      generationMethod: URBAN,
-      gameMode: FROZEN,
-      clockMode: NORMAL,
-      scoreMethod: COUNTRY_RACE,
-      roundPointCap: null,
-    });
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("can have previous game settings passed in to enable reuse button", () => {
-    useCountryLookup.mockReturnValue("country-lookup");
-    const rendered = shallow(
-      <GameCreationForm
-        lastSettings={{
-          timer: 30,
-          rounds: 3,
-          countryLock: "us",
-          generationMethod: URBAN,
-          gameMode: FROZEN,
-          clockMode: NORMAL,
-          scoreMethod: COUNTRY_RACE,
-          roundPointCap: null,
-        }}
-      />
-    );
-    expect(rendered).toMatchSnapshot();
-    rendered.find("LastSettingsButton").first().prop("onClick")();
-    expect(rendered).toMatchSnapshot();
-  });
-
-  describe("LastSettingsButton", () => {
-    it("renders", () => {
-      const onClick = jest.fn();
-      const rendered = shallow(<LastSettingsButton onClick={onClick} />);
-      expect(rendered).toMatchSnapshot();
-    });
-
-    it("responds to click", () => {
-      const onClick = jest.fn();
-      const rendered = shallow(<LastSettingsButton onClick={onClick} />);
-      rendered.simulate("click");
-      expect(onClick).toHaveBeenCalled();
-    });
-
-    it("responds to keydown Enter", () => {
-      const onClick = jest.fn();
-      const rendered = shallow(<LastSettingsButton onClick={onClick} />);
-      rendered.simulate("keydown", { key: "Enter" });
-      expect(onClick).toHaveBeenCalled();
-    });
-
-    it("cannot be selected with other keydowns", () => {
-      const onClick = jest.fn();
-      const rendered = shallow(<LastSettingsButton onClick={onClick} />);
-      rendered.simulate("keydown", { key: "Escape" });
-      expect(onClick).not.toHaveBeenCalled();
-    });
-  });
-});

+ 0 - 194
client/src/tests/GamePanel.hooks.test.js

@@ -1,194 +0,0 @@
-import waitForExpect from "wait-for-expect";
-import {
-  useFirstSubmitter,
-  useIsFaded,
-  useIsFinished,
-  usePano,
-  useSavePanoSettings,
-} from "../components/screens/GamePanel/hooks";
-
-jest.mock("react");
-jest.mock("../domain/gameStore");
-jest.mock("../domain/apiMethods");
-jest.mock("../domain/localStorageMethods");
-
-import { useEffect, useRef, useState } from "react";
-import { dispatch, useCurrentRound, useGameId } from "../domain/gameStore";
-import { getFirstSubmitter } from "../domain/apiMethods";
-import {
-  savePanoPositionToLocalStorage,
-  savePanoPovToLocalStorage,
-} from "../domain/localStorageMethods";
-
-describe("GamePanel hooks", () => {
-  describe("useIsFinished", () => {
-    beforeEach(() => {
-      useEffect.mockImplementation(fn => {
-        fn();
-      });
-    });
-    it("returns false if the current round is non-null", () => {
-      useCurrentRound.mockReturnValue("1");
-      expect(useIsFinished()).toBe(false);
-      expect(dispatch.goToSummary).not.toHaveBeenCalled();
-    });
-    it("returns true and goes to summary if the current round is null", () => {
-      useCurrentRound.mockReturnValue(null);
-      expect(useIsFinished()).toBe(true);
-      expect(dispatch.goToSummary).toHaveBeenCalled();
-    });
-  });
-
-  describe("usePano", () => {
-    beforeEach(() => {
-      useEffect.mockImplementation(fn => {
-        fn();
-      });
-    });
-    it("creates a new pano", () => {
-      useRef.mockImplementation(current => ({ current }));
-      const { current } = usePano(
-        { current: "pano-div-ref" },
-        { lat: 1, lng: 2 },
-        { heading: 3, pitch: 4 }
-      );
-      expect(current).toMatchSnapshot();
-    });
-    it("does not create a new pano when one exists and just moves old one", () => {
-      const setPosition = jest.fn();
-      const setPov = jest.fn();
-      useRef.mockImplementation(() => ({ current: { setPosition, setPov } }));
-      const { current } = usePano(
-        { current: "pano-div-ref" },
-        { lat: 1, lng: 2 },
-        { heading: 3, pitch: 4 }
-      );
-      expect(current).toMatchSnapshot();
-      expect(setPosition).toMatchSnapshot();
-      expect(setPov).toMatchSnapshot();
-    });
-  });
-
-  describe("useSavePanoSettings", () => {
-    beforeEach(() => {
-      useEffect.mockImplementation(fn => {
-        const cleanup = fn();
-        if (cleanup) {
-          cleanup();
-        }
-      });
-    });
-    it("attaches listeners to the given panoRef", () => {
-      const listeners = {};
-      useSavePanoSettings({
-        current: {
-          getPosition: () => ({ lat: () => 1, lng: () => 2 }),
-          getPov: () => ({ heading: 3, pitch: 4 }),
-          addListener: (event, fn) => {
-            listeners[event] = fn;
-          },
-        },
-      });
-      expect(savePanoPositionToLocalStorage).not.toHaveBeenCalled();
-      expect(savePanoPovToLocalStorage).not.toHaveBeenCalled();
-      listeners["position_changed"]();
-      expect(savePanoPositionToLocalStorage).toHaveBeenCalledWith(1, 2);
-      listeners["pov_changed"]();
-      expect(savePanoPovToLocalStorage).toHaveBeenCalledWith(3, 4);
-    });
-    it("does nothing when panoRef.current is null", () => {
-      useSavePanoSettings({ current: null });
-      expect(savePanoPositionToLocalStorage).not.toHaveBeenCalled();
-      expect(savePanoPovToLocalStorage).not.toHaveBeenCalled();
-    });
-  });
-
-  describe("useIsFaded", () => {
-    beforeEach(() => {
-      useEffect.mockImplementation(fn => {
-        const cleanup = fn();
-        if (cleanup) {
-          cleanup();
-        }
-      });
-    });
-    it("does nothing when first is null", () => {
-      useState.mockReturnValue([]);
-      useIsFaded(null);
-      expect(setTimeout).not.toHaveBeenCalled();
-    });
-    it("sets faded 2 seconds after first is non-null", () => {
-      const setFaded = jest.fn();
-      useState.mockReturnValue([false, setFaded]);
-      setTimeout.mockImplementation(fn => {
-        fn();
-      });
-      useIsFaded("first-submitter");
-      expect(setFaded).toHaveBeenCalledWith(true);
-      expect(setTimeout).toHaveBeenCalledWith(expect.any(Function), 2000);
-      expect(clearTimeout).toHaveBeenCalled();
-    });
-  });
-
-  describe("useFirstSubmitter", () => {
-    beforeEach(() => {
-      useGameId.mockReturnValue("test-game-id");
-      useCurrentRound.mockReturnValue("1");
-      useEffect.mockImplementation(fn => {
-        const cleanup = fn();
-        if (cleanup) {
-          cleanup();
-        }
-      });
-    });
-    it("queries to find first submitter if not found yet", async () => {
-      const setFirst = jest.fn();
-      useState.mockReturnValue([null, setFirst]);
-      getFirstSubmitter.mockReturnValue("first");
-      dispatch.updateRoundSeconds.mockImplementation(fn => fn(100));
-      useFirstSubmitter("rate", 10);
-      await waitForExpect(() => {
-        expect(setFirst).toHaveBeenCalledWith("first");
-      });
-      expect(dispatch.updateRoundSeconds).toHaveReturnedWith(10);
-      // TODO don't understand why these are losing their call record
-      // expect(setInterval).toHaveBeenCalledWith(expect.any(Function), "rate");
-      // expect(clearInterval).toHaveBeenCalled();
-    });
-    it("uses min of cutoff arg and current round seconds", async () => {
-      const setFirst = jest.fn();
-      useState.mockReturnValue([null, setFirst]);
-      getFirstSubmitter.mockReturnValue("first");
-      dispatch.updateRoundSeconds.mockImplementation(fn => fn(15));
-      useFirstSubmitter("rate", 200);
-      await waitForExpect(() => {
-        expect(setFirst).toHaveBeenCalledWith("first");
-      });
-      expect(dispatch.updateRoundSeconds).toHaveReturnedWith(15);
-      // TODO don't understand why these are losing their call record
-      // expect(setInterval).toHaveBeenCalledWith(expect.anything(), "rate");
-      // expect(clearInterval).toHaveBeenCalled();
-    });
-    it("does nothing after query if it returns null", async () => {
-      const setFirst = jest.fn();
-      useState.mockReturnValue([null, setFirst]);
-      getFirstSubmitter.mockReturnValue(null);
-      dispatch.updateRoundSeconds.mockImplementation(fn => fn(100));
-      useFirstSubmitter("rate", 10);
-      expect(setFirst).not.toHaveBeenCalled();
-      expect(dispatch.updateRoundSeconds).not.toHaveBeenCalled();
-      // TODO don't understand why these are losing their call record
-      // expect(setInterval).toHaveBeenCalledWith(expect.any(Function), "rate");
-      // expect(clearInterval).toHaveBeenCalled();
-    });
-    it("does nothing if there's already a first submitter found", () => {
-      const setFirst = jest.fn();
-      useState.mockReturnValue(["first", setFirst]);
-      const first = useFirstSubmitter("rate", 10);
-      expect(first).toBe("first");
-      expect(setFirst).not.toHaveBeenCalled();
-      expect(setInterval).not.toHaveBeenCalled();
-      expect(clearInterval).not.toHaveBeenCalled();
-    });
-  });
-});

+ 0 - 70
client/src/tests/GamePanel.test.js

@@ -1,70 +0,0 @@
-import React from "react";
-import { shallow } from "enzyme";
-import { DISTANCE, FROZEN, NORMAL, RACE } from "../domain/constants";
-import GamePanel from "../components/screens/GamePanel";
-
-jest.mock("../hooks/usePreventNavigation");
-jest.mock("../hooks/useGameInfo");
-jest.mock("../components/screens/GamePanel/hooks");
-
-import usePreventNavigation from "../hooks/usePreventNavigation";
-import { useGameConfig } from "../hooks/useGameInfo";
-import { useIsFinished } from "../components/screens/GamePanel/hooks";
-
-describe("GamePanel", () => {
-  it("renders for NORMAL game", () => {
-    useIsFinished.mockReturnValue(false);
-    useGameConfig.mockReturnValue({
-      gameMode: NORMAL,
-      clockMode: NORMAL,
-      scoreMethod: DISTANCE,
-      roundPointCap: null,
-    });
-    const rendered = shallow(<GamePanel />);
-    expect(rendered).toMatchSnapshot();
-    expect(usePreventNavigation).toHaveBeenCalled();
-    expect(useGameConfig).toHaveBeenCalled();
-  });
-
-  it("renders for end of game", () => {
-    useIsFinished.mockReturnValue(true);
-    useGameConfig.mockReturnValue({
-      gameMode: NORMAL,
-      clockMode: NORMAL,
-      scoreMethod: DISTANCE,
-      roundPointCap: null,
-    });
-    const rendered = shallow(<GamePanel />);
-    expect(rendered).toMatchSnapshot();
-    expect(usePreventNavigation).toHaveBeenCalled();
-    expect(useGameConfig).toHaveBeenCalled();
-  });
-
-  it("renders for FROZEN game", () => {
-    useIsFinished.mockReturnValue(false);
-    useGameConfig.mockReturnValue({
-      gameMode: FROZEN,
-      clockMode: NORMAL,
-      scoreMethod: DISTANCE,
-      roundPointCap: null,
-    });
-    const rendered = shallow(<GamePanel />);
-    expect(rendered).toMatchSnapshot();
-    expect(usePreventNavigation).toHaveBeenCalled();
-    expect(useGameConfig).toHaveBeenCalled();
-  });
-
-  it("renders for RACE game", () => {
-    useIsFinished.mockReturnValue(false);
-    useGameConfig.mockReturnValue({
-      gameMode: NORMAL,
-      clockMode: RACE,
-      scoreMethod: DISTANCE,
-      roundPointCap: null,
-    });
-    const rendered = shallow(<GamePanel />);
-    expect(rendered).toMatchSnapshot();
-    expect(usePreventNavigation).toHaveBeenCalled();
-    expect(useGameConfig).toHaveBeenCalled();
-  });
-});

+ 0 - 35
client/src/tests/GameSummary.test.js

@@ -1,35 +0,0 @@
-import React from "react";
-import { shallow } from "enzyme";
-import GameSummary from "../components/screens/GameSummary/GameSummary";
-
-jest.mock("../domain/gameStore");
-jest.mock("../hooks/useGameInfo");
-
-import { useGameId } from "../domain/gameStore";
-import { useGameCoords, usePlayers } from "../hooks/useGameInfo";
-
-describe("GameSummary", () => {
-  it("renders loading when null players", () => {
-    useGameId.mockReturnValue("test-game-id");
-    useGameCoords.mockReturnValue([]);
-    usePlayers.mockReturnValue(null);
-    const rendered = shallow(<GameSummary />);
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("renders loading when null coords", () => {
-    useGameId.mockReturnValue("test-game-id");
-    useGameCoords.mockReturnValue(null);
-    usePlayers.mockReturnValue([]);
-    const rendered = shallow(<GameSummary />);
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("renders", () => {
-    useGameId.mockReturnValue("test-game-id");
-    useGameCoords.mockReturnValue([]);
-    usePlayers.mockReturnValue([]);
-    const rendered = shallow(<GameSummary />);
-    expect(rendered).toMatchSnapshot();
-  });
-});

+ 0 - 100
client/src/tests/GuessPane.hooks.test.js

@@ -1,100 +0,0 @@
-import {
-  useMapResizeKeybindings,
-  useRoundTimer,
-} from "../components/screens/GamePanel/GuessPane/hooks";
-
-jest.mock("react");
-jest.mock("../domain/gameStore");
-
-import { useEffect, useState } from "react";
-import { dispatch, useRoundSeconds } from "../domain/gameStore";
-
-describe("GuessPane hooks", () => {
-  describe("useMapResizeKeybindings", () => {
-    document.addEventListener = jest.fn();
-    document.removeEventListener = jest.fn();
-
-    it("attaches key listener on mount and removes them on unmount", () => {
-      let listener;
-      document.addEventListener.mockImplementation((_, fn) => {
-        listener = fn;
-      });
-      let cleanup;
-      useEffect.mockImplementation(fn => {
-        cleanup = fn();
-      });
-      const toggleMapSize = jest.fn();
-      useMapResizeKeybindings(toggleMapSize);
-      expect(document.addEventListener).toHaveBeenCalledWith(
-        "keydown",
-        listener,
-        false
-      );
-      listener({ code: "Escape" });
-      expect(toggleMapSize).toHaveBeenCalled();
-      cleanup();
-      expect(document.removeEventListener).toHaveBeenCalledWith(
-        "keydown",
-        listener,
-        false
-      );
-    });
-    it("attaches key listener that only listens on escape", () => {
-      let listener;
-      document.addEventListener.mockImplementation((_, fn) => {
-        listener = fn;
-      });
-      let cleanup;
-      useEffect.mockImplementation(fn => {
-        cleanup = fn();
-      });
-      const toggleMapSize = jest.fn();
-      useMapResizeKeybindings(toggleMapSize);
-      expect(document.addEventListener).toHaveBeenCalledWith(
-        "keydown",
-        listener,
-        false
-      );
-      listener({ code: "Enter" });
-      expect(toggleMapSize).not.toHaveBeenCalled();
-    });
-  });
-  describe("useRoundTimer", () => {
-    beforeEach(() => {
-      useEffect.mockImplementation(f => {
-        const cleanup = f();
-        if (cleanup) {
-          cleanup();
-        }
-      });
-      setTimeout.mockImplementation(f => f());
-      dispatch.updateRoundSeconds.mockImplementation(f => f(100));
-    });
-    it("sets up a timer and counts down", () => {
-      useRoundSeconds.mockReturnValue(100);
-      useState.mockReturnValue([false, () => {}]);
-      const onTimeout = jest.fn();
-      expect(useRoundTimer(onTimeout)).toBe(100);
-      expect(setTimeout).toHaveBeenCalledWith(expect.any(Function), 1000);
-      expect(dispatch.updateRoundSeconds).toHaveReturnedWith(99);
-      expect(clearTimeout).toHaveBeenCalled();
-      expect(onTimeout).not.toHaveBeenCalled();
-    });
-    it("calls onTimeout when round ends", () => {
-      useRoundSeconds.mockReturnValue(0);
-      useState.mockReturnValue([false, () => {}]);
-      const onTimeout = jest.fn();
-      expect(useRoundTimer(onTimeout)).toBe(0);
-      expect(setTimeout).not.toHaveBeenCalled();
-      expect(dispatch.updateRoundSeconds).not.toHaveBeenCalled();
-      expect(onTimeout).toHaveBeenCalled();
-    });
-    it("only calls onTimeout once", () => {
-      useRoundSeconds.mockReturnValue(0);
-      useState.mockReturnValue([true, () => {}]);
-      const onTimeout = jest.fn();
-      expect(useRoundTimer(onTimeout)).toBe(0);
-      expect(onTimeout).not.toHaveBeenCalled();
-    });
-  });
-});

+ 0 - 105
client/src/tests/GuessPane.test.js

@@ -1,105 +0,0 @@
-import React from "react";
-import { shallow } from "enzyme";
-import GuessPane from "../components/screens/GamePanel/GuessPane";
-
-jest.mock("../domain/gameStore");
-jest.mock("../components/screens/GamePanel/GuessPane/hooks");
-
-import { dispatch } from "../domain/gameStore";
-
-describe("GuessPane", () => {
-  it("renders", () => {
-    const rendered = shallow(<GuessPane />);
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("resizes to large", () => {
-    const handle = shallow(<GuessPane />);
-    handle.find("div.resize").first().simulate("click");
-    expect(handle).toMatchSnapshot();
-  });
-
-  it("resizes to large then back", () => {
-    const handle = shallow(<GuessPane />);
-    handle.find("div.resize").first().simulate("click");
-    handle.find("div.resize").first().simulate("click");
-    expect(handle).toMatchSnapshot();
-  });
-
-  it("resizes to medium", () => {
-    const handle = shallow(<GuessPane />);
-    handle.find("div.resize--medium").first().simulate("click");
-    expect(handle).toMatchSnapshot();
-  });
-
-  it("resizes to medium then back", () => {
-    const handle = shallow(<GuessPane />);
-    handle.find("div.resize--medium").first().simulate("click");
-    handle.find("div.resize--medium").first().simulate("click");
-    expect(handle).toMatchSnapshot();
-  });
-
-  it("resizes to large on keydown Enter", () => {
-    const handle = shallow(<GuessPane />);
-    handle.find("div.resize").first().simulate("keydown", { key: "Enter" });
-    expect(handle).toMatchSnapshot();
-  });
-
-  it("large resize ignores other keydowns", () => {
-    const handle = shallow(<GuessPane />);
-    handle.find("div.resize").first().simulate("keydown", { key: "Escape" });
-    expect(handle).toMatchSnapshot();
-  });
-
-  it("resizes to medium on keydown Enter", () => {
-    const handle = shallow(<GuessPane />);
-    handle
-      .find("div.resize--medium")
-      .first()
-      .simulate("keydown", { key: "Enter" });
-    expect(handle).toMatchSnapshot();
-  });
-
-  it("medium resize ignores other keydowns", () => {
-    const handle = shallow(<GuessPane />);
-    handle
-      .find("div.resize--medium")
-      .first()
-      .simulate("keydown", { key: "Escape" });
-    expect(handle).toMatchSnapshot();
-  });
-
-  it("submits", async () => {
-    const handle = shallow(<GuessPane />);
-    handle.find("ClickMarkerMap").first().prop("onMarkerMoved")({
-      lat: "lat",
-      lng: "lng",
-    });
-    // check submit enabled
-    expect(handle).toMatchSnapshot();
-    await handle.find("button").first().simulate("click");
-    expect(dispatch.submitGuess).toHaveBeenCalledWith(
-      expect.objectContaining({
-        lat: "lat",
-        lng: "lng",
-      })
-    );
-    // check submit disabled again
-    expect(handle).toMatchSnapshot();
-  });
-
-  it("cannot be tricked into resubmitting", async () => {
-    const handle = shallow(<GuessPane />);
-    handle.find("ClickMarkerMap").first().prop("onMarkerMoved")({
-      lat: "lat",
-      lng: "lng",
-    });
-    // check submit enabled
-    expect(handle).toMatchSnapshot();
-    await handle.find("button").first().simulate("click");
-    await handle.find("button").prop("onClick")();
-    expect(dispatch.submitGuess).toHaveBeenCalledTimes(1);
-    // check submit disabled again
-    expect(handle).toMatchSnapshot();
-  });
-});

+ 0 - 50
client/src/tests/HomePage.test.js

@@ -1,50 +0,0 @@
-import React from "react";
-import { mount, shallow } from "enzyme";
-import HomePage, { Rejoin } from "../components/screens/HomePage/HomePage";
-
-jest.mock("../domain/gameStore");
-jest.mock("../components/screens/HomePage/useHasSavedInfo");
-
-import { dispatch } from "../domain/gameStore";
-import useHasSavedInfo from "../components/screens/HomePage/useHasSavedInfo";
-
-describe("HomePage", () => {
-  it("renders", () => {
-    useHasSavedInfo.mockReturnValue(false);
-    const rendered = shallow(<HomePage />);
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("renders with saved info", () => {
-    useHasSavedInfo.mockReturnValue(true);
-    const rendered = shallow(<HomePage />);
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("goes to lobby after game created", () => {
-    const rendered = shallow(<HomePage />);
-    rendered.find("GameCreationForm").first().prop("afterCreate")(
-      "test-game-id"
-    );
-    expect(dispatch.goToLobby).toHaveBeenCalledWith("test-game-id");
-  });
-
-  describe("Rejoin", () => {
-    it("renders", () => {
-      const rendered = shallow(<Rejoin />);
-      expect(rendered).toMatchSnapshot();
-    });
-
-    it("handles click", () => {
-      const rendered = mount(<Rejoin />);
-      rendered.find("button").first().simulate("click");
-      expect(rendered).toMatchSnapshot();
-    });
-
-    it("rejoins when button ends", () => {
-      const rendered = shallow(<Rejoin />);
-      rendered.find("DelayedButton").first().prop("onEnd")();
-      expect(dispatch.rejoinGame).toHaveBeenCalled();
-    });
-  });
-});

+ 0 - 79
client/src/tests/JoinForm.test.js

@@ -1,79 +0,0 @@
-import React from "react";
-import { shallow } from "enzyme";
-import JoinForm from "../components/screens/Lobby/JoinForm";
-
-jest.mock("../domain/gameStore");
-
-import { usePlayerName, dispatch } from "../domain/gameStore";
-
-describe("JoinForm", () => {
-  it("renders", () => {
-    const onJoined = jest.fn();
-    const rendered = shallow(<JoinForm onJoined={onJoined} />);
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("blocks joining with empty player name", () => {
-    const onJoined = jest.fn();
-    usePlayerName.mockReturnValue("");
-    const rendered = shallow(<JoinForm onJoined={onJoined} />);
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("sets player name", () => {
-    const onJoined = jest.fn();
-    const rendered = shallow(<JoinForm onJoined={onJoined} />);
-    rendered
-      .find("input")
-      .first()
-      .simulate("change", { target: { value: "test" } });
-    expect(dispatch.setPlayerName).toHaveBeenCalledWith("test");
-  });
-
-  it("joins game", async () => {
-    const onJoined = jest.fn();
-    usePlayerName.mockReturnValue("test-player");
-    const rendered = shallow(<JoinForm onJoined={onJoined} />);
-    expect(rendered).toMatchSnapshot();
-    await rendered.find("button").first().simulate("click");
-    expect(rendered).toMatchSnapshot();
-    expect(dispatch.joinGame).toHaveBeenCalled();
-    expect(onJoined).toHaveBeenCalled();
-  });
-
-  it("joins game if enter pressed in input", async () => {
-    const onJoined = jest.fn();
-    usePlayerName.mockReturnValue("test-player");
-    const rendered = shallow(<JoinForm onJoined={onJoined} />);
-    expect(rendered).toMatchSnapshot();
-    await rendered.find("input").first().simulate("keydown", { key: "Enter" });
-    expect(rendered).toMatchSnapshot();
-    expect(dispatch.joinGame).toHaveBeenCalled();
-    expect(onJoined).toHaveBeenCalled();
-  });
-
-  it("does not join game if other keys pressed in input", async () => {
-    const onJoined = jest.fn();
-    usePlayerName.mockReturnValue("test-player");
-    const rendered = shallow(<JoinForm onJoined={onJoined} />);
-    expect(rendered).toMatchSnapshot();
-    await rendered.find("input").first().simulate("keydown", { key: "Escape" });
-    expect(rendered).toMatchSnapshot();
-    expect(dispatch.joinGame).not.toHaveBeenCalled();
-    expect(onJoined).not.toHaveBeenCalled();
-  });
-
-  it("handles failure", async () => {
-    dispatch.joinGame.mockImplementation(() => {
-      throw new Error();
-    });
-    const onJoined = jest.fn();
-    usePlayerName.mockReturnValue("test-player");
-    const rendered = shallow(<JoinForm onJoined={onJoined} />);
-    expect(rendered).toMatchSnapshot();
-    await rendered.find("button").first().simulate("click");
-    expect(rendered).toMatchSnapshot();
-    expect(dispatch.joinGame).toHaveBeenCalled();
-    expect(onJoined).not.toHaveBeenCalled();
-  });
-});

+ 0 - 40
client/src/tests/LinkedGame.test.js

@@ -1,40 +0,0 @@
-import React from "react";
-import { shallow } from "enzyme";
-import LinkedGame from "../components/screens/GameSummary/LinkedGame";
-
-jest.mock("../domain/gameStore");
-jest.mock("../domain/apiMethods");
-
-import { dispatch } from "../domain/gameStore";
-import { linkGame } from "../domain/apiMethods";
-
-describe("LinkedGame", () => {
-  it("renders with no linked game", () => {
-    const rendered = shallow(
-      <LinkedGame linkedGame={null} gameId="test-game-id" />
-    );
-    expect(rendered).toMatchSnapshot();
-  });
-  it("renders with linked game", () => {
-    const rendered = shallow(
-      <LinkedGame linkedGame={"linked-game-id"} gameId="test-game-id" />
-    );
-    expect(rendered).toMatchSnapshot();
-  });
-  it("links game after creation", () => {
-    const rendered = shallow(
-      <LinkedGame linkedGame={null} gameId="test-game-id" />
-    );
-    rendered.find("GameCreationForm").first().prop("afterCreate")(
-      "linked-game-id"
-    );
-    expect(linkGame).toHaveBeenCalledWith("test-game-id", "linked-game-id");
-  });
-  it("goes to linked game on click", () => {
-    const rendered = shallow(
-      <LinkedGame linkedGame={"linked-game-id"} gameId="test-game-id" />
-    );
-    rendered.find("button").first().simulate("click");
-    expect(dispatch.goToLobby).toHaveBeenCalledWith("linked-game-id");
-  });
-});

+ 0 - 10
client/src/tests/Loading.test.js

@@ -1,10 +0,0 @@
-import React from "react";
-import { shallow } from "enzyme";
-import Loading from "../components/util/Loading";
-
-describe("Loading icon", () => {
-  it("renders", () => {
-    const loading = shallow(<Loading />);
-    expect(loading).toMatchSnapshot();
-  });
-});

+ 0 - 217
client/src/tests/Lobby.test.js

@@ -1,217 +0,0 @@
-import React from "react";
-import { shallow } from "enzyme";
-import Lobby, { GameInfo, PlayerList } from "../components/screens/Lobby/Lobby";
-import {
-  COUNTRY_RACE,
-  DISTANCE,
-  FROZEN,
-  NORMAL,
-  RACE,
-  TIME_BANK,
-} from "../domain/constants";
-
-jest.mock("iso-3166-1");
-jest.mock("../domain/gameStore");
-jest.mock("../hooks/useGameInfo");
-
-import iso from "iso-3166-1";
-import { useGameId } from "../domain/gameStore";
-import { useGameConfig, usePlayers } from "../hooks/useGameInfo";
-
-describe("Lobby", () => {
-  it("renders while loading", () => {
-    useGameId.mockReturnValue("test-game-id");
-    usePlayers.mockReturnValue(null);
-    const onStart = jest.fn();
-    const rendered = shallow(<Lobby onStart={onStart} />);
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("renders with no players", () => {
-    useGameId.mockReturnValue("test-game-id");
-    usePlayers.mockReturnValue([]);
-    const onStart = jest.fn();
-    const rendered = shallow(<Lobby onStart={onStart} />);
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("renders", () => {
-    useGameId.mockReturnValue("test-game-id");
-    usePlayers.mockReturnValue([{ name: "foo", name: "bar" }]);
-    const onStart = jest.fn();
-    const rendered = shallow(<Lobby onStart={onStart} />);
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("properly handles joining and starting", () => {
-    useGameId.mockReturnValue("test-game-id");
-    usePlayers.mockReturnValue([]);
-    const onStart = jest.fn();
-    const rendered = shallow(<Lobby onStart={onStart} />);
-    rendered.find("JoinForm").first().prop("onJoined")();
-    expect(rendered).toMatchSnapshot();
-    rendered.find("StartGame").first().prop("onStart")();
-    expect(onStart).toHaveBeenCalled();
-  });
-
-  describe("GameInfo", () => {
-    it("renders while loading", () => {
-      useGameConfig.mockReturnValue({});
-      const rendered = shallow(<GameInfo />);
-      expect(rendered).toMatchSnapshot();
-    });
-
-    it("renders", () => {
-      useGameConfig.mockReturnValue({
-        rounds: 5,
-        timer: 300,
-        gameMode: NORMAL,
-        clockMode: NORMAL,
-        scoreMethod: DISTANCE,
-        roundPointCap: null,
-      });
-      const rendered = shallow(<GameInfo />);
-      expect(rendered).toMatchSnapshot();
-    });
-
-    it("renders for single round", () => {
-      useGameConfig.mockReturnValue({
-        rounds: 1,
-        timer: 300,
-        gameMode: NORMAL,
-        clockMode: NORMAL,
-        scoreMethod: DISTANCE,
-        roundPointCap: null,
-      });
-      const rendered = shallow(<GameInfo />);
-      expect(rendered).toMatchSnapshot();
-    });
-
-    it("renders for COUNTRY_RACE", () => {
-      useGameConfig.mockReturnValue({
-        rounds: 5,
-        timer: 300,
-        gameMode: NORMAL,
-        clockMode: NORMAL,
-        scoreMethod: COUNTRY_RACE,
-        roundPointCap: null,
-      });
-      const rendered = shallow(<GameInfo />);
-      expect(rendered).toMatchSnapshot();
-    });
-
-    it("renders for FROZEN", () => {
-      useGameConfig.mockReturnValue({
-        rounds: 5,
-        timer: 300,
-        gameMode: FROZEN,
-        clockMode: NORMAL,
-        scoreMethod: DISTANCE,
-        roundPointCap: null,
-      });
-      const rendered = shallow(<GameInfo />);
-      expect(rendered).toMatchSnapshot();
-    });
-
-    it("renders for single round COUNTRY_RACE", () => {
-      useGameConfig.mockReturnValue({
-        rounds: 1,
-        timer: 300,
-        gameMode: NORMAL,
-        clockMode: NORMAL,
-        scoreMethod: COUNTRY_RACE,
-        roundPointCap: null,
-      });
-      const rendered = shallow(<GameInfo />);
-      expect(rendered).toMatchSnapshot();
-    });
-
-    it("renders for single round FROZEN", () => {
-      useGameConfig.mockReturnValue({
-        rounds: 1,
-        timer: 300,
-        gameMode: FROZEN,
-        clockMode: NORMAL,
-        scoreMethod: DISTANCE,
-        roundPointCap: null,
-      });
-      const rendered = shallow(<GameInfo />);
-      expect(rendered).toMatchSnapshot();
-    });
-
-    it("renders for TIME_BANK", () => {
-      useGameConfig.mockReturnValue({
-        rounds: 5,
-        timer: 300,
-        gameMode: NORMAL,
-        clockMode: TIME_BANK,
-        scoreMethod: DISTANCE,
-        roundPointCap: null,
-      });
-      const rendered = shallow(<GameInfo />);
-      expect(rendered).toMatchSnapshot();
-    });
-
-    it("renders for RACE", () => {
-      useGameConfig.mockReturnValue({
-        rounds: 5,
-        timer: 300,
-        gameMode: NORMAL,
-        clockMode: RACE,
-        scoreMethod: DISTANCE,
-        roundPointCap: null,
-      });
-      const rendered = shallow(<GameInfo />);
-      expect(rendered).toMatchSnapshot();
-    });
-
-    it("renders for NORMAL", () => {
-      useGameConfig.mockReturnValue({
-        rounds: 5,
-        timer: 300,
-        gameMode: NORMAL,
-        clockMode: NORMAL,
-        scoreMethod: DISTANCE,
-        roundPointCap: null,
-      });
-      const rendered = shallow(<GameInfo />);
-      expect(rendered).toMatchSnapshot();
-    });
-
-    it("renders with a round point cap", () => {
-      useGameConfig.mockReturnValue({
-        rounds: 5,
-        timer: 300,
-        gameMode: NORMAL,
-        clockMode: NORMAL,
-        scoreMethod: DISTANCE,
-        roundPointCap: 10000,
-      });
-      const rendered = shallow(<GameInfo />);
-      expect(rendered).toMatchSnapshot();
-    });
-
-    it("renders with country lock", () => {
-      iso.whereAlpha2.mockReturnValue({ country: "test-country" });
-      useGameConfig.mockReturnValue({
-        rounds: 5,
-        timer: 300,
-        countryLock: "country",
-        gameMode: NORMAL,
-        clockMode: NORMAL,
-        scoreMethod: DISTANCE,
-        roundPointCap: null,
-      });
-      const rendered = shallow(<GameInfo />);
-      expect(rendered).toMatchSnapshot();
-    });
-  });
-
-  describe("PlayerList", () => {
-    it("renders", () => {
-      const playerNames = ["foo", "bar"];
-      const rendered = shallow(<PlayerList playerNames={playerNames} />);
-      expect(rendered).toMatchSnapshot();
-    });
-  });
-});

+ 0 - 70
client/src/tests/PositionedStreetView.test.js

@@ -1,70 +0,0 @@
-import React from "react";
-import { shallow } from "enzyme";
-import PositionedStreetView from "../components/screens/GamePanel/PositionedStreetView";
-
-jest.mock("../domain/gameStore");
-jest.mock("../components/screens/GamePanel/hooks");
-
-import {
-  usePanoStartPosition,
-  usePanoStartPov,
-  useTargetPoint,
-} from "../domain/gameStore";
-import { usePano } from "../components/screens/GamePanel/hooks";
-
-describe("PositionedStreetView", () => {
-  it("renders", () => {
-    usePanoStartPosition.mockReturnValue();
-    usePanoStartPov.mockReturnValue();
-    useTargetPoint.mockReturnValue();
-
-    const rendered = shallow(<PositionedStreetView />);
-    expect(rendered).toMatchSnapshot();
-    expect(usePano).toHaveBeenCalled();
-  });
-
-  it("resets", () => {
-    usePanoStartPosition.mockReturnValue();
-    usePanoStartPov.mockReturnValue();
-    useTargetPoint.mockReturnValue("point");
-    const setPosition = jest.fn();
-    usePano.mockReturnValue({ current: { setPosition } });
-
-    const handle = shallow(<PositionedStreetView />);
-    expect(handle).toMatchSnapshot();
-    handle.find("div.resetButton").first().simulate("click");
-    expect(setPosition).toHaveBeenCalledWith("point");
-  });
-
-  it("resets on enter on button", () => {
-    usePanoStartPosition.mockReturnValue();
-    usePanoStartPov.mockReturnValue();
-    useTargetPoint.mockReturnValue("point");
-    const setPosition = jest.fn();
-    usePano.mockReturnValue({ current: { setPosition } });
-
-    const handle = shallow(<PositionedStreetView />);
-    expect(handle).toMatchSnapshot();
-    handle
-      .find("div.resetButton")
-      .first()
-      .simulate("keydown", { key: "Enter" });
-    expect(setPosition).toHaveBeenCalledWith("point");
-  });
-
-  it("does not reset on other keys on button", () => {
-    usePanoStartPosition.mockReturnValue();
-    usePanoStartPov.mockReturnValue();
-    useTargetPoint.mockReturnValue("point");
-    const setPosition = jest.fn();
-    usePano.mockReturnValue({ current: { setPosition } });
-
-    const handle = shallow(<PositionedStreetView />);
-    expect(handle).toMatchSnapshot();
-    handle
-      .find("div.resetButton")
-      .first()
-      .simulate("keydown", { key: "Escape" });
-    expect(setPosition).not.toHaveBeenCalled();
-  });
-});

+ 0 - 33
client/src/tests/RaceMode.test.js

@@ -1,33 +0,0 @@
-import React from "react";
-import { shallow } from "enzyme";
-import RaceMode from "../components/screens/GamePanel/RaceMode";
-
-jest.mock("../domain/gameStore");
-jest.mock("../domain/apiMethods");
-jest.mock("../components/screens/GamePanel/hooks");
-
-import {
-  useFirstSubmitter,
-  useIsFaded,
-} from "../components/screens/GamePanel/hooks";
-
-describe("PositionedStreetView", () => {
-  it("renders", () => {
-    useFirstSubmitter.mockReturnValue(null);
-    useIsFaded.mockReturnValue(false);
-    const rendered = shallow(<RaceMode />);
-    expect(rendered).toMatchSnapshot();
-  });
-  it("renders when cut off", () => {
-    useFirstSubmitter.mockReturnValue("cutoff-player");
-    useIsFaded.mockReturnValue(false);
-    const rendered = shallow(<RaceMode cutoffTime={10} />);
-    expect(rendered).toMatchSnapshot();
-  });
-  it("renders when faded", () => {
-    useFirstSubmitter.mockReturnValue("cutoff-player");
-    useIsFaded.mockReturnValue(true);
-    const rendered = shallow(<RaceMode cutoffTime={10} />);
-    expect(rendered).toMatchSnapshot();
-  });
-});

+ 0 - 77
client/src/tests/RoundSummary.test.js

@@ -1,77 +0,0 @@
-import React from "react";
-import { mount, shallow } from "enzyme";
-import RoundSummary, {
-  NextRoundButton,
-} from "../components/screens/RoundSummary/RoundSummary";
-
-jest.mock("../domain/gameStore");
-jest.mock("../hooks/useMap");
-jest.mock("../hooks/usePreventNavigation");
-jest.mock("../hooks/useGameInfo");
-jest.mock("../hooks/useMarkersFromGuesses");
-jest.mock("../components/screens/RoundSummary/useClickToCheckScore");
-
-import { dispatch, useCurrentRound, useLastRound } from "../domain/gameStore";
-import useMap from "../hooks/useMap";
-import usePreventNavigation from "../hooks/usePreventNavigation";
-import { usePlayers } from "../hooks/useGameInfo";
-import useMarkersFromGuesses from "../hooks/useMarkersFromGuesses";
-import useClickToCheckScore from "../components/screens/RoundSummary/useClickToCheckScore";
-
-describe("RoundSummary", () => {
-  it("renders", () => {
-    useLastRound.mockReturnValue({
-      roundNum: "round",
-      score: 5000,
-      totalScore: 10000,
-      targetPoint: "target",
-    });
-    useMap.mockReturnValue("map");
-    usePlayers.mockReturnValue("players");
-    const rendered = shallow(<RoundSummary />);
-    expect(rendered).toMatchSnapshot();
-    expect(usePreventNavigation).toHaveBeenCalled();
-    expect(useMarkersFromGuesses).toHaveBeenCalledWith(
-      "map",
-      "players",
-      "round",
-      "target"
-    );
-    expect(useClickToCheckScore).toHaveBeenCalledWith("map", "target");
-  });
-
-  describe("NextRoundButton", () => {
-    it("renders when there is not a next round", () => {
-      useCurrentRound.mockReturnValue(null);
-      const rendered = shallow(<NextRoundButton />);
-      expect(rendered).toMatchSnapshot();
-    });
-
-    it("proceeds to summary when clicked if there is not a next round", () => {
-      useCurrentRound.mockReturnValue(null);
-      const rendered = shallow(<NextRoundButton />);
-      rendered.find("button").first().simulate("click");
-      expect(dispatch.goToSummary).toHaveBeenCalled();
-    });
-
-    it("renders when there is a next round", () => {
-      useCurrentRound.mockReturnValue("round");
-      const rendered = shallow(<NextRoundButton />);
-      expect(rendered).toMatchSnapshot();
-    });
-
-    it("handles click if there is a next round", () => {
-      useCurrentRound.mockReturnValue("round");
-      const rendered = mount(<NextRoundButton />);
-      rendered.find("button").first().simulate("click");
-      expect(rendered).toMatchSnapshot();
-    });
-
-    it("proceeds to next round when button ends", () => {
-      useCurrentRound.mockReturnValue("round");
-      const rendered = mount(<NextRoundButton />);
-      rendered.find("DelayedButton").first().prop("onEnd")();
-      expect(dispatch.startRound).toHaveBeenCalled();
-    });
-  });
-});

+ 0 - 20
client/src/tests/RoundTimer.test.js

@@ -1,20 +0,0 @@
-import React from "react";
-import { shallow } from "enzyme";
-import RoundTimer from "../components/screens/GamePanel/GuessPane/RoundTimer";
-
-jest.mock("../components/screens/GamePanel/GuessPane/hooks");
-
-import { useRoundTimer } from "../components/screens/GamePanel/GuessPane/hooks";
-
-describe("RoundTimer", () => {
-  it("renders with time left", () => {
-    useRoundTimer.mockReturnValue(100);
-    const rendered = shallow(<RoundTimer />);
-    expect(rendered).toMatchSnapshot();
-  });
-  it("renders with no time left", () => {
-    useRoundTimer.mockReturnValue(0);
-    const rendered = shallow(<RoundTimer />);
-    expect(rendered).toMatchSnapshot();
-  });
-});

+ 0 - 135
client/src/tests/Scoreboard.test.js

@@ -1,135 +0,0 @@
-import React from "react";
-import { shallow } from "enzyme";
-import ScoreBoard, {
-  PlayerScoreTile,
-} from "../components/screens/GameSummary/ScoreBoard/ScoreBoard";
-
-jest.mock("iso-3166-1");
-jest.mock("../domain/flagLookup");
-
-import iso from "iso-3166-1";
-import flagLookup from "../domain/flagLookup";
-
-describe("ScoreBoard", () => {
-  it("renders with no players", () => {
-    const rendered = shallow(<ScoreBoard players={[]} />);
-    expect(rendered).toMatchSnapshot();
-  });
-  it("renders with player tiles sorted by score", () => {
-    const rendered = shallow(
-      <ScoreBoard
-        players={[
-          { currentRound: null, totalScore: 5000, name: "Name1" },
-          { currentRound: null, totalScore: 10000, name: "Name2" },
-          { currentRound: null, totalScore: 1000, name: "Name3" },
-          { currentRound: null, totalScore: 5000, name: "Name4" },
-        ]}
-      />
-    );
-    expect(rendered).toMatchSnapshot();
-  });
-  it("does not add tiles for unfinished players", () => {
-    const rendered = shallow(
-      <ScoreBoard
-        players={[
-          { currentRound: null, totalScore: 5000, name: "Name1" },
-          { currentRound: null, totalScore: 10000, name: "Name2" },
-          { currentRound: "1", totalScore: 1000, name: "Name3" },
-        ]}
-      />
-    );
-    expect(rendered).toMatchSnapshot();
-  });
-  describe("PlayerScoreTile", () => {
-    beforeEach(() => {
-      iso.whereAlpha2.mockReturnValue({ country: "test-country" });
-    });
-    it("renders with no guesses", () => {
-      const rendered = shallow(
-        <PlayerScoreTile name="Name" guesses={[]} totalScore={0} />
-      );
-      expect(rendered).toMatchSnapshot();
-    });
-    it("renders overly long name", () => {
-      const rendered = shallow(
-        <PlayerScoreTile name={"Long".repeat(10)} guesses={[]} totalScore={0} />
-      );
-      expect(rendered).toMatchSnapshot();
-    });
-    it("renders slightly long name", () => {
-      const rendered = shallow(
-        <PlayerScoreTile name={"Long".repeat(5)} guesses={[]} totalScore={0} />
-      );
-      expect(rendered).toMatchSnapshot();
-    });
-    it("renders with guesses", () => {
-      flagLookup.mockReturnValue("flag");
-      const rendered = shallow(
-        <PlayerScoreTile
-          name="Name"
-          guesses={{
-            1: { score: 50, country: "test-country" },
-            2: { score: 150, country: "test-country" },
-            3: { score: 20, country: "test-country" },
-          }}
-          totalScore={220}
-          winner
-        />
-      );
-      expect(rendered).toMatchSnapshot();
-      expect(flagLookup).toMatchSnapshot();
-    });
-    it("sorts guesses by round number", () => {
-      flagLookup.mockReturnValue("flag");
-      const rendered = shallow(
-        <PlayerScoreTile
-          name="Name"
-          guesses={{
-            // using these weird keys to force other branch of sort
-            "03": { score: 20, country: "test-country" },
-            "02": { score: 150, country: "test-country" },
-            "01": { score: 50, country: "test-country" },
-          }}
-          totalScore={220}
-          winner
-        />
-      );
-      expect(rendered).toMatchSnapshot();
-      expect(flagLookup).toMatchSnapshot();
-    });
-    it("renders with missing guess", () => {
-      flagLookup.mockReturnValue("flag");
-      const rendered = shallow(
-        <PlayerScoreTile
-          name="Name"
-          guesses={{
-            1: { score: 50, country: "test-country" },
-            2: {},
-            3: { score: 20, country: "test-country" },
-          }}
-          totalScore={220}
-          winner
-        />
-      );
-      expect(rendered).toMatchSnapshot();
-      expect(flagLookup).toMatchSnapshot();
-    });
-    it("renders with timeout", () => {
-      flagLookup.mockReturnValue("flag");
-      const rendered = shallow(
-        <PlayerScoreTile
-          name="Name"
-          guesses={{
-            1: { score: 50, country: "test-country" },
-            2: { score: null, country: null },
-            3: { score: 20, country: "test-country" },
-          }}
-          totalScore={220}
-          winner
-        />
-      );
-      expect(rendered).toMatchSnapshot();
-      expect(flagLookup).toMatchSnapshot();
-    });
-  });
-});

+ 0 - 21
client/src/tests/StartGame.test.js

@@ -1,21 +0,0 @@
-import React from "react";
-import { shallow, mount } from "enzyme";
-import StartGame from "../components/screens/Lobby/StartGame";
-
-jest.mock("../domain/gameStore");
-
-import { usePlayerName } from "../domain/gameStore";
-
-describe("StartGame", () => {
-  it("renders without crashing", () => {
-    usePlayerName.mockReturnValue("test-player");
-    const rendered = shallow(<StartGame />);
-    expect(rendered).toMatchSnapshot();
-  });
-  it("responds to clicking the join button", () => {
-    usePlayerName.mockReturnValue("test-player");
-    const handle = mount(<StartGame />);
-    handle.find("button").first().simulate("click");
-    expect(handle).toMatchSnapshot();
-  });
-});

+ 0 - 252
client/src/tests/SummaryMap.test.js

@@ -1,252 +0,0 @@
-import React from "react";
-import { shallow } from "enzyme";
-import SummaryMap, {
-  RoundSelect,
-} from "../components/screens/GameSummary/SummaryMap/SummaryMap";
-
-jest.mock("iso-3166-1");
-jest.mock("../domain/flagLookup");
-jest.mock("../hooks/useGameInfo");
-jest.mock("../hooks/useMap");
-jest.mock("../hooks/useMapBounds");
-jest.mock("../hooks/useMarkersFromGuesses");
-
-import iso from "iso-3166-1";
-import useMarkersFromGuesses from "../hooks/useMarkersFromGuesses";
-import useMap from "../hooks/useMap";
-import useMapBounds from "../hooks/useMapBounds";
-import { useGameConfig } from "../hooks/useGameInfo";
-
-describe("SummaryMap", () => {
-  beforeEach(() => {
-    iso.whereAlpha2.mockReturnValue({ country: "test-country" });
-  });
-
-  it("renders", () => {
-    useMap.mockReturnValue("map");
-    useGameConfig.mockReturnValue({ countryLock: "lock" });
-    const rendered = shallow(
-      <SummaryMap
-        players="players"
-        coords={{
-          1: {},
-          2: {},
-          3: {},
-        }}
-      />
-    );
-    expect(rendered).toMatchSnapshot();
-    expect(useMapBounds).toHaveBeenCalledWith("map", "lock");
-    expect(useMarkersFromGuesses).toHaveBeenCalledWith(
-      "map",
-      "players",
-      "0",
-      null
-    );
-  });
-
-  it("renders without selector if single round", () => {
-    useMap.mockReturnValue("map");
-    useGameConfig.mockReturnValue({ countryLock: "lock" });
-    const rendered = shallow(
-      <SummaryMap
-        players="players"
-        coords={{
-          1: "round",
-        }}
-      />
-    );
-    expect(rendered).toMatchSnapshot();
-    expect(useMapBounds).toHaveBeenCalledWith("map", "lock");
-    expect(useMarkersFromGuesses).toHaveBeenCalledWith(
-      "map",
-      "players",
-      "1",
-      "round"
-    );
-  });
-
-  it("handles having the round changed", () => {
-    const panTo = jest.fn();
-    useMap.mockReturnValue({ current: { panTo } });
-    useGameConfig.mockReturnValue({ countryLock: "lock" });
-    const rendered = shallow(
-      <SummaryMap
-        players="players"
-        coords={{
-          1: { lat: 1, lng: 2 },
-          2: { lat: 3, lng: 4 },
-          3: { lat: 5, lng: 6 },
-        }}
-      />
-    );
-    rendered.find("RoundSelect").prop("onSelect")(2);
-    expect(panTo).toMatchSnapshot();
-    expect(rendered).toMatchSnapshot();
-  });
-
-  it("handles invalid round change", () => {
-    const panTo = jest.fn();
-    useMap.mockReturnValue({ current: { panTo } });
-    useGameConfig.mockReturnValue({ countryLock: "lock" });
-    const rendered = shallow(
-      <SummaryMap
-        players="players"
-        coords={{
-          1: { lat: 1, lng: 2 },
-          2: { lat: 3, lng: 4 },
-          3: { lat: 5, lng: 6 },
-        }}
-      />
-    );
-    rendered.find("RoundSelect").prop("onSelect")(5);
-    expect(panTo).toMatchSnapshot();
-    expect(rendered).toMatchSnapshot();
-  });
-
-  describe("RoundSelect", () => {
-    it("renders", () => {
-      const onSelect = jest.fn();
-      const rendered = shallow(
-        <RoundSelect
-          rounds={3}
-          coords={{
-            1: { country: "country1" },
-            2: { country: "country2" },
-            3: { country: "country3" },
-          }}
-          onSelect={onSelect}
-        />
-      );
-      expect(rendered).toMatchSnapshot();
-    });
-
-    it("can be selected", () => {
-      const onSelect = jest.fn();
-      const rendered = shallow(
-        <RoundSelect
-          rounds={3}
-          coords={{
-            1: { country: "country1" },
-            2: { country: "country2" },
-            3: { country: "country3" },
-          }}
-          selected="2"
-          onSelect={onSelect}
-        />
-      );
-      expect(rendered).toMatchSnapshot();
-    });
-
-    it("calls onSelect when clicked", () => {
-      const onSelect = jest.fn();
-      const rendered = shallow(
-        <RoundSelect
-          rounds={3}
-          coords={{
-            1: { country: "country1" },
-            2: { country: "country2" },
-            3: { country: "country3" },
-          }}
-          onSelect={onSelect}
-        />
-      );
-      rendered.find("div.tab").first().simulate("click");
-      expect(onSelect).toHaveBeenCalledWith("1");
-    });
-
-    it("calls onSelect when enter pressed", () => {
-      const onSelect = jest.fn();
-      const rendered = shallow(
-        <RoundSelect
-          rounds={3}
-          coords={{
-            1: { country: "country1" },
-            2: { country: "country2" },
-            3: { country: "country3" },
-          }}
-          onSelect={onSelect}
-        />
-      );
-      rendered.find("div.tab").first().simulate("keydown", { key: "Enter" });
-      expect(onSelect).toHaveBeenCalledWith("1");
-    });
-
-    it("does not call onSelect when other keys pressed", () => {
-      const onSelect = jest.fn();
-      const rendered = shallow(
-        <RoundSelect
-          rounds={3}
-          coords={{
-            1: { country: "country1" },
-            2: { country: "country2" },
-            3: { country: "country3" },
-          }}
-          onSelect={onSelect}
-        />
-      );
-      rendered.find("div.tab").first().simulate("keydown", { key: "Escape" });
-      expect(onSelect).not.toHaveBeenCalledWith("1");
-    });
-
-    it("calls onSelect with 0 when X clicked", () => {
-      const onSelect = jest.fn();
-      const rendered = shallow(
-        <RoundSelect
-          rounds={3}
-          coords={{
-            1: { country: "country1" },
-            2: { country: "country2" },
-            3: { country: "country3" },
-          }}
-          onSelect={onSelect}
-        />
-      );
-      rendered
-        .findWhere(x => x.text() === "X")
-        .first()
-        .simulate("click");
-      expect(onSelect).toHaveBeenCalledWith("0");
-    });
-
-    it("calls onSelect with 0 when enter pressed on X", () => {
-      const onSelect = jest.fn();
-      const rendered = shallow(
-        <RoundSelect
-          rounds={3}
-          coords={{
-            1: { country: "country1" },
-            2: { country: "country2" },
-            3: { country: "country3" },
-          }}
-          onSelect={onSelect}
-        />
-      );
-      rendered
-        .findWhere(x => x.text() === "X")
-        .first()
-        .simulate("keydown", { key: "Enter" });
-      expect(onSelect).toHaveBeenCalledWith("0");
-    });
-
-    it("does not call onSelect with 0 when other keys pressed on X", () => {
-      const onSelect = jest.fn();
-      const rendered = shallow(
-        <RoundSelect
-          rounds={3}
-          coords={{
-            1: { country: "country1" },
-            2: { country: "country2" },
-            3: { country: "country3" },
-          }}
-          onSelect={onSelect}
-        />
-      );
-      rendered
-        .findWhere(x => x.text() === "X")
-        .first()
-        .simulate("keydown", { key: "Escape" });
-      expect(onSelect).not.toHaveBeenCalledWith("0");
-    });
-  });
-});

+ 6 - 6
client/src/tests/__snapshots__/ApiInfo.test.js.snap

@@ -1,21 +1,21 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
-exports[`ApiInfo PureApiInfo renders 1`] = `
+exports[`ApiInfo renders and matches healthy snapshot 1`] = `
 <p>
   API Version: 
   test
 </p>
 `;
 
-exports[`ApiInfo PureApiInfo renders for unhealthy 1`] = `
+exports[`ApiInfo renders and matches snapshot 1`] = `
 <p>
-  Unable to communicate with API server! Error: 
-  bad
+  Connecting to back-end...
 </p>
 `;
 
-exports[`ApiInfo renders 1`] = `
+exports[`ApiInfo renders and matches unhealthy snapshot 1`] = `
 <p>
-  Connecting to back-end...
+  Unable to communicate with API server! Error: 
+  unhealthy
 </p>
 `;

+ 0 - 134
client/src/tests/__snapshots__/App.test.js.snap

@@ -1,134 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`App Footer renders 1`] = `
-<CSSTransition
-  classNames="fade"
-  mountOnEnter={true}
-  nodeRef={
-    Object {
-      "current": null,
-    }
-  }
-  timeout={500}
-  unmountOnExit={true}
->
-  <div
-    className="footer"
-  >
-    <ApiInfo />
-  </div>
-</CSSTransition>
-`;
-
-exports[`App Header renders 1`] = `
-<CSSTransition
-  classNames="fade"
-  mountOnEnter={true}
-  nodeRef={
-    Object {
-      "current": null,
-    }
-  }
-  timeout={500}
-  unmountOnExit={true}
->
-  <div
-    className="header"
-  >
-    <p>
-      TerrAssumptions!
-    </p>
-  </div>
-</CSSTransition>
-`;
-
-exports[`App State renders 1`] = `
-<CSSTransition
-  classNames="fade"
-  mountOnEnter={true}
-  nodeRef={
-    Object {
-      "current": null,
-    }
-  }
-  onEnter={[Function]}
-  onExited={[Function]}
-  timeout={500}
-  unmountOnExit={true}
->
-  <div
-    className="state"
-  >
-    Test
-  </div>
-</CSSTransition>
-`;
-
-exports[`App paramRouter routes summary param 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "test-game-id",
-      false,
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`App renders 1`] = `
-<StrictMode>
-  <div
-    className="page"
-  >
-    <Header />
-    <State
-      setTransitioning={[Function]}
-      show={true}
-    >
-      <div
-        className="loading"
-      >
-        <Loading />
-      </div>
-    </State>
-    <State
-      setTransitioning={[Function]}
-      show={false}
-    >
-      <HomePage />
-    </State>
-    <State
-      setTransitioning={[Function]}
-      show={false}
-    >
-      <Lobby />
-    </State>
-    <State
-      setTransitioning={[Function]}
-      show={false}
-    >
-      <RoundSummary />
-    </State>
-    <State
-      setTransitioning={[Function]}
-      show={false}
-    >
-      <GameSummary />
-    </State>
-    <State
-      show={false}
-    >
-      <p>
-        Application encountered unrecoverable error, please refresh the page.
-      </p>
-    </State>
-    <Footer />
-  </div>
-</StrictMode>
-`;

+ 0 - 7
client/src/tests/__snapshots__/ClickMarkerMap.test.js.snap

@@ -1,7 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`ClickMarkerMap renders 1`] = `
-<div
-  className="map"
-/>
-`;

+ 0 - 189
client/src/tests/__snapshots__/ClickToCopy.test.js.snap

@@ -1,189 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`ClickToCopy renders children 1`] = `
-<div
-  className="container"
->
-  <span
-    className="underlined"
-    onClick={[Function]}
-    onFocus={[Function]}
-    onKeyDown={[Function]}
-    onMouseOver={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    <span>
-      other text
-    </span>
-  </span>
-  <span
-    className="tooltip"
-  >
-    Click to Copy
-  </span>
-  <textarea
-    className="invisible"
-    readOnly={true}
-    value="test-text"
-  />
-</div>
-`;
-
-exports[`ClickToCopy renders without crashing 1`] = `
-<div
-  className="container"
->
-  <span
-    className="underlined"
-    onClick={[Function]}
-    onFocus={[Function]}
-    onKeyDown={[Function]}
-    onMouseOver={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    test-text
-  </span>
-  <span
-    className="tooltip"
-  >
-    Click to Copy
-  </span>
-  <textarea
-    className="invisible"
-    readOnly={true}
-    value="test-text"
-  />
-</div>
-`;
-
-exports[`ClickToCopy resets when focused 1`] = `
-<ClickToCopy
-  text="test-text"
->
-  <div
-    className="container"
-  >
-    <span
-      className="underlined"
-      onClick={[Function]}
-      onFocus={[Function]}
-      onKeyDown={[Function]}
-      onMouseOver={[Function]}
-      role="button"
-      tabIndex="0"
-    >
-      test-text
-    </span>
-    <span
-      className="tooltip"
-    >
-      Click to Copy
-    </span>
-    <textarea
-      className="invisible"
-      readOnly={true}
-      value="test-text"
-    />
-  </div>
-</ClickToCopy>
-`;
-
-exports[`ClickToCopy shows tooltip when hovered 1`] = `
-<ClickToCopy
-  text="test-text"
->
-  <div
-    className="container"
-  >
-    <span
-      className="underlined"
-      onClick={[Function]}
-      onFocus={[Function]}
-      onKeyDown={[Function]}
-      onMouseOver={[Function]}
-      role="button"
-      tabIndex="0"
-    >
-      test-text
-    </span>
-    <span
-      className="tooltip"
-    >
-      Click to Copy
-    </span>
-    <textarea
-      className="invisible"
-      readOnly={true}
-      value="test-text"
-    />
-  </div>
-</ClickToCopy>
-`;
-
-exports[`ClickToCopy shows tooltip when hovered 2`] = `
-<ClickToCopy
-  text="test-text"
->
-  <div
-    className="container"
-  >
-    <span
-      className="underlined"
-      onClick={[Function]}
-      onFocus={[Function]}
-      onKeyDown={[Function]}
-      onMouseOver={[Function]}
-      role="button"
-      tabIndex="0"
-    >
-      test-text
-    </span>
-    <span
-      className="tooltip"
-    >
-      Copied!
-    </span>
-    <textarea
-      className="invisible"
-      readOnly={true}
-      value="test-text"
-    />
-  </div>
-</ClickToCopy>
-`;
-
-exports[`ClickToCopy uses children if no text provided 1`] = `
-<div
-  className="container"
->
-  <span
-    className="underlined"
-    onClick={[Function]}
-    onFocus={[Function]}
-    onKeyDown={[Function]}
-    onMouseOver={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    <span>
-      other text
-    </span>
-  </span>
-  <span
-    className="tooltip"
-  >
-    Click to Copy
-  </span>
-  <textarea
-    className="invisible"
-    readOnly={true}
-    value={
-      <span>
-        other text
-      </span>
-    }
-  />
-</div>
-`;

+ 0 - 45
client/src/tests/__snapshots__/DelayedButton.test.js.snap

@@ -1,45 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`DelayedButton CountdownButton renders 1`] = `
-<button
-  autoFocus={true}
-  className="test-button"
-  onClick={[Function]}
-  type="button"
->
-  formatted
-</button>
-`;
-
-exports[`DelayedButton renders 1`] = `
-<button
-  autoFocus={true}
-  className="test-button"
-  onClick={[Function]}
-  type="button"
->
-  test
-</button>
-`;
-
-exports[`DelayedButton resets self after second click 1`] = `
-<button
-  autoFocus={true}
-  className="test-button"
-  onClick={[Function]}
-  type="button"
->
-  test
-</button>
-`;
-
-exports[`DelayedButton starts timer after click 1`] = `
-<CountdownButton
-  autoFocus={true}
-  buttonClass="test-button"
-  formatter={[MockFunction]}
-  onCancelled={[Function]}
-  onEnd={[MockFunction]}
-  seconds={10}
-/>
-`;

+ 0 - 512
client/src/tests/__snapshots__/Dropdown.test.js.snap

@@ -1,512 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`CountryDropdown renders 1`] = `
-<div
-  className="container"
->
-  <div
-    className="button"
-    onClick={[MockFunction]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    flag
-  </div>
-  <CSSTransition
-    classNames={
-      Object {
-        "enter": "list-enter",
-        "enterActive": "list-enter-active",
-        "exit": "list-exit",
-        "exitActive": "list-exit-active",
-      }
-    }
-    in={true}
-    mountOnEnter={true}
-    nodeRef={
-      Object {
-        "current": null,
-      }
-    }
-    timeout={200}
-    unmountOnExit={true}
-  >
-    <div
-      className="list"
-      role="menu"
-    >
-      <input
-        autoFocus={true}
-        className="search"
-        onChange={[Function]}
-        onKeyDown={[Function]}
-        type="text"
-        value=""
-      />
-      <CountryItem
-        code={null}
-        country="All Countries"
-        onSelect={[Function]}
-      />
-    </div>
-  </CSSTransition>
-</div>
-`;
-
-exports[`CountryDropdown renders closed 1`] = `
-<div
-  className="container"
->
-  <div
-    className="button"
-    onClick={[MockFunction]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    flag
-  </div>
-  <CSSTransition
-    classNames={
-      Object {
-        "enter": "list-enter",
-        "enterActive": "list-enter-active",
-        "exit": "list-exit",
-        "exitActive": "list-exit-active",
-      }
-    }
-    mountOnEnter={true}
-    nodeRef={
-      Object {
-        "current": null,
-      }
-    }
-    timeout={200}
-    unmountOnExit={true}
-  >
-    <div
-      className="list"
-      role="menu"
-    >
-      <input
-        autoFocus={true}
-        className="search"
-        onChange={[Function]}
-        onKeyDown={[Function]}
-        type="text"
-        value=""
-      />
-      <CountryItem
-        code={null}
-        country="All Countries"
-        onSelect={[Function]}
-      />
-    </div>
-  </CSSTransition>
-</div>
-`;
-
-exports[`CountryDropdown renders with countries 1`] = `
-<div
-  className="container"
->
-  <div
-    className="button"
-    onClick={[MockFunction]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    flag
-  </div>
-  <CSSTransition
-    classNames={
-      Object {
-        "enter": "list-enter",
-        "enterActive": "list-enter-active",
-        "exit": "list-exit",
-        "exitActive": "list-exit-active",
-      }
-    }
-    in={true}
-    mountOnEnter={true}
-    nodeRef={
-      Object {
-        "current": null,
-      }
-    }
-    timeout={200}
-    unmountOnExit={true}
-  >
-    <div
-      className="list"
-      role="menu"
-    >
-      <input
-        autoFocus={true}
-        className="search"
-        onChange={[Function]}
-        onKeyDown={[Function]}
-        type="text"
-        value=""
-      />
-      <CountryItem
-        code="a21"
-        country="c1"
-        key="a21"
-        onSelect={[Function]}
-      />
-      <CountryItem
-        code="a22"
-        country="c2"
-        key="a22"
-        onSelect={[Function]}
-      />
-      <CountryItem
-        code="a23"
-        country="c3"
-        key="a23"
-        onSelect={[Function]}
-      />
-      <CountryItem
-        code={null}
-        country="All Countries"
-        onSelect={[Function]}
-      />
-    </div>
-  </CSSTransition>
-</div>
-`;
-
-exports[`CountryItem renders 1`] = `
-<div
-  className="item"
-  onClick={[Function]}
-  onKeyDown={[Function]}
-  role="menuitem"
-  tabIndex="0"
->
-  flag
-   - 
-  test-country
-</div>
-`;
-
-exports[`Dropdown passes button class 1`] = `
-<div
-  className="container"
->
-  <div
-    className="button test-button-class"
-    onClick={[MockFunction]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  />
-  <CSSTransition
-    classNames={
-      Object {
-        "enter": "list-enter",
-        "enterActive": "list-enter-active",
-        "exit": "list-exit",
-        "exitActive": "list-exit-active",
-      }
-    }
-    mountOnEnter={true}
-    nodeRef={
-      Object {
-        "current": null,
-      }
-    }
-    timeout={200}
-    unmountOnExit={true}
-  >
-    <div
-      className="list"
-      role="menu"
-    />
-  </CSSTransition>
-</div>
-`;
-
-exports[`Dropdown renders closed 1`] = `
-<div
-  className="container"
->
-  <div
-    className="button "
-    onClick={[MockFunction]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  />
-  <CSSTransition
-    classNames={
-      Object {
-        "enter": "list-enter",
-        "enterActive": "list-enter-active",
-        "exit": "list-exit",
-        "exitActive": "list-exit-active",
-      }
-    }
-    mountOnEnter={true}
-    nodeRef={
-      Object {
-        "current": null,
-      }
-    }
-    timeout={200}
-    unmountOnExit={true}
-  >
-    <div
-      className="list"
-      role="menu"
-    />
-  </CSSTransition>
-</div>
-`;
-
-exports[`Dropdown renders with items 1`] = `
-<div
-  className="container"
->
-  <div
-    className="button "
-    onClick={[MockFunction]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  />
-  <CSSTransition
-    classNames={
-      Object {
-        "enter": "list-enter",
-        "enterActive": "list-enter-active",
-        "exit": "list-exit",
-        "exitActive": "list-exit-active",
-      }
-    }
-    in={true}
-    mountOnEnter={true}
-    nodeRef={
-      Object {
-        "current": null,
-      }
-    }
-    timeout={200}
-    unmountOnExit={true}
-  >
-    <div
-      className="list"
-      role="menu"
-    >
-      <Item
-        key="\\"test1\\""
-        onSelect={[Function]}
-        value="test1"
-      />
-      <Item
-        key="\\"test2\\""
-        onSelect={[Function]}
-        value="test2"
-      />
-    </div>
-  </CSSTransition>
-</div>
-`;
-
-exports[`Dropdown renders with no items 1`] = `
-<div
-  className="container"
->
-  <div
-    className="button "
-    onClick={[MockFunction]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  />
-  <CSSTransition
-    classNames={
-      Object {
-        "enter": "list-enter",
-        "enterActive": "list-enter-active",
-        "exit": "list-exit",
-        "exitActive": "list-exit-active",
-      }
-    }
-    in={true}
-    mountOnEnter={true}
-    nodeRef={
-      Object {
-        "current": null,
-      }
-    }
-    timeout={200}
-    unmountOnExit={true}
-  >
-    <div
-      className="list"
-      role="menu"
-    />
-  </CSSTransition>
-</div>
-`;
-
-exports[`Dropdown responds to item selection 1`] = `
-<div
-  className="container"
->
-  <div
-    className="button "
-    onClick={[MockFunction]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    display
-  </div>
-  <CSSTransition
-    classNames={
-      Object {
-        "enter": "list-enter",
-        "enterActive": "list-enter-active",
-        "exit": "list-exit",
-        "exitActive": "list-exit-active",
-      }
-    }
-    in={true}
-    mountOnEnter={true}
-    nodeRef={
-      Object {
-        "current": null,
-      }
-    }
-    timeout={200}
-    unmountOnExit={true}
-  >
-    <div
-      className="list"
-      role="menu"
-    >
-      <Item
-        key="\\"test1\\""
-        onSelect={[Function]}
-        value="test1"
-      />
-      <Item
-        key="\\"test2\\""
-        onSelect={[Function]}
-        value="test2"
-      />
-    </div>
-  </CSSTransition>
-</div>
-`;
-
-exports[`DropdownGroup can have a dropdown closed after opening 1`] = `
-<Fragment>
-  <Dropdown
-    key="dd1"
-    onClick={[Function]}
-    onSelect={[Function]}
-    open={false}
-  />
-  <Dropdown
-    key="dd2"
-    onClick={[Function]}
-    onSelect={[Function]}
-    open={false}
-  />
-  <Dropdown
-    key="dd3"
-    onClick={[Function]}
-    onSelect={[Function]}
-    open={false}
-  />
-</Fragment>
-`;
-
-exports[`DropdownGroup can have a dropdown opened 1`] = `
-<Fragment>
-  <Dropdown
-    key="dd1"
-    onClick={[Function]}
-    onSelect={[Function]}
-    open={false}
-  />
-  <Dropdown
-    key="dd2"
-    onClick={[Function]}
-    onSelect={[Function]}
-    open={true}
-  />
-  <Dropdown
-    key="dd3"
-    onClick={[Function]}
-    onSelect={[Function]}
-    open={false}
-  />
-</Fragment>
-`;
-
-exports[`DropdownGroup renders with dropdowns 1`] = `
-<Fragment>
-  <Dropdown
-    key="dd1"
-    onClick={[Function]}
-    onSelect={[Function]}
-    open={false}
-  />
-  <Dropdown
-    key="dd2"
-    onClick={[Function]}
-    onSelect={[Function]}
-    open={false}
-  />
-  <Dropdown
-    key="dd3"
-    onClick={[Function]}
-    onSelect={[Function]}
-    open={false}
-  />
-</Fragment>
-`;
-
-exports[`DropdownGroup renders with no dropdowns 1`] = `<Fragment />`;
-
-exports[`DropdownGroup selecting a dropdown re-closes it 1`] = `
-<Fragment>
-  <Dropdown
-    key="dd1"
-    onClick={[Function]}
-    onSelect={[Function]}
-    open={false}
-  />
-  <Dropdown
-    key="dd2"
-    onClick={[Function]}
-    onSelect={[Function]}
-    open={false}
-  />
-  <Dropdown
-    key="dd3"
-    onClick={[Function]}
-    onSelect={[Function]}
-    open={false}
-  />
-</Fragment>
-`;
-
-exports[`Item renders with no text 1`] = `
-<div
-  className="item"
-  onClick={[Function]}
-  onKeyDown={[Function]}
-  role="menuitem"
-  tabIndex="0"
->
-  display
-</div>
-`;

+ 0 - 70
client/src/tests/__snapshots__/ErrorModal.test.js.snap

@@ -1,70 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`ErrorModal renders 1`] = `
-<CSSTransition
-  classNames="fade"
-  mountOnEnter={true}
-  nodeRef={
-    Object {
-      "current": null,
-    }
-  }
-  timeout={200}
-  unmountOnExit={true}
->
-  <div
-    className="background"
-  >
-    <div
-      className="content"
-    >
-      <p
-        className="text"
-      >
-        Sorry! The server took too long to generate points for that game - your configurations may be too restrictive.
-      </p>
-      <button
-        onClick={[MockFunction]}
-        type="button"
-      >
-        Close
-      </button>
-    </div>
-  </div>
-</CSSTransition>
-`;
-
-exports[`ErrorModal renders when open 1`] = `
-<CSSTransition
-  classNames="fade"
-  in={true}
-  mountOnEnter={true}
-  nodeRef={
-    Object {
-      "current": null,
-    }
-  }
-  timeout={200}
-  unmountOnExit={true}
->
-  <div
-    className="background"
-  >
-    <div
-      className="content"
-    >
-      <p
-        className="text"
-      >
-        Sorry! The server took too long to generate points for that game - your configurations may be too restrictive.
-      </p>
-      <button
-        onClick={[MockFunction]}
-        type="button"
-      >
-        Close
-      </button>
-    </div>
-  </div>
-</CSSTransition>
-`;

+ 0 - 2258
client/src/tests/__snapshots__/GameCreationForm.test.js.snap

@@ -1,2258 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`GameCreationForm LastSettingsButton renders 1`] = `
-<div
-  className="reusebutton"
-  onClick={[MockFunction]}
-  onKeyDown={[Function]}
-  role="button"
-  tabIndex="0"
-  title="Reuse Previous Game Settings"
->
-  <span
-    aria-label="recycle"
-    role="img"
-  >
-    ♻️
-  </span>
-</div>
-`;
-
-exports[`GameCreationForm can have presets selected 1`] = `
-<div
-  className="form"
->
-  <ErrorModal
-    onClose={[Function]}
-    open={false}
-  />
-  <div
-    className="buttoncontainer"
-  >
-    <Dropdown
-      buttonClass="favbutton"
-      onClick={[Function]}
-      onSelect={[Function]}
-      open={false}
-      selected={
-        Object {
-          "clockMode": "NORMAL",
-          "countryLock": null,
-          "gameMode": "NORMAL",
-          "generationMethod": "RANDOMSTREETVIEW",
-          "roundPointCap": null,
-          "rounds": 5,
-          "scoreMethod": "DISTANCE",
-          "timer": 300,
-        }
-      }
-    >
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "NORMAL",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "DISTANCE",
-            "timer": 300,
-          }
-        }
-      >
-        Default
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": "us",
-            "gameMode": "NORMAL",
-            "generationMethod": "URBAN",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "DISTANCE",
-            "timer": 300,
-          }
-        }
-      >
-        Urban America
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "NORMAL",
-            "generationMethod": "URBAN",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "DISTANCE",
-            "timer": 300,
-          }
-        }
-      >
-        Urban Global
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "FROZEN",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 3,
-            "scoreMethod": "DISTANCE",
-            "timer": 30,
-          }
-        }
-      >
-        Fast Frozen
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "NORMAL",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "COUNTRYRACE",
-            "timer": 300,
-          }
-        }
-      >
-        Country Race
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "FROZEN",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "COUNTRYRACE",
-            "timer": 30,
-          }
-        }
-      >
-        Frozen Country Race
-      </Item>
-    </Dropdown>
-    <button
-      className="start"
-      onClick={[Function]}
-      type="button"
-    >
-      New Game
-    </button>
-  </div>
-  <div
-    className="dropdowns"
-  >
-    <DropdownGroup>
-      <Dropdown
-        onSelect={[Function]}
-        open="timer"
-        selected={30}
-      >
-        <Item
-          display="30s"
-          value={30}
-        >
-          30 Seconds
-        </Item>
-        <Item
-          display="2m"
-          value={120}
-        >
-          2 Minutes
-        </Item>
-        <Item
-          display="5m"
-          value={300}
-        >
-          5 Minutes
-        </Item>
-        <Item
-          display="1h"
-          value={3600}
-        >
-          1 Hour
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="rounds"
-        selected={3}
-      >
-        <Item
-          value={1}
-        >
-          1 Round
-        </Item>
-        <Item
-          value={3}
-        >
-          3 Rounds
-        </Item>
-        <Item
-          value={5}
-        >
-          5 Rounds
-        </Item>
-        <Item
-          value={10}
-        >
-          10 Rounds
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="gen"
-        selected="URBAN"
-      >
-        <Item
-          display="🎲"
-          value="RANDOMSTREETVIEW"
-        >
-          Random Street View
-        </Item>
-        <Item
-          display="🏙️"
-          value="URBAN"
-        >
-          Urban Centers
-        </Item>
-      </Dropdown>
-      <CountryDropdown
-        countryLookup="country-lookup"
-        onSelect={[Function]}
-        open="country"
-        selected="us"
-      />
-      <Dropdown
-        onSelect={[Function]}
-        open="gameMode"
-        selected="FROZEN"
-      >
-        <Item
-          display="📍"
-          value="NORMAL"
-        >
-          Normal
-        </Item>
-        <Item
-          display="❄️"
-          value="FROZEN"
-        >
-          Frozen
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="clockMode"
-        selected="NORMAL"
-      >
-        <Item
-          display="⏰"
-          value="NORMAL"
-        >
-          Normal
-        </Item>
-        <Item
-          display="🏦"
-          value="TIMEBANK"
-        >
-          Time Bank
-        </Item>
-        <Item
-          display="🏃"
-          value="RACE"
-        >
-          Race
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="scoreMethod"
-        selected="COUNTRYRACE"
-      >
-        <Item
-          display="📏"
-          value="DISTANCE"
-        >
-          Distance
-        </Item>
-        <Item
-          display="🗾"
-          value="COUNTRYRACE"
-        >
-          Country Race
-        </Item>
-        <Item
-          display="😬"
-          value="HARD"
-        >
-          Hard Mode
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="roundPointCap"
-        selected={null}
-      >
-        <Item
-          display="♾️"
-          value={null}
-        >
-          No Limit
-        </Item>
-        <Item
-          display="10k"
-          value={10000}
-        >
-          10k Total Points per Round
-        </Item>
-        <Item
-          display="20k"
-          value={20000}
-        >
-          20k Total Points per Round
-        </Item>
-      </Dropdown>
-    </DropdownGroup>
-  </div>
-</div>
-`;
-
-exports[`GameCreationForm can have previous game settings passed in to enable reuse button 1`] = `
-<div
-  className="form"
->
-  <ErrorModal
-    onClose={[Function]}
-    open={false}
-  />
-  <div
-    className="buttoncontainer"
-  >
-    <Dropdown
-      buttonClass="favbutton"
-      onClick={[Function]}
-      onSelect={[Function]}
-      open={false}
-      selected={
-        Object {
-          "clockMode": "NORMAL",
-          "countryLock": null,
-          "gameMode": "NORMAL",
-          "generationMethod": "RANDOMSTREETVIEW",
-          "roundPointCap": null,
-          "rounds": 5,
-          "scoreMethod": "DISTANCE",
-          "timer": 300,
-        }
-      }
-    >
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "NORMAL",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "DISTANCE",
-            "timer": 300,
-          }
-        }
-      >
-        Default
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": "us",
-            "gameMode": "NORMAL",
-            "generationMethod": "URBAN",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "DISTANCE",
-            "timer": 300,
-          }
-        }
-      >
-        Urban America
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "NORMAL",
-            "generationMethod": "URBAN",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "DISTANCE",
-            "timer": 300,
-          }
-        }
-      >
-        Urban Global
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "FROZEN",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 3,
-            "scoreMethod": "DISTANCE",
-            "timer": 30,
-          }
-        }
-      >
-        Fast Frozen
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "NORMAL",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "COUNTRYRACE",
-            "timer": 300,
-          }
-        }
-      >
-        Country Race
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "FROZEN",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "COUNTRYRACE",
-            "timer": 30,
-          }
-        }
-      >
-        Frozen Country Race
-      </Item>
-    </Dropdown>
-    <LastSettingsButton
-      onClick={[Function]}
-    />
-    <button
-      className="start"
-      onClick={[Function]}
-      type="button"
-    >
-      New Game
-    </button>
-  </div>
-  <div
-    className="dropdowns"
-  >
-    <DropdownGroup>
-      <Dropdown
-        onSelect={[Function]}
-        open="timer"
-        selected={300}
-      >
-        <Item
-          display="30s"
-          value={30}
-        >
-          30 Seconds
-        </Item>
-        <Item
-          display="2m"
-          value={120}
-        >
-          2 Minutes
-        </Item>
-        <Item
-          display="5m"
-          value={300}
-        >
-          5 Minutes
-        </Item>
-        <Item
-          display="1h"
-          value={3600}
-        >
-          1 Hour
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="rounds"
-        selected={5}
-      >
-        <Item
-          value={1}
-        >
-          1 Round
-        </Item>
-        <Item
-          value={3}
-        >
-          3 Rounds
-        </Item>
-        <Item
-          value={5}
-        >
-          5 Rounds
-        </Item>
-        <Item
-          value={10}
-        >
-          10 Rounds
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="gen"
-        selected="RANDOMSTREETVIEW"
-      >
-        <Item
-          display="🎲"
-          value="RANDOMSTREETVIEW"
-        >
-          Random Street View
-        </Item>
-        <Item
-          display="🏙️"
-          value="URBAN"
-        >
-          Urban Centers
-        </Item>
-      </Dropdown>
-      <CountryDropdown
-        countryLookup="country-lookup"
-        onSelect={[Function]}
-        open="country"
-        selected={null}
-      />
-      <Dropdown
-        onSelect={[Function]}
-        open="gameMode"
-        selected="NORMAL"
-      >
-        <Item
-          display="📍"
-          value="NORMAL"
-        >
-          Normal
-        </Item>
-        <Item
-          display="❄️"
-          value="FROZEN"
-        >
-          Frozen
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="clockMode"
-        selected="NORMAL"
-      >
-        <Item
-          display="⏰"
-          value="NORMAL"
-        >
-          Normal
-        </Item>
-        <Item
-          display="🏦"
-          value="TIMEBANK"
-        >
-          Time Bank
-        </Item>
-        <Item
-          display="🏃"
-          value="RACE"
-        >
-          Race
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="scoreMethod"
-        selected="DISTANCE"
-      >
-        <Item
-          display="📏"
-          value="DISTANCE"
-        >
-          Distance
-        </Item>
-        <Item
-          display="🗾"
-          value="COUNTRYRACE"
-        >
-          Country Race
-        </Item>
-        <Item
-          display="😬"
-          value="HARD"
-        >
-          Hard Mode
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="roundPointCap"
-        selected={null}
-      >
-        <Item
-          display="♾️"
-          value={null}
-        >
-          No Limit
-        </Item>
-        <Item
-          display="10k"
-          value={10000}
-        >
-          10k Total Points per Round
-        </Item>
-        <Item
-          display="20k"
-          value={20000}
-        >
-          20k Total Points per Round
-        </Item>
-      </Dropdown>
-    </DropdownGroup>
-  </div>
-</div>
-`;
-
-exports[`GameCreationForm can have previous game settings passed in to enable reuse button 2`] = `
-<div
-  className="form"
->
-  <ErrorModal
-    onClose={[Function]}
-    open={false}
-  />
-  <div
-    className="buttoncontainer"
-  >
-    <Dropdown
-      buttonClass="favbutton"
-      onClick={[Function]}
-      onSelect={[Function]}
-      open={false}
-      selected={
-        Object {
-          "clockMode": "NORMAL",
-          "countryLock": null,
-          "gameMode": "NORMAL",
-          "generationMethod": "RANDOMSTREETVIEW",
-          "roundPointCap": null,
-          "rounds": 5,
-          "scoreMethod": "DISTANCE",
-          "timer": 300,
-        }
-      }
-    >
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "NORMAL",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "DISTANCE",
-            "timer": 300,
-          }
-        }
-      >
-        Default
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": "us",
-            "gameMode": "NORMAL",
-            "generationMethod": "URBAN",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "DISTANCE",
-            "timer": 300,
-          }
-        }
-      >
-        Urban America
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "NORMAL",
-            "generationMethod": "URBAN",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "DISTANCE",
-            "timer": 300,
-          }
-        }
-      >
-        Urban Global
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "FROZEN",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 3,
-            "scoreMethod": "DISTANCE",
-            "timer": 30,
-          }
-        }
-      >
-        Fast Frozen
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "NORMAL",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "COUNTRYRACE",
-            "timer": 300,
-          }
-        }
-      >
-        Country Race
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "FROZEN",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "COUNTRYRACE",
-            "timer": 30,
-          }
-        }
-      >
-        Frozen Country Race
-      </Item>
-    </Dropdown>
-    <LastSettingsButton
-      onClick={[Function]}
-    />
-    <button
-      className="start"
-      onClick={[Function]}
-      type="button"
-    >
-      New Game
-    </button>
-  </div>
-  <div
-    className="dropdowns"
-  >
-    <DropdownGroup>
-      <Dropdown
-        onSelect={[Function]}
-        open="timer"
-        selected={30}
-      >
-        <Item
-          display="30s"
-          value={30}
-        >
-          30 Seconds
-        </Item>
-        <Item
-          display="2m"
-          value={120}
-        >
-          2 Minutes
-        </Item>
-        <Item
-          display="5m"
-          value={300}
-        >
-          5 Minutes
-        </Item>
-        <Item
-          display="1h"
-          value={3600}
-        >
-          1 Hour
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="rounds"
-        selected={3}
-      >
-        <Item
-          value={1}
-        >
-          1 Round
-        </Item>
-        <Item
-          value={3}
-        >
-          3 Rounds
-        </Item>
-        <Item
-          value={5}
-        >
-          5 Rounds
-        </Item>
-        <Item
-          value={10}
-        >
-          10 Rounds
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="gen"
-        selected="URBAN"
-      >
-        <Item
-          display="🎲"
-          value="RANDOMSTREETVIEW"
-        >
-          Random Street View
-        </Item>
-        <Item
-          display="🏙️"
-          value="URBAN"
-        >
-          Urban Centers
-        </Item>
-      </Dropdown>
-      <CountryDropdown
-        countryLookup="country-lookup"
-        onSelect={[Function]}
-        open="country"
-        selected="us"
-      />
-      <Dropdown
-        onSelect={[Function]}
-        open="gameMode"
-        selected="FROZEN"
-      >
-        <Item
-          display="📍"
-          value="NORMAL"
-        >
-          Normal
-        </Item>
-        <Item
-          display="❄️"
-          value="FROZEN"
-        >
-          Frozen
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="clockMode"
-        selected="NORMAL"
-      >
-        <Item
-          display="⏰"
-          value="NORMAL"
-        >
-          Normal
-        </Item>
-        <Item
-          display="🏦"
-          value="TIMEBANK"
-        >
-          Time Bank
-        </Item>
-        <Item
-          display="🏃"
-          value="RACE"
-        >
-          Race
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="scoreMethod"
-        selected="COUNTRYRACE"
-      >
-        <Item
-          display="📏"
-          value="DISTANCE"
-        >
-          Distance
-        </Item>
-        <Item
-          display="🗾"
-          value="COUNTRYRACE"
-        >
-          Country Race
-        </Item>
-        <Item
-          display="😬"
-          value="HARD"
-        >
-          Hard Mode
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="roundPointCap"
-        selected={null}
-      >
-        <Item
-          display="♾️"
-          value={null}
-        >
-          No Limit
-        </Item>
-        <Item
-          display="10k"
-          value={10000}
-        >
-          10k Total Points per Round
-        </Item>
-        <Item
-          display="20k"
-          value={20000}
-        >
-          20k Total Points per Round
-        </Item>
-      </Dropdown>
-    </DropdownGroup>
-  </div>
-</div>
-`;
-
-exports[`GameCreationForm can have the error modal closed 1`] = `
-<div
-  className="form"
->
-  <ErrorModal
-    onClose={[Function]}
-    open={false}
-  />
-  <div
-    className="buttoncontainer"
-  >
-    <Dropdown
-      buttonClass="favbutton"
-      onClick={[Function]}
-      onSelect={[Function]}
-      open={false}
-      selected={
-        Object {
-          "clockMode": "NORMAL",
-          "countryLock": null,
-          "gameMode": "NORMAL",
-          "generationMethod": "RANDOMSTREETVIEW",
-          "roundPointCap": null,
-          "rounds": 5,
-          "scoreMethod": "DISTANCE",
-          "timer": 300,
-        }
-      }
-    >
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "NORMAL",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "DISTANCE",
-            "timer": 300,
-          }
-        }
-      >
-        Default
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": "us",
-            "gameMode": "NORMAL",
-            "generationMethod": "URBAN",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "DISTANCE",
-            "timer": 300,
-          }
-        }
-      >
-        Urban America
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "NORMAL",
-            "generationMethod": "URBAN",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "DISTANCE",
-            "timer": 300,
-          }
-        }
-      >
-        Urban Global
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "FROZEN",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 3,
-            "scoreMethod": "DISTANCE",
-            "timer": 30,
-          }
-        }
-      >
-        Fast Frozen
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "NORMAL",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "COUNTRYRACE",
-            "timer": 300,
-          }
-        }
-      >
-        Country Race
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "FROZEN",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "COUNTRYRACE",
-            "timer": 30,
-          }
-        }
-      >
-        Frozen Country Race
-      </Item>
-    </Dropdown>
-    <button
-      className="start"
-      onClick={[Function]}
-      type="button"
-    >
-      New Game
-    </button>
-  </div>
-  <div
-    className="dropdowns"
-  >
-    <DropdownGroup>
-      <Dropdown
-        onSelect={[Function]}
-        open="timer"
-        selected={300}
-      >
-        <Item
-          display="30s"
-          value={30}
-        >
-          30 Seconds
-        </Item>
-        <Item
-          display="2m"
-          value={120}
-        >
-          2 Minutes
-        </Item>
-        <Item
-          display="5m"
-          value={300}
-        >
-          5 Minutes
-        </Item>
-        <Item
-          display="1h"
-          value={3600}
-        >
-          1 Hour
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="rounds"
-        selected={5}
-      >
-        <Item
-          value={1}
-        >
-          1 Round
-        </Item>
-        <Item
-          value={3}
-        >
-          3 Rounds
-        </Item>
-        <Item
-          value={5}
-        >
-          5 Rounds
-        </Item>
-        <Item
-          value={10}
-        >
-          10 Rounds
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="gen"
-        selected="RANDOMSTREETVIEW"
-      >
-        <Item
-          display="🎲"
-          value="RANDOMSTREETVIEW"
-        >
-          Random Street View
-        </Item>
-        <Item
-          display="🏙️"
-          value="URBAN"
-        >
-          Urban Centers
-        </Item>
-      </Dropdown>
-      <CountryDropdown
-        countryLookup="country-lookup"
-        onSelect={[Function]}
-        open="country"
-        selected={null}
-      />
-      <Dropdown
-        onSelect={[Function]}
-        open="gameMode"
-        selected="NORMAL"
-      >
-        <Item
-          display="📍"
-          value="NORMAL"
-        >
-          Normal
-        </Item>
-        <Item
-          display="❄️"
-          value="FROZEN"
-        >
-          Frozen
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="clockMode"
-        selected="NORMAL"
-      >
-        <Item
-          display="⏰"
-          value="NORMAL"
-        >
-          Normal
-        </Item>
-        <Item
-          display="🏦"
-          value="TIMEBANK"
-        >
-          Time Bank
-        </Item>
-        <Item
-          display="🏃"
-          value="RACE"
-        >
-          Race
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="scoreMethod"
-        selected="DISTANCE"
-      >
-        <Item
-          display="📏"
-          value="DISTANCE"
-        >
-          Distance
-        </Item>
-        <Item
-          display="🗾"
-          value="COUNTRYRACE"
-        >
-          Country Race
-        </Item>
-        <Item
-          display="😬"
-          value="HARD"
-        >
-          Hard Mode
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="roundPointCap"
-        selected={null}
-      >
-        <Item
-          display="♾️"
-          value={null}
-        >
-          No Limit
-        </Item>
-        <Item
-          display="10k"
-          value={10000}
-        >
-          10k Total Points per Round
-        </Item>
-        <Item
-          display="20k"
-          value={20000}
-        >
-          20k Total Points per Round
-        </Item>
-      </Dropdown>
-    </DropdownGroup>
-  </div>
-</div>
-`;
-
-exports[`GameCreationForm can have the preset dropdown opened 1`] = `
-<div
-  className="form"
->
-  <ErrorModal
-    onClose={[Function]}
-    open={false}
-  />
-  <div
-    className="buttoncontainer"
-  >
-    <Dropdown
-      buttonClass="favbutton"
-      onClick={[Function]}
-      onSelect={[Function]}
-      open={true}
-      selected={
-        Object {
-          "clockMode": "NORMAL",
-          "countryLock": null,
-          "gameMode": "NORMAL",
-          "generationMethod": "RANDOMSTREETVIEW",
-          "roundPointCap": null,
-          "rounds": 5,
-          "scoreMethod": "DISTANCE",
-          "timer": 300,
-        }
-      }
-    >
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "NORMAL",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "DISTANCE",
-            "timer": 300,
-          }
-        }
-      >
-        Default
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": "us",
-            "gameMode": "NORMAL",
-            "generationMethod": "URBAN",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "DISTANCE",
-            "timer": 300,
-          }
-        }
-      >
-        Urban America
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "NORMAL",
-            "generationMethod": "URBAN",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "DISTANCE",
-            "timer": 300,
-          }
-        }
-      >
-        Urban Global
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "FROZEN",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 3,
-            "scoreMethod": "DISTANCE",
-            "timer": 30,
-          }
-        }
-      >
-        Fast Frozen
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "NORMAL",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "COUNTRYRACE",
-            "timer": 300,
-          }
-        }
-      >
-        Country Race
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "FROZEN",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "COUNTRYRACE",
-            "timer": 30,
-          }
-        }
-      >
-        Frozen Country Race
-      </Item>
-    </Dropdown>
-    <button
-      className="start"
-      onClick={[Function]}
-      type="button"
-    >
-      New Game
-    </button>
-  </div>
-  <div
-    className="dropdowns"
-  >
-    <DropdownGroup>
-      <Dropdown
-        onSelect={[Function]}
-        open="timer"
-        selected={300}
-      >
-        <Item
-          display="30s"
-          value={30}
-        >
-          30 Seconds
-        </Item>
-        <Item
-          display="2m"
-          value={120}
-        >
-          2 Minutes
-        </Item>
-        <Item
-          display="5m"
-          value={300}
-        >
-          5 Minutes
-        </Item>
-        <Item
-          display="1h"
-          value={3600}
-        >
-          1 Hour
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="rounds"
-        selected={5}
-      >
-        <Item
-          value={1}
-        >
-          1 Round
-        </Item>
-        <Item
-          value={3}
-        >
-          3 Rounds
-        </Item>
-        <Item
-          value={5}
-        >
-          5 Rounds
-        </Item>
-        <Item
-          value={10}
-        >
-          10 Rounds
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="gen"
-        selected="RANDOMSTREETVIEW"
-      >
-        <Item
-          display="🎲"
-          value="RANDOMSTREETVIEW"
-        >
-          Random Street View
-        </Item>
-        <Item
-          display="🏙️"
-          value="URBAN"
-        >
-          Urban Centers
-        </Item>
-      </Dropdown>
-      <CountryDropdown
-        countryLookup="country-lookup"
-        onSelect={[Function]}
-        open="country"
-        selected={null}
-      />
-      <Dropdown
-        onSelect={[Function]}
-        open="gameMode"
-        selected="NORMAL"
-      >
-        <Item
-          display="📍"
-          value="NORMAL"
-        >
-          Normal
-        </Item>
-        <Item
-          display="❄️"
-          value="FROZEN"
-        >
-          Frozen
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="clockMode"
-        selected="NORMAL"
-      >
-        <Item
-          display="⏰"
-          value="NORMAL"
-        >
-          Normal
-        </Item>
-        <Item
-          display="🏦"
-          value="TIMEBANK"
-        >
-          Time Bank
-        </Item>
-        <Item
-          display="🏃"
-          value="RACE"
-        >
-          Race
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="scoreMethod"
-        selected="DISTANCE"
-      >
-        <Item
-          display="📏"
-          value="DISTANCE"
-        >
-          Distance
-        </Item>
-        <Item
-          display="🗾"
-          value="COUNTRYRACE"
-        >
-          Country Race
-        </Item>
-        <Item
-          display="😬"
-          value="HARD"
-        >
-          Hard Mode
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="roundPointCap"
-        selected={null}
-      >
-        <Item
-          display="♾️"
-          value={null}
-        >
-          No Limit
-        </Item>
-        <Item
-          display="10k"
-          value={10000}
-        >
-          10k Total Points per Round
-        </Item>
-        <Item
-          display="20k"
-          value={20000}
-        >
-          20k Total Points per Round
-        </Item>
-      </Dropdown>
-    </DropdownGroup>
-  </div>
-</div>
-`;
-
-exports[`GameCreationForm handles error creating a game 1`] = `
-<div
-  className="form"
->
-  <ErrorModal
-    onClose={[Function]}
-    open={true}
-  />
-  <div
-    className="buttoncontainer"
-  >
-    <Dropdown
-      buttonClass="favbutton"
-      onClick={[Function]}
-      onSelect={[Function]}
-      open={false}
-      selected={
-        Object {
-          "clockMode": "NORMAL",
-          "countryLock": null,
-          "gameMode": "NORMAL",
-          "generationMethod": "RANDOMSTREETVIEW",
-          "roundPointCap": null,
-          "rounds": 5,
-          "scoreMethod": "DISTANCE",
-          "timer": 300,
-        }
-      }
-    >
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "NORMAL",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "DISTANCE",
-            "timer": 300,
-          }
-        }
-      >
-        Default
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": "us",
-            "gameMode": "NORMAL",
-            "generationMethod": "URBAN",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "DISTANCE",
-            "timer": 300,
-          }
-        }
-      >
-        Urban America
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "NORMAL",
-            "generationMethod": "URBAN",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "DISTANCE",
-            "timer": 300,
-          }
-        }
-      >
-        Urban Global
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "FROZEN",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 3,
-            "scoreMethod": "DISTANCE",
-            "timer": 30,
-          }
-        }
-      >
-        Fast Frozen
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "NORMAL",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "COUNTRYRACE",
-            "timer": 300,
-          }
-        }
-      >
-        Country Race
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "FROZEN",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "COUNTRYRACE",
-            "timer": 30,
-          }
-        }
-      >
-        Frozen Country Race
-      </Item>
-    </Dropdown>
-    <button
-      className="start"
-      onClick={[Function]}
-      type="button"
-    >
-      New Game
-    </button>
-  </div>
-  <div
-    className="dropdowns"
-  >
-    <DropdownGroup>
-      <Dropdown
-        onSelect={[Function]}
-        open="timer"
-        selected={300}
-      >
-        <Item
-          display="30s"
-          value={30}
-        >
-          30 Seconds
-        </Item>
-        <Item
-          display="2m"
-          value={120}
-        >
-          2 Minutes
-        </Item>
-        <Item
-          display="5m"
-          value={300}
-        >
-          5 Minutes
-        </Item>
-        <Item
-          display="1h"
-          value={3600}
-        >
-          1 Hour
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="rounds"
-        selected={5}
-      >
-        <Item
-          value={1}
-        >
-          1 Round
-        </Item>
-        <Item
-          value={3}
-        >
-          3 Rounds
-        </Item>
-        <Item
-          value={5}
-        >
-          5 Rounds
-        </Item>
-        <Item
-          value={10}
-        >
-          10 Rounds
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="gen"
-        selected="RANDOMSTREETVIEW"
-      >
-        <Item
-          display="🎲"
-          value="RANDOMSTREETVIEW"
-        >
-          Random Street View
-        </Item>
-        <Item
-          display="🏙️"
-          value="URBAN"
-        >
-          Urban Centers
-        </Item>
-      </Dropdown>
-      <CountryDropdown
-        countryLookup="country-lookup"
-        onSelect={[Function]}
-        open="country"
-        selected={null}
-      />
-      <Dropdown
-        onSelect={[Function]}
-        open="gameMode"
-        selected="NORMAL"
-      >
-        <Item
-          display="📍"
-          value="NORMAL"
-        >
-          Normal
-        </Item>
-        <Item
-          display="❄️"
-          value="FROZEN"
-        >
-          Frozen
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="clockMode"
-        selected="NORMAL"
-      >
-        <Item
-          display="⏰"
-          value="NORMAL"
-        >
-          Normal
-        </Item>
-        <Item
-          display="🏦"
-          value="TIMEBANK"
-        >
-          Time Bank
-        </Item>
-        <Item
-          display="🏃"
-          value="RACE"
-        >
-          Race
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="scoreMethod"
-        selected="DISTANCE"
-      >
-        <Item
-          display="📏"
-          value="DISTANCE"
-        >
-          Distance
-        </Item>
-        <Item
-          display="🗾"
-          value="COUNTRYRACE"
-        >
-          Country Race
-        </Item>
-        <Item
-          display="😬"
-          value="HARD"
-        >
-          Hard Mode
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="roundPointCap"
-        selected={null}
-      >
-        <Item
-          display="♾️"
-          value={null}
-        >
-          No Limit
-        </Item>
-        <Item
-          display="10k"
-          value={10000}
-        >
-          10k Total Points per Round
-        </Item>
-        <Item
-          display="20k"
-          value={20000}
-        >
-          20k Total Points per Round
-        </Item>
-      </Dropdown>
-    </DropdownGroup>
-  </div>
-</div>
-`;
-
-exports[`GameCreationForm renders 1`] = `
-<div
-  className="form"
->
-  <ErrorModal
-    onClose={[Function]}
-    open={false}
-  />
-  <div
-    className="buttoncontainer"
-  >
-    <Dropdown
-      buttonClass="favbutton"
-      onClick={[Function]}
-      onSelect={[Function]}
-      open={false}
-      selected={
-        Object {
-          "clockMode": "NORMAL",
-          "countryLock": null,
-          "gameMode": "NORMAL",
-          "generationMethod": "RANDOMSTREETVIEW",
-          "roundPointCap": null,
-          "rounds": 5,
-          "scoreMethod": "DISTANCE",
-          "timer": 300,
-        }
-      }
-    >
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "NORMAL",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "DISTANCE",
-            "timer": 300,
-          }
-        }
-      >
-        Default
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": "us",
-            "gameMode": "NORMAL",
-            "generationMethod": "URBAN",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "DISTANCE",
-            "timer": 300,
-          }
-        }
-      >
-        Urban America
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "NORMAL",
-            "generationMethod": "URBAN",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "DISTANCE",
-            "timer": 300,
-          }
-        }
-      >
-        Urban Global
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "FROZEN",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 3,
-            "scoreMethod": "DISTANCE",
-            "timer": 30,
-          }
-        }
-      >
-        Fast Frozen
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "NORMAL",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "COUNTRYRACE",
-            "timer": 300,
-          }
-        }
-      >
-        Country Race
-      </Item>
-      <Item
-        display="⭐"
-        value={
-          Object {
-            "clockMode": "NORMAL",
-            "countryLock": null,
-            "gameMode": "FROZEN",
-            "generationMethod": "RANDOMSTREETVIEW",
-            "roundPointCap": null,
-            "rounds": 5,
-            "scoreMethod": "COUNTRYRACE",
-            "timer": 30,
-          }
-        }
-      >
-        Frozen Country Race
-      </Item>
-    </Dropdown>
-    <button
-      className="start"
-      onClick={[Function]}
-      type="button"
-    >
-      New Game
-    </button>
-  </div>
-  <div
-    className="dropdowns"
-  >
-    <DropdownGroup>
-      <Dropdown
-        onSelect={[Function]}
-        open="timer"
-        selected={300}
-      >
-        <Item
-          display="30s"
-          value={30}
-        >
-          30 Seconds
-        </Item>
-        <Item
-          display="2m"
-          value={120}
-        >
-          2 Minutes
-        </Item>
-        <Item
-          display="5m"
-          value={300}
-        >
-          5 Minutes
-        </Item>
-        <Item
-          display="1h"
-          value={3600}
-        >
-          1 Hour
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="rounds"
-        selected={5}
-      >
-        <Item
-          value={1}
-        >
-          1 Round
-        </Item>
-        <Item
-          value={3}
-        >
-          3 Rounds
-        </Item>
-        <Item
-          value={5}
-        >
-          5 Rounds
-        </Item>
-        <Item
-          value={10}
-        >
-          10 Rounds
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="gen"
-        selected="RANDOMSTREETVIEW"
-      >
-        <Item
-          display="🎲"
-          value="RANDOMSTREETVIEW"
-        >
-          Random Street View
-        </Item>
-        <Item
-          display="🏙️"
-          value="URBAN"
-        >
-          Urban Centers
-        </Item>
-      </Dropdown>
-      <CountryDropdown
-        countryLookup="country-lookup"
-        onSelect={[Function]}
-        open="country"
-        selected={null}
-      />
-      <Dropdown
-        onSelect={[Function]}
-        open="gameMode"
-        selected="NORMAL"
-      >
-        <Item
-          display="📍"
-          value="NORMAL"
-        >
-          Normal
-        </Item>
-        <Item
-          display="❄️"
-          value="FROZEN"
-        >
-          Frozen
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="clockMode"
-        selected="NORMAL"
-      >
-        <Item
-          display="⏰"
-          value="NORMAL"
-        >
-          Normal
-        </Item>
-        <Item
-          display="🏦"
-          value="TIMEBANK"
-        >
-          Time Bank
-        </Item>
-        <Item
-          display="🏃"
-          value="RACE"
-        >
-          Race
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="scoreMethod"
-        selected="DISTANCE"
-      >
-        <Item
-          display="📏"
-          value="DISTANCE"
-        >
-          Distance
-        </Item>
-        <Item
-          display="🗾"
-          value="COUNTRYRACE"
-        >
-          Country Race
-        </Item>
-        <Item
-          display="😬"
-          value="HARD"
-        >
-          Hard Mode
-        </Item>
-      </Dropdown>
-      <Dropdown
-        onSelect={[Function]}
-        open="roundPointCap"
-        selected={null}
-      >
-        <Item
-          display="♾️"
-          value={null}
-        >
-          No Limit
-        </Item>
-        <Item
-          display="10k"
-          value={10000}
-        >
-          10k Total Points per Round
-        </Item>
-        <Item
-          display="20k"
-          value={20000}
-        >
-          20k Total Points per Round
-        </Item>
-      </Dropdown>
-    </DropdownGroup>
-  </div>
-</div>
-`;

+ 0 - 103
client/src/tests/__snapshots__/GamePanel.hooks.test.js.snap

@@ -1,103 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`GamePanel hooks usePano creates a new pano 1`] = `
-fakeClass {
-  "addListener": [Function],
-  "calledWith": Array [
-    "pano-div-ref",
-    Object {
-      "addressControl": false,
-      "clickToGo": true,
-      "fullscreenControl": false,
-      "motionTracking": false,
-      "motionTrackingControl": false,
-      "position": Object {
-        "lat": 1,
-        "lng": 2,
-      },
-      "pov": Object {
-        "heading": 3,
-        "pitch": 4,
-      },
-      "showRoadLabels": false,
-      "visible": true,
-    },
-  ],
-  "listeners": Map {},
-}
-`;
-
-exports[`GamePanel hooks usePano does not create a new pano when one exists and just moves old one 1`] = `
-Object {
-  "setPosition": [MockFunction] {
-    "calls": Array [
-      Array [
-        Object {
-          "lat": 1,
-          "lng": 2,
-        },
-      ],
-    ],
-    "results": Array [
-      Object {
-        "type": "return",
-        "value": undefined,
-      },
-    ],
-  },
-  "setPov": [MockFunction] {
-    "calls": Array [
-      Array [
-        Object {
-          "heading": 3,
-          "pitch": 4,
-        },
-      ],
-    ],
-    "results": Array [
-      Object {
-        "type": "return",
-        "value": undefined,
-      },
-    ],
-  },
-}
-`;
-
-exports[`GamePanel hooks usePano does not create a new pano when one exists and just moves old one 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      Object {
-        "lat": 1,
-        "lng": 2,
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`GamePanel hooks usePano does not create a new pano when one exists and just moves old one 3`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      Object {
-        "heading": 3,
-        "pitch": 4,
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;

+ 0 - 49
client/src/tests/__snapshots__/GamePanel.test.js.snap

@@ -1,49 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`GamePanel renders for FROZEN game 1`] = `
-<div
-  className="page"
->
-  <div
-    className="streetview"
-  >
-    <PositionedStreetView />
-    <div
-      className="freeze"
-    />
-  </div>
-  <GuessPane />
-</div>
-`;
-
-exports[`GamePanel renders for NORMAL game 1`] = `
-<div
-  className="page"
->
-  <div
-    className="streetview"
-  >
-    <PositionedStreetView />
-  </div>
-  <GuessPane />
-</div>
-`;
-
-exports[`GamePanel renders for RACE game 1`] = `
-<div
-  className="page"
->
-  <RaceMode
-    cutoffTime={10}
-    rate={1000}
-  />
-  <div
-    className="streetview"
-  >
-    <PositionedStreetView />
-  </div>
-  <GuessPane />
-</div>
-`;
-
-exports[`GamePanel renders for end of game 1`] = `<Loading />`;

+ 0 - 35
client/src/tests/__snapshots__/GameSummary.test.js.snap

@@ -1,35 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`GameSummary renders 1`] = `
-<div
-  className="page"
->
-  <div
-    className="top"
-  >
-    <SummaryMap
-      coords={Array []}
-      players={Array []}
-    />
-    <Memo()
-      gameId="test-game-id"
-    />
-  </div>
-  <ScoreBoard
-    players={Array []}
-  />
-  <span
-    className="label"
-  >
-    <ClickToCopy
-      text="http://localhost/?summary=test-game-id"
-    >
-      Click here to copy a link to this summary!
-    </ClickToCopy>
-  </span>
-</div>
-`;
-
-exports[`GameSummary renders loading when null coords 1`] = `<Loading />`;
-
-exports[`GameSummary renders loading when null players 1`] = `<Loading />`;

+ 0 - 508
client/src/tests/__snapshots__/GuessPane.test.js.snap

@@ -1,508 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`GuessPane cannot be tricked into resubmitting 1`] = `
-<div
-  className="pane pane--small"
->
-  <button
-    className="submit"
-    disabled={false}
-    onClick={[Function]}
-    type="button"
-  >
-    Submit Guess
-  </button>
-  <ClickMarkerMap
-    onMarkerMoved={[Function]}
-  />
-  <RoundTimer
-    onTimeout={[Function]}
-  />
-  <div
-    className="resize"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    ↗️
-  </div>
-  <div
-    className="resize resize--medium"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    ➡️
-  </div>
-</div>
-`;
-
-exports[`GuessPane cannot be tricked into resubmitting 2`] = `
-<div
-  className="pane pane--small"
->
-  <button
-    className="submit"
-    disabled={true}
-    onClick={[Function]}
-    type="button"
-  >
-    Submit Guess
-  </button>
-  <ClickMarkerMap
-    onMarkerMoved={[Function]}
-  />
-  <RoundTimer
-    onTimeout={[Function]}
-  />
-  <div
-    className="resize"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    ↗️
-  </div>
-  <div
-    className="resize resize--medium"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    ➡️
-  </div>
-</div>
-`;
-
-exports[`GuessPane large resize ignores other keydowns 1`] = `
-<div
-  className="pane pane--small"
->
-  <button
-    className="submit"
-    disabled={true}
-    onClick={[Function]}
-    type="button"
-  >
-    Submit Guess
-  </button>
-  <ClickMarkerMap
-    onMarkerMoved={[Function]}
-  />
-  <RoundTimer
-    onTimeout={[Function]}
-  />
-  <div
-    className="resize"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    ↗️
-  </div>
-  <div
-    className="resize resize--medium"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    ➡️
-  </div>
-</div>
-`;
-
-exports[`GuessPane medium resize ignores other keydowns 1`] = `
-<div
-  className="pane pane--small"
->
-  <button
-    className="submit"
-    disabled={true}
-    onClick={[Function]}
-    type="button"
-  >
-    Submit Guess
-  </button>
-  <ClickMarkerMap
-    onMarkerMoved={[Function]}
-  />
-  <RoundTimer
-    onTimeout={[Function]}
-  />
-  <div
-    className="resize"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    ↗️
-  </div>
-  <div
-    className="resize resize--medium"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    ➡️
-  </div>
-</div>
-`;
-
-exports[`GuessPane renders 1`] = `
-<div
-  className="pane pane--small"
->
-  <button
-    className="submit"
-    disabled={true}
-    onClick={[Function]}
-    type="button"
-  >
-    Submit Guess
-  </button>
-  <ClickMarkerMap
-    onMarkerMoved={[Function]}
-  />
-  <RoundTimer
-    onTimeout={[Function]}
-  />
-  <div
-    className="resize"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    ↗️
-  </div>
-  <div
-    className="resize resize--medium"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    ➡️
-  </div>
-</div>
-`;
-
-exports[`GuessPane resizes to large 1`] = `
-<div
-  className="pane pane--big"
->
-  <button
-    className="submit"
-    disabled={true}
-    onClick={[Function]}
-    type="button"
-  >
-    Submit Guess
-  </button>
-  <ClickMarkerMap
-    onMarkerMoved={[Function]}
-  />
-  <RoundTimer
-    onTimeout={[Function]}
-  />
-  <div
-    className="resize"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    ↙️
-  </div>
-  <div
-    className="resize resize--medium"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    ⬅️
-  </div>
-</div>
-`;
-
-exports[`GuessPane resizes to large on keydown Enter 1`] = `
-<div
-  className="pane pane--big"
->
-  <button
-    className="submit"
-    disabled={true}
-    onClick={[Function]}
-    type="button"
-  >
-    Submit Guess
-  </button>
-  <ClickMarkerMap
-    onMarkerMoved={[Function]}
-  />
-  <RoundTimer
-    onTimeout={[Function]}
-  />
-  <div
-    className="resize"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    ↙️
-  </div>
-  <div
-    className="resize resize--medium"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    ⬅️
-  </div>
-</div>
-`;
-
-exports[`GuessPane resizes to large then back 1`] = `
-<div
-  className="pane pane--small"
->
-  <button
-    className="submit"
-    disabled={true}
-    onClick={[Function]}
-    type="button"
-  >
-    Submit Guess
-  </button>
-  <ClickMarkerMap
-    onMarkerMoved={[Function]}
-  />
-  <RoundTimer
-    onTimeout={[Function]}
-  />
-  <div
-    className="resize"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    ↗️
-  </div>
-  <div
-    className="resize resize--medium"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    ➡️
-  </div>
-</div>
-`;
-
-exports[`GuessPane resizes to medium 1`] = `
-<div
-  className="pane pane--medium"
->
-  <button
-    className="submit"
-    disabled={true}
-    onClick={[Function]}
-    type="button"
-  >
-    Submit Guess
-  </button>
-  <ClickMarkerMap
-    onMarkerMoved={[Function]}
-  />
-  <RoundTimer
-    onTimeout={[Function]}
-  />
-  <div
-    className="resize"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    ↙️
-  </div>
-  <div
-    className="resize resize--medium"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    ⬅️
-  </div>
-</div>
-`;
-
-exports[`GuessPane resizes to medium on keydown Enter 1`] = `
-<div
-  className="pane pane--medium"
->
-  <button
-    className="submit"
-    disabled={true}
-    onClick={[Function]}
-    type="button"
-  >
-    Submit Guess
-  </button>
-  <ClickMarkerMap
-    onMarkerMoved={[Function]}
-  />
-  <RoundTimer
-    onTimeout={[Function]}
-  />
-  <div
-    className="resize"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    ↙️
-  </div>
-  <div
-    className="resize resize--medium"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    ⬅️
-  </div>
-</div>
-`;
-
-exports[`GuessPane resizes to medium then back 1`] = `
-<div
-  className="pane pane--small"
->
-  <button
-    className="submit"
-    disabled={true}
-    onClick={[Function]}
-    type="button"
-  >
-    Submit Guess
-  </button>
-  <ClickMarkerMap
-    onMarkerMoved={[Function]}
-  />
-  <RoundTimer
-    onTimeout={[Function]}
-  />
-  <div
-    className="resize"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    ↗️
-  </div>
-  <div
-    className="resize resize--medium"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    ➡️
-  </div>
-</div>
-`;
-
-exports[`GuessPane submits 1`] = `
-<div
-  className="pane pane--small"
->
-  <button
-    className="submit"
-    disabled={false}
-    onClick={[Function]}
-    type="button"
-  >
-    Submit Guess
-  </button>
-  <ClickMarkerMap
-    onMarkerMoved={[Function]}
-  />
-  <RoundTimer
-    onTimeout={[Function]}
-  />
-  <div
-    className="resize"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    ↗️
-  </div>
-  <div
-    className="resize resize--medium"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    ➡️
-  </div>
-</div>
-`;
-
-exports[`GuessPane submits 2`] = `
-<div
-  className="pane pane--small"
->
-  <button
-    className="submit"
-    disabled={true}
-    onClick={[Function]}
-    type="button"
-  >
-    Submit Guess
-  </button>
-  <ClickMarkerMap
-    onMarkerMoved={[Function]}
-  />
-  <RoundTimer
-    onTimeout={[Function]}
-  />
-  <div
-    className="resize"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    ↗️
-  </div>
-  <div
-    className="resize resize--medium"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    ➡️
-  </div>
-</div>
-`;

+ 0 - 99
client/src/tests/__snapshots__/HomePage.test.js.snap

@@ -1,99 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`HomePage Rejoin handles click 1`] = `
-<ForwardRef>
-  <div
-    className="rejoinSection"
-  >
-    <span
-      className="rejoinLabel"
-    >
-      Looks like you were in a game before that you didn't finish!
-    </span>
-    <DelayedButton
-      countDownFormatter={[Function]}
-      onEnd={[Function]}
-    >
-      <CountdownButton
-        formatter={[Function]}
-        onCancelled={[Function]}
-        onEnd={[Function]}
-        seconds={3}
-      >
-        <button
-          onClick={[Function]}
-          type="button"
-        >
-          Rejoining in 3s...
-        </button>
-      </CountdownButton>
-    </DelayedButton>
-  </div>
-</ForwardRef>
-`;
-
-exports[`HomePage Rejoin renders 1`] = `
-<div
-  className="rejoinSection"
->
-  <span
-    className="rejoinLabel"
-  >
-    Looks like you were in a game before that you didn't finish!
-  </span>
-  <DelayedButton
-    countDownFormatter={[Function]}
-    onEnd={[Function]}
-  >
-    Rejoin Game?
-  </DelayedButton>
-</div>
-`;
-
-exports[`HomePage renders 1`] = `
-<div
-  className="page"
->
-  <CSSTransition
-    classNames="fade"
-    in={false}
-    mountOnEnter={true}
-    nodeRef={
-      Object {
-        "current": null,
-      }
-    }
-    timeout={500}
-    unmountOnExit={true}
-  >
-    <ForwardRef />
-  </CSSTransition>
-  <GameCreationForm
-    afterCreate={[Function]}
-  />
-</div>
-`;
-
-exports[`HomePage renders with saved info 1`] = `
-<div
-  className="page"
->
-  <CSSTransition
-    classNames="fade"
-    in={true}
-    mountOnEnter={true}
-    nodeRef={
-      Object {
-        "current": null,
-      }
-    }
-    timeout={500}
-    unmountOnExit={true}
-  >
-    <ForwardRef />
-  </CSSTransition>
-  <GameCreationForm
-    afterCreate={[Function]}
-  />
-</div>
-`;

+ 0 - 313
client/src/tests/__snapshots__/JoinForm.test.js.snap

@@ -1,313 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`JoinForm blocks joining with empty player name 1`] = `
-<Fragment>
-  <div
-    className="join"
-  >
-    <span
-      className="label"
-    >
-      Enter your name to join:
-    </span>
-    <input
-      className="name"
-      onChange={[Function]}
-      onKeyDown={[Function]}
-      type="text"
-      value=""
-    />
-    <button
-      disabled={true}
-      onClick={[Function]}
-      type="button"
-    >
-      Join Game
-    </button>
-  </div>
-  <div
-    className="error"
-  />
-</Fragment>
-`;
-
-exports[`JoinForm does not join game if other keys pressed in input 1`] = `
-<Fragment>
-  <div
-    className="join"
-  >
-    <span
-      className="label"
-    >
-      Enter your name to join:
-    </span>
-    <input
-      className="name"
-      onChange={[Function]}
-      onKeyDown={[Function]}
-      type="text"
-      value="test-player"
-    />
-    <button
-      disabled={false}
-      onClick={[Function]}
-      type="button"
-    >
-      Join Game
-    </button>
-  </div>
-  <div
-    className="error"
-  />
-</Fragment>
-`;
-
-exports[`JoinForm does not join game if other keys pressed in input 2`] = `
-<Fragment>
-  <div
-    className="join"
-  >
-    <span
-      className="label"
-    >
-      Enter your name to join:
-    </span>
-    <input
-      className="name"
-      onChange={[Function]}
-      onKeyDown={[Function]}
-      type="text"
-      value="test-player"
-    />
-    <button
-      disabled={false}
-      onClick={[Function]}
-      type="button"
-    >
-      Join Game
-    </button>
-  </div>
-  <div
-    className="error"
-  />
-</Fragment>
-`;
-
-exports[`JoinForm handles failure 1`] = `
-<Fragment>
-  <div
-    className="join"
-  >
-    <span
-      className="label"
-    >
-      Enter your name to join:
-    </span>
-    <input
-      className="name"
-      onChange={[Function]}
-      onKeyDown={[Function]}
-      type="text"
-      value="test-player"
-    />
-    <button
-      disabled={false}
-      onClick={[Function]}
-      type="button"
-    >
-      Join Game
-    </button>
-  </div>
-  <div
-    className="error"
-  />
-</Fragment>
-`;
-
-exports[`JoinForm handles failure 2`] = `
-<Fragment>
-  <div
-    className="join"
-  >
-    <span
-      className="label"
-    >
-      Enter your name to join:
-    </span>
-    <input
-      className="name"
-      onChange={[Function]}
-      onKeyDown={[Function]}
-      type="text"
-      value="test-player"
-    />
-    <button
-      disabled={false}
-      onClick={[Function]}
-      type="button"
-    >
-      Join Game
-    </button>
-  </div>
-  <div
-    className="error"
-  >
-    Failed to join the game! Maybe try a different name?
-  </div>
-</Fragment>
-`;
-
-exports[`JoinForm joins game 1`] = `
-<Fragment>
-  <div
-    className="join"
-  >
-    <span
-      className="label"
-    >
-      Enter your name to join:
-    </span>
-    <input
-      className="name"
-      onChange={[Function]}
-      onKeyDown={[Function]}
-      type="text"
-      value="test-player"
-    />
-    <button
-      disabled={false}
-      onClick={[Function]}
-      type="button"
-    >
-      Join Game
-    </button>
-  </div>
-  <div
-    className="error"
-  />
-</Fragment>
-`;
-
-exports[`JoinForm joins game 2`] = `
-<Fragment>
-  <div
-    className="join"
-  >
-    <span
-      className="label"
-    >
-      Enter your name to join:
-    </span>
-    <input
-      className="name"
-      onChange={[Function]}
-      onKeyDown={[Function]}
-      type="text"
-      value="test-player"
-    />
-    <button
-      disabled={true}
-      onClick={[Function]}
-      type="button"
-    >
-      Join Game
-    </button>
-  </div>
-  <div
-    className="error"
-  />
-</Fragment>
-`;
-
-exports[`JoinForm joins game if enter pressed in input 1`] = `
-<Fragment>
-  <div
-    className="join"
-  >
-    <span
-      className="label"
-    >
-      Enter your name to join:
-    </span>
-    <input
-      className="name"
-      onChange={[Function]}
-      onKeyDown={[Function]}
-      type="text"
-      value="test-player"
-    />
-    <button
-      disabled={false}
-      onClick={[Function]}
-      type="button"
-    >
-      Join Game
-    </button>
-  </div>
-  <div
-    className="error"
-  />
-</Fragment>
-`;
-
-exports[`JoinForm joins game if enter pressed in input 2`] = `
-<Fragment>
-  <div
-    className="join"
-  >
-    <span
-      className="label"
-    >
-      Enter your name to join:
-    </span>
-    <input
-      className="name"
-      onChange={[Function]}
-      onKeyDown={[Function]}
-      type="text"
-      value="test-player"
-    />
-    <button
-      disabled={true}
-      onClick={[Function]}
-      type="button"
-    >
-      Join Game
-    </button>
-  </div>
-  <div
-    className="error"
-  />
-</Fragment>
-`;
-
-exports[`JoinForm renders 1`] = `
-<Fragment>
-  <div
-    className="join"
-  >
-    <span
-      className="label"
-    >
-      Enter your name to join:
-    </span>
-    <input
-      className="name"
-      onChange={[Function]}
-      onKeyDown={[Function]}
-      type="text"
-      value=""
-    />
-    <button
-      disabled={true}
-      onClick={[Function]}
-      type="button"
-    >
-      Join Game
-    </button>
-  </div>
-  <div
-    className="error"
-  />
-</Fragment>
-`;

+ 0 - 25
client/src/tests/__snapshots__/LinkedGame.test.js.snap

@@ -1,25 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`LinkedGame renders with linked game 1`] = `
-<div
-  className="linked"
->
-  <button
-    onClick={[Function]}
-    type="button"
-  >
-    Continue to Linked Game Lobby
-  </button>
-</div>
-`;
-
-exports[`LinkedGame renders with no linked game 1`] = `
-<div
-  className="linked"
->
-  <GameCreationForm
-    afterCreate={[Function]}
-    lastSettings={Object {}}
-  />
-</div>
-`;

+ 0 - 12
client/src/tests/__snapshots__/Loading.test.js.snap

@@ -1,12 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Loading icon renders 1`] = `
-<div
-  className="loading"
->
-  <div />
-  <div />
-  <div />
-  <div />
-</div>
-`;

+ 0 - 372
client/src/tests/__snapshots__/Lobby.test.js.snap

@@ -1,372 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Lobby GameInfo renders 1`] = `
-<Fragment>
-  <span
-    className="label"
-  >
-    Game will run for 
-    5
-     round
-    s
-  </span>
-  <span
-    className="label"
-  >
-    Each round will have a time limit of 
-    5m
-  </span>
-</Fragment>
-`;
-
-exports[`Lobby GameInfo renders for COUNTRY_RACE 1`] = `
-<Fragment>
-  <span
-    className="label"
-  >
-    Game will run for 
-    5
-     round
-    s
-  </span>
-  <span
-    className="label"
-  >
-    Each round will have a time limit of 
-    5m
-  </span>
-  <span
-    className="label"
-  >
-    Your score will be based on how quickly you select the right country - you will get 0 points for the wrong country!
-  </span>
-</Fragment>
-`;
-
-exports[`Lobby GameInfo renders for FROZEN 1`] = `
-<Fragment>
-  <span
-    className="label"
-  >
-    Game will run for 
-    5
-     round
-    s
-  </span>
-  <span
-    className="label"
-  >
-    Each round will have a time limit of 
-    5m
-  </span>
-  <span
-    className="label"
-  >
-    You will not be able to adjust your view
-  </span>
-</Fragment>
-`;
-
-exports[`Lobby GameInfo renders for NORMAL 1`] = `
-<Fragment>
-  <span
-    className="label"
-  >
-    Game will run for 
-    5
-     round
-    s
-  </span>
-  <span
-    className="label"
-  >
-    Each round will have a time limit of 
-    5m
-  </span>
-</Fragment>
-`;
-
-exports[`Lobby GameInfo renders for RACE 1`] = `
-<Fragment>
-  <span
-    className="label"
-  >
-    Game will run for 
-    5
-     round
-    s
-  </span>
-  <span
-    className="label"
-  >
-    Each round will have a time limit of 
-    5m
-  </span>
-  <span
-    className="label"
-  >
-    If someone submits before you your remaining time will be cut down to just 10 seconds!
-  </span>
-</Fragment>
-`;
-
-exports[`Lobby GameInfo renders for TIME_BANK 1`] = `
-<Fragment>
-  <span
-    className="label"
-  >
-    Game will run for 
-    5
-     round
-    s
-  </span>
-  <span
-    className="label"
-  >
-    Your time will be banked, with 
-    25m
-     available across all rounds
-  </span>
-</Fragment>
-`;
-
-exports[`Lobby GameInfo renders for single round 1`] = `
-<Fragment>
-  <span
-    className="label"
-  >
-    Game will run for 
-    1
-     round
-  </span>
-  <span
-    className="label"
-  >
-    Each round will have a time limit of 
-    5m
-  </span>
-</Fragment>
-`;
-
-exports[`Lobby GameInfo renders for single round COUNTRY_RACE 1`] = `
-<Fragment>
-  <span
-    className="label"
-  >
-    Game will run for 
-    1
-     round
-  </span>
-  <span
-    className="label"
-  >
-    Each round will have a time limit of 
-    5m
-  </span>
-  <span
-    className="label"
-  >
-    Your score will be based on how quickly you select the right country - you will get 0 points for the wrong country!
-  </span>
-</Fragment>
-`;
-
-exports[`Lobby GameInfo renders for single round FROZEN 1`] = `
-<Fragment>
-  <span
-    className="label"
-  >
-    Game will run for 
-    1
-     round
-  </span>
-  <span
-    className="label"
-  >
-    Each round will have a time limit of 
-    5m
-  </span>
-  <span
-    className="label"
-  >
-    You will not be able to adjust your view
-  </span>
-</Fragment>
-`;
-
-exports[`Lobby GameInfo renders while loading 1`] = `<Loading />`;
-
-exports[`Lobby GameInfo renders with a round point cap 1`] = `
-<Fragment>
-  <span
-    className="label"
-  >
-    Game will run for 
-    5
-     round
-    s
-  </span>
-  <span
-    className="label"
-  >
-    Each round will have a time limit of 
-    5m
-  </span>
-  <span
-    className="label"
-  >
-    Only 
-    10000
-     total points will be up for grabs each round
-  </span>
-</Fragment>
-`;
-
-exports[`Lobby GameInfo renders with country lock 1`] = `
-<Fragment>
-  <span
-    className="label"
-  >
-    Game will run for 
-    5
-     round
-    s
-  </span>
-  <span
-    className="label"
-  >
-    Each round will have a time limit of 
-    5m
-  </span>
-  <span
-    className="label"
-  >
-    This game will only use locations within:
-     
-    test-country
-  </span>
-</Fragment>
-`;
-
-exports[`Lobby PlayerList renders 1`] = `
-<div
-  className="players"
->
-  <span
-    className="playersTitle"
-  >
-    Players
-  </span>
-  <ul>
-    <li
-      key="foo"
-    >
-      foo
-    </li>
-    <li
-      key="bar"
-    >
-      bar
-    </li>
-  </ul>
-</div>
-`;
-
-exports[`Lobby properly handles joining and starting 1`] = `
-<div
-  className="page"
->
-  <div
-    className="info"
-  >
-    <GameInfo />
-    <div
-      className="form"
-    >
-      <StartGame
-        onStart={[MockFunction]}
-      />
-    </div>
-    <span
-      className="label"
-    >
-      <ClickToCopy
-        text="http://localhost/?join=test-game-id"
-      >
-        Click here to copy an invite link!
-      </ClickToCopy>
-    </span>
-  </div>
-  <PlayerList
-    playerNames={Array []}
-  />
-</div>
-`;
-
-exports[`Lobby renders 1`] = `
-<div
-  className="page"
->
-  <div
-    className="info"
-  >
-    <GameInfo />
-    <div
-      className="form"
-    >
-      <JoinForm
-        onJoined={[Function]}
-      />
-    </div>
-    <span
-      className="label"
-    >
-      <ClickToCopy
-        text="http://localhost/?join=test-game-id"
-      >
-        Click here to copy an invite link!
-      </ClickToCopy>
-    </span>
-  </div>
-  <PlayerList
-    playerNames={
-      Array [
-        "bar",
-      ]
-    }
-  />
-</div>
-`;
-
-exports[`Lobby renders while loading 1`] = `<Loading />`;
-
-exports[`Lobby renders with no players 1`] = `
-<div
-  className="page"
->
-  <div
-    className="info"
-  >
-    <GameInfo />
-    <div
-      className="form"
-    >
-      <JoinForm
-        onJoined={[Function]}
-      />
-    </div>
-    <span
-      className="label"
-    >
-      <ClickToCopy
-        text="http://localhost/?join=test-game-id"
-      >
-        Click here to copy an invite link!
-      </ClickToCopy>
-    </span>
-  </div>
-  <PlayerList
-    playerNames={Array []}
-  />
-</div>
-`;

+ 0 - 69
client/src/tests/__snapshots__/PositionedStreetView.test.js.snap

@@ -1,69 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`PositionedStreetView does not reset on other keys on button 1`] = `
-<Fragment>
-  <div
-    className="fullsize"
-  />
-  <div
-    className="resetButton"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    Reset
-  </div>
-</Fragment>
-`;
-
-exports[`PositionedStreetView renders 1`] = `
-<Fragment>
-  <div
-    className="fullsize"
-  />
-  <div
-    className="resetButton"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    Reset
-  </div>
-</Fragment>
-`;
-
-exports[`PositionedStreetView resets 1`] = `
-<Fragment>
-  <div
-    className="fullsize"
-  />
-  <div
-    className="resetButton"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    Reset
-  </div>
-</Fragment>
-`;
-
-exports[`PositionedStreetView resets on enter on button 1`] = `
-<Fragment>
-  <div
-    className="fullsize"
-  />
-  <div
-    className="resetButton"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    Reset
-  </div>
-</Fragment>
-`;

+ 0 - 27
client/src/tests/__snapshots__/RaceMode.test.js.snap

@@ -1,27 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`PositionedStreetView renders 1`] = `<Fragment />`;
-
-exports[`PositionedStreetView renders when cut off 1`] = `
-<div
-  className="cutoff "
->
-  You were cut off by 
-  cutoff-player
-  ! Only 
-  10s
-   left!
-</div>
-`;
-
-exports[`PositionedStreetView renders when faded 1`] = `
-<div
-  className="cutoff hidden"
->
-  You were cut off by 
-  cutoff-player
-  ! Only 
-  10s
-   left!
-</div>
-`;

+ 0 - 79
client/src/tests/__snapshots__/RoundSummary.test.js.snap

@@ -1,79 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`RoundSummary NextRoundButton handles click if there is a next round 1`] = `
-<NextRoundButton>
-  <DelayedButton
-    autoFocus={true}
-    buttonClass="next"
-    countDownFormatter={[Function]}
-    onEnd={[MockFunction]}
-  >
-    <CountdownButton
-      autoFocus={true}
-      buttonClass="next"
-      formatter={[Function]}
-      onCancelled={[Function]}
-      onEnd={[MockFunction]}
-      seconds={3}
-    >
-      <button
-        autoFocus={true}
-        className="next"
-        onClick={[Function]}
-        type="button"
-      >
-        Click to cancel, 3s...
-      </button>
-    </CountdownButton>
-  </DelayedButton>
-</NextRoundButton>
-`;
-
-exports[`RoundSummary NextRoundButton renders when there is a next round 1`] = `
-<DelayedButton
-  autoFocus={true}
-  buttonClass="next"
-  countDownFormatter={[Function]}
-  onEnd={[MockFunction]}
->
-  Next Round
-</DelayedButton>
-`;
-
-exports[`RoundSummary NextRoundButton renders when there is not a next round 1`] = `
-<button
-  autoFocus={true}
-  className="next"
-  onClick={[Function]}
-  type="button"
->
-  View Summary
-</button>
-`;
-
-exports[`RoundSummary renders 1`] = `
-<div>
-  <div
-    className="map"
-  />
-  <div
-    className="panel"
-  >
-    <span
-      className="score"
-    >
-      Score for Round 
-      round
-      : 
-      5000
-    </span>
-    <span
-      className="score"
-    >
-      Running Total: 
-      10000
-    </span>
-    <NextRoundButton />
-  </div>
-</div>
-`;

+ 0 - 18
client/src/tests/__snapshots__/RoundTimer.test.js.snap

@@ -1,18 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`RoundTimer renders with no time left 1`] = `
-<span
-  className="timer timer--timeout"
->
-  Time's up!
-</span>
-`;
-
-exports[`RoundTimer renders with time left 1`] = `
-<span
-  className="timer"
->
-  Time: 
-  1m 40s
-</span>
-`;

+ 0 - 562
client/src/tests/__snapshots__/Scoreboard.test.js.snap

@@ -1,562 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`ScoreBoard PlayerScoreTile renders overly long name 1`] = `
-<div
-  className="tile"
->
-  <div
-    className="header"
-  >
-    <span
-      className="name longname"
-    >
-      LongLongLongLongLongLongLongLongLongLong
-    </span>
-    <span
-      className="total"
-    >
-       
-      0
-    </span>
-  </div>
-  <div
-    className="scores"
-  />
-</div>
-`;
-
-exports[`ScoreBoard PlayerScoreTile renders slightly long name 1`] = `
-<div
-  className="tile"
->
-  <div
-    className="header"
-  >
-    <span
-      className="name medname"
-    >
-      LongLongLongLongLong
-    </span>
-    <span
-      className="total"
-    >
-       
-      0
-    </span>
-  </div>
-  <div
-    className="scores"
-  />
-</div>
-`;
-
-exports[`ScoreBoard PlayerScoreTile renders with guesses 1`] = `
-<div
-  className="tile"
->
-  <div
-    className="header"
-  >
-    <span
-      className="name "
-    >
-      Name
-    </span>
-    <span
-      className="total"
-    >
-      🏆
-       
-      220
-    </span>
-  </div>
-  <div
-    className="scores"
-  >
-    <div
-      className="round"
-      key="1"
-    >
-      <span
-        className="score"
-      >
-        Round 
-        1
-        : 
-        50
-      </span>
-      <span
-        className="flag"
-        title="test-country"
-      >
-        flag
-      </span>
-    </div>
-    <div
-      className="round"
-      key="2"
-    >
-      <span
-        className="score"
-      >
-        Round 
-        2
-        : 
-        150
-      </span>
-      <span
-        className="flag"
-        title="test-country"
-      >
-        flag
-      </span>
-    </div>
-    <div
-      className="round"
-      key="3"
-    >
-      <span
-        className="score"
-      >
-        Round 
-        3
-        : 
-        20
-      </span>
-      <span
-        className="flag"
-        title="test-country"
-      >
-        flag
-      </span>
-    </div>
-  </div>
-</div>
-`;
-
-exports[`ScoreBoard PlayerScoreTile renders with guesses 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "test-country",
-    ],
-    Array [
-      "test-country",
-    ],
-    Array [
-      "test-country",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": "flag",
-    },
-    Object {
-      "type": "return",
-      "value": "flag",
-    },
-    Object {
-      "type": "return",
-      "value": "flag",
-    },
-  ],
-}
-`;
-
-exports[`ScoreBoard PlayerScoreTile renders with missing guess 1`] = `
-<div
-  className="tile"
->
-  <div
-    className="header"
-  >
-    <span
-      className="name "
-    >
-      Name
-    </span>
-    <span
-      className="total"
-    >
-      🏆
-       
-      220
-    </span>
-  </div>
-  <div
-    className="scores"
-  >
-    <div
-      className="round"
-      key="1"
-    >
-      <span
-        className="score"
-      >
-        Round 
-        1
-        : 
-        50
-      </span>
-      <span
-        className="flag"
-        title="test-country"
-      >
-        flag
-      </span>
-    </div>
-    <div
-      className="round"
-      key="3"
-    >
-      <span
-        className="score"
-      >
-        Round 
-        3
-        : 
-        20
-      </span>
-      <span
-        className="flag"
-        title="test-country"
-      >
-        flag
-      </span>
-    </div>
-  </div>
-</div>
-`;
-
-exports[`ScoreBoard PlayerScoreTile renders with missing guess 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "test-country",
-    ],
-    Array [
-      "test-country",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": "flag",
-    },
-    Object {
-      "type": "return",
-      "value": "flag",
-    },
-  ],
-}
-`;
-
-exports[`ScoreBoard PlayerScoreTile renders with no guesses 1`] = `
-<div
-  className="tile"
->
-  <div
-    className="header"
-  >
-    <span
-      className="name "
-    >
-      Name
-    </span>
-    <span
-      className="total"
-    >
-       
-      0
-    </span>
-  </div>
-  <div
-    className="scores"
-  />
-</div>
-`;
-
-exports[`ScoreBoard PlayerScoreTile renders with timeout 1`] = `
-<div
-  className="tile"
->
-  <div
-    className="header"
-  >
-    <span
-      className="name "
-    >
-      Name
-    </span>
-    <span
-      className="total"
-    >
-      🏆
-       
-      220
-    </span>
-  </div>
-  <div
-    className="scores"
-  >
-    <div
-      className="round"
-      key="1"
-    >
-      <span
-        className="score"
-      >
-        Round 
-        1
-        : 
-        50
-      </span>
-      <span
-        className="flag"
-        title="test-country"
-      >
-        flag
-      </span>
-    </div>
-    <div
-      className="round"
-      key="2"
-    >
-      <span
-        className="score"
-      >
-        Round 
-        2
-        : 
-        0
-      </span>
-      <span
-        className="flag"
-        title={null}
-      >
-        flag
-      </span>
-    </div>
-    <div
-      className="round"
-      key="3"
-    >
-      <span
-        className="score"
-      >
-        Round 
-        3
-        : 
-        20
-      </span>
-      <span
-        className="flag"
-        title="test-country"
-      >
-        flag
-      </span>
-    </div>
-  </div>
-</div>
-`;
-
-exports[`ScoreBoard PlayerScoreTile renders with timeout 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "test-country",
-    ],
-    Array [
-      null,
-    ],
-    Array [
-      "test-country",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": "flag",
-    },
-    Object {
-      "type": "return",
-      "value": "flag",
-    },
-    Object {
-      "type": "return",
-      "value": "flag",
-    },
-  ],
-}
-`;
-
-exports[`ScoreBoard PlayerScoreTile sorts guesses by round number 1`] = `
-<div
-  className="tile"
->
-  <div
-    className="header"
-  >
-    <span
-      className="name "
-    >
-      Name
-    </span>
-    <span
-      className="total"
-    >
-      🏆
-       
-      220
-    </span>
-  </div>
-  <div
-    className="scores"
-  >
-    <div
-      className="round"
-      key="1"
-    >
-      <span
-        className="score"
-      >
-        Round 
-        1
-        : 
-        50
-      </span>
-      <span
-        className="flag"
-        title="test-country"
-      >
-        flag
-      </span>
-    </div>
-    <div
-      className="round"
-      key="2"
-    >
-      <span
-        className="score"
-      >
-        Round 
-        2
-        : 
-        150
-      </span>
-      <span
-        className="flag"
-        title="test-country"
-      >
-        flag
-      </span>
-    </div>
-    <div
-      className="round"
-      key="3"
-    >
-      <span
-        className="score"
-      >
-        Round 
-        3
-        : 
-        20
-      </span>
-      <span
-        className="flag"
-        title="test-country"
-      >
-        flag
-      </span>
-    </div>
-  </div>
-</div>
-`;
-
-exports[`ScoreBoard PlayerScoreTile sorts guesses by round number 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "test-country",
-    ],
-    Array [
-      "test-country",
-    ],
-    Array [
-      "test-country",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": "flag",
-    },
-    Object {
-      "type": "return",
-      "value": "flag",
-    },
-    Object {
-      "type": "return",
-      "value": "flag",
-    },
-  ],
-}
-`;
-
-exports[`ScoreBoard does not add tiles for unfinished players 1`] = `
-<div
-  className="scoreboard"
->
-  <PlayerScoreTile
-    key="Name2"
-    name="Name2"
-    totalScore={10000}
-    winner={true}
-  />
-  <PlayerScoreTile
-    key="Name1"
-    name="Name1"
-    totalScore={5000}
-    winner={false}
-  />
-</div>
-`;
-
-exports[`ScoreBoard renders with no players 1`] = `
-<div
-  className="scoreboard"
-/>
-`;
-
-exports[`ScoreBoard renders with player tiles sorted by score 1`] = `
-<div
-  className="scoreboard"
->
-  <PlayerScoreTile
-    key="Name2"
-    name="Name2"
-    totalScore={10000}
-    winner={true}
-  />
-  <PlayerScoreTile
-    key="Name1"
-    name="Name1"
-    totalScore={5000}
-    winner={false}
-  />
-  <PlayerScoreTile
-    key="Name4"
-    name="Name4"
-    totalScore={5000}
-    winner={false}
-  />
-  <PlayerScoreTile
-    key="Name3"
-    name="Name3"
-    totalScore={1000}
-    winner={false}
-  />
-</div>
-`;

+ 0 - 51
client/src/tests/__snapshots__/StartGame.test.js.snap

@@ -1,51 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`StartGame renders without crashing 1`] = `
-<Fragment>
-  <span
-    className="label"
-  >
-    Playing as 
-    test-player
-  </span>
-  <DelayedButton
-    autoFocus={true}
-    countDownFormatter={[Function]}
-    onEnd={[MockFunction]}
-  >
-    Start Game
-  </DelayedButton>
-</Fragment>
-`;
-
-exports[`StartGame responds to clicking the join button 1`] = `
-<StartGame>
-  <span
-    className="label"
-  >
-    Playing as 
-    test-player
-  </span>
-  <DelayedButton
-    autoFocus={true}
-    countDownFormatter={[Function]}
-    onEnd={[MockFunction]}
-  >
-    <CountdownButton
-      autoFocus={true}
-      formatter={[Function]}
-      onCancelled={[Function]}
-      onEnd={[MockFunction]}
-      seconds={3}
-    >
-      <button
-        autoFocus={true}
-        onClick={[Function]}
-        type="button"
-      >
-        Click to cancel, 3s...
-      </button>
-    </CountdownButton>
-  </DelayedButton>
-</StartGame>
-`;

+ 0 - 238
client/src/tests/__snapshots__/SummaryMap.test.js.snap

@@ -1,238 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`SummaryMap RoundSelect can be selected 1`] = `
-<div
-  className="tabs"
->
-  <div
-    className="tab "
-    key="1"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-    title="test-country"
-  >
-    1
-     - 
-  </div>
-  <div
-    className="tab tab--active"
-    key="2"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-    title="test-country"
-  >
-    2
-     - 
-  </div>
-  <div
-    className="tab "
-    key="3"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-    title="test-country"
-  >
-    3
-     - 
-  </div>
-  <div
-    className="tab"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    X
-  </div>
-</div>
-`;
-
-exports[`SummaryMap RoundSelect renders 1`] = `
-<div
-  className="tabs"
->
-  <div
-    className="tab "
-    key="1"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-    title="test-country"
-  >
-    1
-     - 
-  </div>
-  <div
-    className="tab "
-    key="2"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-    title="test-country"
-  >
-    2
-     - 
-  </div>
-  <div
-    className="tab "
-    key="3"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-    title="test-country"
-  >
-    3
-     - 
-  </div>
-  <div
-    className="tab"
-    onClick={[Function]}
-    onKeyDown={[Function]}
-    role="button"
-    tabIndex="0"
-  >
-    X
-  </div>
-</div>
-`;
-
-exports[`SummaryMap handles having the round changed 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      Object {
-        "lat": 3,
-        "lng": 4,
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`SummaryMap handles having the round changed 2`] = `
-<div
-  className="container"
->
-  <div
-    className="map"
-  />
-  <RoundSelect
-    coords={
-      Object {
-        "1": Object {
-          "lat": 1,
-          "lng": 2,
-        },
-        "2": Object {
-          "lat": 3,
-          "lng": 4,
-        },
-        "3": Object {
-          "lat": 5,
-          "lng": 6,
-        },
-      }
-    }
-    onSelect={[Function]}
-    rounds={3}
-    selected={2}
-  />
-</div>
-`;
-
-exports[`SummaryMap handles invalid round change 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      Object {
-        "lat": 0,
-        "lng": 0,
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`SummaryMap handles invalid round change 2`] = `
-<div
-  className="container"
->
-  <div
-    className="map"
-  />
-  <RoundSelect
-    coords={
-      Object {
-        "1": Object {
-          "lat": 1,
-          "lng": 2,
-        },
-        "2": Object {
-          "lat": 3,
-          "lng": 4,
-        },
-        "3": Object {
-          "lat": 5,
-          "lng": 6,
-        },
-      }
-    }
-    onSelect={[Function]}
-    rounds={3}
-    selected={5}
-  />
-</div>
-`;
-
-exports[`SummaryMap renders 1`] = `
-<div
-  className="container"
->
-  <div
-    className="map"
-  />
-  <RoundSelect
-    coords={
-      Object {
-        "1": Object {},
-        "2": Object {},
-        "3": Object {},
-      }
-    }
-    onSelect={[Function]}
-    rounds={3}
-    selected="0"
-  />
-</div>
-`;
-
-exports[`SummaryMap renders without selector if single round 1`] = `
-<div
-  className="container"
->
-  <div
-    className="map"
-  />
-  <Component />
-</div>
-`;

+ 0 - 878
client/src/tests/__snapshots__/apiMethods.test.js.snap

@@ -1,878 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`apiMethods checkScore checks score 1`] = `
-Object {
-  "score": 1000,
-}
-`;
-
-exports[`apiMethods checkScore checks score 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/score",
-      Object {
-        "body": "{\\"point1\\":\\"point1\\",\\"point2\\":\\"point2\\"}",
-        "headers": Object {
-          "Content-Type": "application/json",
-        },
-        "method": "POST",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods checkScore passes thrown error 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/score",
-      Object {
-        "body": "{\\"point1\\":\\"point1\\",\\"point2\\":\\"point2\\"}",
-        "headers": Object {
-          "Content-Type": "application/json",
-        },
-        "method": "POST",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "throw",
-      "value": [Error: error],
-    },
-  ],
-}
-`;
-
-exports[`apiMethods checkScore throws on server error 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/score",
-      Object {
-        "body": "{\\"point1\\":\\"point1\\",\\"point2\\":\\"point2\\"}",
-        "headers": Object {
-          "Content-Type": "application/json",
-        },
-        "method": "POST",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods createGame creates game 1`] = `"test-game-id"`;
-
-exports[`apiMethods createGame creates game 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game",
-      Object {
-        "body": "{\\"timer\\":\\"timer\\",\\"rounds\\":\\"rounds\\",\\"countryLock\\":\\"countryLock\\",\\"generationMethod\\":\\"generationMethod\\",\\"gameMode\\":\\"gameMode\\",\\"clockMode\\":\\"clockMode\\",\\"scoreMethod\\":\\"scoreMethod\\",\\"roundPointCap\\":\\"roundPointCap\\"}",
-        "headers": Object {
-          "Content-Type": "application/json",
-        },
-        "method": "PUT",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods createGame passes thrown error 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game",
-      Object {
-        "body": "{\\"timer\\":\\"timer\\",\\"rounds\\":\\"rounds\\",\\"countryLock\\":\\"countryLock\\",\\"generationMethod\\":\\"generationMethod\\",\\"gameMode\\":\\"gameMode\\",\\"clockMode\\":\\"clockMode\\",\\"scoreMethod\\":\\"scoreMethod\\",\\"roundPointCap\\":\\"roundPointCap\\"}",
-        "headers": Object {
-          "Content-Type": "application/json",
-        },
-        "method": "PUT",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "throw",
-      "value": [Error: error],
-    },
-  ],
-}
-`;
-
-exports[`apiMethods createGame throws on server error 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game",
-      Object {
-        "body": "{\\"timer\\":\\"timer\\",\\"rounds\\":\\"rounds\\",\\"countryLock\\":\\"countryLock\\",\\"generationMethod\\":\\"generationMethod\\",\\"gameMode\\":\\"gameMode\\",\\"clockMode\\":\\"clockMode\\",\\"scoreMethod\\":\\"scoreMethod\\",\\"roundPointCap\\":\\"roundPointCap\\"}",
-        "headers": Object {
-          "Content-Type": "application/json",
-        },
-        "method": "PUT",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods getCurrentRound gets current round 1`] = `
-Object {
-  "round": "test-round",
-}
-`;
-
-exports[`apiMethods getCurrentRound gets current round 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/players/test-player-id/current",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods getCurrentRound passes thrown error 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/players/test-player-id/current",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "throw",
-      "value": [Error: error],
-    },
-  ],
-}
-`;
-
-exports[`apiMethods getCurrentRound throws on server error 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/players/test-player-id/current",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods getFirstSubmitter gets first submmiter for a round 1`] = `"test-player"`;
-
-exports[`apiMethods getFirstSubmitter gets first submmiter for a round 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/round/round/first",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods getFirstSubmitter passes thrown error 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/round/round/first",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "throw",
-      "value": [Error: error],
-    },
-  ],
-}
-`;
-
-exports[`apiMethods getFirstSubmitter returns null on server error 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/round/round/first",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods getGameConfig gets game config 1`] = `
-Object {
-  "config": "test-config",
-}
-`;
-
-exports[`apiMethods getGameConfig gets game config 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/config",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods getGameConfig passes thrown error 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/config",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "throw",
-      "value": [Error: error],
-    },
-  ],
-}
-`;
-
-exports[`apiMethods getGameConfig throws on server error 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/config",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods getGameCoords gets game coords 1`] = `
-Object {
-  "coords": Array [
-    "test-coord",
-  ],
-}
-`;
-
-exports[`apiMethods getGameCoords gets game coords 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/coords",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods getGameCoords passes thrown error 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/coords",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "throw",
-      "value": [Error: error],
-    },
-  ],
-}
-`;
-
-exports[`apiMethods getGameCoords throws on server error 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/coords",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods getGenerators gets generators 1`] = `
-Object {
-  "generators": Array [],
-}
-`;
-
-exports[`apiMethods getGenerators gets generators 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/generators",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods getGenerators passes thrown error 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/generators",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "throw",
-      "value": [Error: error],
-    },
-  ],
-}
-`;
-
-exports[`apiMethods getGenerators throws on server error 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/generators",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods getLinkedGame gets linked game 1`] = `
-Array [
-  "test-linked-game-id",
-]
-`;
-
-exports[`apiMethods getLinkedGame gets linked game 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/linked",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods getLinkedGame passes thrown error 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/linked",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "throw",
-      "value": [Error: error],
-    },
-  ],
-}
-`;
-
-exports[`apiMethods getLinkedGame throws on server error 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/linked",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods getPlayers gets game players 1`] = `
-Array [
-  "test-player",
-]
-`;
-
-exports[`apiMethods getPlayers gets game players 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/players",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods getPlayers passes thrown error 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/players",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "throw",
-      "value": [Error: error],
-    },
-  ],
-}
-`;
-
-exports[`apiMethods getPlayers throws on server error 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/players",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods getStatus gets status 1`] = `
-Object {
-  "status": "healthy",
-  "version": "test",
-}
-`;
-
-exports[`apiMethods getStatus gets status 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/health",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods getStatus handles server error 1`] = `
-Object {
-  "status": "failed",
-  "version": null,
-}
-`;
-
-exports[`apiMethods getStatus handles server error 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/health",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods getStatus handles thrown error 1`] = `
-Object {
-  "status": "error",
-  "version": null,
-}
-`;
-
-exports[`apiMethods getStatus handles thrown error 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/health",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "throw",
-      "value": [Error: error],
-    },
-  ],
-}
-`;
-
-exports[`apiMethods joinGame joins game 1`] = `
-Object {
-  "playerId": "test-player-id",
-}
-`;
-
-exports[`apiMethods joinGame joins game 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/join",
-      Object {
-        "body": "{\\"playerName\\":\\"test-player-name\\"}",
-        "headers": Object {
-          "Content-Type": "application/json",
-        },
-        "method": "POST",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods joinGame passes thrown error 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/join",
-      Object {
-        "body": "{\\"playerName\\":\\"test-player-name\\"}",
-        "headers": Object {
-          "Content-Type": "application/json",
-        },
-        "method": "POST",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "throw",
-      "value": [Error: error],
-    },
-  ],
-}
-`;
-
-exports[`apiMethods joinGame throws on server error 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/join",
-      Object {
-        "body": "{\\"playerName\\":\\"test-player-name\\"}",
-        "headers": Object {
-          "Content-Type": "application/json",
-        },
-        "method": "POST",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods linkGame links game to another 1`] = `undefined`;
-
-exports[`apiMethods linkGame links game to another 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/linked",
-      Object {
-        "body": "{\\"linkedGame\\":\\"test-linked-game-id\\"}",
-        "headers": Object {
-          "Content-Type": "application/json",
-        },
-        "method": "PUT",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods linkGame passes thrown error 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/linked",
-      Object {
-        "body": "{\\"linkedGame\\":\\"test-linked-game-id\\"}",
-        "headers": Object {
-          "Content-Type": "application/json",
-        },
-        "method": "PUT",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "throw",
-      "value": [Error: error],
-    },
-  ],
-}
-`;
-
-exports[`apiMethods linkGame throws on server error 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/linked",
-      Object {
-        "body": "{\\"linkedGame\\":\\"test-linked-game-id\\"}",
-        "headers": Object {
-          "Content-Type": "application/json",
-        },
-        "method": "PUT",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods sendGuess passes thrown error 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/round/test-round/guess/test-player-id",
-      Object {
-        "body": "{\\"timeRemaining\\":\\"test-time\\",\\"lat\\":\\"lat\\",\\"lng\\":\\"lng\\"}",
-        "headers": Object {
-          "Content-Type": "application/json",
-        },
-        "method": "POST",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "throw",
-      "value": [Error: error],
-    },
-  ],
-}
-`;
-
-exports[`apiMethods sendGuess sends a guess 1`] = `
-Object {
-  "score": 1000,
-  "totalScore": 5000,
-}
-`;
-
-exports[`apiMethods sendGuess sends a guess 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/round/test-round/guess/test-player-id",
-      Object {
-        "body": "{\\"timeRemaining\\":\\"test-time\\",\\"lat\\":\\"lat\\",\\"lng\\":\\"lng\\"}",
-        "headers": Object {
-          "Content-Type": "application/json",
-        },
-        "method": "POST",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods sendGuess throws on server error 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/round/test-round/guess/test-player-id",
-      Object {
-        "body": "{\\"timeRemaining\\":\\"test-time\\",\\"lat\\":\\"lat\\",\\"lng\\":\\"lng\\"}",
-        "headers": Object {
-          "Content-Type": "application/json",
-        },
-        "method": "POST",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods sendtimeout passes thrown error 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/round/test-round/timeout/test-player-id",
-      Object {
-        "method": "POST",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "throw",
-      "value": [Error: error],
-    },
-  ],
-}
-`;
-
-exports[`apiMethods sendtimeout sends a timeout for the round 1`] = `
-Object {
-  "score": 0,
-  "totalScore": 2000,
-}
-`;
-
-exports[`apiMethods sendtimeout sends a timeout for the round 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/round/test-round/timeout/test-player-id",
-      Object {
-        "method": "POST",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`apiMethods sendtimeout throws on server error 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "https://hiram.services/terrassumptions/api/game/test-game-id/round/test-round/timeout/test-player-id",
-      Object {
-        "method": "POST",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;

+ 0 - 13
client/src/tests/__snapshots__/flagLookup.test.js.snap

@@ -1,13 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`flagLookup finds flags 1`] = `"🇺🇸"`;
-
-exports[`flagLookup finds flags 2`] = `"🇬🇧"`;
-
-exports[`flagLookup finds flags 3`] = `"🇨🇳"`;
-
-exports[`flagLookup finds flags 4`] = `"🇧🇷"`;
-
-exports[`flagLookup finds flags 5`] = `"🇕🇕"`;
-
-exports[`flagLookup finds flags 6`] = `"🌎"`;

+ 0 - 256
client/src/tests/__snapshots__/gameStore.test.js.snap

@@ -1,256 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`gameStore dispatch joinGame joins game then updates current round 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "test-game-id",
-      "test-player-name",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Object {
-        "playerId": "test-player-id",
-      },
-    },
-  ],
-}
-`;
-
-exports[`gameStore dispatch joinGame joins game then updates current round 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "test-game-id",
-      "test-player-name",
-      "test-player-id",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`gameStore dispatch joinGame joins game then updates current round 3`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "test-game-id",
-      "test-player-id",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Object {
-        "coord": "coord",
-        "currentRound": "round",
-        "timer": "timer",
-      },
-    },
-  ],
-}
-`;
-
-exports[`gameStore dispatch rejoinGame rejoins game then updates current round 1`] = `[MockFunction]`;
-
-exports[`gameStore dispatch rejoinGame rejoins game then updates current round 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "test-game-id",
-      "test-player-id",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Object {
-        "coord": "coord",
-        "currentRound": "round",
-        "timer": "timer",
-      },
-    },
-  ],
-}
-`;
-
-exports[`gameStore dispatch rejoinGame rejoins game then updates current round even with missing information 1`] = `[MockFunction]`;
-
-exports[`gameStore dispatch rejoinGame rejoins game then updates current round even with missing information 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "test-game-id",
-      "test-player-id",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Object {
-        "coord": "coord",
-        "currentRound": "round",
-        "timer": "timer",
-      },
-    },
-  ],
-}
-`;
-
-exports[`gameStore dispatch submitGuess submits a timeout and then updates the current round 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "test-game-id",
-      null,
-      "prev-round",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Object {
-        "score": 0,
-        "totalScore": 2000,
-      },
-    },
-  ],
-}
-`;
-
-exports[`gameStore dispatch submitGuess submits a timeout and then updates the current round 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`gameStore dispatch submitGuess submits a timeout and then updates the current round 3`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "test-game-id",
-      null,
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Object {
-        "coord": "coord",
-        "currentRound": "round",
-        "timer": "timer",
-      },
-    },
-  ],
-}
-`;
-
-exports[`gameStore dispatch submitGuess submits guess and then updates the current round 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "test-game-id",
-      null,
-      "prev-round",
-      "selected",
-      200,
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Object {
-        "score": 1000,
-        "totalScore": 2000,
-      },
-    },
-  ],
-}
-`;
-
-exports[`gameStore dispatch submitGuess submits guess and then updates the current round 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`gameStore dispatch submitGuess submits guess and then updates the current round 3`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "test-game-id",
-      null,
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Object {
-        "coord": "coord",
-        "currentRound": "round",
-        "timer": "timer",
-      },
-    },
-  ],
-}
-`;
-
-exports[`gameStore dispatch updateCurrentRound updates current round 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      null,
-      null,
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Object {
-        "coord": "coord",
-        "currentRound": "round",
-        "timer": "timer",
-      },
-    },
-  ],
-}
-`;
-
-exports[`gameStore dispatch updateRoundSeconds applies an update to round seconds 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      9,
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;

+ 0 - 13
client/src/tests/__snapshots__/getColorGenerator.test.js.snap

@@ -1,13 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`getColorGenerator provides a color generator 1`] = `"#e67373"`;
-
-exports[`getColorGenerator provides a color generator 2`] = `"#7394e6"`;
-
-exports[`getColorGenerator provides a color generator 3`] = `"#b6e673"`;
-
-exports[`getColorGenerator provides a color generator 4`] = `"#e673d8"`;
-
-exports[`getColorGenerator provides a color generator 5`] = `"#73e6d3"`;
-
-exports[`getColorGenerator provides a color generator 6`] = `"#e6b173"`;

+ 0 - 514
client/src/tests/__snapshots__/localStorageMethods.test.js.snap

@@ -1,514 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`localStorageMethods clearGameInfoFromLocalStorage clears data 1`] = `[MockFunction]`;
-
-exports[`localStorageMethods clearGameInfoFromLocalStorage clears data 2`] = `[MockFunction]`;
-
-exports[`localStorageMethods clearGameInfoFromLocalStorage clears data 3`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "terrassumptions:gameId",
-    ],
-    Array [
-      "terrassumptions:playerName",
-    ],
-    Array [
-      "terrassumptions:playerId",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`localStorageMethods clearRoundInfoFromLocalStorage clears data 1`] = `[MockFunction]`;
-
-exports[`localStorageMethods clearRoundInfoFromLocalStorage clears data 2`] = `[MockFunction]`;
-
-exports[`localStorageMethods clearRoundInfoFromLocalStorage clears data 3`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "terrassumptions:timer",
-    ],
-    Array [
-      "terrassumptions:pano:lat",
-    ],
-    Array [
-      "terrassumptions:pano:lng",
-    ],
-    Array [
-      "terrassumptions:pano:heading",
-    ],
-    Array [
-      "terrassumptions:pano:pitch",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`localStorageMethods getInfoFromLocalStorage gets data 1`] = `
-Object {
-  "gameId": "test-game-id",
-  "playerId": "test-player-id",
-  "playerName": "test-player",
-  "position": Object {
-    "lat": NaN,
-    "lng": NaN,
-  },
-  "pov": Object {
-    "heading": NaN,
-    "pitch": NaN,
-  },
-  "timer": 300,
-}
-`;
-
-exports[`localStorageMethods getInfoFromLocalStorage gets data 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "terrassumptions:timer",
-    ],
-    Array [
-      "terrassumptions:pano:lat",
-    ],
-    Array [
-      "terrassumptions:pano:lng",
-    ],
-    Array [
-      "terrassumptions:pano:heading",
-    ],
-    Array [
-      "terrassumptions:pano:pitch",
-    ],
-    Array [
-      "terrassumptions:gameId",
-    ],
-    Array [
-      "terrassumptions:playerName",
-    ],
-    Array [
-      "terrassumptions:playerId",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": "300",
-    },
-    Object {
-      "type": "return",
-      "value": "test-lat",
-    },
-    Object {
-      "type": "return",
-      "value": "test-lng",
-    },
-    Object {
-      "type": "return",
-      "value": "test-heading",
-    },
-    Object {
-      "type": "return",
-      "value": "test-pitch",
-    },
-    Object {
-      "type": "return",
-      "value": "test-game-id",
-    },
-    Object {
-      "type": "return",
-      "value": "test-player",
-    },
-    Object {
-      "type": "return",
-      "value": "test-player-id",
-    },
-  ],
-}
-`;
-
-exports[`localStorageMethods getInfoFromLocalStorage gets data 3`] = `[MockFunction]`;
-
-exports[`localStorageMethods getInfoFromLocalStorage gets data 4`] = `[MockFunction]`;
-
-exports[`localStorageMethods getInfoFromLocalStorage handles bad/missing extra data 1`] = `
-Object {
-  "gameId": "test-game-id",
-  "playerId": "test-player-id",
-  "playerName": "test-player",
-  "position": null,
-  "pov": null,
-  "timer": null,
-}
-`;
-
-exports[`localStorageMethods getInfoFromLocalStorage handles bad/missing extra data 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "terrassumptions:timer",
-    ],
-    Array [
-      "terrassumptions:pano:lat",
-    ],
-    Array [
-      "terrassumptions:pano:lng",
-    ],
-    Array [
-      "terrassumptions:pano:heading",
-    ],
-    Array [
-      "terrassumptions:pano:pitch",
-    ],
-    Array [
-      "terrassumptions:gameId",
-    ],
-    Array [
-      "terrassumptions:playerName",
-    ],
-    Array [
-      "terrassumptions:playerId",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": null,
-    },
-    Object {
-      "type": "return",
-      "value": null,
-    },
-    Object {
-      "type": "return",
-      "value": "test-lng",
-    },
-    Object {
-      "type": "return",
-      "value": null,
-    },
-    Object {
-      "type": "return",
-      "value": "test-pitch",
-    },
-    Object {
-      "type": "return",
-      "value": "test-game-id",
-    },
-    Object {
-      "type": "return",
-      "value": "test-player",
-    },
-    Object {
-      "type": "return",
-      "value": "test-player-id",
-    },
-  ],
-}
-`;
-
-exports[`localStorageMethods getInfoFromLocalStorage handles bad/missing extra data 3`] = `[MockFunction]`;
-
-exports[`localStorageMethods getInfoFromLocalStorage handles bad/missing extra data 4`] = `[MockFunction]`;
-
-exports[`localStorageMethods hasSavedGameInfo works when all data missing 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "terrassumptions:gameId",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": null,
-    },
-  ],
-}
-`;
-
-exports[`localStorageMethods hasSavedGameInfo works when all data missing 2`] = `[MockFunction]`;
-
-exports[`localStorageMethods hasSavedGameInfo works when all data missing 3`] = `[MockFunction]`;
-
-exports[`localStorageMethods hasSavedGameInfo works when getCurrentRound fails 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "terrassumptions:gameId",
-    ],
-    Array [
-      "terrassumptions:playerName",
-    ],
-    Array [
-      "terrassumptions:playerId",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": "test-game-id",
-    },
-    Object {
-      "type": "return",
-      "value": "test-player",
-    },
-    Object {
-      "type": "return",
-      "value": "test-player-id",
-    },
-  ],
-}
-`;
-
-exports[`localStorageMethods hasSavedGameInfo works when getCurrentRound fails 2`] = `[MockFunction]`;
-
-exports[`localStorageMethods hasSavedGameInfo works when getCurrentRound fails 3`] = `[MockFunction]`;
-
-exports[`localStorageMethods hasSavedGameInfo works when no data missing 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "terrassumptions:gameId",
-    ],
-    Array [
-      "terrassumptions:playerName",
-    ],
-    Array [
-      "terrassumptions:playerId",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": "test-game-id",
-    },
-    Object {
-      "type": "return",
-      "value": "test-player",
-    },
-    Object {
-      "type": "return",
-      "value": "test-player-id",
-    },
-  ],
-}
-`;
-
-exports[`localStorageMethods hasSavedGameInfo works when no data missing 2`] = `[MockFunction]`;
-
-exports[`localStorageMethods hasSavedGameInfo works when no data missing 3`] = `[MockFunction]`;
-
-exports[`localStorageMethods hasSavedGameInfo works when player info missing 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "terrassumptions:gameId",
-    ],
-    Array [
-      "terrassumptions:playerName",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": "test-game-id",
-    },
-    Object {
-      "type": "return",
-      "value": null,
-    },
-  ],
-}
-`;
-
-exports[`localStorageMethods hasSavedGameInfo works when player info missing 2`] = `[MockFunction]`;
-
-exports[`localStorageMethods hasSavedGameInfo works when player info missing 3`] = `[MockFunction]`;
-
-exports[`localStorageMethods hasSavedGameInfo works when playerId missing 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "terrassumptions:gameId",
-    ],
-    Array [
-      "terrassumptions:playerName",
-    ],
-    Array [
-      "terrassumptions:playerId",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": "test-game-id",
-    },
-    Object {
-      "type": "return",
-      "value": "test-player",
-    },
-    Object {
-      "type": "return",
-      "value": null,
-    },
-  ],
-}
-`;
-
-exports[`localStorageMethods hasSavedGameInfo works when playerId missing 2`] = `[MockFunction]`;
-
-exports[`localStorageMethods hasSavedGameInfo works when playerId missing 3`] = `[MockFunction]`;
-
-exports[`localStorageMethods saveGameInfoToLocalStorage saves given data 1`] = `[MockFunction]`;
-
-exports[`localStorageMethods saveGameInfoToLocalStorage saves given data 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "terrassumptions:gameId",
-      "test-game-id",
-    ],
-    Array [
-      "terrassumptions:playerName",
-      "test-player-name",
-    ],
-    Array [
-      "terrassumptions:playerId",
-      "test-player-id",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`localStorageMethods saveGameInfoToLocalStorage saves given data 3`] = `[MockFunction]`;
-
-exports[`localStorageMethods savePanoPositionToLocalStorage saves given data 1`] = `[MockFunction]`;
-
-exports[`localStorageMethods savePanoPositionToLocalStorage saves given data 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "terrassumptions:pano:lat",
-      "1",
-    ],
-    Array [
-      "terrassumptions:pano:lng",
-      "2",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`localStorageMethods savePanoPositionToLocalStorage saves given data 3`] = `[MockFunction]`;
-
-exports[`localStorageMethods savePanoPovToLocalStorage saves given data 1`] = `[MockFunction]`;
-
-exports[`localStorageMethods savePanoPovToLocalStorage saves given data 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "terrassumptions:pano:heading",
-      "3",
-    ],
-    Array [
-      "terrassumptions:pano:pitch",
-      "4",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`localStorageMethods savePanoPovToLocalStorage saves given data 3`] = `[MockFunction]`;
-
-exports[`localStorageMethods saveTimerToLocalStorage saves given data 1`] = `[MockFunction]`;
-
-exports[`localStorageMethods saveTimerToLocalStorage saves given data 2`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "terrassumptions:timer",
-      "100",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`localStorageMethods saveTimerToLocalStorage saves given data 3`] = `[MockFunction]`;

+ 0 - 102
client/src/tests/__snapshots__/markers.test.js.snap

@@ -1,102 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`markers makeFlagMarker makes a flag marker 1`] = `
-fakeClass {
-  "addListener": [Function],
-  "calledWith": Array [
-    Object {
-      "clickable": true,
-      "icon": Object {
-        "anchor": fakeClass {
-          "addListener": [Function],
-          "calledWith": Array [
-            16,
-            512,
-          ],
-          "listeners": Map {},
-        },
-        "fillColor": "#000000",
-        "fillOpacity": 1,
-        "path": "M466.515 66.928C487.731 57.074 512 72.551 512 95.944v243.1c0 10.526-5.161 20.407-13.843 26.358-35.837 24.564-74.335 40.858-122.505 40.858-67.373 0-111.63-34.783-165.217-34.783-50.853 0-86.124 10.058-114.435 22.122V488c0 13.255-10.745 24-24 24H56c-13.255 0-24-10.745-24-24V101.945C17.497 91.825 8 75.026 8 56 8 24.296 34.345-1.254 66.338.048c28.468 1.158 51.779 23.968 53.551 52.404.52 8.342-.81 16.31-3.586 23.562C137.039 68.384 159.393 64 184.348 64c67.373 0 111.63 34.783 165.217 34.783 40.496 0 82.612-15.906 116.95-31.855zM96 134.63v70.49c29-10.67 51.18-17.83 73.6-20.91v-71.57c-23.5 2.17-40.44 9.79-73.6 21.99zm220.8 9.19c-26.417-4.672-49.886-13.979-73.6-21.34v67.42c24.175 6.706 47.566 16.444 73.6 22.31v-68.39zm-147.2 40.39v70.04c32.796-2.978 53.91-.635 73.6 3.8V189.9c-25.247-7.035-46.581-9.423-73.6-5.69zm73.6 142.23c26.338 4.652 49.732 13.927 73.6 21.34v-67.41c-24.277-6.746-47.54-16.45-73.6-22.32v68.39zM96 342.1c23.62-8.39 47.79-13.84 73.6-16.56v-71.29c-26.11 2.35-47.36 8.04-73.6 17.36v70.49zm368-221.6c-21.3 8.85-46.59 17.64-73.6 22.47v71.91c27.31-4.36 50.03-14.1 73.6-23.89V120.5zm0 209.96v-70.49c-22.19 14.2-48.78 22.61-73.6 26.02v71.58c25.07-2.38 48.49-11.04 73.6-27.11zM316.8 212.21v68.16c25.664 7.134 46.616 9.342 73.6 5.62v-71.11c-25.999 4.187-49.943 2.676-73.6-2.67z",
-        "scale": 0.075,
-      },
-      "map": "map",
-      "position": Object {
-        "lat": "lat",
-        "lng": "lng",
-      },
-      "title": "Goal",
-    },
-  ],
-  "listeners": Map {
-    "click" => Array [
-      [Function],
-    ],
-  },
-}
-`;
-
-exports[`markers makeLine makes a line 1`] = `
-fakeClass {
-  "addListener": [Function],
-  "calledWith": Array [
-    Object {
-      "icons": Array [
-        Object {
-          "icon": Object {
-            "path": "M 0,-1 0,1",
-            "scale": 4,
-            "strokeOpacity": 1,
-          },
-          "offset": "0",
-          "repeat": "20px",
-        },
-      ],
-      "map": "map",
-      "path": Array [
-        "p1",
-        "p2",
-      ],
-      "strokeColor": "color",
-      "strokeOpacity": 0,
-    },
-  ],
-  "listeners": Map {},
-}
-`;
-
-exports[`markers makeQuestionMarker makes a question marker 1`] = `
-fakeClass {
-  "addListener": [Function],
-  "calledWith": Array [
-    Object {
-      "clickable": true,
-      "icon": Object {
-        "anchor": fakeClass {
-          "addListener": [Function],
-          "calledWith": Array [
-            32,
-            40,
-          ],
-          "listeners": Map {},
-        },
-        "fillColor": "color",
-        "fillOpacity": 1,
-        "path": "M29.898 26.5722l-4.3921 0c-0.0118,-0.635 -0.0177,-1.0172 -0.0177,-1.1583 0,-1.4229 0.2352,-2.5929 0.7056,-3.5102 0.4704,-0.9231 1.417,-1.952 2.8281,-3.1044 1.4111,-1.1465 2.2578,-1.8991 2.5282,-2.2578 0.4292,-0.5585 0.6409,-1.1818 0.6409,-1.8579 0,-0.9408 -0.3763,-1.7463 -1.1289,-2.4224 -0.7526,-0.6703 -1.7639,-1.0054 -3.0397,-1.0054 -1.2289,0 -2.2578,0.3527 -3.0868,1.0524 -0.8232,0.6997 -1.3935,1.7698 -1.7051,3.2044l-4.4391 -0.5527c0.1234,-2.0578 0.9995,-3.8041 2.6223,-5.2387 1.6286,-1.4346 3.757,-2.152 6.4029,-2.152 2.7752,0 4.9859,0.7291 6.6322,2.1814 1.6404,1.4522 2.4635,3.1397 2.4635,5.0741 0,1.0642 -0.3057,2.0755 -0.9054,3.028 -0.6056,0.9525 -1.8933,2.2519 -3.8688,3.8923 -1.0231,0.8525 -1.6581,1.5346 -1.905,2.052 -0.2469,0.5174 -0.3587,1.4405 -0.3351,2.7752zm-4.3921 6.5087l0 -4.8389 4.8389 0 0 4.8389 -4.8389 0z",
-        "scale": 1,
-      },
-      "map": "map",
-      "position": Object {
-        "lat": "lat",
-        "lng": "lng",
-      },
-      "title": "title",
-    },
-  ],
-  "listeners": Map {
-    "click" => Array [
-      [Function],
-    ],
-  },
-}
-`;

+ 0 - 53
client/src/tests/__snapshots__/store.test.js.snap

@@ -1,53 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Store Library creates a store 1`] = `
-Array [
-  "counter",
-  "increment",
-  "changeCounter",
-  "doInvalid",
-  "getReflectedKeys",
-]
-`;
-
-exports[`Store Library creates a store 2`] = `
-Array [
-  Array [
-    "counter",
-    1,
-    0,
-  ],
-  Array [
-    "counter",
-    3,
-    1,
-  ],
-  Array [
-    "counter",
-    10,
-    3,
-  ],
-]
-`;
-
-exports[`Store Library creates a store 3`] = `
-Array [
-  Array [
-    "increment",
-  ],
-  Array [
-    "changeCounter",
-    [Function],
-  ],
-  Array [
-    "changeCounter",
-    10,
-  ],
-  Array [
-    "getReflectedKeys",
-  ],
-  Array [
-    "doInvalid",
-  ],
-]
-`;

+ 0 - 564
client/src/tests/apiMethods.test.js

@@ -1,564 +0,0 @@
-import {
-  checkScore,
-  createGame,
-  getCurrentRound,
-  getFirstSubmitter,
-  getGameConfig,
-  getGameCoords,
-  getGenerators,
-  getLinkedGame,
-  getPlayers,
-  getStatus,
-  joinGame,
-  linkGame,
-  sendGuess,
-  sendTimeout,
-} from "../domain/apiMethods";
-
-describe("apiMethods", () => {
-  describe("getStatus", () => {
-    it("gets status", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: true,
-          json: () =>
-            Promise.resolve({
-              status: "healthy",
-              version: "test",
-            }),
-        })
-      );
-      expect(await getStatus()).toMatchSnapshot();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("handles server error", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: false,
-          statusText: "failed",
-        })
-      );
-      expect(await getStatus()).toMatchSnapshot();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("handles thrown error", async () => {
-      global.fetch.mockImplementation(() => {
-        throw new Error("error");
-      });
-      expect(await getStatus()).toMatchSnapshot();
-      expect(global.fetch).toMatchSnapshot();
-    });
-  });
-
-  describe("checkScore", () => {
-    it("checks score", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: true,
-          json: () =>
-            Promise.resolve({
-              score: 1000,
-            }),
-        })
-      );
-      expect(await checkScore("point1", "point2")).toMatchSnapshot();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("throws on server error", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: false,
-          statusText: "failed",
-        })
-      );
-      await expect(checkScore("point1", "point2")).rejects.toThrow();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("passes thrown error", async () => {
-      global.fetch.mockImplementation(() => {
-        throw new Error("error");
-      });
-      await expect(checkScore("point1", "point2")).rejects.toThrow();
-      expect(global.fetch).toMatchSnapshot();
-    });
-  });
-
-  describe("getGenerators", () => {
-    it("gets generators", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: true,
-          json: () =>
-            Promise.resolve({
-              generators: [],
-            }),
-        })
-      );
-      expect(await getGenerators()).toMatchSnapshot();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("throws on server error", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: false,
-          statusText: "failed",
-        })
-      );
-      await expect(getGenerators()).rejects.toThrow();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("passes thrown error", async () => {
-      global.fetch.mockImplementation(() => {
-        throw new Error("error");
-      });
-      await expect(getGenerators()).rejects.toThrow();
-      expect(global.fetch).toMatchSnapshot();
-    });
-  });
-
-  describe("createGame", () => {
-    it("creates game", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: true,
-          json: () =>
-            Promise.resolve({
-              gameId: "test-game-id",
-            }),
-        })
-      );
-      expect(
-        await createGame(
-          "timer",
-          "rounds",
-          "countryLock",
-          "generationMethod",
-          "gameMode",
-          "clockMode",
-          "scoreMethod",
-          "roundPointCap"
-        )
-      ).toMatchSnapshot();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("throws on server error", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: false,
-          statusText: "failed",
-        })
-      );
-      await expect(
-        createGame(
-          "timer",
-          "rounds",
-          "countryLock",
-          "generationMethod",
-          "gameMode",
-          "clockMode",
-          "scoreMethod",
-          "roundPointCap"
-        )
-      ).rejects.toThrow();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("passes thrown error", async () => {
-      global.fetch.mockImplementation(() => {
-        throw new Error("error");
-      });
-      await expect(
-        createGame(
-          "timer",
-          "rounds",
-          "countryLock",
-          "generationMethod",
-          "gameMode",
-          "clockMode",
-          "scoreMethod",
-          "roundPointCap"
-        )
-      ).rejects.toThrow();
-      expect(global.fetch).toMatchSnapshot();
-    });
-  });
-
-  describe("getGameConfig", () => {
-    it("gets game config", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: true,
-          json: () =>
-            Promise.resolve({
-              config: "test-config",
-            }),
-        })
-      );
-      expect(await getGameConfig("test-game-id")).toMatchSnapshot();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("throws on server error", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: false,
-          statusText: "failed",
-        })
-      );
-      await expect(getGameConfig("test-game-id")).rejects.toThrow();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("passes thrown error", async () => {
-      global.fetch.mockImplementation(() => {
-        throw new Error("error");
-      });
-      await expect(getGameConfig("test-game-id")).rejects.toThrow();
-      expect(global.fetch).toMatchSnapshot();
-    });
-  });
-
-  describe("getGameCoords", () => {
-    it("gets game coords", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: true,
-          json: () =>
-            Promise.resolve({
-              coords: ["test-coord"],
-            }),
-        })
-      );
-      expect(await getGameCoords("test-game-id")).toMatchSnapshot();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("throws on server error", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: false,
-          statusText: "failed",
-        })
-      );
-      await expect(getGameCoords("test-game-id")).rejects.toThrow();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("passes thrown error", async () => {
-      global.fetch.mockImplementation(() => {
-        throw new Error("error");
-      });
-      await expect(getGameCoords("test-game-id")).rejects.toThrow();
-      expect(global.fetch).toMatchSnapshot();
-    });
-  });
-
-  describe("getPlayers", () => {
-    it("gets game players", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: true,
-          json: () =>
-            Promise.resolve({
-              players: ["test-player"],
-            }),
-        })
-      );
-      expect(await getPlayers("test-game-id")).toMatchSnapshot();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("throws on server error", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: false,
-          statusText: "failed",
-        })
-      );
-      await expect(getPlayers("test-game-id")).rejects.toThrow();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("passes thrown error", async () => {
-      global.fetch.mockImplementation(() => {
-        throw new Error("error");
-      });
-      await expect(getPlayers("test-game-id")).rejects.toThrow();
-      expect(global.fetch).toMatchSnapshot();
-    });
-  });
-
-  describe("getLinkedGame", () => {
-    it("gets linked game", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: true,
-          json: () =>
-            Promise.resolve({
-              linkedGame: ["test-linked-game-id"],
-            }),
-        })
-      );
-      expect(await getLinkedGame("test-game-id")).toMatchSnapshot();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("throws on server error", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: false,
-          statusText: "failed",
-        })
-      );
-      await expect(getLinkedGame("test-game-id")).rejects.toThrow();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("passes thrown error", async () => {
-      global.fetch.mockImplementation(() => {
-        throw new Error("error");
-      });
-      await expect(getLinkedGame("test-game-id")).rejects.toThrow();
-      expect(global.fetch).toMatchSnapshot();
-    });
-  });
-
-  describe("linkGame", () => {
-    it("links game to another", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: true,
-        })
-      );
-      expect(
-        await linkGame("test-game-id", "test-linked-game-id")
-      ).toMatchSnapshot();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("throws on server error", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: false,
-          statusText: "failed",
-        })
-      );
-      await expect(
-        linkGame("test-game-id", "test-linked-game-id")
-      ).rejects.toThrow();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("passes thrown error", async () => {
-      global.fetch.mockImplementation(() => {
-        throw new Error("error");
-      });
-      await expect(
-        linkGame("test-game-id", "test-linked-game-id")
-      ).rejects.toThrow();
-      expect(global.fetch).toMatchSnapshot();
-    });
-  });
-
-  describe("getFirstSubmitter", () => {
-    it("gets first submmiter for a round", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: true,
-          json: () =>
-            Promise.resolve({
-              first: "test-player",
-            }),
-        })
-      );
-      expect(
-        await getFirstSubmitter("test-game-id", "round")
-      ).toMatchSnapshot();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("returns null on server error", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: false,
-          statusText: "failed",
-        })
-      );
-      expect(await getFirstSubmitter("test-game-id", "round")).toBe(null);
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("passes thrown error", async () => {
-      global.fetch.mockImplementation(() => {
-        throw new Error("error");
-      });
-      await expect(
-        getFirstSubmitter("test-game-id", "round")
-      ).rejects.toThrow();
-      expect(global.fetch).toMatchSnapshot();
-    });
-  });
-
-  describe("joinGame", () => {
-    it("joins game", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: true,
-          json: () =>
-            Promise.resolve({
-              playerId: "test-player-id",
-            }),
-        })
-      );
-      expect(
-        await joinGame("test-game-id", "test-player-name")
-      ).toMatchSnapshot();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("throws on server error", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: false,
-          statusText: "failed",
-        })
-      );
-      await expect(
-        joinGame("test-game-id", "test-player-name")
-      ).rejects.toThrow();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("passes thrown error", async () => {
-      global.fetch.mockImplementation(() => {
-        throw new Error("error");
-      });
-      await expect(
-        joinGame("test-game-id", "test-player-name")
-      ).rejects.toThrow();
-      expect(global.fetch).toMatchSnapshot();
-    });
-  });
-
-  describe("getCurrentRound", () => {
-    it("gets current round", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: true,
-          json: () =>
-            Promise.resolve({
-              round: "test-round",
-            }),
-        })
-      );
-      expect(
-        await getCurrentRound("test-game-id", "test-player-id")
-      ).toMatchSnapshot();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("throws on server error", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: false,
-          statusText: "failed",
-        })
-      );
-      await expect(
-        getCurrentRound("test-game-id", "test-player-id")
-      ).rejects.toThrow();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("passes thrown error", async () => {
-      global.fetch.mockImplementation(() => {
-        throw new Error("error");
-      });
-      await expect(
-        getCurrentRound("test-game-id", "test-player-id")
-      ).rejects.toThrow();
-      expect(global.fetch).toMatchSnapshot();
-    });
-  });
-
-  describe("sendGuess", () => {
-    it("sends a guess", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: true,
-          json: () =>
-            Promise.resolve({
-              score: 1000,
-              totalScore: 5000,
-            }),
-        })
-      );
-      expect(
-        await sendGuess(
-          "test-game-id",
-          "test-player-id",
-          "test-round",
-          { lat: "lat", lng: "lng" },
-          "test-time"
-        )
-      ).toMatchSnapshot();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("throws on server error", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: false,
-          statusText: "failed",
-        })
-      );
-      await expect(
-        sendGuess(
-          "test-game-id",
-          "test-player-id",
-          "test-round",
-          { lat: "lat", lng: "lng" },
-          "test-time"
-        )
-      ).rejects.toThrow();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("passes thrown error", async () => {
-      global.fetch.mockImplementation(() => {
-        throw new Error("error");
-      });
-      await expect(
-        sendGuess(
-          "test-game-id",
-          "test-player-id",
-          "test-round",
-          { lat: "lat", lng: "lng" },
-          "test-time"
-        )
-      ).rejects.toThrow();
-      expect(global.fetch).toMatchSnapshot();
-    });
-  });
-
-  describe("sendtimeout", () => {
-    it("sends a timeout for the round", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: true,
-          json: () =>
-            Promise.resolve({
-              score: 0,
-              totalScore: 2000,
-            }),
-        })
-      );
-      expect(
-        await sendTimeout("test-game-id", "test-player-id", "test-round")
-      ).toMatchSnapshot();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("throws on server error", async () => {
-      global.fetch.mockImplementation(() =>
-        Promise.resolve({
-          ok: false,
-          statusText: "failed",
-        })
-      );
-      await expect(
-        sendTimeout("test-game-id", "test-player-id", "test-round")
-      ).rejects.toThrow();
-      expect(global.fetch).toMatchSnapshot();
-    });
-    it("passes thrown error", async () => {
-      global.fetch.mockImplementation(() => {
-        throw new Error("error");
-      });
-      await expect(
-        sendTimeout("test-game-id", "test-player-id", "test-round")
-      ).rejects.toThrow();
-      expect(global.fetch).toMatchSnapshot();
-    });
-  });
-});

+ 0 - 12
client/src/tests/flagLookup.test.js

@@ -1,12 +0,0 @@
-import flagLookup from "../domain/flagLookup";
-
-describe("flagLookup", () => {
-  it("finds flags", () => {
-    expect(flagLookup("us")).toMatchSnapshot();
-    expect(flagLookup("gb")).toMatchSnapshot();
-    expect(flagLookup("cn")).toMatchSnapshot();
-    expect(flagLookup("br")).toMatchSnapshot();
-    expect(flagLookup("00")).toMatchSnapshot();
-    expect(flagLookup(null)).toMatchSnapshot();
-  });
-});

+ 0 - 263
client/src/tests/gameStore.test.js

@@ -1,263 +0,0 @@
-import { IN_ROUND, POST_GAME, PRE_ROUND } from "../domain/constants";
-
-process.env.REACT_APP_MONITOR_STORE = "true";
-
-jest.mock("../store");
-jest.mock("../domain/apiMethods");
-jest.mock("../domain/localStorageMethods");
-
-import {
-  getCurrentRound,
-  joinGame,
-  sendGuess,
-  sendTimeout,
-} from "../domain/apiMethods";
-import {
-  dispatch,
-  useGameId,
-  usePlayerName,
-  useGameState,
-  useCurrentRound,
-  useTargetPoint,
-  usePanoStartPosition,
-  usePanoStartPov,
-  useRoundSeconds,
-  useLastRound,
-} from "../domain/gameStore";
-import {
-  clearGameInfoFromLocalStorage,
-  clearRoundInfoFromLocalStorage,
-  getInfoFromLocalStorage,
-  saveGameInfoToLocalStorage,
-  saveTimerToLocalStorage,
-} from "../domain/localStorageMethods";
-
-describe("gameStore", () => {
-  beforeEach(() => {
-    dispatch.RESET_STORE();
-  });
-  describe("dispatch", () => {
-    describe("setPlayerName", () => {
-      it("sets player name", () => {
-        dispatch.setPlayerName("test-player-name");
-        expect(usePlayerName()).toBe("test-player-name");
-      });
-    });
-    describe("goToLobby", () => {
-      it("goes to lobby", () => {
-        dispatch.goToLobby("test-game-id");
-        expect(useGameId()).toBe("test-game-id");
-        expect(dispatch.GET_STORED_VALUE("playerId")).toBe(null);
-        expect(useGameState()).toBe(PRE_ROUND);
-      });
-    });
-    describe("startRound", () => {
-      it("starts round", () => {
-        dispatch.startRound();
-        expect(useGameState()).toBe(IN_ROUND);
-      });
-    });
-    describe("goToSummary", () => {
-      it("goes to summary", () => {
-        dispatch.goToSummary();
-        expect(useGameId()).toBe(null);
-        expect(useGameState()).toBe(POST_GAME);
-        expect(clearRoundInfoFromLocalStorage).toHaveBeenCalled();
-        expect(clearGameInfoFromLocalStorage).toHaveBeenCalled();
-      });
-      it("updates game ID if given", () => {
-        dispatch.goToSummary("test-game-id");
-        expect(useGameId()).toBe("test-game-id");
-        expect(useGameState()).toBe(POST_GAME);
-        expect(clearRoundInfoFromLocalStorage).toHaveBeenCalled();
-        expect(clearGameInfoFromLocalStorage).toHaveBeenCalled();
-      });
-      it("can avoid clearing saved data", () => {
-        dispatch.goToSummary("test-game-id", false);
-        expect(useGameId()).toBe("test-game-id");
-        expect(useGameState()).toBe(POST_GAME);
-        expect(clearRoundInfoFromLocalStorage).not.toHaveBeenCalled();
-        expect(clearGameInfoFromLocalStorage).not.toHaveBeenCalled();
-      });
-    });
-    describe("updateCurrentRound", () => {
-      it("updates current round", async () => {
-        getCurrentRound.mockReturnValue({
-          currentRound: "round",
-          coord: "coord",
-          timer: "timer",
-        });
-        await dispatch.updateCurrentRound();
-        expect(useCurrentRound()).toBe("round");
-        expect(useTargetPoint()).toBe("coord");
-        expect(usePanoStartPosition()).toBe("coord");
-        expect(usePanoStartPov()).toMatchObject({
-          heading: 0,
-          pitch: 0,
-        });
-        expect(useRoundSeconds()).toBe("timer");
-        expect(getCurrentRound).toMatchSnapshot();
-      });
-    });
-    describe("joinGame", () => {
-      it("joins game then updates current round", async () => {
-        dispatch.SET_STORED_VALUE("gameId", "test-game-id");
-        dispatch.SET_STORED_VALUE("playerName", "test-player-name");
-        joinGame.mockReturnValue({
-          playerId: "test-player-id",
-        });
-        getCurrentRound.mockReturnValue({
-          currentRound: "round",
-          coord: "coord",
-          timer: "timer",
-        });
-        await dispatch.joinGame();
-        expect(joinGame).toMatchSnapshot();
-        expect(saveGameInfoToLocalStorage).toMatchSnapshot();
-        expect(dispatch.GET_STORED_VALUE("playerId")).toBe("test-player-id");
-        expect(useCurrentRound()).toBe("round");
-        expect(useTargetPoint()).toBe("coord");
-        expect(usePanoStartPosition()).toBe("coord");
-        expect(usePanoStartPov()).toMatchObject({
-          heading: 0,
-          pitch: 0,
-        });
-        expect(useRoundSeconds()).toBe("timer");
-        expect(getCurrentRound).toMatchSnapshot();
-      });
-    });
-    describe("rejoinGame", () => {
-      it("rejoins game then updates current round", async () => {
-        getInfoFromLocalStorage.mockReturnValue({
-          gameId: "test-game-id",
-          playerName: "test-player-name",
-          playerId: "test-player-id",
-          timer: "test-timer",
-          position: "test-position",
-          pov: "test-pov",
-        });
-        getCurrentRound.mockReturnValue({
-          currentRound: "round",
-          coord: "coord",
-          timer: "timer",
-        });
-        await dispatch.rejoinGame();
-        expect(saveGameInfoToLocalStorage).toMatchSnapshot();
-        expect(useGameId()).toBe("test-game-id");
-        expect(usePlayerName()).toBe("test-player-name");
-        expect(dispatch.GET_STORED_VALUE("playerId")).toBe("test-player-id");
-        expect(useCurrentRound()).toBe("round");
-        expect(useTargetPoint()).toBe("coord");
-        expect(usePanoStartPosition()).toBe("test-position");
-        expect(usePanoStartPov()).toBe("test-pov");
-        expect(useRoundSeconds()).toBe("test-timer");
-        expect(useGameState()).toBe(IN_ROUND);
-        expect(getCurrentRound).toMatchSnapshot();
-      });
-      it("rejoins game then updates current round even with missing information", async () => {
-        getInfoFromLocalStorage.mockReturnValue({
-          gameId: "test-game-id",
-          playerName: "test-player-name",
-          playerId: "test-player-id",
-        });
-        getCurrentRound.mockReturnValue({
-          currentRound: "round",
-          coord: "coord",
-          timer: "timer",
-        });
-        await dispatch.rejoinGame();
-        expect(saveGameInfoToLocalStorage).toMatchSnapshot();
-        expect(useGameId()).toBe("test-game-id");
-        expect(usePlayerName()).toBe("test-player-name");
-        expect(dispatch.GET_STORED_VALUE("playerId")).toBe("test-player-id");
-        expect(useCurrentRound()).toBe("round");
-        expect(useTargetPoint()).toBe("coord");
-        expect(usePanoStartPosition()).toBe("coord");
-        expect(usePanoStartPov()).toMatchObject({
-          heading: 0,
-          pitch: 0,
-        });
-        expect(useRoundSeconds()).toBe("timer");
-        expect(useGameState()).toBe(IN_ROUND);
-        expect(getCurrentRound).toMatchSnapshot();
-      });
-    });
-    describe("submitGuess", () => {
-      it("submits guess and then updates the current round", async () => {
-        dispatch.SET_STORED_VALUE("gameId", "test-game-id");
-        dispatch.SET_STORED_VALUE("playerName", "test-player-name");
-        dispatch.SET_STORED_VALUE("currentRound", "prev-round");
-        dispatch.SET_STORED_VALUE("roundSeconds", 200);
-        dispatch.SET_STORED_VALUE("targetPoint", "prev-target");
-        sendGuess.mockReturnValue({
-          score: 1000,
-          totalScore: 2000,
-        });
-        getCurrentRound.mockReturnValue({
-          currentRound: "round",
-          coord: "coord",
-          timer: "timer",
-        });
-        await dispatch.submitGuess("selected");
-        expect(sendGuess).toMatchSnapshot();
-        expect(clearRoundInfoFromLocalStorage).toMatchSnapshot();
-        expect(useLastRound()).toMatchObject({
-          roundNum: "prev-round",
-          targetPoint: "prev-target",
-          score: 1000,
-          totalScore: 2000,
-        });
-        expect(useCurrentRound()).toBe("round");
-        expect(useTargetPoint()).toBe("coord");
-        expect(usePanoStartPosition()).toBe("coord");
-        expect(usePanoStartPov()).toMatchObject({
-          heading: 0,
-          pitch: 0,
-        });
-        expect(useRoundSeconds()).toBe("timer");
-        expect(getCurrentRound).toMatchSnapshot();
-      });
-      it("submits a timeout and then updates the current round", async () => {
-        dispatch.SET_STORED_VALUE("gameId", "test-game-id");
-        dispatch.SET_STORED_VALUE("playerName", "test-player-name");
-        dispatch.SET_STORED_VALUE("currentRound", "prev-round");
-        dispatch.SET_STORED_VALUE("targetPoint", "prev-target");
-        sendTimeout.mockReturnValue({
-          score: 0,
-          totalScore: 2000,
-        });
-        getCurrentRound.mockReturnValue({
-          currentRound: "round",
-          coord: "coord",
-          timer: "timer",
-        });
-        await dispatch.submitGuess(null);
-        expect(sendTimeout).toMatchSnapshot();
-        expect(clearRoundInfoFromLocalStorage).toMatchSnapshot();
-        expect(useLastRound()).toMatchObject({
-          roundNum: "prev-round",
-          targetPoint: "prev-target",
-          score: 0,
-          totalScore: 2000,
-        });
-        expect(useCurrentRound()).toBe("round");
-        expect(useTargetPoint()).toBe("coord");
-        expect(usePanoStartPosition()).toBe("coord");
-        expect(usePanoStartPov()).toMatchObject({
-          heading: 0,
-          pitch: 0,
-        });
-        expect(useRoundSeconds()).toBe("timer");
-        expect(getCurrentRound).toMatchSnapshot();
-      });
-    });
-    describe("updateRoundSeconds", () => {
-      it("applies an update to round seconds", () => {
-        dispatch.SET_STORED_VALUE("roundSeconds", 10);
-        dispatch.updateRoundSeconds(c => c - 1);
-        expect(useRoundSeconds()).toBe(9);
-        expect(saveTimerToLocalStorage).toMatchSnapshot();
-      });
-    });
-  });
-});

+ 0 - 60
client/src/tests/geocoding.test.js

@@ -1,60 +0,0 @@
-import { GEOCODER, getCountryBounds } from "../domain/geocoding";
-
-jest.mock("iso-3166-1");
-
-import iso from "iso-3166-1";
-
-describe("geocoding", () => {
-  describe("getCountryBounds", () => {
-    it("gets bounds for a given country", async () => {
-      iso.whereAlpha2.mockReturnValue({ country: "test-country" });
-      GEOCODER.geocode.mockReturnValue({
-        results: [
-          {
-            geometry: { viewport: "viewport" },
-            types: ["country"],
-          },
-        ],
-      });
-      expect(await getCountryBounds("success-test")).toBe("viewport");
-      expect(GEOCODER.geocode).toHaveBeenCalledWith(
-        expect.objectContaining({
-          address: "test-country",
-        })
-      );
-    });
-    it("handles missing data gracefully", async () => {
-      iso.whereAlpha2.mockReturnValue({ country: "test-country" });
-      GEOCODER.geocode.mockReturnValue({
-        results: [
-          {
-            geometry: { viewport: "viewport" },
-            types: ["not-country"],
-          },
-        ],
-      });
-      expect(await getCountryBounds("bad-data-test")).toBe(null);
-    });
-    it("suppresses errors and returns null", async () => {
-      iso.whereAlpha2.mockReturnValue({ country: "test-country" });
-      GEOCODER.geocode.mockImplementation(() => {
-        throw new Error();
-      });
-      expect(await getCountryBounds("error-test")).toBe(null);
-    });
-    it("uses cache when possible", async () => {
-      iso.whereAlpha2.mockReturnValue({ country: "test-country" });
-      GEOCODER.geocode.mockReturnValue({
-        results: [
-          {
-            geometry: { viewport: "viewport" },
-            types: ["country"],
-          },
-        ],
-      });
-      expect(await getCountryBounds("cache-test")).toBe("viewport");
-      expect(await getCountryBounds("cache-test")).toBe("viewport");
-      expect(GEOCODER.geocode).toHaveBeenCalledTimes(1);
-    });
-  });
-});

+ 0 - 13
client/src/tests/getColorGenerator.test.js

@@ -1,13 +0,0 @@
-import getColorGenerator from "../hooks/useMarkersFromGuesses/getColorGenerator";
-
-describe("getColorGenerator", () => {
-  it("provides a color generator", () => {
-    const gen = getColorGenerator();
-    expect(gen()).toMatchSnapshot();
-    expect(gen()).toMatchSnapshot();
-    expect(gen()).toMatchSnapshot();
-    expect(gen()).toMatchSnapshot();
-    expect(gen()).toMatchSnapshot();
-    expect(gen()).toMatchSnapshot();
-  });
-});

+ 0 - 192
client/src/tests/localStorageMethods.test.js

@@ -1,192 +0,0 @@
-import { getCurrentRound } from "../domain/apiMethods";
-import {
-  clearGameInfoFromLocalStorage,
-  clearRoundInfoFromLocalStorage,
-  getInfoFromLocalStorage,
-  hasSavedGameInfo,
-  saveGameInfoToLocalStorage,
-  savePanoPositionToLocalStorage,
-  savePanoPovToLocalStorage,
-  saveTimerToLocalStorage,
-} from "../domain/localStorageMethods";
-
-const localStorageGameId = "terrassumptions:gameId";
-const localStoragePlayerName = "terrassumptions:playerName";
-const localStoragePlayerId = "terrassumptions:playerId";
-
-const localStorageTimer = "terrassumptions:timer";
-
-const localStoragePanoLat = "terrassumptions:pano:lat";
-const localStoragePanoLng = "terrassumptions:pano:lng";
-
-const localStoragePanoHeading = "terrassumptions:pano:heading";
-const localStoragePanoPitch = "terrassumptions:pano:pitch";
-
-jest.mock("../domain/apiMethods");
-
-describe("localStorageMethods", () => {
-  beforeEach(() => {
-    jest.spyOn(window.localStorage.__proto__, "getItem");
-    jest.spyOn(window.localStorage.__proto__, "setItem");
-    jest.spyOn(window.localStorage.__proto__, "removeItem");
-  });
-
-  describe("hasSavedGameInfo", () => {
-    it("works when all data missing", async () => {
-      expect(await hasSavedGameInfo()).toBe(false);
-      expect(localStorage.getItem).toMatchSnapshot();
-      expect(localStorage.setItem).toMatchSnapshot();
-      expect(localStorage.removeItem).toMatchSnapshot();
-      expect(getCurrentRound).not.toHaveBeenCalled();
-    });
-    it("works when player info missing", async () => {
-      const data = {
-        [localStorageGameId]: "test-game-id",
-      };
-      localStorage.getItem.mockImplementation(key => data[key] ?? null);
-
-      expect(await hasSavedGameInfo()).toBe(false);
-      expect(localStorage.getItem).toMatchSnapshot();
-      expect(localStorage.setItem).toMatchSnapshot();
-      expect(localStorage.removeItem).toMatchSnapshot();
-      expect(getCurrentRound).not.toHaveBeenCalled();
-    });
-    it("works when playerId missing", async () => {
-      const data = {
-        [localStorageGameId]: "test-game-id",
-        [localStoragePlayerName]: "test-player",
-      };
-      localStorage.getItem.mockImplementation(key => data[key] ?? null);
-
-      expect(await hasSavedGameInfo()).toBe(false);
-      expect(localStorage.getItem).toMatchSnapshot();
-      expect(localStorage.setItem).toMatchSnapshot();
-      expect(localStorage.removeItem).toMatchSnapshot();
-      expect(getCurrentRound).not.toHaveBeenCalled();
-    });
-    it("works when getCurrentRound fails", async () => {
-      const data = {
-        [localStorageGameId]: "test-game-id",
-        [localStoragePlayerName]: "test-player",
-        [localStoragePlayerId]: "test-player-id",
-      };
-      localStorage.getItem.mockImplementation(key => data[key] ?? null);
-      getCurrentRound.mockImplementation(() => {
-        throw new Error();
-      });
-      expect(await hasSavedGameInfo()).toBe(false);
-      expect(localStorage.getItem).toMatchSnapshot();
-      expect(localStorage.setItem).toMatchSnapshot();
-      expect(localStorage.removeItem).toMatchSnapshot();
-      expect(getCurrentRound).toHaveBeenCalled();
-    });
-    it("works when no data missing", async () => {
-      const data = {
-        [localStorageGameId]: "test-game-id",
-        [localStoragePlayerName]: "test-player",
-        [localStoragePlayerId]: "test-player-id",
-      };
-      localStorage.getItem.mockImplementation(key => data[key] ?? null);
-
-      expect(await hasSavedGameInfo()).toBe(true);
-      expect(localStorage.getItem).toMatchSnapshot();
-      expect(localStorage.setItem).toMatchSnapshot();
-      expect(localStorage.removeItem).toMatchSnapshot();
-      expect(getCurrentRound).toHaveBeenCalled();
-    });
-  });
-
-  describe("saveGameInfoToLocalStorage", () => {
-    it("saves given data", () => {
-      saveGameInfoToLocalStorage(
-        "test-game-id",
-        "test-player-name",
-        "test-player-id"
-      );
-      expect(localStorage.getItem).toMatchSnapshot();
-      expect(localStorage.setItem).toMatchSnapshot();
-      expect(localStorage.removeItem).toMatchSnapshot();
-    });
-  });
-
-  describe("saveTimerToLocalStorage", () => {
-    it("saves given data", () => {
-      saveTimerToLocalStorage(100);
-      expect(localStorage.getItem).toMatchSnapshot();
-      expect(localStorage.setItem).toMatchSnapshot();
-      expect(localStorage.removeItem).toMatchSnapshot();
-    });
-  });
-
-  describe("savePanoPositionToLocalStorage", () => {
-    it("saves given data", () => {
-      savePanoPositionToLocalStorage(1, 2);
-      expect(localStorage.getItem).toMatchSnapshot();
-      expect(localStorage.setItem).toMatchSnapshot();
-      expect(localStorage.removeItem).toMatchSnapshot();
-    });
-  });
-
-  describe("savePanoPovToLocalStorage", () => {
-    it("saves given data", () => {
-      savePanoPovToLocalStorage(3, 4);
-      expect(localStorage.getItem).toMatchSnapshot();
-      expect(localStorage.setItem).toMatchSnapshot();
-      expect(localStorage.removeItem).toMatchSnapshot();
-    });
-  });
-
-  describe("clearGameInfoFromLocalStorage", () => {
-    it("clears data", () => {
-      clearGameInfoFromLocalStorage();
-      expect(localStorage.getItem).toMatchSnapshot();
-      expect(localStorage.setItem).toMatchSnapshot();
-      expect(localStorage.removeItem).toMatchSnapshot();
-    });
-  });
-
-  describe("clearRoundInfoFromLocalStorage", () => {
-    it("clears data", () => {
-      clearRoundInfoFromLocalStorage();
-      expect(localStorage.getItem).toMatchSnapshot();
-      expect(localStorage.setItem).toMatchSnapshot();
-      expect(localStorage.removeItem).toMatchSnapshot();
-    });
-  });
-
-  describe("getInfoFromLocalStorage", () => {
-    it("gets data", () => {
-      const data = {
-        [localStorageGameId]: "test-game-id",
-        [localStoragePlayerName]: "test-player",
-        [localStoragePlayerId]: "test-player-id",
-        [localStorageTimer]: "300",
-        [localStoragePanoLat]: "test-lat",
-        [localStoragePanoLng]: "test-lng",
-        [localStoragePanoHeading]: "test-heading",
-        [localStoragePanoPitch]: "test-pitch",
-      };
-      localStorage.getItem.mockImplementation(key => data[key] ?? null);
-
-      expect(getInfoFromLocalStorage()).toMatchSnapshot();
-      expect(localStorage.getItem).toMatchSnapshot();
-      expect(localStorage.setItem).toMatchSnapshot();
-      expect(localStorage.removeItem).toMatchSnapshot();
-    });
-    it("handles bad/missing extra data", () => {
-      const data = {
-        [localStorageGameId]: "test-game-id",
-        [localStoragePlayerName]: "test-player",
-        [localStoragePlayerId]: "test-player-id",
-        [localStoragePanoLng]: "test-lng",
-        [localStoragePanoPitch]: "test-pitch",
-      };
-      localStorage.getItem.mockImplementation(key => data[key] ?? null);
-
-      expect(getInfoFromLocalStorage()).toMatchSnapshot();
-      expect(localStorage.getItem).toMatchSnapshot();
-      expect(localStorage.setItem).toMatchSnapshot();
-      expect(localStorage.removeItem).toMatchSnapshot();
-    });
-  });
-});

+ 0 - 38
client/src/tests/markers.test.js

@@ -1,38 +0,0 @@
-import {
-  makeFlagMarker,
-  makeLine,
-  makeQuestionMarker,
-} from "../hooks/useMarkersFromGuesses/markers";
-
-describe("markers", () => {
-  describe("makeLine", () => {
-    it("makes a line", () => {
-      const result = makeLine("p1", "p2", "map", "color");
-      expect(result).toMatchSnapshot();
-    });
-  });
-
-  describe("makeQuestionMarker", () => {
-    it("makes a question marker", () => {
-      const result = makeQuestionMarker(
-        "map",
-        { lat: "lat", lng: "lng" },
-        "title",
-        "color"
-      );
-      expect(result).toMatchSnapshot();
-      result.listeners.get("click")[0]();
-      expect(global.window.open).toHaveBeenCalledWith(
-        "https://www.google.com/maps?hl=en&q=+lat,+lng",
-        "_blank"
-      );
-    });
-  });
-
-  describe("makeFlagMarker", () => {
-    it("makes a flag marker", () => {
-      const result = makeFlagMarker("map", { lat: "lat", lng: "lng" });
-      expect(result).toMatchSnapshot();
-    });
-  });
-});

+ 0 - 74
client/src/tests/store.test.js

@@ -1,74 +0,0 @@
-import create from "../store";
-
-jest.mock("react");
-
-import { useEffect, useState } from "react";
-
-describe("Store Library", () => {
-  it("creates a store", () => {
-    let v;
-    useState.mockImplementation(fn => {
-      v = fn();
-      return [
-        v,
-        x => {
-          v = x;
-        },
-      ];
-    });
-
-    let unsub = null;
-    useEffect.mockImplementation(fn => {
-      if (unsub) {
-        unsub();
-      }
-      unsub = fn();
-    });
-
-    const [hooks, actions, watch] = create(store => ({
-      counter: 0,
-      increment: () => {
-        store.counter++;
-      },
-      changeCounter: counter => store({ counter }),
-      doInvalid: () => {
-        store.invalidKey = 7;
-      },
-
-      getReflectedKeys: () => Reflect.ownKeys(store),
-    }));
-
-    const changes = [];
-    watch.onChange((...args) => {
-      changes.push(args);
-    });
-    const calls = [];
-    watch.onCall((...args) => {
-      calls.push(args);
-    });
-
-    expect(hooks.useCounter).toBeInstanceOf(Function);
-    expect(actions.increment).toBeInstanceOf(Function);
-    expect(actions.changeCounter).toBeInstanceOf(Function);
-    expect(watch.onChange).toBeInstanceOf(Function);
-    expect(watch.onCall).toBeInstanceOf(Function);
-    expect(watch.setGlobal).toBeInstanceOf(Function);
-
-    expect(hooks.useCounter(() => true)).toBe(0);
-    actions.increment();
-    expect(hooks.useCounter()).toBe(1);
-    actions.changeCounter(x => x * 3);
-    expect(hooks.useCounter()).toBe(3);
-    actions.changeCounter(10);
-    expect(hooks.useCounter()).toBe(10);
-
-    expect(actions.getReflectedKeys()).toMatchSnapshot();
-
-    expect(actions.doInvalid).toThrow();
-
-    expect(changes).toMatchSnapshot();
-    expect(calls).toMatchSnapshot();
-    watch.setGlobal("testing-store");
-    expect(window["testing-store"]).toBeDefined();
-  });
-});

+ 100 - 5
client/yarn.lock

@@ -1017,7 +1017,7 @@
     core-js-pure "^3.20.2"
     regenerator-runtime "^0.13.4"
 
-"@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7":
+"@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
   version "7.17.9"
   resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.9.tgz#d19fbf802d01a8cb6cf053a64e472d42c434ba72"
   integrity sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==
@@ -1606,6 +1606,21 @@
     lz-string "^1.4.4"
     pretty-format "^27.0.2"
 
+"@testing-library/jest-dom@^5.16.4":
+  version "5.16.4"
+  resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.4.tgz#938302d7b8b483963a3ae821f1c0808f872245cd"
+  integrity sha512-Gy+IoFutbMQcky0k+bqqumXZ1cTGswLsFqmNLzNdSKkU9KGV2u9oXhukCbbJ9/LRPKiqwxEE8VpV/+YZlfkPUA==
+  dependencies:
+    "@babel/runtime" "^7.9.2"
+    "@types/testing-library__jest-dom" "^5.9.1"
+    aria-query "^5.0.0"
+    chalk "^3.0.0"
+    css "^3.0.0"
+    css.escape "^1.5.1"
+    dom-accessibility-api "^0.5.6"
+    lodash "^4.17.15"
+    redent "^3.0.0"
+
 "@testing-library/react@^13.0.0":
   version "13.0.0"
   resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-13.0.0.tgz#8cdaf4667c6c2b082eb0513731551e9db784e8bc"
@@ -1804,6 +1819,14 @@
   dependencies:
     "@types/istanbul-lib-report" "*"
 
+"@types/jest@*":
+  version "27.4.1"
+  resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.4.1.tgz#185cbe2926eaaf9662d340cc02e548ce9e11ab6d"
+  integrity sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==
+  dependencies:
+    jest-matcher-utils "^27.0.0"
+    pretty-format "^27.0.0"
+
 "@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
   version "7.0.11"
   resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
@@ -1914,6 +1937,13 @@
   resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c"
   integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==
 
+"@types/testing-library__jest-dom@^5.9.1":
+  version "5.14.3"
+  resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.3.tgz#ee6c7ffe9f8595882ee7bda8af33ae7b8789ef17"
+  integrity sha512-oKZe+Mf4ioWlMuzVBaXQ9WDnEm1+umLx0InILg+yvZVBBDmzV5KfZyLrCvadtWcx8+916jLmHafcmqqffl+iIw==
+  dependencies:
+    "@types/jest" "*"
+
 "@types/trusted-types@^2.0.2":
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.2.tgz#fc25ad9943bcac11cceb8168db4f275e0e72e756"
@@ -2435,6 +2465,11 @@ at-least-node@^1.0.0:
   resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
   integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
 
+atob@^2.1.2:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
+  integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
+
 autoprefixer@^10.4.4:
   version "10.4.4"
   resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.4.tgz#3e85a245b32da876a893d3ac2ea19f01e7ea5a1e"
@@ -2789,6 +2824,14 @@ chalk@^2.0.0, chalk@^2.4.1:
     escape-string-regexp "^1.0.5"
     supports-color "^5.3.0"
 
+chalk@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4"
+  integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==
+  dependencies:
+    ansi-styles "^4.1.0"
+    supports-color "^7.1.0"
+
 chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.2:
   version "4.1.2"
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
@@ -3191,6 +3234,20 @@ css-what@^6.0.1:
   resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4"
   integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==
 
+css.escape@^1.5.1:
+  version "1.5.1"
+  resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb"
+  integrity sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s=
+
+css@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/css/-/css-3.0.0.tgz#4447a4d58fdd03367c516ca9f64ae365cee4aa5d"
+  integrity sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==
+  dependencies:
+    inherits "^2.0.4"
+    source-map "^0.6.1"
+    source-map-resolve "^0.6.0"
+
 cssdb@^6.5.0:
   version "6.5.0"
   resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-6.5.0.tgz#61264b71f29c834f09b59cb3e5b43c8226590122"
@@ -3319,6 +3376,11 @@ decimal.js@^10.2.1:
   resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783"
   integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==
 
+decode-uri-component@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
+  integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
+
 dedent@^0.7.0:
   version "0.7.0"
   resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
@@ -3458,7 +3520,7 @@ doctrine@^3.0.0:
   dependencies:
     esutils "^2.0.2"
 
-dom-accessibility-api@^0.5.9:
+dom-accessibility-api@^0.5.6, dom-accessibility-api@^0.5.9:
   version "0.5.13"
   resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.13.tgz#102ee5f25eacce09bdf1cfa5a298f86da473be4b"
   integrity sha512-R305kwb5CcMDIpSHUnLyIAp7SrSPBx6F0VfQFB3M75xVMHhXJJIdePYgbPPh1o57vCHNu5QztokWUPsLjWzFqw==
@@ -4692,6 +4754,11 @@ imurmurhash@^0.1.4:
   resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
   integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
 
+indent-string@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
+  integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
+
 inflight@^1.0.4:
   version "1.0.6"
   resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
@@ -4700,7 +4767,7 @@ inflight@^1.0.4:
     once "^1.3.0"
     wrappy "1"
 
-inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3:
+inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3:
   version "2.0.4"
   resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
   integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
@@ -5165,7 +5232,7 @@ jest-leak-detector@^27.5.1:
     jest-get-type "^27.5.1"
     pretty-format "^27.5.1"
 
-jest-matcher-utils@^27.5.1:
+jest-matcher-utils@^27.0.0, jest-matcher-utils@^27.5.1:
   version "27.5.1"
   resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab"
   integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==
@@ -5787,6 +5854,11 @@ mimic-fn@^2.1.0:
   resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
   integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
 
+min-indent@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
+  integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==
+
 mini-css-extract-plugin@^2.4.5:
   version "2.6.0"
   resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.0.tgz#578aebc7fc14d32c0ad304c2c34f08af44673f5e"
@@ -6834,7 +6906,7 @@ pretty-error@^4.0.0:
     lodash "^4.17.20"
     renderkid "^3.0.0"
 
-pretty-format@^27.0.2, pretty-format@^27.5.1:
+pretty-format@^27.0.0, pretty-format@^27.0.2, pretty-format@^27.5.1:
   version "27.5.1"
   resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e"
   integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==
@@ -7124,6 +7196,14 @@ recursive-readdir@^2.2.2:
   dependencies:
     minimatch "3.0.4"
 
+redent@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f"
+  integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==
+  dependencies:
+    indent-string "^4.0.0"
+    strip-indent "^3.0.0"
+
 regenerate-unicode-properties@^10.0.1:
   version "10.0.1"
   resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz#7f442732aa7934a3740c779bb9b3340dccc1fb56"
@@ -7565,6 +7645,14 @@ source-map-loader@^3.0.0:
     iconv-lite "^0.6.3"
     source-map-js "^1.0.1"
 
+source-map-resolve@^0.6.0:
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.6.0.tgz#3d9df87e236b53f16d01e58150fc7711138e5ed2"
+  integrity sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==
+  dependencies:
+    atob "^2.1.2"
+    decode-uri-component "^0.2.0"
+
 source-map-support@^0.5.6, source-map-support@~0.5.20:
   version "0.5.21"
   resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
@@ -7767,6 +7855,13 @@ strip-final-newline@^2.0.0:
   resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
   integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
 
+strip-indent@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001"
+  integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==
+  dependencies:
+    min-indent "^1.0.0"
+
 strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
   version "3.1.1"
   resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"