/**
* Test Utilities
* Provides fixtures and helpers for integration tests
* ISO/IEC 25010 compliant
*/
import { mkdtempSync, writeFileSync, mkdirSync, rmSync, existsSync } from 'fs';
import { join } from 'path';
import { tmpdir } from 'os';
/**
* Standard Godot 4 project.godot content
*/
export const PROJECT_GODOT_FIXTURE = `; Engine configuration file.
; Generated by Godot Engine 4.2
config_version=5
[application]
config/name="Test Project"
config/features=PackedStringArray("4.2")
run/main_scene="res://scenes/main.tscn"
config/icon="res://icon.svg"
[display]
window/size/viewport_width=1920
window/size/viewport_height=1080
[rendering]
renderer/rendering_method="forward_plus"
`;
/**
* Minimal TSCN scene fixture
*/
export const MINIMAL_SCENE_FIXTURE = `[gd_scene format=3 uid="uid://test123"]
[node name="Root" type="Node2D"]
[node name="Player" type="CharacterBody2D" parent="."]
[node name="Sprite" type="Sprite2D" parent="Player"]
position = Vector2(100, 200)
`;
/**
* Scene with script attached
*/
export const SCENE_WITH_SCRIPT_FIXTURE = `[gd_scene load_steps=2 format=3]
[ext_resource type="Script" path="res://scripts/player.gd" id="1_script"]
[node name="Player" type="CharacterBody2D" script=ExtResource("1_script")]
`;
/**
* Scene with connections
*/
export const SCENE_WITH_CONNECTIONS_FIXTURE = `[gd_scene format=3]
[node name="Root" type="Node2D"]
[node name="Button" type="Button" parent="."]
[node name="Timer" type="Timer" parent="."]
[connection signal="pressed" from="Button" to="." method="_on_button_pressed"]
[connection signal="timeout" from="Timer" to="." method="_on_timer_timeout"]
`;
/**
* GDScript fixture
*/
export const GDSCRIPT_FIXTURE = `extends CharacterBody2D
const SPEED = 300.0
const JUMP_VELOCITY = -400.0
func _ready():
pass
func _physics_process(delta):
velocity.y += get_gravity().y * delta
move_and_slide()
`;
/**
* Resource file fixture (.tres)
*/
export const RESOURCE_FIXTURE = `[gd_resource type="Theme" format=3]
[resource]
default_font_size = 16
`;
/**
* Creates a temporary Godot project for testing
* @returns Object with project path and cleanup function
*/
export function createTempProject(): { projectPath: string; cleanup: () => void } {
const projectPath = mkdtempSync(join(tmpdir(), 'godot-mcp-test-'));
// Create project structure
mkdirSync(join(projectPath, 'scenes'), { recursive: true });
mkdirSync(join(projectPath, 'scripts'), { recursive: true });
mkdirSync(join(projectPath, 'resources'), { recursive: true });
// Write fixtures
writeFileSync(join(projectPath, 'project.godot'), PROJECT_GODOT_FIXTURE);
writeFileSync(join(projectPath, 'scenes', 'main.tscn'), MINIMAL_SCENE_FIXTURE);
writeFileSync(join(projectPath, 'scenes', 'with_script.tscn'), SCENE_WITH_SCRIPT_FIXTURE);
writeFileSync(join(projectPath, 'scenes', 'with_connections.tscn'), SCENE_WITH_CONNECTIONS_FIXTURE);
writeFileSync(join(projectPath, 'scripts', 'player.gd'), GDSCRIPT_FIXTURE);
writeFileSync(join(projectPath, 'resources', 'theme.tres'), RESOURCE_FIXTURE);
const cleanup = () => {
if (existsSync(projectPath)) {
rmSync(projectPath, { recursive: true, force: true });
}
};
return { projectPath, cleanup };
}
/**
* Extract text content from tool response
*/
export function getResponseText(response: { content: Array<{ text: string }> }): string {
return response.content[0]?.text || '';
}
/**
* Parse JSON response from tool
*/
export function parseJsonResponse<T>(response: { content: Array<{ text: string }> }): T {
return JSON.parse(getResponseText(response)) as T;
}
/**
* Check if response is an error
*/
export function isErrorResponse(response: { isError?: boolean }): boolean {
return response.isError === true;
}