Skip to content

Commit

Permalink
test: add test for game_session, profile, search pages
Browse files Browse the repository at this point in the history
  • Loading branch information
prisca-c committed Nov 1, 2024
1 parent 6ae0786 commit c0cc75b
Show file tree
Hide file tree
Showing 6 changed files with 466 additions and 0 deletions.
281 changes: 281 additions & 0 deletions tests/browser/game_session.spec.ts
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')
})
})
97 changes: 97 additions & 0 deletions tests/browser/profile.spec.ts
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')
})
})
Loading

0 comments on commit c0cc75b

Please sign in to comment.