Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Arthurr23/XHealtXperience/llms.txt

Use this file to discover all available pages before exploring further.

XHealtXperience ships with a PHPUnit 11 test suite targeting the central authentication, user-profile flows, and basic application health. Tests run against an in-memory SQLite database so they are fast, hermetic, and require no changes to your local .env file. This page explains the configuration, describes every test class, and shows you how to run the suite.

Test configuration (phpunit.xml)

The phpunit.xml at the project root configures two test suites and a set of environment overrides that isolate the test run from your local services:
<testsuites>
  <testsuite name="Unit">
    <directory>tests/Unit</directory>
  </testsuite>
  <testsuite name="Feature">
    <directory>tests/Feature</directory>
  </testsuite>
</testsuites>

Environment overrides

VariableTest valueWhy
APP_ENVtestingActivates Laravel’s testing mode.
DB_CONNECTIONsqliteUses SQLite instead of your local DB.
DB_DATABASE:memory:Every test run starts with a blank in-memory database — no file cleanup needed.
CACHE_STOREarrayIn-process array cache; no Redis/database needed.
QUEUE_CONNECTIONsyncJobs run synchronously in the same process — no queue worker required.
SESSION_DRIVERarrayIn-process session store; no database write required.
MAIL_MAILERarrayOutgoing mail is captured in memory for assertion, never sent.
BCRYPT_ROUNDS4Minimum bcrypt cost — makes User::factory() calls dramatically faster.
BROADCAST_CONNECTIONnullDisables broadcasting.

Running the test suite

1
Clear the configuration cache
2
Stale cached config can cause unexpected failures in the testing environment. The composer run test script does this automatically, but you can also do it manually:
3
php artisan config:clear
4
Run all tests
5
The recommended way to execute the full suite:
6
composer run test
7
Internally this runs:
8
php artisan config:clear --ansi
php artisan test
9
Alternatively, invoke PHPUnit directly
10
./vendor/bin/phpunit
11
Review results
12
PHPUnit outputs a colour-coded summary. A passing run looks like:
13
PASS  Tests\Unit\ExampleTest
PASS  Tests\Feature\ExampleTest
PASS  Tests\Feature\Auth\AuthenticationTest
PASS  Tests\Feature\Auth\EmailVerificationTest
PASS  Tests\Feature\Auth\PasswordConfirmationTest
PASS  Tests\Feature\Auth\PasswordResetTest
PASS  Tests\Feature\Auth\PasswordUpdateTest
PASS  Tests\Feature\Auth\RegistrationTest
PASS  Tests\Feature\ProfileTest
Use the --filter flag to run a single test method or class without executing the entire suite:
# Run one test class
php artisan test --filter=AuthenticationTest

# Run a single test method
php artisan test --filter=test_users_can_authenticate_using_the_login_screen

# Run only the Feature suite
php artisan test --testsuite=Feature

Test inventory

Unit tests — tests/Unit/

FileTests
ExampleTest.phpSanity check — asserts that true === true. Serves as a placeholder for future unit tests.

Feature tests — tests/Feature/

All feature tests that use the RefreshDatabase trait wrap each test in a transaction (or re-migrate the in-memory SQLite DB) so tests never bleed state into one another.

ExampleTest.php

Basic application health check.
Test methodWhat it asserts
test_the_application_returns_a_successful_responseGET / returns HTTP 200, confirming the application boots and routes correctly.

Auth/AuthenticationTest.php

Tests the central login and logout flow.
Test methodWhat it asserts
test_login_screen_can_be_renderedGET /login returns HTTP 200.
test_users_can_authenticate_using_the_login_screenPOST /login with valid credentials authenticates the user and redirects to dashboard.
test_users_can_not_authenticate_with_invalid_passwordPOST /login with a wrong password leaves the user as a guest.
test_users_can_logoutPOST /logout while authenticated de-authenticates and redirects to /.

Auth/RegistrationTest.php

Tests the central user registration screen.
Test methodWhat it asserts
test_registration_screen_can_be_renderedGET /register returns HTTP 200.
test_new_users_can_registerPOST /register with valid data authenticates the new user and redirects to dashboard.

