class: SpecterWorld

The SpecterWorld class provides methods to interact with the Unreal Engine instance. It is the primary fixture passed to every test, equivalent to the page fixture in Playwright.

Connection & Lifecycle

SpecterWorld.connect

Static factory method that connects to an Unreal Engine instance over WebSockets and returns a new SpecterWorld fixture.

Usage

const world = await SpecterWorld.connect();

Arguments

  • urlstring(optional)
    The WebSocket URL (Default: 'ws://127.0.0.1:8080').

Returns

world.joinHost

Commands the local client to join a multiplayer host/server via IP.

Usage

await world.joinHost("192.168.1.100", "Arena_P");

Arguments

  • ipAddressstring
    The server IP address.
  • expectedMapstring(optional)
    Wait for this map to load after joining.

Returns

  • Promise<void>

world.close

Closes the WebSocket connection to the engine.

Usage

await world.close();

Returns

  • Promise<void>

world.cleanup

Destroys all actors that were dynamically spawned during the test via world.spawnActor().

Usage

await world.cleanup();

Returns

  • Promise<void>

World & Level Management

world.loadMap

Synchronously loads a level. Supports advanced options like game modes and listen servers.

Usage

await world.loadMap("/Game/Maps/Arena", { listen: true });

Arguments

  • mapNamestring
    The map name or path.
  • optionsLoadMapOptions(optional)
    Configuration object.

Returns

  • Promise<void>

world.waitForMapLoad

Waits for a specific map to be loaded.

Usage

await world.waitForMapLoad("Arena");

Arguments

  • mapNamestring
    The map to wait for.
  • timeoutnumber(optional)
    Timeout in ms (Default: 15000).

Returns

  • Promise<void>

world.currentMap

Property getter for the currently loaded map name.

Usage

console.log(world.currentMap);

Returns

  • string

world.getNetworkStatus

Retrieves the current network mode and server address.

Usage

const status = await world.getNetworkStatus();

Returns

  • Promise<{ netMode: string, map: string, serverAddress: string }>

world.spawnActor

Synchronously spawns an actor of the given class into the world.

Usage

const boss = await world.spawnActor('/Game/Blueprints/Enemies/BP_Boss');

Arguments

  • assetPathstring
    The blueprint class path to spawn.
  • optionsSpawnOptions(optional)
    Configuration object containing location, rotation, and properties.

Returns

Global Engine Execution

world.evaluate

Executes a global C++ plugin command.

Usage

await world.evaluate("TakeScreenshot", { fileName: "menu" });

Arguments

  • commandNamestring
    The command to execute.
  • payloadobject(optional)
    Command payload.
  • contextstring(optional)
    Test runner UI context.
  • targetLocatorstring(optional)
    Target locator string.

Returns

  • Promise<any>

world.console

Executes a raw Unreal Engine console command.

Usage

await world.console("cheat god");

Arguments

  • commandStringstring
    The console command.

Returns

  • Promise<void>

world.setTimeScale

Adjusts the global time dilation of the Unreal Engine world. Alias for world.setTimeDilation(). Useful for fast-forwarding through long cutscenes or slowing down simulation to validate frame-perfect physics and combat.

Usage

// Fast-forward simulation at 2x speed
await world.setTimeScale(2.0);

Arguments

  • multipliernumber
    The time scale multiplier (1.0 is normal speed, 2.0 is 2x fast-forward, 0.5 is slow motion).

Returns

  • Promise<void>

world.setTimeDilation

Adjusts the global Unreal Engine time dilation (AWorldSettings::SetTimeDilation). Alias for world.setTimeScale(). Multiplier of 1.0 represents normal real-time speed, > 1.0 runs faster, and < 1.0 runs in slow motion.

Usage

// Slow down simulation to half speed for physics validation
await world.setTimeDilation(0.5);

Arguments

  • multipliernumber
    The time dilation multiplier (1.0 is normal speed, 2.0 is 2x fast-forward, 0.5 is slow motion).

Returns

  • Promise<void>

world.stepFrame

Advances the Unreal Engine simulation forward frame-by-frame. Essential for tick-accurate inspection, physics stepping, and deterministic playback verification.

Usage

// Advance simulation by 1 frame
await world.stepFrame(1);

// Step 5 frames during combat collision resolution
await world.stepFrame(5);

Arguments

  • frameCountnumber(optional)
    Number of frames to advance (Default: 1).

Returns

  • Promise<void>

world.advanceTime

Fast-forwards the Unreal Engine simulation time by the specified number of seconds without sleeping in real time. Skips cooldowns, buff durations, and timers in a fraction of a second.

