-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9ffe4f5
commit 6ae6071
Showing
2 changed files
with
338 additions
and
0 deletions.
There are no files selected for viewing
271 changes: 271 additions & 0 deletions
271
packages/frontend/web-ui/src/game/hooks/useGame.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,271 @@ | ||
import { afterAll, beforeAll, describe, expect, it, jest } from '@jest/globals'; | ||
|
||
jest.mock('../../common/hooks/useRedirectUnauthorized'); | ||
jest.mock('../../common/hooks/useUrlLikeLocation'); | ||
jest.mock('../../user/hooks/useGetUserMe'); | ||
jest.mock('../helpers/getGameSlotIndex'); | ||
jest.mock('./useGameCards'); | ||
jest.mock('./useGetGamesV1GameId'); | ||
jest.mock('./useGetGamesV1GameIdSlotsSlotIdCards'); | ||
|
||
import { models as apiModels } from '@cornie-js/api-models'; | ||
import { renderHook, RenderHookResult } from '@testing-library/react'; | ||
|
||
import { useRedirectUnauthorized } from '../../common/hooks/useRedirectUnauthorized'; | ||
import { useUrlLikeLocation } from '../../common/hooks/useUrlLikeLocation'; | ||
import { UrlLikeLocation } from '../../common/models/UrlLikeLocation'; | ||
import { useGetUserMe } from '../../user/hooks/useGetUserMe'; | ||
import { getGameSlotIndex } from '../helpers/getGameSlotIndex'; | ||
import { useGame, UseGameResult } from './useGame'; | ||
import { useGameCards, UseGameCardsResult } from './useGameCards'; | ||
import { useGetGamesV1GameId } from './useGetGamesV1GameId'; | ||
import { useGetGamesV1GameIdSlotsSlotIdCards } from './useGetGamesV1GameIdSlotsSlotIdCards'; | ||
|
||
describe(useGame.name, () => { | ||
describe('when called, and queries return null result', () => { | ||
let gameIdFixture: string; | ||
let urlLikeLocationFixture: UrlLikeLocation; | ||
let useGameCardsResultFixture: UseGameCardsResult; | ||
|
||
let renderResult: RenderHookResult<UseGameResult, unknown>; | ||
|
||
beforeAll(() => { | ||
gameIdFixture = 'game-id-fixture'; | ||
|
||
urlLikeLocationFixture = { | ||
pathname: '/path', | ||
searchParams: new URLSearchParams(`?gameId=${gameIdFixture}`), | ||
} as Partial<UrlLikeLocation> as UrlLikeLocation; | ||
|
||
useGameCardsResultFixture = { | ||
cards: [], | ||
hasNext: false, | ||
hasPrevious: false, | ||
setNext: jest.fn(), | ||
setPrevious: jest.fn(), | ||
}; | ||
|
||
( | ||
useUrlLikeLocation as jest.Mock<typeof useUrlLikeLocation> | ||
).mockReturnValueOnce(urlLikeLocationFixture); | ||
|
||
(useGetUserMe as jest.Mock<typeof useGetUserMe>).mockReturnValueOnce({ | ||
result: null, | ||
}); | ||
|
||
( | ||
useGetGamesV1GameId as jest.Mock<typeof useGetGamesV1GameId> | ||
).mockReturnValueOnce({ result: null }); | ||
|
||
( | ||
useGetGamesV1GameIdSlotsSlotIdCards as jest.Mock< | ||
typeof useGetGamesV1GameIdSlotsSlotIdCards | ||
> | ||
).mockReturnValueOnce({ result: null }); | ||
|
||
(useGameCards as jest.Mock<typeof useGameCards>).mockReturnValueOnce( | ||
useGameCardsResultFixture, | ||
); | ||
|
||
renderResult = renderHook(() => useGame()); | ||
}); | ||
|
||
afterAll(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
it('should call useRedirectUnauthorized()', () => { | ||
expect(useRedirectUnauthorized).toHaveBeenCalledTimes(1); | ||
expect(useRedirectUnauthorized).toHaveBeenCalledWith(); | ||
}); | ||
|
||
it('should call useGetUserMe()', () => { | ||
expect(useGetUserMe).toHaveBeenCalledTimes(1); | ||
expect(useGetUserMe).toHaveBeenCalledWith(); | ||
}); | ||
|
||
it('should call useGetGamesV1GameId()', () => { | ||
expect(useGetGamesV1GameId).toHaveBeenCalledTimes(1); | ||
expect(useGetGamesV1GameId).toHaveBeenCalledWith(gameIdFixture); | ||
}); | ||
|
||
it('should not call getGameSlotIndex()', () => { | ||
expect(getGameSlotIndex).not.toHaveBeenCalled(); | ||
}); | ||
|
||
it('should call useGetGamesV1GameIdSlotsSlotIdCards()', () => { | ||
expect(useGetGamesV1GameIdSlotsSlotIdCards).toHaveBeenCalledTimes(1); | ||
expect(useGetGamesV1GameIdSlotsSlotIdCards).toHaveBeenCalledWith( | ||
gameIdFixture, | ||
null, | ||
); | ||
}); | ||
|
||
it('should call useGameCards()', () => { | ||
expect(useGameCards).toHaveBeenCalledTimes(1); | ||
expect(useGameCards).toHaveBeenCalledWith([]); | ||
}); | ||
|
||
it('should retuen expected result', () => { | ||
const expected: UseGameResult = { | ||
currentCard: undefined, | ||
game: undefined, | ||
isPending: true, | ||
useGameCardsResult: useGameCardsResultFixture, | ||
}; | ||
|
||
expect(renderResult.result.current).toStrictEqual(expected); | ||
}); | ||
}); | ||
|
||
describe('when called, and queries return non null results', () => { | ||
let gameCardsFixture: apiModels.CardArrayV1; | ||
let gameFixture: apiModels.ActiveGameV1; | ||
let gameIdFixture: string; | ||
let gameSlotIndexFixture: string; | ||
let urlLikeLocationFixture: UrlLikeLocation; | ||
let userFixture: apiModels.UserV1; | ||
let useGameCardsResultFixture: UseGameCardsResult; | ||
|
||
let renderResult: RenderHookResult<UseGameResult, unknown>; | ||
|
||
beforeAll(() => { | ||
gameCardsFixture = [ | ||
{ | ||
kind: 'wildDraw4', | ||
}, | ||
]; | ||
|
||
gameFixture = { | ||
id: 'game-id-fixture', | ||
isPublic: true, | ||
state: { | ||
currentCard: { | ||
kind: 'wild', | ||
}, | ||
currentColor: 'blue', | ||
currentDirection: 'clockwise', | ||
currentPlayingSlotIndex: 0, | ||
currentTurnCardsDrawn: false, | ||
currentTurnCardsPlayed: false, | ||
drawCount: 0, | ||
lastEventId: 'last-event-id-fixture', | ||
slots: [], | ||
status: 'active', | ||
}, | ||
}; | ||
|
||
gameSlotIndexFixture = '0'; | ||
|
||
userFixture = { | ||
active: true, | ||
id: 'user-id-fixture', | ||
name: 'user-name-fixture', | ||
}; | ||
|
||
gameIdFixture = gameFixture.id; | ||
|
||
urlLikeLocationFixture = { | ||
pathname: '/path', | ||
searchParams: new URLSearchParams(`?gameId=${gameIdFixture}`), | ||
} as Partial<UrlLikeLocation> as UrlLikeLocation; | ||
|
||
useGameCardsResultFixture = { | ||
cards: [], | ||
hasNext: false, | ||
hasPrevious: false, | ||
setNext: jest.fn(), | ||
setPrevious: jest.fn(), | ||
}; | ||
|
||
( | ||
useUrlLikeLocation as jest.Mock<typeof useUrlLikeLocation> | ||
).mockReturnValueOnce(urlLikeLocationFixture); | ||
|
||
(useGetUserMe as jest.Mock<typeof useGetUserMe>).mockReturnValueOnce({ | ||
result: { | ||
isRight: true, | ||
value: userFixture, | ||
}, | ||
}); | ||
|
||
( | ||
useGetGamesV1GameId as jest.Mock<typeof useGetGamesV1GameId> | ||
).mockReturnValueOnce({ | ||
result: { | ||
isRight: true, | ||
value: gameFixture, | ||
}, | ||
}); | ||
|
||
( | ||
useGetGamesV1GameIdSlotsSlotIdCards as jest.Mock< | ||
typeof useGetGamesV1GameIdSlotsSlotIdCards | ||
> | ||
).mockReturnValueOnce({ | ||
result: { | ||
isRight: true, | ||
value: gameCardsFixture, | ||
}, | ||
}); | ||
|
||
( | ||
getGameSlotIndex as jest.Mock<typeof getGameSlotIndex> | ||
).mockReturnValueOnce(gameSlotIndexFixture); | ||
|
||
(useGameCards as jest.Mock<typeof useGameCards>).mockReturnValueOnce( | ||
useGameCardsResultFixture, | ||
); | ||
|
||
renderResult = renderHook(() => useGame()); | ||
}); | ||
|
||
afterAll(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
it('should call useRedirectUnauthorized()', () => { | ||
expect(useRedirectUnauthorized).toHaveBeenCalledTimes(1); | ||
expect(useRedirectUnauthorized).toHaveBeenCalledWith(); | ||
}); | ||
|
||
it('should call useGetUserMe()', () => { | ||
expect(useGetUserMe).toHaveBeenCalledTimes(1); | ||
expect(useGetUserMe).toHaveBeenCalledWith(); | ||
}); | ||
|
||
it('should call useGetGamesV1GameId()', () => { | ||
expect(useGetGamesV1GameId).toHaveBeenCalledTimes(1); | ||
expect(useGetGamesV1GameId).toHaveBeenCalledWith(gameIdFixture); | ||
}); | ||
|
||
it('should call getGameSlotIndex()', () => { | ||
expect(getGameSlotIndex).toHaveBeenCalledTimes(1); | ||
expect(getGameSlotIndex).toHaveBeenCalledWith(gameFixture, userFixture); | ||
}); | ||
|
||
it('should call useGetGamesV1GameIdSlotsSlotIdCards()', () => { | ||
expect(useGetGamesV1GameIdSlotsSlotIdCards).toHaveBeenCalledTimes(1); | ||
expect(useGetGamesV1GameIdSlotsSlotIdCards).toHaveBeenCalledWith( | ||
gameIdFixture, | ||
gameSlotIndexFixture, | ||
); | ||
}); | ||
|
||
it('should call useGameCards()', () => { | ||
expect(useGameCards).toHaveBeenCalledTimes(1); | ||
expect(useGameCards).toHaveBeenCalledWith(gameCardsFixture); | ||
}); | ||
|
||
it('should retuen expected result', () => { | ||
const expected: UseGameResult = { | ||
currentCard: gameFixture.state.currentCard, | ||
game: gameFixture, | ||
isPending: false, | ||
useGameCardsResult: useGameCardsResultFixture, | ||
}; | ||
|
||
expect(renderResult.result.current).toStrictEqual(expected); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import { models as apiModels } from '@cornie-js/api-models'; | ||
|
||
import { useRedirectUnauthorized } from '../../common/hooks/useRedirectUnauthorized'; | ||
import { useUrlLikeLocation } from '../../common/hooks/useUrlLikeLocation'; | ||
import { UrlLikeLocation } from '../../common/models/UrlLikeLocation'; | ||
import { useGetUserMe } from '../../user/hooks/useGetUserMe'; | ||
import { getGameSlotIndex } from '../helpers/getGameSlotIndex'; | ||
import { useGameCards, UseGameCardsResult } from './useGameCards'; | ||
import { useGetGamesV1GameId } from './useGetGamesV1GameId'; | ||
import { useGetGamesV1GameIdSlotsSlotIdCards } from './useGetGamesV1GameIdSlotsSlotIdCards'; | ||
|
||
export interface UseGameResult { | ||
currentCard: apiModels.CardV1 | undefined; | ||
game: apiModels.GameV1 | undefined; | ||
isPending: boolean; | ||
useGameCardsResult: UseGameCardsResult; | ||
} | ||
|
||
function getGameCurrentCard( | ||
game: apiModels.GameV1 | undefined, | ||
): apiModels.CardV1 | undefined { | ||
return game?.state.status === 'active' ? game.state.currentCard : undefined; | ||
} | ||
|
||
export const useGame = (): UseGameResult => { | ||
useRedirectUnauthorized(); | ||
|
||
const url: UrlLikeLocation = useUrlLikeLocation(); | ||
const gameIdParam: string | null = url.searchParams.get('gameId'); | ||
|
||
const { result: usersV1MeResult } = useGetUserMe(); | ||
|
||
const { result: gamesV1GameIdResult } = useGetGamesV1GameId(gameIdParam); | ||
|
||
const game: apiModels.GameV1 | undefined = | ||
gamesV1GameIdResult?.isRight === true | ||
? gamesV1GameIdResult.value | ||
: undefined; | ||
|
||
const currentCard: apiModels.CardV1 | undefined = getGameCurrentCard(game); | ||
|
||
const gameSlotIndexParam: string | null = | ||
usersV1MeResult?.isRight === true | ||
? getGameSlotIndex(game, usersV1MeResult.value) | ||
: null; | ||
|
||
const { result: gamesV1GameIdSlotsSlotIdCardsResult } = | ||
useGetGamesV1GameIdSlotsSlotIdCards(gameIdParam, gameSlotIndexParam); | ||
|
||
const isPending = | ||
gamesV1GameIdResult === null || | ||
gamesV1GameIdSlotsSlotIdCardsResult === null; | ||
|
||
const gameCards: apiModels.CardArrayV1 = | ||
gamesV1GameIdSlotsSlotIdCardsResult?.isRight === true | ||
? gamesV1GameIdSlotsSlotIdCardsResult.value | ||
: []; | ||
|
||
const useGameCardsResult: UseGameCardsResult = useGameCards(gameCards); | ||
|
||
return { | ||
currentCard, | ||
game, | ||
isPending, | ||
useGameCardsResult, | ||
}; | ||
}; |