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
Usage
const world = await SpecterWorld.connect();Arguments
urlstring(optional)The WebSocket URL (Default: 'ws://127.0.0.1:8080').
Returns
- Promise<SpecterWorld>
world.joinHost
Usage
await world.joinHost("192.168.1.100", "Arena_P");Arguments
ipAddressstringThe server IP address.expectedMapstring(optional)Wait for this map to load after joining.
Returns
- Promise<void>
world.close
Usage
await world.close();Returns
- Promise<void>
world.cleanup
Usage
await world.cleanup();Returns
- Promise<void>
World & Level Management
world.loadMap
Usage
await world.loadMap("/Game/Maps/Arena", { listen: true });Arguments
mapNamestringThe map name or path.optionsLoadMapOptions(optional)Configuration object.
Returns
- Promise<void>
world.waitForMapLoad
Usage
await world.waitForMapLoad("Arena");Arguments
mapNamestringThe map to wait for.timeoutnumber(optional)Timeout in ms (Default: 15000).
Returns
- Promise<void>
world.currentMap
Usage
console.log(world.currentMap);Returns
- string
world.getNetworkStatus
Usage
const status = await world.getNetworkStatus();Returns
- Promise<{ netMode: string, map: string, serverAddress: string }>
world.spawnActor
Usage
const boss = await world.spawnActor('/Game/Blueprints/Enemies/BP_Boss');Arguments
assetPathstringThe blueprint class path to spawn.optionsSpawnOptions(optional)Configuration object containing location, rotation, and properties.
Returns
- Promise<ActorLocator>
Global Engine Execution
world.evaluate
Usage
await world.evaluate("TakeScreenshot", { fileName: "menu" });Arguments
commandNamestringThe command to execute.payloadobject(optional)Command payload.contextstring(optional)Test runner UI context.targetLocatorstring(optional)Target locator string.
Returns
- Promise<any>
world.console
Usage
await world.console("cheat god");Arguments
commandStringstringThe console command.
Returns
- Promise<void>
world.setTimeScale
Usage
// Fast-forward simulation at 2x speed
await world.setTimeScale(2.0);Arguments
multipliernumberThe time scale multiplier (1.0 is normal speed, 2.0 is 2x fast-forward, 0.5 is slow motion).
Returns
- Promise<void>
world.setTimeDilation
Usage
// Slow down simulation to half speed for physics validation
await world.setTimeDilation(0.5);Arguments
multipliernumberThe time dilation multiplier (1.0 is normal speed, 2.0 is 2x fast-forward, 0.5 is slow motion).
Returns
- Promise<void>
world.stepFrame
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
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
secondsnumberNumber of in-game seconds to fast-forward.
Returns
- Promise<void>
world.waitForGameSeconds
Usage
// Waits for 5 in-game seconds (takes 500ms if timeDilation is 10.0)
await world.waitForGameSeconds(5.0);Arguments
secondsnumberIn-game seconds to wait.
Returns
- Promise<void>
world.waitForTimeout
Usage
await world.waitForTimeout(1000); // Wait 1 secondArguments
millisecondsnumberDuration to wait in milliseconds.
Returns
- Promise<void>
world.takeScreenshot
Usage
const path = await world.takeScreenshot("inventory_open", true);Arguments
fileNamestringThe name of the saved file.showUIboolean(optional)Render the UMG UI layer (Default: false).
Returns
- Promise<string>
world.waitForVariable
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
varNamestringThe stable variable string returned by a call to trackProperty() or trackAttribute().expectedValuestringThe expected stringified value to wait for (e.g. 'InProgress', '5', 'true').timeoutnumber(optional)Defaults to5000Maximum time in milliseconds to wait before failing with a timeout error.
Returns
- Promise<SpecterTimelineEvent>
world.waitForEvent
Usage
// Custom timeout & predicate options
await world.waitForEvent('playerJoined', {
timeout: 10000,
predicate: (data) => data.playerName === 'Player_1'
});Arguments
eventNamestringThe 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
Usage
// Option 1: Press and hold the key for 2000ms (2 seconds) before releasing
await world.keyboard.press('E', 2000);Arguments
keystringThe 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
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 itArguments
keystringThe UE key name.
Returns
- Promise<void>
world.keyboard.up
Usage
await world.keyboard.up('W');Arguments
keystringThe UE key name.
Returns
- Promise<void>
world.injectAxis
Usage
// Push the left thumbstick 50% forward for one frame
await world.injectAxis('Gamepad_LeftY', 0.5);Arguments
axisNamestringThe name of the axis binding (e.g. 'Gamepad_LeftY').valuenumberThe float value to inject (typically -1.0 to 1.0).
Returns
- Promise<void>
world.playSequence
Usage
import { SpecterInputSequence } from '@specter-automation/test';
const spinAttack = new SpecterInputSequence()
.addAxisCircle('Gamepad_LeftX', 'Gamepad_LeftY', 0, 1500, 2);
await world.playSequence(spinAttack);Arguments
sequenceSpecterInputSequenceThe 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
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
selectorstringClass name (e.g. 'BP_Hero') or tag prefix selector (e.g. 'Tag:Enemy.Boss' or 'tag=Enemy.Boss').
Returns
world.actorByTag
Usage
const enemy = world.actorByTag("Enemy.Boss");Arguments
tagNamestringThe tag name.
Returns
world.widget
Usage
const inventory = world.widget("WBP_Inventory");Arguments
classNamestringThe class name.
Returns
world.getByPlayerId
Usage
const p1 = world.getByPlayerId(0);Arguments
playerIdnumberThe player ID.
Returns
world.subsystem
Usage
const audio = world.subsystem("AudioSubsystem");Arguments
subsystemNamestringThe subsystem class name.
Returns
world.uobject
Usage
const saveGame = world.uobject("MySaveGame");Arguments
classNamestringThe object class name.
Returns
Performance Profiling
Real-time engine performance metrics for benchmarking and regression testing.
world.getPerformanceMetrics
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
Usage
const reachable = await world.isPointReachable(
{ x: 100, y: 200, z: 0 },
{ x: 500, y: 600, z: 0 }
);
expect(reachable).toBe(true);Returns
- Promise<boolean>
Sequencer & Cutscenes
Control and query Level Sequence (cutscene) playback state.
world.isSequencePlaying
Usage
const playing = await world.isSequencePlaying('IntroSequence');Arguments
sequenceNamestringThe name of the Level Sequence Actor.
Returns
- Promise<boolean>
world.getSequencePlaybackPosition
Usage
const pos = await world.getSequencePlaybackPosition('IntroSequence');
console.log(`Cutscene is at ${pos}s`);Arguments
sequenceNamestringThe name of the Level Sequence Actor.
Returns
- Promise<number>
world.scrubSequence
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
sequenceNamestringThe name of the Level Sequence Actor.positionSecondsnumberThe 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
Usage
await client1.network.setEmulatedLatency(150);Arguments
pingMsnumberTarget latency in milliseconds (e.g. 150).
Returns
- Promise<void>
world.network.setPacketLoss
Usage
await client1.network.setPacketLoss(5);Arguments
lossPercentnumberPacket loss percentage from 0 to 100 (e.g. 5).
Returns
- Promise<void>
world.network.resetNetworkEmulation
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
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
optionsDebugSphereOptionsConfiguration object: { center: Vector3, radius: number, segments?: number, color?: string, duration?: number, thickness?: number }.
Returns
- Promise<void>
world.drawDebugBox
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
optionsDebugBoxOptionsConfiguration object: { center: Vector3, extent: Vector3, rotation?: Rotator, color?: string, duration?: number, thickness?: number }.
Returns
- Promise<void>
world.drawDebugLine
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
optionsDebugLineOptionsConfiguration object: { start: Vector3, end: Vector3, color?: string, duration?: number, thickness?: number }.
Returns
- Promise<void>
world.clearDebugVisuals
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
}