Usage

// Fast-forward 60 in-game seconds in ~500ms of real time!
await world.advanceTime(60.0);
await expect(steelActor).not.toHaveGameplayTag("Cooldown.Abilities.R");

Arguments

  • secondsnumber
    Number of in-game seconds to fast-forward.

Returns

  • Promise<void>

world.waitForGameSeconds

Waits for a duration of in-game simulation seconds. Automatically scales the wall-clock wait time down based on the currently active time dilation (e.g. 5 seconds at 10x dilation takes 500ms).

Usage

// Waits for 5 in-game seconds (takes 500ms if timeDilation is 10.0)
await world.waitForGameSeconds(5.0);

Arguments

  • secondsnumber
    In-game seconds to wait.

Returns

  • Promise<void>

world.waitForTimeout

Pauses test execution for the specified duration in milliseconds. Prefer auto-retrying expect assertions when possible.

Usage

await world.waitForTimeout(1000); // Wait 1 second

Arguments

  • millisecondsnumber
    Duration to wait in milliseconds.

Returns

  • Promise<void>

world.takeScreenshot

Captures a screenshot of the active Unreal Engine viewport.

Usage

const path = await world.takeScreenshot("inventory_open", true);

Arguments

  • fileNamestring
    The name of the saved file.
  • showUIboolean(optional)
    Render the UMG UI layer (Default: false).

Returns

  • Promise<string>

world.waitForVariable

Pauses test execution until Unreal Engine pushes an instant telemetry event confirming that a tracked UPROPERTY variable has reached the expected value. Unlike polling, this is zero-overhead and event-driven. See the Events & Telemetry Guide for details.

Usage

const matchStateVar = await world.actor('GameStateBase').trackProperty('MatchState');

// Wait for game state to transition to in-progress
const event = await world.waitForVariable(matchStateVar, "InProgress");
console.log(`Match started at engine timestamp: ${event.timestamp}s`);

// Fast-forward or wait until Wave 5 with a custom 10s timeout
const waveVar = await world.actor('BP_WaveSpawner').trackProperty('CurrentWave');
await world.waitForVariable(waveVar, "5", 10000);

Arguments

  • varNamestring
    The stable variable string returned by a call to trackProperty() or trackAttribute().
  • expectedValuestring
    The expected stringified value to wait for (e.g. 'InProgress', '5', 'true').
  • timeoutnumber(optional)Defaults to 5000
    Maximum time in milliseconds to wait before failing with a timeout error.

Returns

world.waitForEvent

Natively waits for a C++ UObject delegate to broadcast on the world context (e.g. mapLoaded, playerJoined, actorSpawned). Supports predicate filtering.

Usage

// Custom timeout & predicate options
await world.waitForEvent('playerJoined', {
    timeout: 10000,
    predicate: (data) => data.playerName === 'Player_1'
});

Arguments

  • eventNamestring
    The name of the world event to bind to.
  • optionsOrPredicateFunction | Object(optional)
    A predicate function (payload) => boolean, or an options object { timeout, predicate }.

Returns

  • Promise<any>

Input Simulation

Methods for simulating hardware input globally across the active game viewport.

world.keyboard.press

Simulates a raw hardware key press globally.

Usage

// Option 1: Press and hold the key for 2000ms (2 seconds) before releasing
await world.keyboard.press('E', 2000);

Arguments

  • keystring
    The UE key name (e.g. 'E', 'SpaceBar').
  • holdMsnumber(optional)
    How long to hold the key before releasing it (in milliseconds).

Returns

  • Promise<void>

world.keyboard.down

Manually holds a key down indefinitely.

Usage

// Option 2: Manually hold the key down indefinitely (e.g., walking forward)
await world.keyboard.down('W');
await world.waitForEvent('SomeEvent'); // Wait for something to happen while walking
await world.keyboard.up('W'); // Release it

Arguments

  • keystring
    The UE key name.

Returns

  • Promise<void>

world.keyboard.up

Releases a manually held key.

Usage

await world.keyboard.up('W');

Arguments

  • keystring
    The UE key name.

Returns

  • Promise<void>

world.injectAxis

Injects a raw analog value directly into the PlayerController's InputAxis method. Useful for simulating fine analog movements like slightly tilting a gamepad thumbstick or partially pulling a trigger.

Usage

// Push the left thumbstick 50% forward for one frame
await world.injectAxis('Gamepad_LeftY', 0.5);

