§
    �½j’!  ã                   óT  — d Z ddlZddlmc mZ ddlZddlZddl	Z	ddl
mZ  ee¦  «                             ¦   «         j        j        j        Zedz  dz  Zedz  Zedz  dz  dz  Zed	z  Zedz  dz  d
z  Zg d¢Zg d¢Z G d„ dej        ¦  «        Zedk    r ej        ¦   «          dS dS )a¾  
Unit tests for FreeExile WebApp Dynamic Templates and UI Template Manager.
Verifies modular extraction of all modal markups from index.html into:
- Modular HTML templates in client/webapp/templates/
- Domain-driven JS template catalogs in client/webapp/js/ui/templates/
- UITemplateManager in client/webapp/js/ui/template_manager.js
- Minimal, clean index.html conforming to GEMINI.md Section 2.9 (<= 200 lines soft cap, <= 400 lines hard cap).
é    N)ÚPathÚclientÚwebappÚ	templatesÚjsÚuiz
index.htmlztemplate_manager.js)zmodal-game-noticezmodal-npc-dialoguezmodal-meridianzmodal-vaultzmodal-characterz	modal-bagzmodal-loot-filterzmodal-megashopzmodal-checkoutz
modal-web3zmodal-seasonzmodal-agent-orbzmodal-harvest-reportzmodal-worldmapzmodal-dungeonzmodal-hideoutzmodal-endgame-atlaszmodal-war-fogzmodal-forgezmodal-settingszmodal-feedbackzmodal-accountzmodal-char-createzmodal-story-questszmodal-divine-vaultzmodal-combat-test-dashboard)ztemplate_catalog_system.jsztemplate_catalog_auth.jsztemplate_catalog_inventory.jsztemplate_catalog_world.jsztemplate_catalog_activities.jsztemplate_catalog_endgame.jsc                   óZ   — e Zd Zed„ ¦   «         Zd„ Zd„ Zd„ Zd„ Zd„ Z	d„ Z
d„ Zd	„ Zd
„ ZdS )ÚTestWebAppDynamicTemplatesc                 ó‚   — t                                d¬¦  «        | _        | j                             ¦   «         | _        d S )Núutf-8©Úencoding)Ú
INDEX_HTMLÚ	read_textÚindex_contentÚ
splitlinesÚindex_lines)Úclss    úAC:\Projects\FreeExile\tests\unit\test_webapp_dynamic_templates.pyÚ
setUpClassz%TestWebAppDynamicTemplates.setUpClass>   s5   € å&×0Ò0¸'Ð0ÑBÔBˆÔØÔ+×6Ò6Ñ8Ô8ˆŒˆˆó    c                 ó–   — t          | j        ¦  «        }|                      |dd|› �¦  «         |                      |dd|› �¦  «         dS )z_index.html must adhere to GEMINI.md Section 2.9 (<= 200 lines soft cap, <= 400 lines hard cap).éÈ   z'index.html exceeds 200 lines soft cap: é�  z'index.html exceeds 400 lines hard cap: N)Úlenr   ÚassertLessEqual)ÚselfÚ
line_counts     r   Ú&test_01_index_html_line_count_and_capszATestWebAppDynamicTemplates.test_01_index_html_line_count_and_capsC   s\   € å˜Ô)Ñ*Ô*ˆ
Ø×Ò˜Z¨Ð.dÐXbÐ.dÐ.dÑeÔeÐeØ×Ò˜Z¨Ð.dÐXbÐ.dÐ.dÑeÔeÐeÐeÐer   c                 óÔ   — |                       d| j        d¦  «         | j                             d¦  «        }| j                             d¦  «        }|                      ||d¦  «         dS )zQindex.html must provide #modal-container mount point for dynamic modal injection.zid="modal-container"z%index.html must have #modal-containerzid="game-tooltip"z8#modal-container must be inside viewport before tooltipsN)ÚassertInr   ÚindexÚ
assertLess)r   Úcontainer_idxÚtooltip_idxs      r   Ú(test_02_index_html_modal_container_mountzCTestWebAppDynamicTemplates.test_02_index_html_modal_container_mountI   sh   € à�ŠÐ,¨dÔ.@ÐBiÑjÔjÐjØÔ*×0Ò0Ð1GÑHÔHˆØÔ(×.Ò.Ð/BÑCÔCˆØ�Š˜ {Ð4nÑoÔoÐoÐoÐor   c                 ó.  — t           D ]%}|                      d|› �| j        d|› d�¦  «         Œ&|                      d| j        d¦  «         | j                             d¦  «        }| j                             d¦  «        }|                      ||d¦  «         dS )	z[index.html must import all template catalogs and template_manager.js before UI controllers.zjs/ui/templates/zMissing z import in index.htmlzjs/ui/template_manager.jsz)Missing template_manager.js in index.htmlzjs/ui/meridian_vault.jsz:template_manager.js must be imported before UI controllersN)ÚEXPECTED_CATALOGSr!   r   r"   r#   )r   ÚcatÚmgr_idxÚmeridian_idxs       r   Ú8test_03_index_html_imports_template_catalogs_and_managerzSTestWebAppDynamicTemplates.test_03_index_html_imports_template_catalogs_and_managerP   s«   € å$ð 	oð 	oˆCØ�MŠMÐ2¨SÐ2Ð2°DÔ4FÐHmÐSVÐHmÐHmÐHmÑnÔnÐnÐnØ�ŠÐ1°4Ô3EÐGrÑsÔsÐsàÔ$×*Ò*Ð+FÑGÔGˆØÔ)×/Ò/Ð0IÑJÔJˆØ�Š˜ Ð/kÑlÔlÐlÐlÐlr   c           	      ó  — |                       t                               ¦   «         d¦  «         t          t                               d¦  «        ¦  «        }|                      t          |¦  «        ddt          |¦  «        › �¦  «         |D ]{}|                     d¬¦  «        }t          |                     ¦   «         ¦  «        }|  	                    |dd|j
        › d	�¦  «         |                      |d
