symfonia-ai-tools 1.0.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 (74) hide show
  1. package/README.md +489 -0
  2. package/bin/cli.mjs +35 -0
  3. package/lib/installer.mjs +495 -0
  4. package/lib/questions.mjs +332 -0
  5. package/lib/ui.mjs +76 -0
  6. package/lib/utils.mjs +231 -0
  7. package/package.json +26 -0
  8. package/templates/base/CLAUDE.md +34 -0
  9. package/templates/base/_ai/_guidelines_header.md +70 -0
  10. package/templates/base/_ai/context/README.md +20 -0
  11. package/templates/base/_ai/prompts/codereview.prompt.md +324 -0
  12. package/templates/base/_ai/prompts/duplicate-code-analysis.prompt.md +128 -0
  13. package/templates/base/_ai/prompts/figma-analysis.prompt.md +155 -0
  14. package/templates/base/_ai/prompts/security-review.prompt.md +46 -0
  15. package/templates/base/_ai/skills/README.md +80 -0
  16. package/templates/base/_ai/skills/TEMPLATE.md +106 -0
  17. package/templates/base/_ai/skills/babysit-prs/SKILL.md +105 -0
  18. package/templates/base/_ai/skills/debug/SKILL.md +93 -0
  19. package/templates/base/_ai/skills/fill-worklogs/SKILL.md +158 -0
  20. package/templates/base/_ai/skills/hotfix/SKILL.md +52 -0
  21. package/templates/base/_ai/skills/jira-task/SKILL.md +170 -0
  22. package/templates/base/_ai/skills/my-prs/SKILL.md +78 -0
  23. package/templates/base/_ai/skills/pr-dashboard/SKILL.md +43 -0
  24. package/templates/base/_ai/skills/pr-prepare/SKILL.md +106 -0
  25. package/templates/base/_ai/skills/refactor/SKILL.md +87 -0
  26. package/templates/base/_ai/skills/write-tests/SKILL.md +109 -0
  27. package/templates/base/_claude/settings.local.json +37 -0
  28. package/templates/base/_cursor/rules/global.mdc +7 -0
  29. package/templates/base/_editorconfig +18 -0
  30. package/templates/base/_gemini/settings.json +3 -0
  31. package/templates/base/_github/copilot-instructions.md +1 -0
  32. package/templates/base/_github/pull_request_template.md +23 -0
  33. package/templates/base/_gitignore +22 -0
  34. package/templates/base/_junie/guidelines.md +1 -0
  35. package/templates/base/commit-instructions.md +92 -0
  36. package/templates/packs/docker/_ai/instructions/docker.instructions.md +193 -0
  37. package/templates/packs/docker/_guidelines.md +10 -0
  38. package/templates/packs/docker/pack.json +8 -0
  39. package/templates/packs/laravel/_ai/instructions/api-resource.instructions.md +251 -0
  40. package/templates/packs/laravel/_ai/instructions/module.instructions.md +133 -0
  41. package/templates/packs/laravel/_ai/instructions/service-repository.instructions.md +215 -0
  42. package/templates/packs/laravel/_ai/instructions/testing.instructions.md +278 -0
  43. package/templates/packs/laravel/_ai/skills/migration/SKILL.md +172 -0
  44. package/templates/packs/laravel/_ai/skills/new-endpoint/SKILL.md +165 -0
  45. package/templates/packs/laravel/_ai/skills/new-module/SKILL.md +208 -0
  46. package/templates/packs/laravel/_ai/skills/queued-job/SKILL.md +248 -0
  47. package/templates/packs/laravel/_ai/skills/testing-feature/SKILL.md +196 -0
  48. package/templates/packs/laravel/_ai/skills/testing-manual/SKILL.md +186 -0
  49. package/templates/packs/laravel/_ai/skills/testing-unit/SKILL.md +200 -0
  50. package/templates/packs/laravel/_guidelines.md +25 -0
  51. package/templates/packs/laravel/pack.json +6 -0
  52. package/templates/packs/playwright/_ai/instructions/playwright.instructions.md +219 -0
  53. package/templates/packs/playwright/_ai/skills/playwright/README.md +194 -0
  54. package/templates/packs/playwright/_ai/skills/playwright/SKILL.md +1245 -0
  55. package/templates/packs/playwright/_ai/skills/playwright-codereview/SKILL.md +642 -0
  56. package/templates/packs/playwright/_ai/skills/playwright-record/README.md +87 -0
  57. package/templates/packs/playwright/_ai/skills/playwright-record/SKILL.md +564 -0
  58. package/templates/packs/playwright/_guidelines.md +12 -0
  59. package/templates/packs/playwright/pack.json +9 -0
  60. package/templates/packs/storybook/_ai/instructions/storybook.instructions.md +181 -0
  61. package/templates/packs/storybook/pack.json +6 -0
  62. package/templates/packs/vitest/_ai/instructions/vitest.instructions.md +688 -0
  63. package/templates/packs/vitest/pack.json +6 -0
  64. package/templates/packs/vue3/_ai/instructions/api.instructions.md +163 -0
  65. package/templates/packs/vue3/_ai/instructions/coding-conventions.instructions.md +160 -0
  66. package/templates/packs/vue3/_ai/instructions/composables.instructions.md +218 -0
  67. package/templates/packs/vue3/_ai/instructions/forms.instructions.md +227 -0
  68. package/templates/packs/vue3/_ai/instructions/store.instructions.md +504 -0
  69. package/templates/packs/vue3/_ai/instructions/vue.instructions.md +339 -0
  70. package/templates/packs/vue3/_ai/skills/api-integration/SKILL.md +195 -0
  71. package/templates/packs/vue3/_ai/skills/new-component/SKILL.md +133 -0
  72. package/templates/packs/vue3/_ai/skills/new-module/SKILL.md +177 -0
  73. package/templates/packs/vue3/_guidelines.md +45 -0
  74. package/templates/packs/vue3/pack.json +11 -0
