@tantainnovative/ndpr-toolkit 1.0.3 → 1.0.4

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 (156) hide show
  1. package/next-env.d.ts +5 -0
  2. package/package.json +1 -1
  3. package/.claude/settings.local.json +0 -20
  4. package/.eslintrc.json +0 -10
  5. package/.github/workflows/ci.yml +0 -36
  6. package/.github/workflows/nextjs.yml +0 -104
  7. package/.husky/commit-msg +0 -4
  8. package/.husky/pre-commit +0 -4
  9. package/.lintstagedrc.js +0 -4
  10. package/.nvmrc +0 -1
  11. package/.versionrc +0 -17
  12. package/CLAUDE.md +0 -90
  13. package/commitlint.config.js +0 -36
  14. package/eslint.config.mjs +0 -16
  15. package/jest.config.js +0 -31
  16. package/jest.setup.js +0 -15
  17. package/next.config.js +0 -15
  18. package/next.config.ts +0 -62
  19. package/packages/ndpr-toolkit/README.md +0 -467
  20. package/packages/ndpr-toolkit/jest.config.js +0 -23
  21. package/packages/ndpr-toolkit/package-lock.json +0 -8197
  22. package/packages/ndpr-toolkit/package.json +0 -71
  23. package/packages/ndpr-toolkit/rollup.config.js +0 -34
  24. package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentBanner.test.tsx +0 -119
  25. package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentManager.test.tsx +0 -122
  26. package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentStorage.test.tsx +0 -270
  27. package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRDashboard.test.tsx +0 -199
  28. package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRRequestForm.test.tsx +0 -224
  29. package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRTracker.test.tsx +0 -104
  30. package/packages/ndpr-toolkit/src/__tests__/hooks/useConsent.test.tsx +0 -161
  31. package/packages/ndpr-toolkit/src/__tests__/hooks/useDSR.test.tsx +0 -330
  32. package/packages/ndpr-toolkit/src/__tests__/utils/breach.test.ts +0 -149
  33. package/packages/ndpr-toolkit/src/__tests__/utils/consent.test.ts +0 -88
  34. package/packages/ndpr-toolkit/src/__tests__/utils/dpia.test.ts +0 -160
  35. package/packages/ndpr-toolkit/src/__tests__/utils/dsr.test.ts +0 -110
  36. package/packages/ndpr-toolkit/src/__tests__/utils/privacy.test.ts +0 -97
  37. package/packages/ndpr-toolkit/src/components/breach/BreachNotificationManager.tsx +0 -701
  38. package/packages/ndpr-toolkit/src/components/breach/BreachReportForm.tsx +0 -631
  39. package/packages/ndpr-toolkit/src/components/breach/BreachRiskAssessment.tsx +0 -569
  40. package/packages/ndpr-toolkit/src/components/breach/RegulatoryReportGenerator.tsx +0 -496
  41. package/packages/ndpr-toolkit/src/components/consent/ConsentBanner.tsx +0 -270
  42. package/packages/ndpr-toolkit/src/components/consent/ConsentManager.tsx +0 -217
  43. package/packages/ndpr-toolkit/src/components/consent/ConsentStorage.tsx +0 -206
  44. package/packages/ndpr-toolkit/src/components/dpia/DPIAQuestionnaire.tsx +0 -342
  45. package/packages/ndpr-toolkit/src/components/dpia/DPIAReport.tsx +0 -373
  46. package/packages/ndpr-toolkit/src/components/dpia/StepIndicator.tsx +0 -174
  47. package/packages/ndpr-toolkit/src/components/dsr/DSRDashboard.tsx +0 -717
  48. package/packages/ndpr-toolkit/src/components/dsr/DSRRequestForm.tsx +0 -476
  49. package/packages/ndpr-toolkit/src/components/dsr/DSRTracker.tsx +0 -620
  50. package/packages/ndpr-toolkit/src/components/policy/PolicyExporter.tsx +0 -541
  51. package/packages/ndpr-toolkit/src/components/policy/PolicyGenerator.tsx +0 -454
  52. package/packages/ndpr-toolkit/src/components/policy/PolicyPreview.tsx +0 -333
  53. package/packages/ndpr-toolkit/src/hooks/useBreach.ts +0 -409
  54. package/packages/ndpr-toolkit/src/hooks/useConsent.ts +0 -263
  55. package/packages/ndpr-toolkit/src/hooks/useDPIA.ts +0 -457
  56. package/packages/ndpr-toolkit/src/hooks/useDSR.ts +0 -236
  57. package/packages/ndpr-toolkit/src/hooks/usePrivacyPolicy.ts +0 -428
  58. package/packages/ndpr-toolkit/src/index.ts +0 -44
  59. package/packages/ndpr-toolkit/src/setupTests.ts +0 -5
  60. package/packages/ndpr-toolkit/src/types/breach.ts +0 -283
  61. package/packages/ndpr-toolkit/src/types/consent.ts +0 -111
  62. package/packages/ndpr-toolkit/src/types/dpia.ts +0 -236
  63. package/packages/ndpr-toolkit/src/types/dsr.ts +0 -192
  64. package/packages/ndpr-toolkit/src/types/index.ts +0 -42
  65. package/packages/ndpr-toolkit/src/types/privacy.ts +0 -246
  66. package/packages/ndpr-toolkit/src/utils/breach.ts +0 -122
  67. package/packages/ndpr-toolkit/src/utils/consent.ts +0 -51
  68. package/packages/ndpr-toolkit/src/utils/dpia.ts +0 -104
  69. package/packages/ndpr-toolkit/src/utils/dsr.ts +0 -77
  70. package/packages/ndpr-toolkit/src/utils/privacy.ts +0 -100
  71. package/packages/ndpr-toolkit/tsconfig.json +0 -23
  72. package/postcss.config.mjs +0 -5
  73. package/src/__tests__/example.test.ts +0 -13
  74. package/src/__tests__/requestService.test.ts +0 -57
  75. package/src/app/accessibility.css +0 -70
  76. package/src/app/docs/components/DocLayout.tsx +0 -267
  77. package/src/app/docs/components/breach-notification/page.tsx +0 -797
  78. package/src/app/docs/components/consent-management/page.tsx +0 -576
  79. package/src/app/docs/components/data-subject-rights/page.tsx +0 -511
  80. package/src/app/docs/components/dpia-questionnaire/layout.tsx +0 -15
  81. package/src/app/docs/components/dpia-questionnaire/metadata.ts +0 -31
  82. package/src/app/docs/components/dpia-questionnaire/page.tsx +0 -666
  83. package/src/app/docs/components/hooks/page.tsx +0 -305
  84. package/src/app/docs/components/page.tsx +0 -84
  85. package/src/app/docs/components/privacy-policy-generator/page.tsx +0 -634
  86. package/src/app/docs/guides/breach-notification-process/components/BestPractices.tsx +0 -123
  87. package/src/app/docs/guides/breach-notification-process/components/ImplementationSteps.tsx +0 -328
  88. package/src/app/docs/guides/breach-notification-process/components/Introduction.tsx +0 -28
  89. package/src/app/docs/guides/breach-notification-process/components/NotificationTimeline.tsx +0 -91
  90. package/src/app/docs/guides/breach-notification-process/components/Resources.tsx +0 -118
  91. package/src/app/docs/guides/breach-notification-process/page.tsx +0 -39
  92. package/src/app/docs/guides/conducting-dpia/page.tsx +0 -593
  93. package/src/app/docs/guides/data-subject-requests/page.tsx +0 -666
  94. package/src/app/docs/guides/managing-consent/page.tsx +0 -738
  95. package/src/app/docs/guides/ndpr-compliance-checklist/components/ComplianceChecklist.tsx +0 -296
  96. package/src/app/docs/guides/ndpr-compliance-checklist/components/ImplementationTools.tsx +0 -145
  97. package/src/app/docs/guides/ndpr-compliance-checklist/components/Introduction.tsx +0 -33
  98. package/src/app/docs/guides/ndpr-compliance-checklist/components/KeyRequirements.tsx +0 -99
  99. package/src/app/docs/guides/ndpr-compliance-checklist/components/Resources.tsx +0 -159
  100. package/src/app/docs/guides/ndpr-compliance-checklist/page.tsx +0 -38
  101. package/src/app/docs/guides/page.tsx +0 -67
  102. package/src/app/docs/layout.tsx +0 -15
  103. package/src/app/docs/metadata.ts +0 -31
  104. package/src/app/docs/page.tsx +0 -572
  105. package/src/app/favicon.ico +0 -0
  106. package/src/app/globals.css +0 -123
  107. package/src/app/layout.tsx +0 -37
  108. package/src/app/ndpr-demos/breach/page.tsx +0 -354
  109. package/src/app/ndpr-demos/consent/page.tsx +0 -366
  110. package/src/app/ndpr-demos/dpia/page.tsx +0 -495
  111. package/src/app/ndpr-demos/dsr/page.tsx +0 -280
  112. package/src/app/ndpr-demos/page.tsx +0 -73
  113. package/src/app/ndpr-demos/policy/page.tsx +0 -771
  114. package/src/app/page.tsx +0 -452
  115. package/src/components/ErrorBoundary.tsx +0 -90
  116. package/src/components/breach-notification/BreachNotificationForm.tsx +0 -479
  117. package/src/components/consent/ConsentBanner.tsx +0 -159
  118. package/src/components/data-subject-rights/DataSubjectRequestForm.tsx +0 -419
  119. package/src/components/docs/DocLayout.tsx +0 -289
  120. package/src/components/docs/index.ts +0 -2
  121. package/src/components/dpia/DPIAQuestionnaire.tsx +0 -483
  122. package/src/components/privacy-policy/PolicyGenerator.tsx +0 -1062
  123. package/src/components/privacy-policy/data.ts +0 -98
  124. package/src/components/privacy-policy/shared/CheckboxField.tsx +0 -38
  125. package/src/components/privacy-policy/shared/CheckboxGroup.tsx +0 -85
  126. package/src/components/privacy-policy/shared/FormField.tsx +0 -79
  127. package/src/components/privacy-policy/shared/StepIndicator.tsx +0 -86
  128. package/src/components/privacy-policy/steps/CustomSectionsStep.tsx +0 -335
  129. package/src/components/privacy-policy/steps/DataCollectionStep.tsx +0 -231
  130. package/src/components/privacy-policy/steps/DataSharingStep.tsx +0 -418
  131. package/src/components/privacy-policy/steps/OrganizationInfoStep.tsx +0 -202
  132. package/src/components/privacy-policy/steps/PolicyPreviewStep.tsx +0 -172
  133. package/src/components/ui/Badge.tsx +0 -46
  134. package/src/components/ui/Button.tsx +0 -59
  135. package/src/components/ui/Card.tsx +0 -92
  136. package/src/components/ui/Checkbox.tsx +0 -57
  137. package/src/components/ui/FormField.tsx +0 -50
  138. package/src/components/ui/Input.tsx +0 -38
  139. package/src/components/ui/Loading.tsx +0 -201
  140. package/src/components/ui/Select.tsx +0 -42
  141. package/src/components/ui/TextArea.tsx +0 -38
  142. package/src/components/ui/label.tsx +0 -24
  143. package/src/components/ui/switch.tsx +0 -31
  144. package/src/components/ui/tabs.tsx +0 -66
  145. package/src/hooks/useConsent.ts +0 -64
  146. package/src/hooks/useLoadingState.ts +0 -85
  147. package/src/lib/consentService.ts +0 -137
  148. package/src/lib/dpiaQuestions.ts +0 -148
  149. package/src/lib/requestService.ts +0 -75
  150. package/src/lib/sanitize.ts +0 -108
  151. package/src/lib/storage.ts +0 -222
  152. package/src/lib/utils.ts +0 -6
  153. package/src/types/html-to-docx.d.ts +0 -30
  154. package/src/types/index.ts +0 -72
  155. package/tailwind.config.ts +0 -65
  156. package/tsconfig.json +0 -41
