أتمتة اختبارات الوصولية باستخدام Cypress: دليل شامل لتجربة مستخدم شاملة
أهمية اختبارات الوصولية في تطوير الويب الحديث
في عالم تطوير الويب سريع التطور، لم يعد التركيز على الوظائف والتصميم الجذاب وحده كافياً. بل يجب أن نضمن أن منتجاتنا الرقمية متاحة للجميع. في مقال سابق، تناولنا كيفية إضافة اختبارات لقطات الشاشة في Cypress لضمان عدم تغير مكونات الواجهة عن غير قصد بمرور الوقت. والآن، سنتعمق في كيفية أتمتة اختبارات الوصولية (Accessibility Tests) باستخدام Cypress.
لماذا يجب أن نهتم بالوصولية؟
- الإجابة المختصرة: لأنها الممارسة الصحيحة والأخلاقية.
- الإجابة المطولة: يمكن لشبكة ويب يسهل الوصول إليها أن تساعد الأشخاص ذوي الإعاقة على تحسين جودة حياتهم. هناك أنواع مختلفة من الإعاقات، بما في ذلك السمعية، المعرفية، العصبية، الجسدية، النطقية، والبصرية. وهدفنا كصناع للمنتجات، مهندسين، ومصممين هو إنشاء تجارب تشمل جميع الأفراد.
من المهم أيضاً الإشارة إلى أن وصولية الويب تفيد الأشخاص الذين لا يعانون من إعاقات. على سبيل المثال، تساعد المواقع سهلة الوصول الأشخاص الذين تتغير قدراتهم بسبب التقدم في العمر، أو الأشخاص الذين لديهم اتصالات إنترنت بطيئة، أو أولئك الذين يستخدمون أجهزة ذات شاشات صغيرة. وقد تكون الإعاقة مؤقتة أيضاً؛ فمثلاً، شخص ذو ذراع مكسورة لا يستطيع الكتابة واستخدام الفأرة في نفس الوقت بكفاءة.
إذا كنت ترغب في تثقيف نفسك حول هذا الموضوع، يمكنني أن أوصي بـ W3C Web Accessibility Initiative (WAI) و The A11Y Project كموارد ممتازة.
تقنيات فحص الوصولية المتوفرة
توجد طرق مختلفة لاختبار ما إذا كان موقعك الإلكتروني أو تطبيقك سهل الوصول. لدى W3C WAI قائمة تضم أكثر من 140 أداة لمساعدتك في تحديد ما إذا كان موقعك/تطبيقك يفي بإرشادات الوصولية. يمكنك أيضاً إضافة ما يلي إلى استراتيجيتك:
الاختبار اليدوي وتجارب المستخدمين الحقيقيين
- اختبار المستخدمين الحقيقيين: شركات مثل
Fableتربطك بأشخاص ذوي إعاقة، بحيث يمكن أن تساعد أبحاثك واختبارات المستخدمين في تحقيق أهداف الامتثال الخاصة بك.
ملحقات المتصفح وأدوات المطورين
- ملحقات المتصفح:
axeهو امتداد موصى به لمتصفحاتChromeوFirefoxوEdgeيساعد في تحديد وحل مشكلات الوصولية الشائعة. محرك الوصولية الخاص بـaxeمفتوح المصدر ويمكن استخدامه بطرق مختلفة، كما سيوضح هذا المقال.
التحضير للعمل: موقع تجريبي وبيئة التطوير
قبل أن نبدأ، قمت بإنشاء موقع ويب نموذجي لمحاكاة مكتبة مكونات (Component Library). إنه موقع ويب بسيط جداً تم إنشاؤه باستخدام Tailwind CSS ومستضاف على Vercel، ويوثق مكونين: badge و button. يمكنك الاطلاع على الكود المصدري على GitHub.
الموقع ثابت ويقع داخل مجلد public. يمكنك رؤية الموقع محلياً عن طريق تشغيل npm run serve والتحقق منه في المتصفح على http://localhost:8000.