@@ -0,0 +1,688 @@
1
+ ---
2
+ applyTo: "**/*.test.ts,**/*.spec.ts"
3
+ ---
4
+
5
+ # VITEST Testing Instructions
6
+
7
+ ## Table of Contents
8
+
9
+ 1. [Test Structure and Organization](#test-structure-and-organization)
10
+ 2. [Test Naming and Descriptions](#test-naming-and-descriptions)
11
+ 3. [Test Setup and Configuration](#test-setup-and-configuration)
12
+ 4. [Component Testing Patterns](#component-testing-patterns)
13
+ 5. [Test Coverage Requirements](#test-coverage-requirements)
14
+ 6. [Performance and Best Practices](#performance-and-best-practices)
15
+ 7. [Mocking and Stubbing](#mocking-and-stubbing)
16
+ 8. [Accessibility Testing](#accessibility-testing)
17
+ 9. [State and Event Testing](#state-and-event-testing)
18
+ 10. [Test Documentation](#test-documentation)
19
+
20
+ ---
21
+
22
+ ## Test Structure and Organization
23
+
24
+ ### File Organization
25
+ - Place test files next to the component: `ComponentName.test.ts`
26
+ - Use descriptive test file names: `InputText.test.ts`, `Button.test.ts`
27
+ - Group related tests in `describe` blocks
28
+ - Use nested `describe` blocks for logical grouping
29
+
30
+ ### Test Structure Template
31
+ ```typescript
32
+ import { mount, VueWrapper } from '@vue/test-utils';
33
+ import { beforeEach, describe, expect, it } from 'vitest';
34
+ import ComponentName from './ComponentName.vue';
35
+
36
+ describe('ComponentName Component', () => {
37
+ let wrapper: VueWrapper<InstanceType<typeof ComponentName>>;
38
+
39
+ beforeEach(() => {
40
+ wrapper = mount(ComponentName, {
41
+ props: {
42
+ // Required props only
43
+ dataTestId: 'test-component',
44
+ },
45
+ });
46
+ });
47
+
48
+ describe('Basic Rendering', () => {
49
+ // Basic rendering tests
50
+ });
51
+
52
+ describe('Props Testing', () => {
53
+ // Props validation tests
54
+ });
55
+
56
+ describe('States', () => {
57
+ // State-based tests (disabled, error, loading, etc.)
58
+ });
59
+
60
+ describe('Event Handling', () => {
61
+ // Event emission and handling tests
62
+ });
63
+
64
+ describe('Accessibility', () => {
65
+ // Accessibility tests
66
+ });
67
+
68
+ describe('Edge Cases', () => {
69
+ // Edge case and error handling tests
70
+ });
71
+
72
+ describe('Component Integration', () => {
73
+ // Complex integration tests
74
+ });
75
+ });
76
+ ```
77
+
78
+ ---
79
+
80
+ ## Test Naming and Descriptions
81
+
82
+ ### Test Naming Conventions
83
+ - Use descriptive test names that explain the expected behavior
84
+ - Start with "should" for behavior descriptions
85
+ - Use present tense: "should render correctly" not "should have rendered"
86
+ - Be specific about conditions: "should be disabled when disabled prop is true"
87
+
88
+ ### Good Test Names Examples
89
+ ```typescript
90
+ it('should render input element', () => {});
91
+ it('should have correct name attribute', () => {});
92
+ it('should be disabled when disabled prop is true', () => {});
93
+ it('should emit click event when clicked', () => {});
94
+ it('should handle null modelValue gracefully', () => {});
95
+ it('should apply error class when error prop is true', () => {});
96
+ ```
97
+
98
+ ### Bad Test Names Examples
99
+ ```typescript
100
+ it('works', () => {}); // Too vague
101
+ it('test input', () => {}); // Not descriptive
102
+ it('should have rendered', () => {}); // Past tense
103
+ it('input test', () => {}); // Not a sentence
104
+ ```
105
+
106
+ ---
107
+
108
+ ## Test Setup and Configuration
109
+
110
+ ### Required Imports
111
+ ```typescript
112
+ import { mount, VueWrapper } from '@vue/test-utils';
113
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
114
+ import { nextTick } from 'vue'; // When needed for async operations
115
+ ```
116
+
117
+ ### Component Mounting
118
+ - Always provide required props in `beforeEach`
119
+ - Use `dataTestId` for test identification
120
+ - Set up minimal required props only
121
+ - Use `VueWrapper<InstanceType<typeof Component>>` for type safety
122
+
123
+ ### Test Configuration
124
+ ```typescript
125
+ beforeEach(() => {
126
+ wrapper = mount(ComponentName, {
127
+ props: {
128
+ // Only required props
129
+ name: 'test-component',
130
+ dataTestId: 'test-component',
131
+ },
132
+ // Add slots if needed
133
+ slots: {
134
+ default: 'Test Content',
135
+ },
136
+ // Add global plugins if needed
137
+ global: {
138
+ plugins: [i18n, router],
139
+ },
140
+ });
141
+ });
142
+ ```
143
+
144
+ ---
145
+
146
+ ## Component Testing Patterns
147
+
148
+ ### Basic Rendering Tests
149
+ Test fundamental component structure and attributes:
150
+ ```typescript
151
+ describe('Basic Rendering', () => {
152
+ it('should render main element', () => {
153
+ expect(wrapper.element.tagName).toBe('BUTTON');
154
+ });
155
+
156
+ it('should have correct data-testid attribute', () => {
157
+ expect(wrapper.attributes('data-testid')).toBe('test-button');
158
+ });
159
+
160
+ it('should have base CSS class', () => {
161
+ expect(wrapper.classes()).toContain('button');
162
+ });
163
+ });
164
+ ```
165
+
166
+ ### Props Testing
167
+ Test all component props systematically:
168
+ ```typescript
169
+ describe('Props Testing', () => {
170
+ it('should set type attribute correctly', async () => {
171
+ await wrapper.setProps({ type: 'email' });
172
+ const input = wrapper.find('input');
173
+ expect(input.attributes('type')).toBe('email');
174
+ });
175
+
176
+ it('should default to text type', () => {
177
+ const input = wrapper.find('input');
178
+ expect(input.attributes('type')).toBe('text');
179
+ });
180
+
181
+ it('should handle null values gracefully', async () => {
182
+ await wrapper.setProps({ icon: null });
183
+ expect(wrapper.find('.icon').exists()).toBe(false);
184
+ });
185
+ });
186
+ ```
187
+
188
+ ### State Testing
189
+ Test component states (disabled, error, loading, etc.):
190
+ ```typescript
191
+ describe('States', () => {
192
+ it('should be disabled when disabled prop is true', async () => {
193
+ await wrapper.setProps({ disabled: true });
194
+ expect(wrapper.attributes('disabled')).toBeDefined();
195
+ expect(wrapper.classes()).toContain('is-disabled');
196
+ });
197
+
198
+ it('should have error class when error prop is true', async () => {
199
+ await wrapper.setProps({ error: true });
200
+ expect(wrapper.classes()).toContain('is-error');
201
+ });
202
+ });
203
+ ```
204
+
205
+ ### Event Testing
206
+ Test event emission and handling:
207
+ ```typescript
208
+ describe('Event Handling', () => {
209
+ it('should emit click event when clicked', async () => {
210
+ await wrapper.trigger('click');
211
+ expect(wrapper.emitted('click')).toBeTruthy();
212
+ expect(wrapper.emitted('click')).toHaveLength(1);
213
+ });
214
+
215
+ it('should not emit click event when disabled', async () => {
216
+ await wrapper.setProps({ disabled: true });
217
+ await wrapper.trigger('click');
218
+ expect(wrapper.emitted('click')).toBeFalsy();
219
+ });
220
+ });
221
+ ```
222
+
223
+ ---
224
+
225
+ ## Test Coverage Requirements
226
+
227
+ ### Required Test Categories
228
+ Every component must have tests for:
229
+
230
+ 1. **Basic Rendering** - Element structure, attributes, classes
231
+ 2. **Props Testing** - All props, default values, null handling
232
+ 3. **States** - Disabled, error, loading, required states
233
+ 4. **Event Handling** - Click, input, change events
234
+ 5. **Accessibility** - ARIA attributes, keyboard navigation
235
+ 6. **Edge Cases** - Null values, empty strings, boundary conditions
236
+ 7. **Component Integration** - Complex prop combinations
237
+
238
+ ### Coverage Targets
239
+ - **100% line coverage** for all components in authentication and security-critical modules (login, password reset, registration)
240
+ - **Minimum 90% line coverage** for all other components
241
+ - **100% coverage** for critical business logic, composables, and services
242
+ - **All public props and events** must be tested
243
+ - **All conditional rendering** must be tested
244
+
245
+ ---
246
+
247
+ ## Performance and Best Practices
248
+
249
+ ### Test Performance
250
+ - Use `beforeEach` for common setup
251
+ - Avoid unnecessary DOM queries
252
+ - Use `async/await` for prop changes
253
+ - Use `nextTick()` for DOM updates after reactive changes
254
+
255
+ ### Critical: Always use await nextTick() after setProps
256
+ When testing Vue components, **always use `await nextTick()` after `setProps()`** when checking DOM changes or styles:
257
+
258
+ ```typescript
259
+ import { nextTick } from 'vue';
260
+
261
+ // CORRECT: Use await nextTick() after setProps
262
+ it('should update DOM when prop changes', async () => {
263
+ await wrapper.setProps({ disabled: true });
264
+ await nextTick(); // Wait for Vue to update DOM
265
+ expect(wrapper.attributes('disabled')).toBeDefined();
266
+ });
267
+
268
+ it('should apply correct styles after prop change', async () => {
269
+ await wrapper.setProps({ items: newItems });
270
+ await nextTick(); // Wait for computed properties and DOM updates
271
+ const items = wrapper.findAll('.grid-item');
272
+ expect(items).toHaveLength(2);
273
+ });
274
+
275
+ // WRONG: Missing await nextTick() - test may fail intermittently
276
+ it('should update DOM when prop changes', async () => {
277
+ await wrapper.setProps({ disabled: true });
278
+ // Missing nextTick() - DOM may not be updated yet!
279
+ expect(wrapper.attributes('disabled')).toBeDefined();
280
+ });
281
+ ```
282
+
283
+ **Why is this important?**
284
+ - `await wrapper.setProps()` triggers Vue's reactivity system
285
+ - Computed properties, watchers, and DOM updates happen in the **next tick**
286
+ - Without `await nextTick()`, tests check DOM before Vue finishes rendering
287
+ - This causes intermittent test failures that are hard to debug
288
+
289
+ ### Best Practices
290
+ ```typescript
291
+ // Good: Use async/await for prop changes
292
+ it('should update when prop changes', async () => {
293
+ await wrapper.setProps({ disabled: true });
294
+ expect(wrapper.attributes('disabled')).toBeDefined();
295
+ });
296
+
297
+ // Good: Use nextTick for DOM updates
298
+ it('should update DOM after value change', async () => {
299
+ await wrapper.setProps({ modelValue: 'new value' });
300
+ await nextTick();
301
+ expect(wrapper.find('input').element.value).toBe('new value');
302
+ });
303
+
304
+ // Bad: Don't forget await
305
+ it('should update when prop changes', () => {
306
+ wrapper.setProps({ disabled: true }); // Missing await
307
+ expect(wrapper.attributes('disabled')).toBeDefined();
308
+ });
309
+ ```
310
+
311
+ ### Test Isolation
312
+ - Each test should be independent
313
+ - Use `beforeEach` for setup, not shared state
314
+ - Clean up after tests if needed
315
+ - Don't rely on test execution order
316
+
317
+ ---
318
+
319
+ ## Mocking and Stubbing
320
+
321
+ ### Component Mocking
322
+ Mock external components and dependencies:
323
+ ```typescript
324
+ // Mock external components
325
+ vi.mock('{{COMPONENT_LIB_IMPORT}}', () => ({
326
+ Button: {
327
+ name: 'Button',
328
+ template: '<button class="button-mock"><slot /></button>',
329
+ props: ['variant', 'icon', 'dataTestId'],
330
+ emits: ['click'],
331
+ },
332
+ }));
333
+
334
+ // Mock third-party libraries
335
+ vi.mock('ag-grid-vue3', () => ({
336
+ AgGridVue: {
337
+ name: 'AgGridVue',
338
+ template: '<div class="ag-grid-mock"></div>',
339
+ props: ['rowData', 'columnDefs'],
340
+ },
341
+ }));
342
+ ```
343
+
344
+ ### Global Mocks
345
+ Set up global mocks in test setup:
346
+ ```typescript
347
+ // Mock window.matchMedia
348
+ Object.defineProperty(window, 'matchMedia', {
349
+ writable: true,
350
+ value: vi.fn().mockImplementation((query: string) => ({
351
+ matches: false,
352
+ media: query,
353
+ onchange: null,
354
+ addListener: vi.fn(),
355
+ removeListener: vi.fn(),
356
+ })),
357
+ });
358
+
359
+ // Mock ResizeObserver
360
+ global.ResizeObserver = vi.fn().mockImplementation(() => ({
361
+ observe: vi.fn(),
362
+ unobserve: vi.fn(),
363
+ disconnect: vi.fn(),
364
+ }));
365
+ ```
366
+
367
+ ### API and Service Mocking
368
+ ```typescript
369
+ // Mock API calls
370
+ vi.mock('{{MODULE_PATH}}/services/api', () => ({
371
+ fetchData: vi.fn().mockResolvedValue({ data: [] }),
372
+ postData: vi.fn().mockResolvedValue({ success: true }),
373
+ }));
374
+
375
+ // Mock composables
376
+ vi.mock('@/composables/useApi', () => ({
377
+ useApi: () => ({
378
+ loading: ref(false),
379
+ error: ref(null),
380
+ data: ref([]),
381
+ fetch: vi.fn(),
382
+ }),
383
+ }));
384
+ ```
385
+
386
+ ---
387
+
388
+ ## Accessibility Testing
389
+
390
+ ### Required Accessibility Tests
391
+ Every component must test **actual** accessibility features (not just data-testid):
392
+
393
+ ```typescript
394
+ describe('Accessibility', () => {
395
+ it('should have required attribute when required is true', async () => {
396
+ await wrapper.setProps({ required: true });
397
+ const input = wrapper.find('input');
398
+ expect(input.attributes('required')).toBeDefined();
399
+ });
400
+
401
+ it('should have disabled attribute when disabled is true', async () => {
402
+ await wrapper.setProps({ disabled: true });
403
+ const input = wrapper.find('input');
404
+ expect(input.attributes('disabled')).toBeDefined();
405
+ });
406
+
407
+ it('should have aria-hidden on decorative icons', async () => {
408
+ await wrapper.setProps({ icon: 'search' });
409
+ const icon = wrapper.find('.icon');
410
+ expect(icon.attributes('aria-hidden')).toBe('true');
411
+ });
412
+
413
+ it('should have proper aria-label for screen readers', () => {
414
+ const button = wrapper.find('button');
415
+ expect(button.attributes('aria-label')).toBe('Submit form');
416
+ });
417
+ });
418
+ ```
419
+
420
+ ### Important: Accessibility vs Component Integration
421
+ **Do not confuse accessibility tests with component integration tests:**
422
+
423
+ ```typescript
424
+ // BAD: This is NOT an accessibility test
425
+ describe('Accessibility', () => {
426
+ it('should have data-testid', () => {
427
+ expect(wrapper.attributes('data-testid')).toBe('test-component');
428
+ });
429
+
430
+ it('should pass props to child components', () => {
431
+ const child = wrapper.findComponent(ChildComponent);
432
+ expect(child.props('data')).toBeDefined();
433
+ });
434
+ });
435
+
436
+ // GOOD: Rename to Component Integration
437
+ describe('Component Integration', () => {
438
+ it('should have proper data-testid for testing', () => {
439
+ expect(wrapper.attributes('data-testid')).toBe('test-component');
440
+ });
441
+
442
+ it('should pass item data to child components', () => {
443
+ const child = wrapper.findComponent(ChildComponent);
444
+ expect(child.props('item')).toEqual(mockData);
445
+ });
446
+ });
447
+ ```
448
+
449
+ ### ARIA Testing
450
+ - Test `aria-hidden` on decorative elements
451
+ - Test `aria-label` and `aria-describedby`
452
+ - Test `role` attributes where applicable
453
+ - Test keyboard navigation support (Tab, Enter, Escape)
454
+ - Test focus management
455
+
456
+ ---
457
+
458
+ ## State and Event Testing
459
+
460
+ ### v-model Testing
461
+ Test two-way data binding:
462
+ ```typescript
463
+ describe('v-model Functionality', () => {
464
+ it('should update modelValue when input value changes', async () => {
465
+ const input = wrapper.find('input');
466
+ await input.setValue('test value');
467
+ expect(wrapper.vm.modelValue).toBe('test value');
468
+ });
469
+
470
+ it('should update input value when modelValue changes', async () => {
471
+ await wrapper.setProps({ modelValue: 'new value' });
472
+ const input = wrapper.find('input');
473
+ expect(input.element.value).toBe('new value');
474
+ });
475
+
476
+ it('should handle null modelValue', async () => {
477
+ await wrapper.setProps({ modelValue: null });
478
+ const input = wrapper.find('input');
479
+ expect(input.element.value).toBe('');
480
+ });
481
+ });
482
+ ```
483
+
484
+ ### Event Emission Testing
485
+ ```typescript
486
+ describe('Event Handling', () => {
487
+ it('should emit update:modelValue with correct value', async () => {
488
+ const input = wrapper.find('input');
489
+ await input.setValue('test');
490
+ await input.trigger('input');
491
+
492
+ expect(wrapper.emitted('update:modelValue')).toBeTruthy();
493
+ expect(wrapper.emitted('update:modelValue')?.[0]).toEqual(['test']);
494
+ });
495
+
496
+ it('should emit multiple events in sequence', async () => {
497
+ await wrapper.trigger('click');
498
+ await wrapper.trigger('focus');
499
+
500
+ expect(wrapper.emitted('click')).toHaveLength(1);
501
+ expect(wrapper.emitted('focus')).toHaveLength(1);
502
+ });
503
+ });
504
+ ```
505
+
506
+ ---
507
+
508
+ ## Test Documentation
509
+
510
+ ### Test Comments
511
+ - Add comments for complex test logic
512
+ - Explain why certain assertions are needed
513
+ - Document edge cases and their reasoning
514
+
515
+ ### Test Organization
516
+ ```typescript
517
+ describe('ComponentName Component', () => {
518
+ // Basic functionality tests
519
+ describe('Basic Rendering', () => {
520
+ // Tests for fundamental component structure
521
+ });
522
+
523
+ // Props and configuration tests
524
+ describe('Props Testing', () => {
525
+ // Tests for all component props
526
+ });
527
+
528
+ // State-based behavior tests
529
+ describe('States', () => {
530
+ // Tests for different component states
531
+ });
532
+
533
+ // User interaction tests
534
+ describe('Event Handling', () => {
535
+ // Tests for user interactions and events
536
+ });
537
+
538
+ // Accessibility compliance tests
539
+ describe('Accessibility', () => {
540
+ // Tests for accessibility features
541
+ });
542
+
543
+ // Error handling and edge cases
544
+ describe('Edge Cases', () => {
545
+ // Tests for boundary conditions and error states
546
+ });
547
+
548
+ // Complex integration scenarios
549
+ describe('Component Integration', () => {
550
+ // Tests for complex prop combinations and interactions
551
+ });
552
+ });
553
+ ```
554
+
555
+ ### Test Documentation Requirements
556
+ - Each test file should have a clear purpose
557
+ - Complex test logic should be documented
558
+ - Edge cases should be explained
559
+ - Integration tests should describe the scenario
560
+
561
+ ---
562
+
563
+ ## Testing Checklist
564
+
565
+ ### Before Writing Tests
566
+ - [ ] Understand component requirements and props
567
+ - [ ] Identify all public API (props, events, slots)
568
+ - [ ] Plan test structure and organization
569
+ - [ ] Identify dependencies to mock
570
+
571
+ ### During Test Writing
572
+ - [ ] Test all props with valid and invalid values
573
+ - [ ] Test all component states (disabled, error, loading)
574
+ - [ ] Test all event emissions
575
+ - [ ] Test accessibility features
576
+ - [ ] Test edge cases and error conditions
577
+ - [ ] Use descriptive test names
578
+ - [ ] Follow async/await patterns
579
+
580
+ ### After Writing Tests
581
+ - [ ] Run tests to ensure they pass
582
+ - [ ] Check test coverage meets requirements
583
+ - [ ] Verify tests are independent and isolated
584
+ - [ ] Review test names for clarity
585
+ - [ ] Ensure all edge cases are covered
586
+
587
+ ### Quality Gates
588
+ - [ ] All tests pass consistently
589
+ - [ ] Test coverage >= 80%
590
+ - [ ] No flaky or intermittent tests
591
+ - [ ] Tests run in reasonable time
592
+ - [ ] Tests are maintainable and readable
593
+
594
+ ---
595
+
596
+ ## Common Testing Anti-Patterns
597
+
598
+ ### Don't Do This
599
+ ```typescript
600
+ // Don't test implementation details
601
+ it('should call handleClick method', () => {
602
+ const spy = vi.spyOn(wrapper.vm, 'handleClick');
603
+ wrapper.trigger('click');
604
+ expect(spy).toHaveBeenCalled();
605
+ });
606
+
607
+ // Don't use magic numbers without context
608
+ it('should have correct width', () => {
609
+ expect(wrapper.element.style.width).toBe('100px');
610
+ });
611
+
612
+ // Don't test multiple things in one test
613
+ it('should render and handle click and emit event', () => {
614
+ expect(wrapper.exists()).toBe(true);
615
+ wrapper.trigger('click');
616
+ expect(wrapper.emitted('click')).toBeTruthy();
617
+ });
618
+ ```
619
+
620
+ ### Do This Instead
621
+ ```typescript
622
+ // Test behavior, not implementation
623
+ it('should emit click event when clicked', async () => {
624
+ await wrapper.trigger('click');
625
+ expect(wrapper.emitted('click')).toBeTruthy();
626
+ });
627
+
628
+ // Use descriptive assertions
629
+ it('should have full width when wide prop is true', async () => {
630
+ await wrapper.setProps({ wide: true });
631
+ expect(wrapper.classes()).toContain('is-wide');
632
+ });
633
+
634
+ // Test one thing per test
635
+ it('should render button element', () => {
636
+ expect(wrapper.element.tagName).toBe('BUTTON');
637
+ });
638
+
639
+ it('should emit click event when clicked', async () => {
640
+ await wrapper.trigger('click');
641
+ expect(wrapper.emitted('click')).toBeTruthy();
642
+ });
643
+ ```
644
+
645
+ ---
646
+
647
+ ## Additional Resources
648
+
649
+ ### VITEST Documentation
650
+ - [VITEST Testing Framework](https://vitest.dev/)
651
+ - [Vue Test Utils](https://test-utils.vuejs.org/)
652
+ - [Testing Vue Components](https://vuejs.org/guide/scaling-up/testing.html)
653
+
654
+ ### Project-Specific Testing
655
+ - Use existing test files as examples
656
+ - Follow established patterns in the codebase
657
+ - Maintain consistency with existing test structure
658
+ - Use project-specific mocks and utilities
659
+
660
+ ### Testing Tools
661
+ - VITEST for test runner and assertions
662
+ - Vue Test Utils for component testing
663
+ - jsdom for DOM simulation
664
+ - Mock Service Worker for API mocking (if needed)
665
+
666
+ ---
667
+
668
+ ## Essential Test Commands
669
+
670
+ ### Development Commands
671
+ ```bash
672
+ npm run test # Run tests in watch mode
673
+ npm run test:run # Run tests once
674
+ npm run test:coverage # Generate coverage report
675
+ npm run test:ui # Open Vitest UI
676
+ ```
677
+
678
+ ### CI/CD Commands
679
+ ```bash
680
+ npm run test:ci # Run tests in CI mode
681
+ npm run test:coverage:ci # Generate coverage for CI
682
+ ```
683
+
684
+ ### Debugging Tests
685
+ ```bash
686
+ npm run test -- --reporter=verbose # Verbose output
687
+ npm run test -- --run --reporter=json # JSON output for parsing
688
+ ```
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "Vitest",
3
+ "description": "Unit testy z Vitest + Vue Test Utils",
4
+ "default": true,
5
+ "placeholders": {}
6
+ }