دلالات

بالإضافة إلى المعلومات الأساسية التي تحملها الدالة المركّبة، مثل سلسلة نصية لدالة Text المركّبة، قد يكون من المفيد الحصول على مزيد من المعلومات التكميلية حول عناصر في واجهة المستخدم.

تُعرف المعلومات حول معنى ودور مكوّن في Compose باسم الدلالات، وهي طريقة لتوفير سياق إضافي حول الدوال المركّبة لخدمات مثل تسهيل الاستخدام والملء التلقائي والاختبار. على سبيل المثال، قد يكون رمز الكاميرا مجرد صورة من الناحية المرئية، ولكن المعنى الدلالي قد يكون "التقاط صورة".

من خلال الجمع بين الدلالات المناسبة وواجهات برمجة التطبيقات المناسبة في Compose، يمكنك تقديم أكبر قدر ممكن من المعلومات عن المكوّن لخدمات تسهيل الاستخدام، والتي تقرّر بعد ذلك كيفية عرضه للمستخدم.

تتضمّن واجهات برمجة التطبيقات Material وCompose UI وFoundation دلالات مضمّنة تتّبع دورها ووظيفتها المحدّدة، ولكن يمكنك أيضًا تعديل هذه الدلالات لواجهات برمجة التطبيقات الحالية أو ضبط دلالات جديدة للمكوّنات المخصّصة، وفقًا لمتطلباتك المحدّدة.

السمات الدلالية

تنقل السمات الدلالية معنى الدالة المركّبة المقابلة. على سبيل المثال، تحتوي الدالة المركّبة Text على السمة الدلالية text، لأنّ هذا هو معنى هذه الدالة المركّبة. يحتوي Icon على سمة contentDescription (إذا ضبطها المطوّر) توضّح معنى الرمز في نص.

فكِّر في كيفية نقل خصائص الدلالات لمعنى دالة مركّبة. ننصحك باستخدام Switch. إليك كيف يظهر ذلك للمستخدم:

الشكل 1. Switch في حالتَي "تفعيل" و "إيقاف"

لوصف معنى هذا العنصر، يمكنك قول ما يلي: "هذا مفتاح تبديل، وهو عنصر قابل للتبديل في حالة "التفعيل". ويمكنك النقر عليه للتفاعل معه".

هذا هو الغرض من استخدام سمات الدلالات. تحتوي عقدة الدلالات لعنصر Switch هذا على السمات التالية، كما هو موضّح في "أداة فحص التنسيق":

"أداة فحص التنسيق" تعرض خصائص Semantics لدالة Switch مركّبة
الشكل 2. "أداة فحص التنسيق" تعرض خصائص Semantics لدالة مركّبة من النوع Switch.

يشير الرمز Role إلى نوع العنصر. يصف StateDescription كيفية الإشارة إلى الحالة "مفعَّل". By default this is a localized version of the word "On", but this can be made more specific (for example, "Enabled") based on the context. ‫ToggleableState هو الحالة الحالية لمفتاح التبديل. تشير السمة OnClick إلى الطريقة المستخدَمة للتفاعل مع هذا العنصر.

إنّ تتبُّع خصائص الدلالات لكل دالة مركّبة في تطبيقك يتيح لك العديد من الإمكانات الفعّالة:

  • تستخدم خدمات تسهيل الاستخدام السمات لتمثيل واجهة المستخدم المعروضة على الشاشة والسماح للمستخدمين بالتفاعل معها. بالنسبة إلى الدالة المركّبة Switch، قد يعلن Talkback: "مفعَّل، مفتاح تبديل، انقر مرّتين للتبديل". ويمكن للمستخدم النقر مرّتين على الشاشة لإيقاف مفتاح التبديل.
  • يستخدم إطار عمل الاختبار الخصائص للعثور على العُقد والتفاعل معها وإجراء التأكيدات:
    val mySwitch = SemanticsMatcher.expectValue(
        SemanticsProperties.Role, Role.Switch
    )
    composeTestRule.onNode(mySwitch)
        .performClick()
        .assertIsOff()

إنّ الدوال المركّبة والمعدِّلات التي تم إنشاؤها فوق مكتبة الأساس في Compose تضبط لك تلقائيًا الخصائص ذات الصلة. يمكنك اختياريًا تغيير هذه السمات يدويًا لتحسين دعم تسهيل الاستخدام لحالات استخدام معيّنة، أو تغيير استراتيجية الدمج أو المحو للدوال المركّبة.

