improve hook & testing docs (fix #38)

This commit is contained in:
Samuel Štancl 2019-11-10 15:00:23 +01:00
parent 90545f715e
commit 34a6b2cadd
2 changed files with 162 additions and 33 deletions

View file

@ -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
@ -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
{
@ -35,7 +76,9 @@ 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
{
@ -43,8 +86,7 @@ protected function setUp(): void
$this->artisan('migrate:fresh');
tenancy()->create('test.localhost');
tenancy()->init('test.localhost');
// ...
}
```
@ -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`.

View file

@ -7,7 +7,62 @@ 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.
All hook callbacks receive the `TenantManager` as the first argument.
## Tenant events
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',
]);
});
```
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
TenantManager $tenantManager, Tenant $tenant
```
## Database events
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 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`
@ -15,23 +70,7 @@ The following events are available:
- `ending`
- `ended`
### Tenant-specific database connection example {#tenant-specific-database-connection-example}
> Note: Tenant-specific DB connections can now be achieved using a first-class feature: [Custom DB connections]({{ $page->link('custom-db-connections') }})
You can hook into these events using `Tenancy::hook(<eventName>, function () {})`:
```php
\Tenancy::hook('bootstrapping', function ($tenantManager) {
if ($tenantManager->tenant['id'] === 'someID') {
config(['database.connections.someDatabaseConnection' => $tenantManager->tenant['databaseConnection']]);
$tenantManager->database->useConnection('someDatabaseConnection');
return ['database'];
}
});
```
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.
You may use the `bootstrapping` & `ending` events to prevent some bootstrappers from being executed.
The following actions can be prevented:
- database connection switch: `database`
@ -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
```