Arguments

  • axisNamestring
    The name of the axis binding (e.g. 'Gamepad_LeftY').
  • valuenumber
    The float value to inject (typically -1.0 to 1.0).

Returns

  • Promise<void>

world.playSequence

Plays a mathematically accurate frame-by-frame SpecterInputSequence applied globally to the engine's active game viewport.

Usage

import { SpecterInputSequence } from '@specter-automation/test';

const spinAttack = new SpecterInputSequence()
    .addAxisCircle('Gamepad_LeftX', 'Gamepad_LeftY', 0, 1500, 2);

await world.playSequence(spinAttack);

Arguments

  • sequenceSpecterInputSequence
    The input sequence to play.
  • optionsObject(optional)
    { loops?: number } The number of times to loop the sequence.

Returns

  • Promise<void>

Locator Factories

Methods for querying objects in the engine. These return lazy-evaluated Locators.

world.actor

Queries actors by Blueprint class name, or by Gameplay Tag using a 'Tag:' or 'tag=' prefix selector.

Usage

// By Class Name (Default)
const player = world.actor("BP_Hero");

// By Gameplay Tag Prefix Selector (Playwright-style)
const boss = world.actor("Tag:Enemy.Boss");
const bossAlt = world.actor("tag=Enemy.Boss");

Arguments

  • selectorstring
    Class name (e.g. 'BP_Hero') or tag prefix selector (e.g. 'Tag:Enemy.Boss' or 'tag=Enemy.Boss').

world.actorByTag

Queries actors by their Gameplay Tag.

Usage

const enemy = world.actorByTag("Enemy.Boss");

Arguments

  • tagNamestring
    The tag name.

world.widget

Queries UMG widgets by their Blueprint class name.

Usage

const inventory = world.widget("WBP_Inventory");

Arguments

  • classNamestring
    The class name.

world.getByPlayerId

Queries for the possessed pawn of a specific Player ID.

Usage

const p1 = world.getByPlayerId(0);

Arguments

  • playerIdnumber
    The player ID.

world.subsystem

Queries a UEngineSubsystem, UGameInstanceSubsystem, or ULocalPlayerSubsystem.

Usage

const audio = world.subsystem("AudioSubsystem");

Arguments

  • subsystemNamestring
    The subsystem class name.

world.uobject

Queries for a generic UObject in memory by its class name.

Usage

const saveGame = world.uobject("MySaveGame");

Arguments

  • classNamestring
    The object class name.

Performance Profiling

Real-time engine performance metrics for benchmarking and regression testing.

world.getPerformanceMetrics

Retrieves real-time performance metrics from the engine including FPS (from world delta time), frame time in ms, and used physical memory in MB.

Usage

const metrics = await world.getPerformanceMetrics();
console.log(`FPS: ${metrics.fps}`);
console.log(`Frame Time: ${metrics.frameTimeMs}ms`);
console.log(`Memory: ${metrics.memoryMb}MB`);

// Assert minimum performance threshold
expect(metrics.fps).toBeGreaterThan(30);

Returns

  • Promise<{ fps: number, frameTimeMs: number, memoryMb: number }>

AI & Navigation (Global)

Global NavMesh queries that are not tied to a specific actor.

world.isPointReachable

Runs a synchronous NavMesh path query via UNavigationSystemV1 to determine if a path exists between two world positions.

Usage

const reachable = await world.isPointReachable(
  { x: 100, y: 200, z: 0 },
  { x: 500, y: 600, z: 0 }
);
expect(reachable).toBe(true);

Arguments

  • startVector3
    The starting world coordinate.
  • endVector3
    The destination world coordinate.

Returns

  • Promise<boolean>

Sequencer & Cutscenes

Control and query Level Sequence (cutscene) playback state.

world.isSequencePlaying

Checks if a Level Sequence Actor is currently playing. Auto-discovers sequence by name match.

Usage

const playing = await world.isSequencePlaying('IntroSequence');

Arguments

  • sequenceNamestring
    The name of the Level Sequence Actor.

Returns

  • Promise<boolean>

world.getSequencePlaybackPosition

Returns current playback position of a Level Sequence in seconds.

Usage

const pos = await world.getSequencePlaybackPosition('IntroSequence');
console.log(`Cutscene is at ${pos}s`);

Arguments

  • sequenceNamestring
    The name of the Level Sequence Actor.

Returns

  • Promise<number>

world.scrubSequence

Scrubs the Level Sequence to an exact time position in seconds using EUpdatePositionMethod::Scrub.

Usage

// Jump to the 5-second mark of the intro cutscene
await world.scrubSequence('IntroSequence', 5.0);

