מדריך בדיקות

מדריך בדיקות

מדריך זה מספק תיעוד מקיף לבדיקת התוסף WooAI Chatbot Pro בכל השכבות: בדיקות יחידה ואינטגרציה ב-PHP, בדיקות קומפוננטות JavaScript, וזרימות end-to-end.

1. סקירת בדיקות

פילוסופיית הבדיקות

אסטרטגיית הבדיקות של WooAI Chatbot Pro עוקבת אחר עקרונות ליבה אלה:

  1. בידוד בדיקות: כל בדיקה רצה באופן עצמאי עם מצב נקי. mocks גלובליים ו-transients מאופסים בין בדיקות למניעת זיהום צולב.

  2. Mock לתלויות חיצוניות: ספקי AI, WooCommerce, ו-APIs חיצוניים מקבלים mock כדי להבטיח התנהגות דטרמיניסטית והרצה מהירה ללא קריאות רשת.

  3. כיסוי היררכי: בדיקות יחידה מאמתות קומפוננטות בודדות, בדיקות אינטגרציה מאמתות אינטראקציות בין קומפוננטות, ובדיקות E2E מאמתות זרימות משתמש מלאות.

  4. כישלון מהיר: הבדיקות מוגדרות במצב קפדני (failOnRisky, failOnWarning) כדי לתפוס בעיות פוטנציאליות מוקדם.

סוגי בדיקות

סוג Framework ספרייה מטרה
יחידה PHPUnit tests/AI, tests/Search, tests/Chat בדיקת מחלקה/מתודה בודדת
אינטגרציה PHPUnit tests/Integration בדיקת אינטראקציה בין קומפוננטות
E2E PHPUnit tests/E2E בדיקת זרימה מלאה
JavaScript Jest assets/src/**/__tests__ בדיקת קומפוננטות React והוקס

יעדי כיסוי

הפרויקט אוכף סף כיסוי קפדני:

// jest.config.js
coverageThreshold: {
  global: {
    lines: 85,
    branches: 85,
    functions: 85,
    statements: 85,
  },
},

יעדי כיסוי PHP: 80%+ כיסוי שורות למודולי ליבה.


2. בדיקות PHP (PHPUnit)

הגדרה

תצורת PHPUnit

phpunit.xml מגדיר שלוש חבילות בדיקות עם הרצה קפדנית:

<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         bootstrap="tests/bootstrap.php"
         colors="true"
         executionOrder="depends,defects"
         beStrictAboutOutputDuringTests="true"
         failOnRisky="true"
         failOnWarning="true">

    <testsuites>
        <testsuite name="Unit">
            <directory>tests/AI</directory>
            <directory>tests/Search</directory>
            <directory>tests/Chat</directory>
        </testsuite>
        <testsuite name="Integration">
            <directory>tests/Integration</directory>
        </testsuite>
        <testsuite name="E2E">
            <directory>tests/E2E</directory>
        </testsuite>
    </testsuites>
</phpunit>

הגדרת בסיס נתונים לבדיקות

הבדיקות משתמשות בפונקציות WordPress מדומות המוגדרות ב-tests/bootstrap.php. לא נדרש חיבור לבסיס נתונים אמיתי לבדיקות יחידה:

// אחסון mock גלובלי
global $_wp_options, $_wp_transients;
$_wp_options    = array();
$_wp_transients = array();

משתני סביבה לספקי AI מוגדרים בתצורת PHPUnit:

<php>
    <env name="GEMINI_API_KEY" value="test-key"/>
    <env name="OPENAI_API_KEY" value="test-key"/>
    <env name="ANTHROPIC_API_KEY" value="test-key"/>
    <env name="SUPABASE_URL" value="https://test.supabase.co"/>
    <env name="SUPABASE_KEY" value="test-key"/>
</php>

מבנה בדיקות

ארגון קבצי בדיקות

