git-history-ui 1.0.0 → 1.0.2

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.
@@ -44,12 +44,15 @@
44
44
  "@angular/cli": "^20.2.0",
45
45
  "@schematics/angular": "^20.2.0",
46
46
  "@types/jasmine": "~5.1.0",
47
+ "autoprefixer": "^10.4.21",
47
48
  "jasmine-core": "~5.9.0",
48
49
  "karma": "~6.4.0",
49
50
  "karma-chrome-launcher": "~3.2.0",
50
51
  "karma-coverage": "~2.2.0",
51
52
  "karma-jasmine": "~5.1.0",
52
53
  "karma-jasmine-html-reporter": "~2.1.0",
54
+ "postcss": "^8.5.6",
55
+ "tailwindcss": "^3.4.17",
53
56
  "typescript": "~5.9.2"
54
57
  }
55
58
  }
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ }
@@ -1,3 +1,7 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
1
5
  /* You can add global styles to this file, and also import other style files */
2
6
 
3
7
  /* Modern CSS Reset */
@@ -0,0 +1,11 @@
1
+ /** @type {import('tailwindcss').Config} */
2
+ module.exports = {
3
+ content: [
4
+ "./src/**/*.{html,ts}",
5
+ ],
6
+ theme: {
7
+ extend: {},
8
+ },
9
+ plugins: [],
10
+ }
11
+
package/jest.config.js CHANGED
@@ -9,5 +9,18 @@ module.exports = {
9
9
  collectCoverageFrom: [
10
10
  'src/**/*.ts',
11
11
  '!src/**/*.d.ts',
12
+ '!src/**/*.test.ts',
13
+ '!src/**/*.spec.ts',
12
14
  ],
15
+ coverageDirectory: 'coverage',
16
+ coverageReporters: ['text', 'lcov', 'html'],
17
+ coverageThreshold: {
18
+ global: {
19
+ branches: 80,
20
+ functions: 80,
21
+ lines: 80,
22
+ statements: 80
23
+ }
24
+ },
25
+ setupFilesAfterEnv: ['<rootDir>/src/__tests__/setup.ts'],
13
26
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "git-history-ui",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Beautiful git history visualization in your browser",
5
5
  "main": "dist/cli.js",
6
6
  "bin": {
@@ -10,11 +10,15 @@
10
10
  "build": "npm run build:backend && npm run build:frontend",
11
11
  "build:backend": "tsc -p tsconfig.json",
12
12
  "build:frontend": "cd frontend && ng build --configuration production",
13
+ "build:production": "NODE_ENV=production npm run build",
13
14
  "dev": "concurrently \"npm run dev:backend\" \"npm run dev:frontend\"",
14
15
  "dev:backend": "ts-node-dev --respawn --transpile-only src/backend/dev-server.ts",
15
16
  "dev:frontend": "cd frontend && ng serve --port 4200",
16
17
  "start": "node dist/backend/server.js",
18
+ "start:production": "NODE_ENV=production node dist/backend/server.js",
17
19
  "test": "jest",
20
+ "test:coverage": "jest --coverage",
21
+ "test:watch": "jest --watch",
18
22
  "lint": "eslint src/**/*.ts",
19
23
  "prepare": "npm run build"
20
24
  },
package/public/index.html CHANGED
@@ -4,7 +4,6 @@
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>Git History UI</title>
7
- <script src="https://cdn.tailwindcss.com"></script>
8
7
  <script src="https://d3js.org/d3.v7.min.js"></script>
9
8
  <script src="https://cdn.socket.io/4.7.4/socket.io.min.js"></script>
10
9
  <style>
@@ -1,35 +1,533 @@
1
1
  import { GitService } from '../backend/gitService';
2
2
 
3
+ // Mock simple-git
4
+ const mockGit = {
5
+ log: jest.fn(),
6
+ tags: jest.fn(),
7
+ branch: jest.fn(),
8
+ diff: jest.fn(),
9
+ raw: jest.fn(),
10
+ };
11
+
12
+ jest.mock('simple-git', () => {
13
+ return jest.fn(() => mockGit);
14
+ });
15
+
3
16
  describe('GitService', () => {
4
17
  let gitService: GitService;
5
18
 
6
19
  beforeEach(() => {
7
20
  gitService = new GitService();
21
+ jest.clearAllMocks();
8
22
  });
9
23
 
10
24
  describe('getCommits', () => {
11
25
  it('should return an array of commits', async () => {
12
- const commits = await gitService.getCommits({ limit: 5 });
26
+ const mockCommits = [
27
+ {
28
+ hash: 'abc123',
29
+ date: '2024-01-01',
30
+ message: 'Test commit',
31
+ author_name: 'Test Author',
32
+ author_email: 'test@example.com',
33
+ refs: 'HEAD -> main',
34
+ body: '',
35
+ hash_abbrev: 'abc123',
36
+ tree: 'def456',
37
+ tree_abbrev: 'def456',
38
+ parent: 'ghi789',
39
+ parent_abbrev: 'ghi789'
40
+ }
41
+ ];
42
+
43
+ mockGit.log.mockResolvedValue({ all: mockCommits });
44
+ mockGit.diff.mockResolvedValue('');
45
+ mockGit.branch.mockResolvedValue({ all: ['main'] });
46
+ mockGit.raw.mockResolvedValue('');
47
+
48
+ const commits = await gitService.getCommits();
49
+
13
50
  expect(Array.isArray(commits)).toBe(true);
51
+ expect(commits.length).toBeGreaterThan(0);
52
+ expect(commits[0]).toHaveProperty('hash');
53
+ expect(commits[0]).toHaveProperty('author');
54
+ expect(commits[0]).toHaveProperty('date');
55
+ expect(commits[0]).toHaveProperty('message');
14
56
  });
15
57
 
16
58
  it('should respect the limit parameter', async () => {
59
+ const mockCommits = Array(3).fill(null).map((_, i) => ({
60
+ hash: `hash${i}`,
61
+ date: '2024-01-01',
62
+ message: `Commit ${i}`,
63
+ author_name: 'Test Author',
64
+ author_email: 'test@example.com',
65
+ refs: 'HEAD -> main',
66
+ body: '',
67
+ hash_abbrev: `hash${i}`,
68
+ tree: 'def456',
69
+ tree_abbrev: 'def456',
70
+ parent: 'ghi789',
71
+ parent_abbrev: 'ghi789'
72
+ }));
73
+
74
+ mockGit.log.mockResolvedValue({ all: mockCommits });
75
+
17
76
  const commits = await gitService.getCommits({ limit: 3 });
18
- expect(commits.length).toBeLessThanOrEqual(3);
77
+
78
+ // The GitService should respect the limit parameter
79
+ expect(commits.length).toBe(3);
80
+ });
81
+
82
+ it('should handle git log errors', async () => {
83
+ mockGit.log.mockRejectedValue(new Error('Git error'));
84
+
85
+ await expect(gitService.getCommits()).rejects.toThrow('Git error');
86
+ });
87
+
88
+ it('should handle empty commit list', async () => {
89
+ mockGit.log.mockResolvedValue({ all: [] });
90
+
91
+ const commits = await gitService.getCommits();
92
+
93
+ expect(Array.isArray(commits)).toBe(true);
94
+ expect(commits.length).toBe(0);
95
+ });
96
+
97
+ it('should handle file filter option', async () => {
98
+ const mockCommits = [
99
+ {
100
+ hash: 'abc123',
101
+ date: '2024-01-01',
102
+ message: 'Test commit',
103
+ author_name: 'Test Author',
104
+ author_email: 'test@example.com',
105
+ refs: 'HEAD -> main',
106
+ body: '',
107
+ hash_abbrev: 'abc123',
108
+ tree: 'def456',
109
+ tree_abbrev: 'def456',
110
+ parent: 'ghi789',
111
+ parent_abbrev: 'ghi789'
112
+ }
113
+ ];
114
+
115
+ mockGit.log.mockResolvedValue({ all: mockCommits });
116
+
117
+ const commits = await gitService.getCommits({ file: 'src/app.js' });
118
+
119
+ expect(Array.isArray(commits)).toBe(true);
120
+ expect(commits.length).toBeGreaterThan(0);
121
+ });
122
+
123
+ it('should handle since filter option', async () => {
124
+ const mockCommits = [
125
+ {
126
+ hash: 'abc123',
127
+ date: '2024-01-01',
128
+ message: 'Test commit',
129
+ author_name: 'Test Author',
130
+ author_email: 'test@example.com',
131
+ refs: 'HEAD -> main',
132
+ body: '',
133
+ hash_abbrev: 'abc123',
134
+ tree: 'def456',
135
+ tree_abbrev: 'def456',
136
+ parent: 'ghi789',
137
+ parent_abbrev: 'ghi789'
138
+ }
139
+ ];
140
+
141
+ mockGit.log.mockResolvedValue({ all: mockCommits });
142
+
143
+ const commits = await gitService.getCommits({ since: 'v1.0.0' });
144
+
145
+ expect(Array.isArray(commits)).toBe(true);
146
+ expect(commits.length).toBeGreaterThan(0);
147
+ });
148
+
149
+ it('should handle author filter option', async () => {
150
+ const mockCommits = [
151
+ {
152
+ hash: 'abc123',
153
+ date: '2024-01-01',
154
+ message: 'Test commit',
155
+ author_name: 'Test Author',
156
+ author_email: 'test@example.com',
157
+ refs: 'HEAD -> main',
158
+ body: '',
159
+ hash_abbrev: 'abc123',
160
+ tree: 'def456',
161
+ tree_abbrev: 'def456',
162
+ parent: 'ghi789',
163
+ parent_abbrev: 'ghi789'
164
+ }
165
+ ];
166
+
167
+ mockGit.log.mockResolvedValue({ all: mockCommits });
168
+ mockGit.diff.mockResolvedValue('');
169
+ mockGit.branch.mockResolvedValue({ all: ['main'] });
170
+ mockGit.raw.mockResolvedValue('');
171
+
172
+ const commits = await gitService.getCommits({ author: 'Test Author' });
173
+
174
+ expect(Array.isArray(commits)).toBe(true);
175
+ expect(commits.length).toBeGreaterThan(0);
176
+ });
177
+
178
+ it('should handle private method errors gracefully', async () => {
179
+ const mockCommits = [
180
+ {
181
+ hash: 'abc123',
182
+ date: '2024-01-01',
183
+ message: 'Test commit',
184
+ author_name: 'Test Author',
185
+ author_email: 'test@example.com',
186
+ refs: 'HEAD -> main',
187
+ body: '',
188
+ hash_abbrev: 'abc123',
189
+ tree: 'def456',
190
+ tree_abbrev: 'def456',
191
+ parent: 'ghi789',
192
+ parent_abbrev: 'ghi789'
193
+ }
194
+ ];
195
+
196
+ mockGit.log.mockResolvedValue({ all: mockCommits });
197
+ mockGit.diff.mockRejectedValue(new Error('Diff error'));
198
+ mockGit.branch.mockRejectedValue(new Error('Branch error'));
199
+ mockGit.raw.mockRejectedValue(new Error('Tag error'));
200
+
201
+ const commits = await gitService.getCommits();
202
+
203
+ expect(Array.isArray(commits)).toBe(true);
204
+ expect(commits.length).toBeGreaterThan(0);
205
+ expect(commits[0].files).toEqual([]);
206
+ expect(commits[0].branches).toEqual([]);
207
+ expect(commits[0].tags).toEqual([]);
208
+ });
209
+
210
+ it('should handle non-Error exceptions', async () => {
211
+ mockGit.log.mockRejectedValue('String error');
212
+
213
+ await expect(gitService.getCommits()).rejects.toThrow('Failed to get commits: Unknown error');
19
214
  });
20
215
  });
21
216
 
22
217
  describe('getTags', () => {
23
218
  it('should return an array of tags', async () => {
219
+ const mockTags = ['v1.0.0', 'v1.1.0', 'v2.0.0'];
220
+ mockGit.tags.mockResolvedValue({ all: mockTags });
221
+
222
+ const tags = await gitService.getTags();
223
+
224
+ expect(Array.isArray(tags)).toBe(true);
225
+ expect(tags).toEqual(mockTags);
226
+ });
227
+
228
+ it('should handle git tags errors', async () => {
229
+ mockGit.tags.mockRejectedValue(new Error('Git tags error'));
230
+
231
+ await expect(gitService.getTags()).rejects.toThrow('Git tags error');
232
+ });
233
+
234
+ it('should handle empty tags list', async () => {
235
+ mockGit.tags.mockResolvedValue({ all: [] });
236
+
24
237
  const tags = await gitService.getTags();
238
+
25
239
  expect(Array.isArray(tags)).toBe(true);
240
+ expect(tags.length).toBe(0);
26
241
  });
27
242
  });
28
243
 
29
244
  describe('getBranches', () => {
30
245
  it('should return an array of branches', async () => {
246
+ const mockBranches = ['main', 'develop', 'feature/test'];
247
+ mockGit.branch.mockResolvedValue({ all: mockBranches });
248
+
31
249
  const branches = await gitService.getBranches();
250
+
32
251
  expect(Array.isArray(branches)).toBe(true);
252
+ expect(branches).toEqual(mockBranches);
253
+ });
254
+
255
+ it('should handle git branch errors', async () => {
256
+ mockGit.branch.mockRejectedValue(new Error('Git branch error'));
257
+
258
+ await expect(gitService.getBranches()).rejects.toThrow('Git branch error');
259
+ });
260
+
261
+ it('should handle empty branches list', async () => {
262
+ mockGit.branch.mockResolvedValue({ all: [] });
263
+
264
+ const branches = await gitService.getBranches();
265
+
266
+ expect(Array.isArray(branches)).toBe(true);
267
+ expect(branches.length).toBe(0);
268
+ });
269
+ });
270
+
271
+ describe('getDiff', () => {
272
+ it('should return diff for a commit', async () => {
273
+ const mockDiff = 'diff --git a/file.js b/file.js\nindex 123..456 100644\n--- a/file.js\n+++ b/file.js\n@@ -1,3 +1,4 @@\n line1\n+line2\n line3';
274
+ mockGit.diff.mockResolvedValue(mockDiff);
275
+
276
+ const diff = await gitService.getDiff('abc123');
277
+
278
+ expect(Array.isArray(diff)).toBe(true);
279
+ expect(diff.length).toBeGreaterThan(0);
280
+ expect(diff[0]).toHaveProperty('file');
281
+ expect(diff[0]).toHaveProperty('additions');
282
+ expect(diff[0]).toHaveProperty('deletions');
283
+ expect(diff[0]).toHaveProperty('changes');
284
+ });
285
+
286
+ it('should handle git diff errors', async () => {
287
+ mockGit.diff.mockRejectedValue(new Error('Git diff error'));
288
+
289
+ await expect(gitService.getDiff('abc123')).rejects.toThrow('Git diff error');
290
+ });
291
+
292
+ it('should handle empty diff', async () => {
293
+ mockGit.diff.mockResolvedValue('');
294
+
295
+ const diff = await gitService.getDiff('abc123');
296
+
297
+ expect(Array.isArray(diff)).toBe(true);
298
+ expect(diff.length).toBe(0);
299
+ });
300
+
301
+ it('should parse complex diff with multiple files', async () => {
302
+ const mockDiff = `diff --git a/file1.js b/file1.js
303
+ index 123..456 100644
304
+ --- a/file1.js
305
+ +++ b/file1.js
306
+ @@ -1,3 +1,4 @@
307
+ line1
308
+ +line2
309
+ line3
310
+ diff --git a/file2.js b/file2.js
311
+ index 789..012 100644
312
+ --- a/file2.js
313
+ +++ b/file2.js
314
+ @@ -1,2 +1,3 @@
315
+ old1
316
+ +new1
317
+ old2`;
318
+ mockGit.diff.mockResolvedValue(mockDiff);
319
+
320
+ const diff = await gitService.getDiff('abc123');
321
+
322
+ expect(Array.isArray(diff)).toBe(true);
323
+ expect(diff.length).toBe(2);
324
+ expect(diff[0].file).toBe('file1.js');
325
+ expect(diff[1].file).toBe('file2.js');
326
+ });
327
+
328
+ it('should handle diff with no file match', async () => {
329
+ const mockDiff = 'diff --git a/ b/\nindex 123..456 100644\n--- a/\n+++ b/';
330
+ mockGit.diff.mockResolvedValue(mockDiff);
331
+
332
+ const diff = await gitService.getDiff('abc123');
333
+
334
+ expect(Array.isArray(diff)).toBe(true);
335
+ expect(diff.length).toBeGreaterThan(0);
336
+ expect(diff[0].file).toBe('');
337
+ });
338
+
339
+ it('should handle diff with context lines and headers', async () => {
340
+ const mockDiff = `diff --git a/file.js b/file.js
341
+ index 123..456 100644
342
+ --- a/file.js
343
+ +++ b/file.js
344
+ @@ -1,3 +1,4 @@
345
+ line1
346
+ +line2
347
+ line3
348
+ unchanged line`;
349
+ mockGit.diff.mockResolvedValue(mockDiff);
350
+
351
+ const diff = await gitService.getDiff('abc123');
352
+
353
+ expect(Array.isArray(diff)).toBe(true);
354
+ expect(diff.length).toBeGreaterThan(0);
355
+ });
356
+
357
+ it('should handle diff with only deletions', async () => {
358
+ const mockDiff = `diff --git a/file.js b/file.js
359
+ index 123..456 100644
360
+ --- a/file.js
361
+ +++ b/file.js
362
+ @@ -1,3 +1,2 @@
363
+ line1
364
+ -line2
365
+ line3`;
366
+ mockGit.diff.mockResolvedValue(mockDiff);
367
+
368
+ const diff = await gitService.getDiff('abc123');
369
+
370
+ expect(Array.isArray(diff)).toBe(true);
371
+ expect(diff.length).toBeGreaterThan(0);
372
+ expect(diff[0].deletions).toBeGreaterThan(0);
373
+ });
374
+ });
375
+
376
+ describe('getCommit', () => {
377
+ it('should return a single commit', async () => {
378
+ const mockCommit = {
379
+ hash: 'abc123',
380
+ date: '2024-01-01',
381
+ message: 'Test commit',
382
+ author_name: 'Test Author',
383
+ author_email: 'test@example.com',
384
+ refs: 'HEAD -> main',
385
+ body: '',
386
+ hash_abbrev: 'abc123',
387
+ tree: 'def456',
388
+ tree_abbrev: 'def456',
389
+ parent: 'ghi789',
390
+ parent_abbrev: 'ghi789'
391
+ };
392
+
393
+ mockGit.log.mockResolvedValue({ all: [mockCommit] });
394
+
395
+ const commit = await gitService.getCommit('abc123');
396
+
397
+ expect(commit).toHaveProperty('hash', 'abc123');
398
+ expect(commit).toHaveProperty('author', 'Test Author');
399
+ expect(commit).toHaveProperty('date', '2024-01-01');
400
+ expect(commit).toHaveProperty('message', 'Test commit');
401
+ });
402
+
403
+ it('should handle commit not found', async () => {
404
+ mockGit.log.mockResolvedValue({ all: [] });
405
+
406
+ await expect(gitService.getCommit('nonexistent')).rejects.toThrow('Commit not found');
407
+ });
408
+
409
+ it('should handle git log errors', async () => {
410
+ mockGit.log.mockRejectedValue(new Error('Git error'));
411
+
412
+ await expect(gitService.getCommit('abc123')).rejects.toThrow('Git error');
413
+ });
414
+
415
+ it('should handle non-Error exceptions', async () => {
416
+ mockGit.log.mockRejectedValue('String error');
417
+
418
+ await expect(gitService.getCommit('abc123')).rejects.toThrow('Failed to get commit: Unknown error');
419
+ });
420
+ });
421
+
422
+ describe('getBlame', () => {
423
+ it('should return blame information for a file', async () => {
424
+ const mockBlame = 'abc123 1 1 1\nauthor Test Author\n\tline1';
425
+ mockGit.raw.mockResolvedValue(mockBlame);
426
+
427
+ const blame = await gitService.getBlame('test.js');
428
+
429
+ expect(Array.isArray(blame)).toBe(true);
430
+ expect(blame.length).toBeGreaterThan(0);
431
+ expect(blame[0]).toHaveProperty('hash');
432
+ expect(blame[0]).toHaveProperty('author');
433
+ expect(blame[0]).toHaveProperty('line');
434
+ expect(blame[0]).toHaveProperty('content');
435
+ });
436
+
437
+ it('should handle git blame errors', async () => {
438
+ mockGit.raw.mockRejectedValue(new Error('Git blame error'));
439
+
440
+ await expect(gitService.getBlame('test.js')).rejects.toThrow('Git blame error');
441
+ });
442
+
443
+ it('should handle empty blame', async () => {
444
+ mockGit.raw.mockResolvedValue('');
445
+
446
+ const blame = await gitService.getBlame('test.js');
447
+
448
+ expect(Array.isArray(blame)).toBe(true);
449
+ expect(blame.length).toBe(0);
450
+ });
451
+
452
+ it('should handle non-Error exceptions', async () => {
453
+ mockGit.raw.mockRejectedValue('String error');
454
+
455
+ await expect(gitService.getBlame('test.js')).rejects.toThrow('Failed to get blame: Unknown error');
456
+ });
457
+
458
+ it('should parse blame with author-time', async () => {
459
+ const mockBlame = `abc123 1 1 1
460
+ author Test Author
461
+ author-time 1640995200
462
+ \tline1`;
463
+ mockGit.raw.mockResolvedValue(mockBlame);
464
+
465
+ const blame = await gitService.getBlame('test.js');
466
+
467
+ expect(Array.isArray(blame)).toBe(true);
468
+ expect(blame.length).toBeGreaterThan(0);
469
+ expect(blame[0]).toHaveProperty('date');
470
+ });
471
+
472
+ it('should parse blame without author-time', async () => {
473
+ const mockBlame = `abc123 1 1 1
474
+ author Test Author
475
+ \tline1`;
476
+ mockGit.raw.mockResolvedValue(mockBlame);
477
+
478
+ const blame = await gitService.getBlame('test.js');
479
+
480
+ expect(Array.isArray(blame)).toBe(true);
481
+ expect(blame.length).toBeGreaterThan(0);
482
+ expect(blame[0]).toHaveProperty('date');
483
+ });
484
+
485
+ it('should handle malformed blame data', async () => {
486
+ const mockBlame = 'invalid blame data without proper format';
487
+ mockGit.raw.mockResolvedValue(mockBlame);
488
+
489
+ const blame = await gitService.getBlame('test.js');
490
+
491
+ expect(Array.isArray(blame)).toBe(true);
492
+ expect(blame.length).toBe(0);
493
+ });
494
+
495
+ it('should parse blame with multiple lines and complete properly', async () => {
496
+ const mockBlame = `abc123 1 1 1
497
+ author Test Author
498
+ author-time 1640995200
499
+ \tline1
500
+ def456 2 2 1
501
+ author Another Author
502
+ \tline2`;
503
+ mockGit.raw.mockResolvedValue(mockBlame);
504
+
505
+ const blame = await gitService.getBlame('test.js');
506
+
507
+ expect(Array.isArray(blame)).toBe(true);
508
+ expect(blame.length).toBe(2);
509
+ expect(blame[0].hash).toBe('abc123');
510
+ expect(blame[1].hash).toBe('def456');
511
+ });
512
+ });
513
+
514
+ describe('Error handling', () => {
515
+ it('should handle non-Error exceptions in getTags', async () => {
516
+ mockGit.tags.mockRejectedValue('String error');
517
+
518
+ await expect(gitService.getTags()).rejects.toThrow('Failed to get tags: Unknown error');
519
+ });
520
+
521
+ it('should handle non-Error exceptions in getBranches', async () => {
522
+ mockGit.branch.mockRejectedValue('String error');
523
+
524
+ await expect(gitService.getBranches()).rejects.toThrow('Failed to get branches: Unknown error');
525
+ });
526
+
527
+ it('should handle non-Error exceptions in getDiff', async () => {
528
+ mockGit.diff.mockRejectedValue('String error');
529
+
530
+ await expect(gitService.getDiff('abc123')).rejects.toThrow('Failed to get diff: Unknown error');
33
531
  });
34
532
  });
35
533
  });
@@ -0,0 +1,25 @@
1
+ // Test setup file
2
+ import { jest } from '@jest/globals';
3
+
4
+ // Mock console methods to reduce noise in tests
5
+ global.console = {
6
+ ...console,
7
+ log: jest.fn(),
8
+ debug: jest.fn(),
9
+ info: jest.fn(),
10
+ warn: jest.fn(),
11
+ error: jest.fn(),
12
+ };
13
+
14
+ // Mock process.exit to prevent tests from exiting
15
+ process.exit = jest.fn() as any;
16
+
17
+ // Set test timeout
18
+ jest.setTimeout(10000);
19
+
20
+ // Add a simple test to satisfy Jest requirements
21
+ describe('Setup', () => {
22
+ it('should be configured correctly', () => {
23
+ expect(true).toBe(true);
24
+ });
25
+ });
@@ -20,17 +20,25 @@ export async function startServer(
20
20
  ) {
21
21
  const app = express();
22
22
  const server = createServer(app);
23
+
24
+ // CORS configuration
25
+ const corsOptions = {
26
+ origin: process.env.NODE_ENV === 'production'
27
+ ? ['http://localhost:4200', 'http://localhost:3000', 'http://127.0.0.1:4200', 'http://127.0.0.1:3000']
28
+ : true,
29
+ credentials: true,
30
+ methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
31
+ allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With']
32
+ };
33
+
23
34
  const io = new Server(server, {
24
- cors: {
25
- origin: "*",
26
- methods: ["GET", "POST"]
27
- }
35
+ cors: corsOptions
28
36
  });
29
37
 
30
38
  const gitService = new GitService();
31
39
 
32
40
  // Middleware
33
- app.use(cors());
41
+ app.use(cors(corsOptions));
34
42
  app.use(express.json());
35
43
 
36
44
  // Serve Angular build files