nodejs-structure-cli 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 (243) hide show
  1. package/README.md +32 -0
  2. package/bin/index.js +143 -0
  3. package/lib/generator.js +145 -0
  4. package/lib/modules/app-setup.js +479 -0
  5. package/lib/modules/caching-setup.js +76 -0
  6. package/lib/modules/config-files.js +151 -0
  7. package/lib/modules/database-setup.js +116 -0
  8. package/lib/modules/kafka-setup.js +249 -0
  9. package/lib/modules/project-setup.js +32 -0
  10. package/lib/prompts.js +128 -0
  11. package/package.json +66 -0
  12. package/templates/clean-architecture/js/src/domain/models/User.js.ejs +11 -0
  13. package/templates/clean-architecture/js/src/errors/ApiError.js +14 -0
  14. package/templates/clean-architecture/js/src/errors/BadRequestError.js +11 -0
  15. package/templates/clean-architecture/js/src/errors/BadRequestError.spec.js.ejs +22 -0
  16. package/templates/clean-architecture/js/src/errors/NotFoundError.js +11 -0
  17. package/templates/clean-architecture/js/src/errors/NotFoundError.spec.js.ejs +22 -0
  18. package/templates/clean-architecture/js/src/index.js.ejs +56 -0
  19. package/templates/clean-architecture/js/src/infrastructure/config/env.js.ejs +47 -0
  20. package/templates/clean-architecture/js/src/infrastructure/log/logger.js +36 -0
  21. package/templates/clean-architecture/js/src/infrastructure/log/logger.spec.js.ejs +63 -0
  22. package/templates/clean-architecture/js/src/infrastructure/repositories/UserRepository.js.ejs +88 -0
  23. package/templates/clean-architecture/js/src/infrastructure/repositories/UserRepository.spec.js.ejs +142 -0
  24. package/templates/clean-architecture/js/src/infrastructure/webserver/middleware/errorMiddleware.js +30 -0
  25. package/templates/clean-architecture/js/src/infrastructure/webserver/server.js.ejs +93 -0
  26. package/templates/clean-architecture/js/src/infrastructure/webserver/swagger.js.ejs +6 -0
  27. package/templates/clean-architecture/js/src/interfaces/controllers/userController.js.ejs +190 -0
  28. package/templates/clean-architecture/js/src/interfaces/controllers/userController.spec.js.ejs +234 -0
  29. package/templates/clean-architecture/js/src/interfaces/graphql/context.js.ejs +13 -0
  30. package/templates/clean-architecture/js/src/interfaces/graphql/context.spec.js.ejs +31 -0
  31. package/templates/clean-architecture/js/src/interfaces/graphql/index.js.ejs +5 -0
  32. package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/index.js.ejs +6 -0
  33. package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/user.resolvers.js.ejs +27 -0
  34. package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/user.resolvers.spec.js.ejs +66 -0
  35. package/templates/clean-architecture/js/src/interfaces/graphql/typeDefs/index.js.ejs +6 -0
  36. package/templates/clean-architecture/js/src/interfaces/graphql/typeDefs/user.types.js.ejs +19 -0
  37. package/templates/clean-architecture/js/src/interfaces/routes/api.js.ejs +17 -0
  38. package/templates/clean-architecture/js/src/interfaces/routes/api.spec.js.ejs +38 -0
  39. package/templates/clean-architecture/js/src/usecases/CreateUser.js.ejs +14 -0
  40. package/templates/clean-architecture/js/src/usecases/CreateUser.spec.js.ejs +51 -0
  41. package/templates/clean-architecture/js/src/usecases/DeleteUser.js +11 -0
  42. package/templates/clean-architecture/js/src/usecases/DeleteUser.spec.js.ejs +47 -0
  43. package/templates/clean-architecture/js/src/usecases/GetAllUsers.js +12 -0
  44. package/templates/clean-architecture/js/src/usecases/GetAllUsers.spec.js.ejs +61 -0
  45. package/templates/clean-architecture/js/src/usecases/UpdateUser.js.ejs +11 -0
  46. package/templates/clean-architecture/js/src/usecases/UpdateUser.spec.js.ejs +48 -0
  47. package/templates/clean-architecture/js/src/utils/errorMessages.js +14 -0
  48. package/templates/clean-architecture/js/src/utils/httpCodes.js +9 -0
  49. package/templates/clean-architecture/ts/src/config/env.ts.ejs +46 -0
  50. package/templates/clean-architecture/ts/src/config/swagger.ts.ejs +6 -0
  51. package/templates/clean-architecture/ts/src/domain/user.ts.ejs +9 -0
  52. package/templates/clean-architecture/ts/src/errors/ApiError.ts +15 -0
  53. package/templates/clean-architecture/ts/src/errors/BadRequestError.spec.ts.ejs +22 -0
  54. package/templates/clean-architecture/ts/src/errors/BadRequestError.ts +9 -0
  55. package/templates/clean-architecture/ts/src/errors/NotFoundError.spec.ts.ejs +22 -0
  56. package/templates/clean-architecture/ts/src/errors/NotFoundError.ts +9 -0
  57. package/templates/clean-architecture/ts/src/index.ts.ejs +144 -0
  58. package/templates/clean-architecture/ts/src/infrastructure/log/logger.spec.ts.ejs +63 -0
  59. package/templates/clean-architecture/ts/src/infrastructure/log/logger.ts +36 -0
  60. package/templates/clean-architecture/ts/src/infrastructure/repositories/UserRepository.spec.ts.ejs +175 -0
  61. package/templates/clean-architecture/ts/src/infrastructure/repositories/userRepository.ts.ejs +125 -0
  62. package/templates/clean-architecture/ts/src/interfaces/controllers/userController.spec.ts.ejs +331 -0
  63. package/templates/clean-architecture/ts/src/interfaces/controllers/userController.ts.ejs +208 -0
  64. package/templates/clean-architecture/ts/src/interfaces/graphql/context.spec.ts.ejs +32 -0
  65. package/templates/clean-architecture/ts/src/interfaces/graphql/context.ts.ejs +17 -0
  66. package/templates/clean-architecture/ts/src/interfaces/graphql/index.ts.ejs +3 -0
  67. package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/index.ts.ejs +4 -0
  68. package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/user.resolvers.spec.ts.ejs +68 -0
  69. package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/user.resolvers.ts.ejs +29 -0
  70. package/templates/clean-architecture/ts/src/interfaces/graphql/typeDefs/index.ts.ejs +4 -0
  71. package/templates/clean-architecture/ts/src/interfaces/graphql/typeDefs/user.types.ts.ejs +17 -0
  72. package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.spec.ts.ejs +40 -0
  73. package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.ts.ejs +18 -0
  74. package/templates/clean-architecture/ts/src/usecases/createUser.spec.ts.ejs +51 -0
  75. package/templates/clean-architecture/ts/src/usecases/createUser.ts.ejs +11 -0
  76. package/templates/clean-architecture/ts/src/usecases/deleteUser.spec.ts.ejs +47 -0
  77. package/templates/clean-architecture/ts/src/usecases/deleteUser.ts +9 -0
  78. package/templates/clean-architecture/ts/src/usecases/getAllUsers.spec.ts.ejs +63 -0
  79. package/templates/clean-architecture/ts/src/usecases/getAllUsers.ts +10 -0
  80. package/templates/clean-architecture/ts/src/usecases/updateUser.spec.ts.ejs +48 -0
  81. package/templates/clean-architecture/ts/src/usecases/updateUser.ts.ejs +10 -0
  82. package/templates/clean-architecture/ts/src/utils/errorMessages.ts +12 -0
  83. package/templates/clean-architecture/ts/src/utils/errorMiddleware.ts.ejs +27 -0
  84. package/templates/clean-architecture/ts/src/utils/httpCodes.ts +7 -0
  85. package/templates/common/.cursorrules.ejs +60 -0
  86. package/templates/common/.dockerignore +12 -0
  87. package/templates/common/.env.example.ejs +60 -0
  88. package/templates/common/.gitattributes +46 -0
  89. package/templates/common/.gitlab-ci.yml.ejs +86 -0
  90. package/templates/common/.lintstagedrc +6 -0
  91. package/templates/common/.prettierrc +7 -0
  92. package/templates/common/.snyk.ejs +45 -0
  93. package/templates/common/Dockerfile +73 -0
  94. package/templates/common/Jenkinsfile.ejs +87 -0
  95. package/templates/common/README.md.ejs +148 -0
  96. package/templates/common/_github/workflows/ci.yml.ejs +46 -0
  97. package/templates/common/_github/workflows/security.yml.ejs +36 -0
  98. package/templates/common/_gitignore +5 -0
  99. package/templates/common/_husky/pre-commit +4 -0
  100. package/templates/common/caching/clean/js/CreateUser.js.ejs +29 -0
  101. package/templates/common/caching/clean/js/DeleteUser.js.ejs +27 -0
  102. package/templates/common/caching/clean/js/GetAllUsers.js.ejs +37 -0
  103. package/templates/common/caching/clean/js/UpdateUser.js.ejs +27 -0
  104. package/templates/common/caching/clean/ts/createUser.ts.ejs +27 -0
  105. package/templates/common/caching/clean/ts/deleteUser.ts.ejs +24 -0
  106. package/templates/common/caching/clean/ts/getAllUsers.ts.ejs +34 -0
  107. package/templates/common/caching/clean/ts/updateUser.ts.ejs +25 -0
  108. package/templates/common/caching/js/memoryCache.js.ejs +60 -0
  109. package/templates/common/caching/js/memoryCache.spec.js.ejs +101 -0
  110. package/templates/common/caching/js/redisClient.js.ejs +75 -0
  111. package/templates/common/caching/js/redisClient.spec.js.ejs +147 -0
  112. package/templates/common/caching/ts/memoryCache.spec.ts.ejs +102 -0
  113. package/templates/common/caching/ts/memoryCache.ts.ejs +73 -0
  114. package/templates/common/caching/ts/redisClient.spec.ts.ejs +157 -0
  115. package/templates/common/caching/ts/redisClient.ts.ejs +89 -0
  116. package/templates/common/database/js/database.js.ejs +19 -0
  117. package/templates/common/database/js/database.spec.js.ejs +56 -0
  118. package/templates/common/database/js/models/User.js.ejs +91 -0
  119. package/templates/common/database/js/models/User.js.mongoose.ejs +35 -0
  120. package/templates/common/database/js/models/User.spec.js.ejs +94 -0
  121. package/templates/common/database/js/mongoose.js.ejs +33 -0
  122. package/templates/common/database/js/mongoose.spec.js.ejs +43 -0
  123. package/templates/common/database/ts/database.spec.ts.ejs +56 -0
  124. package/templates/common/database/ts/database.ts.ejs +21 -0
  125. package/templates/common/database/ts/models/User.spec.ts.ejs +100 -0
  126. package/templates/common/database/ts/models/User.ts.ejs +102 -0
  127. package/templates/common/database/ts/models/User.ts.mongoose.ejs +34 -0
  128. package/templates/common/database/ts/mongoose.spec.ts.ejs +42 -0
  129. package/templates/common/database/ts/mongoose.ts.ejs +28 -0
  130. package/templates/common/docker-compose.yml.ejs +159 -0
  131. package/templates/common/ecosystem.config.js.ejs +40 -0
  132. package/templates/common/eslint.config.mjs.ejs +77 -0
  133. package/templates/common/health/js/healthRoute.js.ejs +50 -0
  134. package/templates/common/health/js/healthRoute.spec.js.ejs +70 -0
  135. package/templates/common/health/ts/healthRoute.spec.ts.ejs +76 -0
  136. package/templates/common/health/ts/healthRoute.ts.ejs +49 -0
  137. package/templates/common/jest.config.js.ejs +32 -0
  138. package/templates/common/jest.e2e.config.js.ejs +8 -0
  139. package/templates/common/kafka/js/config/kafka.js +9 -0
  140. package/templates/common/kafka/js/config/kafka.spec.js.ejs +27 -0
  141. package/templates/common/kafka/js/messaging/baseConsumer.js.ejs +30 -0
  142. package/templates/common/kafka/js/messaging/baseConsumer.spec.js.ejs +58 -0
  143. package/templates/common/kafka/js/messaging/userEventSchema.js.ejs +12 -0
  144. package/templates/common/kafka/js/messaging/userEventSchema.spec.js.ejs +27 -0
  145. package/templates/common/kafka/js/messaging/welcomeEmailConsumer.js.ejs +44 -0
  146. package/templates/common/kafka/js/messaging/welcomeEmailConsumer.spec.js.ejs +86 -0
  147. package/templates/common/kafka/js/services/kafkaService.js.ejs +93 -0
  148. package/templates/common/kafka/js/services/kafkaService.spec.js.ejs +106 -0
  149. package/templates/common/kafka/js/utils/kafkaEvents.js.ejs +7 -0
  150. package/templates/common/kafka/ts/config/kafka.spec.ts.ejs +27 -0
  151. package/templates/common/kafka/ts/config/kafka.ts +7 -0
  152. package/templates/common/kafka/ts/messaging/baseConsumer.spec.ts.ejs +50 -0
  153. package/templates/common/kafka/ts/messaging/baseConsumer.ts.ejs +27 -0
  154. package/templates/common/kafka/ts/messaging/userEventSchema.spec.ts.ejs +51 -0
  155. package/templates/common/kafka/ts/messaging/userEventSchema.ts.ejs +12 -0
  156. package/templates/common/kafka/ts/messaging/welcomeEmailConsumer.spec.ts.ejs +86 -0
  157. package/templates/common/kafka/ts/messaging/welcomeEmailConsumer.ts.ejs +38 -0
  158. package/templates/common/kafka/ts/services/kafkaService.spec.ts.ejs +81 -0
  159. package/templates/common/kafka/ts/services/kafkaService.ts.ejs +95 -0
  160. package/templates/common/kafka/ts/utils/kafkaEvents.ts.ejs +5 -0
  161. package/templates/common/migrate-mongo-config.js.ejs +31 -0
  162. package/templates/common/migrations/init.js.ejs +23 -0
  163. package/templates/common/package.json.ejs +137 -0
  164. package/templates/common/prompts/add-feature.md.ejs +26 -0
  165. package/templates/common/prompts/project-context.md.ejs +43 -0
  166. package/templates/common/prompts/troubleshoot.md.ejs +28 -0
  167. package/templates/common/public/css/style.css +147 -0
  168. package/templates/common/scripts/run-e2e.js.ejs +63 -0
  169. package/templates/common/shutdown/js/gracefulShutdown.js.ejs +65 -0
  170. package/templates/common/shutdown/js/gracefulShutdown.spec.js.ejs +149 -0
  171. package/templates/common/shutdown/ts/gracefulShutdown.spec.ts.ejs +179 -0
  172. package/templates/common/shutdown/ts/gracefulShutdown.ts.ejs +59 -0
  173. package/templates/common/sonar-project.properties.ejs +27 -0
  174. package/templates/common/src/config/auth.js.ejs +19 -0
  175. package/templates/common/src/config/auth.ts.ejs +19 -0
  176. package/templates/common/src/controllers/authController.js.ejs +101 -0
  177. package/templates/common/src/controllers/authController.ts.ejs +101 -0
  178. package/templates/common/src/middleware/auth.js.ejs +20 -0
  179. package/templates/common/src/middleware/auth.ts.ejs +25 -0
  180. package/templates/common/src/middleware/upload.js.ejs +31 -0
  181. package/templates/common/src/middleware/upload.ts.ejs +32 -0
  182. package/templates/common/src/routes/authRoutes.js.ejs +20 -0
  183. package/templates/common/src/routes/authRoutes.ts.ejs +20 -0
  184. package/templates/common/src/tests/e2e/e2e.users.test.js.ejs +120 -0
  185. package/templates/common/src/tests/e2e/e2e.users.test.ts.ejs +120 -0
  186. package/templates/common/src/utils/errorMiddleware.spec.js.ejs +79 -0
  187. package/templates/common/src/utils/errorMiddleware.spec.ts.ejs +94 -0
  188. package/templates/common/swagger.yml.ejs +118 -0
  189. package/templates/common/tsconfig.json +23 -0
  190. package/templates/common/views/ejs/index.ejs +55 -0
  191. package/templates/common/views/pug/index.pug +40 -0
  192. package/templates/db/mysql/V1__Initial_Setup.sql.ejs +10 -0
  193. package/templates/db/postgres/V1__Initial_Setup.sql.ejs +10 -0
  194. package/templates/mvc/js/src/config/env.js.ejs +46 -0
  195. package/templates/mvc/js/src/config/swagger.js.ejs +6 -0
  196. package/templates/mvc/js/src/controllers/userController.js.ejs +288 -0
  197. package/templates/mvc/js/src/controllers/userController.spec.js.ejs +481 -0
  198. package/templates/mvc/js/src/errors/ApiError.js +14 -0
  199. package/templates/mvc/js/src/errors/BadRequestError.js +11 -0
  200. package/templates/mvc/js/src/errors/BadRequestError.spec.js.ejs +22 -0
  201. package/templates/mvc/js/src/errors/NotFoundError.js +11 -0
  202. package/templates/mvc/js/src/errors/NotFoundError.spec.js.ejs +22 -0
  203. package/templates/mvc/js/src/graphql/context.js.ejs +7 -0
  204. package/templates/mvc/js/src/graphql/context.spec.js.ejs +29 -0
  205. package/templates/mvc/js/src/graphql/index.js.ejs +5 -0
  206. package/templates/mvc/js/src/graphql/resolvers/index.js.ejs +6 -0
  207. package/templates/mvc/js/src/graphql/resolvers/user.resolvers.js.ejs +25 -0
  208. package/templates/mvc/js/src/graphql/resolvers/user.resolvers.spec.js.ejs +64 -0
  209. package/templates/mvc/js/src/graphql/typeDefs/index.js.ejs +6 -0
  210. package/templates/mvc/js/src/graphql/typeDefs/user.types.js.ejs +19 -0
  211. package/templates/mvc/js/src/index.js.ejs +141 -0
  212. package/templates/mvc/js/src/routes/api.js.ejs +15 -0
  213. package/templates/mvc/js/src/routes/api.spec.js.ejs +41 -0
  214. package/templates/mvc/js/src/utils/errorMessages.js +14 -0
  215. package/templates/mvc/js/src/utils/errorMiddleware.js +29 -0
  216. package/templates/mvc/js/src/utils/httpCodes.js +9 -0
  217. package/templates/mvc/js/src/utils/logger.js +40 -0
  218. package/templates/mvc/js/src/utils/logger.spec.js.ejs +63 -0
  219. package/templates/mvc/ts/src/config/env.ts.ejs +45 -0
  220. package/templates/mvc/ts/src/config/swagger.ts.ejs +6 -0
  221. package/templates/mvc/ts/src/controllers/userController.spec.ts.ejs +481 -0
  222. package/templates/mvc/ts/src/controllers/userController.ts.ejs +292 -0
  223. package/templates/mvc/ts/src/errors/ApiError.ts +15 -0
  224. package/templates/mvc/ts/src/errors/BadRequestError.spec.ts.ejs +22 -0
  225. package/templates/mvc/ts/src/errors/BadRequestError.ts +9 -0
  226. package/templates/mvc/ts/src/errors/NotFoundError.spec.ts.ejs +27 -0
  227. package/templates/mvc/ts/src/errors/NotFoundError.ts +9 -0
  228. package/templates/mvc/ts/src/graphql/context.spec.ts.ejs +30 -0
  229. package/templates/mvc/ts/src/graphql/context.ts.ejs +12 -0
  230. package/templates/mvc/ts/src/graphql/index.ts.ejs +3 -0
  231. package/templates/mvc/ts/src/graphql/resolvers/index.ts.ejs +4 -0
  232. package/templates/mvc/ts/src/graphql/resolvers/user.resolvers.spec.ts.ejs +68 -0
  233. package/templates/mvc/ts/src/graphql/resolvers/user.resolvers.ts.ejs +29 -0
  234. package/templates/mvc/ts/src/graphql/typeDefs/index.ts.ejs +4 -0
  235. package/templates/mvc/ts/src/graphql/typeDefs/user.types.ts.ejs +17 -0
  236. package/templates/mvc/ts/src/index.ts.ejs +157 -0
  237. package/templates/mvc/ts/src/routes/api.spec.ts.ejs +59 -0
  238. package/templates/mvc/ts/src/routes/api.ts.ejs +17 -0
  239. package/templates/mvc/ts/src/utils/errorMessages.ts +12 -0
  240. package/templates/mvc/ts/src/utils/errorMiddleware.ts.ejs +27 -0
  241. package/templates/mvc/ts/src/utils/httpCodes.ts +7 -0
  242. package/templates/mvc/ts/src/utils/logger.spec.ts.ejs +63 -0
  243. package/templates/mvc/ts/src/utils/logger.ts +36 -0
