@tantainnovative/ndpr-toolkit 1.0.3 → 1.0.5

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 (110) hide show
  1. package/next-env.d.ts +5 -0
  2. package/package.json +1 -1
  3. package/packages/ndpr-toolkit/dist/components/breach/BreachNotificationManager.d.ts +62 -0
  4. package/packages/ndpr-toolkit/dist/components/breach/BreachReportForm.d.ts +66 -0
  5. package/packages/ndpr-toolkit/dist/components/breach/BreachRiskAssessment.d.ts +50 -0
  6. package/packages/ndpr-toolkit/dist/components/breach/RegulatoryReportGenerator.d.ts +94 -0
  7. package/packages/ndpr-toolkit/dist/components/consent/ConsentBanner.d.ts +79 -0
  8. package/packages/ndpr-toolkit/dist/components/consent/ConsentManager.d.ts +73 -0
  9. package/packages/ndpr-toolkit/dist/components/consent/ConsentStorage.d.ts +41 -0
  10. package/packages/ndpr-toolkit/dist/components/dpia/DPIAQuestionnaire.d.ts +70 -0
  11. package/packages/ndpr-toolkit/dist/components/dpia/DPIAReport.d.ts +40 -0
  12. package/packages/ndpr-toolkit/dist/components/dpia/StepIndicator.d.ts +64 -0
  13. package/packages/ndpr-toolkit/dist/components/dsr/DSRDashboard.d.ts +58 -0
  14. package/packages/ndpr-toolkit/dist/components/dsr/DSRRequestForm.d.ts +74 -0
  15. package/packages/ndpr-toolkit/dist/components/dsr/DSRTracker.d.ts +56 -0
  16. package/packages/ndpr-toolkit/dist/components/policy/PolicyExporter.d.ts +65 -0
  17. package/packages/ndpr-toolkit/dist/components/policy/PolicyGenerator.d.ts +54 -0
  18. package/packages/ndpr-toolkit/dist/components/policy/PolicyPreview.d.ts +71 -0
  19. package/packages/ndpr-toolkit/dist/hooks/useBreach.d.ts +97 -0
  20. package/packages/ndpr-toolkit/dist/hooks/useConsent.d.ts +63 -0
  21. package/packages/ndpr-toolkit/dist/hooks/useDPIA.d.ts +92 -0
  22. package/packages/ndpr-toolkit/dist/hooks/useDSR.d.ts +72 -0
  23. package/packages/ndpr-toolkit/dist/hooks/usePrivacyPolicy.d.ts +87 -0
  24. package/packages/ndpr-toolkit/dist/index.d.ts +31 -0
  25. package/packages/ndpr-toolkit/dist/index.esm.js +2 -0
  26. package/packages/ndpr-toolkit/dist/index.esm.js.map +1 -0
  27. package/packages/ndpr-toolkit/dist/index.js +2 -0
  28. package/packages/ndpr-toolkit/dist/index.js.map +1 -0
  29. package/packages/ndpr-toolkit/dist/setupTests.d.ts +2 -0
  30. package/packages/ndpr-toolkit/dist/types/breach.d.ts +239 -0
  31. package/packages/ndpr-toolkit/dist/types/consent.d.ts +95 -0
  32. package/packages/ndpr-toolkit/dist/types/dpia.d.ts +196 -0
  33. package/packages/ndpr-toolkit/dist/types/dsr.d.ts +162 -0
  34. package/packages/ndpr-toolkit/dist/types/privacy.d.ts +204 -0
  35. package/packages/ndpr-toolkit/dist/utils/breach.d.ts +14 -0
  36. package/packages/ndpr-toolkit/dist/utils/consent.d.ts +10 -0
  37. package/packages/ndpr-toolkit/dist/utils/dpia.d.ts +12 -0
  38. package/packages/ndpr-toolkit/dist/utils/dsr.d.ts +11 -0
  39. package/packages/ndpr-toolkit/dist/utils/privacy.d.ts +12 -0
  40. package/src/components/consent/ConsentBanner.tsx +82 -48
  41. package/src/components/data-subject-rights/DataSubjectRequestForm.tsx +240 -129
  42. package/src/components/dpia/DPIAQuestionnaire.tsx +162 -122
  43. package/src/components/privacy-policy/PolicyGenerator.tsx +5 -5
  44. package/src/components/privacy-policy/steps/CustomSectionsStep.tsx +103 -77
  45. package/src/components/privacy-policy/steps/PolicyPreviewStep.tsx +117 -63
  46. package/src/hooks/useConsent.ts +16 -10
  47. package/src/lib/consentService.ts +44 -37
  48. package/src/lib/dpiaQuestions.ts +139 -99
  49. package/src/lib/requestService.ts +21 -17
  50. package/src/types/index.ts +13 -8
  51. package/.claude/settings.local.json +0 -20
  52. package/.eslintrc.json +0 -10
  53. package/.github/workflows/ci.yml +0 -36
  54. package/.github/workflows/nextjs.yml +0 -104
  55. package/.husky/commit-msg +0 -4
  56. package/.husky/pre-commit +0 -4
  57. package/.lintstagedrc.js +0 -4
  58. package/.nvmrc +0 -1
  59. package/.versionrc +0 -17
  60. package/CLAUDE.md +0 -90
  61. package/commitlint.config.js +0 -36
  62. package/jest.config.js +0 -31
  63. package/jest.setup.js +0 -15
  64. package/packages/ndpr-toolkit/jest.config.js +0 -23
  65. package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentBanner.test.tsx +0 -119
  66. package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentManager.test.tsx +0 -122
  67. package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentStorage.test.tsx +0 -270
  68. package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRDashboard.test.tsx +0 -199
  69. package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRRequestForm.test.tsx +0 -224
  70. package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRTracker.test.tsx +0 -104
  71. package/packages/ndpr-toolkit/src/__tests__/hooks/useConsent.test.tsx +0 -161
  72. package/packages/ndpr-toolkit/src/__tests__/hooks/useDSR.test.tsx +0 -330
  73. package/packages/ndpr-toolkit/src/__tests__/utils/breach.test.ts +0 -149
  74. package/packages/ndpr-toolkit/src/__tests__/utils/consent.test.ts +0 -88
  75. package/packages/ndpr-toolkit/src/__tests__/utils/dpia.test.ts +0 -160
  76. package/packages/ndpr-toolkit/src/__tests__/utils/dsr.test.ts +0 -110
  77. package/packages/ndpr-toolkit/src/__tests__/utils/privacy.test.ts +0 -97
  78. package/src/__tests__/example.test.ts +0 -13
  79. package/src/__tests__/requestService.test.ts +0 -57
  80. package/src/app/docs/components/DocLayout.tsx +0 -267
  81. package/src/app/docs/components/breach-notification/page.tsx +0 -797
  82. package/src/app/docs/components/consent-management/page.tsx +0 -576
  83. package/src/app/docs/components/data-subject-rights/page.tsx +0 -511
  84. package/src/app/docs/components/dpia-questionnaire/layout.tsx +0 -15
  85. package/src/app/docs/components/dpia-questionnaire/metadata.ts +0 -31
  86. package/src/app/docs/components/dpia-questionnaire/page.tsx +0 -666
  87. package/src/app/docs/components/hooks/page.tsx +0 -305
  88. package/src/app/docs/components/page.tsx +0 -84
  89. package/src/app/docs/components/privacy-policy-generator/page.tsx +0 -634
  90. package/src/app/docs/guides/breach-notification-process/components/BestPractices.tsx +0 -123
  91. package/src/app/docs/guides/breach-notification-process/components/ImplementationSteps.tsx +0 -328
  92. package/src/app/docs/guides/breach-notification-process/components/Introduction.tsx +0 -28
  93. package/src/app/docs/guides/breach-notification-process/components/NotificationTimeline.tsx +0 -91
  94. package/src/app/docs/guides/breach-notification-process/components/Resources.tsx +0 -118
  95. package/src/app/docs/guides/breach-notification-process/page.tsx +0 -39
  96. package/src/app/docs/guides/conducting-dpia/page.tsx +0 -593
  97. package/src/app/docs/guides/data-subject-requests/page.tsx +0 -666
  98. package/src/app/docs/guides/managing-consent/page.tsx +0 -738
  99. package/src/app/docs/guides/ndpr-compliance-checklist/components/ComplianceChecklist.tsx +0 -296
  100. package/src/app/docs/guides/ndpr-compliance-checklist/components/ImplementationTools.tsx +0 -145
  101. package/src/app/docs/guides/ndpr-compliance-checklist/components/Introduction.tsx +0 -33
  102. package/src/app/docs/guides/ndpr-compliance-checklist/components/KeyRequirements.tsx +0 -99
  103. package/src/app/docs/guides/ndpr-compliance-checklist/components/Resources.tsx +0 -159
  104. package/src/app/docs/guides/ndpr-compliance-checklist/page.tsx +0 -38
  105. package/src/app/docs/guides/page.tsx +0 -67
  106. package/src/app/docs/layout.tsx +0 -15
  107. package/src/app/docs/metadata.ts +0 -31
  108. package/src/app/docs/page.tsx +0 -572
  109. package/src/components/docs/DocLayout.tsx +0 -289
  110. package/src/components/docs/index.ts +0 -2
