§
    uÆ»jV3  ã                   ó^  — d Z ddlZddlZddlZddlZddlmc mZ ddl	m
Z
  e
e¦  «                             ¦   «         j        j        j        Zedz  Zedz  Zedz  Z G d„ dej        ¦  «        Z G d	„ d
ej        ¦  «        Z G d„ dej        ¦  «        Zedk    r ej        ¦   «          dS dS )z¿
Unit tests for FreeExile iOS and Android Native Platform Release Packaging.
Verifies project configurations, manifests, security, entitlements,
and Swift/Kotlin native bridge architectures.
é    N)ÚPathÚplatformÚiosÚandroidc                   ó0   — e Zd ZdZd„ Zd„ Zd„ Zd„ Zd„ ZdS )ÚTestIOSPlatformPackagingz[Verifies iOS Xcode project structure, Info.plist, Privacy Manifest, and Swift bridge files.c                 óT  — t           dz  t           dz  dz  t           dz  dz  t           dz  dz  t           dz  dz  t           dz  dz  t           dz  dz  t           dz  dz  t           dz  d	z  t           d
z  dz  g
}|D ]-}|                      |                     ¦   «         d|› �¦  «         Œ.dS )z2All required iOS files and directories must exist.Ú	FreeExileú
Info.plistúPrivacyInfo.xcprivacyúAppDelegate.swiftzFreeExileApp.swiftúViewController.swiftúHapticBridge.swiftúStoreKitManager.swiftúAppAttestManager.swiftzFreeExile.xcodeprojzproject.pbxprojzMissing iOS project file: N)ÚIOS_DIRÚ
assertTrueÚexists©ÚselfÚrequired_pathsÚps      úJC:\Projects\FreeExile\tests\unit\test_mobile_platform_release_packaging.pyÚ!test_ios_project_structure_existsz:TestIOSPlatformPackaging.test_ios_project_structure_exists   sØ   € õ �kÑ!Ý�kÑ! LÑ0Ý�kÑ!Ð$;Ñ;Ý�kÑ!Ð$7Ñ7Ý�kÑ!Ð$8Ñ8Ý�kÑ!Ð$:Ñ:Ý�kÑ!Ð$8Ñ8Ý�kÑ!Ð$;Ñ;Ý�kÑ!Ð$<Ñ<ÝÐ+Ñ+Ð.?Ñ?ð
ˆð  ð 	Jð 	JˆAØ�OŠO˜AŸHšH™JœJÐ(HÀQÐ(HÐ(HÑIÔIÐIÐIð	Jð 	Jó    c                 ó  — t           dz  dz  }t          |d¦  «        5 }t          j        |¦  «        }ddd¦  «         n# 1 swxY w Y   |                      |                     d¦  «        d¦  «         |                      |                     d¦  «        d¦  «         |                      |                     d	¦  «        d
¦  «         |                      |                     d¦  «        d¦  «         |                      |                     d¦  «        d¦  «         |                      |                     d¦  «        d¦  «         |                      |                     d¦  «        d¦  «         |                     dg ¦  «        }|                      d|¦  «         |                      d|¦  «         |                     di ¦  «        }|                      |                     dd¦  «        p|                     dd¦  «        ¦  «         dS )zIInfo.plist must parse as valid XML plist and contain exact required keys.r
   r   ÚrbNÚCFBundleIdentifierzcom.freeexile.arpgÚCFBundleShortVersionStringz1.0.0ÚCFBundleVersionÚ1ÚUIRequiresFullScreenz!UIRequiresFullScreen must be trueÚUIStatusBarHiddenzUIStatusBarHidden must be trueÚ(UIViewControllerBasedStatusBarAppearancez6UIViewControllerBasedStatusBarAppearance must be falseÚITSAppUsesNonExemptEncryptionz+ITSAppUsesNonExemptEncryption must be falseÚ UISupportedInterfaceOrientationsÚ#UIInterfaceOrientationLandscapeLeftÚ$UIInterfaceOrientationLandscapeRightÚNSAppTransportSecurityÚ"NSAllowsArbitraryLoadsInWebContentFÚNSAllowsLocalNetworking)	r   ÚopenÚplistlibÚloadÚassertEqualÚgetr   ÚassertFalseÚassertIn)r   Ú
plist_pathÚfÚplistÚorientationsÚatss         r   Útest_ios_info_plist_validityz5TestIOSPlatformPackaging.test_ios_info_plist_validity(   s'  € å˜{Ñ*¨\Ñ9ˆ
Ý�*˜dÑ#Ô#ð 	% qÝ”M !Ñ$Ô$ˆEð	%ð 	%ð 	%ñ 	%ô 	%ð 	%ð 	%ð 	%ð 	%ð 	%ð 	%øøøð 	%ð 	%ð 	%ð 	%ð 	×Ò˜ŸšÐ#7Ñ8Ô8Ð:NÑOÔOÐOØ×Ò˜ŸšÐ#?Ñ@Ô@À'ÑJÔJÐJØ×Ò˜ŸšÐ#4Ñ5Ô5°sÑ;Ô;Ð;Ø�Š˜Ÿ	š	Ð"8Ñ9Ô9Ð;^Ñ_Ô_Ð_Ø�Š˜Ÿ	š	Ð"5Ñ6Ô6Ð8XÑYÔYÐYØ×ÒØ�IŠIÐ@ÑAÔAØDñ	
ô 	
ð 	
ð 	×ÒØ�IŠIÐ5Ñ6Ô6Ø9ñ	
ô 	
ð 	
ð
 —y’yÐ!CÀRÑHÔHˆØ�ŠÐ;¸\ÑJÔJÐJØ�ŠÐ<¸lÑKÔKÐKà�iŠiÐ0°"Ñ5Ô5ˆØ�ŠØ�GŠGÐ8¸%Ñ@Ô@ð 9Ø�wŠwÐ0°%Ñ8Ô8ñ	
ô 	
ð 	
ð 	
ð 	
ó   ž?¿AÁAc           	      ó\  — t           dz  dz  }t          |d¦  «        5 }t          j        |¦  «        }ddd¦  «         n# 1 swxY w Y   |                      |                     d¦  «        d¦  «         |                      d|¦  «         |                     dg ¦  «        }d„ |D ¦   «         }|                      d	|¦  «         |                      d
|¦  «         |D ]R}|                     dg ¦  «        }|                      t          |¦  «        dd|                     d¦  «        › �¦  «         ŒSdS )zGPrivacyInfo.xcprivacy must comply with Apple May 2024 privacy mandates.r
   r   r   NÚNSPrivacyTrackingzNSPrivacyTracking must be falseÚNSPrivacyAccessedAPITypesc                 ó8   — g | ]}|                      d ¦  «        ‘ŒS )ÚNSPrivacyAccessedAPIType)r0   )Ú.0Úitems     r   ú