تثبيت Cypress و cypress-axe
ابدأ باستنساخ المستودع الأمثلة. بعد ذلك، أنشئ فرعاً جديداً وقم بتثبيت cypress-axe، وهي الحزمة المسؤولة عن ربط محرك axe بـ Cypress.
git checkout -b add-cypress
npm install -D cypress cypress-axe
إعداد ملف الدعم لـ Cypress
بعد ذلك، أنشئ ملف cypress/support/index.js يحتوي على ما يلي:
import 'cypress-axe'
سيقوم هذا الاستيراد بحقن جميع الدوال التي نحتاجها لاختباراتنا.
بناء اختبار الوصولية الأول باستخدام Cypress
حان الوقت لإنشاء اختبار الوصولية. إليك الخطة:
- سيقوم
Cypressبزيارة كل صفحة (badgeوbutton) من المشروع. - سيقوم
Cypressباختبار كل مثال في الصفحة.
تحتوي صفحة Badge على مثالين (Default و Pill)، بينما تحتوي صفحة Button على ثلاثة أمثلة (Default و Pill و Outline). جميع هذه الأمثلة موجودة داخل عنصر <div> يحمل الفئة cypress-wrapper. أُضيفت هذه الفئة بقصد وحيد هو تحديد ما يحتاج إلى الاختبار.
تكوين Cypress
الخطوة الأولى هي إنشاء ملف تكوين Cypress (cypress.json):
{
"baseUrl": "http://localhost:8000/",
"video": false
}
يمثل baseUrl عنوان الموقع الإلكتروني الذي يعمل محلياً. كما ذكرت سابقاً، سيقوم npm run serve بتقديم محتوى مجلد public. الخيار الثاني، video، يعطل تسجيل الفيديو في Cypress، والذي لن يتم استخدامه في هذا المشروع.
كتابة نص الاختبار
حان الوقت لإنشاء الاختبار. في ملف cypress/integration/accessibility.spec.js، أضف ما يلي:
const routes = [
'badge.html',
'button.html'
];
describe('Component accessibility test', () => {
routes.forEach((route) => {
const componentName = route.replace('.html', '');
const testName = `${componentName} has no detectable accessibility violations on load`;
it(testName, () => {
cy.visit(route);
cy.injectAxe();
cy.get('.cypress-wrapper').each((element, index) => {
cy.checkA11y('.cypress-wrapper', {
runOnly: {
type: 'tag',
values: ['wcag2a'],
},
});
});
});
});
});
في الكود أعلاه، أقوم بإنشاء اختبارات ديناميكية بناءً على مصفوفة routes. سيقوم الاختبار بالتحقق من كل عنصر .cypress-wrapper مقابل قواعد WCAG 2.0 Level A. هناك معايير/أغراض مختلفة، كما يوضح الجدول أدناه:
معايير الوصولية المدعومة بواسطة axe-core
| اسم الوسم (Tag Name) | معيار/غرض الوصولية (Accessibility Standard / Purpose) |
|---|---|
wcag2a |
WCAG 2.0 Level A |
wcag2aa |
WCAG 2.0 Level AA |
wcag21a |
WCAG 2.1 Level A |
wcag21aa |
WCAG 2.1 Level AA |
best-practice |
أفضل ممارسات الوصولية الشائعة |
wcag*** |
معيار نجاح WCAG (على سبيل المثال، wcag111 يرتبط بـ SC 1.1.1) |
ACT |
قواعد اختبار المطابقة للوصولية المعتمدة من W3C |
section508 |
قواعد القسم 508 القديمة |
section508.*.* |
متطلب في القسم 508 القديم |
يمكنك العثور على مزيد من المعلومات حول هذا الموضوع في وثائق axe-core.
إضافة أمر التشغيل لـ Cypress
أخيراً، دعنا ننشئ أمراً داخل package.json لتشغيل الاختبارات:
{
"test": "cypress"
}
من هنا، هناك خياران: تشغيل Cypress في الوضع الصامت (headless mode) باستخدام npm run cypress run أو استخدام Cypress Test Runner مع npm run cypress open.
تشغيل اختبارات الوصولية
وضع التشغيل الصامت (Headless Mode)
باستخدام npm run test run، يجب أن يكون الإخراج مشابهاً للصورة التالية:

ستنجح الاختبارات نظراً لأن المكونات لا تحتوي على مشكلات وصولية.
وضع تشغيل الاختبار التفاعلي (Test Runner)
باستخدام npm run test open، سيتم فتح Cypress Test Runner ويمكنك متابعة الاختبارات خطوة بخطوة.

