This guide covers development setup, testing, code standards, and contribution guidelines for the Hellotext WordPress plugin.
- Prerequisites
- Development Setup
- Project Structure
- Code Standards
- Testing
- Debugging
- Build & Release
- Contributing
- PHP: 8.2.12 or higher
- Composer: Latest version
- WordPress: 5.0 or higher
- WooCommerce: 5.0 or higher
- Local Development Environment:
- Local by Flywheel
- MAMP/XAMPP
- Docker (wp-env)
- Or similar
cd wp-content/plugins/
git clone https://github.com/hellotext/hellotext-wordpress.git
cd hellotext-wordpresscomposer installThis installs:
- Pest (testing framework)
- Mockery (mocking library)
- WordPress & WooCommerce stubs (for IDE autocomplete)
Create or modify your WordPress configuration to set environment variables.
Option A: wp-config.php
// Add before "That's all, stop editing!"
$_ENV['APP_ENV'] = 'development';
$_ENV['HELLOTEXT_API_URL'] = 'https://api-dev.hellotext.com';Option B: .htaccess
SetEnv APP_ENV development
SetEnv HELLOTEXT_API_URL https://api-dev.hellotext.comOption C: Server Configuration
For Local by Flywheel, add to site configuration or use .env file if supported.
- Navigate to WordPress admin → Plugins
- Activate "Hellotext"
- Configure with development Business ID and Access Token
In wp-config.php:
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);This logs errors to wp-content/debug.log.
- PHP Version: 8.2+
- Namespace:
Hellotext\ - Coding Style: WordPress Coding Standards with modern PHP
All methods must have type hints for parameters and return types:
public function process(?int $user_id, array $data = []): void
{
// Implementation
}All classes and public methods must have PHPDoc comments:
/**
* Create a Hellotext profile.
*
* @param int $user_id WordPress user ID.
* @param array $data Additional profile data.
* @return array Profile response from API.
* @throws \Exception If user not found.
*/
public function create(int $user_id, array $data = []): array
{
// Implementation
}Always use constants from the Constants class instead of magic strings:
// ✅ Good
$session = $_COOKIE[Constants::SESSION_COOKIE_NAME];
$response = Client::post(Constants::API_ENDPOINT_PROFILES, $data);
// ❌ Bad
$session = $_COOKIE['hello_session'];
$response = Client::post('/profiles', $data);Use exceptions for error conditions and log appropriately:
try {
$adapter = new ProductAdapter($product_id);
$payload = $adapter->get();
} catch (\Exception $e) {
error_log('Hellotext: ' . $e->getMessage());
return;
}The project uses Pest for testing.
# Run all tests
./vendor/bin/pest
# Run specific test file
./vendor/bin/pest tests/Unit/Adapters/ProductAdapterTest.php
# Run with coverage (requires Xdebug)
./vendor/bin/pest --coverage
# Run in parallel
./vendor/bin/paratestThe Composer aliases used by CI and maintainers are:
composer install
composer test
composer format:check
composer buildcomposer build installs production dependencies with --no-dev --optimize-autoloader. Do not use the build output for local development without reinstalling dev dependencies afterward.
Last verified: 2026-06-11
| Command | Result | Notes |
|---|---|---|
composer install |
Passed | Requires PHP 8.2+ and Composer 2. The local system Composer emitted PHP deprecation notices under PHP 8.4; dependencies still installed correctly. |
composer test |
Passed | Pest suite runs against WordPress/WooCommerce mocks, not a real WordPress install. |
composer format:check |
Passed | PHP CS Fixer warned when run under PHP 8.4 because the Composer platform is PHP 8.2.12. CI runs the style check on PHP 8.2. |
composer build |
Passed | Runs composer install --no-dev --optimize-autoloader and removes dev tooling from vendor/. Run composer install again afterward before continuing local development. |
Setup assumptions:
- PHP 8.2 or newer is available locally.
- Composer can install from the checked-in
composer.lock. - Tests do not require a real WordPress, WooCommerce, database, or Hellotext API connection.
- Outbound HTTP in tests is mocked through WordPress HTTP function stubs.
Unit tests are located in tests/Unit/. Each test file corresponds to a source file.
Example: Testing an Adapter
<?php
use Hellotext\Adapters\ProductAdapter;
beforeEach(function () {
$this->product = Mockery::mock('WC_Product');
$this->product->shouldReceive('get_id')->andReturn(123);
$this->product->shouldReceive('get_name')->andReturn('Test Product');
// ... more mocks
});
test('ProductAdapter transforms product correctly', function () {
$adapter = new ProductAdapter($this->product);
$result = $adapter->get();
expect($result)
->toHaveKey('reference', 123)
->toHaveKey('name', 'Test Product')
->toHaveKey('source', 'woo');
});
test('ProductAdapter throws exception for invalid product', function () {
$adapter = new ProductAdapter(99999);
$adapter->get(); // Should throw
})->throws(\Exception::class);Use Pest's modern syntax:
// Arrange
$data = ['key' => 'value'];
// Act
$result = (new Service())->process($data);
// Assert
expect($result)->toBe('expected');Use Mockery for mocking WordPress and WooCommerce functions:
beforeEach(function () {
// Mock WordPress functions
Mockery::mock('function:get_option')
->shouldReceive('get_option')
->with('hellotext_business_id')
->andReturn('test_business_id');
});
afterEach(function () {
Mockery::close();
});- Unit Tests: All Adapters and Services
- Integration Tests: Key user flows (order placement, profile creation)
- Coverage Target: 80%+ for critical paths
Enable WordPress debug logging and use error_log():
error_log('Hellotext Debug: ' . print_r($data, true));Logs appear in wp-content/debug.log.
To inspect API requests/responses:
$response = Client::post('/profiles', $data);
error_log('API Response: ' . print_r($response, true));To verify events are being tracked:
add_filter('hellotext_event_payload', function($payload) {
error_log('Event Payload: ' . print_r($payload, true));
return $payload;
});Use add_action() to monitor hook execution:
add_action('all', function($hook) {
if (strpos($hook, 'woocommerce') !== false) {
error_log('Hook fired: ' . $hook);
}
});- Update version in
hellotext.phpheader comment - Update
changelog.txtwith changes - Commit changes
/**
* Version: 1.3.0
*/- Confirm the version in
hellotext.phpmatches the release tag. - Update
changelog.txtwith user-facing changes, compatibility notes, and any known limitations. - Review open dependency PRs and confirm there are no urgent security/runtime updates pending.
- Run
composer installfrom a clean checkout. - Run
composer testand confirm all tests pass. - Run
composer format:checkand confirm no style diff is reported. - Run
composer buildand confirm production dependencies install with--no-dev --optimize-autoloader. - Inspect the production
vendor/tree enough to confirm dev-only packages such as Pest, Mockery, stubs, PHPUnit, and PHP CS Fixer are not included in the release build. - Verify
.distignoreexcludes development files from the release zip:.github/,tests/,composer.json,composer.lock,DEVELOPMENT.md, andAPI.md. - Smoke test the plugin zip in a clean WordPress/WooCommerce site.
- Confirm settings save correctly: Business ID, access token, webchat ID, placement, and behavior.
- Confirm script/webchat injection renders on the storefront when configured.
- Smoke test tracking for product view, cart add/remove, coupon redemption, checkout/order placement, order status change, refund, user registration, plugin activation, and plugin deactivation.
- Smoke test classic template pages and WooCommerce Cart/Checkout blocks separately for product, cart, and checkout coverage.
- Smoke test order placement, order status, and refund flows with WooCommerce HPOS enabled and disabled.
- Record WooCommerce API/HPOS compatibility notes in the release description if anything changed.
- Run
composer installagain after build validation to restore dev dependencies before more local work.
- Tag the release:
git tag -a v1.3.0 -m "Release version 1.3.0"
git push origin v1.3.0- Build release package:
# Remove dev dependencies
composer install --no-dev
3. **Verify the generated release:**
- Download the release zip from GitHub.
- Confirm files excluded by `.distignore` are not included: `.github/`, `tests/`, `composer.json`, `composer.lock`, `DEVELOPMENT.md`, and `API.md`.
- Confirm runtime files are included: `hellotext.php`, `src/`, `vendor/`, `README.md`, and `changelog.txt` if present.
- Install the zip in a clean WordPress/WooCommerce site.
- Confirm the release asset installs and activates without PHP warnings in `debug.log`.
### Post-Release
1. Reinstall dev dependencies: `composer install`
2. Announce release to team
3. Monitor error logs for issues
### Dependency Update Triage
Use this checklist before merging dependency-only PRs:
- Confirm the diff is limited to dependency metadata or the expected workflow file.
- Confirm GitHub reports the PR as mergeable.
- Confirm required CI checks pass.
- Prefer merging patch/minor test stub updates independently from runtime code changes.
- For GitHub Action major updates, inspect the action release notes before merging.
Dependency PRs reviewed during this maintenance pass:
- Keep dependency-only lockfile refreshes separate from runtime compatibility changes.
- Prefer one broad lock refresh over multiple older overlapping Dependabot PRs when it carries newer compatible versions and CI passes.
- For GitHub Action major updates, inspect the action release notes and verify the generated zip on the next tagged release because release publishing only runs on tags.
See also [WooCommerce Compatibility and API Audit](docs/WOOCOMMERCE-AUDIT.md) for hook, HPOS, and release compatibility notes.
## Contributing
### Workflow
1. **Fork & Clone**
```bash
git clone https://github.com/YOUR_USERNAME/hellotext-wordpress.git
cd hellotext-wordpress
composer install- Create Feature Branch
git checkout -b feature/my-new-feature-
Make Changes
- Write code
- Add tests
- Update documentation
-
Run Tests
./vendor/bin/pest- Commit
git add .
git commit -m "feat: add new feature"Use Conventional Commits:
feat:- New featurefix:- Bug fixdocs:- Documentationtest:- Testsrefactor:- Code refactoring
- Push & PR
git push origin feature/my-new-featureThen create a Pull Request on GitHub.
- Code follows WordPress coding standards
- All functions have type hints
- PHPDoc comments present and accurate
- Tests written and passing
- No hardcoded strings (use Constants)
- Proper error handling
- WordPress/WooCommerce hooks used correctly
- Security best practices followed
- Create event file in
src/Events/ - Hook into appropriate WooCommerce action
- Use
Eventclass to track - Add event constant to
Constants.php - Write test in
tests/Unit/Events/
Example:
<?php
use Hellotext\Api\Event;
use Hellotext\Constants;
add_action('woocommerce_new_action', 'hellotext_track_new_action');
function hellotext_track_new_action($data): void {
$event = new Event();
$event->track(Constants::EVENT_NEW_ACTION, [
'object_parameters' => $data
]);
}- Create adapter file in
src/Adapters/ - Implement
get(): arraymethod - Write comprehensive test
- Document in API.md
- Add constant to
Constants.php - Add field to
Settings.phpadmin page - Use
get_option(Constants::OPTION_NAME)to retrieve
Issue: Mockery errors or WordPress function not found
Solution: Ensure WordPress and WooCommerce stubs are installed:
composer require --dev php-stubs/wordpress-stubs php-stubs/woocommerce-stubsIssue: hello_session cookie not being created
Solution: Check that session_start() is called early in plugin load and cookie settings (domain, path) are correct.
Issue: 401 Unauthorized errors
Solution: Verify Business ID and Access Token are set correctly in WordPress admin → Extensions → Hellotext.
- WordPress Plugin Handbook
- WooCommerce Developer Documentation
- Pest Documentation
- Hellotext API Documentation
GPL v2 - See LICENSE file.
- Issues: GitHub Issues
- Email: support@hellotext.com
- Documentation: API.md