Browse Source

Tests for GameSummary

Kirk Trombley 4 years ago
parent
commit
f59e8ba449

+ 7 - 1
client/src/setupTests.js

@@ -17,4 +17,10 @@ global.google = {
       constructor() {}
     }
   },
-};
+};
+
+global.window = {
+  location: {
+    href: "http://test-url-base/",
+  }
+}

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

@@ -0,0 +1,35 @@
+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();
+  });
+});

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

@@ -0,0 +1,40 @@
+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");
+  });
+});

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

@@ -0,0 +1,123 @@
+import React from "react";
+import { shallow } from "enzyme";
+import ScoreBoard, {
+  PlayerScoreTile,
+} from "../components/screens/GameSummary/ScoreBoard/ScoreBoard";
+
+jest.mock("../domain/flagLookup");
+
+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", () => {
+    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 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={{
+            3: { score: 20, country: "test-country" },
+            1: { score: 50, country: "test-country" },
+            2: { score: 150, 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();
+    });
+  });
+});

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

@@ -0,0 +1,171 @@
+import React from "react";
+import { shallow } from "enzyme";
+import SummaryMap, {
+  RoundSelect,
+} from "../components/screens/GameSummary/SummaryMap/SummaryMap";
+
+jest.mock("../domain/flagLookup");
+jest.mock("../hooks/useGameInfo");
+jest.mock("../hooks/useMap");
+jest.mock("../hooks/useMapBounds");
+jest.mock("../hooks/useMarkersFromGuesses");
+
+import useMarkersFromGuesses from "../hooks/useMarkersFromGuesses";
+import useMap from "../hooks/useMap";
+import useMapBounds from "../hooks/useMapBounds";
+import { useGameConfig } from "../hooks/useGameInfo";
+
+describe("SummaryMap", () => {
+  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"
+    );
+  });
+
+  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
+          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("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");
+    });
+  });
+});

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

@@ -0,0 +1,35 @@
+// 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 />`;

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

@@ -0,0 +1,24 @@
+// 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]}
+  />
+</div>
+`;

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

@@ -0,0 +1,520 @@
+// 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 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"
+      >
+        flag
+      </span>
+    </div>
+    <div
+      className="round"
+      key="2"
+    >
+      <span
+        className="score"
+      >
+        Round 
+        2
+        : 
+        150
+      </span>
+      <span
+        className="flag"
+      >
+        flag
+      </span>
+    </div>
+    <div
+      className="round"
+      key="3"
+    >
+      <span
+        className="score"
+      >
+        Round 
+        3
+        : 
+        20
+      </span>
+      <span
+        className="flag"
+      >
+        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"
+      >
+        flag
+      </span>
+    </div>
+    <div
+      className="round"
+      key="3"
+    >
+      <span
+        className="score"
+      >
+        Round 
+        3
+        : 
+        20
+      </span>
+      <span
+        className="flag"
+      >
+        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"
+      >
+        flag
+      </span>
+    </div>
+    <div
+      className="round"
+      key="2"
+    >
+      <span
+        className="score"
+      >
+        Round 
+        2
+        : 
+        0
+      </span>
+      <span
+        className="flag"
+      >
+        flag
+      </span>
+    </div>
+    <div
+      className="round"
+      key="3"
+    >
+      <span
+        className="score"
+      >
+        Round 
+        3
+        : 
+        20
+      </span>
+      <span
+        className="flag"
+      >
+        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"
+      >
+        flag
+      </span>
+    </div>
+    <div
+      className="round"
+      key="2"
+    >
+      <span
+        className="score"
+      >
+        Round 
+        2
+        : 
+        150
+      </span>
+      <span
+        className="flag"
+      >
+        flag
+      </span>
+    </div>
+    <div
+      className="round"
+      key="3"
+    >
+      <span
+        className="score"
+      >
+        Round 
+        3
+        : 
+        20
+      </span>
+      <span
+        className="flag"
+      >
+        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}
+  />
+  <PlayerScoreTile
+    key="Name1"
+    name="Name1"
+    totalScore={5000}
+  />
+</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}
+  />
+  <PlayerScoreTile
+    key="Name1"
+    name="Name1"
+    totalScore={5000}
+  />
+  <PlayerScoreTile
+    key="Name4"
+    name="Name4"
+    totalScore={5000}
+  />
+  <PlayerScoreTile
+    key="Name3"
+    name="Name3"
+    totalScore={1000}
+  />
+</div>
+`;

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

@@ -0,0 +1,132 @@
+// 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"
+  >
+    1
+     - 
+  </div>
+  <div
+    className="tab "
+    key="2"
+    onClick={[Function]}
+    onKeyDown={[Function]}
+    role="button"
+    tabIndex="0"
+  >
+    2
+     - 
+  </div>
+  <div
+    className="tab "
+    key="3"
+    onClick={[Function]}
+    onKeyDown={[Function]}
+    role="button"
+    tabIndex="0"
+  >
+    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"
+  >
+    1
+     - 
+  </div>
+  <div
+    className="tab "
+    key="2"
+    onClick={[Function]}
+    onKeyDown={[Function]}
+    role="button"
+    tabIndex="0"
+  >
+    2
+     - 
+  </div>
+  <div
+    className="tab "
+    key="3"
+    onClick={[Function]}
+    onKeyDown={[Function]}
+    role="button"
+    tabIndex="0"
+  >
+    3
+     - 
+  </div>
+  <div
+    className="tab"
+    onClick={[Function]}
+    onKeyDown={[Function]}
+    role="button"
+    tabIndex="0"
+  >
+    X
+  </div>
+</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>
+`;