import 'package:podman/podman.dart'; import 'package:test/test.dart'; import 'support/fake_podman_transport.dart'; void main() { group('PodmanClient container API', () { test('lists containers', () async { final transport = FakePodmanTransport() ..enqueue( method: HttpMethod.get, path: '/v5.0.0/libpod/containers/json', queryParameters: const >{ 'all': ['true'], }, responseBody: [ { 'Id': 'abc123', 'Image': 'hello-world:latest', 'Names': ['web'], 'State': 'running', 'Status': 'Up 4m', }, ], ); final client = PodmanClient(transport: transport); final containers = await client.listContainers(); expect(containers, hasLength(1)); expect(containers.first.id, 'abc123'); expect(containers.first.image, 'hello-world:latest'); expect(containers.first.name, 'web'); transport.expectNoPending(); }); test('creates and starts container via run', () async { final transport = FakePodmanTransport() ..enqueue( method: HttpMethod.post, path: '/v5.0.0/libpod/containers/create', queryParameters: const >{ 'name': ['web'], }, body: const { 'Image': 'docker.io/library/hello-world:latest', }, statusCode: 201, responseBody: const {'Id': 'container-id-123'}, ) ..enqueue( method: HttpMethod.post, path: '/v5.0.0/libpod/containers/container-id-123/start', statusCode: 204, ); final client = PodmanClient(transport: transport); final id = await client.run( const RunOptions( image: 'docker.io/library/hello-world:latest', name: 'web', ), ); expect(id, 'container-id-123'); transport.expectNoPending(); }); test('inspects container details', () async { final transport = FakePodmanTransport() ..enqueue( method: HttpMethod.get, path: '/v5.0.0/libpod/containers/web/json', responseBody: { 'Id': 'abc', 'Name': '/web', 'ImageName': 'hello-world:latest', 'State': {'Status': 'running'}, 'Config': { 'Labels': {'role': 'frontend'}, }, }, ); final client = PodmanClient(transport: transport); final details = await client.inspectContainer('web'); expect(details.id, 'abc'); expect(details.name, 'web'); expect(details.state, 'running'); expect(details.labels['role'], 'frontend'); transport.expectNoPending(); }); test('containerExists returns false for missing container', () async { final transport = FakePodmanTransport() ..enqueue( method: HttpMethod.get, path: '/v5.0.0/libpod/containers/missing/exists', statusCode: 404, ); final client = PodmanClient(transport: transport); final exists = await client.containerExists('missing'); expect(exists, isFalse); transport.expectNoPending(); }); test('supports lifecycle operations', () async { final transport = FakePodmanTransport() ..enqueue( method: HttpMethod.post, path: '/v5.0.0/libpod/containers/web/stop', queryParameters: const >{ 't': ['10'], }, statusCode: 204, ) ..enqueue( method: HttpMethod.post, path: '/v5.0.0/libpod/containers/web/start', statusCode: 204, ) ..enqueue( method: HttpMethod.post, path: '/v5.0.0/libpod/containers/web/restart', queryParameters: const >{ 't': ['5'], }, statusCode: 204, ) ..enqueue( method: HttpMethod.delete, path: '/v5.0.0/libpod/containers/web', queryParameters: const >{ 'force': ['true'], 'v': ['true'], }, statusCode: 204, ) ..enqueue( method: HttpMethod.post, path: '/v5.0.0/libpod/containers/prune', statusCode: 200, responseBody: const {}, ); final client = PodmanClient(transport: transport); await client.stop('web', timeoutSeconds: 10); await client.start('web'); await client.restart('web', timeoutSeconds: 5); await client.removeContainer('web', force: true, removeVolumes: true); await client.pruneContainers(); transport.expectNoPending(); }); test('supports logs query options and log polling', () async { final since = DateTime.utc(2026, 4, 6, 10, 0, 0); final until = DateTime.utc(2026, 4, 6, 11, 0, 0); final transport = FakePodmanTransport() ..enqueue( method: HttpMethod.get, path: '/v5.0.0/libpod/containers/web/logs', queryParameters: >{ 'stdout': ['true'], 'stderr': ['false'], 'timestamps': ['true'], 'since': [since.toIso8601String()], 'until': [until.toIso8601String()], 'tail': ['25'], }, responseBody: 'log-one\n', ) ..enqueue( method: HttpMethod.get, path: '/v5.0.0/libpod/containers/web/logs', queryParameters: >{ 'stdout': ['true'], 'stderr': ['true'], 'timestamps': ['true'], 'since': [since.toIso8601String()], 'tail': ['10'], }, responseBody: 'log-two\n', ); final client = PodmanClient(transport: transport); final logs = await client.logs( 'web', tail: 25, since: since, until: until, timestamps: true, stdout: true, stderr: false, ); expect(logs, 'log-one\n'); final chunk = await client .watchLogs( 'web', since: since, tail: 10, pollInterval: const Duration(days: 1), reconnect: false, ) .first; expect(chunk, 'log-two\n'); transport.expectNoPending(); }); test('throws on unexpected API status', () async { final transport = FakePodmanTransport() ..enqueue( method: HttpMethod.post, path: '/v5.0.0/libpod/containers/web/start', statusCode: 500, responseBody: const {'message': 'boom'}, ); final client = PodmanClient(transport: transport); await expectLater( client.start('web'), throwsA(isA()), ); }); }); }