<listcomp>zQTestIOSPlatformPackaging.test_ios_privacy_manifest_compliance.<locals>.<listcomp>P   s%   € ÐYÐYÐYÀ4˜$Ÿ(š(Ð#=Ñ>Ô>ÐYÐYÐYr   Ú$NSPrivacyAccessedAPITypeUserDefaultsÚ&NSPrivacyAccessedAPITypeSystemBootTimeÚNSPrivacyAccessedAPITypeReasonsr   zReasons missing for r>   )	r   r,   r-   r.   r1   r0   r2   ÚassertGreaterÚlen)r   Úprivacy_pathr4   ÚprivacyÚaccessed_apisÚapi_type_namesr@   Úreasonss           r   Ú$test_ios_privacy_manifest_compliancez=TestIOSPlatformPackaging.test_ios_privacy_manifest_complianceF   sw  € å Ñ,Ð/FÑFˆÝ�, Ñ%Ô%ð 	'¨Ý”m AÑ&Ô&ˆGð	'ð 	'ð 	'ñ 	'ô 	'ð 	'ð 	'ð 	'ð 	'ð 	'ð 	'øøøð 	'ð 	'ð 	'ð 	'ð 	×Ò˜ŸšÐ%8Ñ9Ô9Ð;\Ñ]Ô]Ð]Ø�ŠÐ1°7Ñ;Ô;Ð;àŸšÐ$?ÀÑDÔDˆØYÐYÈ=ÐYÑYÔYˆØ�ŠÐ<¸nÑMÔMÐMØ�ŠÐ>ÀÑOÔOÐOà!ð 	oð 	oˆDØ—h’hÐ@À"ÑEÔEˆGØ×Ò�s 7™|œ|¨QÐ0mÀtÇxÂxÐPjÑGkÔGkÐ0mÐ0mÑnÔnÐnÐnð	oð 	or9   c                 óp  — t           dz  dz                       d¬¦  «        }|                      d|¦  «         |                      d|¦  «         |                      d|¦  «         |                      d|¦  «         t           dz  d	z                       d¬¦  «        }|                      d
|¦  «         |                      d|¦  «         |                      d|¦  «         |                      d|¦  «         |                      d|¦  «         t           dz  dz                       d¬¦  «        }|                      d|¦  «         |                      d|¦  «         |                      d|¦  «         |                      d|¦  «         |                      d|¦  «         |                      d|¦  «         |                      d|¦  «         t           dz  dz                       d¬¦  «        }|                      d|¦  «         |                      d|¦  «         |                      d|¦  «         |                      d|¦  «         t           dz  dz                       d¬¦  «        }|                      d|¦  «         |                      d|¦  «         |                      d|¦  «         |                      d |¦  «         d!S )"zKSwift files must define designated classes, protocols, and bridge handlers.r
   r   úutf-8©Úencodingzclass AppDelegatez.ambientÚregisterForRemoteNotificationsÚ0didRegisterForRemoteNotificationsWithDeviceTokenr   zclass ViewControllerz allowsInlineMediaPlayback = truez"haptic"z