لقد أنجزنا أول معلم لنا. دعنا ندمج هذا الفرع في الفرع الرئيسي (master). إذا كنت ترغب في رؤية العمل المنجز حتى الآن، يمكنك الاطلاع على طلب السحب الخاص بي.
محاكاة سيناريوهات الفشل وتحسين تقارير الاختبار
تخيل أننا نقوم بتحديث الموقع ونرغب في تحديد الأزرار باستخدام معرفات (ids). يجب أن تكون خاصية id فريدة في المستند، حيث لا يمكن أن يكون لدينا عنصران بنفس المعرف. لكننا نسينا ذلك ووجدت ثلاثة أزرار بنفس المعرف. سيفشل Cypress وسيبدو الإخراج شيئاً كهذا:

تحسين مخرجات الاختبارات
دعنا نحسن إخراج اختباراتنا من خلال عرض جدول بالمشكلات المكتشفة. أولاً، دعنا ننشئ فرعاً جديداً:
git checkout -b improve-cypress-tests
تكوين المكونات الإضافية لـ Cypress
بعد ذلك، أنشئ ملف cypress/plugins/index.js بالمحتوى التالي:
module.exports = (on, config) => {
on('task', {
log(message) {
console.log(message)
return null
},
table(message) {
console.table(message)
return null
}
})
}
سيقوم هذا بتنفيذ الكود في Node عبر حدث المكون الإضافي task الخاص بـ Cypress.
تعديل دالة تسجيل الانتهاكات
بعد ذلك، دعنا نعود إلى ملف accessibility.spec.js ونضيف الدالة التالية في أعلى الملف:
const terminalLog = (violations) => {
cy.task('log', `${violations.length} accessibility violation ${violations.length === 1 ? '' : 's'} ${violations.length === 1 ? 'was' : 'were'} detected`)
// pluck specific keys to keep the table readable
const violationData = violations.map(
({ id, impact, description, nodes }) => ({
id,
impact,
description,
nodes: nodes.length
})
)
cy.task('table', violationData)
}
تحتوي مصفوفة violations على جميع المعلومات حول العناصر الفاشلة. يمكنك تعديل هذا الكود لتضمين، على سبيل المثال، الكود المصدري للعنصر في إخراج الاختبار.
تطبيق الدالة على اختبارات الوصولية
أخيراً، دعنا نستدعي الدالة داخل الاختبارات. عدّل دالة checkA11y لتصبح:
cy.checkA11y(
'.cypress-wrapper',
{
runOnly: {
type: 'tag',
values: ['wcag2a'],
},
},
terminalLog,
);
عند تشغيل الاختبار مرة أخرى، ستحصل على جدول يحتوي على المشكلات التي أبلغ عنها axe:

إذا كانت لديك أي أسئلة، يرجى مراجعة طلب السحب في Github.
الخطوات التالية لتعزيز الوصولية
من هنا، يمكنك مواصلة رحلتك نحو جعل المنتجات أكثر وصولية. كخطوات تالية، أوصي بما يلي:
- إضافة هذه الاختبارات إلى حل التكامل المستمر (CI) الخاص بك – لقد كتبت عن دمج Cypress داخل Semaphore.
- العثور على أفضل طريقة لتخصيص إخراج الاختبارات لتحسين استكشاف الأخطاء وإصلاحها.
- تعلم المزيد حول كيفية عمل
axe.
آمل أن تكون قد تعلمت أن اختبار الوصولية ليس صعباً ولا يتطلب الكثير للبدء. الأتمتة المدعومة بـ axe يمكن أن تساعدنا بالتأكيد في إنشاء تجارب مستخدم أفضل لجميع الأشخاص.
الخلاصة التقنية
تُعد أتمتة اختبارات الوصولية باستخدام أدوات مثل Cypress و axe-core خطوة حاسمة نحو بناء تطبيقات ويب شاملة ومتاحة للجميع. من خلال دمج هذه الاختبارات في سير عمل التطوير، يمكن للمطورين تحديد المشكلات المتعلقة بالوصولية مبكراً ومعالجتها بفعالية، مما يقلل من التكاليف والجهد على المدى الطويل. لا تقتصر فوائد الوصولية على الامتثال للمعايير فحسب، بل تمتد لتشمل تحسين تجربة المستخدم لقطاع أوسع من الجمهور، بما في ذلك ذوي الإعاقة وكبار السن، وحتى المستخدمين في ظروف بيئية صعبة. إن تبني هذه الممارسات يعكس التزاماً بالجودة والمسؤولية الاجتماعية في عالم تطوير الويب.