-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: add test for game_session, profile, search pages
- Loading branch information
Showing
6 changed files
with
466 additions
and
0 deletions.
There are no files selected for viewing
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,281 @@ | ||
import { test } from '@japa/runner' | ||
import { DateTime } from 'luxon' | ||
import { SessionStateEnum } from '#features/game_session/enums/session_state' | ||
import { GameSession, GameSessionId } from '#features/game_session/types/game_session' | ||
import User from '#models/user' | ||
import { CacheService } from '#services/cache/cache_service' | ||
import { BaseGameSessionPage } from '#tests/utils/base_pages/base_game_session_page' | ||
|
||
test.group('game_session_page', (group) => { | ||
group.each.teardown(async () => { | ||
const cache = new CacheService() | ||
await cache.flush() | ||
}) | ||
|
||
async function setupPlayer(email: string, username: string): Promise<User> { | ||
return await User.firstOrCreate({ email }, { username, providerId: 1, password: 'password' }) | ||
} | ||
|
||
async function setupSession( | ||
player1: User, | ||
player2: User, | ||
hintGiver = player1.id, | ||
turn = player1.id, | ||
startedAt = DateTime.now().toISO(), | ||
): Promise<GameSession> { | ||
const session = { | ||
player1: { id: player1.id, username: player1.username, elo: player1.elo, accepted: true, ready: true }, | ||
player2: { id: player2.id, username: player2.username, elo: player2.elo, accepted: true, ready: true }, | ||
wordsList: { hintGiver: [], guesser: [] }, | ||
sessionId: '9bb9871e-9da7-4193-a63c-66ef21687699' as GameSessionId, | ||
startedAt: startedAt, | ||
status: SessionStateEnum.READY, | ||
word: null, | ||
hintGiver: hintGiver, | ||
turn: turn, | ||
guessed: false, | ||
} | ||
await new CacheService().set('game:session:9bb9871e-9da7-4193-a63c-66ef21687699', JSON.stringify(session)) | ||
return session | ||
} | ||
|
||
test('check base parts of the page', async ({ visit, browserContext }) => { | ||
const player1 = await setupPlayer('[email protected]', 'test') | ||
const player2 = await setupPlayer('[email protected]', 'test2') | ||
|
||
await setupSession(player1, player2) | ||
|
||
await browserContext.loginAs(player1) | ||
|
||
const base = await visit(BaseGameSessionPage) | ||
|
||
const { page } = base | ||
|
||
await base.assertHasHeader() | ||
await base.assertHasFooter() | ||
|
||
const title = page.locator('h1', { hasText: 'Session' }) | ||
const playerText = page.locator('p', { hasText: `Player: ${player1.username}` }) | ||
const hintWordsTitle = page.locator('h2', { hasText: 'Hint Words' }) | ||
const guesserWordsTitle = page.locator('h2', { hasText: 'Guesser Words' }) | ||
const giveHintButton = page.locator('button', { hasText: 'Give a hint' }) | ||
|
||
await page.assertExists(title) | ||
await page.assertExists(playerText) | ||
await page.assertExists(hintWordsTitle) | ||
await page.assertExists(guesserWordsTitle) | ||
await page.assertExists(giveHintButton) | ||
}) | ||
|
||
// Need to find a way to fix flacky test | ||
test('copy session id button should copy the session id to the clipboard (can be flacky)', async ({ | ||
visit, | ||
browserContext, | ||
assert, | ||
}) => { | ||
const player1 = await setupPlayer('[email protected]', 'test') | ||
const player2 = await setupPlayer('[email protected]', 'test2') | ||
|
||
await setupSession(player1, player2) | ||
|
||
await browserContext.loginAs(player1) | ||
|
||
await browserContext.grantPermissions(['clipboard-write', 'clipboard-read']) | ||
|
||
const base = await visit(BaseGameSessionPage) | ||
const { page } = base | ||
|
||
const copySessionIdButton = page.getByRole('img', { name: 'Copy icon' }) | ||
|
||
await copySessionIdButton.click() | ||
|
||
const clipboardText = await page.evaluate(async () => { | ||
// @ts-ignore - TS doesn't know about clipboard API | ||
return await navigator.clipboard.readText() | ||
}) | ||
|
||
assert.equal(clipboardText, '9bb9871e-9da7-4193-a63c-66ef21687699') | ||
}) | ||
|
||
test('check if guesser page content is correct and guesser can submit a word', async ({ visit, browserContext }) => { | ||
const player1 = await setupPlayer('[email protected]', 'test') | ||
const player2 = await setupPlayer('[email protected]', 'test2') | ||
|
||
await setupSession(player1, player2, player1.id, player2.id) | ||
|
||
await browserContext.loginAs(player2) | ||
|
||
const base = await visit(BaseGameSessionPage) | ||
|
||
const { page } = base | ||
|
||
const guesserWordsTitle = page.locator('h2', { hasText: 'Guesser Words' }) | ||
const giveHintButton = page.locator('button', { hasText: 'Give a hint' }) | ||
const guessSubmitButton = page.locator('button', { hasText: 'Guess the word' }) | ||
const yourTurnText = page.locator('p', { hasText: "It's your turn to play" }) | ||
|
||
// need to wait for the page to load and state to update | ||
await page.waitForTimeout(1000) | ||
await page.assertNotExists(giveHintButton) | ||
await page.assertExists(guesserWordsTitle) | ||
await page.assertExists(guessSubmitButton) | ||
|
||
await page.assertExists(yourTurnText) | ||
|
||
const wordInput = page.getByRole('textbox') | ||
await page.assertExists(wordInput) | ||
|
||
/** | ||
* This part is commented out because SSE events with current package are not | ||
* supported in Playwright and the whole apps uses them to update the state | ||
* FIXME: Need to find a way to mock the SSE events or find a way to test it | ||
*/ | ||
|
||
// await wordInput.fill('WordTest') | ||
// await page.assertNotDisabled(guessSubmitButton) | ||
// await guessSubmitButton.click() | ||
// | ||
// const guesserWordContainer = page.getByTitle('Guesser Words list') | ||
// await page.assertExists(guesserWordContainer) | ||
// | ||
// const newWordText = await guesserWordContainer.allTextContents() | ||
// assert.include(newWordText, 'WordTest') | ||
}) | ||
|
||
test('check if hint giver page content is correct and hint giver can submit a hint', async ({ | ||
visit, | ||
browserContext, | ||
}) => { | ||
const player1 = await setupPlayer('[email protected]', 'test') | ||
const player2 = await setupPlayer('[email protected]', 'test2') | ||
|
||
await setupSession(player1, player2) | ||
|
||
await browserContext.loginAs(player1) | ||
|
||
const base = await visit(BaseGameSessionPage) | ||
|
||
const { page } = base | ||
|
||
const hintWordsTitle = page.locator('h2', { hasText: 'Hint Words' }) | ||
const giveHintButton = page.locator('button', { hasText: 'Give a hint' }) | ||
const guessSubmitButton = page.locator('button', { hasText: 'Guess the word' }) | ||
const yourTurnText = page.locator('p', { hasText: "It's your turn to play" }) | ||
//const opponentTurnText = page.locator('p', { hasText: 'Wait for the opponent to play' }) | ||
|
||
// need to wait for the page to load and state to update | ||
await page.waitForTimeout(1000) | ||
await page.assertExists(giveHintButton) | ||
await page.assertExists(hintWordsTitle) | ||
await page.assertNotExists(guessSubmitButton) | ||
|
||
await page.assertExists(yourTurnText) | ||
|
||
const wordInput = page.getByRole('textbox') | ||
await page.assertExists(wordInput) | ||
|
||
/** | ||
* This part is commented out because SSE events with current package are not | ||
* supported in Playwright and the whole apps uses them to update the state | ||
* FIXME: Need to find a way to mock the SSE events or find a way to test it | ||
*/ | ||
|
||
// await wordInput.fill('HintTest') | ||
// await page.assertNotDisabled(giveHintButton) | ||
// await giveHintButton.click() | ||
// | ||
// const hintGiverWordContainer = page.getByTitle('Hint Words list') | ||
// await page.assertExists(hintGiverWordContainer) | ||
// | ||
// const newWordText = await hintGiverWordContainer.allTextContents() | ||
// assert.include(newWordText, 'HintTest') | ||
}) | ||
|
||
test("verify that user can't submit a word if it's not his turn", async ({ visit, browserContext }) => { | ||
const player1 = await setupPlayer('[email protected]', 'test') | ||
const player2 = await setupPlayer('[email protected]', 'test2') | ||
|
||
await setupSession(player1, player2) | ||
|
||
await browserContext.loginAs(player2) | ||
|
||
const base = await visit(BaseGameSessionPage) | ||
|
||
const { page } = base | ||
|
||
const guessSubmitButton = page.locator('button', { hasText: 'Guess the word' }) | ||
await page.assertDisabled(guessSubmitButton) | ||
}) | ||
|
||
test("verify each wordInput error's message and verify that button is disabled", async ({ | ||
visit, | ||
browserContext, | ||
}) => { | ||
const player1 = await setupPlayer('[email protected]', 'test') | ||
const player2 = await setupPlayer('[email protected]', 'test2') | ||
|
||
await setupSession(player1, player2) | ||
|
||
await browserContext.loginAs(player1) | ||
|
||
const base = await visit(BaseGameSessionPage) | ||
|
||
const { page } = base | ||
|
||
const wordInput = page.getByRole('textbox') | ||
|
||
await page.assertExists(page.getByText('Invalid word')) | ||
|
||
// Using 'pressSequentially' because first fill doesn't set value to the input correctly | ||
await wordInput.pressSequentially('WordTest', { delay: 100 }) | ||
await page.assertNotExists(page.getByText('Invalid word')) | ||
await page.assertNotDisabled(page.getByRole('button', { name: 'Give a hint' })) | ||
|
||
await wordInput.clear() | ||
await page.assertExists(page.getByText('The field is empty')) | ||
await page.assertDisabled(page.getByRole('button', { name: 'Give a hint' })) | ||
|
||
await wordInput.clear() | ||
await wordInput.fill('Word Test') | ||
await page.assertExists(page.getByText('It can only be one word')) | ||
await page.assertDisabled(page.getByRole('button', { name: 'Give a hint' })) | ||
|
||
await wordInput.clear() | ||
await wordInput.fill('2@Word') | ||
await page.assertExists(page.getByText('Word can only contain letters')) | ||
await page.assertDisabled(page.getByRole('button', { name: 'Give a hint' })) | ||
}) | ||
|
||
test('check page content when game is over', async ({ visit, browserContext }) => { | ||
const player1 = await setupPlayer('[email protected]', 'test') | ||
const player2 = await setupPlayer('[email protected]', 'test2') | ||
|
||
const startedAt = DateTime.now().minus({ seconds: 85 }).toISO() | ||
await setupSession(player1, player2, player1.id, player2.id, startedAt) | ||
|
||
await browserContext.loginAs(player1) | ||
|
||
const base = await visit(BaseGameSessionPage) | ||
const { page } = base | ||
|
||
const backToMenuButton = page.locator('a', { hasText: 'Back to menu' }) | ||
|
||
await page.assertNotExists(backToMenuButton) | ||
// Wait 6 seconds to make sure the game is over | ||
await page.waitForTimeout(6000) | ||
|
||
/** | ||
* This part is commented out because SSE events with current package are not | ||
* supported in Playwright and the whole apps uses them to update the state | ||
* FIXME: Need to find a way to mock the SSE events or find a way to test it | ||
*/ | ||
// await page.assertExists(page.getByText("You didn't find the word")) | ||
// await page.assertExists(page.getByText('Word: test')) | ||
// await page.assertExists(page.getByText('Opponent: test2')) | ||
await page.assertExists(backToMenuButton) | ||
await backToMenuButton.isEnabled() | ||
await backToMenuButton.click() | ||
await page.waitForURL('/game', { timeout: 5000 }) | ||
await page.assertPath('/game') | ||
}) | ||
}) |
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,97 @@ | ||
import { test } from '@japa/runner' | ||
import { DateTime } from 'luxon' | ||
import GameHistory from '#models/game_history' | ||
import User from '#models/user' | ||
import Word from '#models/word' | ||
import { BaseProfilePage } from '#tests/utils/base_pages/base_profile_page' | ||
|
||
test.group('profile_page', () => { | ||
async function setupPlayer(email: string, username: string): Promise<User> { | ||
return await User.firstOrCreate({ email }, { username, providerId: 1, password: 'password' }) | ||
} | ||
|
||
test('check base parts of the page', async ({ visit, browserContext }) => { | ||
const player1 = await setupPlayer('[email protected]', 'test') | ||
const player2 = await setupPlayer('[email protected]', 'test2') | ||
|
||
const word = await Word.create({ | ||
name: 'test', | ||
language: 'en', | ||
}) | ||
|
||
await GameHistory.create({ | ||
sessionId: '9bb9871e-9da7-4193-a63c-66ef21687699', | ||
wordId: word.id, | ||
hintGiverId: player1.id, | ||
guesserId: player2.id, | ||
guessed: true, | ||
date: DateTime.fromObject({ year: 2024, month: 9, day: 1 }), | ||
wordsList: { hintGiver: ['lambda'], guesser: ['test'] }, | ||
}) | ||
|
||
await browserContext.loginAs(player1) | ||
|
||
const base = await visit(BaseProfilePage) | ||
|
||
const { page } = base | ||
|
||
await base.assertHasHeader() | ||
await base.assertHasFooter() | ||
|
||
const profileCard = page.getByTitle('Profile Card') | ||
const gameHistoryTable = page.getByTitle('Game History Table') | ||
|
||
await page.assertExists(profileCard) | ||
await page.assertExists(gameHistoryTable) | ||
|
||
await page.assertExists(page.getByText('Game History')) | ||
|
||
// Check profile card content | ||
await page.assertExists(profileCard.locator('p', { hasText: player1.username })) | ||
await page.assertExists(profileCard.locator('span', { hasText: '500' })) | ||
await page.assertExists(profileCard.getByRole('img', { name: 'avatar' })) | ||
|
||
// Check game history table content | ||
await page.assertExists(gameHistoryTable.getByText('Date')) | ||
await page.assertExists(gameHistoryTable.getByText('Word')) | ||
|
||
const game = gameHistoryTable.getByTitle('Game') | ||
|
||
await page.assertExists(game.getByText('01/09/2024 00:00:00')) | ||
await page.assertExists(game.getByText('test')) | ||
|
||
// Needed since click is not working to display game details | ||
await page.waitForLoadState('networkidle') | ||
|
||
// Check details section | ||
await page.assertNotExists(game.getByTitle('Details')) | ||
await game.click() | ||
await page.assertExists(game.getByTitle('Details')) | ||
await page.assertExists(game.getByText('Opponent: test2')) | ||
|
||
const wordsList = game.getByTitle('Words List') | ||
await page.assertExists(wordsList) | ||
|
||
const hintGiverList = wordsList.getByTitle('Hint Giver') | ||
const guesserList = wordsList.getByTitle('Guesser') | ||
|
||
await page.assertExists(hintGiverList) | ||
await page.assertExists(guesserList) | ||
await page.assertExists(hintGiverList.getByText('lambda')) | ||
await page.assertExists(guesserList.getByText('test')) | ||
}) | ||
|
||
test('back to home button should redirect to home page', async ({ visit, browserContext }) => { | ||
const player1 = await setupPlayer('[email protected]', 'test') | ||
await browserContext.loginAs(player1) | ||
|
||
const base = await visit(BaseProfilePage) | ||
const { page } = base | ||
|
||
const homeButton = page.locator('a', { hasText: 'Go back to home' }) | ||
await page.assertExists(homeButton) | ||
await homeButton.click() | ||
await page.waitForURL('/game', { timeout: 5000 }) | ||
await page.assertPath('/game') | ||
}) | ||
}) |
Oops, something went wrong.