Files
security-game/src/test/tests/test_web_export.gd
T
zwitschi afa1d6beec
Full build / Import + headless tests (push) Successful in 36s
Full build / Full desktop build + optional release (push) Successful in 4m17s
v0.3.0: rendering pass, generated props, selection model and Web build
Rendering and presentation
- Shared surface-material module (src/game/materials.gd) with per-surface
  roughness/metallic/uv profiles; ACES tonemapping, glow, fog and phase-driven sky
  energy. WorldBuilder rebuilt on those profiles with facade windows that light up,
  door trim/handles, curb, lane dashes, bollards, bench, bin and planter foliage.
- NPC silhouettes: per-role clothing palettes, caps/hoods/backpacks/sunglasses,
  hands and shoes, arm/leg walk swing.
- Six generated low-poly GLB props (bollards, bench, bin, planter, newspaper box,
  hydrant) built by tools/model_pipeline.py, loaded by WorldBuilder with a
  procedural fallback; ADR-0012.

Selection and movement
- Focus ranking by view angle then distance (NpcFocus.rank_indices); Tab and the
  mouse wheel cycle nearby people initially, right click clears focus with a
  re-acquire grace, HUD shows the candidate count, Shift walks at half speed.
  ADR-0011. Windowed smoke extended to cover wheel cycling and clearing.

QA tooling
- screen_designs.py catalogue grown to 19 screens (8 scene, 11 UI) plus a `list`
  subcommand; draft generation keeps existing AI references unless --force.

Web export
- New Web preset using the non-threaded Godot template (static hosting, no
  COOP/COEP). tools/build_releases.sh exports build/web and packages
  build/step-line-web-<ver>.zip; publish_release.sh uploads it with the desktop
  artifacts. test_web_export.gd covers the preset and release wiring.

Verification
- Headless suite 177 -> 181, Python tooling 53 tests, all eight smokes pass
  (including the windowed focus/wheel smoke). Web bundle serves index.html,
  index.wasm (35 MB) and index.pck (30 MB) with HTTP 200 from a static server.
- Version 0.3.0; README, PLAN, RELEASING, TODO/DONE and MEMORY updated.
2026-10-31 23:07:41 +01:00

66 lines
2.9 KiB
GDScript

extends RefCounted
## Web export target: the preset exists, uses the non-threaded template (so it
## runs on plain static hosting without COOP/COEP headers), and the release
## scripts build and publish it.
func _preset() -> String:
## Return the `[preset.N]` block whose name is Web plus its `.options` block.
var lines := FileAccess.get_file_as_string("res://export_presets.cfg").split("\n")
var sections := {}
var current := ""
var web_id := ""
for line in lines:
if line.begins_with("[") and line.ends_with("]"):
current = line
sections[current] = PackedStringArray()
continue
if sections.has(current):
# PackedStringArray is a value type: mutate a local and write it back.
var block: PackedStringArray = sections[current]
block.append(line)
sections[current] = block
if line == 'name="Web"':
web_id = current.trim_prefix("[").trim_suffix("]")
if web_id == "":
return ""
var out: PackedStringArray = []
out.append("[%s]" % web_id)
out.append_array(sections.get("[%s]" % web_id, PackedStringArray()))
var options := "[%s.options]" % web_id
if sections.has(options):
out.append(options)
out.append_array(sections[options])
return "\n".join(out)
func test_web_preset_exists() -> bool:
var preset := _preset()
var a := TestUtils.check(preset != "", "a Web export preset exists")
var b := TestUtils.check(preset.contains('platform="Web"'), "preset targets the Web platform")
var c := TestUtils.check(preset.contains('export_path="build/web/index.html"'), "preset writes build/web/index.html")
return a and b and c
func test_web_preset_is_static_hosting_friendly() -> bool:
var preset := _preset()
return TestUtils.check(preset.contains("variant/thread_support=false"),
"threads are disabled so no COOP/COEP headers are required")
func test_release_scripts_build_the_web_zip() -> bool:
var build := FileAccess.get_file_as_string("res://tools/build_releases.sh")
var a := TestUtils.check(build.contains('--export-release "Web"'), "build script exports Web")
var b := TestUtils.check(build.contains("step-line-web-${VERSION}.zip"), "build script names the web zip")
var publish := FileAccess.get_file_as_string("res://tools/publish_release.sh")
var c := TestUtils.check(publish.contains("step-line-web-$VERSION.zip"), "publish script uploads the web zip")
return a and b and c
func test_web_build_files_present_when_exported() -> bool:
## Only asserts shape if a web build exists in build/web (created by the
## release script); missing build output is not a test failure by itself.
var index := "res://build/web/index.html"
if not FileAccess.file_exists(index):
return true
var html := FileAccess.get_file_as_string(index)
var a := TestUtils.check(html.contains("index.js"), "index.html loads index.js")
var b := TestUtils.check(FileAccess.file_exists("res://build/web/index.wasm"), "wasm payload exists")
var c := TestUtils.check(FileAccess.file_exists("res://build/web/index.pck"), "pck payload exists")
return a and b and c