tests/
├── bootstrap.php              # Bootstrap של PHPUnit עם mocks של WordPress
├── Helpers/
│   ├── TestCase.php           # מחלקת בדיקה בסיסית עם כלי עזר
│   ├── MockAIProvider.php     # test double לספק AI
│   └── MockWooCommerce.php    # סימולציית WooCommerce
├── AI/
│   └── ProvidersTest.php      # בדיקות יחידה לספקי AI
├── Search/
│   └── SemanticSearchTest.php # בדיקות חיפוש סמנטי
├── Chat/
│   └── MessageHandlerTest.php # בדיקות טיפול בהודעות
├── Integration/
│   └── WooCommerceTest.php    # בדיקות אינטגרציה עם WooCommerce
└── E2E/
    └── ChatFlowTest.php       # בדיקות זרימה end-to-end

מוסכמות שמות בדיקות

עקבו אחר תבנית זו לשמות מתודות בדיקה:

public function test_{method_or_feature}_{scenario}_{expected_outcome}()

דוגמאות:
test_gemini_provider_initialization()
test_gemini_provider_unavailable_without_key()
test_rate_limit_simulation()

מחלקות בדיקה בסיסיות

הרחיבו את WooAIChatbotTestsHelpersTestCase לגישה לכלי עזר נפוצים:

namespace WooAIChatbotTestsAI;

use WooAIChatbotTestsHelpersTestCase;

class ProvidersTest extends TestCase {

    protected function setUp(): void {
        parent::setUp();
        // הגדרה ספציפית לבדיקה
    }

    protected function tearDown(): void {
        parent::tearDown();
        // ניקוי
    }
}

מתודות עזר זמינות ב-TestCase:

מתודה מטרה
setEnv($name, $value) הגדרת משתנה סביבה לבדיקה
createWPError($code, $message) יצירת mock WP_Error
assertIsWPError($actual) טענה שהערך הוא WP_Error
assertNotWPError($actual) טענה שהערך אינו WP_Error
assertWPErrorCode($code, $error) טענה על קוד שגיאה ספציפי
assertArrayHasKeys($keys, $array) טענה שלמערך יש את כל המפתחות
getPrivateProperty($obj, $prop) גישה למאפיין פרטי
callPrivateMethod($obj, $method) קריאה למתודה פרטית
createTempFile($content) יצירת קובץ זמני

הרצת בדיקות

פקודות בדיקה של Composer

# הרצת כל הבדיקות
composer test

# הרצת חבילת בדיקות ספציפית
composer test:unit
composer test:integration
composer test:e2e

# הרצה עם כיסוי
composer test:coverage          # דוח HTML
composer test:coverage:text     # פלט קונסול

הרצת בדיקה בודדת

# הרצת קובץ בדיקה ספציפי
./vendor/bin/phpunit tests/AI/ProvidersTest.php

# הרצת מתודת בדיקה ספציפית
./vendor/bin/phpunit --filter test_gemini_provider_initialization

# הרצה לפי אנוטציית קבוצה
./vendor/bin/phpunit --group ai
./vendor/bin/phpunit --group woocommerce

כיסוי קוד

דוחות כיסוי נוצרים ל-coverage/:

composer test:coverage

מיקומי פלט:
coverage/html/index.html – דוח HTML אינטראקטיבי
coverage/clover.xml – פורמט לאינטגרציית CI
coverage/junit.xml – פורמט JUnit XML

כתיבת בדיקות

דוגמת בדיקת יחידה

/**
 * בדיקת אתחול GeminiProvider
 *
 * @covers WooAIChatbotAIProvidersGeminiProvider::__construct
 * @group ai
 * @group providers
 */
public function test_gemini_provider_initialization() {
    // Arrange
    $this->setEnv( 'GEMINI_API_KEY', 'test-gemini-key' );

    // Act
    $provider = new GeminiProvider();

    // Assert
    $this->assertInstanceOf( GeminiProvider::class, $provider );
    $this->assertTrue( $provider->is_available() );
    $this->assertEquals( 'Google Gemini', $provider->get_provider_name() );
}

דוגמת בדיקת אינטגרציה

/**
 * בדיקת חילוץ קונטקסט מוצר
 *
 * @group integration
 * @group woocommerce
 */
