EduFlow

الوحدة 4 · الأدوات والتسليم

Storybook والاختبار البصري والإصدارات

22 دقراءة 4 داكتشف الخطأ

الدرس في لمحة

حوّل الـ stories في Storybook إلى مجموعة اختبارات لكل حالة من حالات المكوّنات، والتقط التغييرات البصرية غير المقصودة بمقارنة لقطات الشاشة عبر الـ themes، ومرّر الإصدارات عبر خط CI يفحص قبل أن ينشر.

  1. 1الـ stories حالات اختبار
  2. 2اختبار الانحدار البصري
  3. 3خط الإصدار

لا فيديو هنا، بل الشيء الحقيقي: درس مكتوب وأمثلة قابلة للتشغيل واختبار وتدريب.

غيّر إصدار 4.2.0 في Northwind سطرًا واحدًا: الـ token الخاص بـ line-height لنص المتن، من 1.5 إلى 1.45. بدا كل شيء سليمًا في كل story فحصناها. لكنه دفع أيضًا آخر صف في جدول المسارات في تطبيق الـ dispatch إلى ما تحت حافة الشاشة، على أشيع دقّة شاشة للحواسيب المحمولة، في الكثافة المضغوطة، في الوضع الداكن. لم ينظر أحد إلى تلك التركيبة. ومنذ ذلك الحين صارت القاعدة بسيطة: الآلات تنظر إلى كل تركيبة؛ والبشر ينظرون إلى الفروقات.

الـ stories حالات اختبار

الـ story في Storybook تعرض مكوّنًا في حالة واحدة بـ props محدّدة. كتبت stories للتوثيق في القسم السابق؛ والـ stories نفسها هي العمود الفقري للاختبار:

  • العرض: يجب أن تُعرض كل story دون أخطاء.
  • التفاعل: يمكن أن تحمل الـ story دالة play تنقر وتكتب وتتحقّق، مثل «الضغط على Escape يغلق الـ Dialog ويعيد التركيز إلى الـ trigger».
  • إمكانية الوصول: إضافة إمكانية الوصول (accessibility addon) تشغّل فحوص axe-core على كل story وتبلّغ عن المخالفات مثل التسميات الناقصة أو التباين الفاشل.
  • البصري: تُلتقط صورة لكل story وتُقارن بصورة مرجعية معتمدة.

تستطيع إصدارات Storybook الحديثة تشغيل الـ stories كاختبارات عبر تكامل مع Vitest ‏(@storybook/addon-vitest)، فتعمل الملفات نفسها في واجهة Storybook وفي الطرفية وفي الـ CI. وتشترط Northwind story واحدة لكل خانة في مصفوفة الحالات من درس إمكانية الوصول. هذه القاعدة تمنحك تغطية اختبارية شبه مجانية، لأن عمل تصميم الحالات أُنجز أصلًا.

اختبار الانحدار البصري

اختبار الانحدار البصري يعرض story، ويلتقط صورة، ويقارنها بكسلًا بكسلًا بصورة مرجعية محفوظة. وإن اختلفتا بما يتجاوز حدًّا معيّنًا، يفشل الاختبار ويعرض الفرق. ثم يقرّر إنسان: إن كان التغيير مقصودًا، يقبله صورةً مرجعية جديدة؛ وإن لم يكن، يصلح الكود.

تختار الفرق عادةً أحد إعدادين. خدمة مستضافة مثل Chromatic، التي يصنعها القائمون على Storybook، تعرض الـ stories في السحابة وتعطي المراجعين واجهة ويب لقبول الفروقات. أو تلتقط الصور بنفسك باستخدام Playwright:

tests/visual.spec.ts
import { test, expect } from '@playwright/test';

const stories = ['components-button--primary', 'components-button--danger', 'components-dialog--confirm'];
const themes = ['light', 'dark'];
const densities = ['comfortable', 'compact'];

for (const id of stories) {
  for (const theme of themes) {
    for (const density of densities) {
      test(`${id} ${theme} ${density}`, async ({ page }) => {
        await page.goto(`/iframe.html?id=${id}&viewMode=story`);
        await page.evaluate(([t, d]) => {
          document.documentElement.dataset.theme = t;
          document.documentElement.dataset.density = d;
        }, [theme, density]);
        await expect(page).toHaveScreenshot(`${id}-${theme}-${density}.png`);
      });
    }
  }
}