@@ -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
- });
@@ -1,160 +0,0 @@
1
- import { assessDPIARisk } from '../../utils/dpia';
2
- import { DPIAResult, DPIARisk } from '../../types/dpia';
3
-
4
- describe('assessDPIARisk', () => {
5
- it('should correctly assess risk based on high risk data', () => {
6
- // Create a DPIA result with high risks
7
- const dpiaResult: DPIAResult = {
8
- id: '123',
9
- title: 'Test DPIA',
10
- processingDescription: 'Processing sensitive customer data',
11
- startedAt: Date.now(),
12
- assessor: {
13
- name: 'John Doe',
14
- role: 'DPO',
15
- email: 'john@example.com'
16
- },
17
- answers: {
18
- q1: 'yes',
19
- q2: 'large'
20
- },
21
- risks: [
22
- {
23
- id: 'risk_1',
24
- description: 'Processing involves sensitive personal data',
25
- likelihood: 5,
26
- impact: 5,
27
- score: 25,
28
- level: 'high',
29
- mitigated: false,
30
- relatedQuestionIds: ['q1']
31
- },
32
- {
33
- id: 'risk_2',
34
- description: 'Large volume of data being processed',
35
- likelihood: 5,
36
- impact: 5,
37
- score: 25,
38
- level: 'high',
39
- mitigated: false,
40
- relatedQuestionIds: ['q2']
41
- },
42
- {
43
- id: 'risk_3',
44
- description: 'Another high risk factor',
45
- likelihood: 5,
46
- impact: 5,
47
- score: 25,
48
- level: 'high',
49
- mitigated: false,
50
- relatedQuestionIds: ['q3']
51
- }
52
- ],
53
- overallRiskLevel: 'low', // Will be updated by the function
54
- canProceed: true, // Will be updated by the function
55
- conclusion: 'Initial conclusion',
56
- version: '1.0'
57
- };
58
-
59
- const result = assessDPIARisk(dpiaResult);
60
-
61
- expect(result.overallRiskLevel).toBe('high');
62
- expect(result.requiresConsultation).toBe(true);
63
- expect(result.canProceed).toBe(false);
64
- expect(result.recommendations.length).toBeGreaterThan(0);
65
- });
66
-
67
- it('should handle medium risk levels', () => {
68
- // Create a DPIA result with medium risks
69
- const dpiaResult: DPIAResult = {
70
- id: '456',
71
- title: 'Test DPIA',
72
- processingDescription: 'Processing customer data',
73
- startedAt: Date.now(),
74
- assessor: {
75
- name: 'Jane Smith',
76
- role: 'Privacy Officer',
77
- email: 'jane@example.com'
78
- },
79
- answers: {
80
- q1: 'no',
81
- q2: 'medium'
82
- },
83
- risks: [
84
- {
85
- id: 'risk_1',
86
- description: 'Medium volume of data being processed',
87
- likelihood: 3,
88
- impact: 3,
89
- score: 9,
90
- level: 'medium',
91
- mitigated: false,
92
- relatedQuestionIds: ['q2']
93
- },
94
- {
95
- id: 'risk_2',
96
- description: 'Another medium risk factor',
97
- likelihood: 3,
98
- impact: 3,
99
- score: 9,
100
- level: 'medium',
101
- mitigated: false,
102
- relatedQuestionIds: ['q3']
103
- }
104
- ],
105
- overallRiskLevel: 'low', // Will be updated by the function
106
- canProceed: true, // Will be updated by the function
107
- conclusion: 'Initial conclusion',
108
- version: '1.0'
109
- };
110
-
111
- const result = assessDPIARisk(dpiaResult);
112
-
113
- expect(result.overallRiskLevel).toBe('medium');
114
- expect(result.requiresConsultation).toBe(false);
115
- expect(result.canProceed).toBe(true);
116
- expect(result.recommendations.length).toBeGreaterThan(0);
117
- });
118
-
119
- it('should handle low risk levels', () => {
120
- // Create a DPIA result with no significant risks
121
- const dpiaResult: DPIAResult = {
122
- id: '789',
123
- title: 'Test DPIA',
124
- processingDescription: 'Processing minimal customer data',
125
- startedAt: Date.now(),
126
- assessor: {
127
- name: 'Alex Johnson',
128
- role: 'Compliance Manager',
129
- email: 'alex@example.com'
130
- },
131
- answers: {
132
- q1: 'Marketing purposes',
133
- q2: 'small'
134
- },
135
- risks: [
136
- {
137
- id: 'risk_1',
138
- description: 'Small volume of data being processed',
139
- likelihood: 1,
140
- impact: 1,
141
- score: 1,
142
- level: 'low',
143
- mitigated: true,
144
- relatedQuestionIds: ['q2']
145
- }
146
- ],
147
- overallRiskLevel: 'low', // Will be updated by the function
148
- canProceed: true, // Will be updated by the function
149
- conclusion: 'Initial conclusion',
150
- version: '1.0'
151
- };
152
-
153
- const result = assessDPIARisk(dpiaResult);
154
-
155
- expect(result.overallRiskLevel).toBe('low');
156
- expect(result.requiresConsultation).toBe(false);
157
- expect(result.canProceed).toBe(true);
158
- expect(result.recommendations.length).toBeGreaterThan(0);
159
- });
160
- });
@@ -1,110 +0,0 @@
1
- import { formatDSRRequest } from '../../utils/dsr';
2
- import { DSRRequest, DSRType, DSRStatus } from '../../types/dsr';
3
-
4
- describe('formatDSRRequest', () => {
5
- it('should format a DSR request correctly', () => {
6
- const request: DSRRequest = {
7
- id: '123',
8
- type: 'access',
9
- status: 'pending',
10
- createdAt: 1620000000000,
11
- updatedAt: 1620000000000,
12
- subject: {
13
- name: 'John Doe',
14
- email: 'john@example.com',
15
- phone: '1234567890'
16
- },
17
- description: 'I want to access my data'
18
- };
19
-
20
- const result = formatDSRRequest(request);
21
-
22
- expect(result.isValid).toBe(true);
23
- expect(result.formattedRequest.dataSubject.name).toBe('John Doe');
24
- expect(result.formattedRequest.requestType).toBe('access');
25
- expect(result.formattedRequest.status).toBe('pending');
26
- expect(result.formattedRequest.dataSubject.email).toBe('john@example.com');
27
- expect(result.formattedRequest.additionalInformation).toEqual({});
28
- expect(result.validationErrors.length).toBe(0);
29
- });
30
-
31
- it('should handle missing optional fields', () => {
32
- const request: DSRRequest = {
33
- id: '456',
34
- type: 'erasure',
35
- status: 'completed',
36
- createdAt: 1620000000000,
37
- updatedAt: 1620100000000,
38
- completedAt: 1620200000000,
39
- subject: {
40
- name: 'Jane Smith',
41
- email: 'jane@example.com'
42
- // phone is missing
43
- }
44
- // description is missing
45
- };
46
-
47
- const result = formatDSRRequest(request);
48
-
49
- expect(result.isValid).toBe(true);
50
- expect(result.formattedRequest.dataSubject.name).toBe('Jane Smith');
51
- expect(result.formattedRequest.requestType).toBe('erasure');
52
- expect(result.formattedRequest.status).toBe('completed');
53
- expect(result.formattedRequest.dataSubject.email).toBe('jane@example.com');
54
- expect(result.formattedRequest.dataSubject.phone).toBe('Not provided');
55
- expect(JSON.stringify(result.formattedRequest)).not.toContain('undefined');
56
- });
57
-
58
- it('should include completion date when available', () => {
59
- const request: DSRRequest = {
60
- id: '789',
61
- type: 'rectification',
62
- status: 'completed',
63
- createdAt: 1620000000000,
64
- updatedAt: 1620100000000,
65
- completedAt: 1620200000000,
66
- subject: {
67
- name: 'Bob Johnson',
68
- email: 'bob@example.com'
69
- }
70
- };
71
-
72
- const result = formatDSRRequest(request);
73
-
74
- expect(result.isValid).toBe(true);
75
- // Check that the completedAt date is properly formatted in ISO format
76
- expect(result.formattedRequest.lastUpdated).toBe(new Date(1620100000000).toISOString());
77
- expect(result.formattedRequest.dataSubject.name).toBe('Bob Johnson');
78
- expect(result.formattedRequest.requestType).toBe('rectification');
79
- expect(result.formattedRequest.status).toBe('completed');
80
- });
81
-
82
- it('should handle additional info when present', () => {
83
- const request: DSRRequest = {
84
- id: '101',
85
- type: 'portability',
86
- status: 'inProgress',
87
- createdAt: 1620000000000,
88
- updatedAt: 1620100000000,
89
- subject: {
90
- name: 'Alice Brown',
91
- email: 'alice@example.com'
92
- },
93
- additionalInfo: {
94
- format: 'CSV',
95
- timeRange: 'Last 12 months'
96
- }
97
- };
98
-
99
- const result = formatDSRRequest(request);
100
-
101
- expect(result.isValid).toBe(true);
102
- expect(result.formattedRequest.dataSubject.name).toBe('Alice Brown');
103
- expect(result.formattedRequest.requestType).toBe('portability');
104
- expect(result.formattedRequest.status).toBe('inProgress');
105
- expect(result.formattedRequest.additionalInformation).toEqual({
106
- format: 'CSV',
107
- timeRange: 'Last 12 months'
108
- });
109
- });
110
- });
@@ -1,97 +0,0 @@
1
- import { generatePolicyText } from '../../utils/privacy';
2
- import { PolicySection } from '../../types/privacy';
3
-
4
- describe('generatePolicyText', () => {
5
- it('should replace variables in templates', () => {
6
- const sections: PolicySection[] = [
7
- {
8
- id: 'introduction',
9
- title: 'Introduction',
10
- template: 'This Privacy Policy explains how {{organizationName}} collects and uses your data.',
11
- required: true,
12
- included: true
13
- },
14
- {
15
- id: 'contact',
16
- title: 'Contact Information',
17
- template: 'For questions about this policy, please contact us at {{contactEmail}}.',
18
- required: true,
19
- included: true
20
- }
21
- ];
22
-
23
- const variables = {
24
- organizationName: 'Acme Corporation',
25
- contactEmail: 'privacy@acme.com'
26
- };
27
-
28
- const result = generatePolicyText(sections, variables) as {
29
- fullText: string;
30
- sectionTexts: Record<string, string>;
31
- missingVariables: string[];
32
- };
33
-
34
- expect(result.fullText).toContain('This Privacy Policy explains how Acme Corporation collects and uses your data.');
35
- expect(result.fullText).toContain('For questions about this policy, please contact us at privacy@acme.com.');
36
- // Check the number of sections by counting keys in sectionTexts
37
- expect(Object.keys(result.sectionTexts).length).toBe(2);
38
- // Check the content of the first section
39
- expect(Object.values(result.sectionTexts)[0]).toBe('This Privacy Policy explains how Acme Corporation collects and uses your data.');
40
- });
41
-
42
- it('should skip sections that are not included', () => {
43
- const sections: PolicySection[] = [
44
- {
45
- id: 'introduction',
46
- title: 'Introduction',
47
- template: 'This is the introduction.',
48
- required: true,
49
- included: true
50
- },
51
- {
52
- id: 'optional',
53
- title: 'Optional Section',
54
- template: 'This is optional.',
55
- required: false,
56
- included: false
57
- }
58
- ];
59
-
60
- const result = generatePolicyText(sections, {}) as {
61
- fullText: string;
62
- sectionTexts: Record<string, string>;
63
- missingVariables: string[];
64
- };
65
-
66
- expect(result.fullText).toContain('This is the introduction.');
67
- expect(result.fullText).not.toContain('This is optional.');
68
- expect(Object.keys(result.sectionTexts).length).toBe(1);
69
- });
70
-
71
- it('should handle missing variables gracefully', () => {
72
- const sections: PolicySection[] = [
73
- {
74
- id: 'test',
75
- title: 'Test',
76
- template: 'Hello {{name}}, welcome to {{company}}.',
77
- required: true,
78
- included: true
79
- }
80
- ];
81
-
82
- const variables = {
83
- name: 'John'
84
- // company is missing
85
- };
86
-
87
- const result = generatePolicyText(sections, variables) as {
88
- fullText: string;
89
- sectionTexts: Record<string, string>;
90
- missingVariables: string[];
91
- };
92
-
93
- expect(result.fullText).toContain('Hello John, welcome to .');
94
- // Verify that 'company' is in the missing variables list
95
- expect(result.missingVariables).toContain('company');
96
- });
97
- });
@@ -1,13 +0,0 @@
1
- /**
2
- * Example test file for NDPR-Toolkit
3
- *
4
- * This file demonstrates how to structure tests for the NDPR-Toolkit.
5
- * Add your actual tests in this directory following a similar pattern.
6
- */
7
-
8
- describe('NDPR-Toolkit', () => {
9
- test('example test setup', () => {
10
- // This is just a placeholder test to demonstrate the test structure
11
- expect(true).toBe(true);
12
- });
13
- });
@@ -1,57 +0,0 @@
1
- import requestService from '@/lib/requestService';
2
-
3
- describe('requestService', () => {
4
- beforeEach(() => {
5
- const localStorageMock = (() => {
6
- let store: Record<string, string> = {};
7
- return {
8
- getItem: (key: string) => (key in store ? store[key] : null),
9
- setItem: (key: string, value: string) => {
10
- store[key] = value;
11
- },
12
- removeItem: (key: string) => {
13
- delete store[key];
14
- },
15
- clear: () => {
16
- store = {};
17
- }
18
- };
19
- })();
20
-
21
- Object.defineProperty(window, 'localStorage', {
22
- value: localStorageMock,
23
- writable: true,
24
- });
25
- requestService.clear();
26
- });
27
-
28
- test('creates and retrieves a request', () => {
29
- const req = requestService.createRequest('access', 'John Doe', 'john@example.com', 'details', true);
30
- const stored = requestService.getRequest(req.id);
31
- expect(stored).not.toBeNull();
32
- expect(stored?.requestType).toBe('access');
33
- expect(stored?.status).toBe('pending');
34
- });
35
-
36
- test('updates request status', () => {
37
- const req = requestService.createRequest('erasure', 'Jane', 'jane@example.com', 'erase', true);
38
- const updated = requestService.updateStatus(req.id, 'completed');
39
- expect(updated?.status).toBe('completed');
40
- const stored = requestService.getRequest(req.id);
41
- expect(stored?.status).toBe('completed');
42
- });
43
-
44
- test('retrieves all requests', () => {
45
- requestService.createRequest('access', 'A', 'a@example.com', 'a', true);
46
- requestService.createRequest('erasure', 'B', 'b@example.com', 'b', true);
47
- const all = requestService.getAllRequests();
48
- expect(all.length).toBe(2);
49
- });
50
-
51
- test('clears storage', () => {
52
- requestService.createRequest('access', 'A', 'a@example.com', 'a', true);
53
- requestService.clear();
54
- const all = requestService.getAllRequests();
55
- expect(all.length).toBe(0);
56
- });
57
- });