تخطَّ إلى المحتوى

خارطة الطريق

تستعرض هذه الصفحة الأهداف المتبقية للوصول إلى الغاية المنشودة لبنية وكيل المنصة الأصلي:

Simple Playwright-style test API
-> Astur core
-> Astur platform driver
-> persistent native platform agent
-> UiAutomator / XCUITest
  • المُحدِّدات القابلة للتركيب (Composable Locators) (غير مُصدَرة بعد): حصر البحث داخل عنصر أب، والتصفية عبر filter({ hasText, hasNotText, has, hasNot })، والدمج المنطقي بـ and() و or()، والاختيار بالموضع عبر first() و last() و nth(i). يُحل التركيب مقابل لقطة واحدة من الشجرة على المضيف بدلاً من تمريره إلى الوكلاء (Agents)، ما يبقي المُحدِّد الذي يستقبله المشغّل كما هو تماماً ولا يستدعي أي تغيير في بروتوكول الوكيل على أيٍّ من المنصتين. وإذا وصل المُحدِّد المُركّب إلى عنصر يمكن تسميته بشكل فريد، يُمرَّر مُحدِّده البسيط إلى المشغّل ليطابق سلوك المُحدِّد العادي بدلاً من الهبوط إلى الإحداثيات.
  • قارئات حالة العناصر ووسائل الراحة (0.5.0-beta): textContent() و inputValue() و bounds() و count() و isEnabled() / isDisabled() / isSelected() / isFocused() و clear()، إضافة إلى waitFor({ state }) بأسلوب Playwright.
  • getByPlaceholder() و isChecked() و isEmpty() (غير مُصدَرة بعد)، مع المُطابِقَين toBeChecked و toBeEmpty. وحالة التحديد ثلاثية: العنصر الذي لا يُبلّغ عنها تُسجَّل حالته «غير معروفة» لا false.
  • by.native({ ios, android }) — مخرج الطوارئ للمُحدِّدات الأصلية (0.5.0-beta)، للعنصر النادر الذي تعجز عنه by.label و by.id و by.text و by.role و by.type. الخيار ios هو نص استعلام NSPredicate خام خاص بـ XCUITest — وهي قواعد الاستعلام التصريحية من Apple نفسها، وليست شيفرة قابلة للتنفيذ. أما android فهو سلسلة مُهيكلة (className، textContains، resourceId، hasChild، hasDescendant، …) مبنية بالكامل على واجهة By/BySelector من androidx.test.uiautomator — وهي عن قصد ليست لغة تعبيرات حرة: بلا eval، وبلا مُحلِّل خاص، وبلا مُترجم. ويختار الحقل الاختياري instance التطابق رقم n على كلتا المنصتين. يتطلب وكيلاً أصلياً متصلاً. وتبقى استراتيجية xpath محجوزة وغير مُنفَّذة، ورسالة خطئها تشير إلى هنا.
  • البحث متعدد التطابقات أصلياً على Android (0.5.0-beta): يوفّر وكيل UiAutomator الأمرين element.findAll و element.findMany، فتُحل queryAll() و count() و device.findAll() و device.findMany() على الجهاز في جولة واحدة بدل سحب شجرة الواجهة كاملة. وتعود الوكلاء الأقدم تلقائياً إلى المسار السابق، أما وكيل iOS فكان يوفّرهما أصلاً.
  • ‏Flutter على المنصتين: خدمة Dart VM (شجرة الودجات الحية) على Android، وشجرة إمكانية الوصول لـ XCUITest على iOS مع احتياطي للمطابقة الجزئية على مستوى الوكيل يغطي تسميات Flutter المدمجة.
  • التحكم بـ DOM داخل WebView عبر device.webContext() — جسر يحقن JavaScript ولا يرتبط بمحرك معين، ويقود WebView في تطبيقات Flutter و React Native. مدعوم على Android (Chromium/CDP) وعلى iOS في المحاكي والأجهزة الحقيقية (‏WKWebView عبر ios-webkit-debug-proxy، ويُجسَر المحاكي تلقائياً عبر مقبس webinspectord_sim الخاص به). كما يدمج المُفتّش (Inspector) شجرة DOM ضمن شجرة الواجهة مع مُحدِّدات حقيقية وإمكانية الملء والنقر.
  • الويب على الجوال (0.6.0-beta): تقود device.browser صفحة داخل متصفح الجهاز نفسه — Chrome على Android و Safari على iOS. والإعداد الذي يضبط browser دون app يُنشئ جلسة متصفح فقط لا تُثبّت شيئاً وتجعل الوكيل الأصلي اختيارياً. يحصل Android على تبويب لكل اختبار، بينما يعيد iOS استخدام تبويب واحد ويحدّثه لأن WebKit لا يكشف دورة حياة التبويب.
  • مراقبة الشبكة (0.5.0-beta.5): تُبلّغ device.network عن حركة HTTP الخاصة بالتطبيق — عبر نطاق Network في CDP لتطبيقات React Native على المنصتين، وعبر مُحلِّل HTTP في Dart VM لتطبيقات Flutter. وتُعلَن التغطية من خلال capabilities() ليتخطى الاختبار نفسه مع ذكر السبب بدل أن يفشل حيث تتعذر المراقبة.
  • المقارنة البصرية (0.5.0-beta.5): تعمل toHaveScreenshot() مقابل صور مرجعية خاصة بكل جهاز، مع الإخفاء (Masking) وحدود التسامح وعرض الفروق كصور في تقرير HTML. وتُفهرَس الصور المرجعية حسب المنصة ومحرك العرض ومقاس الشاشة.
  • استكشاف التطبيقات والجهاز (غير مُصدَرة بعد): device.app.list() و device.app.foreground() و device.orientation.get().
  • الأمر astur screenshot (غير مُصدَر بعد) يلتقط شاشة الجهاز كصورة PNG دون كتابة اختبار.
  • تحصين المُفتّش والتوليد التلقائي للشيفرة (0.5.0-beta): يسجّل مُؤلِّف التأكيدات مجموعة المُطابِقات كاملة، وتُسجَّل إيماءات السحب ضمن الشيفرة المولَّدة، وتُرفض خطوات الملء والتأكيد التي لا تحمل مُحدِّداً بدل إنتاج شيفرة معطوبة، ويمكن التصدير بصيغة TypeScript أو JavaScript، ولم يعد الفتح التلقائي للمتصفح يُعطّل الأداة على Windows (#10).
  • يُعيد وكيلا Android و iOS تشخيصات مُهيكلة للتوقيت والأعطال عبر البروتوكول المشترك، وتتضمن أعطال قابلية التنفيذ المُحدِّد ولقطة العنصر المرشّح وحالته من حيث الظهور والتفعيل وقابلية النقر والثبات حيثما تكشفها المنصة. ويحتفظ AsturError على المضيف بهذه التفاصيل بدل إسقاطها عند حدود النقل.
  • سير عمل يدوي للفحص السريع على أجهزة ذاتية الاستضافة يفرض مسارات الوكيل الإلزامية على Android ومحاكي iOS وأجهزة iOS الحقيقية المُوقَّعة.
  • التوثيق باللغة العربية (0.6.0-beta): جميع الصفحات، على المسار /ar/.

الخصائص الجاري العمل عليها

Section titled “الخصائص الجاري العمل عليها”
  • الإجراءات المُعنونة بالفهرس على المسار الأصلي: تُحل nth(n).tap() فهرسها على المضيف، لذا يعود أي إجراء على مُحدِّد مُركّب يتعذّر تسميته بشكل فريد إلى الإحداثيات. وإضافة معامل فهرس للعنصر في بروتوكول الوكيل ستُبقيه أصلياً من طرف إلى طرف. ويحل الحقل instance في by.native() هذه المسألة اليوم لحالة مخرج الطوارئ تحديداً.
  • الدالة fill() على مُحدِّد مُركّب يصل إلى عنصر لا يمكن تسميته: تنقر لتركيز المؤشر ثم تكتب، وهو ما لا يسمح بمسح الحقل أولاً. ويُبلَّغ عن تعذّر ذلك باسم COMPOSED_LOCATOR_FILL_UNSUPPORTED.
  • تغطية الإيماءات والإدخال: لا توجد بعد إيماءات التكبير والتصغير (Pinch/Zoom)، ولا تزال clear() تمر عبر fill('') — وأمر مسح نص أصلي مخصص سيكون أكثر دقة على المنصتين.
  • التطبيق في المقدمة على iOS: لا يُبلّغ عنه لا simctl ولا devicectl، ومُشغّل XCTest محصور بالتطبيق الذي أطلقه. أما Android فيقرأه من dumpsys.
  • اتجاه الشاشة على iOS مُشتق من هندسة إطار العرض، لذا لا يُميَّز بين اتجاهي الوضع الأفقي.
  • السحب والإفلات في Flutter على iOS: لا تُسجَّل سوى أول عملية سحب اصطناعية من XCUITest ضمن السلسلة لدى مُتعرِّف الإيماءات في Flutter، ويلزم حاقن سحب متعدد الخطوات (أحداث حركة حقيقية) لتحقيق التكافؤ مع مشغّل Dart VM على Android.
  • أجهزة iOS الحقيقية لاستهداف المتصفح: المسار البرمجي موجود (‏devicectl ثم Safari) لكنه لم يُجرَّب على جهاز فعلي.
  • عزل بيانات التخزين في المتصفح: التبويب ليس سياق متصفح (Browser Context) بمفهوم Playwright، ولا توفّر أيٌّ من المنصتين ملف تعريف لكل تبويب — فملفات الارتباط و localStorage مُشتركة. وهذا قيد من قيود المنصة لا بند في قائمة العمل.
  • لا تستطيع بيئات التكامل المستمر السحابية الافتراضية تشغيل أجهزة جوال حقيقية، وتتطلب مهام الفحص على iOS المُوقَّع و Android الفعلي أجهزة ذاتية الاستضافة تحمل الوسوم المناسبة.
  • لا يزال العمل جارياً على توسيع تقارير المُحدِّدات الصارمة، بما فيها قوائم المرشحين المُرتّبة لكل استراتيجية تحديد.
  • لا تزال جدولة مجمّعات الأجهزة للأهداف السحابية ومزارع الأجهزة قيد التخطيط، والإعداد السحابي الحالي هيكل أولي لا مسار تنفيذ.
  • يحتاج المُفتّش والتوليد التلقائي على أجهزة iOS الحقيقية إلى بث مُصغّر للشجرة الأصلية حتى لا تُعطّل لقطات XCTest الواسعة الشجرة الحية على الشاشات الكبيرة.
  • يختار الحقل instance في by.native() على Android التطابق رقم n بعد تطبيق كل قيود hasChild و hasDescendant، لكن لا يوجد مكافئ لتضمين «الابن رقم n لأب محدد» داخل الشرط نفسه — بل عند جذر السلسلة فقط.

الأولويات والخطوات القادمة

Section titled “الأولويات والخطوات القادمة”
  1. تكافؤ المسار الأصلي للمُحدِّدات المُركّبة
  • إضافة معامل فهرس للعنصر في بروتوكول الوكيل لتبقى nth(n).tap() و fill() المُركّبة على المسار الأصلي بدل الهبوط إلى الإحداثيات.
  • إضافة أمر أصلي مخصص لمسح النص، وهو ما يفتحه العمل نفسه.
  1. تشخيصات الوكيل والتكافؤ
  • إبقاء أشكال نتائج البروتوكول على Android و iOS متوائمة ومُختبرة تعاقدياً.
  • توسيع تشخيصات المرشحين للمُحدِّدات المعقّدة دون أن تدفع الإجراءات الاعتيادية ثمن سحب الشجرة كاملة.
  1. صقل مسار التفاعل الذرّي
  • إبقاء البحث والانتظار والتنفيذ ضمن مسار أمر أصلي واحد على المنصتين.
  • توسيع تغطية الأدوار وعناصر التحكم مثل أشرطة التمرير ومنتقيات الوسائط والتنبيهات.
  • إضافة إيماءات التكبير والتصغير.
  1. التنفيذ المتوازي
  • مواصلة توسيع مجمّعات الأجهزة ليتمكن التوزيع التلقائي للعاملين على الأجهزة المحلية والبعيدة.
  • إبقاء المشاريع متعددة المنصات معزولة بمُعرّف الجهاز ومجلد المخرجات.
  1. الموثوقية والقياس
  • عرض توقيت الأوامر وبيانات التتبع باتساق في التقارير، بحيث يكشف التشغيل غير المستقر ما إذا كان التأخير في النقل على المضيف أم في البحث الأصلي أم في تصيير التطبيق أم في تنفيذ الإجراء.
  • إضافة توقيتات خاصة بالمُفتّش لتحديث اللقطة وتحديث الشجرة واختبار الإصابة وتسجيل الإجراءات.
  1. فرض التكامل المستمر والترحيل
  • إبقاء سير عمل الفحص بالوكيل الإلزامي ناجحاً على أجهزة Android و iOS ذاتية الاستضافة.
  • إبقاء المسارات الاحتياطية للتطوير المحلي حتى تستقر مجموعات الوكيل بما يكفي لجعل مساره إلزامياً في كل مكان.

هدفنا الأساسي هو ضمان بقاء الأكواد نظيفة، مقروءة، وبسيطة كالتالي:

await device.getByRole('button', { name: 'Sign in' }).tap();
await expect(device.getByText('Welcome')).toBeVisible();

يجب أن تتكفل بيئة الـ Astur ووكلائها الأصليين (Native Agents) بكافة التفاصيل المُرهقة الخاصة بالانتظار، الترجمة، والفروقات المعقدة بين المنصات، ليبقى تركيزك مُنصباً بالكامل على منطق الاختبار.