extends TestCase ## T-WIN-012:版本号展示(文档 §11) ## ## 硬性要求是「单一来源 + 可核对」: ## 版本号只允许有一处权威定义(project.godot 的 application/config/version), ## 界面从该来源读取,且必须与 project.yaml / 产物文件名 / Git tag 一致。 ## 因此这里同时核对 project.godot、project.yaml、README 三处。 const AboutScreen = preload("res://src/ui/about_screen.gd") const Credits = preload("res://src/ui/credits.gd") func _read_text(path: String) -> String: if not FileAccess.file_exists(path): return "" var file := FileAccess.open(path, FileAccess.READ) if file == null: return "" var text := file.get_as_text() file.close() return text func test_version_is_semver_and_matches_project_yaml() -> void: var version := AboutScreen.app_version() var parts := version.split(".") eq(parts.size(), 3, "版本号形如 X.Y.Z(实际 %s)" % version) for part in parts: ok(part.is_valid_int(), "版本号各段为整数(%s)" % part) var yaml := _read_text("res://project.yaml") ne(yaml, "", "可读取 project.yaml") contains(yaml, "version: %s" % version, "project.yaml 的 version 与 project.godot 一致") func test_about_manifest_lists_version() -> void: var manifest := AboutScreen.about_manifest() var found := {} for item in manifest: found[str(item["label"])] = str(item["value"]) ok(found.has("客户端版本"), "关于清单含「客户端版本」一项") eq(found.get("客户端版本", ""), "v%s" % AboutScreen.app_version(), "清单版本号与唯一来源一致") ok(found.has("契约版本"), "关于清单含「契约版本」") for key in Credits.CONTRACT_VERSIONS: contains(str(found.get("契约版本", "")), "%s v%s" % [key, Credits.CONTRACT_VERSIONS[key]], "清单含 %s 契约版本" % key) ok(str(found.get("隐私说明", "")).contains("不存储"), "关于清单声明不存储视频画面") func test_version_not_hardcoded_in_ui_sources() -> void: # 反例防护:界面代码里不允许再手写一份版本号(文档 §11.2 第 1 条) var version := AboutScreen.app_version() for path in ["res://src/ui/about_screen.gd", "res://src/ui/main_menu.gd", "res://src/ui/game_screen.gd"]: var text := _read_text(path) ne(text, "", "可读取 %s" % path) is_false(text.contains("\"%s\"" % version), "%s 未硬编码版本号字面量" % path.get_file()) func test_entry_scene_version_is_exported_into_build() -> void: # 导出产物名必须能由版本号推导(Documentation §11.2 第 2 条) var version := AboutScreen.app_version() contains("opendance-windows-v%s.zip" % version, version, "产物文件名包含版本号") ok(Credits.entry_count() >= 10, "开源声明条目仍齐备") func test_export_preset_version_matches_project_version() -> void: # 缺陷回归:export_presets.cfg 的 application/file_version 与 product_version # 决定导出后 exe 的 PE VERSIONINFO 资源,也就是 Windows「右键 → 属性 → # 详细信息」里显示的文件版本/产品版本。这两个键**不会**跟随 project.godot 的 # application/config/version 自动更新,v0.2.1 的发布包因此显示的是 0.1.0 # (产物名与 tag 都是 v0.2.1,二进制元数据却是 0.1.0)。 # 产物侧由 build/check-pe-version.sh 直接读 exe 复核,这里做静态防线。 var version := AboutScreen.app_version() var preset := _read_text("res://export_presets.cfg") ne(preset, "", "可读取 export_presets.cfg") contains(preset, "application/file_version=\"%s\"" % version, "导出预设的 file_version 与版本号唯一来源一致") contains(preset, "application/product_version=\"%s\"" % version, "导出预设的 product_version 与版本号唯一来源一致")