للإشارة إلى نوع المحتوى المحدّد للمكوّن الخاص بك لخدمات تسهيل الاستخدام، يمكنك تطبيق مجموعة متنوعة من الدلالات المختلفة. ستدعم هذه الإضافات المعلومات الدلالية الرئيسية في مكانها وتساعد خدمات تسهيل الاستخدام في ضبط كيفية تمثيل المكوّن أو الإعلان عنه أو التفاعل معه.

للاطّلاع على قائمة كاملة بخصائص الدلالات، يُرجى مراجعة عنصر SemanticsProperties. للحصول على قائمة كاملة بإجراءات تسهيل الاستخدام المحتملة، يُرجى الاطّلاع على العنصر SemanticsActions.

العناوين

غالبًا ما تحتوي التطبيقات على شاشات ذات محتوى وافٍ بالنصوص، مثل المقالات الطويلة أو صفحات الأخبار، والتي عادةً ما يتم تقسيمها إلى أقسام فرعية مختلفة بعناوين:

منشور مدوّنة يتضمّن نص مقالة في حاوية قابلة للتمرير
الشكل 3. منشور مدوّنة يتضمّن نص المقالة في حاوية قابلة للتمرير

قد يواجه المستخدمون الذين لديهم احتياجات لتسهيل الاستخدام صعوبة في التنقل في هذه الشاشة بسهولة. لتحسين تجربة التنقّل، تتيح بعض خدمات تسهيل الاستخدام التنقّل بسهولة أكبر بين الأقسام أو العناوين مباشرةً. لتفعيل هذه الميزة، يجب الإشارة إلى أنّ المكوّن هو heading من خلال تحديد خاصية الدلالات:

@Composable
private fun Subsection(text: String) {
    Text(
        text = text,
        style = MaterialTheme.typography.headlineSmall,
        modifier = Modifier.semantics { heading() }
    )
}

التنبيهات والنوافذ المنبثقة

إذا كان المكوّن عبارة عن تنبيه أو نافذة منبثقة، مثل Snackbar، قد تحتاج إلى إرسال إشارة إلى خدمات تسهيل الاستخدام بأنّه يمكن نقل بنية جديدة أو تعديلات على المحتوى إلى المستخدمين.

يمكن وضع علامة على المكوّنات التي تشبه التنبيهات باستخدام سمة الدلالات liveRegion. يسمح هذا الإعداد لخدمات تسهيل الاستخدام بإرسال إشعارات تلقائية إلى المستخدم بشأن التغييرات التي تطرأ على هذا المكوّن أو مكوّناته الفرعية:

PopupAlert(
    message = "You have a new message",
    modifier = Modifier.semantics {
        liveRegion = LiveRegionMode.Polite
    }
)

يجب استخدام liveRegionMode.Polite في معظم الحالات التي يجب فيها لفت انتباه المستخدمين لفترة وجيزة فقط إلى التنبيهات أو المحتوى المهم الذي يتغيّر على الشاشة.

يجب استخدام liveRegion.Assertive باعتدال لتجنُّب الملاحظات المزعجة. ويجب استخدامها في الحالات التي يكون فيها من الضروري إعلام المستخدمين بالمحتوى الحسّاس للوقت:

PopupAlert(
    message = "Emergency alert incoming",
    modifier = Modifier.semantics {
        liveRegion = LiveRegionMode.Assertive
    }
)

يجب عدم استخدام المحتوى الديناميكي المتغيّر في المحتوى الذي يتم تحديثه بشكل متكرّر، مثل موقّتات العد التنازلي، لتجنُّب إرباك المستخدمين بالملاحظات المستمرة.

مكوّنات تشبه النوافذ

تحتاج المكوّنات المخصّصة التي تشبه النوافذ، مثل ModalBottomSheet، إلى إشارات إضافية لتمييزها عن المحتوى المحيط بها. لهذا الغرض، يمكنك استخدام دلالات paneTitle، بحيث يمكن تمثيل أي تغييرات ذات صلة في النافذة أو اللوحة بشكل مناسب من خلال خدمات تسهيل الاستخدام، إلى جانب معلوماتها الدلالية الرئيسية:

