Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: Complete the test suite #68

Draft
wants to merge 22 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
66ee087
chore: Temporarily migrate tests
ollieread Nov 18, 2024
04548eb
merge: Merge branch 'main' into test/complete-tests
ollieread Nov 18, 2024
19c939f
test: Separate out test suites
ollieread Nov 18, 2024
fb6376c
refactor: Remove unused method
ollieread Nov 18, 2024
e44e723
fix: Correct naming of markOutsideContext method
ollieread Nov 18, 2024
9554346
test: Start separate unit tests
ollieread Nov 18, 2024
d50337a
chore: Don't pass null to ltrim
ollieread Nov 18, 2024
baea868
build(github): Separate out testsuites for workflow
ollieread Nov 18, 2024
294d12c
build(github): Remove unnecessary vendor:publish
ollieread Nov 18, 2024
297e7d0
build(github): Revert unit test command for workflow
ollieread Nov 18, 2024
c4a3a1b
chore: Fix paths for feature and unit testing
ollieread Nov 18, 2024
5595450
chore: Ensure tests/Feature directory exists
ollieread Nov 18, 2024
a00be22
chore: Reset resolver and hook when current tenant is nullified
ollieread Nov 19, 2024
994871e
chore: Do not generate code coverage for the generic tenant class
ollieread Nov 19, 2024
7d73645
test: Add unit tests for the resolution helper
ollieread Nov 19, 2024
f6eaf00
chore: Tidy up code to use helper functions
ollieread Nov 19, 2024
45d6c80
chore: Add RefreshDatabase trait to relevant tests
ollieread Nov 19, 2024
dc25c65
test: Add unit test for eloquent tenant provider
ollieread Nov 19, 2024
a21189a
test: Add unit test for the database tenant provider
ollieread Nov 19, 2024
6c118f2
chore: Remove unnecessary service override from AuthOverride
ollieread Nov 23, 2024
98854ef
refactor: Boot service override _AFTER_ the application has booted
ollieread Nov 23, 2024
346a6ee
fix: Correct return type for the AddTenantHeaderToResponse middleware
ollieread Nov 25, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ jobs:
- name: Prepare testbench
run: composer clear && composer prepare && composer build

- name: Publish required assets
run: vendor/bin/testbench vendor:publish --provider="Sprout\\SproutServiceProvider"

- name: Execute tests
run: composer test

Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
"@clear",
"@prepare",
"@build",
"@php vendor/bin/phpunit"
"@php vendor/bin/phpunit --testsuite=Unit,Feature"
]
},
"extra" : {
Expand Down
10 changes: 8 additions & 2 deletions phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,14 @@
testdox="true"
>
<testsuites>
<testsuite name="Tenanted Laravel Test Suite">
<directory>tests</directory>
<testsuite name="Original">
<directory>tests/_Original</directory>
</testsuite>
<testsuite name="Feature">
<directory>./tests/Feature</directory>
</testsuite>
<testsuite name="Unit">
<directory>./tests/Unit</directory>
</testsuite>
</testsuites>
<source>
Expand Down
2 changes: 1 addition & 1 deletion src/Concerns/OverridesCookieSettings.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public static function setDomain(?string $domain): void
*/
public static function setPath(?string $path): void
{
self::$settings['path'] = '/' . ltrim($path, '/');
self::$settings['path'] = $path ? '/' . ltrim($path, '/') : null;
}

// @codeCoverageIgnoreStart
Expand Down
10 changes: 5 additions & 5 deletions src/Http/Middleware/AddTenantHeaderToResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@

use Closure;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Sprout\Http\Resolvers\HeaderIdentityResolver;
use Sprout\Sprout;
use Sprout\Support\ResolutionHelper;
use Sprout\Support\ResolutionHook;
use Symfony\Component\HttpFoundation\Response;

/**
* Add Tenant Header to Response
Expand Down Expand Up @@ -43,9 +42,10 @@
* @param \Closure $next
* @param string ...$options
*
* @return \Illuminate\Http\Response
* @return \Symfony\Component\HttpFoundation\Response
*
* @throws \Sprout\Exceptions\NoTenantFound
* @throws \Illuminate\Contracts\Container\BindingResolutionException
* @throws \Sprout\Exceptions\MisconfigurationException
*/
public function handle(Request $request, Closure $next, string ...$options): Response
{
Expand All @@ -68,7 +68,7 @@
}

return $response->withHeaders([
$resolver->getRequestHeaderName($tenancy) => $tenancy->identifier()
$resolver->getRequestHeaderName($tenancy) => $tenancy->identifier(),

Check warning on line 71 in src/Http/Middleware/AddTenantHeaderToResponse.php

View check run for this annotation

Codecov / codecov/patch

src/Http/Middleware/AddTenantHeaderToResponse.php#L71

Added line #L71 was not covered by tests
]);
}
}
2 changes: 1 addition & 1 deletion src/Http/Middleware/TenantRoutes.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public function __construct(Sprout $sprout)
* @param \Closure $next
* @param string ...$options
*
* @return \Illuminate\Http\Response
* @return \Symfony\Component\HttpFoundation\Response
*
* @throws \Sprout\Exceptions\NoTenantFound
* @throws \Illuminate\Contracts\Container\BindingResolutionException
Expand Down
2 changes: 1 addition & 1 deletion src/Overrides/AuthOverride.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
*
* @package Overrides
*/
final class AuthOverride implements ServiceOverride, BootableServiceOverride, DeferrableServiceOverride
final class AuthOverride implements BootableServiceOverride, DeferrableServiceOverride
{
/**
* @var \Illuminate\Auth\AuthManager
Expand Down
14 changes: 1 addition & 13 deletions src/Sprout.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,18 +118,6 @@ public function getAllCurrentTenancies(): array
return $this->tenancies;
}

/**
* Should Sprout listen for the routing event
*
* @return bool
*
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
public function shouldListenForRouting(): bool
{
return (bool)$this->config('listen_for_routing', true);
}

/**
* Get the identity resolver manager
*
Expand Down Expand Up @@ -200,7 +188,7 @@ public function markAsInContext(): self
*
* @return static
*/
public function maskAsOutsideContext(): self
public function markAsOutsideContext(): self
{
$this->withinContext = false;

Expand Down
12 changes: 6 additions & 6 deletions src/SproutServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public function register(): void
$this->registerManagers();
$this->registerMiddleware();
$this->registerRouteMixin();
$this->registerServiceOverrideBooting();
}

private function registerSprout(): void
Expand Down Expand Up @@ -78,13 +79,17 @@ protected function registerRouteMixin(): void
Router::mixin(new RouterMethods());
}

