> For the complete documentation index, see [llms.txt](https://vladimirkostikov.gitbook.io/laraboom/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://vladimirkostikov.gitbook.io/laraboom/quality/15-testing-demos.md).

# 15. Tests and demos

## Which tests live where

| Directory           | How to run      | What they cover                                                                            |
| ------------------- | --------------- | ------------------------------------------------------------------------------------------ |
| `packages/laraboom` | `composer test` | the core. CRUD, gates, schema, idempotent, OpenAPI, seeds, unit attributes/helpers         |
| `apps`              | `composer test` | Host::boot, Demo discovery, the Blade home page, `/api/demos`, login/notify, the path ping |
| `demos/shop`        | `composer test` | the host skeleton plus home                                                                |
| `demos/blog`        | `composer test` | the host skeleton plus home                                                                |

The package uses Orchestra Testbench and SQLite `:memory:`. The hosts use `Host::boot` and `RefreshDatabase`, also often SQLite in phpunit.xml.

## How to write a host test

The reference is `apps/tests`. The pattern:

1. The TestCase boots the host through the LaraBoom Host
2. RefreshDatabase / sync the schema for the test
3. HTTP through `$this->get('/')` and `$this->getJson('/api/demos')`
4. Assert on the status, a JSON fragment, a redirect, the session

Do not test package internals in apps if they are already covered in `packages/laraboom`. In apps check the host wiring.

## What DemoTest actually covers

The `apps/tests/Feature/DemoTest.php` file is a living reference for the expectations:

```php
public function test_demo_resource_discovered(): void
{
    $resources = $this->app->make(ResourceRegistry::class);
    $this->assertTrue($resources->has('demos'));
    $this->assertSame('LaraBoom Demo', Share::get('demo_name'));
}

public function test_home_renders_seeds(): void
{
    $this->seedDemos();
    $this->get('/')
        ->assertOk()
        ->assertSee('LaraBoom')
        ->assertSee('Ada Lovelace');
}

public function test_boom_crud_and_filters(): void
{
    $this->seedDemos();
    $this->getJson('/api/demos?status=active&sort=-price')
        ->assertOk()
        ->assertJsonPath('data.0.name', 'Grace Hopper');

    $this->postJson('/api/demos', [/* fields */])
        ->assertCreated()
        ->assertJsonPath('price_amount', '99.00');
}

public function test_login_and_notify_pipeline(): void
{
    Mail::fake();
    Notification::fake();
    $this->seedDemos();
    $this->post('/login', [
        'email' => 'ada@demo.boom',
        'password' => 'password',
    ])->assertRedirect('/account');
    $this->post('/action/notify')->assertRedirect('/account');
    Mail::assertSent(MailRunner::class);
    Notification::assertSentTo(/* Ada */, NoticeRunner::class);
}
```

Seeds in a test are often created through the Resource `resolvedSeeds()` rather than necessarily through the CLI `boom seed`. That way the test does not depend on the state of the artisan chain beyond the TestCase.

## Recommended cases for your own Resource

* discovery. Registry `has('products')`
* index filter/sort
* store 201 plus the present shape (money/upload)
* update forbidden for guest if Allow requires auth
* destroy plus soft delete (the row disappears from query)
* Path home 200
* one side effect scenario with `Mail::fake` / `Notification::fake` / `Bus::fake`

## Demo hosts

### apps. The full tour

The canon for documentation and learning:

* `app/Resources/Demo.php` almost all attributes and fields
* `app/Routes/Demo.php` auth forms, notify, ping
* `app/App.php` through, share, Every, Run
* `web/views/demo/*` Blade

Study this host before copying patterns into a product.

### demos/shop and demos/blog

Minimal hosts:

* one Resource (`Product` / `Post`) with `#[Migrate]` and seeds
* one Path with `GET /`
* `share` with `demo_name`

They exist to check the path repo and the Docker `APP_TARGET`. Not as an encyclopedia of attributes.

Switching:

```env
APP_TARGET=demos/shop
```

```bash
docker compose up -d
docker compose exec php composer setup
```

## A practical learning route

1. Bring up `apps` following the [installation](/laraboom/getting-started/02-installation.md)
2. Open `/` and log in with the seeded user
3. Play with the `/api/demos` filters
4. Read the three Demo files (Resource, Routes, App) alongside chapters 4-12
5. Make your own Resource plus Path in a separate branch
6. `php boom sync`, `explain`, `openapi`, a test
7. Run `composer test` in the package and in apps

## Antipatterns

* Copying Laravel scaffolding (`php artisan make:controller`) into a LaraBoom host
* Duplicating CRUD in a Path when `/api` is enough
* Changing the schema with an SQL client alone without `fields()`
* Putting jobs in `app/Jobs` out of habit
* Writing documentation only in en and forgetting to update `docs/ru` (while ru is the source of truth)

## What is next in the docs

The Russian version of chapters 1-15 covers the author surface. The next steps for the documentation repository:

1. A translation into `docs/en/` chapter by chapter
2. Connecting a GitBook Space to `docs` (see `docs/.gitbook.yaml`)
3. As the package grows, targeted additions (Sanctum tokens, file disks, multi account) without bloating the introduction

If you find a mismatch between the docs and the code, fix the docs to match the Demo and package code. The code is the truth.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://vladimirkostikov.gitbook.io/laraboom/quality/15-testing-demos.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