"storeKit"z"appAttest"r   zclass HapticBridgeÚUIImpactFeedbackGeneratorz.heavyz.mediumz.rigidz.softÚUINotificationFeedbackGeneratorr   zclass StoreKitManagerzProduct.productszproduct.purchase()zTransaction.currentEntitlementsr   zclass AppAttestManagerÚDCAppAttestServiceÚ	attestKeyÚgenerateAssertionN)r   Ú	read_textr2   )r   Úapp_delegate_textÚview_controller_textÚhaptic_textÚstorekit_textÚapp_attest_texts         r   Ú.test_swift_source_classes_syntax_and_structurezGTestIOSPlatformPackaging.test_swift_source_classes_syntax_and_structureX   s¬  € å$ {Ñ2Ð5HÑH×SÒSÐ]dÐSÑeÔeÐØ�ŠÐ)Ð+<Ñ=Ô=Ð=Ø�Š�jÐ"3Ñ4Ô4Ð4Ø�ŠÐ6Ð8IÑJÔJÐJØ�ŠÐHÐJ[Ñ\Ô\Ð\å '¨+Ñ 5Ð8NÑ N×YÒYÐcjÐYÑkÔkÐØ�ŠÐ,Ð.BÑCÔCÐCØ�ŠÐ8Ð:NÑOÔOÐOØ�Š�jÐ"6Ñ7Ô7Ð7Ø�Š�lÐ$8Ñ9Ô9Ð9Ø�Š�mÐ%9Ñ:Ô:Ð:å Ñ,Ð/CÑC×NÒNÐX_ÐNÑ`Ô`ˆØ�ŠÐ*¨KÑ8Ô8Ð8Ø�ŠÐ1°;Ñ?Ô?Ð?Ø�Š�h Ñ,Ô,Ð,Ø�Š�i Ñ-Ô-Ð-Ø�Š�h Ñ,Ô,Ð,Ø�Š�g˜{Ñ+Ô+Ð+Ø�ŠÐ7¸ÑEÔEÐEå  ;Ñ.Ð1HÑH×SÒSÐ]dÐSÑeÔeˆØ�ŠÐ-¨}Ñ=Ô=Ð=Ø�ŠÐ(¨-Ñ8Ô8Ð8Ø�ŠÐ*¨MÑ:Ô:Ð:Ø�ŠÐ7¸ÑGÔGÐGå" [Ñ0Ð3KÑK×VÒVÐ`gÐVÑhÔhˆØ�ŠÐ.°Ñ@Ô@Ð@Ø�ŠÐ*¨OÑ<Ô<Ð<Ø�Š�k ?Ñ3Ô3Ð3Ø�ŠÐ)¨?Ñ;Ô;Ð;Ð;Ð;r   c           
      ó  — t           dz                       d¦  «        D ]e}|                     d¬¦  «                             ¦   «         }|                      t          |¦  «        d|j        › dt          |¦  «        › �¦  «         ŒfdS )z9No iOS file may exceed 500 lines per FreeExile standards.r
   z*.swiftrN   rO   éô  ú exceeds 500 lines: N)r   ÚglobrX   Ú
