Skip to content

Commit

Permalink
improve hook & testing docs (fix stancl#38)
Browse files Browse the repository at this point in the history
  • Loading branch information
stancl committed Nov 10, 2019
1 parent 90545f7 commit 34a6b2c
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 31 deletions.
110 changes: 102 additions & 8 deletions docs/source/v2/application-testing.blade.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ section: content

# Application Testing {#application-testing}

> Note: You cannot use `:memory:` SQLite databases or the `RefreshDatabase` trait due to the switching of default database.
> Note: At the moment it's not possible to use `:memory:` SQLite databases or the `RefreshDatabase` trait due to the switching of default database. This will hopefully change in the future.
To test your application with this package installed, you can create tenants in the `setUp()` method of your test case:
### Initializing tenancy

You can create tenants in the `setUp()` method of your test case:

```php
protected function setUp(): void
Expand All @@ -21,7 +23,46 @@ protected function setUp(): void
}
```

And to delete tenants & their databases after tests:
If you don't want to initialize tenancy before each test, you may want to do something like this:
```php
class TestCase // extends ...
{
protected $tenancy = false;

public function setUp(): void
{
if ($this->tenancy) {
$this->initializeTenancy();
}
}

public function initializeTenancy($domain = 'test.localhost')
{
tenancy()->create($domain);
tenancy()->init($domain);
}

// ...
}
```

And in your individual test classes:
```php
class FooTest
{
protected $tenancy = true;

/** @test */
public function some_test()
{
$this->assertTrue(...);
}
}
```

### Cleanup

To delete tenants & their databases after tests, you may use this:
```php
public function tearDown(): void
{
Expand All @@ -35,16 +76,17 @@ public function tearDown(): void
}
```

If you're using the database storage driver, you will also need to run the migrations:
### Storage setup

If you're using the database storage driver, you will need to run the migrations in `setUp()`:
```php
protected function setUp(): void
{
parent::setUp();

$this->artisan('migrate:fresh');

tenancy()->create('test.localhost');
tenancy()->init('test.localhost');
// ...
}
```

Expand All @@ -58,7 +100,59 @@ protected function setUp(): void
// make sure you're using a different connection for testing to avoid losing data
Redis::connection('tenancyTesting')->flushdb();

tenant()->create('test.localhost');
tenancy()->init('test.localhost');
// ...
}
```

### Sample TestCase

Put together, here's a ready-to-use base TestCase for the DB storage driver
```php
<?php

namespace Tests;

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;

abstract class TestCase extends BaseTestCase
{
use CreatesApplication;

public function setUp(): void
{
parent::setUp();

$this->artisan('migrate:fresh');

config([
'tenancy.queue_database_creation' => false,
]);

config(['tenancy.exempt_domains' => [
'127.0.0.1',
'localhost',
]]);
}

public function tearDown(): void
{
config([
'tenancy.queue_database_deletion' => false,
'tenancy.delete_database_after_tenant_deletion' => true,
]);
tenancy()->all()->each->delete();

parent::tearDown();
}
}
```

phpunit.xml:
```xml
<server name="DB_DRIVER" value="sqlite"/>
<server name="DB_DATABASE" value="database/testing.sqlite"/>
```

> Don't forget to create an empty database/testing.sqlite
You may also wish toa dd `testing.sqlite` to `database/.gitignore`.
81 changes: 58 additions & 23 deletions docs/source/v2/hooks.blade.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,70 @@ section: content

# Hooks / The Event System

You can use event hooks to change the behavior of the tenancy bootstrapping and tenancy ending processes.
You can use event hooks to change the behavior of the package.

The following events are available:
- `bootstrapping`
- `bootstrapped`
- `ending`
- `ended`
All hook callbacks receive the `TenantManager` as the first argument.

### Tenant-specific database connection example {#tenant-specific-database-connection-example}
## Tenant events

> Note: Tenant-specific DB connections can now be achieved using a first-class feature: [Custom DB connections]({{ $page->link('custom-db-connections') }})
A common use case for these events is seeding the tenant data during creation:
```php
// AppServiceProvider::boot()
tenancy()->hook('tenant.creating', function (TenantManager $tm, Tenant $tenant) {
$tenant->put([
'posts_per_page' => '15',
]);
});
```

You can hook into these events using `Tenancy::hook(<eventName>, function () {})`:
The following events are available:
- `tenant.creating`
- `tenant.created`
- `tenant.updating`
- `tenant.updated`
- `tenant.deleting`
- `tenant.deleted`
- `tenant.softDeleting`
- `tenant.softDeleted`

Callbacks for these events may accept the following arguments:
```php
\Tenancy::hook('bootstrapping', function ($tenantManager) {
if ($tenantManager->tenant['id'] === 'someID') {
config(['database.connections.someDatabaseConnection' => $tenantManager->tenant['databaseConnection']]);
$tenantManager->database->useConnection('someDatabaseConnection');
TenantManager $tenantManager, Tenant $tenant
```

## Database events

return ['database'];
}
A use case for these events is executing something after the tenant database is created (& migrated/seeded) without running into race conditions.

Say you have a `AfterCreatingTenant` job that creates a superadmin user. You may use the `database.creating` event to add this job into the queue chain of the job that creates the tenant's database.
```php
tenancy()->hook('database.creating', function (TenantManager $tm, string $db, Tenant $tenant) {
return [
new AfterCreatingTenant($tenant->id);
]
});
```

The example above checks whether the current tenant has an id of `someID`. If yes, it creates a new database connection based on data stored in the tenant's storage. Then it changes the default database connection. Finally, it returns an array of the events that this callback prevents.
The following events are available:
- `database.creating`
- `database.created`
- `database.deleting`
- `database.deleted`

Callbacks for these events may accept the following arguments:
```php
TenantManager $tenantManager, string $db, Tenant $tenant
```

## Bootstrapping/ending events

The following events are available:
- `bootstrapping`
- `bootstrapped`
- `ending`
- `ended`

You may use the `bootstrapping` & `ending` events to prevent some bootstrappers from being executed.

The following actions can be prevented:
- database connection switch: `database`
Expand All @@ -41,11 +80,7 @@ The following actions can be prevented:
- Queue tenancy: `queue`
- and anything else listed in the [`tenancy.bootstrappers` config]({{ $page->link('configuration#bootstrappers') }})

### Tenant-specific configuration example {#tenant-specific-configuration-example}

Another common use case for events is tenant-specific config:
Callbacks for these events may accept the following arguments:
```php
\Tenancy::hook('bootstrapped', function ($tenantManager) {
config(['some.api.key' => $tenantManager->tenant['api_key']);
});
```
TenantManager $tenantManager, Tenant $tenant
```

0 comments on commit 34a6b2c

Please sign in to comment.