Skip to content

Commit

Permalink
Merge pull request #4 from lineville/single-player
Browse files Browse the repository at this point in the history
Single player
  • Loading branch information
lineville authored Apr 1, 2024
2 parents 005f641 + c1a9f10 commit fe978bc
Show file tree
Hide file tree
Showing 48 changed files with 144 additions and 43 deletions.
8 changes: 4 additions & 4 deletions __tests__/Game.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import "@testing-library/jest-dom";
import { fireEvent, render, screen } from "@testing-library/react";
import { render, screen } from "@testing-library/react";
import Game from "@/components/Game";
import React from "react";
import { useBreakpointValue } from "@chakra-ui/react";
Expand Down Expand Up @@ -29,7 +29,7 @@ jest.mock("next/navigation", () => ({
query: "",
asPath: "/",
}),
usePathname: jest.fn(() => `/game/${mockGameId}`),
usePathname: jest.fn(() => `/game/pixar/${mockGameId}`),
}));

jest.mock("@/hooks/useSocket");
Expand Down Expand Up @@ -99,8 +99,8 @@ describe("Game", () => {
const gameContainer = screen.getByTestId("game-container");
expect(gameContainer).toBeInTheDocument();

const hamburgerButton = screen.getByLabelText("Open drawer");
expect(hamburgerButton).toBeInTheDocument();
const chatButton = screen.getByLabelText("Open drawer");
expect(chatButton).toBeInTheDocument();
});

it("renders error message when there is an error", () => {
Expand Down
5 changes: 3 additions & 2 deletions __tests__/GuessCharacterModal.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import "@testing-library/jest-dom";
import { render, screen } from "@testing-library/react";
import GuessCharacterModal from "@/components/GuessCharacterModal";
import { act } from "react-dom/test-utils";
import { GameType } from "@/lib/gameType";

const mockOnGuess = jest.fn();
const mockOnClose = jest.fn();
Expand All @@ -25,7 +26,7 @@ describe("GuessCharacterModal", () => {
onClose={mockOnClose}
onGuess={mockOnGuess}
remainingCharacters={characters}
gameType="default"
gameType={GameType.Pixar}
/>
);

Expand All @@ -51,7 +52,7 @@ describe("GuessCharacterModal", () => {
onClose={mockOnClose}
onGuess={mockOnGuess}
remainingCharacters={characters}
gameType="default"
gameType={GameType.Pixar}
/>
);

Expand Down
19 changes: 16 additions & 3 deletions __tests__/Home.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { render, screen, fireEvent } from "@testing-library/react";
import Home from "@/app/page";
import Header from "@/components/Header";
import { Providers } from "@/app/providers";
import { formatMenuItem } from "@/lib/menuHelpers";

const mockPush = jest.fn();
const mockGameId = "123e4567-e89b-12d3-a456-426614174000";
Expand Down Expand Up @@ -45,7 +46,7 @@ describe("Home", () => {
</Providers>
);

const heading = screen.getByText("New Game");
const heading = screen.getByText("Play");
expect(heading).toBeInTheDocument();
});

Expand All @@ -56,10 +57,22 @@ describe("Home", () => {
</Providers>
);

const button = screen.getByRole("button", { name: /New Game/i });
const button = screen.getByText("Play");
fireEvent.click(button);

expect(mockPush).toHaveBeenCalledTimes(1);
expect(mockPush).toHaveBeenCalledWith(`/game/default/${mockGameId}`);
expect(mockPush).toHaveBeenCalledWith(`/game/pixar/${mockGameId}`);
});
});

describe("formatMenuItem", () => {
it("formats a string correctly", () => {
const formatted = formatMenuItem("Pixar");
expect(formatted).toEqual("Pixar");
});

it("formats a string correctly", () => {
const formatted = formatMenuItem("single-player");
expect(formatted).toEqual("Single Player");
});
});
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
119 changes: 90 additions & 29 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,28 @@ import {
Button,
useBreakpointValue,
Box,
HStack,
Text,
Menu,
MenuButton,
MenuItem,
MenuList,
Avatar,
} from "@chakra-ui/react";
import { ChevronDownIcon } from "@chakra-ui/icons";
import { ArrowRightIcon, ChevronDownIcon } from "@chakra-ui/icons";
import Instructions from "@/components/Instructions";
import GradientBackground from "@/components/GradientBackground";
import Header from "@/components/Header";
import { GameType } from "@/lib/gameType";
import { useState } from "react";
import { GameMode } from "@/lib/gameMode";
import { formatMenuItem, menuItemImage } from "@/lib/menuHelpers";

