@smartsoft001/pro-claude-plugins 0.2.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 (198) hide show
  1. package/.claude-plugin/marketplace.json +26 -0
  2. package/README.md +56 -0
  3. package/package.json +14 -0
  4. package/plugins/flow/.claude-plugin/README.md +91 -0
  5. package/plugins/flow/.claude-plugin/merge-permissions.js +115 -0
  6. package/plugins/flow/.claude-plugin/plugin.json +5 -0
  7. package/plugins/flow/.claude-plugin/settings.template.json +86 -0
  8. package/plugins/flow/agents/angular-component-scaffolder.md +176 -0
  9. package/plugins/flow/agents/angular-directive-builder.md +154 -0
  10. package/plugins/flow/agents/angular-guard-builder.md +244 -0
  11. package/plugins/flow/agents/angular-jest-test-writer.md +475 -0
  12. package/plugins/flow/agents/angular-pipe-builder.md +170 -0
  13. package/plugins/flow/agents/angular-resolver-builder.md +287 -0
  14. package/plugins/flow/agents/angular-service-builder.md +162 -0
  15. package/plugins/flow/agents/angular-signal-state-builder.md +340 -0
  16. package/plugins/flow/agents/angular-test-diagnostician.md +279 -0
  17. package/plugins/flow/agents/angular-testbed-configurator.md +315 -0
  18. package/plugins/flow/agents/arch-scaffolder.md +278 -0
  19. package/plugins/flow/agents/e2e-data-testid-injector.md +195 -0
  20. package/plugins/flow/agents/e2e-project-scaffolder.md +194 -0
  21. package/plugins/flow/agents/e2e-test-writer.md +357 -0
  22. package/plugins/flow/agents/shared-agent-evolver.md +294 -0
  23. package/plugins/flow/agents/shared-build-verifier.md +160 -0
  24. package/plugins/flow/agents/shared-config-updater.md +310 -0
  25. package/plugins/flow/agents/shared-coverage-enforcer.md +184 -0
  26. package/plugins/flow/agents/shared-error-handler.md +217 -0
  27. package/plugins/flow/agents/shared-file-creator.md +344 -0
  28. package/plugins/flow/agents/shared-impl-orchestrator.md +312 -0
  29. package/plugins/flow/agents/shared-impl-reporter.md +368 -0
  30. package/plugins/flow/agents/shared-impl-teammate.md +201 -0
  31. package/plugins/flow/agents/shared-linear-subtask-iterator.md +337 -0
  32. package/plugins/flow/agents/shared-logic-implementer.md +244 -0
  33. package/plugins/flow/agents/shared-maia-api.md +26 -0
  34. package/plugins/flow/agents/shared-parallelization-analyzer.md +343 -0
  35. package/plugins/flow/agents/shared-performance-validator.md +168 -0
  36. package/plugins/flow/agents/shared-plan-perspective.md +271 -0
  37. package/plugins/flow/agents/shared-project-standardizer.md +205 -0
  38. package/plugins/flow/agents/shared-report-synthesizer.md +188 -0
  39. package/plugins/flow/agents/shared-review-teammate.md +189 -0
  40. package/plugins/flow/agents/shared-security-scanner.md +186 -0
  41. package/plugins/flow/agents/shared-style-enforcer.md +230 -0
  42. package/plugins/flow/agents/shared-subtask-dependency-analyzer.md +189 -0
  43. package/plugins/flow/agents/shared-tdd-developer.md +350 -0
  44. package/plugins/flow/agents/shared-team-coordinator.md +192 -0
  45. package/plugins/flow/agents/shared-test-fixer.md +186 -0
  46. package/plugins/flow/agents/shared-test-runner.md +191 -0
  47. package/plugins/flow/agents/shared-ui-classifier.md +263 -0
  48. package/plugins/flow/agents/shared-verification-orchestrator.md +194 -0
  49. package/plugins/flow/agents/shared-verification-runner.md +140 -0
  50. package/plugins/flow/agents/ui-a11y-validator.md +305 -0
  51. package/plugins/flow/agents/ui-screenshot-reporter.md +329 -0
  52. package/plugins/flow/agents/ui-web-designer.md +214 -0
  53. package/plugins/flow/scripts/compute-session-tokens.sh +39 -0
  54. package/plugins/flow/skills/a11y-audit/SKILL.md +214 -0
  55. package/plugins/flow/skills/angular-patterns/SKILL.md +191 -0
  56. package/plugins/flow/skills/browser-capture/SKILL.md +238 -0
  57. package/plugins/flow/skills/commit/SKILL.md +259 -0
  58. package/plugins/flow/skills/debug-helper/SKILL.md +375 -0
  59. package/plugins/flow/skills/impl/SKILL.md +992 -0
  60. package/plugins/flow/skills/karpathy-guidelines/SKILL.md +72 -0
  61. package/plugins/flow/skills/linear-suggestion/SKILL.md +132 -0
  62. package/plugins/flow/skills/maia-files-delete/SKILL.md +59 -0
  63. package/plugins/flow/skills/maia-files-upload/SKILL.md +57 -0
  64. package/plugins/flow/skills/nx-conventions/SKILL.md +326 -0
  65. package/plugins/flow/skills/plan/SKILL.md +1033 -0
  66. package/plugins/flow/skills/push/SKILL.md +759 -0
  67. package/plugins/flow/skills/review/SKILL.md +443 -0
  68. package/plugins/flow/skills/test-e2e/SKILL.md +164 -0
  69. package/plugins/flow/skills/test-unit/SKILL.md +456 -0
  70. package/plugins/flow-external/.claude-plugin/README.md +146 -0
  71. package/plugins/flow-external/.claude-plugin/merge-permissions.js +94 -0
  72. package/plugins/flow-external/.claude-plugin/plugin.json +5 -0
  73. package/plugins/flow-external/.claude-plugin/settings.template.json +78 -0
  74. package/plugins/flow-external/agents/angular-component-scaffolder.md +271 -0
  75. package/plugins/flow-external/agents/angular-directive-builder.md +134 -0
  76. package/plugins/flow-external/agents/angular-guard-builder.md +73 -0
  77. package/plugins/flow-external/agents/angular-pipe-builder.md +90 -0
  78. package/plugins/flow-external/agents/angular-resolver-builder.md +79 -0
  79. package/plugins/flow-external/agents/angular-service-builder.md +168 -0
  80. package/plugins/flow-external/agents/angular-state-builder.md +263 -0
  81. package/plugins/flow-external/agents/shared-build-verifier.md +67 -0
  82. package/plugins/flow-external/agents/shared-impl-orchestrator.md +90 -0
  83. package/plugins/flow-external/agents/shared-impl-reporter.md +135 -0
  84. package/plugins/flow-external/agents/shared-linear-subtask-iterator.md +70 -0
  85. package/plugins/flow-external/agents/shared-ui-classifier.md +38 -0
  86. package/plugins/flow-external/agents/ui-web-designer.md +203 -0
  87. package/plugins/flow-external/scripts/compute-session-tokens.sh +39 -0
  88. package/plugins/flow-external/skills/a11y-audit/SKILL.md +97 -0
  89. package/plugins/flow-external/skills/angular-cli-conventions/SKILL.md +268 -0
  90. package/plugins/flow-external/skills/angular-patterns/SKILL.md +182 -0
  91. package/plugins/flow-external/skills/browser-capture/SKILL.md +74 -0
  92. package/plugins/flow-external/skills/commit/SKILL.md +114 -0
  93. package/plugins/flow-external/skills/debug-helper/SKILL.md +135 -0
  94. package/plugins/flow-external/skills/impl/SKILL.md +218 -0
  95. package/plugins/flow-external/skills/karpathy-guidelines/SKILL.md +72 -0
  96. package/plugins/flow-external/skills/linear-suggestion/SKILL.md +62 -0
  97. package/plugins/flow-external/skills/maia-files-delete/SKILL.md +34 -0
  98. package/plugins/flow-external/skills/maia-files-upload/SKILL.md +41 -0
  99. package/plugins/flow-external/skills/plan/SKILL.md +334 -0
  100. package/plugins/flow-external/skills/push/SKILL.md +232 -0
  101. package/plugins/flow-legacy/.claude-plugin/README.md +143 -0
  102. package/plugins/flow-legacy/.claude-plugin/merge-permissions.js +94 -0
  103. package/plugins/flow-legacy/.claude-plugin/plugin.json +5 -0
  104. package/plugins/flow-legacy/.claude-plugin/settings.template.json +79 -0
  105. package/plugins/flow-legacy/agents/angular-component-scaffolder.md +327 -0
  106. package/plugins/flow-legacy/agents/angular-directive-builder.md +253 -0
  107. package/plugins/flow-legacy/agents/angular-guard-builder.md +326 -0
  108. package/plugins/flow-legacy/agents/angular-pipe-builder.md +238 -0
  109. package/plugins/flow-legacy/agents/angular-resolver-builder.md +339 -0
  110. package/plugins/flow-legacy/agents/angular-service-builder.md +271 -0
  111. package/plugins/flow-legacy/agents/angular-state-builder.md +480 -0
  112. package/plugins/flow-legacy/agents/shared-impl-orchestrator.md +174 -0
  113. package/plugins/flow-legacy/agents/shared-impl-reporter.md +232 -0
  114. package/plugins/flow-legacy/agents/shared-linear-subtask-iterator.md +198 -0
  115. package/plugins/flow-legacy/agents/shared-tdd-developer.md +307 -0
  116. package/plugins/flow-legacy/agents/shared-test-runner.md +133 -0
  117. package/plugins/flow-legacy/agents/shared-ui-classifier.md +145 -0
  118. package/plugins/flow-legacy/scripts/compute-session-tokens.sh +39 -0
  119. package/plugins/flow-legacy/skills/a11y-audit/SKILL.md +214 -0
  120. package/plugins/flow-legacy/skills/angular-patterns/SKILL.md +346 -0
  121. package/plugins/flow-legacy/skills/browser-capture/SKILL.md +238 -0
  122. package/plugins/flow-legacy/skills/commit/SKILL.md +215 -0
  123. package/plugins/flow-legacy/skills/debug-helper/SKILL.md +395 -0
  124. package/plugins/flow-legacy/skills/impl/SKILL.md +710 -0
  125. package/plugins/flow-legacy/skills/karpathy-guidelines/SKILL.md +72 -0
  126. package/plugins/flow-legacy/skills/linear-suggestion/SKILL.md +132 -0
  127. package/plugins/flow-legacy/skills/maia-files-delete/SKILL.md +59 -0
  128. package/plugins/flow-legacy/skills/maia-files-upload/SKILL.md +57 -0
  129. package/plugins/flow-legacy/skills/nx-conventions/SKILL.md +368 -0
  130. package/plugins/flow-legacy/skills/plan/SKILL.md +742 -0
  131. package/plugins/flow-legacy/skills/push/SKILL.md +645 -0
  132. package/plugins/flow-legacy/skills/test-unit/SKILL.md +500 -0
  133. package/plugins/smart-pro/.claude-plugin/README.md +115 -0
  134. package/plugins/smart-pro/.claude-plugin/merge-permissions.js +129 -0
  135. package/plugins/smart-pro/.claude-plugin/plugin.json +5 -0
  136. package/plugins/smart-pro/.claude-plugin/settings.template.json +94 -0
  137. package/plugins/smart-pro/agents/angular-components/AGENT.md +214 -0
  138. package/plugins/smart-pro/hooks/CONFIG.md +198 -0
  139. package/plugins/smart-pro/hooks/README.md +139 -0
  140. package/plugins/smart-pro/hooks/audit_logger.py +107 -0
  141. package/plugins/smart-pro/hooks/auto_format.sh +11 -0
  142. package/plugins/smart-pro/hooks/hooks.json +79 -0
  143. package/plugins/smart-pro/hooks/safety_validator.py +129 -0
  144. package/plugins/smart-pro/hooks/sensitive_file_blocker.py +58 -0
  145. package/plugins/smart-pro/hooks/skill_validator.py +220 -0
  146. package/plugins/smart-pro/skills/angular-components-action-panel/SKILL.md +159 -0
  147. package/plugins/smart-pro/skills/angular-components-avatar/SKILL.md +142 -0
  148. package/plugins/smart-pro/skills/angular-components-badge/SKILL.md +110 -0
  149. package/plugins/smart-pro/skills/angular-components-breadcrumbs/SKILL.md +91 -0
  150. package/plugins/smart-pro/skills/angular-components-button/SKILL.md +146 -0
  151. package/plugins/smart-pro/skills/angular-components-button-group/SKILL.md +121 -0
  152. package/plugins/smart-pro/skills/angular-components-calendar/SKILL.md +78 -0
  153. package/plugins/smart-pro/skills/angular-components-card/SKILL.md +110 -0
  154. package/plugins/smart-pro/skills/angular-components-card-heading/SKILL.md +105 -0
  155. package/plugins/smart-pro/skills/angular-components-command-palette/SKILL.md +168 -0
  156. package/plugins/smart-pro/skills/angular-components-container/SKILL.md +93 -0
  157. package/plugins/smart-pro/skills/angular-components-description-list/SKILL.md +102 -0
  158. package/plugins/smart-pro/skills/angular-components-details/SKILL.md +70 -0
  159. package/plugins/smart-pro/skills/angular-components-divider/SKILL.md +110 -0
  160. package/plugins/smart-pro/skills/angular-components-drawer/SKILL.md +136 -0
  161. package/plugins/smart-pro/skills/angular-components-dropdown/SKILL.md +131 -0
  162. package/plugins/smart-pro/skills/angular-components-empty-state/SKILL.md +103 -0
  163. package/plugins/smart-pro/skills/angular-components-feed/SKILL.md +110 -0
  164. package/plugins/smart-pro/skills/angular-components-form/SKILL.md +77 -0
  165. package/plugins/smart-pro/skills/angular-components-grid-list/SKILL.md +91 -0
  166. package/plugins/smart-pro/skills/angular-components-input/SKILL.md +118 -0
  167. package/plugins/smart-pro/skills/angular-components-list/SKILL.md +75 -0
  168. package/plugins/smart-pro/skills/angular-components-list-container/SKILL.md +106 -0
  169. package/plugins/smart-pro/skills/angular-components-media-object/SKILL.md +133 -0
  170. package/plugins/smart-pro/skills/angular-components-modal/SKILL.md +159 -0
  171. package/plugins/smart-pro/skills/angular-components-multi-column-layout/SKILL.md +84 -0
  172. package/plugins/smart-pro/skills/angular-components-navbar/SKILL.md +93 -0
  173. package/plugins/smart-pro/skills/angular-components-notification/SKILL.md +147 -0
  174. package/plugins/smart-pro/skills/angular-components-page/SKILL.md +162 -0
  175. package/plugins/smart-pro/skills/angular-components-page-heading/SKILL.md +96 -0
  176. package/plugins/smart-pro/skills/angular-components-paging/SKILL.md +86 -0
  177. package/plugins/smart-pro/skills/angular-components-progress-bars/SKILL.md +94 -0
  178. package/plugins/smart-pro/skills/angular-components-searchbar/SKILL.md +113 -0
  179. package/plugins/smart-pro/skills/angular-components-section-heading/SKILL.md +156 -0
  180. package/plugins/smart-pro/skills/angular-components-select-menu/SKILL.md +101 -0
  181. package/plugins/smart-pro/skills/angular-components-sidebar-layout/SKILL.md +121 -0
  182. package/plugins/smart-pro/skills/angular-components-sidebar-navigation/SKILL.md +80 -0
  183. package/plugins/smart-pro/skills/angular-components-sign-in-form/SKILL.md +91 -0
  184. package/plugins/smart-pro/skills/angular-components-stacked-layout/SKILL.md +114 -0
  185. package/plugins/smart-pro/skills/angular-components-stacked-list/SKILL.md +93 -0
  186. package/plugins/smart-pro/skills/angular-components-stats/SKILL.md +87 -0
  187. package/plugins/smart-pro/skills/angular-components-table/SKILL.md +98 -0
  188. package/plugins/smart-pro/skills/angular-components-tabs/SKILL.md +99 -0
  189. package/plugins/smart-pro/skills/angular-components-textarea/SKILL.md +111 -0
  190. package/plugins/smart-pro/skills/angular-components-toggle/SKILL.md +109 -0
  191. package/plugins/smart-pro/skills/angular-components-vertical-navigation/SKILL.md +139 -0
  192. package/plugins/smart-pro/skills/audit-log/SKILL.md +82 -0
  193. package/plugins/smart-pro/skills/format-code/SKILL.md +46 -0
  194. package/plugins/smart-pro/skills/project-conventions/SKILL.md +90 -0
  195. package/plugins/smart-pro/skills/safety-check/SKILL.md +0 -0
  196. package/src/index.d.ts +6 -0
  197. package/src/index.js +7 -0
  198. package/src/index.js.map +1 -0
