إعداد Cypress مع Next.js

Cypress هو أداة تشغيل اختبارات تُستخدم لاختبارات End-to-End (E2E) واختبارات المكونات. ستوضح لك هذه الصفحة كيفية إعداد Cypress مع Next.js وكتابة أول اختباراتك.

تحذير:

  • بالنسبة لـ اختبارات المكونات، لا يدعم Cypress حاليًا Next.js الإصدار 14 ومكونات الخادم async. يتم تتبع هذه المشكلات حاليًا. في الوقت الحالي، يعمل اختبار المكونات مع Next.js الإصدار 13، ونوصي باستخدام اختبار E2E لمكونات الخادم async.
  • لا يدعم Cypress حاليًا TypeScript الإصدار 5 مع moduleResolution:"bundler". يتم تتبع هذه المشكلة حاليًا.

البدء السريع

يمكنك استخدام create-next-app مع مثال with-cypress للبدء بسرعة.

Terminal
npx create-next-app@latest --example with-cypress with-cypress-app

الإعداد اليدوي

لإعداد Cypress يدويًا، قم بتثبيت cypress كتبعية تطوير:

Terminal
npm install -D cypress
# أو
yarn add -D cypress
# أو
pnpm install -D cypress

أضف أمر open الخاص بـ Cypress إلى حقل scripts في ملف package.json:

package.json
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "cypress:open": "cypress open"
  }
}

قم بتشغيل Cypress لأول مرة لفتح مجموعة اختبارات Cypress:

Terminal
npm run cypress:open

يمكنك اختيار تكوين اختبار E2E و/أو اختبار المكونات. سيؤدي اختيار أي من هذه الخيارات إلى إنشاء ملف cypress.config.js ومجلد cypress في مشروعك تلقائيًا.

إنشاء أول اختبار E2E باستخدام Cypress

تأكد من أن ملف cypress.config.js يحتوي على التكوين التالي:

cypress.config.ts
import { defineConfig } from 'cypress'

export default defineConfig({
  e2e: {
    setupNodeEvents(on, config) {},
  },
})
cypress.config.js
const { defineConfig } = require('cypress')

module.exports = defineConfig({
  e2e: {
    setupNodeEvents(on, config) {},
  },
})

بعد ذلك، قم بإنشاء ملفين جديدين في Next.js:

app/page.js
import Link from 'next/link'

export default function Page() {
  return (
    <div>
      <h1>Home</h1>
      <Link href="/about">About</Link>
    </div>
  )
}
app/about/page.js
import Link from 'next/link'

export default function Page() {
  return (
    <div>
      <h1>About</h1>
      <Link href="/">Home</Link>
    </div>
  )
}

أضف اختبارًا للتحقق من أن التنقل يعمل بشكل صحيح:

cypress/e2e/app.cy.js
describe('Navigation', () => {
  it('should navigate to the about page', () => {
    // ابدأ من الصفحة الرئيسية
    cy.visit('http://localhost:3000/')

    // ابحث عن رابط يحتوي على سمة href تشمل "about" وانقر عليه
    cy.get('a[href*="about"]').click()

    // يجب أن يتضمن الرابط الجديد "/about"
    cy.url().should('include', '/about')

    // يجب أن تحتوي الصفحة الجديدة على h1 مع نص "About"
    cy.get('h1').contains('About')
  })
})

تشغيل اختبارات E2E

سيقوم Cypress بمحاكاة مستخدم يتنقل في تطبيقك، وهذا يتطلب تشغيل خادم Next.js. نوصي بتشغيل اختباراتك ضد كود الإنتاج لمحاكاة سلوك التطبيق الفعلي بشكل أقرب.

قم بتشغيل npm run build && npm run start لبناء تطبيق Next.js الخاص بك، ثم قم بتشغيل npm run cypress:open في نافذة طرفية أخرى لبدء Cypress وتشغيل مجموعة اختبارات E2E.

معلومة مفيدة:

  • يمكنك استخدام cy.visit("/") بدلاً من cy.visit("http://localhost:3000/") عن طريق إضافة baseUrl: 'http://localhost:3000' إلى ملف تكوين cypress.config.js.
  • بدلاً من ذلك، يمكنك تثبيت حزمة start-server-and-test لتشغيل خادم إنتاج Next.js بالتزامن مع Cypress. بعد التثبيت، أضف "test": "start-server-and-test start http://localhost:3000 cypress" إلى حقل scripts في ملف package.json. تذكر إعادة بناء تطبيقك بعد إجراء تغييرات جديدة.

إنشاء أول اختبار مكون باستخدام Cypress

تقوم اختبارات المكونات ببناء وتثبيت مكون معين دون الحاجة إلى تجميع التطبيق بالكامل أو تشغيل خادم.

حدد اختبار المكونات في تطبيق Cypress، ثم حدد Next.js كإطار العمل الأمامي. سيتم إنشاء مجلد cypress/component في مشروعك، وسيتم تحديث ملف cypress.config.js لتمكين اختبار المكونات.

تأكد من أن ملف cypress.config.js يحتوي على التكوين التالي:

cypress.config.ts
import { defineConfig } from 'cypress'

export default defineConfig({
  component: {
    devServer: {
      framework: 'next',
      bundler: 'webpack',
    },
  },
})
cypress.config.js
const { defineConfig } = require('cypress')

module.exports = defineConfig({
  component: {
    devServer: {
      framework: 'next',
      bundler: 'webpack',
    },
  },
})

بافتراض نفس المكونات من القسم السابق، أضف اختبارًا للتحقق من أن المكون يعرض النتائج المتوقعة:

cypress/component/about.cy.tsx
import Page from '../../app/page'

describe('<Page />', () => {
  it('should render and display expected content', () => {
    // قم بتثبيت مكون React لصفحة Home
    cy.mount(<Page />)

    // يجب أن تحتوي الصفحة الجديدة على h1 مع نص "Home"
    cy.get('h1').contains('Home')

    // تحقق من وجود رابط مع الرابط المتوقع
    // يفضل استخدام اختبار E2E لمتابعة الروابط
    cy.get('a[href="/about"]').should('be.visible')
  })
})

معلومة مفيدة:

  • لا يدعم Cypress حاليًا اختبار المكونات لمكونات الخادم async. نوصي باستخدام اختبار E2E.
  • نظرًا لأن اختبارات المكونات لا تتطلب خادم Next.js، فقد لا تعمل ميزات مثل <Image /> التي تعتمد على توفر خادم بشكل افتراضي.

تشغيل اختبارات المكونات

قم بتشغيل npm run cypress:open في طرفيتك لبدء Cypress وتشغيل مجموعة اختبارات المكونات.

التكامل المستمر (CI)

بالإضافة إلى الاختبارات التفاعلية، يمكنك أيضًا تشغيل Cypress بدون واجهة مستخدم باستخدام أمر cypress run، وهو أكثر ملاءمة لبيئات التكامل المستمر:

package.json
{
  "scripts": {
    //...
    "e2e": "start-server-and-test dev http://localhost:3000 \"cypress open --e2e\"",
    "e2e:headless": "start-server-and-test dev http://localhost:3000 \"cypress run --e2e\"",
    "component": "cypress open --component",
    "component:headless": "cypress run --component"
  }
}

يمكنك معرفة المزيد عن Cypress والتكامل المستمر من هذه المصادر: