@friggframework/devtools 2.0.0--canary.545.c459392.0 → 2.0.0--canary.547.67ebb53.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/frigg-cli/README.md +1 -1
  2. package/frigg-cli/__tests__/unit/commands/build.test.js +1 -1
  3. package/frigg-cli/__tests__/unit/commands/doctor.test.js +2 -0
  4. package/frigg-cli/__tests__/unit/commands/install.test.js +19 -23
  5. package/frigg-cli/__tests__/unit/dependencies.test.js +2 -2
  6. package/frigg-cli/build-command/index.js +11 -123
  7. package/frigg-cli/deploy-command/index.js +1 -83
  8. package/frigg-cli/doctor-command/index.js +16 -37
  9. package/frigg-cli/generate-iam-command.js +1 -21
  10. package/frigg-cli/index.js +6 -21
  11. package/frigg-cli/index.test.js +2 -7
  12. package/frigg-cli/init-command/backend-first-handler.js +42 -124
  13. package/frigg-cli/init-command/index.js +1 -2
  14. package/frigg-cli/init-command/template-handler.js +3 -13
  15. package/frigg-cli/install-command/backend-js.js +3 -3
  16. package/frigg-cli/install-command/environment-variables.js +19 -16
  17. package/frigg-cli/install-command/environment-variables.test.js +13 -12
  18. package/frigg-cli/install-command/index.js +9 -14
  19. package/frigg-cli/install-command/integration-file.js +3 -3
  20. package/frigg-cli/install-command/logger.js +12 -0
  21. package/frigg-cli/install-command/validate-package.js +9 -5
  22. package/frigg-cli/jest.config.js +1 -4
  23. package/frigg-cli/repair-command/index.js +128 -121
  24. package/frigg-cli/start-command/index.js +2 -324
  25. package/frigg-cli/ui-command/index.js +36 -58
  26. package/frigg-cli/utils/repo-detection.js +37 -85
  27. package/infrastructure/create-frigg-infrastructure.js +0 -93
  28. package/infrastructure/docs/iam-policy-templates.md +1 -1
  29. package/infrastructure/domains/networking/vpc-builder.test.js +4 -2
  30. package/infrastructure/domains/networking/vpc-resolver.test.js +1 -1
  31. package/infrastructure/domains/shared/cloudformation-discovery.test.js +7 -4
  32. package/infrastructure/domains/shared/resource-discovery.js +5 -5
  33. package/infrastructure/domains/shared/types/app-definition.js +0 -21
  34. package/infrastructure/domains/shared/types/discovery-result.test.js +1 -1
  35. package/infrastructure/domains/shared/utilities/base-definition-factory.js +1 -10
  36. package/infrastructure/domains/shared/utilities/base-definition-factory.test.js +2 -2
  37. package/infrastructure/infrastructure-composer.js +0 -2
  38. package/infrastructure/infrastructure-composer.test.js +2 -2
  39. package/management-ui/README.md +109 -245
  40. package/package.json +7 -8
  41. package/frigg-cli/__tests__/application/use-cases/AddApiModuleToIntegrationUseCase.test.js +0 -326
  42. package/frigg-cli/__tests__/application/use-cases/CreateApiModuleUseCase.test.js +0 -337
  43. package/frigg-cli/__tests__/domain/entities/ApiModule.test.js +0 -373
  44. package/frigg-cli/__tests__/domain/entities/AppDefinition.test.js +0 -313
  45. package/frigg-cli/__tests__/domain/services/IntegrationValidator.test.js +0 -269
  46. package/frigg-cli/__tests__/domain/value-objects/IntegrationName.test.js +0 -82
  47. package/frigg-cli/__tests__/infrastructure/adapters/IntegrationJsUpdater.test.js +0 -408
  48. package/frigg-cli/__tests__/infrastructure/repositories/FileSystemApiModuleRepository.test.js +0 -583
  49. package/frigg-cli/__tests__/infrastructure/repositories/FileSystemAppDefinitionRepository.test.js +0 -314
  50. package/frigg-cli/__tests__/infrastructure/repositories/FileSystemIntegrationRepository.test.js +0 -383
  51. package/frigg-cli/__tests__/unit/commands/init.test.js +0 -406
  52. package/frigg-cli/__tests__/unit/commands/provider-dispatch.test.js +0 -383
  53. package/frigg-cli/__tests__/unit/commands/repair.test.js +0 -275
  54. package/frigg-cli/__tests__/unit/start-command/application/RunPreflightChecksUseCase.test.js +0 -411
  55. package/frigg-cli/__tests__/unit/start-command/infrastructure/DatabaseAdapter.test.js +0 -405
  56. package/frigg-cli/__tests__/unit/start-command/infrastructure/DockerAdapter.test.js +0 -496
  57. package/frigg-cli/__tests__/unit/start-command/presentation/InteractivePromptAdapter.test.js +0 -474
  58. package/frigg-cli/__tests__/unit/utils/output.test.js +0 -196
  59. package/frigg-cli/application/use-cases/AddApiModuleToIntegrationUseCase.js +0 -93
  60. package/frigg-cli/application/use-cases/CreateApiModuleUseCase.js +0 -93
  61. package/frigg-cli/application/use-cases/CreateIntegrationUseCase.js +0 -103
  62. package/frigg-cli/container.js +0 -172
  63. package/frigg-cli/docs/OUTPUT_MIGRATION_GUIDE.md +0 -286
  64. package/frigg-cli/domain/entities/ApiModule.js +0 -272
  65. package/frigg-cli/domain/entities/AppDefinition.js +0 -227
  66. package/frigg-cli/domain/entities/Integration.js +0 -198
  67. package/frigg-cli/domain/exceptions/DomainException.js +0 -24
  68. package/frigg-cli/domain/ports/IApiModuleRepository.js +0 -53
  69. package/frigg-cli/domain/ports/IAppDefinitionRepository.js +0 -43
  70. package/frigg-cli/domain/ports/IIntegrationRepository.js +0 -61
  71. package/frigg-cli/domain/services/IntegrationValidator.js +0 -185
  72. package/frigg-cli/domain/value-objects/IntegrationId.js +0 -42
  73. package/frigg-cli/domain/value-objects/IntegrationName.js +0 -60
  74. package/frigg-cli/domain/value-objects/SemanticVersion.js +0 -70
  75. package/frigg-cli/infrastructure/UnitOfWork.js +0 -46
  76. package/frigg-cli/infrastructure/adapters/BackendJsUpdater.js +0 -197
  77. package/frigg-cli/infrastructure/adapters/FileSystemAdapter.js +0 -224
  78. package/frigg-cli/infrastructure/adapters/IntegrationJsUpdater.js +0 -249
  79. package/frigg-cli/infrastructure/adapters/SchemaValidator.js +0 -92
  80. package/frigg-cli/infrastructure/repositories/FileSystemApiModuleRepository.js +0 -373
  81. package/frigg-cli/infrastructure/repositories/FileSystemAppDefinitionRepository.js +0 -116
  82. package/frigg-cli/infrastructure/repositories/FileSystemIntegrationRepository.js +0 -277
  83. package/frigg-cli/package-lock.json +0 -16226
  84. package/frigg-cli/start-command/application/RunPreflightChecksUseCase.js +0 -376
  85. package/frigg-cli/start-command/infrastructure/DatabaseAdapter.js +0 -591
  86. package/frigg-cli/start-command/infrastructure/DockerAdapter.js +0 -306
  87. package/frigg-cli/start-command/presentation/InteractivePromptAdapter.js +0 -329
  88. package/frigg-cli/templates/backend/.env.example +0 -62
  89. package/frigg-cli/templates/backend/.eslintrc.json +0 -12
  90. package/frigg-cli/templates/backend/.prettierrc +0 -6
  91. package/frigg-cli/templates/backend/docker-compose.yml +0 -22
  92. package/frigg-cli/templates/backend/index.js +0 -96
  93. package/frigg-cli/templates/backend/infrastructure.js +0 -12
  94. package/frigg-cli/templates/backend/jest.config.js +0 -17
  95. package/frigg-cli/templates/backend/package.json +0 -50
  96. package/frigg-cli/templates/backend/src/api-modules/.gitkeep +0 -10
  97. package/frigg-cli/templates/backend/src/base/.gitkeep +0 -7
  98. package/frigg-cli/templates/backend/src/integrations/.gitkeep +0 -10
  99. package/frigg-cli/templates/backend/src/integrations/ExampleIntegration.js +0 -65
  100. package/frigg-cli/templates/backend/src/utils/.gitkeep +0 -7
  101. package/frigg-cli/templates/backend/test/setup.js +0 -30
  102. package/frigg-cli/templates/backend/ui-extensions/.gitkeep +0 -0
  103. package/frigg-cli/templates/backend/ui-extensions/README.md +0 -77
  104. package/frigg-cli/utils/__tests__/provider-helper.test.js +0 -55
  105. package/frigg-cli/utils/__tests__/repo-detection.test.js +0 -436
  106. package/frigg-cli/utils/output.js +0 -382
  107. package/frigg-cli/utils/provider-helper.js +0 -75
  108. package/frigg-cli/validate-command/__tests__/adapters/validate-command.test.js +0 -205
  109. package/frigg-cli/validate-command/__tests__/application/validate-app-use-case.test.js +0 -104
  110. package/frigg-cli/validate-command/__tests__/domain/fix-suggestion.test.js +0 -153
  111. package/frigg-cli/validate-command/__tests__/domain/validation-error.test.js +0 -162
  112. package/frigg-cli/validate-command/__tests__/domain/validation-result.test.js +0 -152
  113. package/frigg-cli/validate-command/__tests__/infrastructure/api-module-validator.test.js +0 -332
  114. package/frigg-cli/validate-command/__tests__/infrastructure/app-definition-validator.test.js +0 -191
  115. package/frigg-cli/validate-command/__tests__/infrastructure/integration-class-validator.test.js +0 -146
  116. package/frigg-cli/validate-command/__tests__/infrastructure/template-validation.test.js +0 -155
  117. package/frigg-cli/validate-command/adapters/cli/validate-command.js +0 -199
  118. package/frigg-cli/validate-command/application/use-cases/validate-app-use-case.js +0 -35
  119. package/frigg-cli/validate-command/domain/entities/validation-result.js +0 -74
  120. package/frigg-cli/validate-command/domain/value-objects/fix-suggestion.js +0 -74
  121. package/frigg-cli/validate-command/domain/value-objects/validation-error.js +0 -68
  122. package/frigg-cli/validate-command/infrastructure/validators/api-module-validator.js +0 -181
  123. package/frigg-cli/validate-command/infrastructure/validators/app-definition-validator.js +0 -128
  124. package/frigg-cli/validate-command/infrastructure/validators/integration-class-validator.js +0 -113
  125. package/infrastructure/domains/admin-scripts/admin-script-builder.js +0 -200
  126. package/infrastructure/domains/admin-scripts/admin-script-builder.test.js +0 -499
  127. package/infrastructure/domains/admin-scripts/index.js +0 -5
  128. package/infrastructure/jest.config.js +0 -16
