put($route, ['api_key' => 'secret'])->assertRedirect(route('login')); $this->actingAs(User::factory()->create())->put($route, ['api_key' => 'secret'])->assertForbidden(); $this->actingAs(User::factory()->create(['role' => 'admin'])) ->put(route('settings.integrations.update', 'unknown'), ['api_key' => 'secret'])->assertNotFound(); $this->assertDatabaseCount('integration_settings', 0); } public function test_saved_values_are_encrypted_masked_and_override_server_values(): void { config()->set('services.bambuddy', ['url' => 'https://old.example.test', 'api_key' => 'old-key']); $admin = User::factory()->create(['role' => 'admin']); $this->actingAs($admin)->put(route('settings.integrations.update', 'bambuddy'), [ 'url' => 'https://new.example.test', 'api_key' => 'saved-key', ])->assertRedirect(route('settings.index')); $record = IntegrationSetting::findOrFail('bambuddy'); $this->assertSame('saved-key', $record->settings['api_key']); $this->assertStringNotContainsString('saved-key', $record->getRawOriginal('settings')); $this->assertArrayNotHasKey('settings', $record->toArray()); $this->actingAs($admin)->get(route('settings.index')) ->assertOk()->assertSee('https://new.example.test')->assertDontSee('saved-key')->assertDontSee('old-key'); Http::preventStrayRequests(); Http::fake(['https://new.example.test/api/v1/printers' => Http::response([])]); $this->assertSame([], app(Bambuddy::class)->printers()); Http::assertSent(fn ($request) => $request->url() === 'https://new.example.test/api/v1/printers' && $request->hasHeader('X-API-Key', 'saved-key')); } public function test_blank_secret_keeps_existing_value_and_save_imports_server_values(): void { config()->set('services.parcel2go', [ 'client_id' => 'server-id', 'client_secret' => 'server-secret', 'auth_url' => 'https://auth.example.test/token', 'base_url' => 'https://api.example.test', ]); $admin = User::factory()->create(['role' => 'admin']); $this->actingAs($admin)->put(route('settings.integrations.update', 'parcel2go'), []) ->assertRedirect(route('settings.index')); $this->assertSame('server-secret', IntegrationSetting::findOrFail('parcel2go')->settings['client_secret']); $this->actingAs($admin)->put(route('settings.integrations.update', 'parcel2go'), [ 'client_id' => 'new-id', 'client_secret' => '', ])->assertRedirect(route('settings.index')); $this->assertSame('server-secret', IntegrationSetting::findOrFail('parcel2go')->settings['client_secret']); Http::preventStrayRequests(); Http::fake([ 'https://auth.example.test/token' => Http::response(['access_token' => 'token']), 'https://api.example.test/me/detail' => Http::response(['ok' => true]), ]); $this->assertSame(['ok' => true], app(Parcel2Go::class)->fetch('me/detail')); Http::assertSent(fn ($request) => $request->url() === 'https://auth.example.test/token' && $request['client_id'] === 'new-id' && $request['client_secret'] === 'server-secret'); } public function test_dryer_uses_saved_endpoint_and_key(): void { config()->set('services.dryer', ['url' => 'https://old.example.test/api/v1', 'api_key' => 'old-key']); $this->actingAs(User::factory()->create(['role' => 'admin'])) ->put(route('settings.integrations.update', 'dryer'), [ 'url' => 'https://dryer.example.test/api/v1', 'api_key' => 'new-key', ])->assertRedirect(route('settings.index')); Http::preventStrayRequests(); Http::fake(['https://dryer.example.test/api/v1/status' => Http::response(['state' => 'idle'])]); $this->assertSame('https://dryer.example.test', app(DryerClient::class)->dashboardUrl()); $this->assertSame(['state' => 'idle'], app(DryerClient::class)->status()); Http::assertSent(fn ($request) => $request->url() === 'https://dryer.example.test/api/v1/status' && $request->hasHeader('X-API-Key', 'new-key')); $this->get(route('dryer'))->assertOk()->assertSee('https://dryer.example.test'); } public function test_endpoint_urls_must_use_https(): void { $this->actingAs(User::factory()->create(['role' => 'admin'])) ->put(route('settings.integrations.update', 'dryer'), [ 'url' => 'http://dryer.example.test', 'api_key' => 'key', ])->assertSessionHasErrors('url'); $this->assertDatabaseCount('integration_settings', 0); } public function test_parcel2go_scope_is_validated_and_saved(): void { $admin = User::factory()->create(['role' => 'admin']); $this->actingAs($admin)->put(route('settings.integrations.update', 'parcel2go'), [ 'scope' => 'admin', ])->assertSessionHasErrors('scope'); $this->assertDatabaseCount('integration_settings', 0); $this->actingAs($admin)->put(route('settings.integrations.update', 'parcel2go'), [ 'scope' => 'public-api my-profile', 'collection_postcode' => 'SW1A 1AA', ])->assertRedirect(route('settings.index')); $this->assertSame('public-api my-profile', IntegrationSetting::findOrFail('parcel2go')->settings['scope']); $this->assertSame('SW1A 1AA', IntegrationSetting::findOrFail('parcel2go')->settings['collection_postcode']); } }