d|j
        › d|› �¦  «         Œ|dS )zUAll 25 modal HTML files in client/webapp/templates/ must exist and have <= 400 lines.ztemplates directory must existz*.htmlé   z+Expected at least 25 template files, found r   r   r   z	Template z	 is emptyr   z exceeds 400 lines: N)Ú
assertTrueÚTEMPLATES_DIRÚis_dirÚlistÚglobÚassertGreaterEqualr   r   r   ÚassertGreaterÚnamer   )r   Ú
html_filesÚ	html_fileÚcontentÚliness        r   Ú-test_04_html_template_files_exist_and_boundedzHTestWebAppDynamicTemplates.test_04_html_template_files_exist_and_boundedZ   s  € à�Š�×,Ò,Ñ.Ô.Ð0PÑQÔQÐQÝ�-×,Ò,¨XÑ6Ô6Ñ7Ô7ˆ
Ø×Ò¥ J¡¤°Ð5tÕcfÐgqÑcrÔcrÐ5tÐ5tÑuÔuÐuà#ð 	fð 	fˆIØ×)Ò)°7Ð)Ñ;Ô;ˆGÝ˜×*Ò*Ñ,Ô,Ñ-Ô-ˆEØ×Ò˜u aÐ)N°Y´^Ð)NÐ)NÐ)NÑOÔOÐOØ× Ò  ¨Ð-d¸¼Ð-dÐ-dÐ]bÐ-dÐ-dÑeÔeÐeÐeð		fð 	fr   c           	      ó¾  — |                       t                               ¦   «         d¦  «         t          D ]§}t          |z  }|                       |                     ¦   «         d|› d�¦  «         t          |                     d¬¦  «                             ¦   «         ¦  «        }|                      |dd|› d|› �¦  «         |                      |dd|› d	|› �¦  «         Œ¨d
S )z]All 6 JS template catalogs must exist and have <= 700 lines soft cap, <= 1000 lines hard cap.z$js/ui/templates directory must existzCatalog z must existr   r   i¼  z exceeds 700 lines soft cap: iè  z exceeds 1000 lines hard cap: N)	r/   ÚJS_TEMPLATES_DIRr1   r(   Úis_filer   r   r   r   )r   r)   Úcat_pathr:   s       r   Ú%test_05_js_catalogs_exist_and_boundedz@TestWebAppDynamicTemplates.test_05_js_catalogs_exist_and_boundedf   sø   € à�ŠÕ(×/Ò/Ñ1Ô1Ð3YÑZÔZÐZå$ð 	eð 	eˆCÝ'¨#Ñ-ˆHØ�OŠO˜H×,Ò,Ñ.Ô.Ð0K¸3Ð0KÐ0KÐ0KÑLÔLÐLÝ˜×*Ò*°GÐ*Ñ<Ô<×GÒGÑIÔIÑJÔJˆEØ× Ò  ¨Ð-a¸Ð-aÐ-aÐZ_Ð-aÐ-aÑbÔbÐbØ× Ò  ¨Ð.c¸Ð.cÐ.cÐ\aÐ.cÐ.cÑdÔdÐdÐdð	eð 	er   c                 ó  — |                       t                               ¦   «         d¦  «         t          t                               d¬¦  «                             ¦   «         ¦  «        }|                      |dd|› �¦  «         dS )zJtemplate_manager.js must exist and adhere to code soft cap (<= 350 lines).ztemplate_manager.js must existr   r   i^  z'template_manager.js exceeds 350 lines: N)r/   ÚTEMPLATE_MANAGER_JSr>   r   r   r   r   )r   r:   s     r   Ú#test_06_js_template_manager_boundedz>TestWebAppDynamicTemplates.test_06_js_template_manager_boundedq   sw   € à�ŠÕ+×3Ò3Ñ5Ô5Ð7WÑXÔXÐXÝÕ'×1Ò1¸7Ð1ÑCÔC×NÒNÑPÔPÑQÔQˆØ×Ò˜U CÐ)ZÐSXÐ)ZÐ)ZÑ[Ô[Ð[Ð[Ð[r   c                 ó    — d                      d„ t          D ¦   «         ¦  «        }t          D ]!}|                      d|› d�|d|› d�¦  «         Œ"dS )zHAll 25 canonical modals must be registered across the template catalogs.ú
c              3   óR   K  — | ]"}t           |z                       d ¬¦  «        V — Œ#dS )r   r   N)r=   r   ©Ú.0r)   s     r   ú	<genexpr>zUTestWebAppDynamicTemplates.test_07_all_canonical_modals_registered.<locals>.<genexpr>y   sJ   è è € ð &
ð &
ØEHÕ Ñ#×.Ò.¸Ð.Ñ@Ô@ð&
ð &
ð &
ð &
ð &
ð &
r   ú'zModal z not registered in catalogsN)Újoinr(   ÚEXPECTED_MODALSr!   )r   Úcombined_catalogsÚmodal_ids      r   Ú'test_07_all_canonical_modals_registeredzBTestWebAppDynamicTemplates.test_07_all_canonical_modals_registeredw   s   € à ŸIšIð &
ð &
ÝL]ð&
ñ &
ô &
ñ 
ô 
Ðõ (ð 	nð 	nˆHØ�MŠM˜/˜h˜/˜/˜/Ð+<Ð>lÀxÐ>lÐ>lÐ>lÑmÔmÐmÐmð	nð 	nr   c           	      óê   — t           gd„ t          D ¦   «         z   }|D ]U}t          j        ddt	          |¦  «        gdd¬¦  «        }|                      |j        dd|j        › d|j        › �¦  «         ŒVd	S )
zIAll template catalogs and manager must pass Node.js syntax parsing check.c                 ó"   — g | ]}t           |z  ‘ŒS © )r=   rG   s     r   ú
<listcomp>zKTestWebAppDynamicTemplates.test_08_node_syntax_validity.<locals>.<listcomp>‚   s   € Ð(]Ð(]Ð(]ÀCÕ)9¸CÑ)?Ð(]Ð(]Ð(]r   Únodez--checkT)Úcapture_outputÚtextr   zSyntax error in z: N)	rB   r(   Ú
subprocessÚrunÚstrÚassertEqualÚ
returncoder6   Ústderr)r   ÚfilesÚfÚress       r   Útest_08_node_syntax_validityz7TestWebAppDynamicTemplates.test_08_node_syntax_validity€   s’   € å$Ð%Ð(]Ð(]ÕK\Ð(]Ñ(]Ô(]Ñ]ˆØð 	[ð 	[ˆAÝ”. &¨)µS¸±V´VÐ!<ÈTÐX\Ð]Ñ]Ô]ˆCØ×Ò˜Sœ^¨QÐ0YÀ1Ä6Ð0YÐ0YÈSÌZÐ0YÐ0YÑZÔZÐZÐZð	[ð 	[r   c                 óâ   — d}t          j        dd|gt          t          ¦  «        dd¬¦  «        }|                      |j        dd|j        › �¦  «         |                      d|j        ¦  «         d	S )
zYUITemplateManager must normalize IDs bidirectionally and resolve candidate template URLs.a"  
        const fs = require('fs');
        global.window = {};
        global.document = {
            readyState: 'complete',
            getElementById: () => null,
            querySelector: () => null,
            addEventListener: () => {},
            dispatchEvent: () => {}
        };
        global.CustomEvent = class {};

        // Load system catalog and manager
        eval(fs.readFileSync('client/webapp/js/ui/templates/template_catalog_system.js', 'utf8'));
        eval(fs.readFileSync('client/webapp/js/ui/template_manager.js', 'utf8'));

        const mgr = window.UITemplateManager;
        const assert = (cond, msg) => { if (!cond) throw new Error(msg); };

        assert(mgr.has('modal-settings'), 'has(modal-settings) should be true');
        assert(mgr.has('settings'), 'has(settings) should be true');
        assert(mgr.get('settings').length > 0, 'get(settings) should return html');
        assert(mgr.get('settings') === mgr.get('modal-settings'), 'get(settings) should match get(modal-settings)');

        assert(mgr.has('combat-test-dashboard'), 'has(combat-test-dashboard) should be true');
        assert(mgr.has('modal-combat-test-dashboard'), 'has(modal-combat-test-dashboard) should be true');

        const urls1 = mgr.resolveCandidateUrls('settings');
        assert(urls1.includes('templates/settings_modal.html'), 'should include settings_modal.html: ' + urls1);

        const urls2 = mgr.resolveCandidateUrls('modal-feedback');
        assert(urls2.includes('templates/feedback_modal.html'), 'should include feedback_modal.html: ' + urls2);

        const urls3 = mgr.resolveCandidateUrls('story-quests');
        assert(urls3.includes('templates/story_quests_modal.html'), 'should include story_quests_modal.html: ' + urls3);

        console.log('ALL_CHECKS_PASSED');
        rT   z-eT)ÚcwdrU   rV   r   zNode verification failed: ÚALL_CHECKS_PASSEDN)	rW   rX   rY   ÚPROJECT_ROOTrZ   r[   r\   r!   Ústdout)r   Únode_scriptr_   s      r   Ú9test_09_template_manager_normalization_and_url_resolutionzTTestWebAppDynamicTemplates.test_09_template_manager_normalization_and_url_resolution‡   sw   € ð%ˆõL Œn˜f d¨KÐ8½cÅ,Ñ>OÔ>OÐ`dÐkoÐpÑpÔpˆØ×Ò˜œ¨Ð,UÈÌÐ,UÐ,UÑVÔVÐVØ�ŠÐ)¨3¬:Ñ6Ô6Ð6Ð6Ð6r   N)Ú__name__Ú
__module__Ú__qualname__Úclassmethodr   r   r&   r,   r;   r@   rC   rO   r`   rg   rR   r   r   r
   r
   =   sÌ   € € € € € Øð9ð 9ñ „[ð9ðfð fð fðpð pð pðmð mð mð
fð 
fð 
fð	eð 	eð 	eð\ð \ð \ðnð nð nð[ð [ð [ð*7ð *7ð *7ð *7ð *7r   r
   Ú__main__)Ú__doc__ÚbuiltinsÚ@py_builtinsÚ_pytest.assertion.rewriteÚ	assertionÚrewriteÚ
@pytest_arÚunittestÚosrW   Úpathlibr   Ú__file__ÚresolveÚparentrd   Ú
WEBAPP_DIRr0   r=   r   rB   rL   r(   ÚTestCaser
   rh   ÚmainrR   r   r   ú<module>r}      sJ  ððð ð € € € € € € € € € € € € €€€€Ø 	€	€	€	Ø Ð Ð Ð Ø Ð Ð Ð Ð Ð àˆt�H‰~Œ~×%Ò%Ñ'Ô'Ô.Ô5Ô<€Ø˜HÑ$ xÑ/€
Ø˜[Ñ(€Ø Ñ$ tÑ+¨kÑ9Ð Ø˜,Ñ&€
Ø  4Ñ'¨$Ñ.Ð1FÑFÐ ðð ð €ð:ð ð Ð ðt7ð t7ð t7ð t7ð t7 Ô!2ñ t7ô t7ð t7ðn ˆzÒÐØ€H„M�O„O€O€O€Oð Ðr   