specweave 0.23.18 → 0.24.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.
- package/.claude-plugin/marketplace.json +144 -45
- package/CLAUDE.md +137 -4
- package/dist/src/cli/helpers/ado-area-path-mapper.d.ts +89 -0
- package/dist/src/cli/helpers/ado-area-path-mapper.d.ts.map +1 -0
- package/dist/src/cli/helpers/ado-area-path-mapper.js +213 -0
- package/dist/src/cli/helpers/ado-area-path-mapper.js.map +1 -0
- package/dist/src/cli/helpers/issue-tracker/ado-auto-discover.d.ts +29 -0
- package/dist/src/cli/helpers/issue-tracker/ado-auto-discover.d.ts.map +1 -0
- package/dist/src/cli/helpers/issue-tracker/ado-auto-discover.js +109 -0
- package/dist/src/cli/helpers/issue-tracker/ado-auto-discover.js.map +1 -0
- package/dist/src/cli/helpers/issue-tracker/ado.d.ts +1 -0
- package/dist/src/cli/helpers/issue-tracker/ado.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/ado.js +2 -0
- package/dist/src/cli/helpers/issue-tracker/ado.js.map +1 -1
- package/dist/src/cli/helpers/smart-filter.d.ts +83 -0
- package/dist/src/cli/helpers/smart-filter.d.ts.map +1 -0
- package/dist/src/cli/helpers/smart-filter.js +265 -0
- package/dist/src/cli/helpers/smart-filter.js.map +1 -0
- package/dist/src/core/qa/quality-gate-decider.d.ts +1 -1
- package/dist/src/core/qa/quality-gate-decider.js +2 -2
- package/dist/src/core/qa/quality-gate-decider.js.map +1 -1
- package/dist/src/core/qa/risk-calculator.d.ts +2 -2
- package/dist/src/core/qa/risk-calculator.js +2 -2
- package/dist/src/core/repo-structure/repo-structure-manager.d.ts.map +1 -1
- package/dist/src/core/repo-structure/repo-structure-manager.js +76 -43
- package/dist/src/core/repo-structure/repo-structure-manager.js.map +1 -1
- package/dist/src/core/validators/ac-presence-validator.d.ts +56 -0
- package/dist/src/core/validators/ac-presence-validator.d.ts.map +1 -0
- package/dist/src/core/validators/ac-presence-validator.js +149 -0
- package/dist/src/core/validators/ac-presence-validator.js.map +1 -0
- package/dist/src/integrations/ado/area-path-mapper.d.ts +137 -0
- package/dist/src/integrations/ado/area-path-mapper.d.ts.map +1 -0
- package/dist/src/integrations/ado/area-path-mapper.js +267 -0
- package/dist/src/integrations/ado/area-path-mapper.js.map +1 -0
- package/dist/src/integrations/jira/filter-processor.d.ts +126 -0
- package/dist/src/integrations/jira/filter-processor.d.ts.map +1 -0
- package/dist/src/integrations/jira/filter-processor.js +207 -0
- package/dist/src/integrations/jira/filter-processor.js.map +1 -0
- package/dist/src/integrations/jira/jira-client.d.ts +13 -0
- package/dist/src/integrations/jira/jira-client.d.ts.map +1 -1
- package/dist/src/integrations/jira/jira-client.js +33 -0
- package/dist/src/integrations/jira/jira-client.js.map +1 -1
- package/dist/src/utils/ac-embedder.d.ts +63 -0
- package/dist/src/utils/ac-embedder.d.ts.map +1 -0
- package/dist/src/utils/ac-embedder.js +217 -0
- package/dist/src/utils/ac-embedder.js.map +1 -0
- package/dist/src/utils/env-manager.d.ts +86 -0
- package/dist/src/utils/env-manager.d.ts.map +1 -0
- package/dist/src/utils/env-manager.js +188 -0
- package/dist/src/utils/env-manager.js.map +1 -0
- package/package.json +1 -1
- package/plugins/specweave/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave/agents/AGENTS-INDEX.md +1 -1
- package/plugins/specweave/agents/increment-quality-judge-v2/AGENT.md +9 -9
- package/plugins/specweave/commands/specweave-do.md +37 -0
- package/plugins/specweave/commands/specweave-done.md +159 -0
- package/plugins/specweave/commands/specweave-embed-acs.md +446 -0
- package/plugins/specweave/commands/specweave-next.md +148 -3
- package/plugins/specweave/commands/specweave-qa.md +2 -2
- package/plugins/specweave/hooks/pre-increment-start.sh +168 -0
- package/plugins/specweave/skills/SKILLS-INDEX.md +1 -1
- package/plugins/specweave-ado/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-ado/commands/specweave-ado-import-projects.md +331 -0
- package/plugins/specweave-alternatives/.claude-plugin/plugin.json +10 -0
- package/plugins/specweave-alternatives/commands/alternatives-analyze.md +336 -0
- package/plugins/specweave-alternatives/skills/architecture-alternatives/SKILL.md +651 -0
- package/plugins/specweave-alternatives/skills/bmad-method/SKILL.md +420 -0
- package/plugins/specweave-alternatives/skills/spec-kit-expert/SKILL.md +487 -0
- package/plugins/specweave-backend/commands/api-scaffold.md +80 -0
- package/plugins/specweave-backend/commands/crud-generate.md +109 -0
- package/plugins/specweave-backend/commands/migration-generate.md +139 -0
- package/plugins/specweave-confluent/commands/connector-deploy.md +154 -0
- package/plugins/specweave-confluent/commands/ksqldb-query.md +179 -0
- package/plugins/specweave-confluent/commands/schema-register.md +123 -0
- package/plugins/specweave-core/.claude-plugin/plugin.json +21 -0
- package/plugins/specweave-core/commands/architecture-review.md +288 -0
- package/plugins/specweave-core/commands/code-review.md +213 -0
- package/plugins/specweave-core/commands/refactor-plan.md +249 -0
- package/plugins/specweave-core/skills/code-quality/SKILL.md +157 -0
- package/plugins/specweave-core/skills/design-patterns/SKILL.md +244 -0
- package/plugins/specweave-core/skills/software-architecture/SKILL.md +83 -0
- package/plugins/specweave-cost-optimizer/.claude-plugin/plugin.json +22 -0
- package/plugins/specweave-cost-optimizer/commands/cost-analyze.md +360 -0
- package/plugins/specweave-cost-optimizer/commands/cost-optimize.md +480 -0
- package/plugins/specweave-cost-optimizer/skills/aws-cost-expert/SKILL.md +416 -0
- package/plugins/specweave-cost-optimizer/skills/cloud-pricing/SKILL.md +325 -0
- package/plugins/specweave-cost-optimizer/skills/cost-optimization/SKILL.md +337 -0
- package/plugins/specweave-diagrams/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-diagrams/commands/diagrams-generate.md +168 -0
- package/plugins/specweave-docs/.claude-plugin/plugin.json +10 -0
- package/plugins/specweave-docs/commands/docs-generate.md +441 -0
- package/plugins/specweave-docs/commands/docs-init.md +334 -0
- package/plugins/specweave-docs/skills/docusaurus/SKILL.md +581 -0
- package/plugins/specweave-docs/skills/spec-driven-brainstorming/SKILL.md +689 -0
- package/plugins/specweave-docs/skills/technical-writing/SKILL.md +1039 -0
- package/plugins/specweave-docs-preview/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-figma/.claude-plugin/plugin.json +23 -0
- package/plugins/specweave-figma/commands/figma-import.md +690 -0
- package/plugins/specweave-figma/commands/figma-to-react.md +834 -0
- package/plugins/specweave-figma/commands/figma-tokens.md +815 -0
- package/plugins/specweave-frontend/.claude-plugin/plugin.json +21 -0
- package/plugins/specweave-frontend/agents/frontend-architect/AGENT.md +408 -0
- package/plugins/specweave-frontend/agents/frontend-architect/README.md +385 -0
- package/plugins/specweave-frontend/agents/frontend-architect/examples.md +590 -0
- package/plugins/specweave-frontend/agents/frontend-architect/templates/component-template.tsx +152 -0
- package/plugins/specweave-frontend/agents/frontend-architect/templates/hook-template.ts +311 -0
- package/plugins/specweave-frontend/agents/frontend-architect/templates/page-template.tsx +228 -0
- package/plugins/specweave-frontend/commands/component-generate.md +510 -0
- package/plugins/specweave-frontend/commands/design-system-init.md +494 -0
- package/plugins/specweave-frontend/commands/frontend-scaffold.md +207 -0
- package/plugins/specweave-frontend/commands/nextjs-setup.md +396 -0
- package/plugins/specweave-frontend/skills/design-system-architect/SKILL.md +278 -0
- package/plugins/specweave-frontend/skills/frontend/SKILL.md +420 -0
- package/plugins/specweave-frontend/skills/nextjs/SKILL.md +546 -0
- package/plugins/specweave-github/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +212 -0
- package/plugins/specweave-infrastructure/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-jira/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-jira/commands/import-projects.js +183 -0
- package/plugins/specweave-jira/commands/import-projects.md +97 -0
- package/plugins/specweave-jira/commands/import-projects.ts +288 -0
- package/plugins/specweave-jira/commands/specweave-jira-import-projects.md +298 -0
- package/plugins/specweave-kafka/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-kafka-streams/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-kubernetes/commands/cluster-setup.md +262 -0
- package/plugins/specweave-kubernetes/commands/deployment-generate.md +242 -0
- package/plugins/specweave-kubernetes/commands/helm-scaffold.md +333 -0
- package/plugins/specweave-ml/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-mobile/commands/app-scaffold.md +233 -0
- package/plugins/specweave-mobile/commands/build-config.md +256 -0
- package/plugins/specweave-mobile/commands/screen-generate.md +289 -0
- package/plugins/specweave-n8n/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-payments/commands/stripe-setup.md +931 -0
- package/plugins/specweave-payments/commands/subscription-flow.md +1193 -0
- package/plugins/specweave-payments/commands/subscription-manage.md +386 -0
- package/plugins/specweave-payments/commands/webhook-setup.md +295 -0
- package/plugins/specweave-plugin-dev/.claude-plugin/plugin.json +13 -12
- package/plugins/specweave-plugin-dev/commands/plugin-create.md +333 -0
- package/plugins/specweave-plugin-dev/commands/plugin-publish.md +339 -0
- package/plugins/specweave-plugin-dev/commands/plugin-test.md +293 -0
- package/plugins/specweave-plugin-dev/skills/claude-sdk/SKILL.md +162 -0
- package/plugins/specweave-plugin-dev/skills/marketplace-publishing/SKILL.md +263 -0
- package/plugins/specweave-plugin-dev/skills/plugin-development/SKILL.md +316 -0
- package/plugins/specweave-release/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-release/commands/specweave-release-npm.md +110 -0
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +168 -0
- package/plugins/specweave-testing/.claude-plugin/plugin.json +21 -0
- package/plugins/specweave-testing/agents/qa-engineer/AGENT.md +818 -0
- package/plugins/specweave-testing/agents/qa-engineer/README.md +443 -0
- package/plugins/specweave-testing/agents/qa-engineer/templates/playwright-e2e-test.ts +470 -0
- package/plugins/specweave-testing/agents/qa-engineer/templates/test-data-factory.ts +507 -0
- package/plugins/specweave-testing/agents/qa-engineer/templates/vitest-unit-test.ts +400 -0
- package/plugins/specweave-testing/agents/qa-engineer/test-strategies.md +726 -0
- package/plugins/specweave-testing/commands/e2e-setup.md +1081 -0
- package/plugins/specweave-testing/commands/test-coverage.md +979 -0
- package/plugins/specweave-testing/commands/test-generate.md +1156 -0
- package/plugins/specweave-testing/commands/test-init.md +409 -0
- package/plugins/specweave-testing/skills/e2e-playwright/SKILL.md +769 -0
- package/plugins/specweave-testing/skills/tdd-expert/SKILL.md +934 -0
- package/plugins/specweave-testing/skills/unit-testing-expert/SKILL.md +1011 -0
- package/plugins/specweave-tooling/.claude-plugin/plugin.json +22 -0
- package/plugins/specweave-tooling/commands/specweave-tooling-skill-create.md +691 -0
- package/plugins/specweave-tooling/commands/specweave-tooling-skill-package.md +751 -0
- package/plugins/specweave-tooling/commands/specweave-tooling-skill-validate.md +858 -0
- package/plugins/specweave-ui/.claude-plugin/plugin.json +10 -0
- package/plugins/specweave-ui/commands/ui-automate.md +199 -0
- package/plugins/specweave-ui/commands/ui-inspect.md +70 -0
- package/plugins/specweave-ui/skills/browser-automation/SKILL.md +314 -0
- package/plugins/specweave-ui/skills/ui-testing/SKILL.md +716 -0
- package/plugins/specweave-ui/skills/visual-regression/SKILL.md +728 -0
- package/plugins/specweave/commands/check-hooks.md +0 -257
- package/plugins/specweave/commands/specweave-archive-increments.md +0 -82
- package/plugins/specweave-plugin-dev/skills/plugin-expert/SKILL.md +0 -1231
- /package/plugins/specweave/{agents/code-reviewer.md → skills/code-reviewer/SKILL.md} +0 -0
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vitest Unit Test Template
|
|
3
|
+
*
|
|
4
|
+
* This template demonstrates best practices for writing unit tests
|
|
5
|
+
* with Vitest for TypeScript projects.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - AAA pattern (Arrange-Act-Assert)
|
|
9
|
+
* - Test isolation
|
|
10
|
+
* - Mocking dependencies
|
|
11
|
+
* - Parametric testing
|
|
12
|
+
* - Error handling tests
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
16
|
+
|
|
17
|
+
// Import the module under test
|
|
18
|
+
import { YourModule } from './YourModule';
|
|
19
|
+
|
|
20
|
+
// Import dependencies (to be mocked)
|
|
21
|
+
import { ExternalDependency } from './ExternalDependency';
|
|
22
|
+
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// MOCKS
|
|
25
|
+
// ============================================================================
|
|
26
|
+
|
|
27
|
+
// Mock external dependencies
|
|
28
|
+
vi.mock('./ExternalDependency', () => ({
|
|
29
|
+
ExternalDependency: vi.fn().mockImplementation(() => ({
|
|
30
|
+
fetchData: vi.fn().mockResolvedValue({ data: 'mocked' }),
|
|
31
|
+
processData: vi.fn(),
|
|
32
|
+
})),
|
|
33
|
+
}));
|
|
34
|
+
|
|
35
|
+
// ============================================================================
|
|
36
|
+
// TEST SUITE
|
|
37
|
+
// ============================================================================
|
|
38
|
+
|
|
39
|
+
describe('YourModule', () => {
|
|
40
|
+
// ========================================================================
|
|
41
|
+
// SETUP & TEARDOWN
|
|
42
|
+
// ========================================================================
|
|
43
|
+
|
|
44
|
+
let instance: YourModule;
|
|
45
|
+
let mockDependency: any;
|
|
46
|
+
|
|
47
|
+
beforeEach(() => {
|
|
48
|
+
// ARRANGE: Set up fresh instance for each test
|
|
49
|
+
mockDependency = new ExternalDependency();
|
|
50
|
+
instance = new YourModule(mockDependency);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
afterEach(() => {
|
|
54
|
+
// TEARDOWN: Clean up mocks
|
|
55
|
+
vi.clearAllMocks();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// ========================================================================
|
|
59
|
+
// HAPPY PATH TESTS
|
|
60
|
+
// ========================================================================
|
|
61
|
+
|
|
62
|
+
describe('methodName', () => {
|
|
63
|
+
it('should perform expected operation with valid input', () => {
|
|
64
|
+
// ARRANGE
|
|
65
|
+
const input = 'test-input';
|
|
66
|
+
const expectedOutput = 'test-output';
|
|
67
|
+
|
|
68
|
+
// ACT
|
|
69
|
+
const result = instance.methodName(input);
|
|
70
|
+
|
|
71
|
+
// ASSERT
|
|
72
|
+
expect(result).toBe(expectedOutput);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should call dependency with correct parameters', () => {
|
|
76
|
+
// ARRANGE
|
|
77
|
+
const input = 'test-input';
|
|
78
|
+
|
|
79
|
+
// ACT
|
|
80
|
+
instance.methodName(input);
|
|
81
|
+
|
|
82
|
+
// ASSERT
|
|
83
|
+
expect(mockDependency.processData).toHaveBeenCalledWith(input);
|
|
84
|
+
expect(mockDependency.processData).toHaveBeenCalledTimes(1);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// ========================================================================
|
|
89
|
+
// ASYNC TESTS
|
|
90
|
+
// ========================================================================
|
|
91
|
+
|
|
92
|
+
describe('asyncMethod', () => {
|
|
93
|
+
it('should resolve with data on success', async () => {
|
|
94
|
+
// ARRANGE
|
|
95
|
+
const mockData = { id: 1, value: 'test' };
|
|
96
|
+
mockDependency.fetchData.mockResolvedValue(mockData);
|
|
97
|
+
|
|
98
|
+
// ACT
|
|
99
|
+
const result = await instance.asyncMethod();
|
|
100
|
+
|
|
101
|
+
// ASSERT
|
|
102
|
+
expect(result).toEqual(mockData);
|
|
103
|
+
expect(mockDependency.fetchData).toHaveBeenCalled();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('should handle async errors gracefully', async () => {
|
|
107
|
+
// ARRANGE
|
|
108
|
+
const error = new Error('Network error');
|
|
109
|
+
mockDependency.fetchData.mockRejectedValue(error);
|
|
110
|
+
|
|
111
|
+
// ACT & ASSERT
|
|
112
|
+
await expect(instance.asyncMethod()).rejects.toThrow('Network error');
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// ========================================================================
|
|
117
|
+
// EDGE CASES
|
|
118
|
+
// ========================================================================
|
|
119
|
+
|
|
120
|
+
describe('edge cases', () => {
|
|
121
|
+
it('should handle empty input', () => {
|
|
122
|
+
// ACT
|
|
123
|
+
const result = instance.methodName('');
|
|
124
|
+
|
|
125
|
+
// ASSERT
|
|
126
|
+
expect(result).toBe('');
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('should handle null input', () => {
|
|
130
|
+
// ACT
|
|
131
|
+
const result = instance.methodName(null as any);
|
|
132
|
+
|
|
133
|
+
// ASSERT
|
|
134
|
+
expect(result).toBeNull();
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('should handle undefined input', () => {
|
|
138
|
+
// ACT
|
|
139
|
+
const result = instance.methodName(undefined as any);
|
|
140
|
+
|
|
141
|
+
// ASSERT
|
|
142
|
+
expect(result).toBeUndefined();
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('should handle very large input', () => {
|
|
146
|
+
// ARRANGE
|
|
147
|
+
const largeInput = 'x'.repeat(1000000);
|
|
148
|
+
|
|
149
|
+
// ACT
|
|
150
|
+
const result = instance.methodName(largeInput);
|
|
151
|
+
|
|
152
|
+
// ASSERT
|
|
153
|
+
expect(result).toBeDefined();
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// ========================================================================
|
|
158
|
+
// ERROR HANDLING
|
|
159
|
+
// ========================================================================
|
|
160
|
+
|
|
161
|
+
describe('error handling', () => {
|
|
162
|
+
it('should throw error for invalid input', () => {
|
|
163
|
+
// ARRANGE
|
|
164
|
+
const invalidInput = -1;
|
|
165
|
+
|
|
166
|
+
// ACT & ASSERT
|
|
167
|
+
expect(() => instance.methodName(invalidInput)).toThrow(
|
|
168
|
+
'Input must be positive'
|
|
169
|
+
);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('should throw specific error type', () => {
|
|
173
|
+
// ARRANGE
|
|
174
|
+
const invalidInput = 'invalid';
|
|
175
|
+
|
|
176
|
+
// ACT & ASSERT
|
|
177
|
+
expect(() => instance.methodName(invalidInput)).toThrow(ValidationError);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('should include error details', () => {
|
|
181
|
+
// ARRANGE
|
|
182
|
+
const invalidInput = 'invalid';
|
|
183
|
+
|
|
184
|
+
// ACT
|
|
185
|
+
try {
|
|
186
|
+
instance.methodName(invalidInput);
|
|
187
|
+
fail('Expected error to be thrown');
|
|
188
|
+
} catch (error) {
|
|
189
|
+
// ASSERT
|
|
190
|
+
expect(error).toBeInstanceOf(ValidationError);
|
|
191
|
+
expect(error.message).toContain('invalid');
|
|
192
|
+
expect(error.code).toBe('INVALID_INPUT');
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// ========================================================================
|
|
198
|
+
// PARAMETRIC TESTS (Table-Driven)
|
|
199
|
+
// ========================================================================
|
|
200
|
+
|
|
201
|
+
describe.each([
|
|
202
|
+
{ input: 1, expected: 2 },
|
|
203
|
+
{ input: 2, expected: 4 },
|
|
204
|
+
{ input: 3, expected: 6 },
|
|
205
|
+
{ input: 4, expected: 8 },
|
|
206
|
+
])('methodName($input)', ({ input, expected }) => {
|
|
207
|
+
it(`should return ${expected}`, () => {
|
|
208
|
+
// ACT
|
|
209
|
+
const result = instance.methodName(input);
|
|
210
|
+
|
|
211
|
+
// ASSERT
|
|
212
|
+
expect(result).toBe(expected);
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// ========================================================================
|
|
217
|
+
// STATE MANAGEMENT TESTS
|
|
218
|
+
// ========================================================================
|
|
219
|
+
|
|
220
|
+
describe('state management', () => {
|
|
221
|
+
it('should update internal state correctly', () => {
|
|
222
|
+
// ARRANGE
|
|
223
|
+
const initialState = instance.getState();
|
|
224
|
+
|
|
225
|
+
// ACT
|
|
226
|
+
instance.updateState('new-value');
|
|
227
|
+
|
|
228
|
+
// ASSERT
|
|
229
|
+
const newState = instance.getState();
|
|
230
|
+
expect(newState).not.toBe(initialState);
|
|
231
|
+
expect(newState).toBe('new-value');
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it('should emit events on state change', () => {
|
|
235
|
+
// ARRANGE
|
|
236
|
+
const eventHandler = vi.fn();
|
|
237
|
+
instance.on('stateChanged', eventHandler);
|
|
238
|
+
|
|
239
|
+
// ACT
|
|
240
|
+
instance.updateState('new-value');
|
|
241
|
+
|
|
242
|
+
// ASSERT
|
|
243
|
+
expect(eventHandler).toHaveBeenCalledWith('new-value');
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// ========================================================================
|
|
248
|
+
// PERFORMANCE TESTS
|
|
249
|
+
// ========================================================================
|
|
250
|
+
|
|
251
|
+
describe('performance', () => {
|
|
252
|
+
it('should complete within reasonable time', () => {
|
|
253
|
+
// ARRANGE
|
|
254
|
+
const startTime = Date.now();
|
|
255
|
+
|
|
256
|
+
// ACT
|
|
257
|
+
instance.methodName('test');
|
|
258
|
+
|
|
259
|
+
// ASSERT
|
|
260
|
+
const endTime = Date.now();
|
|
261
|
+
const executionTime = endTime - startTime;
|
|
262
|
+
expect(executionTime).toBeLessThan(100); // 100ms threshold
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it('should handle large datasets efficiently', () => {
|
|
266
|
+
// ARRANGE
|
|
267
|
+
const largeDataset = Array.from({ length: 10000 }, (_, i) => i);
|
|
268
|
+
|
|
269
|
+
// ACT
|
|
270
|
+
const startTime = Date.now();
|
|
271
|
+
const result = instance.processBatch(largeDataset);
|
|
272
|
+
const endTime = Date.now();
|
|
273
|
+
|
|
274
|
+
// ASSERT
|
|
275
|
+
expect(result).toHaveLength(10000);
|
|
276
|
+
expect(endTime - startTime).toBeLessThan(1000); // 1s threshold
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
// ========================================================================
|
|
281
|
+
// SNAPSHOT TESTS
|
|
282
|
+
// ========================================================================
|
|
283
|
+
|
|
284
|
+
describe('snapshots', () => {
|
|
285
|
+
it('should match snapshot for complex output', () => {
|
|
286
|
+
// ARRANGE
|
|
287
|
+
const input = { id: 1, name: 'Test', nested: { value: 42 } };
|
|
288
|
+
|
|
289
|
+
// ACT
|
|
290
|
+
const result = instance.transform(input);
|
|
291
|
+
|
|
292
|
+
// ASSERT
|
|
293
|
+
expect(result).toMatchSnapshot();
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
it('should match inline snapshot for simple output', () => {
|
|
297
|
+
// ARRANGE
|
|
298
|
+
const input = 'test';
|
|
299
|
+
|
|
300
|
+
// ACT
|
|
301
|
+
const result = instance.methodName(input);
|
|
302
|
+
|
|
303
|
+
// ASSERT
|
|
304
|
+
expect(result).toMatchInlineSnapshot('"test-output"');
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
// ========================================================================
|
|
309
|
+
// TIMER/DEBOUNCE TESTS
|
|
310
|
+
// ========================================================================
|
|
311
|
+
|
|
312
|
+
describe('timers', () => {
|
|
313
|
+
beforeEach(() => {
|
|
314
|
+
vi.useFakeTimers();
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
afterEach(() => {
|
|
318
|
+
vi.restoreAllTimers();
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
it('should debounce function calls', () => {
|
|
322
|
+
// ARRANGE
|
|
323
|
+
const callback = vi.fn();
|
|
324
|
+
const debounced = instance.debounce(callback, 1000);
|
|
325
|
+
|
|
326
|
+
// ACT
|
|
327
|
+
debounced();
|
|
328
|
+
debounced();
|
|
329
|
+
debounced();
|
|
330
|
+
|
|
331
|
+
// ASSERT (not called yet)
|
|
332
|
+
expect(callback).not.toHaveBeenCalled();
|
|
333
|
+
|
|
334
|
+
// Fast-forward time
|
|
335
|
+
vi.advanceTimersByTime(1000);
|
|
336
|
+
|
|
337
|
+
// ASSERT (called once)
|
|
338
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
it('should throttle function calls', () => {
|
|
342
|
+
// ARRANGE
|
|
343
|
+
const callback = vi.fn();
|
|
344
|
+
const throttled = instance.throttle(callback, 1000);
|
|
345
|
+
|
|
346
|
+
// ACT
|
|
347
|
+
throttled(); // Called immediately
|
|
348
|
+
throttled(); // Ignored (within throttle window)
|
|
349
|
+
throttled(); // Ignored (within throttle window)
|
|
350
|
+
|
|
351
|
+
// ASSERT
|
|
352
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
353
|
+
|
|
354
|
+
// Fast-forward time
|
|
355
|
+
vi.advanceTimersByTime(1000);
|
|
356
|
+
|
|
357
|
+
// ACT
|
|
358
|
+
throttled(); // Called after throttle window
|
|
359
|
+
|
|
360
|
+
// ASSERT
|
|
361
|
+
expect(callback).toHaveBeenCalledTimes(2);
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
// ============================================================================
|
|
367
|
+
// HELPER TYPES & CLASSES (For Examples Above)
|
|
368
|
+
// ============================================================================
|
|
369
|
+
|
|
370
|
+
class ValidationError extends Error {
|
|
371
|
+
constructor(
|
|
372
|
+
message: string,
|
|
373
|
+
public code: string
|
|
374
|
+
) {
|
|
375
|
+
super(message);
|
|
376
|
+
this.name = 'ValidationError';
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// ============================================================================
|
|
381
|
+
// BEST PRACTICES CHECKLIST
|
|
382
|
+
// ============================================================================
|
|
383
|
+
|
|
384
|
+
/*
|
|
385
|
+
✅ AAA Pattern (Arrange-Act-Assert)
|
|
386
|
+
✅ Test Isolation (beforeEach creates fresh instance)
|
|
387
|
+
✅ Descriptive Test Names (should do X when Y)
|
|
388
|
+
✅ One Assertion Per Test (when possible)
|
|
389
|
+
✅ Mock External Dependencies
|
|
390
|
+
✅ Test Happy Path
|
|
391
|
+
✅ Test Edge Cases (null, undefined, empty, large)
|
|
392
|
+
✅ Test Error Handling
|
|
393
|
+
✅ Parametric Tests (test.each)
|
|
394
|
+
✅ Async Testing (async/await, rejects, resolves)
|
|
395
|
+
✅ Timer Testing (useFakeTimers)
|
|
396
|
+
✅ Performance Testing (execution time)
|
|
397
|
+
✅ Snapshot Testing (complex outputs)
|
|
398
|
+
✅ No Shared State Between Tests
|
|
399
|
+
✅ Fast Execution (< 1s per test)
|
|
400
|
+
*/
|