|
10 | 10 | use Stancl\Tenancy\Listeners\RevertToCentralContext; |
11 | 11 | use Stancl\Tenancy\Overrides\TenancyBroadcastManager; |
12 | 12 | use Stancl\Tenancy\Bootstrappers\BroadcastingConfigBootstrapper; |
| 13 | +use Illuminate\Support\Facades\Broadcast; |
| 14 | +use Illuminate\Contracts\Broadcasting\Broadcaster as BroadcasterContract; |
13 | 15 |
|
14 | 16 | beforeEach(function () { |
15 | 17 | Event::listen(TenancyInitialized::class, BootstrapTenancy::class); |
|
38 | 40 | expect(app(BroadcastManager::class))->toBeInstanceOf(BroadcastManager::class); |
39 | 41 | }); |
40 | 42 |
|
41 | | -test('BroadcastingConfigBootstrapper maps tenant broadcaster credentials to config as specified in the $credentialsMap property and reverts the config after ending tenancy', function() { |
| 43 | +test('BroadcastingConfigBootstrapper maps tenant properties to broadcaster credentials correctly', function() { |
42 | 44 | config([ |
43 | | - 'broadcasting.connections.testing.driver' => 'testing', |
44 | | - 'broadcasting.connections.testing.message' => $defaultMessage = 'default', |
45 | | - 'tenancy.bootstrappers' => [BroadcastingConfigBootstrapper::class], |
| 45 | + 'broadcasting.default' => $driver = 'testing', |
| 46 | + 'broadcasting.connections.testing.driver' => $driver, |
| 47 | + 'broadcasting.connections.testing.key' => 'central_key', |
| 48 | + 'tenancy.bootstrappers' => [ |
| 49 | + BroadcastingConfigBootstrapper::class, |
| 50 | + ], |
46 | 51 | ]); |
47 | 52 |
|
48 | | - BroadcastingConfigBootstrapper::$credentialsMap = [ |
49 | | - 'broadcasting.connections.testing.message' => 'testing_broadcaster_message', |
50 | | - ]; |
| 53 | + BroadcastingConfigBootstrapper::$credentialsMap['broadcasting.connections.testing.key'] = 'testing_key'; |
51 | 54 |
|
52 | | - $tenant = Tenant::create(['testing_broadcaster_message' => $tenantMessage = 'first testing']); |
53 | | - $tenant2 = Tenant::create(['testing_broadcaster_message' => $secondTenantMessage = 'second testing']); |
| 55 | + // Register the testing broadcaster |
| 56 | + app(BroadcastManager::class)->extend('testing', fn($app, $config) => new TestingBroadcaster('testing', $config)); |
| 57 | + |
| 58 | + $tenant1 = Tenant::create(['testing_key' => 'tenant1_key']); |
| 59 | + $tenant2 = Tenant::create(['testing_key' => 'tenant2_key']); |
| 60 | + |
| 61 | + expect(config('broadcasting.connections.testing.key'))->toBe('central_key'); |
| 62 | + expect(app(BroadcastManager::class)->driver()->config['key'])->toBe('central_key'); |
| 63 | + expect(app(BroadcasterContract::class)->config['key'])->toBe('central_key'); |
| 64 | + expect(Broadcast::driver()->config['key'])->toBe('central_key'); |
| 65 | + |
| 66 | + tenancy()->initialize($tenant1); |
| 67 | + |
| 68 | + expect(array_key_exists('testing_key', tenant()->getAttributes()))->toBeTrue(); |
| 69 | + // Tenant's testing_key property is mapped to broadcasting.connections.testing.key config value |
| 70 | + expect(config('broadcasting.connections.testing.key'))->toBe('tenant1_key'); |
| 71 | + expect(app(BroadcastManager::class)->driver()->config['key'])->toBe('tenant1_key'); |
| 72 | + // Switching to tenant context makes the currently bound Broadcaster instance use the tenant's config |
| 73 | + expect(app(BroadcasterContract::class)->config['key'])->toBe('tenant1_key'); |
| 74 | + // The Broadcast facade (used in BroadcastController::authenticate) uses the broadcaster with tenant config |
| 75 | + // instead of the stale broadcaster instance resolved before tenancy was initialized |
| 76 | + expect(Broadcast::driver()->config['key'])->toBe('tenant1_key'); |
| 77 | + |
| 78 | + tenancy()->initialize($tenant2); |
| 79 | + |
| 80 | + expect(array_key_exists('testing_key', tenant()->getAttributes()))->toBeTrue(); |
| 81 | + expect(config('broadcasting.connections.testing.key'))->toBe('tenant2_key'); |
| 82 | + // Switching to another tenant context makes the current broadcaster use the new tenant's config |
| 83 | + expect(app(BroadcastManager::class)->driver()->config['key'])->toBe('tenant2_key'); |
| 84 | + expect(app(BroadcasterContract::class)->config['key'])->toBe('tenant2_key'); |
| 85 | + expect(Broadcast::driver()->config['key'])->toBe('tenant2_key'); |
| 86 | + |
| 87 | + tenancy()->end(); |
| 88 | + |
| 89 | + expect(config('broadcasting.connections.testing.key'))->toBe('central_key'); |
| 90 | + // Ending tenancy reverts the broadcaster changes |
| 91 | + expect(app(BroadcastManager::class)->driver()->config['key'])->toBe('central_key'); |
| 92 | + expect(app(BroadcasterContract::class)->config['key'])->toBe('central_key'); |
| 93 | + expect(Broadcast::driver()->config['key'])->toBe('central_key'); |
| 94 | +}); |
| 95 | + |
| 96 | +test('tenant broadcast manager receives the custom driver creators of the central broadcast manager', function() { |
| 97 | + config([ |
| 98 | + 'tenancy.bootstrappers' => [ |
| 99 | + BroadcastingConfigBootstrapper::class, |
| 100 | + ], |
| 101 | + ]); |
| 102 | + |
| 103 | + $tenant = Tenant::create(); |
| 104 | + $tenant2 = Tenant::create(); |
| 105 | + |
| 106 | + app(BroadcastManager::class)->extend('testing', fn($app, $config) => new TestingBroadcaster('testing', $config)); |
| 107 | + |
| 108 | + $originalDrivers = array_keys(invade(app(BroadcastManager::class))->customCreators); |
| 109 | + |
| 110 | + expect($originalDrivers)->toContain('testing'); |
54 | 111 |
|
55 | 112 | tenancy()->initialize($tenant); |
56 | 113 |
|
57 | | - expect(array_key_exists('testing_broadcaster_message', tenant()->getAttributes()))->toBeTrue(); |
58 | | - expect(config('broadcasting.connections.testing.message'))->toBe($tenantMessage); |
| 114 | + app(BroadcastManager::class)->extend( |
| 115 | + 'testing-tenant1', |
| 116 | + fn($app, $config) => new TestingBroadcaster('testing-tenant1', $config) |
| 117 | + ); |
| 118 | + |
| 119 | + // Current BroadcastManager instance has the original custom creators plus the newly registered testing-tenant1 creator |
| 120 | + expect(array_keys(invade(app(BroadcastManager::class))->customCreators))->toBe([...$originalDrivers, 'testing-tenant1']); |
59 | 121 |
|
60 | 122 | tenancy()->initialize($tenant2); |
61 | 123 |
|
62 | | - expect(config('broadcasting.connections.testing.message'))->toBe($secondTenantMessage); |
| 124 | + // Current BroadcastManager only has the original custom creators, |
| 125 | + // the creator added in the previous tenant's context doesn't persist. |
| 126 | + expect(array_keys(invade(app(BroadcastManager::class))->customCreators))->toBe($originalDrivers); |
63 | 127 |
|
64 | 128 | tenancy()->end(); |
65 | 129 |
|
66 | | - expect(config('broadcasting.connections.testing.message'))->toBe($defaultMessage); |
| 130 | + // Ending tenancy reverts the BroadcastManager binding back to the original state, |
| 131 | + // the creator registered in the tenant context doesn't persist. |
| 132 | + expect(array_keys(invade(app(BroadcastManager::class))->customCreators))->toBe($originalDrivers); |
67 | 133 | }); |
68 | 134 |
|
69 | | -test('BroadcastingConfigBootstrapper makes the app use broadcasters with the correct credentials', function() { |
| 135 | +test('tenant broadcasters receive the channels from the broadcaster bound in central context', function() { |
| 136 | + config(['tenancy.bootstrappers' => [BroadcastingConfigBootstrapper::class]]); |
70 | 137 | config([ |
71 | | - 'broadcasting.default' => 'testing', |
72 | | - 'broadcasting.connections.testing.driver' => 'testing', |
73 | | - 'broadcasting.connections.testing.message' => $defaultMessage = 'default', |
74 | | - 'tenancy.bootstrappers' => [BroadcastingConfigBootstrapper::class], |
| 138 | + 'broadcasting.default' => $driver = 'testing', |
| 139 | + 'broadcasting.connections.testing.driver' => $driver, |
75 | 140 | ]); |
76 | 141 |
|
77 | | - TenancyBroadcastManager::$tenantBroadcasters[] = 'testing'; |
78 | | - BroadcastingConfigBootstrapper::$credentialsMap = [ |
79 | | - 'broadcasting.connections.testing.message' => 'testing_broadcaster_message', |
80 | | - ]; |
| 142 | + TenancyBroadcastManager::$tenantBroadcasters[] = $driver; |
81 | 143 |
|
82 | | - $registerTestingBroadcaster = fn() => app(BroadcastManager::class)->extend('testing', fn ($app, $config) => new TestingBroadcaster($config['message'])); |
| 144 | + $tenant1 = Tenant::create(); |
| 145 | + $tenant2 = Tenant::create(); |
83 | 146 |
|
84 | | - $registerTestingBroadcaster(); |
| 147 | + app(BroadcastManager::class)->extend('testing', fn($app, $config) => new TestingBroadcaster('testing')); |
| 148 | + $getCurrentChannelsFromBoundBroadcaster = fn() => array_keys(invade(app(BroadcasterContract::class))->channels); |
| 149 | + $getCurrentChannelsThroughManager = fn() => array_keys(invade(app(BroadcastManager::class)->driver())->channels); |
85 | 150 |
|
86 | | - expect(invade(app(BroadcastManager::class)->driver())->message)->toBe($defaultMessage); |
| 151 | + Broadcast::channel($channel = 'testing-channel', fn() => true); |
87 | 152 |
|
88 | | - $tenant = Tenant::create(['testing_broadcaster_message' => $tenantMessage = 'first testing']); |
89 | | - $tenant2 = Tenant::create(['testing_broadcaster_message' => $secondTenantMessage = 'second testing']); |
| 153 | + expect($channel) |
| 154 | + ->toBeIn($getCurrentChannelsThroughManager()) |
| 155 | + ->toBeIn($getCurrentChannelsFromBoundBroadcaster()); |
90 | 156 |
|
91 | | - tenancy()->initialize($tenant); |
92 | | - $registerTestingBroadcaster(); |
| 157 | + tenancy()->initialize($tenant1); |
93 | 158 |
|
94 | | - expect(invade(app(BroadcastManager::class)->driver())->message)->toBe($tenantMessage); |
| 159 | + expect($channel) |
| 160 | + ->toBeIn($getCurrentChannelsThroughManager()) |
| 161 | + ->toBeIn($getCurrentChannelsFromBoundBroadcaster()); |
95 | 162 |
|
96 | 163 | tenancy()->initialize($tenant2); |
97 | | - $registerTestingBroadcaster(); |
98 | 164 |
|
99 | | - expect(invade(app(BroadcastManager::class)->driver())->message)->toBe($secondTenantMessage); |
| 165 | + expect($channel) |
| 166 | + ->toBeIn($getCurrentChannelsThroughManager()) |
| 167 | + ->toBeIn($getCurrentChannelsFromBoundBroadcaster()); |
100 | 168 |
|
101 | 169 | tenancy()->end(); |
102 | | - $registerTestingBroadcaster(); |
103 | 170 |
|
104 | | - expect(invade(app(BroadcastManager::class)->driver())->message)->toBe($defaultMessage); |
| 171 | + expect($channel) |
| 172 | + ->toBeIn($getCurrentChannelsThroughManager()) |
| 173 | + ->toBeIn($getCurrentChannelsFromBoundBroadcaster()); |
105 | 174 | }); |
0 commit comments