splitlinesÚassertLessEqualrF   Úname)r   Ú
swift_fileÚliness      r   Útest_ios_file_length_capsz2TestIOSPlatformPackaging.test_ios_file_length_caps|   s�   € å" [Ñ0×6Ò6°yÑAÔAð 	hð 	hˆJØ×(Ò(°'Ð(Ñ:Ô:×EÒEÑGÔGˆEØ× Ò ¥ U¡¤¨S°Z´_Ð2fÐ2fÕZ]Ð^cÑZdÔZdÐ2fÐ2fÑgÔgÐgÐgð	hð 	hr   N)	Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r8   rL   r^   rh   © r   r   r   r      sq   € € € € € ØeÐeðJð Jð Jð"
ð 
ð 
ð<oð oð oð$"<ð "<ð "<ðHhð hð hð hð hr   r   c                   ó6   — e Zd ZdZd„ Zd„ Zd„ Zd„ Zd„ Zd„ Z	dS )	ÚTestAndroidPlatformPackagingzNVerifies Android Gradle project, Manifest, ProGuard rules, and Kotlin bridges.c                 ó  — t           dz  t           dz  t           dz  dz  t           dz  dz  t           dz  dz  dz  dz  t           dz  dz  dz  dz  d	z  d
z  dz  dz  t           dz  dz  dz  dz  d	z  d
z  dz  dz  t           dz  dz  dz  dz  d	z  d
z  dz  dz  t           dz  dz  dz  dz  d	z  d
z  dz  dz  t           dz  dz  dz  dz  d	z  d
z  dz  dz  g
}|D ]-}|                      |                     ¦   «         d|› �¦  «         Œ.dS )z&All required Android files must exist.úsettings.gradle.ktsúbuild.gradle.ktsÚappúproguard-rules.proÚsrcÚmainúAndroidManifest.xmlÚjavaÚcomÚ	freeexileÚarpgzMainActivity.ktúNativeBridgeInterface.ktzPlayBillingManager.ktzPlayIntegrityManager.ktzHapticFeedbackManager.ktzMissing Android file: N)ÚANDROID_DIRr   r   r   s      r   Ú%test_android_project_structure_existszBTestAndroidPlatformPackaging.test_android_project_structure_exists†   sy  € õ Ð/Ñ/ÝÐ,Ñ,Ý˜%ÑÐ"4Ñ4Ý˜%ÑÐ"6Ñ6Ý˜%Ñ %Ñ'¨&Ñ0Ð3HÑHÝ˜%Ñ %Ñ'¨&Ñ0°6Ñ9¸EÑAÀKÑOÐRXÑXÐ[lÑlÝ˜%Ñ %Ñ'¨&Ñ0°6Ñ9¸EÑAÀKÑOÐRXÑXÐ[uÑuÝ˜%Ñ %Ñ'¨&Ñ0°6Ñ9¸EÑAÀKÑOÐRXÑXÐ[rÑrÝ˜%Ñ %Ñ'¨&Ñ0°6Ñ9¸EÑAÀKÑOÐRXÑXÐ[tÑtÝ˜%Ñ %Ñ'¨&Ñ0°6Ñ9¸EÑAÀKÑOÐRXÑXÐ[uÑuð
ˆð  ð 	Fð 	FˆAØ�OŠO˜AŸHšH™JœJÐ(DÀÐ(DÐ(DÑEÔEÐEÐEð	Fð 	Fr   c                 ó”  — t           dz                       d¬¦  «        }|                      d|¦  «         |                      d|¦  «         t           dz  dz                       d¬¦  «        }|                      d|¦  «         |                      d	|¦  «         |                      d
|¦  «         |                      d|¦  «         |                      d|¦  «         |                      d|¦  «         |                      d|¦  «         |                      d|¦  «         |                      d|¦  «         |                      d|¦  «         dS )zLGradle scripts must configure compileSdk 35, targetSdk 35, and dependencies.rq   rN   rO   zrootProject.name = "FreeExile"zinclude(":app")rs   rr   zcompileSdk = 35ztargetSdk = 35zminSdk = 26z$applicationId = "com.freeexile.arpg"zversionCode = 1zversionName = "1.0.0"zisMinifyEnabled = truezandroidx.webkit:webkitz+com.android.billingclient:billing-ktx:7.0.0z'com.google.android.play:integrity:1.4.0N©r}   rX   r2   )r   Úsettings_textÚapp_gradle_texts      r   Ú&test_android_settings_and_build_gradlezCTestAndroidPlatformPackaging.test_android_settings_and_build_gradle—   sB  € å$Ð'<Ñ<×GÒGÐQXÐGÑYÔYˆØ�ŠÐ6¸ÑFÔFÐFØ�ŠÐ'¨Ñ7Ô7Ð7å&¨Ñ.Ð1CÑC×NÒNÐX_ÐNÑ`Ô`ˆØ�ŠÐ'¨Ñ9Ô9Ð9Ø�ŠÐ&¨Ñ8Ô8Ð8Ø�Š�m _Ñ5Ô5Ð5Ø�ŠÐ<¸oÑNÔNÐNØ�ŠÐ'¨Ñ9Ô9Ð9Ø�ŠÐ-¨Ñ?Ô?Ð?Ø�ŠÐ.°Ñ@Ô@Ð@Ø�ŠÐ.°Ñ@Ô@Ð@Ø�ŠÐCÀ_ÑUÔUÐUØ�ŠÐ?ÀÑQÔQÐQÐQÐQr   c                 ó,  — t           dz  dz  dz  dz  }t          j        |¦  «        }|                     ¦   «         }d„ |                     d¦  «        D ¦   «         }|                      d|¦  «         |                      d|¦  «         |                      d	|¦  «         d
„ |                     d¦  «        D ¦   «         }|                      d|¦  «         d„ |                     d¦  «        D ¦   «         }|                      d|¦  «         |                     d¦  «        }|                      |¦  «         |                      |j	         
                    d¦  «        d¦  «         |                     d¦  «        }|                      |¦  «         |                      |j	         
                    d¦  «        d¦  «         |j	         
                    dd¦  «        }	|                      d|	¦  «         |                      d|	¦  «         |                      d|	¦  «         dS )zQAndroidManifest.xml must declare required permissions, features, and orientation.rs   ru   rv   rw   c                 óB   — g | ]}|j                              d ¦  «        ‘ŒS ©z0{http://schemas.android.com/apk/res/android}name©Úattribr0   ©r?   Úelems     r   rA   zOTestAndroidPlatformPackaging.test_android_manifest_validity.<locals>.<listcomp>°   s:   € ð  Hð  Hð  HÐ_c�t”{—’Ð'YÑZÔZð  Hð  Hð  Hr   zuses-permissionzandroid.permission.INTERNETzandroid.permission.VIBRATEzcom.android.vending.BILLINGc                 óB   — g | ]}|j                              d ¦  «        ‘ŒS r†   r‡   r‰   s     r   rA   zOTestAndroidPlatformPackaging.test_android_manifest_validity.<locals>.<listcomp>¶   s:   € ð  Bð  Bð  BÐ\`�D”K—O’OÐ$VÑWÔWð  Bð  Bð  Br   zuses-featurez'android.hardware.touchscreen.multitouchc                 óT   — g | ]%}d |j         v ¯|j                              d ¦  «        ‘Œ&S )z7{http://schemas.android.com/apk/res/android}glEsVersionr‡   r‰   s     r   rA   zOTestAndroidPlatformPackaging.test_android_manifest_validity.<locals>.<listcomp>¹   s`   € ð  Xð  Xð  XÐfjð  OHð  LPô  LWð  OWð  OW�t”{—’Ð'`ÑaÔað  OWð  OWð  OWr   Ú
0x00030002Úapplicationz?{http://schemas.android.com/apk/res/android}hardwareAcceleratedÚtrueÚactivityz={http://schemas.android.com/apk/res/android}screenOrientationÚsensorLandscapez9{http://schemas.android.com/apk/res/android}configChangesÚ ÚorientationÚ
screenSizeÚkeyboardHiddenN)r}   ÚETÚparseÚgetrootÚfindallr2   ÚfindÚassertIsNotNoner/   rˆ   r0   )
r   Úmanifest_pathÚtreeÚrootÚpermissionsÚfeaturesÚgl_featuresrs   r�   Úconfig_changess
             r   Útest_android_manifest_validityz;TestAndroidPlatformPackaging.test_android_manifest_validity©   sW  € å# eÑ+¨eÑ3°fÑ<Ð?TÑTˆÝŒx˜Ñ&Ô&ˆØ�|Š|‰~Œ~ˆð Hð  HÐgk×gsÒgsð  uFñ  hGô  hGð  Hñ  Hô  HˆØ�ŠÐ3°[ÑAÔAÐAØ�ŠÐ2°KÑ@Ô@Ð@Ø�ŠÐ3°[ÑAÔAÐAð Bð  BÐdh×dpÒdpÐqñ  eAô  eAð  Bñ  Bô  BˆØ�ŠÐ?ÀÑJÔJÐJð Xð  XÐnr×nzÒnzð  |Jñ  oKô  oKð  Xñ  Xô  XˆØ�Š�l KÑ0Ô0Ð0ð �iŠi˜Ñ&Ô&ˆØ×Ò˜SÑ!Ô!Ð!Ø×Ò˜œŸšÐ(iÑjÔjÐlrÑsÔsÐsð —8’8˜JÑ'Ô'ˆØ×Ò˜XÑ&Ô&Ð&Ø×ÒØŒO×ÒÐ _Ñ`Ô`Øñ	