protected function registerServiceOverrideBooting(): void
{
$this->app->booted($this->sprout->bootOverrides(...));
}

public function boot(): void
{
$this->publishConfig();
$this->registerServiceOverrides();
$this->registerEventListeners();
$this->registerTenancyBootstrappers();
$this->bootServiceOverrides();
}

private function publishConfig(): void
Expand Down Expand Up @@ -128,9 +133,4 @@ private function registerTenancyBootstrappers(): void
$events->listen(CurrentTenantChanged::class, $bootstrapper);
}
}

private function bootServiceOverrides(): void
{
$this->sprout->bootOverrides();
}
}
5 changes: 5 additions & 0 deletions src/Support/DefaultTenancy.php
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,11 @@ public function setTenant(?Tenant $tenant): static
event(new CurrentTenantChanged($this, $previousTenant, $tenant));
}

if ($tenant === null) {
$this->resolver = null;
$this->hook = null;
}

return $this;
}

Expand Down
2 changes: 2 additions & 0 deletions src/Support/GenericTenant.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
* as the tenant entity.
*
* @pacakge Core
*
* @codeCoverageIgnore
*/
class GenericTenant implements Tenant
{
Expand Down
Empty file added tests/Feature/.gitkeep
Empty file.
82 changes: 82 additions & 0 deletions tests/Unit/Attributes/CurrentTenantTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php
declare(strict_types=1);

namespace Sprout\Tests\Unit\Attributes;

use Illuminate\Config\Repository;
use Orchestra\Testbench\Attributes\DefineEnvironment;
use PHPUnit\Framework\Attributes\Test;
use Sprout\Attributes\CurrentTenant;
use Sprout\Support\GenericTenant;
use Sprout\Tests\Unit\UnitTestCase;
use Workbench\App\Models\TenantModel;
use function Sprout\sprout;
use function Sprout\tenancy;

class CurrentTenantTest extends UnitTestCase
{
protected function setsUpTenancy($app)
{
tap($app['config'], function ($config) {
$config->set('multitenancy.providers.tenants.model', TenantModel::class);
});
}

protected function setupSecondTenancy($app): void
{
tap($app['config'], static function (Repository $config) {
$config->set('multitenancy.providers.backup', [
'driver' => 'database',
'table' => 'tenants',
]);

$config->set('multitenancy.tenancies.backup', [
'provider' => 'backup',
]);
});
}

#[Test]
public function resolvesCurrentTenant(): void
{
/** @var \Sprout\Contracts\Tenancy $tenancy */
$tenancy = tenancy('tenants');

sprout()->setCurrentTenancy($tenancy);

$tenant = TenantModel::factory()->createOne();

$tenancy->setTenant($tenant);

$callback = static function (#[CurrentTenant] TenantModel $tenant) {
return $tenant;
};

$currentTenant = $this->app->call($callback);

$this->assertSame($tenant, $currentTenant);
$this->assertSame($tenancy->tenant(), $currentTenant);
}

#[Test, DefineEnvironment('setupSecondTenancy')]
public function resolvesCurrentTenantForSpecificTenancy(): void
{
/** @var \Sprout\Contracts\Tenancy $tenancy */
$tenancy = tenancy('backup');

sprout()->setCurrentTenancy($tenancy);

$tenant = new GenericTenant(TenantModel::factory()->createOne()->toArray());

$tenancy->setTenant($tenant);

$callback = static function (#[CurrentTenant('backup')] GenericTenant $tenant) {
return $tenant;
};

$currentTenant = $this->app->call($callback);

$this->assertSame($tenant, $currentTenant);
$this->assertSame($tenancy->tenant(), $currentTenant);
}
}
120 changes: 120 additions & 0 deletions tests/Unit/Providers/DatabaseProviderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<?php
declare(strict_types=1);

namespace Sprout\Tests\Unit\Providers;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Orchestra\Testbench\Attributes\DefineEnvironment;
use PHPUnit\Framework\Attributes\Test;
use Sprout\Providers\DatabaseTenantProvider;
use Sprout\Support\GenericTenant;
use Sprout\Tests\Unit\UnitTestCase;
use Workbench\App\CustomTenantEntity;
use function Sprout\provider;
use function Sprout\sprout;

class DatabaseProviderTest extends UnitTestCase
{
use RefreshDatabase;

protected function defineEnvironment($app): void
{
tap($app['config'], static function ($config) {
$config->set('multitenancy.providers.tenants.driver', 'database');
$config->set('multitenancy.providers.tenants.table', 'tenants');
});
}

protected function withCustomTenantEntity($app): void
{
tap($app['config'], static function ($config) {
$config->set('multitenancy.providers.tenants.entity', CustomTenantEntity::class);
});
}

#[Test]
public function hasARegisteredName(): void
{
$provider = provider('tenants');

$this->assertInstanceOf(DatabaseTenantProvider::class, $provider);
$this->assertSame('tenants', $provider->getName());
}

#[Test]
public function hasATable(): void
{
$provider = provider('tenants');

$this->assertInstanceOf(DatabaseTenantProvider::class, $provider);
$this->assertSame('tenants', $provider->getTable());
}

#[Test]
public function hasATenantEntity(): void
{
$provider = provider('tenants');

$this->assertInstanceOf(DatabaseTenantProvider::class, $provider);
$this->assertSame(GenericTenant::class, $provider->getEntityClass());
}

#[Test]
public function retrievesTenantsByTheirIdentifier(): void
{
$provider = provider('tenants');

$tenantData = [
'name' => 'Test Tenant',
'identifier' => 'tenant-test',
'active' => true,
];

$tenantData['id'] = DB::table('tenants')->insertGetId($tenantData);

$found = $provider->retrieveByIdentifier($tenantData['identifier']);

$this->assertNotNull($found);
$this->assertInstanceOf(GenericTenant::class, $found);
$this->assertSame($tenantData['identifier'], $found->getTenantIdentifier());
$this->assertSame($tenantData['id'], $found->getTenantKey());

$this->assertNull($provider->retrieveByIdentifier('fake-identifier'));
}

#[Test]
public function retrievesTenantsByTheirKey(): void
{
$provider = provider('tenants');

$tenantData = [
'name' => 'Test Tenant',
'identifier' => 'tenant-test',
'active' => true,
];

$tenantData['id'] = DB::table('tenants')->insertGetId($tenantData);

$found = $provider->retrieveByKey($tenantData['id']);

$this->assertNotNull($found);
$this->assertInstanceOf(GenericTenant::class, $found);
$this->assertSame($tenantData['identifier'], $found->getTenantIdentifier());
$this->assertSame($tenantData['id'], $found->getTenantKey());

$this->assertNull($provider->retrieveByKey(-999));
}

#[Test, DefineEnvironment('withCustomTenantEntity')]
public function canHaveCustomTenantEntity(): void
{
// This is necessary as the provider has already been resolved
sprout()->providers()->flushResolved();

$provider = provider('tenants');

$this->assertInstanceOf(DatabaseTenantProvider::class, $provider);
$this->assertSame(CustomTenantEntity::class, $provider->getEntityClass());
}
}
Loading