@@ -1,330 +0,0 @@
1
- import { renderHook, act } from '@testing-library/react';
2
- import { useDSR } from '../../hooks/useDSR';
3
- import React from 'react';
4
- import { DSRRequest, RequestType } from '../../types/dsr';
5
-
6
- // Mock localStorage
7
- const mockLocalStorage = (() => {
8
- let store: Record<string, string> = {};
9
- return {
10
- getItem: jest.fn((key: string) => store[key] || null),
11
- setItem: jest.fn((key: string, value: string) => {
12
- store[key] = value.toString();
13
- }),
14
- removeItem: jest.fn((key: string) => {
15
- delete store[key];
16
- }),
17
- clear: jest.fn(() => {
18
- store = {};
19
- }),
20
- };
21
- })();
22
-
23
- Object.defineProperty(window, 'localStorage', {
24
- value: mockLocalStorage,
25
- });
26
-
27
- describe('useDSR', () => {
28
- beforeEach(() => {
29
- mockLocalStorage.clear();
30
- jest.clearAllMocks();
31
- });
32
-
33
- const mockRequestTypes: RequestType[] = [
34
- {
35
- id: 'access',
36
- name: 'Access Request',
37
- description: 'Request to access your personal data',
38
- estimatedCompletionTime: 30,
39
- requiresAdditionalInfo: false
40
- },
41
- {
42
- id: 'erasure',
43
- name: 'Erasure Request',
44
- description: 'Request to delete your personal data',
45
- estimatedCompletionTime: 45,
46
- requiresAdditionalInfo: false
47
- },
48
- {
49
- id: 'rectification',
50
- name: 'Rectification Request',
51
- description: 'Request to correct your personal data',
52
- estimatedCompletionTime: 15,
53
- requiresAdditionalInfo: true
54
- }
55
- ];
56
-
57
- it('should initialize with empty requests array', () => {
58
- const { result } = renderHook(() => useDSR({
59
- requestTypes: mockRequestTypes,
60
- storageKey: 'test-dsr',
61
- useLocalStorage: true
62
- }));
63
-
64
- expect(result.current.requests).toEqual([]);
65
- });
66
-
67
- it('should submit a new DSR request', () => {
68
- const { result } = renderHook(() => useDSR({
69
- requestTypes: mockRequestTypes,
70
- storageKey: 'test-dsr',
71
- useLocalStorage: true
72
- }));
73
-
74
- act(() => {
75
- result.current.submitRequest({
76
- type: 'access',
77
- subject: {
78
- name: 'John Doe',
79
- email: 'john@example.com',
80
- },
81
- createdAt: Date.now(),
82
- description: 'I want to access my data',
83
- });
84
- });
85
-
86
- expect(result.current.requests.length).toBe(1);
87
- expect(result.current.requests[0].type).toBe('access');
88
- expect(result.current.requests[0].status).toBe('pending');
89
- expect(result.current.requests[0].subject.name).toBe('John Doe');
90
- expect(result.current.requests[0].id).toBeDefined();
91
- expect(result.current.requests[0].createdAt).toBeDefined();
92
- expect(result.current.requests[0].updatedAt).toBeDefined();
93
- });
94
-
95
- it('should get a request by ID', () => {
96
- const { result } = renderHook(() => useDSR({
97
- requestTypes: mockRequestTypes,
98
- storageKey: 'test-dsr',
99
- useLocalStorage: true
100
- }));
101
-
102
- // Initialize requestId with a default value
103
- let requestId: string = '';
104
-
105
- act(() => {
106
- const request = result.current.submitRequest({
107
- type: 'access',
108
- subject: {
109
- name: 'John Doe',
110
- email: 'john@example.com',
111
- },
112
- createdAt: Date.now(),
113
- });
114
- requestId = request.id;
115
- });
116
-
117
- const retrievedRequest = result.current.getRequest(requestId);
118
- expect(retrievedRequest).toBeDefined();
119
- expect(retrievedRequest?.id).toBe(requestId);
120
- });
121
-
122
- it('should update a request', () => {
123
- const { result } = renderHook(() => useDSR({
124
- requestTypes: mockRequestTypes,
125
- storageKey: 'test-dsr',
126
- useLocalStorage: true
127
- }));
128
-
129
- let requestId = '';
130
-
131
- act(() => {
132
- const request = result.current.submitRequest({
133
- type: 'access',
134
- subject: {
135
- name: 'John Doe',
136
- email: 'john@example.com',
137
- },
138
- createdAt: Date.now(),
139
- });
140
- requestId = request.id;
141
- });
142
-
143
- act(() => {
144
- result.current.updateRequest(requestId!, {
145
- status: 'inProgress',
146
- internalNotes: [
147
- {
148
- timestamp: Date.now(),
149
- author: 'Admin',
150
- note: 'Working on this request',
151
- },
152
- ],
153
- });
154
- });
155
-
156
- const updatedRequest = result.current.getRequest(requestId!);
157
- expect(updatedRequest?.status).toBe('inProgress');
158
- expect(updatedRequest?.internalNotes?.length).toBe(1);
159
- expect(updatedRequest?.internalNotes?.[0].author).toBe('Admin');
160
- });
161
-
162
- it('should clear all requests', () => {
163
- const { result } = renderHook(() => useDSR({
164
- requestTypes: mockRequestTypes,
165
- storageKey: 'test-dsr',
166
- useLocalStorage: true
167
- }));
168
-
169
- act(() => {
170
- result.current.submitRequest({
171
- type: 'access',
172
- subject: {
173
- name: 'John Doe',
174
- email: 'john@example.com',
175
- },
176
- createdAt: Date.now(),
177
- });
178
- });
179
-
180
- expect(result.current.requests.length).toBe(1);
181
-
182
- act(() => {
183
- result.current.clearRequests();
184
- });
185
-
186
- expect(result.current.requests.length).toBe(0);
187
- });
188
-
189
- it('should filter requests by type', () => {
190
- const { result } = renderHook(() => useDSR({
191
- requestTypes: mockRequestTypes,
192
- storageKey: 'test-dsr',
193
- useLocalStorage: true
194
- }));
195
-
196
- act(() => {
197
- result.current.submitRequest({
198
- type: 'access',
199
- subject: {
200
- name: 'John Doe',
201
- email: 'john@example.com',
202
- },
203
- createdAt: Date.now(),
204
- });
205
-
206
- result.current.submitRequest({
207
- type: 'erasure',
208
- subject: {
209
- name: 'Jane Smith',
210
- email: 'jane@example.com',
211
- },
212
- createdAt: Date.now(),
213
- });
214
-
215
- result.current.submitRequest({
216
- type: 'access',
217
- subject: {
218
- name: 'Bob Johnson',
219
- email: 'bob@example.com',
220
- },
221
- createdAt: Date.now(),
222
- });
223
- });
224
-
225
- const accessRequests = result.current.getRequestsByType('access');
226
- expect(accessRequests.length).toBe(2);
227
- expect(accessRequests[0].subject.name).toBe('John Doe');
228
- expect(accessRequests[1].subject.name).toBe('Bob Johnson');
229
-
230
- const erasureRequests = result.current.getRequestsByType('erasure');
231
- expect(erasureRequests.length).toBe(1);
232
- expect(erasureRequests[0].subject.name).toBe('Jane Smith');
233
- });
234
-
235
- it('should filter requests by status', () => {
236
- const { result } = renderHook(() => useDSR({
237
- requestTypes: mockRequestTypes,
238
- storageKey: 'test-dsr',
239
- useLocalStorage: true
240
- }));
241
-
242
- let requestId: string = '';
243
-
244
- act(() => {
245
- result.current.submitRequest({
246
- type: 'access',
247
- subject: {
248
- name: 'John Doe',
249
- email: 'john@example.com',
250
- },
251
- createdAt: Date.now(),
252
- });
253
-
254
- const request = result.current.submitRequest({
255
- type: 'erasure',
256
- subject: {
257
- name: 'Jane Smith',
258
- email: 'jane@example.com',
259
- },
260
- createdAt: Date.now(),
261
- });
262
- requestId = request.id;
263
-
264
- result.current.submitRequest({
265
- type: 'rectification',
266
- subject: {
267
- name: 'Bob Johnson',
268
- email: 'bob@example.com',
269
- },
270
- createdAt: Date.now(),
271
- });
272
- });
273
-
274
- act(() => {
275
- result.current.updateRequest(requestId!, {
276
- status: 'completed',
277
- });
278
- });
279
-
280
- const pendingRequests = result.current.getRequestsByStatus('pending');
281
- expect(pendingRequests.length).toBe(2);
282
-
283
- const completedRequests = result.current.getRequestsByStatus('completed');
284
- expect(completedRequests.length).toBe(1);
285
- expect(completedRequests[0].subject.name).toBe('Jane Smith');
286
- });
287
-
288
- it('should format a request', () => {
289
- const { result } = renderHook(() => useDSR({
290
- requestTypes: mockRequestTypes,
291
- storageKey: 'test-dsr',
292
- useLocalStorage: true
293
- }));
294
-
295
- let request: DSRRequest | null = null;
296
-
297
- act(() => {
298
- request = result.current.submitRequest({
299
- type: 'access',
300
- subject: {
301
- name: 'John Doe',
302
- email: 'john@example.com',
303
- },
304
- createdAt: Date.now(),
305
- });
306
- });
307
-
308
- expect(request).not.toBeNull();
309
-
310
- if (request) {
311
- const formattedRequest = result.current.formatRequest(request);
312
- expect(formattedRequest).toBeDefined();
313
- expect(formattedRequest.requestType).toBe('access');
314
- expect(formattedRequest.dataSubject.name).toBe('John Doe');
315
- }
316
- });
317
-
318
- it('should get request type by ID', () => {
319
- const { result } = renderHook(() => useDSR({
320
- requestTypes: mockRequestTypes,
321
- storageKey: 'test-dsr',
322
- useLocalStorage: true
323
- }));
324
-
325
- const requestType = result.current.getRequestType('access');
326
- expect(requestType).toBeDefined();
327
- expect(requestType?.name).toBe('Access Request');
328
- expect(requestType?.estimatedCompletionTime).toBe(30);
329
- });
330
- });
@@ -1,149 +0,0 @@
1
- import { calculateBreachSeverity } from '../../utils/breach';
2
- import { BreachReport, RiskAssessment } from '../../types/breach';
3
-
4
- describe('calculateBreachSeverity', () => {
5
- const breachReport: BreachReport = {
6
- id: 'breach-123',
7
- title: 'Database Breach',
8
- description: 'Unauthorized access to customer database',
9
- category: 'unauthorized_access',
10
- discoveredAt: 1620000000000,
11
- occurredAt: 1619900000000,
12
- reportedAt: 1620010000000,
13
- reporter: {
14
- name: 'John Smith',
15
- email: 'john@example.com',
16
- department: 'IT Security',
17
- phone: '1234567890'
18
- },
19
- affectedSystems: ['customer-db', 'payment-system'],
20
- dataTypes: ['personal', 'financial'],
21
- estimatedAffectedSubjects: 1000,
22
- status: 'contained'
23
- };
24
-
25
- it('should calculate high severity for sensitive data and large number of affected subjects', () => {
26
- const assessment: RiskAssessment = {
27
- id: 'risk-123',
28
- breachId: 'breach-123',
29
- assessor: {
30
- name: 'John Doe',
31
- role: 'DPO',
32
- email: 'dpo@example.com'
33
- },
34
- assessedAt: 1620000000000,
35
- confidentialityImpact: 4,
36
- integrityImpact: 3,
37
- availabilityImpact: 3,
38
- harmLikelihood: 4,
39
- harmSeverity: 4,
40
- overallRiskScore: 16,
41
- riskLevel: 'high',
42
- risksToRightsAndFreedoms: true,
43
- highRisksToRightsAndFreedoms: true,
44
- justification: 'High risk due to sensitive financial data'
45
- };
46
-
47
- const result = calculateBreachSeverity(breachReport, assessment);
48
-
49
- expect(result.severityLevel).toBe('high');
50
- expect(result.notificationRequired).toBe(true);
51
- expect(result.urgentNotificationRequired).toBe(true);
52
- expect(result.timeframeHours).toBe(72);
53
- expect(result.justification).toBe('High risk due to sensitive financial data');
54
- });
55
-
56
- it('should calculate medium severity for non-sensitive data with medium impact', () => {
57
- const assessment: RiskAssessment = {
58
- id: 'risk-456',
59
- breachId: 'breach-456',
60
- assessor: {
61
- name: 'Jane Smith',
62
- role: 'Security Officer',
63
- email: 'security@example.com'
64
- },
65
- assessedAt: 1620100000000,
66
- confidentialityImpact: 3,
67
- integrityImpact: 2,
68
- availabilityImpact: 2,
69
- harmLikelihood: 3,
70
- harmSeverity: 3,
71
- overallRiskScore: 9,
72
- riskLevel: 'medium',
73
- risksToRightsAndFreedoms: true,
74
- highRisksToRightsAndFreedoms: false,
75
- justification: 'Medium risk due to personal data exposure'
76
- };
77
-
78
- const result = calculateBreachSeverity(breachReport, assessment);
79
-
80
- expect(result.severityLevel).toBe('medium');
81
- expect(result.notificationRequired).toBe(true);
82
- expect(result.urgentNotificationRequired).toBe(false);
83
- expect(result.timeframeHours).toBe(72);
84
- expect(result.justification).toBe('Medium risk due to personal data exposure');
85
- });
86
-
87
- it('should calculate low severity for contained breach with low impact', () => {
88
- const assessment: RiskAssessment = {
89
- id: 'risk-789',
90
- breachId: 'breach-789',
91
- assessor: {
92
- name: 'Alex Johnson',
93
- role: 'Compliance Manager',
94
- email: 'compliance@example.com'
95
- },
96
- assessedAt: 1620200000000,
97
- confidentialityImpact: 1,
98
- integrityImpact: 1,
99
- availabilityImpact: 2,
100
- harmLikelihood: 2,
101
- harmSeverity: 1,
102
- overallRiskScore: 2,
103
- riskLevel: 'low',
104
- risksToRightsAndFreedoms: false,
105
- highRisksToRightsAndFreedoms: false,
106
- justification: 'Low risk due to minimal data exposure'
107
- };
108
-
109
- const result = calculateBreachSeverity(breachReport, assessment);
110
-
111
- expect(result.severityLevel).toBe('low');
112
- expect(result.notificationRequired).toBe(false);
113
- expect(result.urgentNotificationRequired).toBe(false);
114
- expect(result.timeframeHours).toBe(72);
115
- expect(result.justification).toBe('Low risk due to minimal data exposure');
116
- });
117
-
118
- it('should calculate severity based on breach report when no assessment is provided', () => {
119
- // Create a breach report with sensitive data and large scale
120
- const sensitiveBreachReport: BreachReport = {
121
- ...breachReport,
122
- dataTypes: ['personal', 'financial', 'health'],
123
- estimatedAffectedSubjects: 5000,
124
- status: 'ongoing'
125
- };
126
-
127
- const result = calculateBreachSeverity(sensitiveBreachReport);
128
-
129
- // With 3 severity factors (sensitive data, large scale, ongoing), it should be critical
130
- expect(result.severityLevel).toBe('critical');
131
- expect(result.notificationRequired).toBe(true);
132
- expect(result.urgentNotificationRequired).toBe(true);
133
- expect(result.timeframeHours).toBe(72);
134
- expect(result.justification).toContain('Critical risk');
135
- });
136
-
137
- it('should always require notification for ongoing breaches', () => {
138
- const ongoingBreachReport: BreachReport = {
139
- ...breachReport,
140
- status: 'ongoing',
141
- dataTypes: ['personal']
142
- };
143
-
144
- const result = calculateBreachSeverity(ongoingBreachReport);
145
-
146
- expect(result.notificationRequired).toBe(true);
147
- expect(result.justification).toContain('Medium risk');
148
- });
149
- });
@@ -1,88 +0,0 @@
1
- import { validateConsent } from '../../utils/consent';
2
- import { ConsentSettings } from '../../types/consent';
3
-
4
- describe('validateConsent', () => {
5
- it('should validate valid consent settings', () => {
6
- const settings: ConsentSettings = {
7
- consents: {
8
- necessary: true,
9
- analytics: false,
10
- marketing: true
11
- },
12
- timestamp: Date.now(),
13
- version: '1.0',
14
- method: 'banner',
15
- hasInteracted: true
16
- };
17
-
18
- const result = validateConsent(settings);
19
- expect(result.valid).toBe(true);
20
- expect(result.errors).toEqual([]);
21
- });
22
-
23
- it('should invalidate settings with missing consents', () => {
24
- const settings: ConsentSettings = {
25
- consents: {},
26
- timestamp: Date.now(),
27
- version: '1.0',
28
- method: 'banner',
29
- hasInteracted: true
30
- };
31
-
32
- const result = validateConsent(settings);
33
- expect(result.valid).toBe(false);
34
- expect(result.errors).toContain('Consent settings must include at least one consent option');
35
- });
36
-
37
- it('should invalidate settings with missing timestamp', () => {
38
- const settings = {
39
- consents: { necessary: true },
40
- version: '1.0',
41
- method: 'banner',
42
- hasInteracted: true
43
- } as unknown as ConsentSettings;
44
-
45
- const result = validateConsent(settings);
46
- expect(result.valid).toBe(false);
47
- expect(result.errors).toContain('Consent timestamp is required');
48
- });
49
-
50
- it('should invalidate settings with missing version', () => {
51
- const settings = {
52
- consents: { necessary: true },
53
- timestamp: Date.now(),
54
- method: 'banner',
55
- hasInteracted: true
56
- } as unknown as ConsentSettings;
57
-
58
- const result = validateConsent(settings);
59
- expect(result.valid).toBe(false);
60
- expect(result.errors).toContain('Consent version is required');
61
- });
62
-
63
- it('should invalidate settings with missing method', () => {
64
- const settings = {
65
- consents: { necessary: true },
66
- timestamp: Date.now(),
67
- version: '1.0',
68
- hasInteracted: true
69
- } as unknown as ConsentSettings;
70
-
71
- const result = validateConsent(settings);
72
- expect(result.valid).toBe(false);
73
- expect(result.errors).toContain('Consent collection method is required');
74
- });
75
-
76
- it('should invalidate settings with missing hasInteracted', () => {
77
- const settings = {
78
- consents: { necessary: true },
79
- timestamp: Date.now(),
80
- version: '1.0',
81
- method: 'banner'
82
- } as unknown as ConsentSettings;
83
-
84
- const result = validateConsent(settings);
85
- expect(result.valid).toBe(false);
86
- expect(result.errors).toContain('User interaction status is required');
87
- });
88
- });