ô 	
ð 	
ð "œ×,Ò,Ð-hÐjlÑmÔmˆØ�Š�m ^Ñ4Ô4Ð4Ø�Š�l NÑ3Ô3Ð3Ø�ŠÐ&¨Ñ7Ô7Ð7Ð7Ð7r   c                 óø   — t           dz  dz                       d¬¦  «        }|                      d|¦  «         |                      d|¦  «         |                      d|¦  «         |                      d|¦  «         d	S )
zPProGuard rules must preserve JavascriptInterface and billing/integrity packages.rs   rt   rN   rO   ÚJavascriptInterfacez(com.freeexile.arpg.NativeBridgeInterfacez com.android.billingclient.api.**z)com.google.android.play.core.integrity.**Nr€   )r   Úproguard_texts     r   Útest_android_proguard_rulesz8TestAndroidPlatformPackaging.test_android_proguard_rulesÍ   s~   € å$ uÑ,Ð/CÑC×NÒNÐX_ÐNÑ`Ô`ˆØ�ŠÐ+¨]Ñ;Ô;Ð;Ø�ŠÐ@À-ÑPÔPÐPØ�ŠÐ8¸-ÑHÔHÐHØ�ŠÐAÀ=ÑQÔQÐQÐQÐQr   c                 óJ  — t           dz  dz  dz  dz  dz  dz  dz  dz                       d	¬
¦  «        }|                      d|¦  «         d}t          j        ||¦  «        }|                      d|¦  «         |                      d|¦  «         |                      d|¦  «         dS )zYNativeBridgeInterface must expose @JavascriptInterface on haptic, billing, and integrity.rs   ru   rv   rx   ry   rz   r{   r|   rN   rO   z@JavascriptInterfacez"@JavascriptInterface\s+fun\s+(\w+)ÚtriggerHapticÚrequestPlayIntegrityTokenÚlaunchBillingFlowN)r}   rX   r2   Úrer™   )r   Úbridge_textÚpatternÚannotated_methodss       r   Ú%test_kotlin_native_bridge_annotationszBTestAndroidPlatformPackaging.test_kotlin_native_bridge_annotationsÕ   sÒ   € å" UÑ*¨UÑ2°VÑ;¸fÑDÀuÑLÈ{ÑZÐ]cÑcð  gAñ  A÷  Lò  Lð  V]ð  Lñ  ^ô  ^ˆØ�ŠÐ,¨kÑ:Ô:Ð:ð 8ˆÝœJ w°Ñ<Ô<ÐØ�Š�oÐ'8Ñ9Ô9Ð9Ø�ŠÐ1Ð3DÑEÔEÐEØ�ŠÐ)Ð+<Ñ=Ô=Ð=Ð=Ð=r   c           
      ó4  — t           dz  dz  dz  dz  dz  dz  dz  }|                     d¦  «        D ]e}|                     d	¬