// Verify the cutscene spawned a specific actor at that moment
await expect(world.actor('BP_CutsceneBoss')).toBeVisible();

Arguments

  • sequenceNamestring
    The name of the Level Sequence Actor.
  • positionSecondsnumber
    The target time position in seconds.

Returns

  • Promise<void>

Network & Lag Emulation

Methods available on world.network to simulate real-world multiplayer conditions.

world.network.setEmulatedLatency

Simulates network ping/latency on the active client connection.

Usage

await client1.network.setEmulatedLatency(150);

Arguments

  • pingMsnumber
    Target latency in milliseconds (e.g. 150).

Returns

  • Promise<void>

world.network.setPacketLoss

Simulates packet loss percentage on the active client network connection.

Usage

await client1.network.setPacketLoss(5);

Arguments

  • lossPercentnumber
    Packet loss percentage from 0 to 100 (e.g. 5).

Returns

  • Promise<void>

world.network.resetNetworkEmulation

Resets emulated latency and packet loss back to 0.

Usage

await client1.network.resetNetworkEmulation();

Returns

  • Promise<void>

Spatial Primitives & Visual Debugging

Draw persistent 3D spheres, bounding boxes, raycasts, and lines directly into the level viewport to visualize combat radiuses and collision tests.

world.drawDebugSphere

Draws a persistent 3D wireframe or solid sphere in world space to visualize AOE blast zones, capture areas, and explosion radii.

Usage

// AOE Blast / Capture Zone Sphere
await world.drawDebugSphere({
  center: { x: 0, y: 0, z: 92 },
  radius: 300,
  color: 'orange',
  duration: 8,
  thickness: 2
});

Arguments

  • optionsDebugSphereOptions
    Configuration object: { center: Vector3, radius: number, segments?: number, color?: string, duration?: number, thickness?: number }.

Returns

  • Promise<void>

world.drawDebugBox

Draws an oriented 3D bounding box in world space to visualize trigger volumes, spawn zones, and custom hitboxes.

Usage

// 3D Trigger Volume Box
await world.drawDebugBox({
  center: { x: 0, y: 300, z: 92 },
  extent: { x: 100, y: 100, z: 50 },
  color: 'magenta',
  duration: 8
});

Arguments

  • optionsDebugBoxOptions
    Configuration object: { center: Vector3, extent: Vector3, rotation?: Rotator, color?: string, duration?: number, thickness?: number }.

Returns

  • Promise<void>

world.drawDebugLine

Draws a 3D line trace or raycast between two world points to visualize projectile paths, line-of-sight checks, and trajectory traces.

Usage

// Line Trace / Raycast
await world.drawDebugLine({
  start: { x: -250, y: -200, z: 92 },
  end: { x: 0, y: 0, z: 92 },
  color: 'cyan',
  duration: 8,
  thickness: 3
});

Arguments

  • optionsDebugLineOptions
    Configuration object: { start: Vector3, end: Vector3, color?: string, duration?: number, thickness?: number }.

Returns

  • Promise<void>

world.clearDebugVisuals

Clears all active 3D debug shapes, spheres, boxes, lines, motion trails, and stats billboards across the entire level.

Usage

await world.clearDebugVisuals();

Returns

  • Promise<void>

Interfaces

DebugSphereOptions

interface DebugSphereOptions {
  center: Vector3;
  radius: number;
  segments?: number;
  color?: string;
  duration?: number;
  thickness?: number;
}

DebugBoxOptions

interface DebugBoxOptions {
  center: Vector3;
  extent: Vector3;
  rotation?: Rotator;
  color?: string;
  duration?: number;
  thickness?: number;
}

DebugLineOptions

interface DebugLineOptions {
  start: Vector3;
  end: Vector3;
  color?: string;
  duration?: number;
  thickness?: number;
}

SpawnOptions

interface SpawnOptions {
  tag?: string;
  location?: Vector3;
  rotation?: Rotator;
  properties?: Record<string, any>;
  spawnController?: boolean;
}

LoadMapOptions

interface LoadMapOptions {
  gameMode?: string;
  listen?: boolean;
}

SpecterTimelineEvent

interface SpecterTimelineEvent {
  timestamp: number;        // Game world time in seconds
  eventName: string;        // The tracked UPROPERTY variable name
  description: string;      // Human-readable summary
  eventType: 'StandardVariable' | 'GameplayAttribute' | 'GameplayTag';
  oldValue: string;         // Previous value before transition
  newValue: string;         // Current value after transition
  instigator?: string;      // Actor or subsystem that triggered change
}