196 lines
8.4 KiB
GDScript
196 lines
8.4 KiB
GDScript
extends SceneTree
|
|
|
|
const EntryShell = preload("res://entry/entry_shell.gd")
|
|
const InitialCompanyArt = preload("res://entry/initial_company_art.gd")
|
|
const SettingsStore = preload("res://entry/settings_store.gd")
|
|
const DraftService = preload("res://entry/initial_company_draft_service.gd")
|
|
|
|
const DRAFT_PATH := "user://dev2_initial_company_choice_test.json"
|
|
const ERROR_PATH := "user://dev2_initial_company_choice_error.json"
|
|
const SEED := "89abcdef0123456776543210fedcba98"
|
|
|
|
var failures: Array[String] = []
|
|
|
|
|
|
func _initialize() -> void:
|
|
call_deferred("run_test")
|
|
|
|
|
|
func run_test() -> void:
|
|
_cleanup()
|
|
verify_profession_art_registry()
|
|
await verify_choice_inspect_compare_selection_and_restart()
|
|
await verify_corrupt_draft_error_and_back()
|
|
_cleanup()
|
|
if failures.is_empty():
|
|
print("ABG_DEV2_CHOICE_OK title=true offers=4 inspect=true compare=true selected=0,1,2 third_blocked=true review_gate=true restart=true error=true back=true")
|
|
quit(0)
|
|
else:
|
|
for failure in failures:
|
|
push_error(failure)
|
|
quit(1)
|
|
|
|
|
|
func verify_choice_inspect_compare_selection_and_restart() -> void:
|
|
var shell = await _shell(DRAFT_PATH)
|
|
shell.show_title()
|
|
shell.open_new_game_boundary()
|
|
await _frames(3)
|
|
var page = shell.initial_company_page
|
|
expect(shell.current_screen == "initial_company", "Title New Game opens Initial Company")
|
|
expect(page.find_child("CandidateRow", true, false).get_child_count() == 4, "choice page renders exactly four equal offer columns")
|
|
expect(page.find_child("SelectedCount", true, false).text.contains("0/2"), "choice begins at 0/2")
|
|
expect(page.find_child("ReviewCompany", true, false).disabled, "Review is disabled at 0/2")
|
|
var original_ids := _offer_ids(page.draft)
|
|
verify_candidate_stickers(page)
|
|
|
|
page.inspect_candidate(2)
|
|
await _frames(2)
|
|
expect(page.mode == "inspect" and page.find_child("InspectBody", true, false) != null and page.find_child("InspectPortraitStagePortrait", true, false) != null, "Inspect opens complete portrait-led candidate detail")
|
|
expect(page.draft.selected_offer_ids.is_empty(), "Inspect does not change selection")
|
|
page.set_compare_a()
|
|
await _frames(2)
|
|
expect(page.compare_a_index == 2 and page.mode == "choice", "inspected candidate can be assigned to Compare A")
|
|
page.inspect_candidate(0)
|
|
page.set_compare_b()
|
|
await _frames(2)
|
|
expect(page.compare_b_index == 0 and not page.find_child("OpenCompare", true, false).disabled, "a different inspected candidate enables Compare")
|
|
page.show_compare()
|
|
await _frames(2)
|
|
expect(page.mode == "compare" and page.find_child("ComparePortraitAPortrait", true, false) != null and page.find_child("ComparePortraitBPortrait", true, false) != null, "Compare renders two Recruit stickers together")
|
|
expect(page.draft.selected_offer_ids.is_empty(), "Compare does not change selection")
|
|
page.request_back()
|
|
await _frames(2)
|
|
|
|
page.toggle_candidate(0)
|
|
await _frames(2)
|
|
expect(page.draft.selected_offer_ids == [original_ids[0]] and page.find_child("ReviewCompany", true, false).disabled, "one selection persists and keeps Review disabled")
|
|
page.toggle_candidate(1)
|
|
await _frames(2)
|
|
expect(page.draft.selected_offer_ids == [original_ids[0], original_ids[1]], "second independent selection persists")
|
|
expect(not page.find_child("ReviewCompany", true, false).disabled and page.find_child("SelectedCount", true, false).text.contains("2/2"), "exactly 2/2 enables Review")
|
|
page.toggle_candidate(2)
|
|
await _frames(2)
|
|
expect(page.draft.selected_offer_ids == [original_ids[0], original_ids[1]], "third selection attempt leaves the selected pair unchanged")
|
|
expect(not page.notice.is_empty(), "third selection attempt gives a visible reason")
|
|
page.request_review()
|
|
await _frames(2)
|
|
expect(page.mode == "review" and page.find_child("ReviewSelectedPortrait_0Portrait", true, false) != null and page.find_child("ReviewSelectedPortrait_1Portrait", true, false) != null and page.find_child("ReviewUnchosenPortrait_0", true, false) != null, "enabled Review shows selected and unchosen Recruit stickers")
|
|
page.revise_selection()
|
|
await _frames(2)
|
|
expect(page.mode == "choice" and page.draft.selected_offer_ids.size() == 2, "Revise returns to the same draft and pair")
|
|
page.request_back()
|
|
await _frames(2)
|
|
expect(shell.current_screen == "title", "choice Back returns to Title")
|
|
shell.queue_free()
|
|
await _frames(3)
|
|
|
|
var restarted = await _shell(DRAFT_PATH)
|
|
restarted.show_initial_company()
|
|
await _frames(3)
|
|
var restored = restarted.initial_company_page
|
|
expect(_offer_ids(restored.draft) == original_ids, "restart restores the same four IDs and positions")
|
|
expect(restored.draft.selected_offer_ids == [original_ids[0], original_ids[1]], "restart restores the selected pair")
|
|
expect(not restored.find_child("ReviewCompany", true, false).disabled, "restart restores 2/2 Review gating")
|
|
restarted.queue_free()
|
|
await _frames(3)
|
|
|
|
|
|
func verify_corrupt_draft_error_and_back() -> void:
|
|
_write(ERROR_PATH, "{broken")
|
|
_write("%s.bak" % ERROR_PATH, "{also broken")
|
|
var shell = await _shell(ERROR_PATH)
|
|
shell.show_initial_company()
|
|
await _frames(3)
|
|
var page = shell.initial_company_page
|
|
expect(page.find_child("DraftErrorCode", true, false) != null and page.find_child("DraftErrorCode", true, false).text.contains("DRAFT_CORRUPT"), "corrupt replicas show the exact safe error")
|
|
expect(page.find_child("DraftErrorRetry", true, false) != null and page.find_child("DraftErrorBack", true, false) != null, "error state provides Retry and Back")
|
|
page.request_back()
|
|
await _frames(2)
|
|
expect(shell.current_screen == "title", "error Back returns to Title")
|
|
shell.queue_free()
|
|
await _frames(3)
|
|
|
|
|
|
func _shell(draft_path: String):
|
|
var shell = EntryShell.new()
|
|
shell.auto_start = false
|
|
shell.initial_company_service.path = draft_path
|
|
shell.initial_company_service.company_path = "%s.company" % draft_path
|
|
root.add_child(shell)
|
|
await _frames(2)
|
|
shell.settings = SettingsStore.new().defaults()
|
|
shell.settings.setup_completed = true
|
|
shell.settings.locale = "en"
|
|
if draft_path == DRAFT_PATH:
|
|
var service = DraftService.new()
|
|
service.path = draft_path
|
|
service.company_path = "%s.company" % draft_path
|
|
service.begin_or_load(SEED)
|
|
return shell
|
|
|
|
|
|
func _offer_ids(draft: Dictionary) -> Array[String]:
|
|
var result: Array[String] = []
|
|
for offer in draft.offers:
|
|
result.append(String(offer.offer_id))
|
|
return result
|
|
|
|
|
|
func verify_profession_art_registry() -> void:
|
|
var paths: Array[String] = []
|
|
for index in range(1, 13):
|
|
var profession_id := "PF-B%02d" % index
|
|
var texture: Texture2D = InitialCompanyArt.texture_for({"profession_id": profession_id})
|
|
expect(texture != null and not texture.resource_path.is_empty(), "%s has a runtime Recruit sticker" % profession_id)
|
|
paths.append(texture.resource_path)
|
|
expect(paths.duplicate().size() == 12 and _unique(paths).size() == 12, "all 12 base Professions use one-to-one Recruit stickers")
|
|
|
|
|
|
func verify_candidate_stickers(page: Control) -> void:
|
|
var paths: Array[String] = []
|
|
for index in range(4):
|
|
var portrait := page.find_child("CandidatePortrait_%d" % index, true, false) as TextureRect
|
|
var expected: Texture2D = InitialCompanyArt.texture_for(page.draft.offers[index])
|
|
expect(portrait != null and portrait.texture == expected, "candidate %d is a person-bearing control with the matching Profession sticker" % index)
|
|
if portrait != null and portrait.texture != null:
|
|
paths.append(portrait.texture.resource_path)
|
|
expect(_unique(paths).size() == 4, "the four visible candidates do not reuse one character image")
|
|
|
|
|
|
func _unique(values: Array[String]) -> Array[String]:
|
|
var result: Array[String] = []
|
|
for value in values:
|
|
if value not in result:
|
|
result.append(value)
|
|
return result
|
|
|
|
|
|
func _write(file_path: String, text: String) -> void:
|
|
var file := FileAccess.open(file_path, FileAccess.WRITE)
|
|
file.store_string(text)
|
|
file.close()
|
|
|
|
|
|
func _cleanup() -> void:
|
|
for base in [DRAFT_PATH, ERROR_PATH]:
|
|
for suffix in ["", ".bak", ".candidate", ".bak.candidate", ".corrupt"]:
|
|
var file_path := "%s%s" % [base, suffix]
|
|
if FileAccess.file_exists(file_path):
|
|
DirAccess.remove_absolute(file_path)
|
|
var company_base := "%s.company" % base
|
|
for suffix in ["", ".bak", ".candidate", ".bak.candidate", ".corrupt"]:
|
|
var company_file := "%s%s" % [company_base, suffix]
|
|
if FileAccess.file_exists(company_file):
|
|
DirAccess.remove_absolute(company_file)
|
|
|
|
|
|
func _frames(count: int) -> void:
|
|
for frame in range(count):
|
|
await process_frame
|
|
|
|
|
|
func expect(condition: bool, message: String) -> void:
|
|
if not condition:
|
|
failures.append("DEV-2 Recruit choice: %s" % message)
|