nodejs-quickstart-structure 1.18.1 → 1.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (235) hide show
  1. package/CHANGELOG.md +309 -294
  2. package/LICENSE +15 -15
  3. package/README.md +2 -1
  4. package/lib/generator.js +139 -139
  5. package/lib/modules/app-setup.js +401 -401
  6. package/lib/modules/caching-setup.js +76 -73
  7. package/lib/modules/config-files.js +151 -151
  8. package/lib/modules/database-setup.js +116 -116
  9. package/lib/modules/kafka-setup.js +249 -191
  10. package/lib/modules/project-setup.js +32 -31
  11. package/lib/prompts.js +100 -100
  12. package/package.json +78 -67
  13. package/templates/clean-architecture/js/src/domain/models/User.js +9 -9
  14. package/templates/clean-architecture/js/src/errors/ApiError.js +14 -14
  15. package/templates/clean-architecture/js/src/errors/BadRequestError.js +11 -10
  16. package/templates/clean-architecture/js/src/errors/BadRequestError.spec.js.ejs +22 -21
  17. package/templates/clean-architecture/js/src/errors/NotFoundError.js +11 -10
  18. package/templates/clean-architecture/js/src/errors/NotFoundError.spec.js.ejs +22 -21
  19. package/templates/clean-architecture/js/src/index.js.ejs +55 -55
  20. package/templates/clean-architecture/js/src/infrastructure/config/env.js.ejs +47 -47
  21. package/templates/clean-architecture/js/src/infrastructure/log/logger.js +36 -36
  22. package/templates/clean-architecture/js/src/infrastructure/log/logger.spec.js.ejs +63 -63
  23. package/templates/clean-architecture/js/src/infrastructure/repositories/UserRepository.js.ejs +69 -39
  24. package/templates/clean-architecture/js/src/infrastructure/repositories/UserRepository.spec.js.ejs +142 -81
  25. package/templates/clean-architecture/js/src/infrastructure/webserver/middleware/errorMiddleware.js +30 -30
  26. package/templates/clean-architecture/js/src/infrastructure/webserver/server.js.ejs +89 -89
  27. package/templates/clean-architecture/js/src/infrastructure/webserver/swagger.js.ejs +6 -6
  28. package/templates/clean-architecture/js/src/interfaces/controllers/userController.js.ejs +156 -75
  29. package/templates/clean-architecture/js/src/interfaces/controllers/userController.spec.js.ejs +234 -138
  30. package/templates/clean-architecture/js/src/interfaces/graphql/context.js.ejs +13 -13
  31. package/templates/clean-architecture/js/src/interfaces/graphql/context.spec.js.ejs +31 -31
  32. package/templates/clean-architecture/js/src/interfaces/graphql/index.js.ejs +5 -5
  33. package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/index.js.ejs +6 -6
  34. package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/user.resolvers.js.ejs +27 -21
  35. package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/user.resolvers.spec.js.ejs +66 -49
  36. package/templates/clean-architecture/js/src/interfaces/graphql/typeDefs/index.js.ejs +6 -6
  37. package/templates/clean-architecture/js/src/interfaces/graphql/typeDefs/user.types.js.ejs +19 -17
  38. package/templates/clean-architecture/js/src/interfaces/routes/api.js +12 -10
  39. package/templates/clean-architecture/js/src/interfaces/routes/api.spec.js.ejs +38 -38
  40. package/templates/clean-architecture/js/src/usecases/CreateUser.js +14 -14
  41. package/templates/clean-architecture/js/src/usecases/CreateUser.spec.js.ejs +51 -51
  42. package/templates/clean-architecture/js/src/usecases/DeleteUser.js +11 -0
  43. package/templates/clean-architecture/js/src/usecases/DeleteUser.spec.js.ejs +47 -0
  44. package/templates/clean-architecture/js/src/usecases/GetAllUsers.js +12 -12
  45. package/templates/clean-architecture/js/src/usecases/GetAllUsers.spec.js.ejs +61 -61
  46. package/templates/clean-architecture/js/src/usecases/UpdateUser.js +11 -0
  47. package/templates/clean-architecture/js/src/usecases/UpdateUser.spec.js.ejs +48 -0
  48. package/templates/clean-architecture/js/src/utils/errorMessages.js +14 -0
  49. package/templates/clean-architecture/js/src/utils/httpCodes.js +9 -9
  50. package/templates/clean-architecture/ts/src/config/env.ts.ejs +46 -46
  51. package/templates/clean-architecture/ts/src/config/swagger.ts.ejs +6 -6
  52. package/templates/clean-architecture/ts/src/domain/user.ts +7 -7
  53. package/templates/clean-architecture/ts/src/errors/ApiError.ts +15 -15
  54. package/templates/clean-architecture/ts/src/errors/BadRequestError.spec.ts.ejs +22 -21
  55. package/templates/clean-architecture/ts/src/errors/BadRequestError.ts +9 -8
  56. package/templates/clean-architecture/ts/src/errors/NotFoundError.spec.ts.ejs +22 -21
  57. package/templates/clean-architecture/ts/src/errors/NotFoundError.ts +9 -8
  58. package/templates/clean-architecture/ts/src/index.ts.ejs +139 -139
  59. package/templates/clean-architecture/ts/src/infrastructure/log/logger.spec.ts.ejs +63 -63
  60. package/templates/clean-architecture/ts/src/infrastructure/log/logger.ts +36 -36
  61. package/templates/clean-architecture/ts/src/infrastructure/repositories/UserRepository.spec.ts.ejs +175 -85
  62. package/templates/clean-architecture/ts/src/infrastructure/repositories/userRepository.ts.ejs +74 -0
  63. package/templates/clean-architecture/ts/src/interfaces/controllers/userController.spec.ts.ejs +331 -185
  64. package/templates/clean-architecture/ts/src/interfaces/controllers/userController.ts.ejs +173 -84
  65. package/templates/clean-architecture/ts/src/interfaces/graphql/context.spec.ts.ejs +32 -32
  66. package/templates/clean-architecture/ts/src/interfaces/graphql/context.ts.ejs +17 -17
  67. package/templates/clean-architecture/ts/src/interfaces/graphql/index.ts.ejs +3 -3
  68. package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/index.ts.ejs +4 -4
  69. package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/user.resolvers.spec.ts.ejs +68 -51
  70. package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/user.resolvers.ts.ejs +29 -21
  71. package/templates/clean-architecture/ts/src/interfaces/graphql/typeDefs/index.ts.ejs +4 -4
  72. package/templates/clean-architecture/ts/src/interfaces/graphql/typeDefs/user.types.ts.ejs +17 -15
  73. package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.spec.ts.ejs +40 -40
  74. package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.ts +13 -11
  75. package/templates/clean-architecture/ts/src/usecases/createUser.spec.ts.ejs +51 -51
  76. package/templates/clean-architecture/ts/src/usecases/createUser.ts +13 -13
  77. package/templates/clean-architecture/ts/src/usecases/deleteUser.spec.ts.ejs +47 -0
  78. package/templates/clean-architecture/ts/src/usecases/deleteUser.ts +9 -0
  79. package/templates/clean-architecture/ts/src/usecases/getAllUsers.spec.ts.ejs +63 -63
  80. package/templates/clean-architecture/ts/src/usecases/getAllUsers.ts +10 -10
  81. package/templates/clean-architecture/ts/src/usecases/updateUser.spec.ts.ejs +48 -0
  82. package/templates/clean-architecture/ts/src/usecases/updateUser.ts +9 -0
  83. package/templates/clean-architecture/ts/src/utils/errorMessages.ts +12 -0
  84. package/templates/clean-architecture/ts/src/utils/errorMiddleware.ts.ejs +27 -27
  85. package/templates/clean-architecture/ts/src/utils/httpCodes.ts +7 -7
  86. package/templates/common/.cursorrules.ejs +60 -60
  87. package/templates/common/.dockerignore +12 -12
  88. package/templates/common/.env.example.ejs +41 -41
  89. package/templates/common/.gitattributes +46 -0
  90. package/templates/common/.gitlab-ci.yml.ejs +86 -86
  91. package/templates/common/.lintstagedrc +6 -6
  92. package/templates/common/.prettierrc +7 -7
  93. package/templates/common/Dockerfile +73 -73
  94. package/templates/common/Jenkinsfile.ejs +87 -87
  95. package/templates/common/README.md.ejs +294 -270
  96. package/templates/common/SECURITY.md +20 -20
  97. package/templates/common/_github/workflows/ci.yml.ejs +46 -46
  98. package/templates/common/_github/workflows/security.yml.ejs +36 -36
  99. package/templates/common/_gitignore +5 -5
  100. package/templates/common/_husky/pre-commit +4 -4
  101. package/templates/common/caching/clean/js/CreateUser.js.ejs +29 -29
  102. package/templates/common/caching/clean/js/DeleteUser.js.ejs +27 -0
  103. package/templates/common/caching/clean/js/GetAllUsers.js.ejs +37 -37
  104. package/templates/common/caching/clean/js/UpdateUser.js.ejs +27 -0
  105. package/templates/common/caching/clean/ts/createUser.ts.ejs +27 -27
  106. package/templates/common/caching/clean/ts/deleteUser.ts.ejs +24 -0
  107. package/templates/common/caching/clean/ts/getAllUsers.ts.ejs +34 -34
  108. package/templates/common/caching/clean/ts/updateUser.ts.ejs +25 -0
  109. package/templates/common/caching/js/memoryCache.js.ejs +60 -60
  110. package/templates/common/caching/js/memoryCache.spec.js.ejs +101 -101
  111. package/templates/common/caching/js/redisClient.js.ejs +75 -75
  112. package/templates/common/caching/js/redisClient.spec.js.ejs +147 -147
  113. package/templates/common/caching/ts/memoryCache.spec.ts.ejs +102 -102
  114. package/templates/common/caching/ts/memoryCache.ts.ejs +73 -64
  115. package/templates/common/caching/ts/redisClient.spec.ts.ejs +157 -157
  116. package/templates/common/caching/ts/redisClient.ts.ejs +89 -80
  117. package/templates/common/database/js/database.js.ejs +19 -19
  118. package/templates/common/database/js/database.spec.js.ejs +56 -56
  119. package/templates/common/database/js/models/User.js.ejs +79 -53
  120. package/templates/common/database/js/models/User.js.mongoose.ejs +23 -19
  121. package/templates/common/database/js/models/User.spec.js.ejs +94 -84
  122. package/templates/common/database/js/mongoose.js.ejs +33 -33
  123. package/templates/common/database/js/mongoose.spec.js.ejs +43 -43
  124. package/templates/common/database/ts/database.spec.ts.ejs +56 -56
  125. package/templates/common/database/ts/database.ts.ejs +21 -21
  126. package/templates/common/database/ts/models/User.spec.ts.ejs +100 -84
  127. package/templates/common/database/ts/models/User.ts.ejs +87 -61
  128. package/templates/common/database/ts/models/User.ts.mongoose.ejs +30 -25
  129. package/templates/common/database/ts/mongoose.spec.ts.ejs +42 -42
  130. package/templates/common/database/ts/mongoose.ts.ejs +28 -28
  131. package/templates/common/docker-compose.yml.ejs +159 -159
  132. package/templates/common/ecosystem.config.js.ejs +40 -40
  133. package/templates/common/eslint.config.mjs.ejs +77 -77
  134. package/templates/common/health/js/healthRoute.js.ejs +50 -47
  135. package/templates/common/health/js/healthRoute.spec.js.ejs +70 -70
  136. package/templates/common/health/ts/healthRoute.spec.ts.ejs +76 -76
  137. package/templates/common/health/ts/healthRoute.ts.ejs +49 -46
  138. package/templates/common/jest.config.js.ejs +32 -32
  139. package/templates/common/jest.e2e.config.js.ejs +8 -8
  140. package/templates/common/kafka/js/config/kafka.js +9 -9
  141. package/templates/common/kafka/js/config/kafka.spec.js.ejs +27 -27
  142. package/templates/common/kafka/js/messaging/baseConsumer.js.ejs +30 -30
  143. package/templates/common/kafka/js/messaging/baseConsumer.spec.js.ejs +58 -58
  144. package/templates/common/kafka/js/messaging/userEventSchema.js.ejs +12 -11
  145. package/templates/common/kafka/js/messaging/userEventSchema.spec.js.ejs +27 -27
  146. package/templates/common/kafka/js/messaging/welcomeEmailConsumer.js.ejs +44 -31
  147. package/templates/common/kafka/js/messaging/welcomeEmailConsumer.spec.js.ejs +86 -49
  148. package/templates/common/kafka/js/services/kafkaService.js.ejs +93 -93
  149. package/templates/common/kafka/js/services/kafkaService.spec.js.ejs +106 -106
  150. package/templates/common/kafka/js/utils/kafkaEvents.js.ejs +7 -0
  151. package/templates/common/kafka/ts/config/kafka.spec.ts.ejs +27 -27
  152. package/templates/common/kafka/ts/config/kafka.ts +7 -7
  153. package/templates/common/kafka/ts/messaging/baseConsumer.spec.ts.ejs +50 -50
  154. package/templates/common/kafka/ts/messaging/baseConsumer.ts.ejs +27 -27
  155. package/templates/common/kafka/ts/messaging/userEventSchema.spec.ts.ejs +51 -51
  156. package/templates/common/kafka/ts/messaging/userEventSchema.ts.ejs +12 -11
  157. package/templates/common/kafka/ts/messaging/welcomeEmailConsumer.spec.ts.ejs +86 -49
  158. package/templates/common/kafka/ts/messaging/welcomeEmailConsumer.ts.ejs +38 -25
  159. package/templates/common/kafka/ts/services/kafkaService.spec.ts.ejs +81 -81
  160. package/templates/common/kafka/ts/services/kafkaService.ts.ejs +95 -95
  161. package/templates/common/kafka/ts/utils/kafkaEvents.ts.ejs +5 -0
  162. package/templates/common/migrate-mongo-config.js.ejs +31 -31
  163. package/templates/common/migrations/init.js.ejs +23 -23
  164. package/templates/common/package.json.ejs +119 -118
  165. package/templates/common/prompts/add-feature.md.ejs +26 -26
  166. package/templates/common/prompts/project-context.md.ejs +43 -43
  167. package/templates/common/prompts/troubleshoot.md.ejs +28 -28
  168. package/templates/common/public/css/style.css +147 -147
  169. package/templates/common/scripts/run-e2e.js.ejs +63 -63
  170. package/templates/common/shutdown/js/gracefulShutdown.js.ejs +65 -61
  171. package/templates/common/shutdown/js/gracefulShutdown.spec.js.ejs +149 -160
  172. package/templates/common/shutdown/ts/gracefulShutdown.spec.ts.ejs +179 -158
  173. package/templates/common/shutdown/ts/gracefulShutdown.ts.ejs +59 -55
  174. package/templates/common/sonar-project.properties.ejs +27 -27
  175. package/templates/common/src/tests/e2e/e2e.users.test.js.ejs +120 -49
  176. package/templates/common/src/tests/e2e/e2e.users.test.ts.ejs +120 -49
  177. package/templates/common/src/utils/errorMiddleware.spec.js.ejs +79 -79
  178. package/templates/common/src/utils/errorMiddleware.spec.ts.ejs +94 -94
  179. package/templates/common/swagger.yml.ejs +118 -66
  180. package/templates/common/tsconfig.json +22 -22
  181. package/templates/common/views/ejs/index.ejs +55 -55
  182. package/templates/common/views/pug/index.pug +40 -40
  183. package/templates/db/mysql/V1__Initial_Setup.sql.ejs +10 -9
  184. package/templates/db/postgres/V1__Initial_Setup.sql.ejs +10 -9
  185. package/templates/mvc/js/src/config/env.js.ejs +46 -46
  186. package/templates/mvc/js/src/config/swagger.js.ejs +6 -6
  187. package/templates/mvc/js/src/controllers/userController.js.ejs +246 -105
  188. package/templates/mvc/js/src/controllers/userController.spec.js.ejs +481 -209
  189. package/templates/mvc/js/src/errors/ApiError.js +14 -14
  190. package/templates/mvc/js/src/errors/BadRequestError.js +11 -10
  191. package/templates/mvc/js/src/errors/BadRequestError.spec.js.ejs +22 -21
  192. package/templates/mvc/js/src/errors/NotFoundError.js +11 -10
  193. package/templates/mvc/js/src/errors/NotFoundError.spec.js.ejs +22 -21
  194. package/templates/mvc/js/src/graphql/context.js.ejs +7 -7
  195. package/templates/mvc/js/src/graphql/context.spec.js.ejs +29 -29
  196. package/templates/mvc/js/src/graphql/index.js.ejs +5 -5
  197. package/templates/mvc/js/src/graphql/resolvers/index.js.ejs +6 -6
  198. package/templates/mvc/js/src/graphql/resolvers/user.resolvers.js.ejs +25 -19
  199. package/templates/mvc/js/src/graphql/resolvers/user.resolvers.spec.js.ejs +64 -47
  200. package/templates/mvc/js/src/graphql/typeDefs/index.js.ejs +6 -6
  201. package/templates/mvc/js/src/graphql/typeDefs/user.types.js.ejs +19 -17
  202. package/templates/mvc/js/src/index.js.ejs +136 -136
  203. package/templates/mvc/js/src/routes/api.js +10 -8
  204. package/templates/mvc/js/src/routes/api.spec.js.ejs +41 -36
  205. package/templates/mvc/js/src/utils/errorMessages.js +14 -0
  206. package/templates/mvc/js/src/utils/errorMiddleware.js +29 -29
  207. package/templates/mvc/js/src/utils/httpCodes.js +9 -9
  208. package/templates/mvc/js/src/utils/logger.js +40 -40
  209. package/templates/mvc/js/src/utils/logger.spec.js.ejs +63 -63
  210. package/templates/mvc/ts/src/config/env.ts.ejs +45 -45
  211. package/templates/mvc/ts/src/config/swagger.ts.ejs +6 -6
  212. package/templates/mvc/ts/src/controllers/userController.spec.ts.ejs +481 -203
  213. package/templates/mvc/ts/src/controllers/userController.ts.ejs +248 -107
  214. package/templates/mvc/ts/src/errors/ApiError.ts +15 -15
  215. package/templates/mvc/ts/src/errors/BadRequestError.spec.ts.ejs +22 -21
  216. package/templates/mvc/ts/src/errors/BadRequestError.ts +9 -8
  217. package/templates/mvc/ts/src/errors/NotFoundError.spec.ts.ejs +27 -21
  218. package/templates/mvc/ts/src/errors/NotFoundError.ts +9 -8
  219. package/templates/mvc/ts/src/graphql/context.spec.ts.ejs +30 -30
  220. package/templates/mvc/ts/src/graphql/context.ts.ejs +12 -12
  221. package/templates/mvc/ts/src/graphql/index.ts.ejs +3 -3
  222. package/templates/mvc/ts/src/graphql/resolvers/index.ts.ejs +4 -4
  223. package/templates/mvc/ts/src/graphql/resolvers/user.resolvers.spec.ts.ejs +68 -51
  224. package/templates/mvc/ts/src/graphql/resolvers/user.resolvers.ts.ejs +29 -21
  225. package/templates/mvc/ts/src/graphql/typeDefs/index.ts.ejs +4 -4
  226. package/templates/mvc/ts/src/graphql/typeDefs/user.types.ts.ejs +17 -15
  227. package/templates/mvc/ts/src/index.ts.ejs +156 -153
  228. package/templates/mvc/ts/src/routes/api.spec.ts.ejs +59 -40
  229. package/templates/mvc/ts/src/routes/api.ts +12 -10
  230. package/templates/mvc/ts/src/utils/errorMessages.ts +12 -0
  231. package/templates/mvc/ts/src/utils/errorMiddleware.ts.ejs +27 -27
  232. package/templates/mvc/ts/src/utils/httpCodes.ts +7 -7
  233. package/templates/mvc/ts/src/utils/logger.spec.ts.ejs +63 -63
  234. package/templates/mvc/ts/src/utils/logger.ts +36 -36
  235. package/templates/clean-architecture/ts/src/infrastructure/repositories/UserRepository.ts.ejs +0 -37