ShareSheet(
    message = "Choose how to share this photo",
    modifier = Modifier
        .fillMaxWidth()
        .align(Alignment.TopCenter)
        .semantics { paneTitle = "New bottom sheet" }
)

للمزيد من المعلومات، يمكنك الاطّلاع على كيفية استخدام Material 3 لـ paneTitle في مكوّناته.

مكوّنات الخطأ

بالنسبة إلى أنواع المحتوى الأخرى، مثل المكوّنات التي تشبه رسائل الخطأ، قد تحتاج إلى توسيع المعلومات الدلالية الرئيسية للمستخدمين الذين لديهم احتياجات خاصة. عند تحديد حالات الخطأ، يمكنك إبلاغ خدمات تسهيل الاستخدام بدلالات error، وتقديم رسائل خطأ موسّعة.

في هذا المثال، يقرأ TalkBack معلومات نص الخطأ الرئيسي، متبوعة برسائل إضافية موسعة:

Error(
    errorText = "Fields cannot be empty",
    modifier = Modifier
        .semantics {
            error("Please add both email and password")
        }
)

مكوّنات تتبُّع مستوى التقدّم

بالنسبة إلى المكوّنات المخصّصة التي تتتبّع مستوى التقدّم، قد تحتاج إلى إعلام المستخدمين بالتغييرات في مستوى تقدّمهم، بما في ذلك قيمة مستوى التقدّم الحالية ونطاقها وحجم الخطوة. ويمكنك إجراء ذلك باستخدام دلالات progressBarRangeInfo، ما يضمن أنّ خدمات تسهيل الاستخدام على عِلم بالتغييرات في مستوى التقدّم، ويمكنها إبلاغ المستخدمين وفقًا لذلك. قد يكون للتكنولوجيات المساعِدة المختلفة أيضًا طرق فريدة للإشارة إلى زيادة التقدم وتناقصه.

ProgressInfoBar(
    modifier = Modifier
        .semantics {
            progressBarRangeInfo =
                ProgressBarRangeInfo(
                    current = progress,
                    range = 0F..1F
                )
        }
)

معلومات عن القائمة والعناصر

في القوائم والشبكات المخصّصة التي تحتوي على العديد من العناصر، قد يكون من المفيد لخدمات تسهيل الاستخدام أن تتلقّى أيضًا معلومات أكثر تفصيلاً، مثل إجمالي عدد العناصر والفهارس.

باستخدام دلالات collectionInfo وcollectionItemInfo في القائمة والعناصر على التوالي، يمكن لخدمات تسهيل الاستخدام في هذه القائمة الطويلة إعلام المستخدمين بفهرس العناصر الذي يتواجدون فيه من إجمالي المجموعة، بالإضافة إلى المعلومات الدلالية النصية:

MilkyWayList(
    modifier = Modifier
        .semantics {
            collectionInfo = CollectionInfo(
                rowCount = milkyWay.count(),
                columnCount = 1
            )
        }
) {
    milkyWay.forEachIndexed { index, text ->
        Text(
            text = text,
            modifier = Modifier.semantics {
                collectionItemInfo =
                    CollectionItemInfo(index, 0, 0, 0)
            }
        )
    }
}

وصف الحالة

يمكن للدالة المركّبة تحديد stateDescription للدلالات التي يستخدمها إطار عمل Android لقراءة الحالة التي تكون فيها الدالة المركّبة. على سبيل المثال، يمكن أن تكون الدالة المركّبة القابلة للتبديل في حالة "محدَّدة" أو "غير محدَّدة". في بعض الحالات، قد تحتاج إلى إلغاء تصنيفات وصف الحالة التلقائية التي يستخدمها Compose. ويمكنك إجراء ذلك من خلال تحديد تصنيفات وصف الحالة بشكل صريح قبل تحديد دالة مركّبة على أنّها قابلة للتبديل:

@Composable
private fun TopicItem(itemTitle: String, selected: Boolean, onToggle: () -> Unit) {
    val stateSubscribed = stringResource(R.string.subscribed)
    val stateNotSubscribed = stringResource(R.string.not_subscribed)
    Row(
        modifier = Modifier
            .semantics {
                // Set any explicit semantic properties
                stateDescription = if (selected) stateSubscribed else stateNotSubscribed
            }
            .toggleable(
                value = selected,
                onValueChange = { onToggle() }
            )
    ) {
        /* ... */
    }
}

