5]); $plan = (new Caddy2Driver(service: $service))->getOperationPlan('hash'); expect($plan->steps)->toHaveCount(2); expect($plan->steps[0]->getScript())->toContain('mkdir -p /home/keystone/gateway /home/keystone/services/5'); expect($plan->steps[1]->getScript())->toContain('docker compose -f /home/keystone/services/5/compose.yml up -d'); }); it('reports static metadata about the caddy driver', function () { $driver = new Caddy2Driver; expect($driver->serviceType())->toBe(ServiceType::CADDY); expect($driver->versionTrack())->toBe('2'); expect($driver->defaultImage())->toBe('caddy:2'); expect($driver->defaultPorts())->toBe([80, 443]); expect($driver->firewallRules())->toBe(['80/tcp', '443/tcp']); expect($driver->environmentSchema())->toBe([]); expect($driver->resourceDefaults())->toBe([]); expect($driver->updateBehavior())->toBe('stateless_redeploy'); expect($driver->supportedSliceTypes())->toBe(['route']); expect($driver->environmentExports())->toBe([]); }); it('renders a compose service with caddy volumes', function () { $service = new Service(['id' => 8]); $compose = (new Caddy2Driver(service: $service))->composeService(); expect($compose['image'])->toBe('caddy:2'); expect($compose['ports'])->toBe(['80:80', '443:443']); expect($compose['volumes'])->toContain('keystone_service_8_caddy_data:/data'); }); it('declares the caddy data and config volumes', function () { $service = new Service(['id' => 8]); expect((new Caddy2Driver(service: $service))->composeVolumes())->toBe([ 'keystone_service_8_caddy_data' => null, 'keystone_service_8_caddy_config' => null, ]); }); it('returns an empty environment export for a slice', function () { $slice = new ServiceSlice; expect((new Caddy2Driver)->environmentExportsForSlice($slice))->toBe([]); }); it('emits a provisioning script for a route slice', function () { $slice = new ServiceSlice(['id' => 42]); $script = (new Caddy2Driver)->provisionSliceScript($slice); expect($script)->toContain('mkdir -p /home/keystone/gateway/Caddyfile.d'); expect($script)->toContain('Caddyfile.d/42.caddy'); });