@@ -1,138 +1,234 @@
1
- const UserController = require('@/interfaces/controllers/userController');
2
- const CreateUser = require('@/usecases/CreateUser');
3
- const GetAllUsers = require('@/usecases/GetAllUsers');
4
-
5
- jest.mock('@/usecases/CreateUser');
6
- jest.mock('@/usecases/GetAllUsers');
7
- <%_ if (communication === 'Kafka') { -%>
8
- jest.mock('@/infrastructure/messaging/kafkaClient', () => ({
9
- sendMessage: jest.fn().mockResolvedValue(undefined)
10
- }));
11
- <%_ } -%>
12
-
13
-
14
- describe('UserController (Clean Architecture)', () => {
15
- let userController;
16
- let mockCreateUserUseCase;
17
- let mockGetAllUsersUseCase;
18
- <%_ if (communication !== 'GraphQL') { -%>
19
- let mockRequest;
20
- let mockResponse;
21
- let mockNext;
22
- <%_ } -%>
23
-
24
- beforeEach(() => {
25
- jest.clearAllMocks();
26
-
27
- userController = new UserController();
28
-
29
- // Retrieve the mocked instances created inside UserController constructor
30
- mockCreateUserUseCase = CreateUser.mock.instances[0];
31
- mockGetAllUsersUseCase = GetAllUsers.mock.instances[0];
32
-
33
- <%_ if (communication !== 'GraphQL') { -%>
34
- mockRequest = {
35
- body: {}
36
- };
37
- mockResponse = {
38
- status: jest.fn().mockReturnThis(),
39
- json: jest.fn()
40
- };
41
- mockNext = jest.fn();
42
- <%_ } -%>
43
- });
44
-
45
- describe('getUsers', () => {
46
- it('should return successfully (Happy Path)', async () => {
47
- const usersMock = [{ id: '1', name: 'Test', email: 'test@example.com' }];
48
- mockGetAllUsersUseCase.execute.mockResolvedValue(usersMock);
49
-
50
- <%_ if (communication === 'GraphQL') { -%>
51
- const result = await userController.getUsers();
52
- expect(result).toEqual(usersMock);
53
- <%_ } else { -%>
54
- await userController.getUsers(mockRequest, mockResponse, mockNext);
55
- expect(mockResponse.json).toHaveBeenCalledWith(usersMock);
56
- <%_ } -%>
57
- expect(mockGetAllUsersUseCase.execute).toHaveBeenCalled();
58
- });
59
-
60
- it('should handle errors correctly (Error Handling)', async () => {
61
- const error = new Error('UseCase Error');
62
- mockGetAllUsersUseCase.execute.mockRejectedValue(error);
63
-
64
- <%_ if (communication === 'GraphQL') { -%>
65
- await expect(userController.getUsers()).rejects.toThrow(error);
66
- <%_ } else { -%>
67
- await userController.getUsers(mockRequest, mockResponse, mockNext);
68
- expect(mockNext).toHaveBeenCalledWith(error);
69
- <%_ } -%>
70
- });
71
- });
72
-
73
- describe('createUser', () => {
74
- it('should successfully create a new user (Happy Path)', async () => {
75
- const payload = { name: 'Alice', email: 'alice@example.com' };
76
- <%_ if (communication === 'GraphQL') { -%>
77
- const dataArg = payload;
78
- <%_ } else { -%>
79
- mockRequest.body = payload;
80
- <%_ } -%>
81
- const expectedUser = { id: '1', ...payload };
82
-
83
- mockCreateUserUseCase.execute.mockResolvedValue(expectedUser);
84
-
85
- <%_ if (communication === 'GraphQL') { -%>
86
- const result = await userController.createUser(dataArg);
87
- expect(result).toEqual(expectedUser);
88
- <%_ } else { -%>
89
- await userController.createUser(mockRequest, mockResponse, mockNext);
90
- <%_ if (communication === 'Kafka') { -%>
91
- const { sendMessage } = require('@/infrastructure/messaging/kafkaClient');
92
- expect(sendMessage).toHaveBeenCalled();
93
- <%_ } -%>
94
- expect(mockResponse.status).toHaveBeenCalledWith(201);
95
-
96
- expect(mockResponse.json).toHaveBeenCalledWith(expectedUser);
97
- <%_ } -%>
98
- expect(mockCreateUserUseCase.execute).toHaveBeenCalledWith(payload.name, payload.email);
99
- });
100
-
101
- it('should handle errors when creation fails (Error Handling)', async () => {
102
- const error = new Error('Creation Error');
103
- mockCreateUserUseCase.execute.mockRejectedValue(error);
104
-
105
- <%_ if (communication === 'GraphQL') { -%>
106
- await expect(userController.createUser({ name: 'Bob', email: 'bob@example.com' })).rejects.toThrow(error);
107
- <%_ } else { -%>
108
- await userController.createUser(mockRequest, mockResponse, mockNext);
109
- expect(mockNext).toHaveBeenCalledWith(error);
110
- <%_ } -%>
111
- });
112
-
113
- <%_ if (communication === 'Kafka') { -%>
114
- it('should successfully create a new user with _id for Kafka (Happy Path)', async () => {
115
- const payload = { name: 'Bob', email: 'bob@example.com' };
116
- <% if (communication === 'GraphQL') { -%>
117
- const dataArg = payload;
118
- <% } else { -%>
119
- mockRequest.body = payload;
120
- <% } -%>
121
- const expectedUser = { _id: '2', ...payload };
122
-
123
- mockCreateUserUseCase.execute.mockResolvedValue(expectedUser);
124
-
125
- <% if (communication === 'GraphQL') { -%>
126
- await userController.createUser(dataArg);
127
- <% } else { -%>
128
- await userController.createUser(mockRequest, mockResponse, mockNext);
129
- <% } -%>
130
- const { sendMessage } = require('@/infrastructure/messaging/kafkaClient');
131
- expect(sendMessage).toHaveBeenCalledWith(
132
- 'user-topic',
133
- expect.stringContaining('"id":"2"')
134
- );
135
- });
136
- <%_ } -%>
137
- });
138
- });
1
+ const UserController = require('@/interfaces/controllers/userController');
2
+ const ERROR_MESSAGES = require('@/utils/errorMessages');
3
+ const CreateUser = require('@/usecases/CreateUser');
4
+ const GetAllUsers = require('@/usecases/GetAllUsers');
5
+ const UpdateUser = require('@/usecases/UpdateUser');
6
+ const DeleteUser = require('@/usecases/DeleteUser');
7
+
8
+ jest.mock('@/usecases/CreateUser');
9
+ jest.mock('@/usecases/GetAllUsers');
10
+ jest.mock('@/usecases/UpdateUser');
11
+ jest.mock('@/usecases/DeleteUser');
12
+ <%_ if (communication === 'Kafka') { -%>
13
+ jest.mock('@/infrastructure/messaging/kafkaClient', () => ({
14
+ sendMessage: jest.fn().mockResolvedValue(undefined)
15
+ }));
16
+ <%_ } -%>
17
+
18
+
19
+ describe('UserController (Clean Architecture)', () => {
20
+ let userController;
21
+ let mockCreateUserUseCase;
22
+ let mockGetAllUsersUseCase;
23
+ let mockUpdateUserUseCase;
24
+ let mockDeleteUserUseCase;
25
+ <%_ if (communication !== 'GraphQL') { -%>
26
+ let mockRequest;
27
+ let mockResponse;
28
+ let mockNext;
29
+ <%_ } -%>
30
+
31
+ beforeEach(() => {
32
+ jest.resetAllMocks();
33
+
34
+ userController = new UserController();
35
+
36
+ // Retrieve the mocked instances created inside UserController constructor
37
+ mockCreateUserUseCase = CreateUser.mock.instances[0];
38
+ mockGetAllUsersUseCase = GetAllUsers.mock.instances[0];
39
+ mockUpdateUserUseCase = UpdateUser.mock.instances[0];
40
+ mockDeleteUserUseCase = DeleteUser.mock.instances[0];
41
+
42
+ <%_ if (communication !== 'GraphQL') { -%>
43
+ mockRequest = {
44
+ body: {},
45
+ params: {}
46
+ };
47
+ mockResponse = {
48
+ status: jest.fn().mockReturnThis(),
49
+ json: jest.fn()
50
+ };
51
+ mockNext = jest.fn();
52
+ <%_ } -%>
53
+ });
54
+
55
+ describe('getUsers', () => {
56
+ it('should return successfully (Happy Path)', async () => {
57
+ const usersMock = [{ id: '1', name: 'Test', email: 'test@example.com' }];
58
+ mockGetAllUsersUseCase.execute.mockResolvedValue(usersMock);
59
+
60
+ <%_ if (communication === 'GraphQL') { -%>
61
+ const result = await userController.getUsers();
62
+ expect(result).toEqual(usersMock);
63
+ <%_ } else { -%>
64
+ await userController.getUsers(mockRequest, mockResponse, mockNext);
65
+ expect(mockResponse.json).toHaveBeenCalledWith(usersMock);
66
+ <%_ } -%>
67
+ expect(mockGetAllUsersUseCase.execute).toHaveBeenCalled();
68
+ });
69
+
70
+ it('should handle errors correctly (Error Handling)', async () => {
71
+ const error = new Error('UseCase Error');
72
+ mockGetAllUsersUseCase.execute.mockRejectedValue(error);
73
+
74
+ <%_ if (communication === 'GraphQL') { -%>
75
+ await expect(userController.getUsers()).rejects.toThrow(error);
76
+ <%_ } else { -%>
77
+ await userController.getUsers(mockRequest, mockResponse, mockNext);
78
+ expect(mockNext).toHaveBeenCalledWith(error);
79
+ <%_ } -%>
80
+ });
81
+ });
82
+
83
+ describe('createUser', () => {
84
+ it('should successfully create a new user (Happy Path)', async () => {
85
+ const payload = { name: 'Alice', email: 'alice@example.com' };
86
+ <%_ if (communication === 'GraphQL') { -%>
87
+ const dataArg = payload;
88
+ <%_ } else { -%>
89
+ mockRequest.body = payload;
90
+ <%_ } -%>
91
+ const expectedUser = { id: '1', ...payload };
92
+
93
+ mockCreateUserUseCase.execute.mockResolvedValue(expectedUser);
94
+
95
+ <%_ if (communication === 'GraphQL') { -%>
96
+ const result = await userController.createUser(dataArg);
97
+ expect(result).toEqual(expectedUser);
98
+ <%_ } else { -%>
99
+ await userController.createUser(mockRequest, mockResponse, mockNext);
100
+ <%_ if (communication === 'Kafka') { -%>
101
+ const { sendMessage } = require('@/infrastructure/messaging/kafkaClient');
102
+ expect(sendMessage).toHaveBeenCalled();
103
+ <%_ } -%>
104
+ expect(mockResponse.status).toHaveBeenCalledWith(201);
105
+
106
+ expect(mockResponse.json).toHaveBeenCalledWith(expectedUser);
107
+ <%_ } -%>
108
+ expect(mockCreateUserUseCase.execute).toHaveBeenCalledWith(payload.name, payload.email);
109
+ });
110
+ });
111
+
112
+ describe('updateUser', () => {
113
+ it('should successfully update a user (Happy Path)', async () => {
114
+ const id = '1';
115
+ const payload = { name: 'Alice Updated' };
116
+ <%_ if (communication === 'GraphQL') { -%>
117
+ const idArg = id;
118
+ const dataArg = payload;
119
+ <%_ } else { -%>
120
+ mockRequest.params = { id };
121
+ mockRequest.body = payload;
122
+ <%_ } -%>
123
+ const expectedUser = { id, ...payload };
124
+
125
+ mockUpdateUserUseCase.execute.mockResolvedValue(expectedUser);
126
+
127
+ <%_ if (communication === 'GraphQL') { -%>
128
+ const result = await userController.updateUser(idArg, dataArg);
129
+ expect(result.name).toBe(payload.name);
130
+ <%_ } else { -%>
131
+ await userController.updateUser(mockRequest, mockResponse, mockNext);
132
+ expect(mockResponse.json).toHaveBeenCalled();
133
+ <%_ } -%>
134
+ <%_ if (communication === 'Kafka') { -%>
135
+ const { sendMessage } = require('@/infrastructure/messaging/kafkaClient');
136
+ expect(sendMessage).toHaveBeenCalled();
137
+ <%_ } -%>
138
+ expect(mockUpdateUserUseCase.execute).toHaveBeenCalledWith(id, payload);
139
+ });
140
+
141
+ it('should handle database errors during update (Error Handling)', async () => {
142
+ const id = '1';
143
+ const error = new Error('Database Error');
144
+ mockUpdateUserUseCase.execute.mockRejectedValue(error);
145
+ <%_ if (communication === 'GraphQL') { -%>
146
+ await expect(userController.updateUser(id, { name: 'Fail' })).rejects.toThrow(error);
147
+ <%_ } else { -%>
148
+ await userController.updateUser(mockRequest, mockResponse, mockNext);
149
+ expect(mockNext).toHaveBeenCalledWith(error);
150
+ <%_ } -%>
151
+ });
152
+ });
153
+
154
+ describe('deleteUser', () => {
155
+ it('should successfully delete a user (Happy Path)', async () => {
156
+ const id = '1';
157
+ <%_ if (communication === 'GraphQL') { -%>
158
+ const idArg = id;
159
+ <%_ } else { -%>
160
+ mockRequest.params = { id };
161
+ <%_ } -%>
162
+ mockDeleteUserUseCase.execute.mockResolvedValue(true);
163
+
164
+ <%_ if (communication === 'GraphQL') { -%>
165
+ const result = await userController.deleteUser(idArg);
166
+ expect(result).toBe(true);
167
+ <%_ } else { -%>
168
+ await userController.deleteUser(mockRequest, mockResponse, mockNext);
169
+ expect(mockResponse.status).toHaveBeenCalledWith(200);
170
+ <%_ } -%>
171
+ <%_ if (communication === 'Kafka') { -%>
172
+ const { sendMessage } = require('@/infrastructure/messaging/kafkaClient');
173
+ expect(sendMessage).toHaveBeenCalled();
174
+ <%_ } -%>
175
+ expect(mockDeleteUserUseCase.execute).toHaveBeenCalledWith(id);
176
+ });
177
+
178
+ it('should throw error if user not found during deletion (Error Handling)', async () => {
179
+ const id = '999';
180
+ <%_ if (communication === 'GraphQL') { -%>
181
+ mockDeleteUserUseCase.execute.mockResolvedValue(false);
182
+ await expect(userController.deleteUser(id)).rejects.toThrow(ERROR_MESSAGES.USER_NOT_FOUND);
183
+ <%_ } else { -%>
184
+ mockRequest.params = { id };
185
+ mockDeleteUserUseCase.execute.mockResolvedValue(false);
186
+ await userController.deleteUser(mockRequest, mockResponse, mockNext);
187
+ expect(mockResponse.status).toHaveBeenCalledWith(404);
188
+ <%_ } -%>
189
+ });
190
+
191
+ it('should handle database errors during deletion (Error Handling)', async () => {
192
+ const id = '1';
193
+ const error = new Error('Database Error');
194
+ mockDeleteUserUseCase.execute.mockRejectedValue(error);
195
+ <%_ if (communication === 'GraphQL') { -%>
196
+ await expect(userController.deleteUser(id)).rejects.toThrow(error);
197
+ <%_ } else { -%>
198
+ mockRequest.params = { id };
199
+ await userController.deleteUser(mockRequest, mockResponse, mockNext);
200
+ expect(mockNext).toHaveBeenCalledWith(error);
201
+ <%_ } -%>
202
+ });
203
+ });
204
+
205
+ describe('createUser Error Paths', () => {
206
+ it('should handle database errors during creation (Error Handling)', async () => {
207
+ const error = new Error('Database Error');
208
+ mockCreateUserUseCase.execute.mockRejectedValue(error);
209
+ <%_ if (communication === 'GraphQL') { -%>
210
+ await expect(userController.createUser({ name: 'Alice', email: 'alice@example.com' })).rejects.toThrow(error);
211
+ <%_ } else { -%>
212
+ mockRequest.body = { name: 'Alice', email: 'alice@example.com' };
213
+ await userController.createUser(mockRequest, mockResponse, mockNext);
214
+ expect(mockNext).toHaveBeenCalledWith(error);
215
+ <%_ } -%>
216
+ });
217
+ });
218
+
219
+ describe('updateUser Error Paths', () => {
220
+ it('should handle database errors during update (Error Handling)', async () => {
221
+ const id = '1';
222
+ const error = new Error('Database Error');
223
+ mockUpdateUserUseCase.execute.mockRejectedValue(error);
224
+ <%_ if (communication === 'GraphQL') { -%>
225
+ await expect(userController.updateUser(id, { name: 'Bob' })).rejects.toThrow(error);
226
+ <%_ } else { -%>
227
+ mockRequest.params = { id };
228
+ mockRequest.body = { name: 'Bob' };
229
+ await userController.updateUser(mockRequest, mockResponse, mockNext);
230
+ expect(mockNext).toHaveBeenCalledWith(error);
231
+ <%_ } -%>
232
+ });
233
+ });
234
+ });
@@ -1,13 +1,13 @@
1
- const UserRepository = require('../../infrastructure/repositories/UserRepository');
2
-
3
- const gqlContext = async ({ req }) => {
4
- const token = req.headers.authorization || '';
5
- const userRepository = new UserRepository();
6
-
7
- return {
8
- token,
9
- userRepository
10
- };
11
- };
12
-
13
- module.exports = { gqlContext };
1
+ const UserRepository = require('../../infrastructure/repositories/UserRepository');
2
+
3
+ const gqlContext = async ({ req }) => {
4
+ const token = req.headers.authorization || '';
5
+ const userRepository = new UserRepository();
6
+
7
+ return {
8
+ token,
9
+ userRepository
10
+ };
11
+ };
12
+
13
+ module.exports = { gqlContext };
@@ -1,31 +1,31 @@
1
- const { gqlContext } = require('@/interfaces/graphql/context');
2
- const { resolvers } = require('@/interfaces/graphql/resolvers');
3
- const { typeDefs } = require('@/interfaces/graphql/typeDefs');
4
-
5
- jest.mock('@/infrastructure/repositories/UserRepository');
6
-
7
- describe('GraphQL Context', () => {
8
- it('should exercise GraphQL index entry points', () => {
9
- expect(resolvers).toBeDefined();
10
- expect(typeDefs).toBeDefined();
11
- });
12
- it('should return context with token when authorization header is present', async () => {
13
- const mockRequest = {
14
- headers: {
15
- authorization: 'Bearer token123',
16
- },
17
- };
18
-
19
- const context = await gqlContext({ req: mockRequest });
20
- expect(context.token).toBe('Bearer token123');
21
- });
22
-
23
- it('should return context with empty token when authorization header is missing', async () => {
24
- const mockRequest = {
25
- headers: {},
26
- };
27
-
28
- const context = await gqlContext({ req: mockRequest });
29
- expect(context.token).toBe('');
30
- });
31
- });
1
+ const { gqlContext } = require('@/interfaces/graphql/context');
2
+ const { resolvers } = require('@/interfaces/graphql/resolvers');
3
+ const { typeDefs } = require('@/interfaces/graphql/typeDefs');
4
+
5
+ jest.mock('@/infrastructure/repositories/UserRepository');
6
+
7
+ describe('GraphQL Context', () => {
8
+ it('should exercise GraphQL index entry points', () => {
9
+ expect(resolvers).toBeDefined();
10
+ expect(typeDefs).toBeDefined();
11
+ });
12
+ it('should return context with token when authorization header is present', async () => {
13
+ const mockRequest = {
14
+ headers: {
15
+ authorization: 'Bearer token123',
16
+ },
17
+ };
18
+
19
+ const context = await gqlContext({ req: mockRequest });
20
+ expect(context.token).toBe('Bearer token123');
21
+ });
22
+
23
+ it('should return context with empty token when authorization header is missing', async () => {
24
+ const mockRequest = {
25
+ headers: {},
26
+ };
27
+
28
+ const context = await gqlContext({ req: mockRequest });
29
+ expect(context.token).toBe('');
30
+ });
31
+ });
@@ -1,5 +1,5 @@
1
- const { typeDefs } = require('./typeDefs');
2
- const { resolvers } = require('./resolvers');
3
- const { gqlContext } = require('./context');
4
-
5
- module.exports = { typeDefs, resolvers, gqlContext };
1
+ const { typeDefs } = require('./typeDefs');
2
+ const { resolvers } = require('./resolvers');
3
+ const { gqlContext } = require('./context');
4
+
5
+ module.exports = { typeDefs, resolvers, gqlContext };
@@ -1,6 +1,6 @@
1
- const { mergeResolvers } = require('@graphql-tools/merge');
2
- const { userResolvers } = require('./user.resolvers');
3
-
4
- const resolvers = mergeResolvers([userResolvers]);
5
-
6
- module.exports = { resolvers };
1
+ const { mergeResolvers } = require('@graphql-tools/merge');
2
+ const { userResolvers } = require('./user.resolvers');
3
+
4
+ const resolvers = mergeResolvers([userResolvers]);
5
+
6
+ module.exports = { resolvers };
@@ -1,21 +1,27 @@
1
- const UserController = require('../../controllers/userController');
2
-
3
- const userController = new UserController();
4
-
5
- const userResolvers = {
6
- Query: {
7
- getAllUsers: async () => {
8
- return await userController.getUsers();
9
- }
10
- },
11
- Mutation: {
12
- createUser: async (_, { name, email }) => {
13
- return await userController.createUser({ name, email });
14
- }
15
- }<%_ if (database === 'MongoDB') { -%>,
16
- User: {
17
- id: (parent) => parent.id || parent._id
18
- }<%_ } %>
19
- };
20
-
21
- module.exports = { userResolvers };
1
+ const UserController = require('../../controllers/userController');
2
+
3
+ const userController = new UserController();
4
+
5
+ const userResolvers = {
6
+ Query: {
7
+ getAllUsers: async () => {
8
+ return await userController.getUsers();
9
+ }
10
+ },
11
+ Mutation: {
12
+ createUser: async (_, { name, email }) => {
13
+ return await userController.createUser({ name, email });
14
+ },
15
+ updateUser: async (_, { id, name, email }) => {
16
+ return await userController.updateUser(id, { name, email });
17
+ },
18
+ deleteUser: async (_, { id }) => {
19
+ return await userController.deleteUser(id);
20
+ }
21
+ }<%_ if (database === 'MongoDB') { -%>,
22
+ User: {
23
+ id: (parent) => parent.id || parent._id
24
+ }<%_ } %>
25
+ };
26
+
27
+ module.exports = { userResolvers };