export default function Home() {
const router = useRouter();
const isMobile = useBreakpointValue({ base: true, md: false });
const [gameType, setGameType] = useState<GameType>("default");
const [gameType, setGameType] = useState<GameType>(GameType.Pixar);
const [gameMode, setGameMode] = useState<GameMode>(GameMode.MultiPlayer);

// Generate a new clientId and gameId
const createGame = () => {
Expand All @@ -46,34 +51,90 @@ export default function Home() {
<Box mb={isMobile ? 4 : 20}>
<Header title="Guess Who" />
</Box>
<Box mb={isMobile ? 4 : 30}>
<Button onClick={createGame} size="lg" colorScheme="teal">
New Game

<HStack spacing={4} mb={isMobile ? 4 : 30}>
<Box>
<Text fontSize="sm" mb={2}>
Game Mode:
</Text>
<Menu>
<MenuButton
as={Button}
rightIcon={<ChevronDownIcon />}
colorScheme="blue"
size="lg"
>
{formatMenuItem(gameMode)}
</MenuButton>
<MenuList
maxH="60vh"
overflowY="auto"
style={{ touchAction: "auto" }}
zIndex={2}
>
{(Object.values(GameMode) as GameMode[]).map(
(mode: GameMode, index) => (
<MenuItem key={index} onClick={() => setGameMode(mode)} isDisabled={mode === GameMode.SinglePlayer}>
<Box display="flex" alignItems="center">
<Text mr={2}>{mode === GameMode.SinglePlayer ? '🤖' : '👬'}</Text>
<Text>{formatMenuItem(mode)}</Text>
</Box>
</MenuItem>
)
)}
</MenuList>
</Menu>
</Box>
<Box>
<Text fontSize="sm" mb={2}>
Game Type:
</Text>
<Menu>
<MenuButton
as={Button}
rightIcon={<ChevronDownIcon />}
colorScheme="blue"
size="lg"
>
{formatMenuItem(gameType)}
</MenuButton>
<MenuList
maxH="60vh"
overflowY="auto"
style={{ touchAction: "auto" }}
zIndex={2}
>
{(Object.values(GameType) as GameType[]).map(
(type: GameType, index) => (
<MenuItem key={index} onClick={() => setGameType(type)}>
<Box display="flex" alignItems="center">
<Avatar
name="Tonto"
src={menuItemImage(type)}
size="xs"
mr="2"
/>
<Text>{formatMenuItem(type)}</Text>
</Box>
</MenuItem>
)
)}
</MenuList>
</Menu>
</Box>
<Button
onClick={createGame}
size="lg"
colorScheme="blue"
ml={2}
rightIcon={<ArrowRightIcon />}
mt={8}
>
Play
</Button>
</Box>
<Box mb={isMobile ? 4 : 30}>
<Menu>
<MenuButton as={Button} rightIcon={<ChevronDownIcon />}>
Game Type: {gameType}
</MenuButton>
<MenuList
maxH="60vh"
overflowY="auto"
style={{ touchAction: "auto" }}
zIndex={2}
>
{(["default", "super-heroes"] as GameType[]).map(
(type: GameType, index) => (
<MenuItem key={index} onClick={() => setGameType(type)}>
<Box display="flex" alignItems="center">
<Text>{type.toString()}</Text>
</Box>
</MenuItem>
)
)}
</MenuList>
</Menu>
</Box>
</HStack>

<Box mb={isMobile ? 4 : 30}></Box>

<Instructions />
</Flex>
Expand Down
4 changes: 2 additions & 2 deletions src/components/Game.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
} from "@chakra-ui/react";
import QuestionModal from "@/components/QuestionModal";
import AnswerModal from "@/components/AnswerModal";
import { ArrowLeftIcon, HamburgerIcon, StarIcon } from "@chakra-ui/icons";
import { ArrowLeftIcon, ChatIcon, StarIcon } from "@chakra-ui/icons";
import Dialogue from "@/components/Dialogue";
import GuessCharacterModal from "@/components/GuessCharacterModal";
import WinnerModal from "@/components/WinnerModal";
Expand Down Expand Up @@ -229,7 +229,7 @@ export default function Game({ clientId }: GameProps): JSX.Element {

{isMobile && (
<IconButton
icon={<HamburgerIcon />}
icon={<ChatIcon />}
onClick={openDrawer}
aria-label={"Open drawer"}
isRound={true}
Expand Down
4 changes: 4 additions & 0 deletions src/lib/gameMode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum GameMode {
SinglePlayer = "single-player",
MultiPlayer = "multi-player",
}
6 changes: 5 additions & 1 deletion src/lib/gameType.ts
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
export type GameType = "default" | "super-heroes" | "celebs";
export enum GameType {
Pixar = "pixar",
SuperHeroes = "super-heroes",
// TODO Add more
}
18 changes: 18 additions & 0 deletions src/lib/menuHelpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { GameType } from "./gameType";

export const formatMenuItem = (str: string): string => {
return str
.split("-")
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ");
};

export const menuItemImage = (gameType: GameType): string => {
switch (gameType) {
case GameType.Pixar:
return "/pixar/Tonto.png";
case GameType.SuperHeroes:
return "/super-heroes/Hulk.png";
}
return "/pixar/Tonto.png";
};
4 changes: 2 additions & 2 deletions src/lib/socket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ const URL =
export const socket = (
gameId: string,
clientId: string,
gameType: GameType = "default"
gameType: GameType = GameType.Pixar
) => {
return io(URL, {
path: "/clients/socketio/hubs/Hub",
query: { gameId: gameId, clientId: clientId, gameType: gameType },
query: { gameId: gameId, clientId: clientId, gameType: gameType.toString() },
});
};

0 comments on commit fe978bc

Please sign in to comment.