metacoding 1.5.1 → 2.0.1

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 (95) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +108 -514
  3. package/lib/cli.d.ts.map +1 -1
  4. package/lib/cli.js +18 -19
  5. package/lib/cli.js.map +1 -1
  6. package/lib/commands/init.d.ts +8 -14
  7. package/lib/commands/init.d.ts.map +1 -1
  8. package/lib/commands/init.js +105 -387
  9. package/lib/commands/init.js.map +1 -1
  10. package/lib/commands/update.d.ts +9 -9
  11. package/lib/commands/update.d.ts.map +1 -1
  12. package/lib/commands/update.js +141 -320
  13. package/lib/commands/update.js.map +1 -1
  14. package/lib/services/backup.d.ts +1 -1
  15. package/lib/services/backup.d.ts.map +1 -1
  16. package/lib/services/backup.js +10 -6
  17. package/lib/services/backup.js.map +1 -1
  18. package/lib/services/filesystem.d.ts.map +1 -1
  19. package/lib/services/filesystem.js +11 -5
  20. package/lib/services/filesystem.js.map +1 -1
  21. package/lib/services/gitignore-manager.js +5 -5
  22. package/lib/services/gitignore-manager.js.map +1 -1
  23. package/lib/services/project-detector.d.ts +9 -8
  24. package/lib/services/project-detector.d.ts.map +1 -1
  25. package/lib/services/project-detector.js +79 -197
  26. package/lib/services/project-detector.js.map +1 -1
  27. package/lib/services/skill-manager.d.ts +23 -0
  28. package/lib/services/skill-manager.d.ts.map +1 -0
  29. package/lib/services/skill-manager.js +212 -0
  30. package/lib/services/skill-manager.js.map +1 -0
  31. package/lib/types/index.d.ts +5 -15
  32. package/lib/types/index.d.ts.map +1 -1
  33. package/package.json +9 -17
  34. package/skills/metacoding-workflow/SKILL.md +52 -0
  35. package/skills/metacoding-workflow/agents/openai.yaml +4 -0
  36. package/skills/metacoding-workflow/assets/templates/changelog-entry.md +6 -0
  37. package/skills/metacoding-workflow/assets/templates/project-context.md +18 -0
  38. package/skills/metacoding-workflow/assets/templates/repeated-task-checklist.md +8 -0
  39. package/skills/metacoding-workflow/assets/templates/task-entry.md +9 -0
  40. package/skills/metacoding-workflow/assets/templates/test-plan.md +8 -0
  41. package/skills/metacoding-workflow/references/javascript.md +7 -0
  42. package/skills/metacoding-workflow/references/node.md +7 -0
  43. package/skills/metacoding-workflow/references/platform-adaptation.md +37 -0
  44. package/skills/metacoding-workflow/references/python.md +7 -0
  45. package/skills/metacoding-workflow/references/react.md +7 -0
  46. package/skills/metacoding-workflow/references/repository-organization.md +84 -0
  47. package/skills/metacoding-workflow/references/typescript.md +7 -0
  48. package/skills/metacoding-workflow/references/workflow-rules.md +54 -0
  49. package/skills/vendor-templates/claude-agent.md.template +41 -0
  50. package/lib/services/assistant-adapter.d.ts +0 -18
  51. package/lib/services/assistant-adapter.d.ts.map +0 -1
  52. package/lib/services/assistant-adapter.js +0 -246
  53. package/lib/services/assistant-adapter.js.map +0 -1
  54. package/lib/services/cursor.d.ts +0 -47
  55. package/lib/services/cursor.d.ts.map +0 -1
  56. package/lib/services/cursor.js +0 -314
  57. package/lib/services/cursor.js.map +0 -1
  58. package/lib/services/template-manager.d.ts +0 -23
  59. package/lib/services/template-manager.d.ts.map +0 -1
  60. package/lib/services/template-manager.js +0 -374
  61. package/lib/services/template-manager.js.map +0 -1
  62. package/lib/services/vscode.d.ts +0 -10
  63. package/lib/services/vscode.d.ts.map +0 -1
  64. package/lib/services/vscode.js +0 -108
  65. package/lib/services/vscode.js.map +0 -1
  66. package/templates/assistants/AGENTS.md +0 -203
  67. package/templates/assistants/CLAUDE.md +0 -156
  68. package/templates/assistants/GEMINI.md +0 -193
  69. package/templates/general/code-review.instructions.md +0 -265
  70. package/templates/general/copilot-instructions.md +0 -427
  71. package/templates/general/docs-update.instructions.md +0 -275
  72. package/templates/general/release.instructions.md +0 -242
  73. package/templates/general/template.json +0 -9
  74. package/templates/general/test-runner.instructions.md +0 -188
  75. package/templates/javascript/javascript.coding.instructions.md +0 -500
  76. package/templates/javascript/javascript.docs.instructions.md +0 -563
  77. package/templates/javascript/javascript.testing.instructions.md +0 -686
  78. package/templates/javascript/template.json +0 -36
  79. package/templates/node/nodejs.coding.instructions.md +0 -249
  80. package/templates/node/nodejs.docs.instructions.md +0 -261
  81. package/templates/node/nodejs.testing.instructions.md +0 -373
  82. package/templates/node/template.json +0 -23
  83. package/templates/python/python.coding.instructions.md +0 -338
  84. package/templates/python/python.docs.instructions.md +0 -1178
  85. package/templates/python/python.testing.instructions.md +0 -1073
  86. package/templates/python/template.json +0 -75
  87. package/templates/react/react.coding.instructions.md +0 -694
  88. package/templates/react/react.docs.instructions.md +0 -451
  89. package/templates/react/react.testing.instructions.md +0 -192
  90. package/templates/react/template.json +0 -14
  91. package/templates/react/test-runner.instructions.md +0 -135
  92. package/templates/typescript/template.json +0 -16
  93. package/templates/typescript/typescript.coding.instructions.md +0 -368
  94. package/templates/typescript/typescript.docs.instructions.md +0 -760
  95. package/templates/typescript/typescript.testing.instructions.md +0 -739
