Skip to main content

Integration testing

Allows you to setup your game room for testing specific cases.

Starting from client-side:

  1. Create new room passing test name in options: game.joinOrCreate("MyGame", { test: "testName" })
  2. New "MyGame" room is created
  3. Server-side calls integration hooks named "testName"
  4. Your game room is now ready for testing
  5. Start the game, interact with it like usual and inspect the results

Setup integration hooks

First you need to define integration hooks and what they'll do.

  1. Create new directory in your server game package: game-mygame-server/src/integration
  2. Create new file for your setup:
/src/integration/attack3.ts
export const attack3: IntegrationHooks<MyGameState> = {
data: {
shuffleDeck: false,
},
init: function (state, context) {
state.attackPoints = 3

const clients = ["test1", "test2"]
clients.forEach((i) => context.addClient(i))
},
}

IntegrationHooks object defines hooks callbacks and persistent data:

Hooks callbacks

  • init - will be called during room creation, but after onInitGame, so your game state object is already prepared
  • startPre - called right before the game starts. state.isGameStarted is already true and room's onStartGame has not yet been called.
  • startPost - called last during game start sequence, after onStartGame.

Integration data

  • data - an object for you to define additional flags available in the game's room. It'll be available in room's class under this.currentIntegration.data (readonly).
Example
/src/integration/attack3.ts
export const attack3: IntegrationHooks<MyGameState> = {
data: {
shuffleDeck: false,
},
// ...
}
/src/index.ts - Room class
  onStartGame() {
const { state } = this
const { shuffleDeck } = this.currentIntegration.data

return [
shuffleDeck && new commands.ShuffleChildren(state.deck)
].filter(cmd => cmd)
}

Add hooks to the Room

Hooks are defined so now we can pass them to the Room class. In example below we might keep many integration objects in one /integration/attack.ts file.

/src/index.ts - Room class
import * as integrationAttack from "./integration/attack"
import * as integrationUi from "./integration/ui"

export default class MyGame extends Room<MyGameState> {
possibleActions = new Set<ActionTemplate<MyGameState>>(actions)

integrationHooks = {
...integrationAttack,
...integrationUi,
}
// ...
}

Run

With the server-side setup we can finally enter the game from client-side and see the game being prepared differently than usual:

game.joinOrCreate("MyGame", { test: "attack3" })

Tips

What's left for you is to setup your own e2e testing environment.

  1. Setup a test route in your webapp to quickly join the room with an integration test like: locahost:8000/game/MyGame/autoplay?test=attack3.

  2. Make quick function to open up these URLs.

    // In my Cypress setup I've created a support function
    Cypress.Commands.add("testRoom", (roomName, testName) => {
    cy.visit(`/game/${roomName}/autoplay?test=${testName}`)
    })
    // And call it like so
    cy.testRoom("MyGame", "attack3")