¦  «                             ¦   «         }|                      t          |¦  «        d|j        › dt          |¦  «        › �¦  «         ŒfdS )z<No Kotlin file may exceed 500 lines per FreeExile standards.rs   ru   rv   rx   ry   rz   r{   z*.ktrN   rO   r`   ra   N)r}   rb   rX   rc   rd   rF   re   )r   Úkt_dirÚkt_filerg   s       r   Útest_kotlin_file_length_capsz9TestAndroidPlatformPackaging.test_kotlin_file_length_capsá   s±   € å˜uÑ$ uÑ,¨vÑ5¸Ñ>ÀÑFÈÑTÐW]Ñ]ˆØ—{’{ 6Ñ*Ô*ð 	eð 	eˆGØ×%Ò%¨wÐ%Ñ7Ô7×BÒBÑDÔDˆEØ× Ò ¥ U¡¤¨S°W´\Ð2cÐ2cÕWZÐ[`ÑWaÔWaÐ2cÐ2cÑdÔdÐdÐdð	eð 	er   N)
ri   rj   rk   rl   r~   rƒ   r£   r§   r°   r´   rm   r   r   ro   ro   ƒ   sƒ   € € € € € ØXÐXðFð Fð Fð"Rð Rð Rð$"8ð "8ð "8ðHRð Rð Rð
>ð 
>ð 
>ðeð eð eð eð er   ro   c                   ó   — e Zd ZdZd„ ZdS )ÚTestUnifiedMobileBridgez^Verifies that unified client JS bridge integrates with both iOS and Android native interfaces.c                 ó„  — t           dz  dz  dz  dz  }|                      |                     ¦   «         d¦  «         |                     d¬¦  «        }|                      d|¦  «         |                      d	|¦  «         |                      d
|¦  «         |                      d|¦  «         |                      d|¦  «         d S )NÚclientÚwebappÚjszmobile_native_bridge.jsz"mobile_native_bridge.js must existrN   rO   zwebkit.messageHandlersÚNativeBridger©   r«   ÚrequestAttestationToken)ÚPROJECT_ROOTr   r   rX   r2   )r   Ú	bridge_jsÚcontents      r   Ú#test_mobile_native_bridge_js_existsz;TestUnifiedMobileBridge.test_mobile_native_bridge_js_existsì   sÀ   € Ý  8Ñ+¨hÑ6¸Ñ=Ð@YÑYˆ	Ø�Š˜	×(Ò(Ñ*Ô*Ð,PÑQÔQÐQØ×%Ò%¨wÐ%Ñ7Ô7ˆØ�ŠÐ.°Ñ8Ô8Ð8Ø�Š�n gÑ.Ô.Ð.Ø�Š�o wÑ/Ô/Ð/Ø�ŠÐ)¨7Ñ3Ô3Ð3Ø�ŠÐ/°Ñ9Ô9Ð9Ð9Ð9r   N)ri   rj   rk   rl   rÀ   rm   r   r   r¶   r¶   é   s)   € € € € € ØhÐhð:ð :ð :ð :ð :r   r¶   Ú__main__)rl   ÚunittestÚosr¬   r-   Úxml.etree.ElementTreeÚetreeÚElementTreer–   Úpathlibr   Ú__file__ÚresolveÚparentr½   ÚPLATFORM_DIRr   r}   ÚTestCaser   ro   r¶   ri   rv   rm   r   r   ú<module>rÍ      sq  ððð ð €€€Ø 	€	€	€	Ø 	€	€	€	Ø €€€Ø "Ð "Ð "Ð "Ð "Ð "Ð "Ð "Ð "Ø Ð Ð Ð Ð Ð àˆt�H‰~Œ~×%Ò%Ñ'Ô'Ô.Ô5Ô<€Ø˜jÑ(€Ø
˜Ñ
€Ø˜YÑ&€ðlhð lhð lhð lhð lh˜xÔ0ñ lhô lhð lhð^ceð ceð ceð ceð ce 8Ô#4ñ ceô ceð ceðL:ð :ð :ð :ð :˜hÔ/ñ :ô :ð :ð ˆzÒÐØ€H„M�O„O€O€O€Oð Ðr   