Replay Test

Once you've worked on your game for a while, it's a good idea to add some tests to avoid things breaking in the future. It gives you the confidence to keep publishing new updates!

The @replay/test package is useful for writing tests in Jest for your Replay game. It provides a test platform, which works the same as any other like web and iOS, but returns helpful utility functions for testing.

testSprite(sprite, gameProps, options)

Parameters

  • sprite: The Sprite you want to test called with its props, e.g. Player(playerProps).
  • gameProps: The props defined for your top-level Game. This sets the device size during tests.
  • options: (Optional) An object with the following properties:
    • initInputs: (Optional) The inputs your device returns. Match with the platforms you're targeting.
    • mapInputCoordinates: (Optional) A mapping function to adjust an input's (x, y) coordinate to its relative value within a Sprite. The Web package exports this for pointer values.
    • initRandom: (Optional) An array of numbers that random() will call, starting from index 0 and looping if it reaches the end. Allows for predictable randomness.
    • size: (Optional) Set the size parameter passed into Sprites.
    • initStore: (Optional) Set the init store for local storage.
    • networkResponses: (Optional) Mock network responses by URL, e.g:
    {
    get: {
    "/api/score": {
    success: true,
    },
    },
    },
    • initAlertResponse: (Optional) Set which choice is chosen for OK / cancel alerts. Default true.
    • nativeSpriteNames: (Optional) A list of Native Sprite names to mock.
    • isTouchScreen: (Optional) Set the isTouchScreen parameter.

testSprite returns an object with the following fields:

nextFrame()

Increment game by one frame.

nextFrame();

jumpToFrame(() => condition)

Synchronously progress frames of the game until condition is met and no errors are thrown. Condition can also return a Texture (useful for throwing methods like getByText). Throws if 1000 gameplay seconds (60,000 loops) pass and condition not met / still errors.

jumpToFrame(() => props.x > 10);

setRandomNumbers(array)

Reset the array of random numbers.

setRandomNumbers([0.2, 0.3, 0.4]);

updateInputs(inputs)

Update the input state for the next frame, such as to indicate the pointer is pressed.

updateInputs({
pointer: {
pressed: true,
justPressed: true,
justReleased: false,
// Here the pointer position will have the
// same coordinates in all Sprites unless
// you set mapInputCoordinates
x: 0,
y: 0,
},
});

getTextures()

Returns an array of textures that were just rendered to the screen.

const textures = getTextures();

getTexture(testId)

Get a Texture with a matching prop testId. Throws if there are no matches.

const player = getTexture("player");

textureExists(testId)

Boolean of whether a Texture with a testId prop exists.

expect(textureExists("player")).toBe(true);

getByText(text)

Get a text Texture based on its text content. Returns an array of all matches, throws if there are no matches.

const scoreLabel = getByText("Score: 10")[0];

log

A Jest mock function to detect if log was called by a Sprite.

expect(log).toBeCalledWith("Hello Replay");

audio

An object of Jest mock functions for testing audio calls.

expect(audio.play).toBeCalledWith("boop.wav");

network

An object of network mock functions for testing network responses.

expect(network.get).toBeCalled();

store

A mock local storage store.

expect(store).toEqual({ highScore: 5 });

alert

A mock alert object.

expect(alert.okCancel).toBeCalledWith("Ok or cancel?", expect.any(Function));

updateAlertResponse(isOk)

Update whether OK / cancel alert chooses OK or cancel.

updateAlertResponse(false);

clipboard

A mock clipboard object.

expect(clipboard.copy).toBeCalledWith("ABCDEFG", expect.any(Function));

Example

import { testSprite } from "@replay/test";
import { Game, gameProps } from "..";
test("Can shoot bullet", () => {
const initInputs = {
pointer: {
pressed: false,
justPressed: false,
justReleased: false,
x: 0,
y: 0,
},
};
const { nextFrame, updateInputs, getTexture, textureExists } = testSprite(
Game(gameProps),
gameProps,
{
initInputs,
}
);
expect(textureExists("bullet")).toBe(false);
updateInputs({
pointer: {
pressed: true,
justPressed: true,
justReleased: false,
x: 0,
y: 0,
},
});
nextFrame();
updateInputs(initInputs);
nextFrame();
expect(textureExists("bullet")).toBe(true);
expect(getTexture("bullet").props.y).toBe(100);
});