# Unit Testing

This document explains how to set up and run the unit tests for the Bukazu Search Widget WordPress plugin.

## Framework

The test suite uses [PHPUnit](https://phpunit.de/) (v10) together with [Brain\Monkey](https://giuseppe-mazzapica.gitbook.io/brain-monkey/) to mock WordPress-specific functions, enabling the plugin code to be tested in isolation — **no WordPress installation or database is required**.

## Requirements

- PHP 8.1 or higher
- [Composer](https://getcomposer.org/) 2.x

## Setup

Install the development dependencies with Composer from the `trunk` directory:

```bash
cd trunk
composer install
```

This installs PHPUnit and Brain\Monkey into the `vendor/` directory.

## Running the Tests

From the `trunk` directory, run:

```bash
./vendor/bin/phpunit
```

Or use the Composer shortcut:

```bash
composer test
```

### Example output

```
PHPUnit 10.5.x by Sebastian Bergmann and contributors.

Runtime:       PHP 8.3.x
Configuration: phpunit.xml

.................                                                 17 / 17 (100%)

Time: 00:00.105, Memory: 12.00 MB

OK (17 tests)
```

## Test Structure

```
trunk/
├── composer.json          # Declares PHPUnit & Brain\Monkey as dev dependencies
├── phpunit.xml            # PHPUnit configuration (bootstrap, test directories)
└── tests/
    ├── bootstrap.php      # Loads Composer autoloader, WordPress stubs, and the plugin
    └── BukazuWidgetTest.php  # Test cases covering plugin functions and the widget class
```

### What is tested

| Test | Description |
|------|-------------|
| `testExemptShortcodeAddsTagToArray` | `bukazu_search_widget_shortcodes_to_exempt_from_wptexturize()` appends the `bukazu_search` tag |
| `testExemptShortcodeWorksOnEmptyArray` | Returns `['bukazu_search']` when given an empty array |
| `testIframeShortcodeDefaultAttributes` | Shortcode renders with default `language="en"` and empty codes when no atts passed |
| `testIframeShortcodeCustomAttributes` | Shortcode uses attributes passed to it |
| `testIframeShortcodeFiltersJsonContainsPersons` | Output contains a valid JSON `filters` attribute |
| `testIframeShortcodeWithGetDataAndValidNonce` | Form data is embedded in filters when nonce passes |
| `testIframeShortcodeIgnoresGetDataWithoutNonce` | Form data is discarded when nonce key is missing |
| `testWidgetUpdateSanitizesTitle` | `Bukazu_Search_Widget::update()` strips HTML tags from title |
| `testWidgetUpdateSanitizesSearchUrl` | `update()` strips HTML tags from search URL |
| `testWidgetUpdateDefaultsToEmptyStringForMissingKeys` | Missing keys default to empty string |
| `testWidgetUpdateAllowsValidLocale` | All supported locale codes are stored as-is |
| `testWidgetUpdateAllowsValidViewStyles` | All supported view-style values are stored as-is |
| `testWidgetOutputContainsFormWhenSearchUrlIsSet` | `widget()` renders a `<form>` when a search URL is configured |
| `testWidgetOutputOmitsFormWhenSearchUrlIsEmpty` | `widget()` renders no `<form>` when the search URL is empty |
| `testWidgetOutputContainsTitleWhenSet` | Widget title is wrapped in `before_title`/`after_title` markup |
| `testWidgetOutputContainsPersonsSelect` | Widget form contains a persons `<select>` element |

## Adding New Tests

1. Create a new `*Test.php` file in the `tests/` directory.
2. Extend `PHPUnit\Framework\TestCase`.
3. Call `Brain\Monkey\setUp()` / `Brain\Monkey\tearDown()` in your `setUp`/`tearDown` methods to reset mock state between tests.
4. Use the WordPress stub functions defined in `tests/bootstrap.php` — they mirror the real WordPress API signatures.

```php
<?php

declare(strict_types=1);

use Brain\Monkey;
use PHPUnit\Framework\TestCase;

class MyFeatureTest extends TestCase
{
    protected function setUp(): void
    {
        parent::setUp();
        Monkey\setUp();
    }

    protected function tearDown(): void
    {
        Monkey\tearDown();
        parent::tearDown();
    }

    public function testSomething(): void
    {
        // Your assertions here
        $this->assertTrue(true);
    }
}
```