public function test_product_context_extraction() {
    // Arrange
    $product = MockWooCommerce::create_product(
        array(
            'id'          => 123,
            'name'        => 'Premium Headphones',
            'price'       => 199.99,
            'description' => 'High-quality wireless headphones',
            'in_stock'    => true,
        )
    );

    // Act
    $context = array(
        'product_id'  => $product->get_id(),
        'name'        => $product->get_name(),
        'price'       => $product->get_price(),
        'description' => $product->get_description(),
        'in_stock'    => $product->is_in_stock(),
    );

    // Assert
    $this->assertArrayHasKeys(
        array( 'product_id', 'name', 'price', 'description', 'in_stock' ),
        $context
    );
    $this->assertEquals( 'Premium Headphones', $context['name'] );
    $this->assertTrue( $context['in_stock'] );
}

אסטרטגיות Mocking

שימוש ב-MockAIProvider:

// תרחיש הצלחה
$mock_provider = new MockAIProvider(
    array(
        'response' => array(
            'content' => 'Test response',
            'tokens'  => 5,
            'model'   => 'test-model',
        ),
    )
);

$response = $mock_provider->generate_response( $messages );
$this->assertEquals( 'Test response', $response['content'] );

// תרחיש שגיאה
$mock_provider = new MockAIProvider(
    array(
        'response' => $this->createWPError( 'rate_limit_exceeded', 'Rate limit exceeded' ),
    )
);

$response = $mock_provider->generate_response( array() );
$this->assertIsWPError( $response );

// אימות קריאה
$this->assertTrue( $mock_provider->was_called( 'generate_response' ) );
$this->assertEquals( 1, $mock_provider->get_call_count( 'generate_response' ) );

שימוש ב-MockWooCommerce:

// יצירת מוצרי בדיקה
MockWooCommerce::create_product( array(
    'id'    => 1,
    'name'  => 'Product 1',
    'price' => 29.99,
));

// הוספה לעגלה
MockWooCommerce::add_to_cart( 1, 2 );

// קבלת עגלה
$cart = MockWooCommerce::get_cart();

// איפוס בין בדיקות
MockWooCommerce::reset();

3. בדיקות JavaScript (Jest)

הגדרה

תצורת Jest

jest.config.js מגדיר תמיכת TypeScript עם כינויי נתיבים:

module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'jsdom',
  roots: ['<rootDir>/assets/src'],
  testMatch: ['**/__tests__/**/*.ts?(x)', '**/?(*.)+(spec|test).ts?(x)'],
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/assets/src/$1',
    '^@admin/(.*)$': '<rootDir>/assets/src/admin/$1',
    '^@chat/(.*)$': '<rootDir>/assets/src/chat/$1',
    '^@components/(.*)$': '<rootDir>/assets/src/components/$1',
    '^@hooks/(.*)$': '<rootDir>/assets/src/hooks/$1',
    '^@utils/(.*)$': '<rootDir>/assets/src/utils/$1',
    '.(css|less|scss|sass)$': 'identity-obj-proxy',
  },
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
};

אינטגרציית Testing Library

jest.setup.js מספק גלובליים של WordPress ותצורה:

import '@testing-library/jest-dom';

// Mock גלובלי של WordPress
global.wp = {
  i18n: {
    __: (text) => text,
    _x: (text) => text,
    _n: (single, plural, number) => (number === 1 ? single : plural),
  },
  hooks: {
    addAction: jest.fn(),
    addFilter: jest.fn(),
    doAction: jest.fn(),
    applyFilters: jest.fn(),
  },
};

// Mock ל-window.wooAIConfig
global.window.wooAIConfig = {
  apiUrl: 'http://localhost/wp-json/woo-ai/v1',
  nonce: 'test-nonce',
  locale: 'en_US',
  isRtl: false,
};

הרצת בדיקות

# הרצת כל בדיקות JavaScript
npm run test

# מצב watch לפיתוח
npm run test:watch

# יצירת דוח כיסוי
npm run test:coverage

כתיבת בדיקות

דוגמת בדיקת קומפוננטה

import { render, screen, fireEvent } from '@testing-library/react';
import { ChatMessage } from '@components/ChatMessage';

describe('ChatMessage', () => {
  it('renders user message correctly', () => {
    // Arrange
    const message = {
      id: '1',
      role: 'user' as const,
      content: 'Hello, I need help with shoes',
      timestamp: new Date().toISOString(),
    };

    // Act
    render(<ChatMessage message={message} />);

    // Assert
    expect(screen.getByText('Hello, I need help with shoes')).toBeInTheDocument();
    expect(screen.getByRole('article')).toHaveClass('user-message');
  });

  it('renders assistant message with products', () => {
    // Arrange
    const message = {
      id: '2',
      role: 'assistant' as const,
      content: 'Here are some shoes I found',
      data: {
        products: [
          { id: 1, name: 'Running Shoes', price: '$99.00' },
        ],
      },
      timestamp: new Date().toISOString(),
    };

    // Act
    render(<ChatMessage message={message} />);

    // Assert
    expect(screen.getByText('Running Shoes')).toBeInTheDocument();
    expect(screen.getByText('$99.00')).toBeInTheDocument();
  });
});

דוגמת בדיקת Hook

import { renderHook, act } from '@testing-library/react';
import { useChat } from '@hooks/useChat';

describe('useChat', () => {
  beforeEach(() => {
    global.fetch = jest.fn();
  });

  it('initializes with empty messages', () => {
    const { result } = renderHook(() => useChat());

    expect(result.current.messages).toEqual([]);
    expect(result.current.isLoading).toBe(false);
  });

  it('sends message and receives response', async () => {
    // Mock תגובת API
    (global.fetch as jest.Mock).mockResolvedValueOnce({
      ok: true,
      json: () => Promise.resolve({
        content: 'Here are your results',
        type: 'text',
      }),
    });

    const { result } = renderHook(() => useChat());

    await act(async () => {
      await result.current.sendMessage('Show me laptops');
    });

    expect(result.current.messages).toHaveLength(2);
    expect(result.current.messages[0].role).toBe('user');
    expect(result.current.messages[1].role).toBe('assistant');
  });
});

דוגמת בדיקת שירות

import { ChatService } from '@utils/ChatService';

describe('ChatService', () => {
  let chatService: ChatService;

  beforeEach(() => {
    chatService = new ChatService({
      apiUrl: 'http://localhost/wp-json/woo-ai/v1',
      nonce: 'test-nonce',
    });
    global.fetch = jest.fn();
  });

  it('sends chat message with correct headers', async () => {
    (global.fetch as jest.Mock).mockResolvedValueOnce({
      ok: true,
      json: () => Promise.resolve({ content: 'Response' }),
    });

    await chatService.send('Hello');

    expect(global.fetch).toHaveBeenCalledWith(
      'http://localhost/wp-json/woo-ai/v1/chat',
      expect.objectContaining({
        method: 'POST',
        headers: expect.objectContaining({
          'Content-Type': 'application/json',
          'X-WP-Nonce': 'test-nonce',
        }),
      })
    );
  });

  it('handles API errors gracefully', async () => {
    (global.fetch as jest.Mock).mockRejectedValueOnce(new Error('Network error'));

    await expect(chatService.send('Hello')).rejects.toThrow('Network error');
  });
});

4. בדיקות E2E (Playwright)

הגדרה

Playwright כלול כתלות לבדיקות E2E מבוססות דפדפן:

# התקנת דפדפני Playwright
npx playwright install

תצורת Playwright

צרו playwright.config.ts לתרחישי E2E של WordPress:

import { defineConfig } from '@playwright/test';

export default defineConfig({
  testDir: './e2e',
  timeout: 30000,
  use: {
    baseURL: 'http://localhost:8080',
    trace: 'on-first-retry',
    screenshot: 'only-on-failure',
  },
  projects: [
    { name: 'chromium', use: { browserName: 'chromium' } },
    { name: 'firefox', use: { browserName: 'firefox' } },
    { name: 'webkit', use: { browserName: 'webkit' } },
  ],
});

כתיבת בדיקות E2E

תבנית Page Object

// e2e/pages/ChatWidgetPage.ts
import { Page, Locator } from '@playwright/test';

export class ChatWidgetPage {
  readonly page: Page;
  readonly chatButton: Locator;
  readonly chatInput: Locator;
  readonly sendButton: Locator;
  readonly messagesContainer: Locator;

  constructor(page: Page) {
    this.page = page;
    this.chatButton = page.locator('[data-testid="chat-widget-button"]');
    this.chatInput = page.locator('[data-testid="chat-input"]');
    this.sendButton = page.locator('[data-testid="send-button"]');
    this.messagesContainer = page.locator('[data-testid="messages-container"]');
  }

  async openChat() {
    await this.chatButton.click();
    await this.page.waitForSelector('[data-testid="chat-input"]');
  }

  async sendMessage(message: string) {
    await this.chatInput.fill(message);
    await this.sendButton.click();
  }

  async waitForResponse() {
    await this.page.waitForSelector('[data-testid="assistant-message"]');
  }

  async getLastMessage(): Promise<string> {
    const messages = this.messagesContainer.locator('[data-testid="message"]');
    const lastMessage = messages.last();
    return lastMessage.textContent() ?? '';
  }
}

תרחישים נפוצים

// e2e/chat-flow.spec.ts
import { test, expect } from '@playwright/test';
import { ChatWidgetPage } from './pages/ChatWidgetPage';

test.describe('Chat Widget Flow', () => {
  let chatWidget: ChatWidgetPage;

  test.beforeEach(async ({ page }) => {
    chatWidget = new ChatWidgetPage(page);
    await page.goto('/shop');
  });

  test('opens chat widget and sends message', async ({ page }) => {
    await chatWidget.openChat();
    await chatWidget.sendMessage('Show me running shoes');
    await chatWidget.waitForResponse();

    const response = await chatWidget.getLastMessage();
    expect(response).toContain('running shoes');
  });

  test('displays product cards in response', async ({ page }) => {
    await chatWidget.openChat();
    await chatWidget.sendMessage('I need a laptop under $1000');
    await chatWidget.waitForResponse();

    const productCards = page.locator('[data-testid="product-card"]');
    await expect(productCards).toHaveCount.greaterThan(0);
  });
});

5. כלי איכות קוד

ESLint

תצורה

.eslintrc.json מרחיב כללים מומלצים של TypeScript ו-React:

{
  "extends": [
    "eslint:recommended",
    "plugin:react/recommended",
    "plugin:react-hooks/recommended",
    "plugin:@typescript-eslint/recommended",
    "prettier"
  ],
  "rules": {
    "react/react-in-jsx-scope": "off",
    "@typescript-eslint/no-explicit-any": "warn",
    "@typescript-eslint/no-unused-vars": ["error", {
      "argsIgnorePattern": "^_",
      "varsIgnorePattern": "^_"
    }],
    "no-console": ["warn", { "allow": ["warn", "error"] }]
  }
}

פקודות

# Lint עם תיקון אוטומטי
npm run lint

# בדיקה בלבד (ללא שינויים)
npm run lint:check

PHPCS

תקני WordPress

תצורת phpcs.xml אוכפת כללי תחביר ואבטחה של PHP:

<ruleset name="WooAI Chatbot Pro">
    <file>./woo-ai-chatbot-pro.php</file>
    <file>./includes</file>

    <exclude-pattern>*/vendor/*</exclude-pattern>
    <exclude-pattern>*/tests/*</exclude-pattern>

    <!-- תחביר ואבטחה -->
    <rule ref="Generic.PHP.Syntax"/>
    <rule ref="Squiz.PHP.Eval"/>
    <rule ref="Generic.PHP.NoSilencedErrors"/>
</ruleset>

פקודות

# הרצת PHPCS
npm run phpcs
# או
composer phpcs

# תיקון אוטומטי של בעיות
npm run phpcs:fix
# או
composer phpcbf

TypeScript

תצורת מצב קפדני

tsconfig.json מאפשר את כל אפשרויות הבדיקה הקפדניות:

{
  "compilerOptions": {
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictPropertyInitialization": true
  }
}

בדיקת טיפוסים

# הרצת בדיקת טיפוסים
npm run typecheck

6. הוקי Pre-commit (Husky)

תצורת Hook

התקנת הוקי Husky:

npm run prepare

זה מריץ husky install ומגדיר הוקי Git ב-.husky/.

הגדרת Lint-staged

הוסיפו ל-package.json:

{
  "lint-staged": {
    "assets/src/**/*.{ts,tsx}": [
      "eslint --fix",
      "prettier --write"
    ],
    "includes/**/*.php": [
      "composer phpcs"
    ]
  }
}

הוק Pre-commit

צרו .husky/pre-commit:

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npm run typecheck
npx lint-staged
npm run test -- --passWithNoTests

7. נתוני בדיקה ו-Fixtures

נתונים לדוגמה

השתמשו ב-MockWooCommerce ליצירת מוצרי בדיקה עקביים:

protected function createTestProducts(): array {
    return array(
        MockWooCommerce::create_product( array(
            'id'    => 1,
            'name'  => 'Running Shoes',
            'price' => 129.99,
        )),
        MockWooCommerce::create_product( array(
            'id'    => 2,
            'name'  => 'Hiking Boots',
            'price' => 189.99,
        )),
    );
}

תבניות Factory

class ProductFactory {
    private static int $id = 0;

    public static function create( array $overrides = array() ): MockProduct {
        return MockWooCommerce::create_product( array_merge(
            array(
                'id'    => ++self::$id,
                'name'  => 'Product ' . self::$id,
                'price' => rand( 10, 500 ) + 0.99,
            ),
            $overrides
        ));
    }

    public static function createMany( int $count ): array {
        return array_map( fn() => self::create(), range( 1, $count ) );
    }
}

זריעת בסיס נתונים

לבדיקות אינטגרציה הדורשות מצב בסיס נתונים:

protected function seedTestData(): void {
    global $_wp_options;

    $_wp_options['woo_ai_settings'] = array(
        'primary_provider'   => 'gemini',
        'fallback_providers' => array( 'openai', 'claude' ),
        'temperature'        => 0.7,
    );

    // יצירת מוצרי בדיקה
    for ( $i = 1; $i <= 10; ++$i ) {
        MockWooCommerce::create_product( array(
            'id'    => $i,
            'name'  => "Test Product {$i}",
            'price' => $i * 10.00,
        ));
    }
}

8. אינטגרציית CI/CD

GitHub Actions

צרו .github/workflows/tests.yml:

name: Tests

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main, develop]

jobs:
  php-tests:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        php: ['8.1', '8.2', '8.3']

    steps:
      - uses: actions/checkout@v4

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: ${{ matrix.php }}
          coverage: xdebug

      - name: Install dependencies
        run: composer install --prefer-dist --no-progress

      - name: Run PHPUnit
        run: composer test:coverage:text

      - name: Run PHPCS
        run: composer phpcs

  js-tests:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: '18'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Type check
        run: npm run typecheck

      - name: Lint
        run: npm run lint:check

      - name: Run tests
        run: npm run test:coverage

      - name: Build
        run: npm run build

שערי Deployment

הבדיקות חייבות לעבור לפני deployment. הגדירו כללי הגנת branch:

  1. בדיקות נדרשות: php-tests, js-tests
  2. סף כיסוי: כישלון אם הכיסוי יורד מתחת ל-80%
  3. ללא force pushes: הגנה על branch ראשי

דיווח כיסוי

העלאת כיסוי לשירותים חיצוניים:

- name: Upload coverage to Codecov
  uses: codecov/codecov-action@v3
  with:
    files: ./coverage/clover.xml
    fail_ci_if_error: true

התייחסות מהירה

משימה פקודה
הרצת כל בדיקות PHP composer test
הרצת בדיקות יחידה PHP composer test:unit
הרצת בדיקות אינטגרציה PHP composer test:integration
הרצת בדיקות E2E של PHP composer test:e2e
דוח כיסוי PHP composer test:coverage
הרצת כל בדיקות JS npm run test
מצב watch של JS npm run test:watch
כיסוי JS npm run test:coverage
בדיקת TypeScript npm run typecheck
ESLint npm run lint
PHPCS npm run phpcs
תיקון בעיות PHPCS npm run phpcs:fix

פתרון בעיות

בעיות נפוצות

Bootstrap של PHPUnit נכשל:
– ודאו ש-composer install הושלם בהצלחה
– ודאו שקובץ .env קיים (הועתק מ-.env.example)

שגיאות פתרון מודולים ב-Jest:
– הריצו npm ci להתקנה נקייה של תלויות
– ודאו שכינויי נתיבים ב-jest.config.js תואמים ל-tsconfig.json

כיסוי מתחת לסף:
– הוסיפו בדיקות לענפים לא מכוסים
– עיינו ב-collectCoverageFrom בתצורת Jest להחרגות

Mock לא מתאפס בין בדיקות:
– קראו ל-MockWooCommerce::reset() ב-setUp()
– ודאו שנקראים קודם ל-setUp() של ההורה