imlil 1.0.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 (175) hide show
  1. package/.eslintrc.cjs +40 -0
  2. package/DOCS.md +63 -0
  3. package/README.md +160 -0
  4. package/agentTestSandbox/cli-test-zone/README.md +0 -0
  5. package/agentTestSandbox/cli-test-zone/imlil.blueprint.json +5 -0
  6. package/agentTestSandbox/cli-test-zone/notes-warning.md +3 -0
  7. package/agentTestSandbox/cli-test-zone/package.json +0 -0
  8. package/agentTestSandbox/cli-test-zone/public/index.html +0 -0
  9. package/agentTestSandbox/cli-test-zone/src/App.js +0 -0
  10. package/agentTestSandbox/cli-test-zone/src/App.jsx +29 -0
  11. package/agentTestSandbox/cli-test-zone/src/__tests__/App.test.jsx +48 -0
  12. package/agentTestSandbox/cli-test-zone/src/components/AddTodo.js +0 -0
  13. package/agentTestSandbox/cli-test-zone/src/components/Navigation/Navigation.jsx +48 -0
  14. package/agentTestSandbox/cli-test-zone/src/components/Navigation/__tests__/Navigation.module.test.js +45 -0
  15. package/agentTestSandbox/cli-test-zone/src/components/Navigation/__tests__/Navigation.test.jsx +47 -0
  16. package/agentTestSandbox/cli-test-zone/src/components/Navigation.js +0 -0
  17. package/agentTestSandbox/cli-test-zone/src/components/TodoItem/TodoItem.jsx +41 -0
  18. package/agentTestSandbox/cli-test-zone/src/components/TodoItem/__tests__/TodoItem.test.jsx +65 -0
  19. package/agentTestSandbox/cli-test-zone/src/components/TodoItem.js +0 -0
  20. package/agentTestSandbox/cli-test-zone/src/components/TodoList/TodoList.module.css +62 -0
  21. package/agentTestSandbox/cli-test-zone/src/components/TodoList.js +0 -0
  22. package/agentTestSandbox/cli-test-zone/src/index.js +0 -0
  23. package/agentTestSandbox/cli-test-zone/src/pages/About.js +0 -0
  24. package/agentTestSandbox/cli-test-zone/src/pages/Home.js +0 -0
  25. package/agentTestSandbox/cli-test-zone/src/store/TodoContext.js +0 -0
  26. package/agentTestSandbox/cli-test-zone/src/styles/Todo.css +0 -0
  27. package/agentTestSandbox/cli-test-zone/src/styles/index.css +0 -0
  28. package/agentTestSandbox/cli-test-zone/src/utils/__tests__/localStorage.test.js +48 -0
  29. package/agentTestSandbox/cli-test-zone/src/utils/localStorage.js +38 -0
  30. package/agentTestSandbox/parallel-test/.env.example +0 -0
  31. package/agentTestSandbox/parallel-test/.eslintrc.json +0 -0
  32. package/agentTestSandbox/parallel-test/.github/workflows/__tests__/workflows.test.ts +115 -0
  33. package/agentTestSandbox/parallel-test/.github/workflows/cd.yml +0 -0
  34. package/agentTestSandbox/parallel-test/.github/workflows/ci.yml +4 -0
  35. package/agentTestSandbox/parallel-test/.imlil/plan-2026-02-08.md +186 -0
  36. package/agentTestSandbox/parallel-test/.prettierrc +0 -0
  37. package/agentTestSandbox/parallel-test/Dockerfile +0 -0
  38. package/agentTestSandbox/parallel-test/README.md +3 -0
  39. package/agentTestSandbox/parallel-test/ast.json +74 -0
  40. package/agentTestSandbox/parallel-test/docker-compose.yml +4 -0
  41. package/agentTestSandbox/parallel-test/jest.config.js +61 -0
  42. package/agentTestSandbox/parallel-test/k8s/__tests__/deployment.test.ts +168 -0
  43. package/agentTestSandbox/parallel-test/k8s/frontend-deployment.yaml +4 -0
  44. package/agentTestSandbox/parallel-test/nginx/nginx.conf +0 -0
  45. package/agentTestSandbox/parallel-test/package.json +50 -0
  46. package/agentTestSandbox/parallel-test/prisma/__tests__/schema.test.ts +176 -0
  47. package/agentTestSandbox/parallel-test/prisma/schema.prisma +109 -0
  48. package/agentTestSandbox/parallel-test/server/__tests__/controllers/dashboard.controller.test.ts +127 -0
  49. package/agentTestSandbox/parallel-test/server/__tests__/index.test.ts +60 -0
  50. package/agentTestSandbox/parallel-test/server/__tests__/models/user.model.test.ts +111 -0
  51. package/agentTestSandbox/parallel-test/server/config/__tests__/swagger.test.ts +128 -0
  52. package/agentTestSandbox/parallel-test/server/config/database.ts +0 -0
  53. package/agentTestSandbox/parallel-test/server/config/redis.ts +0 -0
  54. package/agentTestSandbox/parallel-test/server/config/swagger.ts +0 -0
  55. package/agentTestSandbox/parallel-test/server/controllers/__tests__/auth.controller.test.ts +178 -0
  56. package/agentTestSandbox/parallel-test/server/controllers/__tests__/user.controller.test.ts +105 -0
  57. package/agentTestSandbox/parallel-test/server/controllers/auth.controller.ts +148 -0
  58. package/agentTestSandbox/parallel-test/server/controllers/dashboard.controller.ts +137 -0
  59. package/agentTestSandbox/parallel-test/server/controllers/user.controller.ts +161 -0
  60. package/agentTestSandbox/parallel-test/server/index.ts +62 -0
  61. package/agentTestSandbox/parallel-test/server/middleware/__tests__/auth.middleware.test.ts +74 -0
  62. package/agentTestSandbox/parallel-test/server/middleware/auth.middleware.ts +55 -0
  63. package/agentTestSandbox/parallel-test/server/middleware/error.middleware.ts +0 -0
  64. package/agentTestSandbox/parallel-test/server/middleware/validation.middleware.ts +0 -0
  65. package/agentTestSandbox/parallel-test/server/models/analytics.model.ts +0 -0
  66. package/agentTestSandbox/parallel-test/server/models/profile.model.ts +0 -0
  67. package/agentTestSandbox/parallel-test/server/models/user.model.ts +78 -0
  68. package/agentTestSandbox/parallel-test/server/routes/auth.routes.ts +0 -0
  69. package/agentTestSandbox/parallel-test/server/routes/dashboard.routes.ts +0 -0
  70. package/agentTestSandbox/parallel-test/server/routes/user.routes.ts +0 -0
  71. package/agentTestSandbox/parallel-test/src/App.tsx +0 -0
  72. package/agentTestSandbox/parallel-test/src/__tests__/config.test.ts +127 -0
  73. package/agentTestSandbox/parallel-test/src/__tests__/index.test.tsx +36 -0
  74. package/agentTestSandbox/parallel-test/src/__tests__/setup.test.ts +34 -0
  75. package/agentTestSandbox/parallel-test/src/__tests__/setupTest.test.ts +44 -0
  76. package/agentTestSandbox/parallel-test/src/components/common/Button/Button.tsx +80 -0
  77. package/agentTestSandbox/parallel-test/src/components/common/Button/__tests__/Button.test.tsx +75 -0
  78. package/agentTestSandbox/parallel-test/src/components/common/Card/Card.tsx +0 -0
  79. package/agentTestSandbox/parallel-test/src/components/common/Input/Input.tsx +0 -0
  80. package/agentTestSandbox/parallel-test/src/components/common/Table/Table.tsx +0 -0
  81. package/agentTestSandbox/parallel-test/src/components/features/Authentication/LoginForm.tsx +75 -0
  82. package/agentTestSandbox/parallel-test/src/components/features/Authentication/RegisterForm.tsx +0 -0
  83. package/agentTestSandbox/parallel-test/src/components/features/Authentication/__tests__/LoginForm.test.tsx +101 -0
  84. package/agentTestSandbox/parallel-test/src/components/features/Dashboard/AnalyticsChart.tsx +0 -0
  85. package/agentTestSandbox/parallel-test/src/components/features/Dashboard/DashboardStats.tsx +81 -0
  86. package/agentTestSandbox/parallel-test/src/components/features/Dashboard/__tests__/DashboardStats.test.tsx +122 -0
  87. package/agentTestSandbox/parallel-test/src/components/layouts/Header.tsx +70 -0
  88. package/agentTestSandbox/parallel-test/src/components/layouts/MainLayout.tsx +0 -0
  89. package/agentTestSandbox/parallel-test/src/components/layouts/Sidebar.tsx +0 -0
  90. package/agentTestSandbox/parallel-test/src/components/layouts/__tests__/MainLayout.test.tsx +65 -0
  91. package/agentTestSandbox/parallel-test/src/hooks/__tests__/useAuth.test.ts +75 -0
  92. package/agentTestSandbox/parallel-test/src/hooks/useApi.ts +0 -0
  93. package/agentTestSandbox/parallel-test/src/hooks/useAuth.ts +54 -0
  94. package/agentTestSandbox/parallel-test/src/hooks/useTheme.ts +0 -0
  95. package/agentTestSandbox/parallel-test/src/index.tsx +0 -0
  96. package/agentTestSandbox/parallel-test/src/services/__tests__/api.service.test.ts +48 -0
  97. package/agentTestSandbox/parallel-test/src/services/analytics.service.ts +0 -0
  98. package/agentTestSandbox/parallel-test/src/services/api.service.ts +59 -0
  99. package/agentTestSandbox/parallel-test/src/services/api.ts +0 -0
  100. package/agentTestSandbox/parallel-test/src/services/auth.service.ts +0 -0
  101. package/agentTestSandbox/parallel-test/src/services/user.service.ts +0 -0
  102. package/agentTestSandbox/parallel-test/src/store/__tests__/store.test.ts +60 -0
  103. package/agentTestSandbox/parallel-test/src/store/index.ts +23 -0
  104. package/agentTestSandbox/parallel-test/src/store/slices/authSlice.ts +0 -0
  105. package/agentTestSandbox/parallel-test/src/store/slices/dashboardSlice.ts +0 -0
  106. package/agentTestSandbox/parallel-test/src/store/slices/userSlice.ts +0 -0
  107. package/agentTestSandbox/parallel-test/src/types/auth.types.ts +0 -0
  108. package/agentTestSandbox/parallel-test/src/types/dashboard.types.ts +0 -0
  109. package/agentTestSandbox/parallel-test/src/types/user.types.ts +0 -0
  110. package/agentTestSandbox/parallel-test/src/utils/constants.ts +0 -0
  111. package/agentTestSandbox/parallel-test/src/utils/formatters.ts +0 -0
  112. package/agentTestSandbox/parallel-test/src/utils/validation.ts +0 -0
  113. package/agentTestSandbox/parallel-test/src/views/Dashboard.tsx +0 -0
  114. package/agentTestSandbox/parallel-test/src/views/Login.tsx +31 -0
  115. package/agentTestSandbox/parallel-test/src/views/Profile.tsx +0 -0
  116. package/agentTestSandbox/parallel-test/src/views/Register.tsx +0 -0
  117. package/agentTestSandbox/parallel-test/src/views/Settings.tsx +0 -0
  118. package/agentTestSandbox/parallel-test/src/views/__tests__/Login.test.tsx +62 -0
  119. package/agentTestSandbox/parallel-test/src/vite-env.d.ts +1 -0
  120. package/agentTestSandbox/parallel-test/tailwind.config.js +0 -0
  121. package/agentTestSandbox/parallel-test/tests/integration/api/auth.test.ts +120 -0
  122. package/agentTestSandbox/parallel-test/tests/unit/components/Button.test.tsx +35 -0
  123. package/agentTestSandbox/parallel-test/tests/unit/config/jest.config.test.js +62 -0
  124. package/agentTestSandbox/parallel-test/tests/unit/config/jest.setup.test.js +52 -0
  125. package/agentTestSandbox/parallel-test/tests/unit/infrastructure/__tests__/docker-config.test.ts +107 -0
  126. package/agentTestSandbox/parallel-test/tsconfig.json +0 -0
  127. package/agentTestSandbox/zone2/Makefile +58 -0
  128. package/agentTestSandbox/zone2/README.md +0 -0
  129. package/agentTestSandbox/zone2/docs/API.md +0 -0
  130. package/agentTestSandbox/zone2/docs/CONTRIBUTING.md +0 -0
  131. package/agentTestSandbox/zone2/imlil.blueprint.json +5 -0
  132. package/agentTestSandbox/zone2/notes-warning.md +3 -0
  133. package/agentTestSandbox/zone2/src/calculator.c +0 -0
  134. package/agentTestSandbox/zone2/src/calculator.h +0 -0
  135. package/agentTestSandbox/zone2/src/core/__tests__/test_memory.c +89 -0
  136. package/agentTestSandbox/zone2/src/core/memory.c +60 -0
  137. package/agentTestSandbox/zone2/src/display.c +0 -0
  138. package/agentTestSandbox/zone2/src/display.h +0 -0
  139. package/agentTestSandbox/zone2/src/input_handler.c +0 -0
  140. package/agentTestSandbox/zone2/src/input_handler.h +0 -0
  141. package/agentTestSandbox/zone2/src/main.c +0 -0
  142. package/agentTestSandbox/zone2/src/utils/error_handling.c +0 -0
  143. package/agentTestSandbox/zone2/src/utils/error_handling.h +0 -0
  144. package/agentTestSandbox/zone2/src/utils/input.c +0 -0
  145. package/agentTestSandbox/zone2/src/utils/input.h +0 -0
  146. package/agentTestSandbox/zone2/src/utils/math_utils.c +0 -0
  147. package/agentTestSandbox/zone2/src/utils/math_utils.h +0 -0
  148. package/agentTestSandbox/zone2/src/utils/stack.c +0 -0
  149. package/agentTestSandbox/zone2/src/utils/stack.h +0 -0
  150. package/agentTestSandbox/zone2/src/utils.c +34 -0
  151. package/agentTestSandbox/zone2/tests/__tests__/test_makefile.c +58 -0
  152. package/agentTestSandbox/zone2/tests/calculator_tests.c +0 -0
  153. package/agentTestSandbox/zone2/tests/input_handler_tests.c +0 -0
  154. package/agentTestSandbox/zone2/tests/math_utils_tests.c +0 -0
  155. package/agentTestSandbox/zone2/tests/test_calculator.c +0 -0
  156. package/agentTestSandbox/zone2/tests/test_input.c +0 -0
  157. package/agentTestSandbox/zone2/tests/test_stack.c +0 -0
  158. package/agentTestSandbox/zone2/tests/test_utils.c +8 -0
  159. package/bin/cli.js +369 -0
  160. package/imlil.config.js +22 -0
  161. package/index.js +0 -0
  162. package/jest.config.js +5 -0
  163. package/package.json +45 -0
  164. package/src/__tests__/cli.test.js +5 -0
  165. package/src/actions/Action.js +125 -0
  166. package/src/agents/Agent.js +64 -0
  167. package/src/agents/Operator.js +147 -0
  168. package/src/agents/ScrumAgent.js +74 -0
  169. package/src/agents/SupervisorAgent.js +198 -0
  170. package/src/agents/ValidatorAgent.js +48 -0
  171. package/src/agents/coder.js +208 -0
  172. package/src/agents/worker.js +52 -0
  173. package/src/utils/db.js +40 -0
  174. package/src/utils/embedapi.js +19 -0
  175. package/test-api.js +24 -0