الإجراءات المخصّصة

يمكن استخدام الإجراءات المخصّصة لإيماءات الشاشة التي تعمل باللمس الأكثر تعقيدًا، مثل التمرير السريع للإغلاق أو السحب والإفلات، لأنّ هذه الإيماءات قد تكون صعبة على المستخدمين الذين يعانون من إعاقات حركية أو إعاقات أخرى.

لتسهيل استخدام إيماءة التمرير السريع للإغلاق، يمكنك ربطها بإجراء مخصّص، مع تمرير إجراء الإغلاق والتصنيف هناك:

SwipeToDismissBox(
    modifier = Modifier.semantics {
        // Represents the swipe to dismiss for accessibility
        customActions = listOf(
            CustomAccessibilityAction(
                label = "Remove article from list",
                action = {
                    removeArticle()
                    true
                }
            )
        )
    },
    state = rememberSwipeToDismissBoxState(),
    backgroundContent = {}
) {
    ArticleListItem()
}

بعد ذلك، تبرز خدمة تسهيل الاستخدام، مثل TalkBack، المكوّن وتلمّح إلى توفّر المزيد من الإجراءات في قائمته، ما يمثّل إجراء التمرير السريع للإغلاق:

عرض مرئي لقائمة إجراءات TalkBack
الشكل 4. صورة توضيحية لقائمة إجراءات TalkBack

من حالات الاستخدام الأخرى للإجراءات المخصّصة هي القوائم الطويلة التي تحتوي على عناصر تتضمّن المزيد من الإجراءات المتاحة، لأنّه قد يكون من المملّ للمستخدمين تكرار كل إجراء لكل عنصر على حدة:

=عرض مرئي للتنقّل في ميزة "الوصول عبر مفتاح تحكّم" على الشاشة
الشكل 5. صورة توضيحية للتنقّل في ميزة "الوصول عبر مفتاح تحكّم" على الشاشة

لتحسين تجربة التنقّل، وهو أمر مفيد بشكل خاص للتكنولوجيات المساعدة المستندة إلى التفاعل، مثل "الوصول عبر مفتاح التحكّم" أو "الوصول الصوتي"، يمكنك استخدام الإجراءات المخصّصة في الحاوية لنقل الإجراءات من التنقّل الفردي إلى قائمة إجراءات منفصلة:

ArticleListItemRow(
    modifier = Modifier
        .semantics {
            customActions = listOf(
                CustomAccessibilityAction(
                    label = "Open article",
                    action = {
                        openArticle()
                        true
                    }
                ),
                CustomAccessibilityAction(
                    label = "Add to bookmarks",
                    action = {
                        addToBookmarks()
                        true
                    }
                ),
            )
        }
) {
    Article(
        modifier = Modifier.clearAndSetSemantics { },
        onClick = openArticle,
    )
    BookmarkButton(
        modifier = Modifier.clearAndSetSemantics { },
        onClick = addToBookmarks,
    )
}

في هذه الحالات، احرص على محو دلالات العناصر الفرعية الأصلية يدويًا باستخدام المُعدِّل clearAndSetSemantics، لأنّك تنقلها إلى الإجراءات المخصّصة.

على سبيل المثال، عند استخدام ميزة "الوصول عبر مفتاح تحكّم"، تفتح قائمتها عند اختيار الحاوية وتعرض الإجراءات المتاحة المتداخلة فيها:

تمييز عنصر قائمة المقالات في ميزة "الوصول عبر مفتاح تحكّم"
الشكل 6. تمييز عنصر قائمة المقالات في ميزة "الوصول عبر مفتاح تحكّم"
صورة توضيحية لقائمة الإجراءات في ميزة "الوصول عبر مفتاح تحكّم"
الشكل 7: صورة توضيحية لقائمة الإجراءات في ميزة "الوصول عبر مفتاح تحكّم"

شجرة الدلالات

يصف الإصدار واجهة المستخدم في تطبيقك ويتم إنشاؤه من خلال تشغيل الدوال المركّبة. التركيب هو بنية شجرية تتكون من الدوال المركّبة التي تصف واجهة المستخدم.

