use std::fs;
use assert_cmd::Command;
use predicates::str::contains;
#[test]
fn fgk_package_with_binary_writes_full_bundle() {
let td = tempfile::tempdir().unwrap();
let project = td.path().join("smoke-game");
Command::cargo_bin("fgk")
.unwrap()
.arg("new")
.arg(&project)
.assert()
.success();
let fake_bin = td.path().join("smoke-game-bin");
fs::write(&fake_bin, b"#!/bin/sh\necho fake\n").unwrap();
let out = td.path().join("dist");
Command::cargo_bin("fgk")
.unwrap()
.arg("package")
.arg("--out")
.arg(&out)
.arg("--project")
.arg(&project)
.arg("--binary")
.arg(&fake_bin)
.assert()
.success()
.stdout(contains("Packaged `smoke-game`"));
assert!(out.join("smoke-game").is_file(), "binary missing");
assert!(out.join("run.sh").is_file(), "run.sh missing");
assert!(out.join("manifest.json").is_file(), "manifest.json missing");
assert!(out.join("assets").is_dir(), "assets/ missing");
let body = fs::read_to_string(out.join("manifest.json")).unwrap();
let v: serde_json::Value = serde_json::from_str(&body).unwrap();
assert_eq!(v["slug"], "smoke-game");
assert_eq!(v["command"], "/srv/foglet/doors/smoke-game/run.sh");
let run_sh = fs::read_to_string(out.join("run.sh")).unwrap();
assert!(run_sh.contains(r#"exec "$DIR/smoke-game""#));
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
let bin_mode = fs::metadata(out.join("smoke-game"))
.unwrap()
.permissions()
.mode();
let run_mode = fs::metadata(out.join("run.sh"))
.unwrap()
.permissions()
.mode();
assert_eq!(bin_mode & 0o111, 0o111, "binary missing exec bit");
assert_eq!(run_mode & 0o111, 0o111, "run.sh missing exec bit");
}
}
#[test]
fn fgk_package_murder_motel_seeds_world_directory() {
let project = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
.join("..")
.join("..")
.join("examples")
.join("murder_motel");
assert!(
project.join("assets/game.toml").is_file(),
"Murder Motel fixture missing — test path drift?"
);
let td = tempfile::tempdir().unwrap();
let fake_bin = td.path().join("murder-motel-bin");
fs::write(&fake_bin, b"#!/bin/sh\necho fake\n").unwrap();
let out = td.path().join("dist");
Command::cargo_bin("fgk")
.unwrap()
.arg("package")
.arg("--out")
.arg(&out)
.arg("--project")
.arg(&project)
.arg("--binary")
.arg(&fake_bin)
.assert()
.success()
.stdout(contains("Packaged `murder-motel`"));
let world_dir = out.join("world");
assert!(
world_dir.is_dir(),
"world/ directory missing for murder motel"
);
assert!(
world_dir.join(".keep").is_file(),
"world/.keep sentinel missing"
);
assert!(
!world_dir.join("world.sqlite").exists(),
"world.sqlite must not be pre-created at package time"
);
}
#[test]
fn fgk_package_rejects_relative_install_dir() {
let td = tempfile::tempdir().unwrap();
let project = td.path().join("smoke-game");
Command::cargo_bin("fgk")
.unwrap()
.arg("new")
.arg(&project)
.assert()
.success();
let fake_bin = td.path().join("smoke-game-bin");
fs::write(&fake_bin, b"#!/bin/sh\n").unwrap();
let out = td.path().join("dist");
Command::cargo_bin("fgk")
.unwrap()
.arg("package")
.arg("--out")
.arg(&out)
.arg("--project")
.arg(&project)
.arg("--binary")
.arg(&fake_bin)
.arg("--install-dir")
.arg("relative/path")
.assert()
.failure()
.stderr(contains("must be an absolute path"));
}