@@ -0,0 +1,168 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import yaml from 'js-yaml';
4
+
5
+ describe('Kubernetes Deployment Configuration Tests', () => {
6
+ const k8sPath = path.resolve(__dirname, '..');
7
+
8
+ // Test deployment files existence
9
+ test('should have required k8s deployment files', () => {
10
+ const requiredFiles = [
11
+ 'deployment.yaml',
12
+ 'service.yaml',
13
+ 'ingress.yaml',
14
+ 'configmap.yaml',
15
+ 'secrets.yaml'
16
+ ];
17
+
18
+ requiredFiles.forEach(file => {
19
+ expect(fs.existsSync(path.join(k8sPath, file))).toBeTruthy();
20
+ });
21
+ });
22
+
23
+ // Test deployment.yaml configuration
24
+ describe('deployment.yaml', () => {
25
+ let deploymentConfig;
26
+
27
+ beforeAll(() => {
28
+ const deploymentFile = fs.readFileSync(
29
+ path.join(k8sPath, 'deployment.yaml'),
30
+ 'utf8'
31
+ );
32
+ deploymentConfig = yaml.load(deploymentFile);
33
+ });
34
+
35
+ test('should have correct API version and kind', () => {
36
+ expect(deploymentConfig.apiVersion).toBe('apps/v1');
37
+ expect(deploymentConfig.kind).toBe('Deployment');
38
+ });
39
+
40
+ test('should have proper metadata', () => {
41
+ expect(deploymentConfig.metadata).toHaveProperty('name');
42
+ expect(deploymentConfig.metadata).toHaveProperty('namespace');
43
+ expect(deploymentConfig.metadata.labels).toBeDefined();
44
+ });
45
+
46
+ test('should have correct deployment spec', () => {
47
+ expect(deploymentConfig.spec).toHaveProperty('replicas');
48
+ expect(deploymentConfig.spec).toHaveProperty('selector');
49
+ expect(deploymentConfig.spec).toHaveProperty('template');
50
+ });
51
+
52
+ test('should have container specifications', () => {
53
+ const containers = deploymentConfig.spec.template.spec.containers;
54
+ expect(containers).toBeInstanceOf(Array);
55
+ expect(containers.length).toBeGreaterThan(0);
56
+
57
+ const mainContainer = containers[0];
58
+ expect(mainContainer).toHaveProperty('name');
59
+ expect(mainContainer).toHaveProperty('image');
60
+ expect(mainContainer).toHaveProperty('ports');
61
+ expect(mainContainer).toHaveProperty('resources');
62
+ });
63
+
64
+ test('should have resource limits and requests', () => {
65
+ const container = deploymentConfig.spec.template.spec.containers[0];
66
+ expect(container.resources).toHaveProperty('limits');
67
+ expect(container.resources).toHaveProperty('requests');
68
+ });
69
+ });
70
+
71
+ // Test service.yaml configuration
72
+ describe('service.yaml', () => {
73
+ let serviceConfig;
74
+
75
+ beforeAll(() => {
76
+ const serviceFile = fs.readFileSync(
77
+ path.join(k8sPath, 'service.yaml'),
78
+ 'utf8'
79
+ );
80
+ serviceConfig = yaml.load(serviceFile);
81
+ });
82
+
83
+ test('should have correct API version and kind', () => {
84
+ expect(serviceConfig.apiVersion).toBe('v1');
85
+ expect(serviceConfig.kind).toBe('Service');
86
+ });
87
+
88
+ test('should have proper service specifications', () => {
89
+ expect(serviceConfig.spec).toHaveProperty('selector');
90
+ expect(serviceConfig.spec).toHaveProperty('ports');
91
+ expect(serviceConfig.spec.ports).toBeInstanceOf(Array);
92
+ });
93
+ });
94
+
95
+ // Test ingress.yaml configuration
96
+ describe('ingress.yaml', () => {
97
+ let ingressConfig;
98
+
99
+ beforeAll(() => {
100
+ const ingressFile = fs.readFileSync(
101
+ path.join(k8sPath, 'ingress.yaml'),
102
+ 'utf8'
103
+ );
104
+ ingressConfig = yaml.load(ingressFile);
105
+ });
106
+
107
+ test('should have correct API version and kind', () => {
108
+ expect(ingressConfig.apiVersion).toBe('networking.k8s.io/v1');
109
+ expect(ingressConfig.kind).toBe('Ingress');
110
+ });
111
+
112
+ test('should have proper ingress rules', () => {
113
+ expect(ingressConfig.spec).toHaveProperty('rules');
114
+ expect(ingressConfig.spec.rules).toBeInstanceOf(Array);
115
+ });
116
+ });
117
+
118
+ // Test configmap.yaml configuration
119
+ describe('configmap.yaml', () => {
120
+ let configMapConfig;
121
+
122
+ beforeAll(() => {
123
+ const configMapFile = fs.readFileSync(
124
+ path.join(k8sPath, 'configmap.yaml'),
125
+ 'utf8'
126
+ );
127
+ configMapConfig = yaml.load(configMapFile);
128
+ });
129
+
130
+ test('should have correct API version and kind', () => {
131
+ expect(configMapConfig.apiVersion).toBe('v1');
132
+ expect(configMapConfig.kind).toBe('ConfigMap');
133
+ });
134
+
135
+ test('should have data section', () => {
136
+ expect(configMapConfig).toHaveProperty('data');
137
+ expect(typeof configMapConfig.data).toBe('object');
138
+ });
139
+ });
140
+
141
+ // Test secrets.yaml configuration
142
+ describe('secrets.yaml', () => {
143
+ let secretsConfig;
144
+
145
+ beforeAll(() => {
146
+ const secretsFile = fs.readFileSync(
147
+ path.join(k8sPath, 'secrets.yaml'),
148
+ 'utf8'
149
+ );
150
+ secretsConfig = yaml.load(secretsFile);
151
+ });
152
+
153
+ test('should have correct API version and kind', () => {
154
+ expect(secretsConfig.apiVersion).toBe('v1');
155
+ expect(secretsConfig.kind).toBe('Secret');
156
+ });
157
+
158
+ test('should have proper secret type', () => {
159
+ expect(secretsConfig).toHaveProperty('type');
160
+ expect(secretsConfig.type).toBe('Opaque');
161
+ });
162
+
163
+ test('should have data section', () => {
164
+ expect(secretsConfig).toHaveProperty('data');
165
+ expect(typeof secretsConfig.data).toBe('object');
166
+ });
167
+ });
168
+ });
@@ -0,0 +1,4 @@
1
+
2
+ 2. Frontend service:
3
+
4
+ {"action": "writeFile", "filePath": "k8s/frontend-service.yaml"}
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "admin-dashboard",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "dev": "vite",
7
+ "build": "tsc && vite build",
8
+ "preview": "vite preview",
9
+ "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10
+ "format": "prettier --write \"src/**/*.{ts,tsx,json,md}\"",
11
+ "test": "jest",
12
+ "test:watch": "jest --watch",
13
+ "test:coverage": "jest --coverage"
14
+ },
15
+ "dependencies": {
16
+ "@emotion/react": "^11.11.1",
17
+ "@emotion/styled": "^11.11.0",
18
+ "@mui/material": "^5.14.5",
19
+ "@reduxjs/toolkit": "^1.9.5",
20
+ "axios": "^1.4.0",
21
+ "react": "^18.2.0",
22
+ "react-dom": "^18.2.0",
23
+ "react-hook-form": "^7.45.4",
24
+ "react-redux": "^8.1.2",
25
+ "react-router-dom": "^6.15.0",
26
+ "recharts": "^2.7.3",
27
+ "yup": "^1.2.0"
28
+ },
29
+ "devDependencies": {
30
+ "@testing-library/jest-dom": "^6.1.2",
31
+ "@testing-library/react": "^14.0.0",
32
+ "@types/node": "^20.5.7",
33
+ "@types/react": "^18.2.21",
34
+ "@types/react-dom": "^18.2.7",
35
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
36
+ "@typescript-eslint/parser": "^6.0.0",
37
+ "@vitejs/plugin-react": "^4.0.3",
38
+ "autoprefixer": "^10.4.15",
39
+ "eslint": "^8.45.0",
40
+ "eslint-config-airbnb": "^19.0.4",
41
+ "eslint-plugin-react-hooks": "^4.6.0",
42
+ "eslint-plugin-react-refresh": "^0.4.3",
43
+ "jest": "^29.6.4",
44
+ "postcss": "^8.4.28",
45
+ "prettier": "^3.0.2",
46
+ "tailwindcss": "^3.3.3",
47
+ "typescript": "^5.0.2",
48
+ "vite": "^4.4.5"
49
+ }
50
+ }
@@ -0,0 +1,176 @@
1
+ import { PrismaClient } from '@prisma/client';
2
+ import { execSync } from 'child_process';
3
+ import path from 'path';
4
+
5
+ describe('Prisma Schema Validation', () => {
6
+ let prisma: PrismaClient;
7
+
8
+ beforeAll(async () => {
9
+ // Reset the database before running tests
10
+ execSync('npx prisma migrate reset --force');
11
+ prisma = new PrismaClient();
12
+ });
13
+
14
+ afterAll(async () => {
15
+ await prisma.$disconnect();
16
+ });
17
+
18
+ describe('User Model', () => {
19
+ it('should create a user with required fields', async () => {
20
+ const user = await prisma.user.create({
21
+ data: {
22
+ email: 'test@example.com',
23
+ password: 'hashedPassword123',
24
+ },
25
+ });
26
+
27
+ expect(user).toHaveProperty('id');
28
+ expect(user.email).toBe('test@example.com');
29
+ expect(user.createdAt).toBeInstanceOf(Date);
30
+ expect(user.updatedAt).toBeInstanceOf(Date);
31
+ });
32
+
33
+ it('should not allow duplicate emails', async () => {
34
+ await expect(
35
+ prisma.user.create({
36
+ data: {
37
+ email: 'test@example.com',
38
+ password: 'anotherPassword',
39
+ },
40
+ })
41
+ ).rejects.toThrow();
42
+ });
43
+ });
44
+
45
+ describe('Profile Model', () => {
46
+ let userId: string;
47
+
48
+ beforeAll(async () => {
49
+ const user = await prisma.user.create({
50
+ data: {
51
+ email: 'profile.test@example.com',
52
+ password: 'hashedPassword123',
53
+ },
54
+ });
55
+ userId = user.id;
56
+ });
57
+
58
+ it('should create a profile linked to a user', async () => {
59
+ const profile = await prisma.profile.create({
60
+ data: {
61
+ firstName: 'John',
62
+ lastName: 'Doe',
63
+ userId: userId,
64
+ },
65
+ });
66
+
67
+ expect(profile).toHaveProperty('id');
68
+ expect(profile.firstName).toBe('John');
69
+ expect(profile.lastName).toBe('Doe');
70
+ expect(profile.userId).toBe(userId);
71
+ });
72
+
73
+ it('should not allow multiple profiles for the same user', async () => {
74
+ await expect(
75
+ prisma.profile.create({
76
+ data: {
77
+ firstName: 'Jane',
78
+ lastName: 'Doe',
79
+ userId: userId,
80
+ },
81
+ })
82
+ ).rejects.toThrow();
83
+ });
84
+ });
85
+
86
+ describe('Analytics Model', () => {
87
+ let userId: string;
88
+
89
+ beforeAll(async () => {
90
+ const user = await prisma.user.create({
91
+ data: {
92
+ email: 'analytics.test@example.com',
93
+ password: 'hashedPassword123',
94
+ },
95
+ });
96
+ userId = user.id;
97
+ });
98
+
99
+ it('should create analytics entry for a user', async () => {
100
+ const analytics = await prisma.analytics.create({
101
+ data: {
102
+ userId: userId,
103
+ eventType: 'LOGIN',
104
+ eventData: { ip: '127.0.0.1', userAgent: 'Test Browser' },
105
+ },
106
+ });
107
+
108
+ expect(analytics).toHaveProperty('id');
109
+ expect(analytics.userId).toBe(userId);
110
+ expect(analytics.eventType).toBe('LOGIN');
111
+ expect(analytics.eventData).toEqual({
112
+ ip: '127.0.0.1',
113
+ userAgent: 'Test Browser',
114
+ });
115
+ });
116
+
117
+ it('should allow multiple analytics entries for the same user', async () => {
118
+ await prisma.analytics.createMany({
119
+ data: [
120
+ {
121
+ userId: userId,
122
+ eventType: 'PAGE_VIEW',
123
+ eventData: { page: '/dashboard' },
124
+ },
125
+ {
126
+ userId: userId,
127
+ eventType: 'PAGE_VIEW',
128
+ eventData: { page: '/profile' },
129
+ },
130
+ ],
131
+ });
132
+
133
+ const analyticsCount = await prisma.analytics.count({
134
+ where: { userId: userId },
135
+ });
136
+
137
+ expect(analyticsCount).toBeGreaterThanOrEqual(3);
138
+ });
139
+ });
140
+
141
+ describe('Model Relationships', () => {
142
+ it('should fetch user with related profile and analytics', async () => {
143
+ const testUser = await prisma.user.create({
144
+ data: {
145
+ email: 'relationships.test@example.com',
146
+ password: 'hashedPassword123',
147
+ profile: {
148
+ create: {
149
+ firstName: 'Test',
150
+ lastName: 'User',
151
+ },
152
+ },
153
+ analytics: {
154
+ create: {
155
+ eventType: 'REGISTRATION',
156
+ eventData: { source: 'direct' },
157
+ },
158
+ },
159
+ },
160
+ });
161
+
162
+ const userWithRelations = await prisma.user.findUnique({
163
+ where: { id: testUser.id },
164
+ include: {
165
+ profile: true,
166
+ analytics: true,
167
+ },
168
+ });
169
+
170
+ expect(userWithRelations).toHaveProperty('profile');
171
+ expect(userWithRelations?.profile?.firstName).toBe('Test');
172
+ expect(userWithRelations?.analytics).toHaveLength(1);
173
+ expect(userWithRelations?.analytics[0].eventType).toBe('REGISTRATION');
174
+ });
175
+ });
176
+ });
@@ -0,0 +1,109 @@
1
+ // This is your Prisma schema file,
2
+ // learn more about it in the docs: https://pris.ly/d/prisma-schema
3
+
4
+ generator client {
5
+ provider = "prisma-client-js"
6
+ }
7
+
8
+ datasource db {
9
+ provider = "postgresql"
10
+ url = env("DATABASE_URL")
11
+ }
12
+
13
+ // User model - Core user information
14
+ model User {
15
+ id String @id @default(cuid())
16
+ email String @unique
17
+ passwordHash String
18
+ role Role @default(USER)
19
+ status UserStatus @default(ACTIVE)
20
+ createdAt DateTime @default(now())
21
+ updatedAt DateTime @updatedAt
22
+ lastLoginAt DateTime?
23
+
24
+ // Relations
25
+ profile Profile?
26
+ analytics Analytics[]
27
+
28
+ // Security and account management
29
+ resetToken String?
30
+ resetTokenExpiry DateTime?
31
+ verificationToken String?
32
+ isVerified Boolean @default(false)
33
+
34
+ @@map("users")
35
+ }
36
+
37
+ // Profile model - Extended user information
38
+ model Profile {
39
+ id String @id @default(cuid())
40
+ userId String @unique
41
+ firstName String?
42
+ lastName String?
43
+ avatar String?
44
+ phoneNumber String?
45
+ timezone String @default("UTC")
46
+ language String @default("en")
47
+
48
+ // Preferences and settings
49
+ notifications NotificationSettings?
50
+ theme String @default("light")
51
+
52
+ // Metadata
53
+ createdAt DateTime @default(now())
54
+ updatedAt DateTime @updatedAt
55
+
56
+ // Relations
57
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
58
+
59
+ @@map("profiles")
60
+ }
61
+
62
+ // Analytics model - User activity and metrics
63
+ model Analytics {
64
+ id String @id @default(cuid())
65
+ userId String
66
+ eventType String
67
+ eventData Json
68
+ userAgent String?
69
+ ipAddress String?
70
+ timestamp DateTime @default(now())
71
+
72
+ // Relations
73
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
74
+
75
+ // Indexes for better query performance
76
+ @@index([userId, eventType])
77
+ @@index([timestamp])
78
+
79
+ @@map("analytics")
80
+ }
81
+
82
+ // Notification settings - Embedded in Profile
83
+ model NotificationSettings {
84
+ id String @id @default(cuid())
85
+ profileId String @unique
86
+ email Boolean @default(true)
87
+ push Boolean @default(true)
88
+ sms Boolean @default(false)
89
+ marketing Boolean @default(false)
90
+
91
+ // Relations
92
+ profile Profile @relation(fields: [profileId], references: [id], onDelete: Cascade)
93
+
94
+ @@map("notification_settings")
95
+ }
96
+
97
+ // Enums
98
+ enum Role {
99
+ ADMIN
100
+ MANAGER
101
+ USER
102
+ }
103
+
104
+ enum UserStatus {
105
+ ACTIVE
106
+ INACTIVE
107
+ SUSPENDED
108
+ PENDING
109
+ }
@@ -0,0 +1,127 @@
1
+ import { Request, Response } from 'express';
2
+ import { DashboardController } from '../../controllers/dashboard.controller';
3
+ import prisma from '../../config/database';
4
+
5
+ // Mock the Prisma client
6
+ jest.mock('../../config/database', () => ({
7
+ analytics: {
8
+ findMany: jest.fn(),
9
+ groupBy: jest.fn(),
10
+ aggregate: jest.fn(),
11
+ },
12
+ user: {
13
+ count: jest.fn(),
14
+ },
15
+ }));
16
+
17
+ describe('DashboardController', () => {
18
+ let mockRequest: Partial<Request>;
19
+ let mockResponse: Partial<Response>;
20
+ let dashboardController: DashboardController;
21
+
22
+ beforeEach(() => {
23
+ mockRequest = {
24
+ query: {},
25
+ params: {},
26
+ body: {},
27
+ };
28
+ mockResponse = {
29
+ status: jest.fn().mockReturnThis(),
30
+ json: jest.fn(),
31
+ };
32
+ dashboardController = new DashboardController();
33
+ });
34
+
35
+ describe('getDashboardStats', () => {
36
+ it('should return dashboard statistics successfully', async () => {
37
+ // Mock the prisma queries
38
+ const mockUserCount = 100;
39
+ const mockAnalytics = [
40
+ { id: 1, value: 150, timestamp: new Date() },
41
+ { id: 2, value: 200, timestamp: new Date() },
42
+ ];
43
+
44
+ (prisma.user.count as jest.Mock).mockResolvedValue(mockUserCount);
45
+ (prisma.analytics.findMany as jest.Mock).mockResolvedValue(mockAnalytics);
46
+
47
+ await dashboardController.getDashboardStats(
48
+ mockRequest as Request,
49
+ mockResponse as Response
50
+ );
51
+
52
+ expect(mockResponse.status).toHaveBeenCalledWith(200);
53
+ expect(mockResponse.json).toHaveBeenCalledWith({
54
+ success: true,
55
+ data: {
56
+ totalUsers: mockUserCount,
57
+ analytics: mockAnalytics,
58
+ },
59
+ });
60
+ });
61
+
62
+ it('should handle errors appropriately', async () => {
63
+ const errorMessage = 'Database error';
64
+ (prisma.user.count as jest.Mock).mockRejectedValue(new Error(errorMessage));
65
+
66
+ await dashboardController.getDashboardStats(
67
+ mockRequest as Request,
68
+ mockResponse as Response
69
+ );
70
+
71
+ expect(mockResponse.status).toHaveBeenCalledWith(500);
72
+ expect(mockResponse.json).toHaveBeenCalledWith({
73
+ success: false,
74
+ error: 'Failed to fetch dashboard statistics',
75
+ });
76
+ });
77
+ });
78
+
79
+ describe('getAnalytics', () => {
80
+ it('should return analytics data with proper date filtering', async () => {
81
+ const mockRequest = {
82
+ query: {
83
+ startDate: '2026-01-01',
84
+ endDate: '2026-02-08',
85
+ },
86
+ } as Partial<Request>;
87
+
88
+ const mockAnalyticsData = [
89
+ { date: '2026-01-01', count: 10 },
90
+ { date: '2026-01-02', count: 15 },
91
+ ];
92
+
93
+ (prisma.analytics.groupBy as jest.Mock).mockResolvedValue(mockAnalyticsData);
94
+
95
+ await dashboardController.getAnalytics(
96
+ mockRequest as Request,
97
+ mockResponse as Response
98
+ );
99
+
100
+ expect(mockResponse.status).toHaveBeenCalledWith(200);
101
+ expect(mockResponse.json).toHaveBeenCalledWith({
102
+ success: true,
103
+ data: mockAnalyticsData,
104
+ });
105
+ });
106
+
107
+ it('should handle invalid date parameters', async () => {
108
+ const mockRequest = {
109
+ query: {
110
+ startDate: 'invalid-date',
111
+ endDate: '2026-02-08',
112
+ },
113
+ } as Partial<Request>;
114
+
115
+ await dashboardController.getAnalytics(
116
+ mockRequest as Request,
117
+ mockResponse as Response
118
+ );
119
+
120
+ expect(mockResponse.status).toHaveBeenCalledWith(400);
121
+ expect(mockResponse.json).toHaveBeenCalledWith({
122
+ success: false,
123
+ error: 'Invalid date parameters',
124
+ });
125
+ });
126
+ });
127
+ });
@@ -0,0 +1,60 @@
1
+ import request from 'supertest';
2
+ import { Express } from 'express';
3
+ import { createServer } from '../index';
4
+ import { connectDatabase } from '../config/database';
5
+ import { connectRedis } from '../config/redis';
6
+
7
+ // Mock the database and redis connections
8
+ jest.mock('../config/database');
9
+ jest.mock('../config/redis');
10
+
11
+ describe('Server Setup', () => {
12
+ let app: Express;
13
+
14
+ beforeEach(async () => {
15
+ // Reset all mocks before each test
16
+ jest.clearAllMocks();
17
+ app = await createServer();
18
+ });
19
+
20
+ describe('Server Initialization', () => {
21
+ it('should create an Express server successfully', async () => {
22
+ expect(app).toBeDefined();
23
+ });
24
+
25
+ it('should connect to database on startup', async () => {
26
+ expect(connectDatabase).toHaveBeenCalled();
27
+ });
28
+
29
+ it('should connect to Redis on startup', async () => {
30
+ expect(connectRedis).toHaveBeenCalled();
31
+ });
32
+
33
+ it('should respond to health check endpoint', async () => {
34
+ const response = await request(app).get('/health');
35
+ expect(response.status).toBe(200);
36
+ expect(response.body).toEqual({ status: 'ok' });
37
+ });
38
+
39
+ it('should handle undefined routes', async () => {
40
+ const response = await request(app).get('/non-existent-route');
41
+ expect(response.status).toBe(404);
42
+ });
43
+ });
44
+
45
+ describe('Server Configuration', () => {
46
+ it('should use JSON middleware', async () => {
47
+ const response = await request(app)
48
+ .post('/api/test')
49
+ .send({ test: 'data' });
50
+
51
+ // Even though route doesn't exist, server should parse JSON
52
+ expect(response.status).toBe(404);
53
+ });
54
+
55
+ it('should have CORS enabled', async () => {
56
+ const response = await request(app).options('/');
57
+ expect(response.headers['access-control-allow-origin']).toBeDefined();
58
+ });
59
+ });
60
+ });