@@ -0,0 +1,175 @@
1
+ import { UserRepository } from '@/infrastructure/repositories/UserRepository';
2
+ import UserModel from '@/infrastructure/database/models/User';
3
+
4
+ // Mock DB Model Database Layer
5
+ jest.mock('@/infrastructure/database/models/User');
6
+
7
+ describe('UserRepository', () => {
8
+ let userRepository: UserRepository;
9
+
10
+ beforeEach(() => {
11
+ userRepository = new UserRepository();
12
+ jest.clearAllMocks();
13
+ });
14
+
15
+ describe('save', () => {
16
+ it('should save and return a newly created user (Happy Path)', async () => {
17
+ // Arrange
18
+ const payload = { id: '', name: 'TestUser', email: 'test@example.com' };
19
+ <%_ if (database === 'MongoDB') { -%>
20
+ const mockDbRecord = { _id: { toString: () => '1' }, name: 'TestUser', email: 'test@example.com' };
21
+ (UserModel.create as jest.Mock).mockResolvedValue(mockDbRecord);
22
+ <%_ } else if (database === 'None') { -%>
23
+ (UserModel.create as jest.Mock).mockResolvedValue(payload);
24
+ <%_ } else { -%>
25
+ const mockDbRecord = { id: '1', name: 'TestUser', email: 'test@example.com' };
26
+ (UserModel.create as jest.Mock).mockResolvedValue(mockDbRecord);
27
+ <%_ } -%>
28
+
29
+ // Act
30
+ const result = await userRepository.save(payload);
31
+
32
+ // Assert
33
+ <%_ if (database === 'None') { -%>
34
+ expect(result.name).toEqual(payload.name)
35
+ <%_ } else { -%>
36
+ expect(result).toEqual({ id: '1', name: 'TestUser', email: 'test@example.com' });
37
+ expect(UserModel.create).toHaveBeenCalledWith({ name: payload.name, email: payload.email });
38
+ <%_ } -%>
39
+ });
40
+
41
+ it('should throw an error when DB fails explicitly (Edge Case)', async () => {
42
+ <%_ if (database === 'None') { -%>
43
+ // Mocks do not naturally fail
44
+ <%_ } else { -%>
45
+ // Arrange
46
+ const payload = { id: '', name: 'FailUser', email: 'fail@example.com' };
47
+ const error = new Error('DB Connection Refused');
48
+ (UserModel.create as jest.Mock).mockRejectedValue(error);
49
+
50
+ // Act & Assert
51
+ await expect(userRepository.save(payload)).rejects.toThrow(error);
52
+ <%_ } -%>
53
+ });
54
+ });
55
+
56
+ describe('getUsers', () => {
57
+ it('should return a list of mapped UserEntities (Happy Path)', async () => {
58
+ // Arrange
59
+ <%_ if (database === 'MongoDB') { -%>
60
+ const mockDbRecords = [{ _id: { toString: () => '1' }, name: 'User1', email: 'user1@example.com' }];
61
+ (UserModel.find as jest.Mock).mockResolvedValue(mockDbRecords);
62
+ <%_ } else if (database === 'None') { -%>
63
+ const mockData = [{ id: '1', name: 'User1', email: 'user1@example.com' }];
64
+ (UserModel.find as jest.Mock).mockResolvedValue(mockData);
65
+ <%_ } else { -%>
66
+ const mockDbRecords = [{ id: '1', name: 'User1', email: 'user1@example.com' }];
67
+ (UserModel.findAll as jest.Mock).mockResolvedValue(mockDbRecords);
68
+ <%_ } -%>
69
+
70
+ // Act
71
+ const result = await userRepository.getUsers();
72
+
73
+ // Assert
74
+ expect(result).toHaveLength(1);
75
+ expect(result[0]).toEqual({ id: '1', name: 'User1', email: 'user1@example.com' });
76
+ <%_ if (database !== 'None') { -%>
77
+ <%_ if (database === 'MongoDB') { -%>
78
+ expect(UserModel.find).toHaveBeenCalled();
79
+ <%_ } else { -%>
80
+ expect(UserModel.findAll).toHaveBeenCalled();
81
+ <%_ } -%>
82
+ <%_ } -%>
83
+ });
84
+ });
85
+
86
+ describe('update', () => {
87
+ it('should update and return the user (Happy Path)', async () => {
88
+ // Arrange
89
+ const id = '1';
90
+ const data = { name: 'Updated' };
91
+ const expectedUser = { id: '1', name: 'Updated', email: 'test@example.com' };
92
+
93
+ <%_ if (database === 'MongoDB') { -%>
94
+ const mockDbRecord = { _id: { toString: () => '1' }, name: 'Updated', email: 'test@example.com' };
95
+ (UserModel.findByIdAndUpdate as jest.Mock).mockResolvedValue(mockDbRecord);
96
+ <%_ } else if (database === 'None') { -%>
97
+ (UserModel.update as jest.Mock).mockResolvedValue(expectedUser);
98
+ <%_ } else { -%>
99
+ const mockDbRecord = { id: '1', name: 'Updated', email: 'test@example.com', update: jest.fn().mockResolvedValue(true) };
100
+ (UserModel.findByPk as jest.Mock).mockResolvedValue(mockDbRecord);
101
+ <%_ } -%>
102
+
103
+ // Act
104
+ const result = await userRepository.update(id, data);
105
+
106
+ // Assert
107
+ expect(result?.name).toEqual(data.name);
108
+ <%_ if (database !== 'None') { -%>
109
+ <%_ if (database === 'MongoDB') { -%>
110
+ expect(UserModel.findByIdAndUpdate).toHaveBeenCalled();
111
+ <%_ } else { -%>
112
+ expect(UserModel.findByPk).toHaveBeenCalled();
113
+ <%_ } -%>
114
+ <%_ } -%>
115
+ });
116
+
117
+ it('should return null when user not found (Error Handling)', async () => {
118
+ // Arrange
119
+ const id = '999';
120
+ <%_ if (database === 'MongoDB') { -%>
121
+ (UserModel.findByIdAndUpdate as jest.Mock).mockResolvedValue(null);
122
+ <%_ } else if (database === 'None') { -%>
123
+ (UserModel.update as jest.Mock).mockResolvedValue(null);
124
+ <%_ } else { -%>
125
+ (UserModel.findByPk as jest.Mock).mockResolvedValue(null);
126
+ <%_ } -%>
127
+
128
+ // Act
129
+ const result = await userRepository.update(id, { name: 'Fail' });
130
+
131
+ // Assert
132
+ expect(result).toBeNull();
133
+ });
134
+ });
135
+
136
+ describe('delete', () => {
137
+ it('should successfully delete a user (Happy Path)', async () => {
138
+ // Arrange
139
+ const id = '1';
140
+
141
+ <%_ if (database === 'MongoDB') { -%>
142
+ (UserModel.findByIdAndDelete as jest.Mock).mockResolvedValue(true);
143
+ <%_ } else if (database === 'None') { -%>
144
+ (UserModel.destroy as jest.Mock).mockResolvedValue(true);
145
+ <%_ } else { -%>
146
+ const mockDbRecord = { id: '1', destroy: jest.fn().mockResolvedValue(true) };
147
+ (UserModel.findByPk as jest.Mock).mockResolvedValue(mockDbRecord);
148
+ <%_ } -%>
149
+
150
+ // Act
151
+ const result = await userRepository.delete(id);
152
+
153
+ // Assert
154
+ expect(result).toBe(true);
155
+ });
156
+
157
+ it('should return false when user not found during deletion (Error Handling)', async () => {
158
+ // Arrange
159
+ const id = '999';
160
+ <%_ if (database === 'MongoDB') { -%>
161
+ (UserModel.findByIdAndDelete as jest.Mock).mockResolvedValue(null);
162
+ <%_ } else if (database === 'None') { -%>
163
+ (UserModel.destroy as jest.Mock).mockResolvedValue(false);
164
+ <%_ } else { -%>
165
+ (UserModel.findByPk as jest.Mock).mockResolvedValue(null);
166
+ <%_ } -%>
167
+
168
+ // Act
169
+ const result = await userRepository.delete(id);
170
+
171
+ // Assert
172
+ expect(result).toBe(false);
173
+ });
174
+ });
175
+ });
@@ -0,0 +1,125 @@
1
+ import { User as UserEntity } from '@/domain/user';
2
+ import UserModel from '@/infrastructure/database/models/User';
3
+
4
+ export class UserRepository {
5
+ async save(user: UserEntity): Promise<UserEntity> {
6
+ <%_ if (database === 'MongoDB') { -%>
7
+ const userData = { name: user.name, email: user.email };
8
+ <% if (auth && auth !== 'None') { %>if (user.password) (userData as any).password = user.password;<% } %>
9
+ <% if (includeMulter) { %>if (user.imageUrl) (userData as any).imageUrl = user.imageUrl;<% } %>
10
+ const newUser = await UserModel.create(userData);
11
+ return {
12
+ id: newUser._id.toString(),
13
+ name: newUser.name,
14
+ email: newUser.email,
15
+ <% if (auth && auth !== 'None') { %>password: (newUser as any).password,<% } %>
16
+ <% if (includeMulter) { %>imageUrl: (newUser as any).imageUrl,<% } %>
17
+ };
18
+ <%_ } else if (database === 'None') { -%>
19
+ const userData = { name: user.name, email: user.email };
20
+ <% if (auth && auth !== 'None') { %>if (user.password) (userData as any).password = user.password;<% } %>
21
+ <% if (includeMulter) { %>if (user.imageUrl) (userData as any).imageUrl = user.imageUrl;<% } %>
22
+ const newUser = await UserModel.create(userData);
23
+ return {
24
+ id: newUser.id,
25
+ name: newUser.name,
26
+ email: newUser.email,
27
+ <% if (auth && auth !== 'None') { %>password: (newUser as any).password,<% } %>
28
+ <% if (includeMulter) { %>imageUrl: (newUser as any).imageUrl,<% } %>
29
+ };
30
+ <%_ } else { -%>
31
+ const userData = { name: user.name, email: user.email };
32
+ <% if (auth && auth !== 'None') { %>if (user.password) (userData as any).password = user.password;<% } %>
33
+ <% if (includeMulter) { %>if (user.imageUrl) (userData as any).imageUrl = user.imageUrl;<% } %>
34
+ const newUser = await UserModel.create(userData);
35
+ return {
36
+ id: newUser.id,
37
+ name: newUser.name,
38
+ email: newUser.email,
39
+ <% if (auth && auth !== 'None') { %>password: (newUser as any).password,<% } %>
40
+ <% if (includeMulter) { %>imageUrl: (newUser as any).imageUrl,<% } %>
41
+ };
42
+ <%_ } -%>
43
+ }
44
+
45
+ async getUsers(): Promise<UserEntity[]> {
46
+ <%_ if (database === 'MongoDB') { -%>
47
+ const users = await UserModel.find();
48
+ return users.map(user => ({
49
+ id: user._id.toString(),
50
+ name: user.name,
51
+ email: user.email,
52
+ <% if (auth && auth !== 'None') { %>password: (user as any).password,<% } %>
53
+ <% if (includeMulter) { %>imageUrl: (user as any).imageUrl,<% } %>
54
+ }));
55
+ <%_ } else if (database === 'None') { -%>
56
+ const users = await UserModel.find();
57
+ return users.map(user => ({
58
+ id: user.id,
59
+ name: user.name,
60
+ email: user.email,
61
+ <% if (auth && auth !== 'None') { %>password: (user as any).password,<% } %>
62
+ <% if (includeMulter) { %>imageUrl: (user as any).imageUrl,<% } %>
63
+ }));
64
+ <%_ } else { -%>
65
+ const users = await UserModel.findAll();
66
+ return users.map(user => ({
67
+ id: user.id,
68
+ name: user.name,
69
+ email: user.email,
70
+ <% if (auth && auth !== 'None') { %>password: (user as any).password,<% } %>
71
+ <% if (includeMulter) { %>imageUrl: (user as any).imageUrl,<% } %>
72
+ }));
73
+ <%_ } -%>
74
+ }
75
+
76
+ async update(id: number | string, data: Partial<UserEntity>): Promise<UserEntity | null> {
77
+ <%_ if (database === 'MongoDB') { -%>
78
+ const user = await UserModel.findByIdAndUpdate(id, data, { new: true });
79
+ if (!user) return null;
80
+ return {
81
+ id: user._id.toString(),
82
+ name: user.name,
83
+ email: user.email,
84
+ <% if (auth && auth !== 'None') { %>password: (user as any).password,<% } %>
85
+ <% if (includeMulter) { %>imageUrl: (user as any).imageUrl,<% } %>
86
+ };
87
+ <%_ } else if (database === 'None') { -%>
88
+ const { id: _, ...updateData } = data;
89
+ const user = await UserModel.update(id, updateData as Parameters<typeof UserModel.update>[1]);
90
+ if (!user) return null;
91
+ return {
92
+ id: user.id,
93
+ name: user.name,
94
+ email: user.email,
95
+ <% if (auth && auth !== 'None') { %>password: (user as any).password,<% } %>
96
+ <% if (includeMulter) { %>imageUrl: (user as any).imageUrl,<% } %>
97
+ };
98
+ <%_ } else { -%>
99
+ const user = await UserModel.findByPk(id);
100
+ if (!user) return null;
101
+ await user.update(data);
102
+ return {
103
+ id: user.id || 0,
104
+ name: user.name,
105
+ email: user.email,
106
+ <% if (auth && auth !== 'None') { %>password: (user as any).password,<% } %>
107
+ <% if (includeMulter) { %>imageUrl: (user as any).imageUrl,<% } %>
108
+ };
109
+ <%_ } -%>
110
+ }
111
+
112
+ async delete(id: number | string): Promise<boolean> {
113
+ <%_ if (database === 'MongoDB') { -%>
114
+ const result = await UserModel.findByIdAndDelete(id);
115
+ return !!result;
116
+ <%_ } else if (database === 'None') { -%>
117
+ return await UserModel.destroy(id);
118
+ <%_ } else { -%>
119
+ const user = await UserModel.findByPk(id);
120
+ if (!user) return false;
121
+ await user.destroy();
122
+ return true;
123
+ <%_ } -%>
124
+ }
125
+ }
@@ -0,0 +1,331 @@
1
+ <% if (communication !== 'GraphQL') { -%>
2
+ import { Request, Response, NextFunction } from 'express';
3
+ import { HTTP_STATUS } from '@/utils/httpCodes';
4
+ <% } -%>
5
+ import { ERROR_MESSAGES } from '@/utils/errorMessages';
6
+ import { UserController } from '@/interfaces/controllers/userController';
7
+ import CreateUser from '@/usecases/createUser';
8
+ import GetAllUsers from '@/usecases/getAllUsers';
9
+ import UpdateUser from '@/usecases/updateUser';
10
+ import DeleteUser from '@/usecases/deleteUser';
11
+
12
+ // Mock dependencies
13
+ jest.mock('@/infrastructure/repositories/UserRepository');
14
+ jest.mock('@/usecases/createUser');
15
+ jest.mock('@/usecases/getAllUsers');
16
+ jest.mock('@/usecases/updateUser');
17
+ jest.mock('@/usecases/deleteUser');
18
+ jest.mock('@/infrastructure/log/logger');
19
+ <%_ if (communication === 'Kafka') { -%>
20
+ jest.mock('@/infrastructure/messaging/kafkaClient', () => ({
21
+ kafkaService: {
22
+ sendMessage: jest.fn().mockResolvedValue(undefined)
23
+ },
24
+ KafkaService: jest.fn().mockImplementation(() => ({
25
+ sendMessage: jest.fn().mockResolvedValue(undefined)
26
+ }))
27
+ }));
28
+ const { kafkaService } = require('@/infrastructure/messaging/kafkaClient');
29
+ <%_ } -%>
30
+
31
+
32
+ describe('UserController (Clean Architecture)', () => {
33
+ let userController: UserController;
34
+ let mockCreateUserUseCase: jest.Mocked<CreateUser>;
35
+ let mockGetAllUsersUseCase: jest.Mocked<GetAllUsers>;
36
+ let mockUpdateUserUseCase: jest.Mocked<UpdateUser>;
37
+ let mockDeleteUserUseCase: jest.Mocked<DeleteUser>;
38
+ <% if (communication !== 'GraphQL') { -%>
39
+ let mockRequest: Partial<Request>;
40
+ let mockResponse: Partial<Response>;
41
+ let mockNext: NextFunction;
42
+ <% } -%>
43
+
44
+ beforeEach(() => {
45
+ // Clear all mocks
46
+ jest.resetAllMocks();
47
+
48
+ userController = new UserController();
49
+
50
+ // Retrieve the mocked instances created inside UserController constructor
51
+ mockCreateUserUseCase = (CreateUser as jest.Mock).mock.instances[0] as jest.Mocked<CreateUser>;
52
+ mockGetAllUsersUseCase = (GetAllUsers as jest.Mock).mock.instances[0] as jest.Mocked<GetAllUsers>;
53
+ mockUpdateUserUseCase = (UpdateUser as jest.Mock).mock.instances[0] as jest.Mocked<UpdateUser>;
54
+ mockDeleteUserUseCase = (DeleteUser as jest.Mock).mock.instances[0] as jest.Mocked<DeleteUser>;
55
+
56
+ <% if (communication !== 'GraphQL') { -%>
57
+ mockRequest = {
58
+ body: {}
59
+ };
60
+ mockResponse = {
61
+ json: jest.fn(),
62
+ status: jest.fn().mockReturnThis(),
63
+ };
64
+ mockNext = jest.fn();
65
+ <% } -%>
66
+ });
67
+
68
+ describe('getUsers', () => {
69
+ it('should return successfully (Happy Path)', async () => {
70
+ // Arrange
71
+ const usersMock = [{ id: '1', name: 'Test', email: 'test@example.com' }];
72
+ mockGetAllUsersUseCase.execute.mockResolvedValue(usersMock);
73
+
74
+ // Act
75
+ <% if (communication === 'GraphQL') { -%>
76
+ const result = await userController.getUsers();
77
+
78
+ // Assert
79
+ expect(result).toEqual(usersMock);
80
+ <% } else { -%>
81
+ await userController.getUsers(mockRequest as Request, mockResponse as Response, mockNext);
82
+
83
+ // Assert
84
+ expect(mockResponse.json).toHaveBeenCalledWith(usersMock);
85
+ <% } -%>
86
+ expect(mockGetAllUsersUseCase.execute).toHaveBeenCalled();
87
+ });
88
+
89
+ it('should handle errors correctly (Error Handling)', async () => {
90
+ // Arrange
91
+ const error = new Error('UseCase Error');
92
+ mockGetAllUsersUseCase.execute.mockRejectedValue(error);
93
+
94
+ // Act & Assert
95
+ <% if (communication === 'GraphQL') { -%>
96
+ await expect(userController.getUsers()).rejects.toThrow(error);
97
+ <% } else { -%>
98
+ await userController.getUsers(mockRequest as Request, mockResponse as Response, mockNext);
99
+ expect(mockNext).toHaveBeenCalledWith(error);
100
+ <% } -%>
101
+ });
102
+
103
+ it('should handle non-Error objects in catch block', async () => {
104
+ // Arrange
105
+ const error = 'String Error';
106
+ mockGetAllUsersUseCase.execute.mockRejectedValue(error);
107
+
108
+ // Act & Assert
109
+ <% if (communication === 'GraphQL') { -%>
110
+ await expect(userController.getUsers()).rejects.toEqual(error);
111
+ <% } else { -%>
112
+ await userController.getUsers(mockRequest as Request, mockResponse as Response, mockNext);
113
+ expect(mockNext).toHaveBeenCalledWith(error);
114
+ <% } -%>
115
+ });
116
+ });
117
+
118
+ describe('createUser', () => {
119
+ it('should successfully create a new user (Happy Path)', async () => {
120
+ // Arrange
121
+ const payload = { name: 'Alice', email: 'alice@example.com' };
122
+ <% if (communication === 'GraphQL') { -%>
123
+ const dataArg = payload;
124
+ <% } else { -%>
125
+ mockRequest.body = payload;
126
+ <% } -%>
127
+ const expectedUser = { id: '1', ...payload };
128
+
129
+ mockCreateUserUseCase.execute.mockResolvedValue(expectedUser);
130
+
131
+ // Act
132
+ <% if (communication === 'GraphQL') { -%>
133
+ const result = await userController.createUser(dataArg);
134
+
135
+ // Assert
136
+ expect(result).toEqual(expectedUser);
137
+ <% } else { -%>
138
+ await userController.createUser(mockRequest as Request, mockResponse as Response, mockNext);
139
+
140
+ // Assert
141
+ <%_ if (communication === 'Kafka') { -%>
142
+ const { kafkaService } = require('@/infrastructure/messaging/kafkaClient');
143
+ expect(kafkaService.sendMessage).toHaveBeenCalled();
144
+ <%_ } -%>
145
+ expect(mockResponse.status).toHaveBeenCalledWith(HTTP_STATUS.CREATED);
146
+
147
+ expect(mockResponse.json).toHaveBeenCalledWith(expectedUser);
148
+ <% } -%>
149
+ expect(mockCreateUserUseCase.execute).toHaveBeenCalledWith(payload.name, payload.email);
150
+ });
151
+
152
+ it('should handle errors when creation fails (Error Handling)', async () => {
153
+ // Arrange
154
+ const error = new Error('Creation Error');
155
+ const payload = { name: 'Bob', email: 'bob@example.com' };
156
+ <% if (communication === 'GraphQL') { -%>
157
+ const dataArg = payload;
158
+ <% } else { -%>
159
+ mockRequest.body = payload;
160
+ <% } -%>
161
+
162
+ mockCreateUserUseCase.execute.mockRejectedValue(error);
163
+
164
+ // Act & Assert
165
+ <% if (communication === 'GraphQL') { -%>
166
+ await expect(userController.createUser(dataArg)).rejects.toThrow(error);
167
+ <% } else { -%>
168
+ await userController.createUser(mockRequest as Request, mockResponse as Response, mockNext);
169
+ expect(mockNext).toHaveBeenCalledWith(error);
170
+ <% } -%>
171
+ });
172
+
173
+ it('should handle non-Error objects in catch block when creation fails', async () => {
174
+ // Arrange
175
+ const error = 'Creation String Error';
176
+ const payload = { name: 'Bob', email: 'bob@example.com' };
177
+ <% if (communication === 'GraphQL') { -%>
178
+ const dataArg = payload;
179
+ <% } else { -%>
180
+ mockRequest.body = payload;
181
+ <% } -%>
182
+
183
+ mockCreateUserUseCase.execute.mockRejectedValue(error);
184
+
185
+ // Act & Assert
186
+ <% if (communication === 'GraphQL') { -%>
187
+ await expect(userController.createUser(dataArg)).rejects.toEqual(error);
188
+ <% } else { -%>
189
+ await userController.createUser(mockRequest as Request, mockResponse as Response, mockNext);
190
+ expect(mockNext).toHaveBeenCalledWith(error);
191
+ <% } -%>
192
+ });
193
+ });
194
+
195
+ describe('updateUser', () => {
196
+ it('should successfully update a user (Happy Path)', async () => {
197
+ // Arrange
198
+ const id = '1';
199
+ const payload = { name: 'Alice Updated' };
200
+ <% if (communication === 'GraphQL') { -%>
201
+ const idArg = id;
202
+ const dataArg = payload;
203
+ <% } else { -%>
204
+ mockRequest.params = { id };
205
+ mockRequest.body = payload;
206
+ <% } -%>
207
+ const expectedUser = { id, name: 'Alice Updated', email: 'alice@example.com' };
208
+
209
+ mockUpdateUserUseCase.execute.mockResolvedValue(expectedUser as any);
210
+
211
+ // Act
212
+ <% if (communication === 'GraphQL') { -%>
213
+ const result = await userController.updateUser(idArg, dataArg);
214
+ expect(result).toEqual(expectedUser);
215
+ <% } else { -%>
216
+ await userController.updateUser(mockRequest as Request, mockResponse as Response, mockNext);
217
+ expect(mockResponse.json).toHaveBeenCalledWith(expectedUser);
218
+ <% } -%>
219
+
220
+ <%_ if (communication === 'Kafka') { -%>
221
+ const { kafkaService } = require('@/infrastructure/messaging/kafkaClient');
222
+ expect(kafkaService.sendMessage).toHaveBeenCalled();
223
+ <%_ } -%>
224
+ expect(mockUpdateUserUseCase.execute).toHaveBeenCalledWith(id, payload);
225
+ });
226
+
227
+ it('should handle 404/errors when user not found or update fails', async () => {
228
+ // Arrange
229
+ const id = '999';
230
+ <%_ if (communication === 'GraphQL') { -%>
231
+ const idArg = id;
232
+ const dataArg = { name: 'Fail' };
233
+ mockUpdateUserUseCase.execute.mockResolvedValue(null);
234
+ await expect(userController.updateUser(idArg, dataArg)).rejects.toThrow(ERROR_MESSAGES.USER_NOT_FOUND);
235
+ <%_ } else { -%>
236
+ mockRequest.params = { id };
237
+ mockRequest.body = { name: 'Fail' };
238
+ mockUpdateUserUseCase.execute.mockResolvedValue(null);
239
+
240
+ // Act
241
+ await userController.updateUser(mockRequest as Request, mockResponse as Response, mockNext);
242
+ expect(mockResponse.status).toHaveBeenCalledWith(HTTP_STATUS.NOT_FOUND);
243
+ <%_ } -%>
244
+ });
245
+
246
+ it('should handle database errors during update (Error Handling)', async () => {
247
+ // Arrange
248
+ const id = '1';
249
+ const error = new Error('Database Error');
250
+ mockUpdateUserUseCase.execute.mockRejectedValue(error);
251
+ <%_ if (communication === 'GraphQL') { -%>
252
+ await expect(userController.updateUser(id, { name: 'Fail' })).rejects.toThrow(error);
253
+ <%_ } else { -%>
254
+ mockRequest.params = { id };
255
+ await userController.updateUser(mockRequest as Request, mockResponse as Response, mockNext);
256
+ expect(mockNext).toHaveBeenCalledWith(error);
257
+ <%_ } -%>
258
+ });
259
+ });
260
+
261
+ describe('deleteUser', () => {
262
+ it('should successfully delete a user (Happy Path)', async () => {
263
+ // Arrange
264
+ const id = '1';
265
+ <% if (communication === 'GraphQL') { -%>
266
+ const idArg = id;
267
+ <% } else { -%>
268
+ mockRequest.params = { id };
269
+ <% } -%>
270
+ mockDeleteUserUseCase.execute.mockResolvedValue(true);
271
+
272
+ // Act
273
+ <% if (communication === 'GraphQL') { -%>
274
+ const result = await userController.deleteUser(idArg);
275
+ expect(result).toBe(true);
276
+ <% } else { -%>
277
+ await userController.deleteUser(mockRequest as Request, mockResponse as Response, mockNext);
278
+ expect(mockResponse.status).toHaveBeenCalledWith(HTTP_STATUS.OK);
279
+ <% } -%>
280
+
281
+ <%_ if (communication === 'Kafka') { -%>
282
+ const { kafkaService } = require('@/infrastructure/messaging/kafkaClient');
283
+ expect(kafkaService.sendMessage).toHaveBeenCalled();
284
+ <%_ } -%>
285
+ expect(mockDeleteUserUseCase.execute).toHaveBeenCalledWith(id);
286
+ });
287
+
288
+ it('should throw error if user not found during deletion (Error Handling)', async () => {
289
+ // Arrange
290
+ const id = '999';
291
+ <%_ if (communication === 'GraphQL') { -%>
292
+ mockDeleteUserUseCase.execute.mockResolvedValue(false);
293
+ await expect(userController.deleteUser(id)).rejects.toThrow(ERROR_MESSAGES.USER_NOT_FOUND);
294
+ <%_ } else { -%>
295
+ mockRequest.params = { id };
296
+ mockDeleteUserUseCase.execute.mockResolvedValue(false);
297
+ await userController.deleteUser(mockRequest as Request, mockResponse as Response, mockNext);
298
+ expect(mockResponse.status).toHaveBeenCalledWith(HTTP_STATUS.NOT_FOUND);
299
+ <%_ } -%>
300
+ });
301
+
302
+ it('should handle database errors during deletion (Error Handling)', async () => {
303
+ // Arrange
304
+ const id = '1';
305
+ const error = new Error('Database Error');
306
+ mockDeleteUserUseCase.execute.mockRejectedValue(error);
307
+ <%_ if (communication === 'GraphQL') { -%>
308
+ await expect(userController.deleteUser(id)).rejects.toThrow(error);
309
+ <%_ } else { -%>
310
+ mockRequest.params = { id };
311
+ await userController.deleteUser(mockRequest as Request, mockResponse as Response, mockNext);
312
+ expect(mockNext).toHaveBeenCalledWith(error);
313
+ <%_ } -%>
314
+ });
315
+ });
316
+
317
+
318
+ describe('createUser Error Paths', () => {
319
+ it('should handle database errors during creation (Error Handling)', async () => {
320
+ const error = new Error('Database Error');
321
+ mockCreateUserUseCase.execute.mockRejectedValue(error);
322
+ <%_ if (communication === 'GraphQL') { -%>
323
+ await expect(userController.createUser({ name: 'Alice', email: 'alice@example.com' })).rejects.toThrow(error);
324
+ <%_ } else { -%>
325
+ mockRequest.body = { name: 'Alice', email: 'alice@example.com' };
326
+ await userController.createUser(mockRequest as Request, mockResponse as Response, mockNext);
327
+ expect(mockNext).toHaveBeenCalledWith(error);
328
+ <%_ } -%>
329
+ });
330
+ });
331
+ });