@@ -1,686 +0,0 @@
1
- ---
2
- description: 'JavaScript testing strategies and frameworks for browser and Node.js environments'
3
- applyTo: 'test/**/*.{js,mjs}'
4
- ---
5
-
6
- # JavaScript Testing Guidelines
7
-
8
- ## Test Case Naming Conventions
9
-
10
- ### Test Case ID Format: `[AREA]-[TYPE]-[NUMBER]`
11
-
12
- **JavaScript/Frontend Area Prefixes:**
13
-
14
- - `DOM` - DOM manipulation and browser API tests
15
- - `UI` - User interface component tests
16
- - `EVENT` - Event handling and interaction tests
17
- - `API_CLIENT` - API client and HTTP request tests
18
- - `UTIL` - Utility function tests
19
- - `CORE` - Core application logic tests
20
- - `MODULE` - Module loading and dependency tests
21
- - `SERVER` - Server-side JavaScript tests (Node.js)
22
- - `CLI` - Command-line interface tests (Node.js)
23
- - `PKG` - Package/library functionality tests
24
-
25
- **Type Suffixes:**
26
-
27
- - `UNIT` - Unit tests (isolated function/component testing)
28
- - `INT` - Integration tests (component interaction testing)
29
- - `E2E` - End-to-end tests (full user workflow testing)
30
-
31
- **Examples:**
32
-
33
- - `DOM-UNIT-001` - First unit test for DOM manipulation
34
- - `UI-UNIT-001` - First unit test for UI component
35
- - `API_CLIENT-INT-001` - First integration test for API client
36
- - `EVENT-E2E-001` - First end-to-end event handling test
37
-
38
- ## Testing Strategy Overview
39
-
40
- ### Testing Pyramid for JavaScript
41
-
42
- - **Unit Tests (70%):** Test individual functions and modules in isolation
43
- - **Integration Tests (20%):** Test interactions between components
44
- - **End-to-End Tests (10%):** Test complete user workflows in browser/environment
45
-
46
- ### Test Framework Selection
47
-
48
- #### Primary Testing Frameworks
49
-
50
- - **Jest:** Comprehensive testing framework for unit and integration tests
51
- - **Vitest:** Fast alternative to Jest with native ES modules support
52
- - **Mocha + Chai:** Flexible testing framework with assertion library
53
- - **Cypress/Playwright:** End-to-end testing for browser applications
54
-
55
- #### Browser Testing Tools
56
-
57
- - **jsdom:** Simulate browser environment in Node.js for DOM testing
58
- - **@testing-library/dom:** Simple and complete testing utilities for DOM
59
- - **Puppeteer:** Control headless Chrome for integration testing
60
- - **WebDriver:** Cross-browser testing automation
61
-
62
- ## Jest Testing Patterns
63
-
64
- ### Basic Test Structure
65
-
66
- ```javascript
67
- // Basic test setup
68
- describe('UserService', () => {
69
- let userService;
70
- let mockDatabase;
71
-
72
- beforeEach(() => {
73
- mockDatabase = {
74
- users: {
75
- findById: jest.fn(),
76
- create: jest.fn(),
77
- update: jest.fn(),
78
- },
79
- };
80
- userService = new UserService(mockDatabase);
81
- });
82
-
83
- afterEach(() => {
84
- jest.clearAllMocks();
85
- });
86
-
87
- describe('getUserById', () => {
88
- it('should return user when found', async () => {
89
- // Arrange
90
- const userId = '123';
91
- const expectedUser = { id: userId, name: 'John Doe' };
92
- mockDatabase.users.findById.mockResolvedValue(expectedUser);
93
-
94
- // Act
95
- const result = await userService.getUserById(userId);
96
-
97
- // Assert
98
- expect(result).toEqual(expectedUser);
99
- expect(mockDatabase.users.findById).toHaveBeenCalledWith(userId);
100
- });
101
-
102
- it('should return null when user not found', async () => {
103
- // Arrange
104
- const userId = '999';
105
- mockDatabase.users.findById.mockResolvedValue(null);
106
-
107
- // Act
108
- const result = await userService.getUserById(userId);
109
-
110
- // Assert
111
- expect(result).toBeNull();
112
- });
113
-
114
- it('should handle database errors gracefully', async () => {
115
- // Arrange
116
- const userId = '123';
117
- const dbError = new Error('Database connection failed');
118
- mockDatabase.users.findById.mockRejectedValue(dbError);
119
-
120
- // Act
121
- const result = await userService.getUserById(userId);
122
-
123
- // Assert
124
- expect(result).toBeNull();
125
- });
126
- });
127
- });
128
- ```
129
-
130
- ### Testing Async Code
131
-
132
- ```javascript
133
- // Testing promises and async/await
134
- describe('API Client', () => {
135
- let apiClient;
136
- let mockFetch;
137
-
138
- beforeEach(() => {
139
- mockFetch = jest.fn();
140
- global.fetch = mockFetch;
141
- apiClient = new ApiClient('https://api.example.com');
142
- });
143
-
144
- afterEach(() => {
145
- global.fetch.mockRestore();
146
- });
147
-
148
- it('should fetch user data successfully', async () => {
149
- // Arrange
150
- const userData = { id: 1, name: 'John' };
151
- mockFetch.mockResolvedValue({
152
- ok: true,
153
- json: jest.fn().mockResolvedValue(userData),
154
- });
155
-
156
- // Act
157
- const result = await apiClient.getUser(1);
158
-
159
- // Assert
160
- expect(result).toEqual(userData);
161
- expect(mockFetch).toHaveBeenCalledWith('https://api.example.com/users/1');
162
- });
163
-
164
- it('should handle HTTP errors', async () => {
165
- // Arrange
166
- mockFetch.mockResolvedValue({
167
- ok: false,
168
- status: 404,
169
- statusText: 'Not Found',
170
- });
171
-
172
- // Act & Assert
173
- await expect(apiClient.getUser(999)).rejects.toThrow(
174
- 'HTTP error! status: 404'
175
- );
176
- });
177
-
178
- it('should handle network errors', async () => {
179
- // Arrange
180
- const networkError = new Error('Network error');
181
- mockFetch.mockRejectedValue(networkError);
182
-
183
- // Act & Assert
184
- await expect(apiClient.getUser(1)).rejects.toThrow('Network error');
185
- });
186
- });
187
- ```
188
-
189
- ### Mocking and Spying
190
-
191
- ```javascript
192
- // Module mocking
193
- jest.mock('./logger', () => ({
194
- log: jest.fn(),
195
- error: jest.fn(),
196
- }));
197
-
198
- // Partial mocking
199
- jest.mock('./config', () => ({
200
- ...jest.requireActual('./config'),
201
- apiUrl: 'http://test-api.example.com',
202
- }));
203
-
204
- // Spy on methods
205
- describe('Analytics Service', () => {
206
- it('should track user actions', () => {
207
- const analytics = new AnalyticsService();
208
- const trackSpy = jest.spyOn(analytics, 'track');
209
-
210
- analytics.trackUserLogin('user123');
211
-
212
- expect(trackSpy).toHaveBeenCalledWith('user_login', { userId: 'user123' });
213
-
214
- trackSpy.mockRestore();
215
- });
216
- });
217
-
218
- // Timer mocking
219
- describe('Debounced Function', () => {
220
- beforeEach(() => {
221
- jest.useFakeTimers();
222
- });
223
-
224
- afterEach(() => {
225
- jest.runOnlyPendingTimers();
226
- jest.useRealTimers();
227
- });
228
-
229
- it('should debounce function calls', () => {
230
- const mockFn = jest.fn();
231
- const debouncedFn = debounce(mockFn, 100);
232
-
233
- debouncedFn();
234
- debouncedFn();
235
- debouncedFn();
236
-
237
- expect(mockFn).not.toHaveBeenCalled();
238
-
239
- jest.advanceTimersByTime(100);
240
-
241
- expect(mockFn).toHaveBeenCalledTimes(1);
242
- });
243
- });
244
- ```
245
-
246
- ## DOM Testing with jsdom
247
-
248
- ### Testing DOM Manipulation
249
-
250
- ```javascript
251
- /**
252
- * @jest-environment jsdom
253
- */
254
-
255
- describe('DOM Utilities', () => {
256
- beforeEach(() => {
257
- document.body.innerHTML = '';
258
- });
259
-
260
- it('should create and append element', () => {
261
- // Arrange
262
- const container = document.createElement('div');
263
- document.body.appendChild(container);
264
-
265
- // Act
266
- const element = createButton('Click me', 'btn-primary');
267
- container.appendChild(element);
268
-
269
- // Assert
270
- expect(container.children).toHaveLength(1);
271
- expect(container.firstChild.textContent).toBe('Click me');
272
- expect(container.firstChild.className).toBe('btn-primary');
273
- });
274
-
275
- it('should handle click events', () => {
276
- // Arrange
277
- const mockHandler = jest.fn();
278
- const button = document.createElement('button');
279
- button.addEventListener('click', mockHandler);
280
- document.body.appendChild(button);
281
-
282
- // Act
283
- button.click();
284
-
285
- // Assert
286
- expect(mockHandler).toHaveBeenCalledTimes(1);
287
- });
288
-
289
- it('should update element content', () => {
290
- // Arrange
291
- document.body.innerHTML = '<div id="counter">0</div>';
292
- const counter = document.getElementById('counter');
293
-
294
- // Act
295
- updateCounter(counter, 5);
296
-
297
- // Assert
298
- expect(counter.textContent).toBe('5');
299
- });
300
- });
301
- ```
302
-
303
- ### Testing with @testing-library
304
-
305
- ```javascript
306
- import { fireEvent, screen } from '@testing-library/dom';
307
- import '@testing-library/jest-dom';
308
-
309
- describe('Form Component', () => {
310
- beforeEach(() => {
311
- document.body.innerHTML = `
312
- <form id="login-form">
313
- <input type="email" id="email" placeholder="Email" />
314
- <input type="password" id="password" placeholder="Password" />
315
- <button type="submit">Login</button>
316
- </form>
317
- `;
318
- });
319
-
320
- it('should validate email input', () => {
321
- // Arrange
322
- const emailInput = screen.getByPlaceholderText('Email');
323
-
324
- // Act
325
- fireEvent.change(emailInput, { target: { value: 'invalid-email' } });
326
- fireEvent.blur(emailInput);
327
-
328
- // Assert
329
- expect(emailInput).toHaveClass('error');
330
- });
331
-
332
- it('should submit form with valid data', () => {
333
- // Arrange
334
- const mockSubmit = jest.fn();
335
- const form = document.getElementById('login-form');
336
- form.addEventListener('submit', mockSubmit);
337
-
338
- // Act
339
- fireEvent.change(screen.getByPlaceholderText('Email'), {
340
- target: { value: 'user@example.com' },
341
- });
342
- fireEvent.change(screen.getByPlaceholderText('Password'), {
343
- target: { value: 'password123' },
344
- });
345
- fireEvent.click(screen.getByText('Login'));
346
-
347
- // Assert
348
- expect(mockSubmit).toHaveBeenCalled();
349
- });
350
- });
351
- ```
352
-
353
- ## Node.js Testing Patterns
354
-
355
- ### File System Testing
356
-
357
- ```javascript
358
- import { promises as fs } from 'fs';
359
- import path from 'path';
360
- import { tmpdir } from 'os';
361
-
362
- describe('File Service', () => {
363
- let tempDir;
364
- let fileService;
365
-
366
- beforeEach(async () => {
367
- tempDir = await fs.mkdtemp(path.join(tmpdir(), 'test-'));
368
- fileService = new FileService(tempDir);
369
- });
370
-
371
- afterEach(async () => {
372
- await fs.rmdir(tempDir, { recursive: true });
373
- });
374
-
375
- it('should create and read file', async () => {
376
- // Arrange
377
- const filename = 'test.txt';
378
- const content = 'Hello, World!';
379
-
380
- // Act
381
- await fileService.writeFile(filename, content);
382
- const result = await fileService.readFile(filename);
383
-
384
- // Assert
385
- expect(result).toBe(content);
386
- });
387
-
388
- it('should handle file not found error', async () => {
389
- // Act & Assert
390
- await expect(fileService.readFile('nonexistent.txt')).rejects.toThrow(
391
- 'File not found'
392
- );
393
- });
394
- });
395
- ```
396
-
397
- ### HTTP Server Testing
398
-
399
- ```javascript
400
- import request from 'supertest';
401
- import app from '../src/app.js';
402
-
403
- describe('API Endpoints', () => {
404
- describe('GET /api/users', () => {
405
- it('should return list of users', async () => {
406
- const response = await request(app)
407
- .get('/api/users')
408
- .expect('Content-Type', /json/)
409
- .expect(200);
410
-
411
- expect(response.body).toHaveProperty('users');
412
- expect(Array.isArray(response.body.users)).toBe(true);
413
- });
414
- });
415
-
416
- describe('POST /api/users', () => {
417
- it('should create new user', async () => {
418
- const newUser = {
419
- name: 'John Doe',
420
- email: 'john@example.com',
421
- };
422
-
423
- const response = await request(app)
424
- .post('/api/users')
425
- .send(newUser)
426
- .expect('Content-Type', /json/)
427
- .expect(201);
428
-
429
- expect(response.body).toHaveProperty('id');
430
- expect(response.body.name).toBe(newUser.name);
431
- expect(response.body.email).toBe(newUser.email);
432
- });
433
-
434
- it('should validate required fields', async () => {
435
- const invalidUser = { name: 'John Doe' }; // Missing email
436
-
437
- await request(app)
438
- .post('/api/users')
439
- .send(invalidUser)
440
- .expect('Content-Type', /json/)
441
- .expect(400);
442
- });
443
- });
444
- });
445
- ```
446
-
447
- ## End-to-End Testing
448
-
449
- ### Cypress Testing Patterns
450
-
451
- ```javascript
452
- // cypress/integration/user-workflow.spec.js
453
- describe('User Registration Flow', () => {
454
- beforeEach(() => {
455
- cy.visit('/register');
456
- });
457
-
458
- it('should complete user registration', () => {
459
- // Fill out registration form
460
- cy.get('[data-testid="email-input"]').type('user@example.com');
461
- cy.get('[data-testid="password-input"]').type('securepassword');
462
- cy.get('[data-testid="confirm-password-input"]').type('securepassword');
463
-
464
- // Submit form
465
- cy.get('[data-testid="register-button"]').click();
466
-
467
- // Verify success
468
- cy.url().should('include', '/dashboard');
469
- cy.get('[data-testid="welcome-message"]').should('contain', 'Welcome');
470
- });
471
-
472
- it('should show validation errors for invalid data', () => {
473
- cy.get('[data-testid="email-input"]').type('invalid-email');
474
- cy.get('[data-testid="register-button"]').click();
475
-
476
- cy.get('[data-testid="email-error"]').should(
477
- 'contain',
478
- 'Valid email required'
479
- );
480
- });
481
- });
482
- ```
483
-
484
- ### Playwright Testing Patterns
485
-
486
- ```javascript
487
- import { test, expect } from '@playwright/test';
488
-
489
- test.describe('Shopping Cart', () => {
490
- test.beforeEach(async ({ page }) => {
491
- await page.goto('/shop');
492
- });
493
-
494
- test('should add items to cart', async ({ page }) => {
495
- // Add item to cart
496
- await page.click('[data-testid="add-to-cart-123"]');
497
-
498
- // Verify cart badge
499
- await expect(page.locator('[data-testid="cart-count"]')).toHaveText('1');
500
-
501
- // Navigate to cart
502
- await page.click('[data-testid="cart-link"]');
503
-
504
- // Verify item in cart
505
- await expect(page.locator('[data-testid="cart-item-123"]')).toBeVisible();
506
- });
507
-
508
- test('should calculate total correctly', async ({ page }) => {
509
- await page.click('[data-testid="add-to-cart-123"]'); // $10 item
510
- await page.click('[data-testid="add-to-cart-456"]'); // $15 item
511
-
512
- await page.click('[data-testid="cart-link"]');
513
-
514
- await expect(page.locator('[data-testid="cart-total"]')).toHaveText(
515
- '$25.00'
516
- );
517
- });
518
- });
519
- ```
520
-
521
- ## Test Configuration
522
-
523
- ### Jest Configuration
524
-
525
- ```javascript
526
- // jest.config.js
527
- export default {
528
- testEnvironment: 'node',
529
- transform: {},
530
- extensionsToTreatAsEsm: ['.js'],
531
- globals: {
532
- 'ts-jest': {
533
- useESM: true,
534
- },
535
- },
536
- moduleNameMapping: {
537
- '^@/(.*)$': '<rootDir>/src/$1',
538
- },
539
- testMatch: ['<rootDir>/test/**/*.test.js', '<rootDir>/src/**/__tests__/*.js'],
540
- collectCoverageFrom: ['src/**/*.js', '!src/**/*.test.js', '!src/index.js'],
541
- coverageDirectory: 'coverage',
542
- coverageReporters: ['text', 'lcov', 'html'],
543
- setupFilesAfterEnv: ['<rootDir>/test/setup.js'],
544
- testTimeout: 10000,
545
- };
546
- ```
547
-
548
- ### Browser Test Configuration
549
-
550
- ```javascript
551
- // jest.config.browser.js
552
- export default {
553
- testEnvironment: 'jsdom',
554
- setupFilesAfterEnv: [
555
- '@testing-library/jest-dom',
556
- '<rootDir>/test/browser-setup.js',
557
- ],
558
- moduleNameMapping: {
559
- '\\.(css|less|scss|sass)$': 'identity-obj-proxy',
560
- '\\.(gif|ttf|eot|svg|png)$': '<rootDir>/test/__mocks__/fileMock.js',
561
- },
562
- transform: {
563
- '^.+\\.js$': 'babel-jest',
564
- },
565
- };
566
- ```
567
-
568
- ## Test Data Management
569
-
570
- ### Test Fixtures
571
-
572
- ```javascript
573
- // test/fixtures/users.js
574
- export const validUser = {
575
- id: '1',
576
- name: 'John Doe',
577
- email: 'john@example.com',
578
- active: true,
579
- createdAt: '2023-01-01T00:00:00Z',
580
- };
581
-
582
- export const invalidUser = {
583
- name: '',
584
- email: 'invalid-email',
585
- };
586
-
587
- export const userList = [
588
- validUser,
589
- {
590
- id: '2',
591
- name: 'Jane Smith',
592
- email: 'jane@example.com',
593
- active: false,
594
- createdAt: '2023-01-02T00:00:00Z',
595
- },
596
- ];
597
-
598
- // Test factories
599
- export function createUser(overrides = {}) {
600
- return {
601
- ...validUser,
602
- id: Math.random().toString(36).substr(2, 9),
603
- ...overrides,
604
- };
605
- }
606
- ```
607
-
608
- ### Mock Data Generators
609
-
610
- ```javascript
611
- // test/helpers/generators.js
612
- export function generateRandomUser() {
613
- return {
614
- id: Math.random().toString(36).substr(2, 9),
615
- name: `User ${Math.floor(Math.random() * 1000)}`,
616
- email: `user${Math.floor(Math.random() * 1000)}@example.com`,
617
- active: Math.random() > 0.5,
618
- createdAt: new Date().toISOString(),
619
- };
620
- }
621
-
622
- export function generateUserList(count = 10) {
623
- return Array.from({ length: count }, generateRandomUser);
624
- }
625
- ```
626
-
627
- ## Testing Best Practices
628
-
629
- ### Test Organization
630
-
631
- - **Describe blocks:** Group related tests logically
632
- - **Clear test names:** Use descriptive test names that explain the expected behavior
633
- - **Arrange-Act-Assert:** Structure tests with clear setup, execution, and verification phases
634
- - **One assertion per test:** Focus each test on a single behavior
635
- - **Test isolation:** Ensure tests don't depend on each other
636
-
637
- ### Mock Strategy
638
-
639
- - **Mock external dependencies:** Isolate units under test from external systems
640
- - **Use real objects when possible:** Prefer real implementations for simple dependencies
641
- - **Verify interactions:** Test that methods are called with correct parameters
642
- - **Clean up mocks:** Reset mocks between tests to avoid interference
643
-
644
- ### Coverage Guidelines
645
-
646
- - **Aim for high coverage:** Target 80%+ line coverage for critical code paths
647
- - **Quality over quantity:** Focus on meaningful tests rather than coverage metrics
648
- - **Test edge cases:** Include tests for error conditions and boundary values
649
- - **Integration testing:** Ensure components work together correctly
650
-
651
- ### Performance Testing
652
-
653
- ```javascript
654
- // Performance testing examples
655
- describe('Performance Tests', () => {
656
- it('should process large dataset efficiently', () => {
657
- const largeArray = new Array(10000)
658
- .fill()
659
- .map((_, i) => ({ id: i, value: i * 2 }));
660
-
661
- const start = performance.now();
662
- const result = processLargeDataset(largeArray);
663
- const end = performance.now();
664
-
665
- expect(end - start).toBeLessThan(100); // Should complete in under 100ms
666
- expect(result).toHaveLength(10000);
667
- });
668
-
669
- it('should handle memory efficiently', () => {
670
- const initialMemory = process.memoryUsage().heapUsed;
671
-
672
- const largeData = createLargeDataStructure();
673
- processData(largeData);
674
-
675
- // Force garbage collection if available
676
- if (global.gc) {
677
- global.gc();
678
- }
679
-
680
- const finalMemory = process.memoryUsage().heapUsed;
681
- const memoryIncrease = finalMemory - initialMemory;
682
-
683
- expect(memoryIncrease).toBeLessThan(50 * 1024 * 1024); // Less than 50MB increase
684
- });
685
- });
686
- ```
@@ -1,36 +0,0 @@
1
- {
2
- "name": "javascript",
3
- "description": "Modern JavaScript development template for browser and Node.js environments with ES6+, testing frameworks, and build tools",
4
- "prompts": [],
5
- "vscodeSettings": {
6
- "github.copilot.chat.codeGeneration.useInstructionFiles": true,
7
- "chat.promptFiles": true,
8
- "editor.formatOnSave": true,
9
- "editor.codeActionsOnSave": {
10
- "source.organizeImports": true,
11
- "source.fixAll.eslint": true
12
- },
13
- "javascript.preferences.inlayHints.parameterNames.enabled": "all",
14
- "javascript.preferences.inlayHints.variableTypes.enabled": true,
15
- "javascript.preferences.inlayHints.functionLikeReturnTypes.enabled": true,
16
- "files.exclude": {
17
- "**/node_modules": true,
18
- "**/dist": true,
19
- "**/build": true,
20
- "**/.nyc_output": true,
21
- "**/coverage": true,
22
- "**/public/build": true,
23
- "**/.cache": true
24
- },
25
- "search.exclude": {
26
- "**/node_modules": true,
27
- "**/dist": true,
28
- "**/build": true,
29
- "**/coverage": true
30
- },
31
- "javascript.suggest.autoImports": true,
32
- "javascript.updateImportsOnFileMove.enabled": "always",
33
- "eslint.enable": true,
34
- "eslint.format.enable": true
35
- }
36
- }