Auth/PasswordResetTest.php

Tests the full password-reset flow using Notification::fake().
Test methodWhat it asserts
test_reset_password_link_screen_can_be_renderedGET /forgot-password returns HTTP 200.
test_reset_password_link_can_be_requestedPOST /forgot-password dispatches a ResetPassword notification to the user.
test_reset_password_screen_can_be_renderedGET /reset-password/{token} (from the notification) returns HTTP 200.
test_password_can_be_reset_with_valid_tokenPOST /reset-password with a valid token sets the new password and redirects to /login.

Auth/PasswordUpdateTest.php

Tests updating a user’s own password from the profile page.
Test methodWhat it asserts
test_password_can_be_updatedPUT /password with the correct current password updates the hash and redirects to /profile.
test_correct_password_must_be_provided_to_update_passwordPUT /password with a wrong current password returns a current_password validation error.

Auth/PasswordConfirmationTest.php

Tests the password-confirmation gate used before sensitive actions.
Test methodWhat it asserts
test_confirm_password_screen_can_be_renderedGET /confirm-password returns HTTP 200 for an authenticated user.
test_password_can_be_confirmedPOST /confirm-password with the correct password redirects without session errors.
test_password_is_not_confirmed_with_invalid_passwordPOST /confirm-password with a wrong password returns session errors.

Auth/EmailVerificationTest.php

Tests the email-verification flow using Event::fake() and temporary signed URLs.
Test methodWhat it asserts
test_email_verification_screen_can_be_renderedGET /verify-email returns HTTP 200 for an unverified user.
test_email_can_be_verifiedNavigating to a valid signed verification URL dispatches the Verified event and marks the user’s email as verified; redirects to dashboard?verified=1.
test_email_is_not_verified_with_invalid_hashA signed URL with a wrong hash does not verify the email.

ProfileTest.php

Tests profile viewing, updating, and account deletion.
Test methodWhat it asserts
test_profile_page_is_displayedGET /profile returns HTTP 200 for an authenticated user.
test_profile_information_can_be_updatedPATCH /profile updates name and email, clears email_verified_at.
test_email_verification_status_is_unchanged_when_the_email_address_is_unchangedPATCH /profile with the same email does not clear email_verified_at.
test_user_can_delete_their_accountDELETE /profile with the correct password deletes the user and logs them out.
test_correct_password_must_be_provided_to_delete_accountDELETE /profile with the wrong password returns a password error and does not delete the user.

Continuous integration

The repository uses GitHub Actions with a single workflow defined in .github/workflows/deploy.yml. On every push to the main branch, the workflow SSH-deploys to the production Hetzner server — it does not currently run the PHPUnit suite in CI. The deploy script executes:
git pull origin main
composer install --optimize-autoloader --no-dev
npm install && npm run build
php artisan migrate --force
php artisan config:cache
php artisan route:cache
sudo systemctl restart php8.5-fpm
sudo supervisorctl restart xhealthxperience-worker:xhealthxperience-worker_00
If you want to add a CI test step before deployment, insert composer run test as a job step in deploy.yml before the SSH deploy action. This requires a test database to be available in the runner environment — the in-memory SQLite configuration in phpunit.xml makes this straightforward without any additional service containers.

Writing new tests

Follow these conventions when adding tests:
  1. Feature tests go in tests/Feature/ (or a subdirectory). Extend Tests\TestCase and use RefreshDatabase.
  2. Unit tests go in tests/Unit/. They extend PHPUnit\Framework\TestCase directly and should have no database or HTTP dependencies.
  3. The app/ directory is the only code coverage source configured in phpunit.xml — keep non-app code out of coverage reports.
  4. Use Notification::fake(), Mail::fake(), and Event::fake() to test side-effects without real infrastructure, exactly as the existing auth tests do.
<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class MyNewTest extends TestCase
{
    use RefreshDatabase;

    public function test_something_works(): void
    {
        // Arrange, Act, Assert
        $this->assertTrue(true);
    }
}

Build docs developers (and LLMs) love