كل story تُعرض في كل تركيبة من الـ theme والكثافة، ومعهما العلامة في مجموعة Northwind الحقيقية، وهكذا كان سيُلتقط انحدار ارتفاع السطر. والدالة toHaveScreenshot في Playwright تعطّل حركات CSS افتراضيًا وتعيد المحاولة حتى تتطابق لقطتان متتاليتان، فتزيل أشيع مصادر الضجيج.

والاختبارات البصرية تحرس طبقات الـ tokens أيضًا. تضيف Northwind قاعدة Stylelint في مهمّة الـ CI نفسها ترفض أي إشارة إلى primitive token، مثل var(--nw-blue-600)، داخل أنماط المكوّنات. ثم تؤكّد المجموعة البصرية أن الـ CSS الملتزم بالقاعدة ما زال يعرض ما اعتمده المصمّمون.

خط الإصدار

الاختبار لا يحمي المستخدمين إلا إذا كان النشر عاجزًا عن تخطّيه. لخط الإصدار في Northwind نصفان.

على كل pull request: التثبيت بـ npm ci، وتشغيل فحوص الـ tokens (التسمية، والمراجع، والتباين)، وفحص الأنواع، والـ lint، واختبارات الوحدات والـ stories، وفحوص إمكانية الوصول، والاختبارات البصرية، واشتراط ملف changeset حين تتغيّر حزمة. ولا يمكن دمج الـ pull request حتى تنجح كل هذه، ويوافق عضو من النواة على الفروقات البصرية.

على main: يجمع إجراء Changesets الـ changesets المعلّقة في pull request باسم «Version Packages» يرفع الإصدارات ويحدّث CHANGELOG.md. ودمج هذا الـ pull request يشغّل خطوة النشر:

.github/workflows/release.yml
name: Release
on:
  push:
    branches: [main]
jobs:
  release:
    runs-on: ubuntu-latest
    permissions:
      contents: write        # push version commits and tags
      pull-requests: write   # open the Version Packages pull request
      id-token: write        # npm trusted publishing
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with:
          node-version: 24
      - run: npm ci
      - run: npm run build
      - run: npm test
      - uses: changesets/action@v2
        with:
          publish-script: npm run release

النشر يحدث أخيرًا، ومن main وحده، وبعد البناء والاختبارات فقط. وبعد خروج الحزم، ينشر سير العمل نفسه موقع التوثيق ونسخة Storybook، ويستورد فريق النواة الـ tokens التي صدرت في الإصدار إلى مكتبة Figma.

في التمرين تراجع سير عمل للإصدار يمكنه نشر كود معطوب. وبهذا يكتمل قسم التسليم؛ وبعده توسّع النظام ليخدم أربعين فريقًا.

أهم النقاط

  • الـ story حالة موثّقة للمكوّن، والـ story نفسها يمكن أن تقود اختبارات التفاعل وفحوص إمكانية الوصول واللقطات البصرية.
  • اختبارات الانحدار البصري (visual regression) تقارن لقطات الشاشة بصور مرجعية معتمدة (baselines)، فتظهر التغييرات غير المقصودة كفروقات يقبلها إنسان أو يرفضها.
  • اعرض كل مكوّن في كل تركيبة من الـ themes، لأن الزوايا التي لا تنظر إليها أبدًا هي التي تنكسر.
  • خط الإصدار يفحص، ثم يرقّم، ثم ينشر؛ ولا يُنشر شيء من branch لم يجتز كل الفحوص.

قراءات إضافية

تحقّق من فهمك

3 أسئلة

السؤال 1 من 3

فشل اختبار بصري في 46 story بعد pull request لم يغيّر إلا token الحشوة الخاص بـ Dialog. ماذا يجب أن يفعل المراجع أولًا؟

السؤال 2 من 3

تنجح الاختبارات البصرية على حاسوب المطوّر وتفشل في الـ CI بفروقات صغيرة في حواف النص. ما السبب الأرجح والإصلاح؟

السؤال 3 من 3

أين يجب أن يعمل npm publish في سير عمل الإصدار لنظام التصميم؟

تدريب

اكتشف الخطأ

امنع سير العمل من نشر كود معطوب

سير العمل هذا في GitHub Actions يُفترض أن ينشر @northwind/ui على npm بعد دمج التغييرات واختبارها. لكنه بصيغته الحالية قد يضع كودًا غير مختبَر وغير مُراجَع أمام الفرق الأربعين كلها. اختر السطر أو الأسطر المسبّبة لذلك.

حدّد السطر أو الأسطر التي تظنها خاطئة، ثم تحقّق.