@friggframework/devtools 2.0.0--canary.545.ae2019f.0 → 2.0.0--canary.549.a579cca.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 (127) 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/resource-discovery.js +5 -5
  32. package/infrastructure/domains/shared/types/app-definition.js +0 -21
  33. package/infrastructure/domains/shared/types/discovery-result.test.js +1 -1
  34. package/infrastructure/domains/shared/utilities/base-definition-factory.js +1 -10
  35. package/infrastructure/domains/shared/utilities/base-definition-factory.test.js +2 -2
  36. package/infrastructure/infrastructure-composer.js +0 -2
  37. package/infrastructure/infrastructure-composer.test.js +2 -2
  38. package/management-ui/README.md +109 -245
  39. package/package.json +7 -8
  40. package/frigg-cli/__tests__/application/use-cases/AddApiModuleToIntegrationUseCase.test.js +0 -326
  41. package/frigg-cli/__tests__/application/use-cases/CreateApiModuleUseCase.test.js +0 -337
  42. package/frigg-cli/__tests__/domain/entities/ApiModule.test.js +0 -373
  43. package/frigg-cli/__tests__/domain/entities/AppDefinition.test.js +0 -313
  44. package/frigg-cli/__tests__/domain/services/IntegrationValidator.test.js +0 -269
  45. package/frigg-cli/__tests__/domain/value-objects/IntegrationName.test.js +0 -82
  46. package/frigg-cli/__tests__/infrastructure/adapters/IntegrationJsUpdater.test.js +0 -408
  47. package/frigg-cli/__tests__/infrastructure/repositories/FileSystemApiModuleRepository.test.js +0 -583
  48. package/frigg-cli/__tests__/infrastructure/repositories/FileSystemAppDefinitionRepository.test.js +0 -314
  49. package/frigg-cli/__tests__/infrastructure/repositories/FileSystemIntegrationRepository.test.js +0 -383
  50. package/frigg-cli/__tests__/unit/commands/init.test.js +0 -406
  51. package/frigg-cli/__tests__/unit/commands/provider-dispatch.test.js +0 -383
  52. package/frigg-cli/__tests__/unit/commands/repair.test.js +0 -275
  53. package/frigg-cli/__tests__/unit/start-command/application/RunPreflightChecksUseCase.test.js +0 -411
  54. package/frigg-cli/__tests__/unit/start-command/infrastructure/DatabaseAdapter.test.js +0 -405
  55. package/frigg-cli/__tests__/unit/start-command/infrastructure/DockerAdapter.test.js +0 -496
  56. package/frigg-cli/__tests__/unit/start-command/presentation/InteractivePromptAdapter.test.js +0 -474
  57. package/frigg-cli/__tests__/unit/utils/output.test.js +0 -196
  58. package/frigg-cli/application/use-cases/AddApiModuleToIntegrationUseCase.js +0 -93
  59. package/frigg-cli/application/use-cases/CreateApiModuleUseCase.js +0 -93
  60. package/frigg-cli/application/use-cases/CreateIntegrationUseCase.js +0 -103
  61. package/frigg-cli/container.js +0 -172
  62. package/frigg-cli/docs/OUTPUT_MIGRATION_GUIDE.md +0 -286
  63. package/frigg-cli/domain/entities/ApiModule.js +0 -272
  64. package/frigg-cli/domain/entities/AppDefinition.js +0 -227
  65. package/frigg-cli/domain/entities/Integration.js +0 -198
  66. package/frigg-cli/domain/exceptions/DomainException.js +0 -24
  67. package/frigg-cli/domain/ports/IApiModuleRepository.js +0 -53
  68. package/frigg-cli/domain/ports/IAppDefinitionRepository.js +0 -43
  69. package/frigg-cli/domain/ports/IIntegrationRepository.js +0 -61
  70. package/frigg-cli/domain/services/IntegrationValidator.js +0 -185
  71. package/frigg-cli/domain/value-objects/IntegrationId.js +0 -42
  72. package/frigg-cli/domain/value-objects/IntegrationName.js +0 -60
  73. package/frigg-cli/domain/value-objects/SemanticVersion.js +0 -70
  74. package/frigg-cli/infrastructure/UnitOfWork.js +0 -46
  75. package/frigg-cli/infrastructure/adapters/BackendJsUpdater.js +0 -197
  76. package/frigg-cli/infrastructure/adapters/FileSystemAdapter.js +0 -224
  77. package/frigg-cli/infrastructure/adapters/IntegrationJsUpdater.js +0 -249
  78. package/frigg-cli/infrastructure/adapters/SchemaValidator.js +0 -92
  79. package/frigg-cli/infrastructure/repositories/FileSystemApiModuleRepository.js +0 -373
  80. package/frigg-cli/infrastructure/repositories/FileSystemAppDefinitionRepository.js +0 -116
  81. package/frigg-cli/infrastructure/repositories/FileSystemIntegrationRepository.js +0 -277
  82. package/frigg-cli/package-lock.json +0 -16226
  83. package/frigg-cli/start-command/application/RunPreflightChecksUseCase.js +0 -376
  84. package/frigg-cli/start-command/infrastructure/DatabaseAdapter.js +0 -591
  85. package/frigg-cli/start-command/infrastructure/DockerAdapter.js +0 -306
  86. package/frigg-cli/start-command/presentation/InteractivePromptAdapter.js +0 -329
  87. package/frigg-cli/templates/backend/.env.example +0 -62
  88. package/frigg-cli/templates/backend/.eslintrc.json +0 -12
  89. package/frigg-cli/templates/backend/.prettierrc +0 -6
  90. package/frigg-cli/templates/backend/docker-compose.yml +0 -22
  91. package/frigg-cli/templates/backend/index.js +0 -96
  92. package/frigg-cli/templates/backend/infrastructure.js +0 -12
  93. package/frigg-cli/templates/backend/jest.config.js +0 -17
  94. package/frigg-cli/templates/backend/package.json +0 -50
  95. package/frigg-cli/templates/backend/src/api-modules/.gitkeep +0 -10
  96. package/frigg-cli/templates/backend/src/base/.gitkeep +0 -7
  97. package/frigg-cli/templates/backend/src/integrations/.gitkeep +0 -10
  98. package/frigg-cli/templates/backend/src/integrations/ExampleIntegration.js +0 -65
  99. package/frigg-cli/templates/backend/src/utils/.gitkeep +0 -7
  100. package/frigg-cli/templates/backend/test/setup.js +0 -30
  101. package/frigg-cli/templates/backend/ui-extensions/.gitkeep +0 -0
  102. package/frigg-cli/templates/backend/ui-extensions/README.md +0 -77
  103. package/frigg-cli/utils/__tests__/provider-helper.test.js +0 -55
  104. package/frigg-cli/utils/__tests__/repo-detection.test.js +0 -436
  105. package/frigg-cli/utils/output.js +0 -382
  106. package/frigg-cli/utils/provider-helper.js +0 -75
  107. package/frigg-cli/validate-command/__tests__/adapters/validate-command.test.js +0 -205
  108. package/frigg-cli/validate-command/__tests__/application/validate-app-use-case.test.js +0 -104
  109. package/frigg-cli/validate-command/__tests__/domain/fix-suggestion.test.js +0 -153
  110. package/frigg-cli/validate-command/__tests__/domain/validation-error.test.js +0 -162
  111. package/frigg-cli/validate-command/__tests__/domain/validation-result.test.js +0 -152
  112. package/frigg-cli/validate-command/__tests__/infrastructure/api-module-validator.test.js +0 -332
  113. package/frigg-cli/validate-command/__tests__/infrastructure/app-definition-validator.test.js +0 -191
  114. package/frigg-cli/validate-command/__tests__/infrastructure/integration-class-validator.test.js +0 -146
  115. package/frigg-cli/validate-command/__tests__/infrastructure/template-validation.test.js +0 -155
  116. package/frigg-cli/validate-command/adapters/cli/validate-command.js +0 -199
  117. package/frigg-cli/validate-command/application/use-cases/validate-app-use-case.js +0 -35
  118. package/frigg-cli/validate-command/domain/entities/validation-result.js +0 -74
  119. package/frigg-cli/validate-command/domain/value-objects/fix-suggestion.js +0 -74
  120. package/frigg-cli/validate-command/domain/value-objects/validation-error.js +0 -68
  121. package/frigg-cli/validate-command/infrastructure/validators/api-module-validator.js +0 -181
  122. package/frigg-cli/validate-command/infrastructure/validators/app-definition-validator.js +0 -128
  123. package/frigg-cli/validate-command/infrastructure/validators/integration-class-validator.js +0 -113
  124. package/infrastructure/domains/admin-scripts/admin-script-builder.js +0 -200
  125. package/infrastructure/domains/admin-scripts/admin-script-builder.test.js +0 -499
  126. package/infrastructure/domains/admin-scripts/index.js +0 -5
  127. 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
- });