[ 'web' => [ 'image' => 'nginx:latest', 'exclude_from_hc' => true, 'ports' => ['80:80'], ], ], ]; $result = stripCoolifyCustomFields($yaml); assertEquals('nginx:latest', $result['services']['web']['image']); assertEquals(['80:80'], $result['services']['web']['ports']); expect($result['services']['web'])->not->toHaveKey('exclude_from_hc'); }); test('removes content from volume level', function () { $yaml = [ 'services' => [ 'app' => [ 'image' => 'php:8.4', 'volumes' => [ [ 'type' => 'bind', 'source' => './config.xml', 'target' => '/app/config.xml', 'content' => '', ], ], ], ], ]; $result = stripCoolifyCustomFields($yaml); expect($result['services']['app']['volumes'][0])->toHaveKeys(['type', 'source', 'target']); expect($result['services']['app']['volumes'][0])->not->toHaveKey('content'); }); test('removes isDirectory from volume level', function () { $yaml = [ 'services' => [ 'app' => [ 'image' => 'node:20', 'volumes' => [ [ 'type' => 'bind', 'source' => './data', 'target' => '/app/data', 'isDirectory' => true, ], ], ], ], ]; $result = stripCoolifyCustomFields($yaml); expect($result['services']['app']['volumes'][0])->toHaveKeys(['type', 'source', 'target']); expect($result['services']['app']['volumes'][0])->not->toHaveKey('isDirectory'); }); test('removes is_directory from volume level', function () { $yaml = [ 'services' => [ 'app' => [ 'image' => 'python:3.12', 'volumes' => [ [ 'type' => 'bind', 'source' => './logs', 'target' => '/var/log/app', 'is_directory' => true, ], ], ], ], ]; $result = stripCoolifyCustomFields($yaml); expect($result['services']['app']['volumes'][0])->toHaveKeys(['type', 'source', 'target']); expect($result['services']['app']['volumes'][0])->not->toHaveKey('is_directory'); }); test('removes all custom fields together', function () { $yaml = [ 'services' => [ 'web' => [ 'image' => 'nginx:latest', 'exclude_from_hc' => true, 'volumes' => [ [ 'type' => 'bind', 'source' => './config.xml', 'target' => '/etc/nginx/config.xml', 'content' => '', 'isDirectory' => false, ], [ 'type' => 'bind', 'source' => './data', 'target' => '/var/www/data', 'is_directory' => true, ], ], ], 'worker' => [ 'image' => 'worker:latest', 'exclude_from_hc' => true, ], ], ]; $result = stripCoolifyCustomFields($yaml); // Verify service-level custom fields removed expect($result['services']['web'])->not->toHaveKey('exclude_from_hc'); expect($result['services']['worker'])->not->toHaveKey('exclude_from_hc'); // Verify volume-level custom fields removed expect($result['services']['web']['volumes'][0])->not->toHaveKey('content'); expect($result['services']['web']['volumes'][0])->not->toHaveKey('isDirectory'); expect($result['services']['web']['volumes'][1])->not->toHaveKey('is_directory'); // Verify standard fields preserved assertEquals('nginx:latest', $result['services']['web']['image']); assertEquals('worker:latest', $result['services']['worker']['image']); }); test('preserves standard Docker Compose fields', function () { $yaml = [ 'services' => [ 'db' => [ 'image' => 'postgres:16', 'environment' => [ 'POSTGRES_DB' => 'mydb', 'POSTGRES_USER' => 'user', ], 'ports' => ['5432:5432'], 'volumes' => [ 'db-data:/var/lib/postgresql/data', ], 'healthcheck' => [ 'test' => ['CMD', 'pg_isready'], 'interval' => '5s', ], 'restart' => 'unless-stopped', 'networks' => ['backend'], ], ], 'networks' => [ 'backend' => [ 'driver' => 'bridge', ], ], 'volumes' => [ 'db-data' => null, ], ]; $result = stripCoolifyCustomFields($yaml); // All standard fields should be preserved expect($result)->toHaveKeys(['services', 'networks', 'volumes']); expect($result['services']['db'])->toHaveKeys([ 'image', 'environment', 'ports', 'volumes', 'healthcheck', 'restart', 'networks', ]); assertEquals('postgres:16', $result['services']['db']['image']); assertEquals(['5432:5432'], $result['services']['db']['ports']); }); test('handles missing services gracefully', function () { $yaml = [ 'version' => '3.8', ]; $result = stripCoolifyCustomFields($yaml); expect($result)->toBe($yaml); }); test('handles missing volumes in service gracefully', function () { $yaml = [ 'services' => [ 'app' => [ 'image' => 'nginx:latest', 'exclude_from_hc' => true, ], ], ]; $result = stripCoolifyCustomFields($yaml); expect($result['services']['app'])->not->toHaveKey('exclude_from_hc'); expect($result['services']['app'])->not->toHaveKey('volumes'); assertEquals('nginx:latest', $result['services']['app']['image']); }); test('handles traccar.yaml example with multiline content', function () { $yaml = [ 'services' => [ 'traccar' => [ 'image' => 'traccar/traccar:latest', 'volumes' => [ [ 'type' => 'bind', 'source' => './srv/traccar/conf/traccar.xml', 'target' => '/opt/traccar/conf/traccar.xml', 'content' => "\n\n\n ./conf/default.xml\n", ], ], ], ], ]; $result = stripCoolifyCustomFields($yaml); expect($result['services']['traccar']['volumes'][0])->toHaveKeys(['type', 'source', 'target']); expect($result['services']['traccar']['volumes'][0])->not->toHaveKey('content'); assertEquals('./srv/traccar/conf/traccar.xml', $result['services']['traccar']['volumes'][0]['source']); });