import copy import unittest from pathlib import Path import numpy as np from PIL import Image from automation.pages import PageMap ROOT = Path(__file__).resolve().parent.parent class PageTests(unittest.TestCase): def setUp(self): self.page_map = PageMap(ROOT) def frame(self, *page_ids): image = Image.new('RGB', (562, 1002), (35, 50, 70)) for page_id in page_ids: for spec in self.page_map.pages[page_id]['recognition'][0]: with Image.open(ROOT / 'assets' / spec['template']) as template: x, y = spec['search'][:2] image.paste(template.convert('RGB'), (x + 4, y + 4)) return np.asarray(image) def test_primary_pages_are_distinct(self): for page_id in ('home', 'shop', 'heroes', 'king', 'territory', 'guild'): with self.subTest(page=page_id): result = self.page_map.identify(self.frame(page_id)) self.assertEqual(result['status'], 'identified') self.assertEqual(result['page']['id'], page_id) def test_white_or_darkened_frame_is_not_treated_as_home(self): self.assertEqual(self.page_map.identify(np.full((1002, 562, 3), 255, dtype=np.uint8))['status'], 'unknown') dark = (self.frame('home').astype(float) * .35).astype(np.uint8) self.assertEqual(self.page_map.identify(dark)['status'], 'unknown') def test_overlay_has_priority_and_does_not_guess_its_parent(self): result = self.page_map.identify(self.frame('shop', 'reward')) self.assertEqual(result['page']['id'], 'reward') self.assertIsNone(self.page_map.pages['reward']['parent']) def test_duplicate_identity_reports_ambiguity(self): duplicate = copy.deepcopy(self.page_map.pages['territory']) duplicate['id'] = 'another_territory' self.page_map.pages[duplicate['id']] = duplicate result = self.page_map.identify(self.frame('territory')) self.assertEqual(result['status'], 'ambiguous') self.assertIsNone(result['page']) def test_specific_tab_supersedes_matching_overlay_and_background(self): container = copy.deepcopy(self.page_map.pages['reward']) container['id'] = 'test.container' self.page_map.pages[container['id']] = container # Keep the generic reward out of this fixture: it has no known parent. self.page_map.pages['reward']['recognition'] = [] tab = copy.deepcopy(container) tab.update(id='test.tab', parent='test.container', kind='tab') self.page_map.pages[tab['id']] = tab result = self.page_map.identify(self.frame('shop', 'test.tab')) self.assertEqual(result['page']['id'], 'test.tab') self.assertEqual(result['status'], 'identified') def test_territory_to_recruit_route_includes_home_and_shop(self): route = self.page_map.route('territory', 'recruit.lamp') self.assertEqual([edge['to'] for edge in route], ['home', 'shop', 'recruit.lamp']) self.assertIn('condition', route[-1]) def test_unverified_paths_are_excluded(self): with self.assertRaises(ValueError): self.page_map.route('home', 'guild.boss') with self.assertRaises(ValueError): self.page_map.route('reward', 'home') def test_shared_progress_popup_requires_known_origin(self): frame = self.frame('planet.progress') self.assertEqual(self.page_map.identify(frame)['status'], 'ambiguous') self.assertEqual(self.page_map.identify(frame, previous_page='territory.rank.board')['page']['id'], 'territory.rank.progress') self.assertEqual(self.page_map.identify(frame, previous_page='planet.rank')['page']['id'], 'planet.progress') self.assertEqual(self.page_map.identify(frame, previous_page='home')['status'], 'ambiguous') def test_mode_selection_uses_its_distinct_card_label(self): for page_id in ('coop.selection', 'arena.selection'): with self.subTest(page=page_id): result = self.page_map.identify(self.frame(page_id)) self.assertEqual(result['page']['id'], page_id) def test_pet_weekly_challenge_is_not_home_weekly_tasks(self): # Actual audit pixels retain the similar task title that previously # matched home weekly tasks; the selected navigation label differs. frame = np.asarray(Image.open(ROOT / 'tests/fixtures/pet_challenge_identity.png').convert('RGB')) result = self.page_map.identify(frame) self.assertEqual(result['page']['id'], 'coop.pet.challenge.weekly') self.assertNotIn('tasks.weekly', [p['id'] for p in result['candidates']]) def test_history_does_not_resolve_unrelated_matches(self): duplicate = copy.deepcopy(self.page_map.pages['territory']) duplicate.update(id='test.unknown_territory', parent='home') self.page_map.pages[duplicate['id']] = duplicate result = self.page_map.identify(self.frame('territory'), previous_page='home') self.assertEqual(result['status'], 'ambiguous') if __name__ == '__main__': unittest.main()