بجانب "التركيب"، توجد شجرة موازية تُسمّى شجرة الدلالات. تصف هذه الشجرة واجهة المستخدم بطريقة بديلة يمكن فهمها من خلال خدمات تسهيل الاستخدام وإطار عمل الاختبار. تستخدم الخدمات المخصصة لتسهيل الاستخدام الشجرة لوصف التطبيق للمستخدمين الذين لديهم احتياجات محددة. يستخدم إطار عمل الاختبار الشجرة للتفاعل مع تطبيقك وإجراء تأكيدات بشأنه. لا تحتوي شجرة Semantics على معلومات حول كيفية رسم الدوال المركّبة، ولكنّها تحتوي على معلومات حول المعنى الدلالي للدوال المركّبة.

هيكلية واجهة مستخدم نموذجية وشجرة دلالاتها
الشكل 8 هيكلية واجهة مستخدم نموذجية وشجرة الدلالات الخاصة بها

إذا كان تطبيقك يتألف من دوال مركّبة ومعدِّلات من مكتبة Compose Foundation وMaterial، يتم ملء شجرة Semantics وإنشاؤها تلقائيًا لك. ومع ذلك، عند إضافة دوال مركّبة مخصّصة منخفضة المستوى، عليك توفير دلالاتها يدويًا. قد تكون هناك أيضًا مواقف لا تمثل فيها شجرتك بشكل صحيح أو كامل معنى العناصر الموجودة على الشاشة، وفي هذه الحالة يمكنك تكييف الشجرة.

على سبيل المثال، لنلقِ نظرة على الدالة المركّبة التالية لتقويم مخصّص:

دالة مركّبة لتقويم مخصّص مع عناصر أيام قابلة للاختيار
الشكل 9: دالة مركّبة لتقويم مخصّص مع عناصر أيام قابلة للاختيار

في هذا المثال، يتم تنفيذ التقويم بأكمله كدالة مركّبة واحدة منخفضة المستوى، باستخدام الدالة المركّبة Layout والرسم مباشرةً على Canvas. إذا لم تتّخذ أي إجراء آخر، لن تتلقّى خدمات تسهيل الاستخدام معلومات كافية حول محتوى الدالة المركّبة واختيار المستخدم ضمن التقويم. على سبيل المثال، إذا نقر المستخدم على اليوم الذي يحتوي على 17، فإن إطار عمل إمكانية الوصول يتلقى فقط معلومات الوصف للتقويم بأكمله مراقبة. في هذه الحالة، ستعلن خدمة تسهيل الاستخدام TalkBack عن "التقويم" أو "تقويم أبريل"، وهو أفضل قليلاً، وسيُترك المستخدم ليتساءل عن اليوم الذي تم اختياره. لجعل هذه الدالة المركّبة أكثر سهولة في الاستخدام، عليك إضافة معلومات دلالية يدويًا.

شجرة مدمجة وغير مدمجة

كما ذكرنا سابقًا، قد تحتوي كل دالة مركّبة في شجرة واجهة المستخدم على صفر أو أكثر من خصائص الدلالات التي تم ضبطها. عندما لا تتضمّن دالة مركّبة أي سمات دلالية، لا يتم تضمينها كجزء من شجرة الدلالات. بهذه الطريقة، تحتوي شجرة الدلالات على العُقَد التي تتضمّن معنى دلاليًا فقط. ومع ذلك، في بعض الأحيان لنقل المعنى الصحيح لما يظهر على الشاشة، من المفيد أيضًا دمج بعض الأشجار الفرعية للعقد والتعامل معها كعقدة واحدة. بهذه الطريقة، يمكنك التفكير في مجموعة من العُقد ككل، بدلاً من التعامل مع كل عقدة فرعية بشكل فردي. كقاعدة عامة، تمثّل كل عقدة في هذه الشجرة عنصرًا يمكن التركيز عليه عند استخدام خدمات تسهيل الاستخدام.

ومن الأمثلة على هذه الدوال المركّبة Button. يمكنك التفكير في الزر كعنصر واحد، على الرغم من أنّه قد يحتوي على عدة عُقد فرعية:

Button(onClick = { /*TODO*/ }) {
    Icon(
        imageVector = Icons.Filled.Favorite,
        contentDescription = null
    )
    Spacer(Modifier.size(ButtonDefaults.IconSpacing))
    Text("Like")
}

