كيفية إعداد Cypress مع Next.js

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

تحذير:

  • إصدارات Cypress الأقدم من 13.6.3 لا تدعم TypeScript الإصدار 5 مع moduleResolution:"bundler". ومع ذلك، تم حل هذه المشكلة في Cypress الإصدار 13.6.3 وما بعده. cypress v13.6.3

البدء السريع

يمكنك استخدام 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 يحتوي على التكوين التالي:

import { defineConfig } from 'cypress'

export default defineConfig({
  e2e: {
    setupNodeEvents(on, config) {},
  },
})
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 يحتوي على التكوين التالي:

import { defineConfig } from 'cypress'

export default defineConfig({
  component: {
    devServer: {
      framework: 'next',
      bundler: 'webpack',
    },
  },
})
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 Server Components. نوصي باستخدام اختبارات 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 والتكامل المستمر من هذه المصادر: