# Testing Guide

## Overview

The plugin uses three quality tools:

| Tool | Purpose | Config File |
|---|---|---|
| PHPUnit | Unit testing | `composer.json` (phpunit dependency) |
| PHP CodeSniffer (PHPCS) | Coding standards + security linting | `phpcs.xml.dist` |
| PHPStan | Static type analysis | `phpstan.neon` |

---

## PHPUnit

### Setup

PHPUnit is installed as a dev dependency:

```bash
composer install
```

Test stubs are located at `tests/php/stubs/aiosrs-stubs.php`. These stubs allow PHPUnit/PHPStan to understand plugin-specific function signatures without requiring a full WordPress install.

### Regenerating Stubs

```bash
composer gen-stubs
```

This runs `generate-stubs` on the plugin files, outputs to `artifact/phpstan/`, then moves stubs to `tests/php/stubs/aiosrs-stubs.php`.

### Running Tests

```bash
vendor/bin/phpunit
```

The test directory is `tests/php/`. There are currently no additional test files beyond the stubs — the primary quality gate is PHPCS and PHPStan.

---

## PHP CodeSniffer (PHPCS)

### Configuration

Config file: `phpcs.xml.dist`

Standards enforced:
- `PHPCompatibility` — checks for PHP version incompatibilities
- `WordPress-Core` — core WordPress coding standards
- `WordPress-Docs` — documentation standards
- `WordPress-Extra` — additional WordPress best practices

### Running PHPCS

```bash
# Check for violations
composer lint
# or directly:
vendor/bin/phpcs --standard=phpcs.xml.dist

# Auto-fix fixable issues (PHPCBF)
composer format
# or directly:
vendor/bin/phpcbf --standard=phpcs.xml.dist
```

### Excluded Paths

PHPCS will not scan:
- `node_modules/`
- `vendor/`
- `tests/php/stubs/`
- `stubs-generator.php`
- `lib/`
- `admin/bsf-analytics/`

### PHPCS Exclusions

These WordPress-standard rules are excluded from the config:

| Rule | Reason |
|---|---|
| `WordPress.PHP.StrictComparisons.LooseComparison` | Legacy loose comparisons (`==`) used throughout |
| `WordPress.PHP.StrictInArray.MissingTrueStrict` | Legacy `in_array()` calls |
| `WordPress.Files.FileName.InvalidClassFileName` | Multiple classes in single files |
| `Generic.Files.OneClassPerFile.MultipleFound` | Multiple classes in single files |
| `WordPress.WP.GlobalVariablesOverride.Prohibited` | `$post` global used intentionally |
| `WordPress.WP.EnqueuedResourceParameters.NotInFooter` | Scripts enqueued in header |
| `Generic.Files.OneObjectStructurePerFile.MultipleFound` | Multiple structures per file |
| `WordPress.WP.I18n.MissingTranslatorsComment` | Translator comments not required |

### Security-Specific Forbidden Functions

The following PHP functions are flagged as errors by PHPCS (`Generic.PHP.ForbiddenFunctions`):

`eval`, `assert`, `create_function`, `preg_replace` (with /e modifier), `exec`, `shell_exec`, `system`, `passthru`, `popen`, `proc_open`, `phpinfo`, `extract`, `parse_str`, `fsockopen`, `pfsockopen`, and all POSIX system-exposure functions.

---

## PHPStan

### Configuration

Config file: `phpstan.neon`
Analysis level: **9** (maximum strictness)

Bootstrap files:
- `vendor/php-stubs/wordpress-stubs/wordpress-stubs.php`
- `tests/php/stubs/aiosrs-stubs.php`

Analysed paths:
- `index.php`
- `functions.php`
- `init.php`
- `meta-boxes.php`
- `settings.php`
- `languages/`
- `admin/`

### Running PHPStan

```bash
composer phpstan
# or directly:
vendor/bin/phpstan --memory-limit=2048M analyse
```

### Baseline

Known false positives are suppressed in `phpstan-baseline.neon`. When new intentional patterns arise that PHPStan cannot resolve (e.g. dynamic WordPress API calls), add them to the baseline rather than suppressing at the call site.

To update the baseline:

```bash
vendor/bin/phpstan --memory-limit=2048M analyse --generate-baseline phpstan-baseline.neon
```

### Suppressed Error Patterns

The following PHPStan error patterns are ignored via `phpstan.neon`:

- `Call to an undefined method ... ::add_control()`
- Dynamic method calls (Elementor compatibility)
- `Cannot access ...` / `Parameter ...` / `Offset ...`
- `Access to an undefined property`
- Strict comparison with `'no'` and `true`

---

## CI / Pre-commit Hooks

### Pre-commit Hook

Managed by `brainmaestro/composer-git-hooks`. Runs on every `git commit`:

1. Echoes committer name
2. Runs `bin/block-commits-with-merge-conflict.sh` — prevents committing files containing unresolved merge conflict markers (seven `<`, `=======`, seven `>`)

### Installing Hooks

```bash
# After composer install
vendor/bin/cghooks add --ignore-lock
```

---

## PHPCS Security Report

A full PHPCS security audit report is stored at `phpcs-report.xml`. This file is generated by running PHPCS with `pheromone/phpcs-security-audit` and can be reviewed for security-related warnings outside the standard WordPress ruleset.

---

## Recommended Testing Workflow

```bash
# 1. Fix code style
composer format

# 2. Check remaining style issues
composer lint

# 3. Run static analysis
composer phpstan

# 4. Run unit tests
vendor/bin/phpunit

# 5. Test in browser — validate output
# Visit: https://validator.schema.org/
```

---

## See Also

- [Environment Configuration](Environment-Configuration)
- [Contributing Guide](Contributing-Guide)
- [Troubleshooting FAQ](Troubleshooting-FAQ)