في شجرة Semantics، يتم دمج خصائص العناصر التابعة للزر، ويتم عرض الزر كعقدة طرفية واحدة في الشجرة:

تمثيل دلالي مدمج لورقة شجر واحدة
الشكل 10: تم دمج تمثيل دلالات ورقة الشجر الواحدة.

يمكن للدوال المركّبة والمعدِّلات الإشارة إلى أنّها تريد دمج سمات دلالات العناصر التابعة لها من خلال استدعاء Modifier.semantics (mergeDescendants = true) {}. يشير ضبط هذه السمة على true إلى أنّه يجب دمج سمات الدلالات. في مثال Button، تستخدم الدالة المركّبة Button المعدِّل clickable داخليًا، والذي يتضمّن المعدِّل semantics. وبالتالي، يتم دمج العُقد الفرعية للزر. يمكنك الاطّلاع على مستندات أدوات تسهيل الاستخدام لمعرفة المزيد من المعلومات حول الحالات التي يجب فيها تغيير سلوك الدمج في الدالة المركّبة.

تحتوي العديد من المُعدِّلات والدوال المركّبة في مكتبتَي Foundation وMaterial Compose على هذه السمة. على سبيل المثال، سيتم دمج العناصر التابعة تلقائيًا في المعدِّلَين clickable وtoggleable. بالإضافة إلى ذلك، ستدمج الدالة المركّبة ListItem العناصر التابعة لها.

فحص الشجرة

شجرة الدلالات هي في الواقع شجرتان مختلفتان. هناك شجرة دلالات مدمجة، تدمج العُقَد الفرعية عندما يتم ضبط mergeDescendants على true. هناك أيضًا شجرة دلالات غير مدمجة، لا تطبّق الدمج، ولكنها تحافظ على سلامة كل عقدة. تستخدم خدمات تسهيل الاستخدام الشجرة غير المدمجة وتطبّق خوارزميات الدمج الخاصة بها، مع مراعاة السمة mergeDescendants. يستخدم إطار عمل الاختبار الشجرة المدمجة تلقائيًا.

يمكنك فحص كلتا الشجرتين باستخدام طريقة printToLog(). بشكل تلقائي، وكما هو الحال في الأمثلة السابقة، يتم تسجيل الشجرة المدمجة. لطباعة الشجرة غير المدمجة بدلاً من ذلك، اضبط مَعلمة useUnmergedTree لمطابق onRoot() على true:

composeTestRule.onRoot(useUnmergedTree = true).printToLog("MY TAG")

تتيح لك "أداة فحص التنسيق" عرض شجرة Semantics المدمجة وغير المدمجة، وذلك من خلال اختيار الشجرة المفضّلة في فلتر العرض:

خيارات عرض "أداة فحص التنسيق"، ما يسمح بعرض شجرة Semantics المدمجة وغير المدمجة
الشكل 11: خيارات عرض "أداة فحص التنسيق"، ما يسمح بعرض شجرة Semantics المدمجة وغير المدمجة

بالنسبة إلى كل عقدة في الشجرة، تعرض "أداة فحص التنسيق" كلاً من "الدلالات المدمجة" و"الدلالات" التي تم ضبطها على تلك العقدة في لوحة الخصائص:

تم دمج خصائص الدلالات وضبطها
الشكل 12: تم دمج خصائص الدلالات وضبطها.

تستخدم أدوات المطابقة في إطار عمل الاختبار شجرة الدلالات المدمجة تلقائيًا. لهذا السبب، يمكنك التفاعل مع Button من خلال مطابقة النص المعروض بداخله:

composeTestRule.onNodeWithText("Like").performClick()

يمكنك إلغاء هذا السلوك من خلال ضبط المَعلمة useUnmergedTree لأدوات المطابقة على true، كما هو الحال مع أداة المطابقة onRoot.

تعديل الشجرة

كما ذكرنا سابقًا، يمكنك إلغاء أو محو بعض خصائص الدلالات أو تغيير سلوك دمج الشجرة. وهذا مهم بشكل خاص عند إنشاء مكونات مخصصة خاصة بك. فبدون ضبط السمات وسلوك الدمج الصحيحَين، قد لا يكون تطبيقك متاحًا، وقد تختلف نتائج الاختبارات عن توقعاتك. لمزيد من المعلومات حول الاختبار، يُرجى الاطّلاع على دليل الاختبار.