@@ -0,0 +1,456 @@
1
+ ---
2
+ name: test-unit
3
+ description: Write unit tests following project conventions. Generates Jest tests for Angular components, services, and NestJS services using AAA pattern.
4
+ allowed-tools:
5
+ - Bash
6
+ - Read
7
+ - Write
8
+ - Edit
9
+ - Glob
10
+ - Grep
11
+ ---
12
+
13
+ # Unit Test Skill
14
+
15
+ Write unit tests following project conventions using Jest framework with AAA (Arrange-Act-Assert) pattern.
16
+
17
+ ## Testing Framework
18
+
19
+ - **Framework**: Jest for all unit tests
20
+ - **File naming**: `{name}.spec.ts` alongside source files
21
+ - **Test runner**: Nx (`nx test {project}`)
22
+
23
+ ## Test File Location
24
+
25
+ Place test files next to the source files they test:
26
+
27
+ ```
28
+ feature/
29
+ ├── feature.service.ts
30
+ ├── feature.service.spec.ts
31
+ ├── feature.component.ts
32
+ └── feature.component.spec.ts
33
+ ```
34
+
35
+ ## Naming Convention
36
+
37
+ - **Describe blocks**: `@{package-name}: ClassName`
38
+ - **Test format**: `it('should...')` with clear behavior description
39
+
40
+ ## Test Structure (AAA Pattern)
41
+
42
+ Always use Arrange-Act-Assert pattern with blank line separation (no comments):
43
+
44
+ ```typescript
45
+ it('should perform expected operation', () => {
46
+ const input = 'test';
47
+
48
+ const result = service.performOperation(input);
49
+
50
+ expect(result).toBe('expected output');
51
+ });
52
+ ```
53
+
54
+ ## Angular Component Testing
55
+
56
+ ### Basic Component Test
57
+
58
+ ```typescript
59
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
60
+
61
+ import { FeatureComponent } from './feature.component';
62
+
63
+ describe('@mms/shared-angular: FeatureComponent', () => {
64
+ let component: FeatureComponent;
65
+ let fixture: ComponentFixture<FeatureComponent>;
66
+
67
+ beforeEach(async () => {
68
+ await TestBed.configureTestingModule({
69
+ imports: [FeatureComponent], // Standalone components
70
+ }).compileComponents();
71
+
72
+ fixture = TestBed.createComponent(FeatureComponent);
73
+ component = fixture.componentInstance;
74
+ fixture.detectChanges();
75
+ });
76
+
77
+ it('should create', () => {
78
+ expect(component).toBeTruthy();
79
+ });
80
+
81
+ it('should display expected content', () => {
82
+ component.title = 'Test Title';
83
+ fixture.detectChanges();
84
+
85
+ const compiled = fixture.nativeElement;
86
+ expect(compiled.querySelector('h1')?.textContent).toContain('Test Title');
87
+ });
88
+ });
89
+ ```
90
+
91
+ ### Testing Signal-based Components
92
+
93
+ ```typescript
94
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
95
+ import { signal } from '@angular/core';
96
+
97
+ import { SignalComponent } from './signal.component';
98
+
99
+ describe('@mms/shared-angular: SignalComponent', () => {
100
+ let component: SignalComponent;
101
+ let fixture: ComponentFixture<SignalComponent>;
102
+
103
+ beforeEach(async () => {
104
+ await TestBed.configureTestingModule({
105
+ imports: [SignalComponent],
106
+ }).compileComponents();
107
+
108
+ fixture = TestBed.createComponent(SignalComponent);
109
+ component = fixture.componentInstance;
110
+ fixture.detectChanges();
111
+ });
112
+
113
+ it('should update when signal changes', () => {
114
+ component.count.set(5);
115
+ fixture.detectChanges();
116
+
117
+ expect(fixture.nativeElement.textContent).toContain('5');
118
+ });
119
+
120
+ it('should compute derived value', () => {
121
+ component.items.set([1, 2, 3]);
122
+
123
+ expect(component.total()).toBe(6);
124
+ });
125
+ });
126
+ ```
127
+
128
+ ### Testing Components with input()/output()
129
+
130
+ ```typescript
131
+ describe('@mms/shared-angular: InputOutputComponent', () => {
132
+ let component: InputOutputComponent;
133
+ let fixture: ComponentFixture<InputOutputComponent>;
134
+
135
+ beforeEach(async () => {
136
+ await TestBed.configureTestingModule({
137
+ imports: [InputOutputComponent],
138
+ }).compileComponents();
139
+
140
+ fixture = TestBed.createComponent(InputOutputComponent);
141
+ component = fixture.componentInstance;
142
+ });
143
+
144
+ it('should accept input value', () => {
145
+ fixture.componentRef.setInput('value', 'test');
146
+ fixture.detectChanges();
147
+
148
+ expect(component.value()).toBe('test');
149
+ });
150
+
151
+ it('should emit output event', () => {
152
+ const spy = jest.fn();
153
+ component.changed.subscribe(spy);
154
+
155
+ component.emitChange('new value');
156
+
157
+ expect(spy).toHaveBeenCalledWith('new value');
158
+ });
159
+ });
160
+ ```
161
+
162
+ ### Testing with Services
163
+
164
+ ```typescript
165
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
166
+
167
+ import { FeatureComponent } from './feature.component';
168
+ import { DataService } from './data.service';
169
+
170
+ describe('@mms/shared-angular: FeatureComponent', () => {
171
+ let component: FeatureComponent;
172
+ let fixture: ComponentFixture<FeatureComponent>;
173
+ let mockDataService: jest.Mocked<DataService>;
174
+
175
+ beforeEach(async () => {
176
+ mockDataService = {
177
+ getData: jest.fn().mockReturnValue(of(['item1', 'item2'])),
178
+ saveData: jest.fn().mockReturnValue(of(true)),
179
+ } as unknown as jest.Mocked<DataService>;
180
+
181
+ await TestBed.configureTestingModule({
182
+ imports: [FeatureComponent],
183
+ providers: [{ provide: DataService, useValue: mockDataService }],
184
+ }).compileComponents();
185
+
186
+ fixture = TestBed.createComponent(FeatureComponent);
187
+ component = fixture.componentInstance;
188
+ fixture.detectChanges();
189
+ });
190
+
191
+ it('should load data on init', () => {
192
+ expect(mockDataService.getData).toHaveBeenCalled();
193
+ expect(component.items()).toEqual(['item1', 'item2']);
194
+ });
195
+ });
196
+ ```
197
+
198
+ ## Angular Service Testing
199
+
200
+ ```typescript
201
+ import { TestBed } from '@angular/core/testing';
202
+ import {
203
+ HttpTestingController,
204
+ provideHttpClientTesting,
205
+ } from '@angular/common/http/testing';
206
+ import { provideHttpClient } from '@angular/common/http';
207
+
208
+ import { DataService } from './data.service';
209
+
210
+ describe('@mms/shared-angular: DataService', () => {
211
+ let service: DataService;
212
+ let httpMock: HttpTestingController;
213
+
214
+ beforeEach(() => {
215
+ TestBed.configureTestingModule({
216
+ providers: [DataService, provideHttpClient(), provideHttpClientTesting()],
217
+ });
218
+
219
+ service = TestBed.inject(DataService);
220
+ httpMock = TestBed.inject(HttpTestingController);
221
+ });
222
+
223
+ afterEach(() => {
224
+ httpMock.verify();
225
+ });
226
+
227
+ it('should be created', () => {
228
+ expect(service).toBeTruthy();
229
+ });
230
+
231
+ it('should fetch data', () => {
232
+ const mockData = [{ id: 1, name: 'Test' }];
233
+
234
+ service.getData().subscribe((data) => {
235
+ expect(data).toEqual(mockData);
236
+ });
237
+
238
+ const req = httpMock.expectOne('/api/data');
239
+ expect(req.request.method).toBe('GET');
240
+ req.flush(mockData);
241
+ });
242
+ });
243
+ ```
244
+
245
+ ## NestJS Service Testing
246
+
247
+ ### Basic Service Test
248
+
249
+ ```typescript
250
+ import { TestingModule, Test } from '@nestjs/testing';
251
+
252
+ import { FeatureService } from './feature.service';
253
+
254
+ describe('@mms/module-name: FeatureService', () => {
255
+ let service: FeatureService;
256
+ let module: TestingModule;
257
+
258
+ beforeEach(async () => {
259
+ module = await Test.createTestingModule({
260
+ providers: [FeatureService],
261
+ }).compile();
262
+
263
+ service = module.get<FeatureService>(FeatureService);
264
+ });
265
+
266
+ afterEach(async () => {
267
+ await module.close();
268
+ });
269
+
270
+ it('should be defined', () => {
271
+ expect(service).toBeDefined();
272
+ });
273
+
274
+ it('should perform expected operation', () => {
275
+ const input = 'test';
276
+
277
+ const result = service.performOperation(input);
278
+
279
+ expect(result).toBe('expected output');
280
+ });
281
+ });
282
+ ```
283
+
284
+ ### Service with Repository
285
+
286
+ ```typescript
287
+ import { TestingModule, Test } from '@nestjs/testing';
288
+ import { getRepositoryToken } from '@nestjs/typeorm';
289
+
290
+ import { UserService } from './user.service';
291
+ import { User } from './user.entity';
292
+
293
+ describe('@mms/module-name: UserService', () => {
294
+ let service: UserService;
295
+ let module: TestingModule;
296
+ let mockRepository: Record<string, jest.Mock>;
297
+
298
+ beforeEach(async () => {
299
+ mockRepository = {
300
+ findOne: jest.fn(),
301
+ find: jest.fn(),
302
+ save: jest.fn(),
303
+ update: jest.fn(),
304
+ delete: jest.fn(),
305
+ };
306
+
307
+ module = await Test.createTestingModule({
308
+ providers: [
309
+ UserService,
310
+ {
311
+ provide: getRepositoryToken(User),
312
+ useValue: mockRepository,
313
+ },
314
+ ],
315
+ }).compile();
316
+
317
+ service = module.get<UserService>(UserService);
318
+ });
319
+
320
+ afterEach(async () => {
321
+ await module.close();
322
+ });
323
+
324
+ it('should find user by id', async () => {
325
+ const mockUser = { id: '1', name: 'Test User' };
326
+ mockRepository.findOne.mockResolvedValue(mockUser);
327
+
328
+ const result = await service.findById('1');
329
+
330
+ expect(result).toEqual(mockUser);
331
+ expect(mockRepository.findOne).toHaveBeenCalledWith({ where: { id: '1' } });
332
+ });
333
+ });
334
+ ```
335
+
336
+ ## Mocking Patterns
337
+
338
+ ### HTTP Client Mock
339
+
340
+ ```typescript
341
+ const mockHttpClient = {
342
+ get: jest.fn(),
343
+ post: jest.fn(),
344
+ put: jest.fn(),
345
+ delete: jest.fn(),
346
+ };
347
+ ```
348
+
349
+ ### Service Mock
350
+
351
+ ```typescript
352
+ const mockService = {
353
+ getData: jest.fn().mockReturnValue(of(mockData)),
354
+ createItem: jest.fn().mockReturnValue(of(mockItem)),
355
+ updateItem: jest.fn().mockReturnValue(of(updatedMockItem)),
356
+ };
357
+ ```
358
+
359
+ ### LocalStorage Mock
360
+
361
+ ```typescript
362
+ let localStorageMock: any;
363
+
364
+ beforeEach(() => {
365
+ localStorageMock = (() => {
366
+ let store: Record<string, string> = {};
367
+ return {
368
+ getItem: jest.fn((key: string) => store[key] || null),
369
+ setItem: jest.fn((key: string, value: string) => {
370
+ store[key] = value;
371
+ }),
372
+ removeItem: jest.fn((key: string) => {
373
+ delete store[key];
374
+ }),
375
+ clear: jest.fn(() => {
376
+ store = {};
377
+ }),
378
+ };
379
+ })();
380
+ Object.defineProperty(window, 'localStorage', { value: localStorageMock });
381
+ });
382
+ ```
383
+
384
+ ## Test Data Factory Pattern
385
+
386
+ ```typescript
387
+ export const createMockUser = (overrides: Partial<User> = {}): User => ({
388
+ id: 'test-id',
389
+ login: 'testuser',
390
+ name: 'Test',
391
+ surname: 'User',
392
+ email: 'test@example.com',
393
+ phoneNumber: '+1234567890',
394
+ del: false,
395
+ createdAt: new Date(),
396
+ updatedAt: new Date(),
397
+ ...overrides,
398
+ });
399
+ ```
400
+
401
+ ## Test Commands
402
+
403
+ ```bash
404
+ # Run tests for specific project
405
+ nx test web
406
+ nx test shared-angular
407
+
408
+ # Run tests in watch mode
409
+ nx test web --watch
410
+
411
+ # Run tests with coverage
412
+ nx test web --coverage
413
+
414
+ # Run all tests
415
+ nx run-many --target=test
416
+
417
+ # Run specific test file
418
+ nx test shared-angular --testFile=feature.service.spec.ts
419
+ ```
420
+
421
+ ## What to Test
422
+
423
+ - Business logic in services
424
+ - Component behavior and state changes
425
+ - Public API contracts
426
+ - Error handling scenarios
427
+ - Input validation
428
+ - Edge cases and boundary conditions
429
+
430
+ ## What NOT to Test
431
+
432
+ - Third-party libraries
433
+ - Framework internals (Angular/NestJS)
434
+ - Simple getters/setters without logic
435
+ - Auto-generated code
436
+ - Private methods directly (test through public API)
437
+
438
+ ## Workflow
439
+
440
+ 1. **Read source file** to understand the code being tested
441
+ 2. **Create test file** with `.spec.ts` extension next to source
442
+ 3. **Write describe block** with package and class name
443
+ 4. **Add beforeEach** with TestBed/Test setup
444
+ 5. **Write tests** using AAA pattern
445
+ 6. **Run tests** with `nx test {project}`
446
+ 7. **Fix failures** and ensure all pass
447
+
448
+ ## Best Practices
449
+
450
+ 1. **One assertion per test** when practical
451
+ 2. **Descriptive test names** that explain behavior
452
+ 3. **Independent tests** - no shared state between tests
453
+ 4. **Mock external dependencies** - isolate unit under test
454
+ 5. **Test edge cases** - empty arrays, null values, boundaries
455
+ 6. **Keep tests fast** - avoid real HTTP calls or timers
456
+ 7. **Clean up** - use afterEach for cleanup when needed
@@ -0,0 +1,146 @@
1
+ # Flow-External Plugin for Claude Code
2
+
3
+ Development flow skills for **standalone Angular 6-11 projects** without the Pro framework. These are external projects using Angular CLI with their own styling approach (Bootstrap 4, custom SCSS, or other).
4
+
5
+ ## Target Projects
6
+
7
+ This plugin is designed for standalone Angular 6-11 projects without the Pro framework — typical use case: legacy client apps using Angular CLI with their own styling and project layout.
8
+
9
+ ### Technology Stack
10
+
11
+ | Feature | External Projects |
12
+ |---------|-------------------|
13
+ | Angular | 6 - 11 |
14
+ | Build system | Angular CLI (`ng`) |
15
+ | Styling | Project-specific (Bootstrap 4 / custom SCSS) |
16
+ | i18n | ngx-translate + LocalizeRouter |
17
+ | State | NgRx + localStorage sync |
18
+ | Project structure | Standalone (app/cli/docker) |
19
+
20
+ ### Patterns (what this plugin supports)
21
+
22
+ | Feature | External (Angular 6-11) | Legacy (Angular 14) | Modern (Angular 20+) |
23
+ |---------|-------------------------|---------------------|----------------------|
24
+ | Control flow | `*ngIf`, `*ngFor` | `*ngIf`, `*ngFor` | `@if`, `@for` |
25
+ | DI | Constructor injection | Constructor injection | `inject()` |
26
+ | Inputs/Outputs | `@Input()`, `@Output()` | `@Input()`, `@Output()` | `input()`, `output()` |
27
+ | State | BehaviorSubject, NgRx | BehaviorSubject | Signals |
28
+ | Components | NgModules | NgModules | Standalone |
29
+ | Styling | Bootstrap 4 / custom SCSS | Tailwind CSS | Tailwind CSS |
30
+ | Build | `ng build` | `nx build` | `nx build` |
31
+
32
+ ## Workflow Skills
33
+
34
+ | Skill | Description |
35
+ |-------|-------------|
36
+ | `/commit` | Create conventional commit based on Linear task |
37
+ | `/impl` | Implement plans from Linear task comments |
38
+ | `/plan` | Create implementation plan and save to Linear |
39
+ | `/push` | Push changes and update Linear status |
40
+
41
+ ## Installation
42
+
43
+ ### 1. Enable plugin in project's `.claude/settings.json`:
44
+
45
+ ```json
46
+ {
47
+ "enabledPlugins": {
48
+ "flow-external@smart-pro": true
49
+ }
50
+ }
51
+ ```
52
+
53
+ ### 2. Merge permissions from template
54
+
55
+ Run the merge script:
56
+
57
+ ```bash
58
+ node node_modules/@smartsoft001/pro-claude-plugins/plugins/flow-external/.claude-plugin/merge-permissions.js
59
+ ```
60
+
61
+ ## Required MCP Servers
62
+
63
+ Configure these in your `.mcp.json`:
64
+
65
+ - `linear` - Linear API integration (MCP prefix `mcp__linear__`)
66
+ - `playwright` - Browser automation for screenshots
67
+
68
+ ## Permission Strategy
69
+
70
+ ### Automatic (allow)
71
+ - Git read operations (status, diff, log, show)
72
+ - Angular CLI commands (ng build, ng lint, ng serve)
73
+ - Linear API (read/write issues, comments)
74
+ - Playwright (screenshots)
75
+ - Utility skills
76
+
77
+ ### Requires Confirmation (ask)
78
+ - Workflow skills (/commit, /impl, /plan, /push)
79
+ - `git commit` - creating commits
80
+ - `git push` - pushing to remote
81
+ - `gh pr create` - creating pull requests
82
+
83
+ ## Utility Skills
84
+
85
+ | Skill | Description |
86
+ |-------|-------------|
87
+ | `maia-files-upload` | Upload files to Maia API |
88
+ | `maia-files-delete` | Delete files from Maia API |
89
+ | `browser-capture` | Capture screenshots with Playwright |
90
+ | `linear-suggestion` | Create Linear issues for improvements |
91
+ | `a11y-audit` | Accessibility audit |
92
+
93
+ ## Agents
94
+
95
+ ### Angular Agents (Legacy CLI patterns)
96
+ - `angular-component-scaffolder` - Components with NgModules, `*ngIf`/`*ngFor`, constructor DI
97
+ - `angular-service-builder` - Services with BehaviorSubject, constructor DI
98
+ - `angular-state-builder` - NgRx state management with reducers and effects
99
+ - `angular-directive-builder` - Directives with constructor DI
100
+ - `angular-pipe-builder` - Pipes with constructor DI
101
+ - `angular-guard-builder` - Class-based guards with constructor DI
102
+ - `angular-resolver-builder` - Class-based resolvers with constructor DI
103
+
104
+ ### Shared Agents
105
+ - `shared-impl-orchestrator` - Implementation orchestration
106
+ - `shared-impl-reporter` - Implementation reporting
107
+ - `shared-linear-subtask-iterator` - Linear subtask iteration
108
+ - `shared-build-verifier` - Build verification via `ng build`
109
+ - `shared-ui-classifier` - UI change classification
110
+ - `ui-web-designer` - Styling with project-specific approach (Bootstrap 4 or custom SCSS)
111
+
112
+ ## Differences from other plugins
113
+
114
+ | Aspect | `flow` (modern) | `flow-legacy` | `flow-external` |
115
+ |--------|-----------------|---------------|-----------------|
116
+ | Angular version | 20+ | 14 | 6-11 |
117
+ | Build system | Nx | Nx | Angular CLI |
118
+ | Styling | Tailwind | Tailwind | Project-specific |
119
+ | State | Signals | BehaviorSubject | NgRx + BehaviorSubject |
120
+ | Project structure | Nx monorepo | Nx monorepo | Standalone app/ |
121
+
122
+ ## Example Project Structure
123
+
124
+ ```
125
+ project-root/
126
+ app/ # Frontend Angular application
127
+ src/
128
+ app/
129
+ components/
130
+ services/
131
+ pipes/
132
+ directives/
133
+ interceptors/
134
+ guards/
135
+ state/ # NgRx store
136
+ assets/
137
+ environments/
138
+ angular.json
139
+ package.json
140
+ tsconfig.json
141
+ cli/ # CLI scripts
142
+ frontend-cli
143
+ docker/ # Docker configuration
144
+ Dockerfile
145
+ .env
146
+ ```
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Merge flow-external plugin permissions into project's .claude/settings.json
4
+ *
5
+ * Usage:
6
+ * npx @smartsoft001/pro-claude-plugins flow-external:merge-permissions
7
+ *
8
+ * Or directly:
9
+ * node node_modules/@smartsoft001/pro-claude-plugins/plugins/flow-external/.claude-plugin/merge-permissions.js
10
+ */
11
+
12
+ const fs = require('fs');
13
+ const path = require('path');
14
+
15
+ const SETTINGS_PATH = path.join(process.cwd(), '.claude', 'settings.json');
16
+ const TEMPLATE_PATH = path.join(__dirname, 'settings.template.json');
17
+
18
+ function loadJson(filePath) {
19
+ try {
20
+ return JSON.parse(fs.readFileSync(filePath, 'utf8'));
21
+ } catch (e) {
22
+ return null;
23
+ }
24
+ }
25
+
26
+ function mergeArrays(existing, template) {
27
+ return [...new Set([...existing, ...template])];
28
+ }
29
+
30
+ function main() {
31
+ console.log('Flow-External Plugin - Merge Permissions\n');
32
+
33
+ // Load template
34
+ const template = loadJson(TEMPLATE_PATH);
35
+ if (!template) {
36
+ console.error('ERROR: Could not load template from:', TEMPLATE_PATH);
37
+ process.exit(1);
38
+ }
39
+
40
+ // Load or create settings
41
+ let settings = loadJson(SETTINGS_PATH);
42
+ if (!settings) {
43
+ console.log('Creating new .claude/settings.json...');
44
+ fs.mkdirSync(path.dirname(SETTINGS_PATH), { recursive: true });
45
+ settings = { permissions: { allow: [], deny: [], ask: [] } };
46
+ }
47
+
48
+ // Ensure permissions structure exists
49
+ settings.permissions = settings.permissions || {
50
+ allow: [],
51
+ deny: [],
52
+ ask: [],
53
+ };
54
+ settings.permissions.allow = settings.permissions.allow || [];
55
+ settings.permissions.ask = settings.permissions.ask || [];
56
+ settings.permissions.deny = settings.permissions.deny || [];
57
+
58
+ // Count before
59
+ const beforeAllow = settings.permissions.allow.length;
60
+ const beforeAsk = settings.permissions.ask.length;
61
+
62
+ // Merge permissions
63
+ settings.permissions.allow = mergeArrays(
64
+ settings.permissions.allow,
65
+ template.permissions.allow,
66
+ );
67
+ settings.permissions.ask = mergeArrays(
68
+ settings.permissions.ask,
69
+ template.permissions.ask,
70
+ );
71
+
72
+ // Enable plugin
73
+ settings.enabledPlugins = settings.enabledPlugins || {};
74
+ settings.enabledPlugins['flow-external@smart-pro'] = true;
75
+
76
+ // Write back
77
+ fs.writeFileSync(SETTINGS_PATH, JSON.stringify(settings, null, 2) + '\n');
78
+
79
+ // Report
80
+ const addedAllow = settings.permissions.allow.length - beforeAllow;
81
+ const addedAsk = settings.permissions.ask.length - beforeAsk;
82
+
83
+ console.log('Permissions merged successfully!\n');
84
+ console.log(
85
+ ` allow: ${beforeAllow} -> ${settings.permissions.allow.length} (+${addedAllow})`,
86
+ );
87
+ console.log(
88
+ ` ask: ${beforeAsk} -> ${settings.permissions.ask.length} (+${addedAsk})`,
89
+ );
90
+ console.log(`\nPlugin enabled: flow-external@smart-pro`);
91
+ console.log(`\nFile updated: ${SETTINGS_PATH}`);
92
+ }
93
+
94
+ main();
@@ -0,0 +1,5 @@
1
+ {
2
+ "name": "flow-external",
3
+ "description": "Development flow skills for standalone Angular 6-11 projects without framework (Angular CLI, Karma/Jasmine, Bootstrap 4)",
4
+ "version": "0.0.1"
5
+ }