Skip to content

Commit

Permalink
test(e2e): split launch game test
Browse files Browse the repository at this point in the history
  • Loading branch information
garrappachc committed Aug 5, 2024
1 parent e56b851 commit ab0d608
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 151 deletions.
135 changes: 0 additions & 135 deletions tests/10-queue/01-launch-game.spec.ts

This file was deleted.

38 changes: 38 additions & 0 deletions tests/20-game/01-configure-game-server.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { expect } from '@playwright/test'
import { launchGame } from '../fixtures/launch-game'
import { secondsToMilliseconds } from 'date-fns'
import { GamePage } from '../pages/game.page'
import { users } from '../data'

launchGame('configure game server', async ({ steamIds, gameNumber, pages, page, gameServer }) => {
const players = steamIds.slice(0, 12)

await Promise.all(
players.map(async steamId => {
const page = new GamePage(pages.get(steamId)!, gameNumber)
await expect(page.gameEvent('Game server assigned')).toBeVisible()

const connectString = page.connectString()
await expect(connectString).toHaveText(/^connect .+;\s?password (.+)$/, {
timeout: secondsToMilliseconds(30),
})

const [, password] =
(await connectString.innerText()).match(/^connect .+;\s?password (.+)$/) ?? []
expect(gameServer.cvar('sv_password').value).toEqual(password)

await expect(page.gameEvent('Game server initialized')).toBeVisible()
await expect(page.joinGameButton()).toBeVisible()

expect(gameServer.addedPlayers.some(p => p.steamId64 === steamId)).toBe(true)
}),
)

const gamePage = new GamePage(page, gameNumber)
await gamePage.goto()
await expect(gamePage.connectString()).toHaveText(/^connect ([a-z0-9\s.:]+)(;\s?password tv)?$/)
await expect(gamePage.watchStvButton()).toBeVisible()

const adminsPage = new GamePage(pages.get(users[0].steamId)!, gameNumber)
await adminsPage.forceEnd()
})
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,9 @@ launchGame(
)

await gameServer.connectAllPlayers()
gameServer.log('World triggered "Round_Start"')
await gameServer.matchStarts()
await waitABit(secondsToMilliseconds(10))
gameServer.log('World triggered "Game_Over" reason "Reached Win Limit"')
gameServer.log('Team "Red" final score "5" with "6" players')
gameServer.log('Team "Blue" final score "0" with "6" players')
await gameServer.matchEnds({ blu: 0, red: 5 })