@@ -1,496 +0,0 @@
1
- /**
2
- * DockerAdapter Tests
3
- * Infrastructure adapter for Docker operations - used by pre-flight checks
4
- *
5
- * Tests follow TDD pattern - written BEFORE implementation
6
- */
7
-
8
- // Mock child_process before importing
9
- jest.mock('child_process', () => ({
10
- exec: jest.fn(),
11
- spawn: jest.fn()
12
- }));
13
-
14
- // Mock fs for docker-compose file detection
15
- jest.mock('fs', () => ({
16
- existsSync: jest.fn(),
17
- promises: {
18
- access: jest.fn()
19
- }
20
- }));
21
-
22
- const { exec, spawn } = require('child_process');
23
- const fs = require('fs');
24
- const path = require('path');
25
-
26
- // Import after mocks are set up
27
- const { DockerAdapter } = require('../../../../start-command/infrastructure/DockerAdapter');
28
-
29
- describe('DockerAdapter', () => {
30
- let adapter;
31
-
32
- beforeEach(() => {
33
- jest.clearAllMocks();
34
- adapter = new DockerAdapter();
35
- });
36
-
37
- describe('isDockerInstalled()', () => {
38
- it('should return true when docker CLI is available', async () => {
39
- exec.mockImplementation((cmd, callback) => {
40
- callback(null, 'Docker version 24.0.7, build afdd53b', '');
41
- });
42
-
43
- const result = await adapter.isDockerInstalled();
44
-
45
- expect(result).toBe(true);
46
- expect(exec).toHaveBeenCalledWith('docker --version', expect.any(Function));
47
- });
48
-
49
- it('should return false when docker CLI is not found', async () => {
50
- exec.mockImplementation((cmd, callback) => {
51
- const error = new Error('command not found: docker');
52
- error.code = 127;
53
- callback(error, '', 'command not found: docker');
54
- });
55
-
56
- const result = await adapter.isDockerInstalled();
57
-
58
- expect(result).toBe(false);
59
- });
60
-
61
- it('should return false when docker command fails', async () => {
62
- exec.mockImplementation((cmd, callback) => {
63
- callback(new Error('Docker not installed'), '', '');
64
- });
65
-
66
- const result = await adapter.isDockerInstalled();
67
-
68
- expect(result).toBe(false);
69
- });
70
- });
71
-
72
- describe('isDockerRunning()', () => {
73
- it('should return true when Docker daemon is running', async () => {
74
- exec.mockImplementation((cmd, callback) => {
75
- callback(null, '', '');
76
- });
77
-
78
- const result = await adapter.isDockerRunning();
79
-
80
- expect(result).toBe(true);
81
- expect(exec).toHaveBeenCalledWith('docker info', expect.any(Function));
82
- });
83
-
84
- it('should return false when Docker daemon is not running', async () => {
85
- exec.mockImplementation((cmd, callback) => {
86
- const error = new Error('Cannot connect to the Docker daemon');
87
- callback(error, '', 'Cannot connect to the Docker daemon');
88
- });
89
-
90
- const result = await adapter.isDockerRunning();
91
-
92
- expect(result).toBe(false);
93
- });
94
-
95
- it('should return false when docker info command times out', async () => {
96
- exec.mockImplementation((cmd, callback) => {
97
- const error = new Error('ETIMEDOUT');
98
- error.code = 'ETIMEDOUT';
99
- callback(error, '', '');
100
- });
101
-
102
- const result = await adapter.isDockerRunning();
103
-
104
- expect(result).toBe(false);
105
- });
106
- });
107
-
108
- describe('findDockerComposeFile()', () => {
109
- const projectPath = '/test/project';
110
-
111
- it('should find docker-compose.yml in project root', async () => {
112
- fs.existsSync.mockImplementation((filePath) => {
113
- return filePath === path.join(projectPath, 'docker-compose.yml');
114
- });
115
-
116
- const result = await adapter.findDockerComposeFile(projectPath);
117
-
118
- expect(result).toBe(path.join(projectPath, 'docker-compose.yml'));
119
- });
120
-
121
- it('should find docker-compose.yaml in project root', async () => {
122
- fs.existsSync.mockImplementation((filePath) => {
123
- return filePath === path.join(projectPath, 'docker-compose.yaml');
124
- });
125
-
126
- const result = await adapter.findDockerComposeFile(projectPath);
127
-
128
- expect(result).toBe(path.join(projectPath, 'docker-compose.yaml'));
129
- });
130
-
131
- it('should find compose.yml in project root', async () => {
132
- fs.existsSync.mockImplementation((filePath) => {
133
- return filePath === path.join(projectPath, 'compose.yml');
134
- });
135
-
136
- const result = await adapter.findDockerComposeFile(projectPath);
137
-
138
- expect(result).toBe(path.join(projectPath, 'compose.yml'));
139
- });
140
-
141
- it('should find compose.yaml in project root', async () => {
142
- fs.existsSync.mockImplementation((filePath) => {
143
- return filePath === path.join(projectPath, 'compose.yaml');
144
- });
145
-
146
- const result = await adapter.findDockerComposeFile(projectPath);
147
-
148
- expect(result).toBe(path.join(projectPath, 'compose.yaml'));
149
- });
150
-
151
- it('should return null when no docker-compose file exists', async () => {
152
- fs.existsSync.mockReturnValue(false);
153
-
154
- const result = await adapter.findDockerComposeFile(projectPath);
155
-
156
- expect(result).toBeNull();
157
- });
158
-
159
- it('should prefer docker-compose.yml over other variants', async () => {
160
- // All variants exist
161
- fs.existsSync.mockReturnValue(true);
162
-
163
- const result = await adapter.findDockerComposeFile(projectPath);
164
-
165
- // Should return the first one checked (docker-compose.yml)
166
- expect(result).toBe(path.join(projectPath, 'docker-compose.yml'));
167
- });
168
-
169
- it('should search in parent directory if not found in project path', async () => {
170
- const backendPath = '/test/project/backend';
171
- fs.existsSync.mockImplementation((filePath) => {
172
- // Only exists in parent directory
173
- return filePath === path.join('/test/project', 'docker-compose.yml');
174
- });
175
-
176
- const result = await adapter.findDockerComposeFile(backendPath);
177
-
178
- expect(result).toBe(path.join('/test/project', 'docker-compose.yml'));
179
- });
180
- });
181
-
182
- describe('startDockerCompose()', () => {
183
- const composePath = '/test/project/docker-compose.yml';
184
-
185
- it('should run docker compose up -d successfully', async () => {
186
- exec.mockImplementation((cmd, opts, callback) => {
187
- if (typeof opts === 'function') {
188
- callback = opts;
189
- }
190
- callback(null, 'Container started', '');
191
- });
192
-
193
- const result = await adapter.startDockerCompose(composePath);
194
-
195
- expect(result.success).toBe(true);
196
- expect(exec).toHaveBeenCalledWith(
197
- expect.stringContaining('docker compose'),
198
- expect.any(Object),
199
- expect.any(Function)
200
- );
201
- });
202
-
203
- it('should use correct docker-compose file path', async () => {
204
- exec.mockImplementation((cmd, opts, callback) => {
205
- if (typeof opts === 'function') {
206
- callback = opts;
207
- }
208
- callback(null, '', '');
209
- });
210
-
211
- await adapter.startDockerCompose(composePath);
212
-
213
- expect(exec).toHaveBeenCalledWith(
214
- expect.stringContaining(`-f ${composePath}`),
215
- expect.any(Object),
216
- expect.any(Function)
217
- );
218
- });
219
-
220
- it('should return error when docker compose fails', async () => {
221
- exec.mockImplementation((cmd, opts, callback) => {
222
- if (typeof opts === 'function') {
223
- callback = opts;
224
- }
225
- const error = new Error('Service failed to start');
226
- callback(error, '', 'Service failed to start');
227
- });
228
-
229
- const result = await adapter.startDockerCompose(composePath);
230
-
231
- expect(result.success).toBe(false);
232
- expect(result.error).toContain('Service failed to start');
233
- });
234
-
235
- it('should run in detached mode by default', async () => {
236
- exec.mockImplementation((cmd, opts, callback) => {
237
- if (typeof opts === 'function') {
238
- callback = opts;
239
- }
240
- callback(null, '', '');
241
- });
242
-
243
- await adapter.startDockerCompose(composePath);
244
-
245
- expect(exec).toHaveBeenCalledWith(
246
- expect.stringContaining('up -d'),
247
- expect.any(Object),
248
- expect.any(Function)
249
- );
250
- });
251
-
252
- it('should set working directory to compose file directory', async () => {
253
- exec.mockImplementation((cmd, opts, callback) => {
254
- if (typeof opts === 'function') {
255
- callback = opts;
256
- }
257
- callback(null, '', '');
258
- });
259
-
260
- await adapter.startDockerCompose(composePath);
261
-
262
- expect(exec).toHaveBeenCalledWith(
263
- expect.any(String),
264
- expect.objectContaining({
265
- cwd: path.dirname(composePath)
266
- }),
267
- expect.any(Function)
268
- );
269
- });
270
- });
271
-
272
- describe('stopDockerCompose()', () => {
273
- const composePath = '/test/project/docker-compose.yml';
274
-
275
- it('should run docker compose down successfully', async () => {
276
- exec.mockImplementation((cmd, opts, callback) => {
277
- if (typeof opts === 'function') {
278
- callback = opts;
279
- }
280
- callback(null, 'Containers stopped', '');
281
- });
282
-
283
- const result = await adapter.stopDockerCompose(composePath);
284
-
285
- expect(result.success).toBe(true);
286
- expect(exec).toHaveBeenCalledWith(
287
- expect.stringContaining('docker compose'),
288
- expect.any(Object),
289
- expect.any(Function)
290
- );
291
- expect(exec).toHaveBeenCalledWith(
292
- expect.stringContaining('down'),
293
- expect.any(Object),
294
- expect.any(Function)
295
- );
296
- });
297
-
298
- it('should return error when docker compose down fails', async () => {
299
- exec.mockImplementation((cmd, opts, callback) => {
300
- if (typeof opts === 'function') {
301
- callback = opts;
302
- }
303
- callback(new Error('Failed to stop'), '', 'Failed to stop');
304
- });
305
-
306
- const result = await adapter.stopDockerCompose(composePath);
307
-
308
- expect(result.success).toBe(false);
309
- expect(result.error).toContain('Failed to stop');
310
- });
311
- });
312
-
313
- describe('startDockerDesktop()', () => {
314
- it('should open Docker Desktop on macOS', async () => {
315
- const originalPlatform = process.platform;
316
- Object.defineProperty(process, 'platform', { value: 'darwin' });
317
-
318
- exec.mockImplementation((cmd, callback) => {
319
- callback(null, '', '');
320
- });
321
-
322
- const result = await adapter.startDockerDesktop();
323
-
324
- expect(result.success).toBe(true);
325
- expect(exec).toHaveBeenCalledWith(
326
- expect.stringContaining('open'),
327
- expect.any(Function)
328
- );
329
-
330
- Object.defineProperty(process, 'platform', { value: originalPlatform });
331
- });
332
-
333
- it('should start Docker Desktop on Windows', async () => {
334
- const originalPlatform = process.platform;
335
- Object.defineProperty(process, 'platform', { value: 'win32' });
336
-
337
- exec.mockImplementation((cmd, callback) => {
338
- callback(null, '', '');
339
- });
340
-
341
- const result = await adapter.startDockerDesktop();
342
-
343
- expect(result.success).toBe(true);
344
- expect(exec).toHaveBeenCalledWith(
345
- expect.stringContaining('Docker Desktop'),
346
- expect.any(Function)
347
- );
348
-
349
- Object.defineProperty(process, 'platform', { value: originalPlatform });
350
- });
351
-
352
- it('should start docker service on Linux', async () => {
353
- const originalPlatform = process.platform;
354
- Object.defineProperty(process, 'platform', { value: 'linux' });
355
-
356
- exec.mockImplementation((cmd, callback) => {
357
- callback(null, '', '');
358
- });
359
-
360
- const result = await adapter.startDockerDesktop();
361
-
362
- expect(result.success).toBe(true);
363
- expect(exec).toHaveBeenCalledWith(
364
- expect.stringMatching(/systemctl|service/),
365
- expect.any(Function)
366
- );
367
-
368
- Object.defineProperty(process, 'platform', { value: originalPlatform });
369
- });
370
-
371
- it('should return error when Docker Desktop fails to start', async () => {
372
- exec.mockImplementation((cmd, callback) => {
373
- callback(new Error('Failed to start Docker Desktop'), '', '');
374
- });
375
-
376
- const result = await adapter.startDockerDesktop();
377
-
378
- expect(result.success).toBe(false);
379
- expect(result.error).toBeDefined();
380
- });
381
- });
382
-
383
- describe('getDockerComposeServices()', () => {
384
- const composePath = '/test/project/docker-compose.yml';
385
-
386
- it('should list running services', async () => {
387
- exec.mockImplementation((cmd, opts, callback) => {
388
- if (typeof opts === 'function') {
389
- callback = opts;
390
- }
391
- callback(null, 'mongodb\nredis\n', '');
392
- });
393
-
394
- const result = await adapter.getDockerComposeServices(composePath);
395
-
396
- expect(result).toEqual(['mongodb', 'redis']);
397
- });
398
-
399
- it('should return empty array when no services running', async () => {
400
- exec.mockImplementation((cmd, opts, callback) => {
401
- if (typeof opts === 'function') {
402
- callback = opts;
403
- }
404
- callback(null, '', '');
405
- });
406
-
407
- const result = await adapter.getDockerComposeServices(composePath);
408
-
409
- expect(result).toEqual([]);
410
- });
411
-
412
- it('should handle docker compose ps command failure', async () => {
413
- exec.mockImplementation((cmd, opts, callback) => {
414
- if (typeof opts === 'function') {
415
- callback = opts;
416
- }
417
- callback(new Error('Failed'), '', '');
418
- });
419
-
420
- const result = await adapter.getDockerComposeServices(composePath);
421
-
422
- expect(result).toEqual([]);
423
- });
424
- });
425
-
426
- describe('isServiceRunning()', () => {
427
- const composePath = '/test/project/docker-compose.yml';
428
-
429
- it('should return true when specific service is running', async () => {
430
- exec.mockImplementation((cmd, opts, callback) => {
431
- if (typeof opts === 'function') {
432
- callback = opts;
433
- }
434
- // docker compose ps --services --filter "status=running"
435
- callback(null, 'mongodb\nredis\n', '');
436
- });
437
-
438
- const result = await adapter.isServiceRunning(composePath, 'mongodb');
439
-
440
- expect(result).toBe(true);
441
- });
442
-
443
- it('should return false when service is not running', async () => {
444
- exec.mockImplementation((cmd, opts, callback) => {
445
- if (typeof opts === 'function') {
446
- callback = opts;
447
- }
448
- callback(null, 'redis\n', '');
449
- });
450
-
451
- const result = await adapter.isServiceRunning(composePath, 'mongodb');
452
-
453
- expect(result).toBe(false);
454
- });
455
- });
456
-
457
- describe('waitForDockerReady()', () => {
458
- it('should resolve when Docker becomes ready', async () => {
459
- let callCount = 0;
460
- exec.mockImplementation((cmd, callback) => {
461
- callCount++;
462
- if (callCount >= 3) {
463
- // Docker is ready on third try
464
- callback(null, '', '');
465
- } else {
466
- callback(new Error('Not ready'), '', '');
467
- }
468
- });
469
-
470
- const result = await adapter.waitForDockerReady({ maxAttempts: 5, intervalMs: 10 });
471
-
472
- expect(result).toBe(true);
473
- expect(callCount).toBe(3);
474
- });
475
-
476
- it('should return false after max attempts exceeded', async () => {
477
- exec.mockImplementation((cmd, callback) => {
478
- callback(new Error('Not ready'), '', '');
479
- });
480
-
481
- const result = await adapter.waitForDockerReady({ maxAttempts: 3, intervalMs: 10 });
482
-
483
- expect(result).toBe(false);
484
- });
485
-
486
- it('should use default options when not specified', async () => {
487
- exec.mockImplementation((cmd, callback) => {
488
- callback(null, '', '');
489
- });
490
-
491
- const result = await adapter.waitForDockerReady();
492
-
493
- expect(result).toBe(true);
494
- });
495
- });
496
- });