await Promise.all(
queueUsers.map(async steamId => {
Expand Down
33 changes: 33 additions & 0 deletions tests/20-game/03-update-player-connection-status.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { secondsToMilliseconds } from 'date-fns'
import { expect, launchGame } from '../fixtures/launch-game'
import { GamePage } from '../pages/game.page'
import { users } from '../data'

launchGame(
'update player connection status',
async ({ steamIds, gameNumber, pages, gameServer }) => {
const players = steamIds.slice(0, 12)

await Promise.all(
players.map(async steamId => {
const page = new GamePage(pages.get(steamId)!, gameNumber)
const playerName = users.find(u => u.steamId === steamId)!.name

await expect(page.gameEvent('Game server initialized')).toBeVisible({
timeout: secondsToMilliseconds(30),
})

const slot = page.playerSlot(playerName)

await gameServer.playerConnects(playerName)
await expect(slot.getByLabel('Player connection status')).toHaveClass(/joining/)

await gameServer.playerJoinsTeam(playerName)
await expect(slot.getByLabel('Player connection status')).toHaveClass(/connected/)
}),
)

const adminsPage = new GamePage(pages.get(users[0].steamId)!, gameNumber)
await adminsPage.forceEnd()
},
)
62 changes: 51 additions & 11 deletions tests/game-server-simulator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,17 @@ class CVar {
}

class AddedPlayer {
private static lastUserId = 0
readonly userId: number

constructor(
public readonly steamId64: string,
public readonly name: string,
public readonly team: string,
public readonly gameClass: string,
) {}
) {
this.userId = AddedPlayer.lastUserId++
}
}

export class GameServerSimulator {
Expand All @@ -81,7 +86,8 @@ export class GameServerSimulator {
new CVar('tv_port', '27020', 'Host SourceTV port'),
new CVar('tv_password', 'tv', 'SourceTV password for all clients'),
]
private addedPlayers: AddedPlayer[] = []
addedPlayers: AddedPlayer[] = []
private readonly eventDelay = 100

constructor(
readonly apiAddress: string,
Expand Down Expand Up @@ -213,20 +219,54 @@ export class GameServerSimulator {
})
}

async playerConnects(playerName: string) {
const player = this.addedPlayers.find(player => player.name === playerName)
if (!player) {
throw new Error(`player not found: ${playerName}`)
}

const steamId3 = new SteamID(player.steamId64).steam3()
await waitABit(this.eventDelay / 2)
this.log(
`"${player.name}<${player.userId}><${steamId3}><>" connected, address "127.0.0.1:27005"`,
)
await waitABit(this.eventDelay / 2)
}

async playerJoinsTeam(playerName: string) {
const player = this.addedPlayers.find(player => player.name === playerName)
if (!player) {
throw new Error(`player not found: ${playerName}`)
}

const team = player.team === 'blu' ? 'Blue' : 'Red'
const steamId3 = new SteamID(player.steamId64).steam3()
await waitABit(this.eventDelay / 2)
this.log(`"${player.name}<${player.userId}><${steamId3}><Unassigned>" joined team "${team}"`)
await waitABit(this.eventDelay / 2)
}

async connectAllPlayers() {
const eventDelay = 100
let i = 1
for (const player of this.addedPlayers) {
const team = player.team === 'blu' ? 'Blue' : 'Red'
const steamId3 = new SteamID(player.steamId64).steam3()
this.log(`"${player.name}<${i}><${steamId3}><>" connected, address "127.0.0.1:27005"`)
await waitABit(eventDelay)
this.log(`"${player.name}<${i}><${steamId3}><Unassigned>" joined team "${team}"`)
await waitABit(eventDelay)
i += 1
await this.playerConnects(player.name)
await this.playerJoinsTeam(player.name)
}
}

async matchStarts() {
await waitABit(this.eventDelay / 2)
this.log('World triggered "Round_Start"')
await waitABit(this.eventDelay / 2)
}

async matchEnds(score: { blu: number; red: number }) {
await waitABit(this.eventDelay / 2)
this.log('World triggered "Game_Over" reason "Reached Win Limit"')
this.log(`Team "Red" final score "${score.red}" with "6" players`)
this.log(`Team "Blue" final score "${score.blu}" with "6" players`)
await waitABit(this.eventDelay / 2)
}

async sendHeartbeat() {
const params = new URLSearchParams()
params.set('name', 'Simulated Game Server')
Expand Down
12 changes: 12 additions & 0 deletions tests/pages/game.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ export class GamePage {
return this.playerSlot(playerName).getByRole('link', { name: playerName })
}

connectString() {
return this.page.getByLabel('Connect string')
}

joinGameButton() {
return this.page.getByRole('link', { name: 'join game' })
}

watchStvButton() {
return this.page.getByRole('link', { name: 'watch stv' })
}

async requestSubstitute(playerName: string) {
const btn = this.playerSlot(playerName).getByLabel('Request substitute')
await btn.click()
Expand Down
17 changes: 16 additions & 1 deletion tests/pages/queue.page.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
import type { Page } from '@playwright/test'
import type { Locator, Page } from '@playwright/test'
import { secondsToMilliseconds } from 'date-fns'

class QueueSlot {
readonly locator: Locator

constructor(
private readonly page: Page,
private readonly slotNumber: number,
) {
this.locator = this.page.getByLabel(`Queue slot ${this.slotNumber}`, { exact: true })
}

markAsFriendButton() {
return this.locator.getByRole('button', { name: 'Mark as friend' })
}
}

class ReadyUpDialog {
constructor(private readonly page: Page) {}

Expand Down

0 comments on commit ab0d608

Please sign in to comment.