@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.
- package/next-env.d.ts +5 -0
- package/package.json +1 -1
- package/packages/ndpr-toolkit/dist/components/breach/BreachNotificationManager.d.ts +62 -0
- package/packages/ndpr-toolkit/dist/components/breach/BreachReportForm.d.ts +66 -0
- package/packages/ndpr-toolkit/dist/components/breach/BreachRiskAssessment.d.ts +50 -0
- package/packages/ndpr-toolkit/dist/components/breach/RegulatoryReportGenerator.d.ts +94 -0
- package/packages/ndpr-toolkit/dist/components/consent/ConsentBanner.d.ts +79 -0
- package/packages/ndpr-toolkit/dist/components/consent/ConsentManager.d.ts +73 -0
- package/packages/ndpr-toolkit/dist/components/consent/ConsentStorage.d.ts +41 -0
- package/packages/ndpr-toolkit/dist/components/dpia/DPIAQuestionnaire.d.ts +70 -0
- package/packages/ndpr-toolkit/dist/components/dpia/DPIAReport.d.ts +40 -0
- package/packages/ndpr-toolkit/dist/components/dpia/StepIndicator.d.ts +64 -0
- package/packages/ndpr-toolkit/dist/components/dsr/DSRDashboard.d.ts +58 -0
- package/packages/ndpr-toolkit/dist/components/dsr/DSRRequestForm.d.ts +74 -0
- package/packages/ndpr-toolkit/dist/components/dsr/DSRTracker.d.ts +56 -0
- package/packages/ndpr-toolkit/dist/components/policy/PolicyExporter.d.ts +65 -0
- package/packages/ndpr-toolkit/dist/components/policy/PolicyGenerator.d.ts +54 -0
- package/packages/ndpr-toolkit/dist/components/policy/PolicyPreview.d.ts +71 -0
- package/packages/ndpr-toolkit/dist/hooks/useBreach.d.ts +97 -0
- package/packages/ndpr-toolkit/dist/hooks/useConsent.d.ts +63 -0
- package/packages/ndpr-toolkit/dist/hooks/useDPIA.d.ts +92 -0
- package/packages/ndpr-toolkit/dist/hooks/useDSR.d.ts +72 -0
- package/packages/ndpr-toolkit/dist/hooks/usePrivacyPolicy.d.ts +87 -0
- package/packages/ndpr-toolkit/dist/index.d.ts +31 -0
- package/packages/ndpr-toolkit/dist/index.esm.js +2 -0
- package/packages/ndpr-toolkit/dist/index.esm.js.map +1 -0
- package/packages/ndpr-toolkit/dist/index.js +2 -0
- package/packages/ndpr-toolkit/dist/index.js.map +1 -0
- package/packages/ndpr-toolkit/dist/setupTests.d.ts +2 -0
- package/packages/ndpr-toolkit/dist/types/breach.d.ts +239 -0
- package/packages/ndpr-toolkit/dist/types/consent.d.ts +95 -0
- package/packages/ndpr-toolkit/dist/types/dpia.d.ts +196 -0
- package/packages/ndpr-toolkit/dist/types/dsr.d.ts +162 -0
- package/packages/ndpr-toolkit/dist/types/privacy.d.ts +204 -0
- package/packages/ndpr-toolkit/dist/utils/breach.d.ts +14 -0
- package/packages/ndpr-toolkit/dist/utils/consent.d.ts +10 -0
- package/packages/ndpr-toolkit/dist/utils/dpia.d.ts +12 -0
- package/packages/ndpr-toolkit/dist/utils/dsr.d.ts +11 -0
- package/packages/ndpr-toolkit/dist/utils/privacy.d.ts +12 -0
- package/src/components/consent/ConsentBanner.tsx +82 -48
- package/src/components/data-subject-rights/DataSubjectRequestForm.tsx +240 -129
- package/src/components/dpia/DPIAQuestionnaire.tsx +162 -122
- package/src/components/privacy-policy/PolicyGenerator.tsx +5 -5
- package/src/components/privacy-policy/steps/CustomSectionsStep.tsx +103 -77
- package/src/components/privacy-policy/steps/PolicyPreviewStep.tsx +117 -63
- package/src/hooks/useConsent.ts +16 -10
- package/src/lib/consentService.ts +44 -37
- package/src/lib/dpiaQuestions.ts +139 -99
- package/src/lib/requestService.ts +21 -17
- package/src/types/index.ts +13 -8
- package/.claude/settings.local.json +0 -20
- package/.eslintrc.json +0 -10
- package/.github/workflows/ci.yml +0 -36
- package/.github/workflows/nextjs.yml +0 -104
- package/.husky/commit-msg +0 -4
- package/.husky/pre-commit +0 -4
- package/.lintstagedrc.js +0 -4
- package/.nvmrc +0 -1
- package/.versionrc +0 -17
- package/CLAUDE.md +0 -90
- package/commitlint.config.js +0 -36
- package/jest.config.js +0 -31
- package/jest.setup.js +0 -15
- package/packages/ndpr-toolkit/jest.config.js +0 -23
- package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentBanner.test.tsx +0 -119
- package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentManager.test.tsx +0 -122
- package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentStorage.test.tsx +0 -270
- package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRDashboard.test.tsx +0 -199
- package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRRequestForm.test.tsx +0 -224
- package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRTracker.test.tsx +0 -104
- package/packages/ndpr-toolkit/src/__tests__/hooks/useConsent.test.tsx +0 -161
- package/packages/ndpr-toolkit/src/__tests__/hooks/useDSR.test.tsx +0 -330
- package/packages/ndpr-toolkit/src/__tests__/utils/breach.test.ts +0 -149
- package/packages/ndpr-toolkit/src/__tests__/utils/consent.test.ts +0 -88
- package/packages/ndpr-toolkit/src/__tests__/utils/dpia.test.ts +0 -160
- package/packages/ndpr-toolkit/src/__tests__/utils/dsr.test.ts +0 -110
- package/packages/ndpr-toolkit/src/__tests__/utils/privacy.test.ts +0 -97
- package/src/__tests__/example.test.ts +0 -13
- package/src/__tests__/requestService.test.ts +0 -57
- package/src/app/docs/components/DocLayout.tsx +0 -267
- package/src/app/docs/components/breach-notification/page.tsx +0 -797
- package/src/app/docs/components/consent-management/page.tsx +0 -576
- package/src/app/docs/components/data-subject-rights/page.tsx +0 -511
- package/src/app/docs/components/dpia-questionnaire/layout.tsx +0 -15
- package/src/app/docs/components/dpia-questionnaire/metadata.ts +0 -31
- package/src/app/docs/components/dpia-questionnaire/page.tsx +0 -666
- package/src/app/docs/components/hooks/page.tsx +0 -305
- package/src/app/docs/components/page.tsx +0 -84
- package/src/app/docs/components/privacy-policy-generator/page.tsx +0 -634
- package/src/app/docs/guides/breach-notification-process/components/BestPractices.tsx +0 -123
- package/src/app/docs/guides/breach-notification-process/components/ImplementationSteps.tsx +0 -328
- package/src/app/docs/guides/breach-notification-process/components/Introduction.tsx +0 -28
- package/src/app/docs/guides/breach-notification-process/components/NotificationTimeline.tsx +0 -91
- package/src/app/docs/guides/breach-notification-process/components/Resources.tsx +0 -118
- package/src/app/docs/guides/breach-notification-process/page.tsx +0 -39
- package/src/app/docs/guides/conducting-dpia/page.tsx +0 -593
- package/src/app/docs/guides/data-subject-requests/page.tsx +0 -666
- package/src/app/docs/guides/managing-consent/page.tsx +0 -738
- package/src/app/docs/guides/ndpr-compliance-checklist/components/ComplianceChecklist.tsx +0 -296
- package/src/app/docs/guides/ndpr-compliance-checklist/components/ImplementationTools.tsx +0 -145
- package/src/app/docs/guides/ndpr-compliance-checklist/components/Introduction.tsx +0 -33
- package/src/app/docs/guides/ndpr-compliance-checklist/components/KeyRequirements.tsx +0 -99
- package/src/app/docs/guides/ndpr-compliance-checklist/components/Resources.tsx +0 -159
- package/src/app/docs/guides/ndpr-compliance-checklist/page.tsx +0 -38
- package/src/app/docs/guides/page.tsx +0 -67
- package/src/app/docs/layout.tsx +0 -15
- package/src/app/docs/metadata.ts +0 -31
- package/src/app/docs/page.tsx +0 -572
- package/src/components/docs/DocLayout.tsx +0 -289
- package/src/components/docs/index.ts +0 -2
package/.eslintrc.json
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "next/core-web-vitals",
|
|
3
|
-
"rules": {
|
|
4
|
-
"@typescript-eslint/no-unused-vars": "off",
|
|
5
|
-
"@typescript-eslint/no-empty-object-type": "off",
|
|
6
|
-
"react/no-unescaped-entities": "off",
|
|
7
|
-
"@typescript-eslint/no-explicit-any": "off"
|
|
8
|
-
},
|
|
9
|
-
"ignorePatterns": ["node_modules/**/*"]
|
|
10
|
-
}
|
package/.github/workflows/ci.yml
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
name: Continuous Integration
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [ main, develop ]
|
|
6
|
-
pull_request:
|
|
7
|
-
branches: [ main, develop ]
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
lint-and-test:
|
|
11
|
-
runs-on: ubuntu-latest
|
|
12
|
-
|
|
13
|
-
strategy:
|
|
14
|
-
matrix:
|
|
15
|
-
node-version: [20.x]
|
|
16
|
-
|
|
17
|
-
steps:
|
|
18
|
-
- uses: actions/checkout@v4
|
|
19
|
-
|
|
20
|
-
- name: Use Node.js ${{ matrix.node-version }}
|
|
21
|
-
uses: actions/setup-node@v4
|
|
22
|
-
with:
|
|
23
|
-
node-version: ${{ matrix.node-version }}
|
|
24
|
-
cache: 'npm'
|
|
25
|
-
|
|
26
|
-
- name: Install dependencies
|
|
27
|
-
run: npm ci
|
|
28
|
-
|
|
29
|
-
- name: Lint
|
|
30
|
-
run: npm run lint
|
|
31
|
-
|
|
32
|
-
- name: Type check
|
|
33
|
-
run: npx tsc --noEmit
|
|
34
|
-
|
|
35
|
-
- name: Run tests
|
|
36
|
-
run: npm test
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
# Sample workflow for building and deploying a Next.js site to GitHub Pages
|
|
2
|
-
#
|
|
3
|
-
# To get started with Next.js see: https://nextjs.org/docs/getting-started
|
|
4
|
-
#
|
|
5
|
-
name: Deploy Next.js site to Pages
|
|
6
|
-
|
|
7
|
-
on:
|
|
8
|
-
# Runs on pushes targeting the default branch
|
|
9
|
-
push:
|
|
10
|
-
branches: ["main"]
|
|
11
|
-
|
|
12
|
-
# Allows you to run this workflow manually from the Actions tab
|
|
13
|
-
workflow_dispatch:
|
|
14
|
-
|
|
15
|
-
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
|
|
16
|
-
permissions:
|
|
17
|
-
contents: read
|
|
18
|
-
pages: write
|
|
19
|
-
id-token: write
|
|
20
|
-
|
|
21
|
-
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
|
|
22
|
-
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
|
|
23
|
-
concurrency:
|
|
24
|
-
group: "pages"
|
|
25
|
-
cancel-in-progress: false
|
|
26
|
-
|
|
27
|
-
jobs:
|
|
28
|
-
# Build job
|
|
29
|
-
build:
|
|
30
|
-
runs-on: ubuntu-latest
|
|
31
|
-
steps:
|
|
32
|
-
- name: Checkout
|
|
33
|
-
uses: actions/checkout@v4
|
|
34
|
-
- name: Detect package manager
|
|
35
|
-
id: detect-package-manager
|
|
36
|
-
run: |
|
|
37
|
-
if [ -f "${{ github.workspace }}/pnpm-lock.yaml" ]; then
|
|
38
|
-
echo "manager=pnpm" >> $GITHUB_OUTPUT
|
|
39
|
-
echo "command=install" >> $GITHUB_OUTPUT
|
|
40
|
-
echo "runner=pnpm" >> $GITHUB_OUTPUT
|
|
41
|
-
exit 0
|
|
42
|
-
elif [ -f "${{ github.workspace }}/yarn.lock" ]; then
|
|
43
|
-
echo "manager=yarn" >> $GITHUB_OUTPUT
|
|
44
|
-
echo "command=install" >> $GITHUB_OUTPUT
|
|
45
|
-
echo "runner=yarn" >> $GITHUB_OUTPUT
|
|
46
|
-
exit 0
|
|
47
|
-
elif [ -f "${{ github.workspace }}/package.json" ]; then
|
|
48
|
-
echo "manager=npm" >> $GITHUB_OUTPUT
|
|
49
|
-
echo "command=ci" >> $GITHUB_OUTPUT
|
|
50
|
-
echo "runner=npx --no-install" >> $GITHUB_OUTPUT
|
|
51
|
-
exit 0
|
|
52
|
-
else
|
|
53
|
-
echo "Unable to determine package manager"
|
|
54
|
-
exit 1
|
|
55
|
-
fi
|
|
56
|
-
- name: Setup Node
|
|
57
|
-
uses: actions/setup-node@v4
|
|
58
|
-
with:
|
|
59
|
-
node-version: "20"
|
|
60
|
-
cache: ${{ steps.detect-package-manager.outputs.manager }}
|
|
61
|
-
- name: Setup pnpm
|
|
62
|
-
if: steps.detect-package-manager.outputs.manager == 'pnpm'
|
|
63
|
-
uses: pnpm/action-setup@v2
|
|
64
|
-
with:
|
|
65
|
-
version: 8
|
|
66
|
-
run_install: false
|
|
67
|
-
- name: Setup Pages
|
|
68
|
-
uses: actions/configure-pages@v5
|
|
69
|
-
with:
|
|
70
|
-
# Automatically inject basePath in your Next.js configuration file and disable
|
|
71
|
-
# server side image optimization (https://nextjs.org/docs/api-reference/next/image#unoptimized).
|
|
72
|
-
#
|
|
73
|
-
# You may remove this line if you want to manage the configuration yourself.
|
|
74
|
-
static_site_generator: next
|
|
75
|
-
- name: Restore cache
|
|
76
|
-
uses: actions/cache@v4
|
|
77
|
-
with:
|
|
78
|
-
path: |
|
|
79
|
-
.next/cache
|
|
80
|
-
# Generate a new cache whenever packages or source files change.
|
|
81
|
-
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }}
|
|
82
|
-
# If source files changed but packages didn't, rebuild from a prior cache.
|
|
83
|
-
restore-keys: |
|
|
84
|
-
${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}-
|
|
85
|
-
- name: Install dependencies
|
|
86
|
-
run: ${{ steps.detect-package-manager.outputs.manager }} ${{ steps.detect-package-manager.outputs.command }}
|
|
87
|
-
- name: Build with Next.js
|
|
88
|
-
run: ${{ steps.detect-package-manager.outputs.runner }} next build
|
|
89
|
-
- name: Upload artifact
|
|
90
|
-
uses: actions/upload-pages-artifact@v3
|
|
91
|
-
with:
|
|
92
|
-
path: ./out
|
|
93
|
-
|
|
94
|
-
# Deployment job
|
|
95
|
-
deploy:
|
|
96
|
-
environment:
|
|
97
|
-
name: github-pages
|
|
98
|
-
url: ${{ steps.deployment.outputs.page_url }}
|
|
99
|
-
runs-on: ubuntu-latest
|
|
100
|
-
needs: build
|
|
101
|
-
steps:
|
|
102
|
-
- name: Deploy to GitHub Pages
|
|
103
|
-
id: deployment
|
|
104
|
-
uses: actions/deploy-pages@v4
|
package/.husky/commit-msg
DELETED
package/.husky/pre-commit
DELETED
package/.lintstagedrc.js
DELETED
package/.nvmrc
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
20
|
package/.versionrc
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"types": [
|
|
3
|
-
{"type": "feat", "section": "Features"},
|
|
4
|
-
{"type": "fix", "section": "Bug Fixes"},
|
|
5
|
-
{"type": "chore", "hidden": true},
|
|
6
|
-
{"type": "docs", "section": "Documentation"},
|
|
7
|
-
{"type": "style", "hidden": true},
|
|
8
|
-
{"type": "refactor", "section": "Code Refactoring"},
|
|
9
|
-
{"type": "perf", "section": "Performance Improvements"},
|
|
10
|
-
{"type": "test", "hidden": true},
|
|
11
|
-
{"type": "build", "hidden": true},
|
|
12
|
-
{"type": "ci", "hidden": true}
|
|
13
|
-
],
|
|
14
|
-
"commitUrlFormat": "https://github.com/tantainnovative/ndpr-toolkit/commit/{{hash}}",
|
|
15
|
-
"compareUrlFormat": "https://github.com/tantainnovative/ndpr-toolkit/compare/{{previousTag}}...{{currentTag}}",
|
|
16
|
-
"releaseCommitMessageFormat": "chore(release): {{currentTag}}"
|
|
17
|
-
}
|
package/CLAUDE.md
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
# CLAUDE.md
|
|
2
|
-
|
|
3
|
-
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
-
|
|
5
|
-
## Project Overview
|
|
6
|
-
|
|
7
|
-
The Nigerian Data Protection Compliance Toolkit (NDPR-Toolkit) is a Next.js application that helps developers implement NDPR and DPA compliant features. It's deployed as a static site to GitHub Pages.
|
|
8
|
-
|
|
9
|
-
## Development Commands
|
|
10
|
-
|
|
11
|
-
### Package Manager
|
|
12
|
-
Always use `pnpm` for all package management operations.
|
|
13
|
-
|
|
14
|
-
### Core Commands
|
|
15
|
-
- **Development server**: `pnpm dev` (uses Turbopack)
|
|
16
|
-
- **Build**: `pnpm build`
|
|
17
|
-
- **Production server**: `pnpm start`
|
|
18
|
-
- **Static export**: `pnpm export` or `pnpm build:static`
|
|
19
|
-
- **Deploy to GitHub Pages**: `pnpm deploy`
|
|
20
|
-
|
|
21
|
-
### Testing
|
|
22
|
-
- **Run tests**: `pnpm test`
|
|
23
|
-
- **Run specific test**: `pnpm test -- path/to/test.spec.ts`
|
|
24
|
-
- **Tests use**: Jest with React Testing Library and jest-environment-jsdom
|
|
25
|
-
|
|
26
|
-
### Code Quality
|
|
27
|
-
- **Lint**: `pnpm lint`
|
|
28
|
-
- **Git hooks**: Pre-commit runs lint-staged, commit-msg runs commitlint
|
|
29
|
-
- **Commit format**: Use conventional commits (feat, fix, docs, style, refactor, test, chore)
|
|
30
|
-
|
|
31
|
-
### Release Management
|
|
32
|
-
- **Standard release**: `pnpm release`
|
|
33
|
-
- **Version bumps**: `pnpm release:patch`, `pnpm release:minor`, `pnpm release:major`
|
|
34
|
-
|
|
35
|
-
## Architecture
|
|
36
|
-
|
|
37
|
-
### Tech Stack
|
|
38
|
-
- **Next.js 15.3.1** with App Router
|
|
39
|
-
- **React 19** with TypeScript
|
|
40
|
-
- **Tailwind CSS v4** with custom theme configuration
|
|
41
|
-
- **Radix UI** for accessible components
|
|
42
|
-
- **Nextra** for documentation pages
|
|
43
|
-
|
|
44
|
-
### Project Structure
|
|
45
|
-
```
|
|
46
|
-
src/
|
|
47
|
-
├── app/ # Next.js pages (App Router)
|
|
48
|
-
│ ├── docs/ # Documentation pages
|
|
49
|
-
│ ├── ndpr-demos/ # Interactive NDPR compliance demos
|
|
50
|
-
│ └── page.tsx # Homepage
|
|
51
|
-
├── components/ # Feature-based component organization
|
|
52
|
-
│ ├── breach-notification/
|
|
53
|
-
│ ├── consent/
|
|
54
|
-
│ ├── data-subject-rights/
|
|
55
|
-
│ ├── dpia/
|
|
56
|
-
│ ├── privacy-policy/
|
|
57
|
-
│ └── ui/ # Base UI components
|
|
58
|
-
├── hooks/ # Custom React hooks
|
|
59
|
-
├── lib/ # Services and utilities
|
|
60
|
-
│ ├── consentService.ts
|
|
61
|
-
│ ├── requestService.ts # LocalStorage-based state management
|
|
62
|
-
│ └── utils.ts
|
|
63
|
-
└── types/ # TypeScript type definitions
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
### Key Patterns
|
|
67
|
-
|
|
68
|
-
1. **State Management**: Demo data persists in localStorage via service layer (e.g., `requestService.ts`)
|
|
69
|
-
2. **Component Architecture**: Feature-based organization with modular, reusable components
|
|
70
|
-
3. **Static Site**: Configured for GitHub Pages with basePath and assetPrefix in `next.config.ts`
|
|
71
|
-
4. **Type Safety**: Comprehensive TypeScript types in `types/` directory
|
|
72
|
-
5. **Styling**: Tailwind CSS with CSS variables for theming
|
|
73
|
-
|
|
74
|
-
### NDPR Compliance Features
|
|
75
|
-
|
|
76
|
-
When working on NDPR features, understand these core modules:
|
|
77
|
-
|
|
78
|
-
1. **Consent Management** (`components/consent/`): Multi-purpose consent with granular controls
|
|
79
|
-
2. **Data Subject Rights** (`components/data-subject-rights/`): Request portal for access, deletion, etc.
|
|
80
|
-
3. **Privacy Policy Generator** (`components/privacy-policy/`): Step-by-step wizard
|
|
81
|
-
4. **DPIA Tool** (`components/dpia/`): Data Protection Impact Assessment questionnaire
|
|
82
|
-
5. **Breach Notification** (`components/breach-notification/`): Incident reporting system
|
|
83
|
-
|
|
84
|
-
### Important Notes
|
|
85
|
-
|
|
86
|
-
- All data in demos uses localStorage - no backend required
|
|
87
|
-
- Components are designed for NDPR/DPA compliance out of the box
|
|
88
|
-
- The project auto-deploys to GitHub Pages on main branch pushes
|
|
89
|
-
- TypeScript strict mode is enabled - maintain type safety
|
|
90
|
-
- Follow existing component patterns when adding new features
|
package/commitlint.config.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
extends: ['@commitlint/config-conventional'],
|
|
3
|
-
rules: {
|
|
4
|
-
'body-leading-blank': [1, 'always'],
|
|
5
|
-
'body-max-line-length': [2, 'always', 100],
|
|
6
|
-
'footer-leading-blank': [1, 'always'],
|
|
7
|
-
'footer-max-line-length': [2, 'always', 100],
|
|
8
|
-
'header-max-length': [2, 'always', 100],
|
|
9
|
-
'subject-case': [
|
|
10
|
-
2,
|
|
11
|
-
'never',
|
|
12
|
-
['sentence-case', 'start-case', 'pascal-case', 'upper-case'],
|
|
13
|
-
],
|
|
14
|
-
'subject-empty': [2, 'never'],
|
|
15
|
-
'subject-full-stop': [2, 'never', '.'],
|
|
16
|
-
'type-case': [2, 'always', 'lower-case'],
|
|
17
|
-
'type-empty': [2, 'never'],
|
|
18
|
-
'type-enum': [
|
|
19
|
-
2,
|
|
20
|
-
'always',
|
|
21
|
-
[
|
|
22
|
-
'build',
|
|
23
|
-
'chore',
|
|
24
|
-
'ci',
|
|
25
|
-
'docs',
|
|
26
|
-
'feat',
|
|
27
|
-
'fix',
|
|
28
|
-
'perf',
|
|
29
|
-
'refactor',
|
|
30
|
-
'revert',
|
|
31
|
-
'style',
|
|
32
|
-
'test',
|
|
33
|
-
],
|
|
34
|
-
],
|
|
35
|
-
},
|
|
36
|
-
};
|
package/jest.config.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
const nextJest = require('next/jest');
|
|
2
|
-
|
|
3
|
-
const createJestConfig = nextJest({
|
|
4
|
-
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
|
|
5
|
-
dir: './',
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
// Add any custom config to be passed to Jest
|
|
9
|
-
const customJestConfig = {
|
|
10
|
-
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
|
|
11
|
-
testEnvironment: 'jest-environment-jsdom',
|
|
12
|
-
moduleNameMapper: {
|
|
13
|
-
// Handle module aliases (if you have them in tsconfig.json)
|
|
14
|
-
'^@/(.*)$': '<rootDir>/src/$1',
|
|
15
|
-
},
|
|
16
|
-
testPathIgnorePatterns: [
|
|
17
|
-
'<rootDir>/node_modules/',
|
|
18
|
-
'<rootDir>/.next/',
|
|
19
|
-
'<rootDir>/out/'
|
|
20
|
-
],
|
|
21
|
-
collectCoverage: true,
|
|
22
|
-
collectCoverageFrom: [
|
|
23
|
-
'src/**/*.{js,jsx,ts,tsx}',
|
|
24
|
-
'!src/**/*.d.ts',
|
|
25
|
-
'!src/**/_*.{js,jsx,ts,tsx}',
|
|
26
|
-
'!src/**/index.{js,jsx,ts,tsx}',
|
|
27
|
-
],
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
|
|
31
|
-
module.exports = createJestConfig(customJestConfig);
|
package/jest.setup.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
// Learn more: https://github.com/testing-library/jest-dom
|
|
2
|
-
import '@testing-library/jest-dom';
|
|
3
|
-
|
|
4
|
-
// Mock localStorage for tests
|
|
5
|
-
if (typeof window !== 'undefined') {
|
|
6
|
-
Object.defineProperty(window, 'localStorage', {
|
|
7
|
-
value: {
|
|
8
|
-
getItem: jest.fn(),
|
|
9
|
-
setItem: jest.fn(),
|
|
10
|
-
removeItem: jest.fn(),
|
|
11
|
-
clear: jest.fn(),
|
|
12
|
-
},
|
|
13
|
-
writable: true
|
|
14
|
-
});
|
|
15
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
preset: 'ts-jest',
|
|
3
|
-
testEnvironment: 'jsdom',
|
|
4
|
-
moduleNameMapper: {
|
|
5
|
-
'\\.(css|less|scss|sass)$': 'identity-obj-proxy',
|
|
6
|
-
},
|
|
7
|
-
setupFilesAfterEnv: ['<rootDir>/src/setupTests.ts'],
|
|
8
|
-
testPathIgnorePatterns: ['/node_modules/', '/dist/'],
|
|
9
|
-
collectCoverageFrom: [
|
|
10
|
-
'src/**/*.{ts,tsx}',
|
|
11
|
-
'!src/**/*.d.ts',
|
|
12
|
-
'!src/index.ts',
|
|
13
|
-
'!src/setupTests.ts',
|
|
14
|
-
],
|
|
15
|
-
coverageThreshold: {
|
|
16
|
-
global: {
|
|
17
|
-
branches: 70,
|
|
18
|
-
functions: 70,
|
|
19
|
-
lines: 70,
|
|
20
|
-
statements: 70,
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
};
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { render, screen, fireEvent } from '@testing-library/react';
|
|
3
|
-
import { ConsentBanner } from '../../../components/consent/ConsentBanner';
|
|
4
|
-
import { ConsentOption } from '../../../types/consent';
|
|
5
|
-
|
|
6
|
-
describe('ConsentBanner', () => {
|
|
7
|
-
const mockOnSave = jest.fn();
|
|
8
|
-
|
|
9
|
-
const consentOptions: ConsentOption[] = [
|
|
10
|
-
{
|
|
11
|
-
id: 'necessary',
|
|
12
|
-
label: 'Necessary Cookies',
|
|
13
|
-
description: 'Essential cookies for the website to function.',
|
|
14
|
-
required: true
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
id: 'analytics',
|
|
18
|
-
label: 'Analytics Cookies',
|
|
19
|
-
description: 'Cookies that help us understand how you use our website.',
|
|
20
|
-
required: false
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
id: 'marketing',
|
|
24
|
-
label: 'Marketing Cookies',
|
|
25
|
-
description: 'Cookies used for marketing purposes.',
|
|
26
|
-
required: false
|
|
27
|
-
}
|
|
28
|
-
];
|
|
29
|
-
|
|
30
|
-
const renderComponent = (props = {}) => {
|
|
31
|
-
return render(
|
|
32
|
-
<ConsentBanner
|
|
33
|
-
options={consentOptions}
|
|
34
|
-
position="bottom"
|
|
35
|
-
onSave={mockOnSave}
|
|
36
|
-
show={true}
|
|
37
|
-
storageKey="test-consent"
|
|
38
|
-
{...props}
|
|
39
|
-
/>
|
|
40
|
-
);
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
beforeEach(() => {
|
|
44
|
-
mockOnSave.mockClear();
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('renders the consent banner correctly', () => {
|
|
48
|
-
renderComponent();
|
|
49
|
-
|
|
50
|
-
expect(screen.getByText(/We Value Your Privacy/i)).toBeInTheDocument();
|
|
51
|
-
expect(screen.getByRole('button', { name: /accept all/i })).toBeInTheDocument();
|
|
52
|
-
expect(screen.getByRole('button', { name: /reject all/i })).toBeInTheDocument();
|
|
53
|
-
expect(screen.getByRole('button', { name: /customize/i })).toBeInTheDocument();
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it('calls onSave when "Accept All" is clicked', () => {
|
|
57
|
-
renderComponent();
|
|
58
|
-
|
|
59
|
-
fireEvent.click(screen.getByRole('button', { name: /accept all/i }));
|
|
60
|
-
|
|
61
|
-
expect(mockOnSave).toHaveBeenCalled();
|
|
62
|
-
const saveCall = mockOnSave.mock.calls[0][0];
|
|
63
|
-
expect(saveCall.consents.necessary).toBe(true);
|
|
64
|
-
expect(saveCall.consents.analytics).toBe(true);
|
|
65
|
-
expect(saveCall.consents.marketing).toBe(true);
|
|
66
|
-
expect(saveCall.timestamp).toBeDefined();
|
|
67
|
-
expect(saveCall.version).toBe('1.0');
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it('shows preferences panel when "Customize" is clicked', () => {
|
|
71
|
-
renderComponent();
|
|
72
|
-
|
|
73
|
-
fireEvent.click(screen.getByRole('button', { name: /customize/i }));
|
|
74
|
-
|
|
75
|
-
expect(screen.getByText(/necessary cookies/i)).toBeInTheDocument();
|
|
76
|
-
expect(screen.getByText(/analytics cookies/i)).toBeInTheDocument();
|
|
77
|
-
expect(screen.getByText(/marketing cookies/i)).toBeInTheDocument();
|
|
78
|
-
expect(screen.getByRole('button', { name: /save preferences/i })).toBeInTheDocument();
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
it('disables required consent options', () => {
|
|
82
|
-
renderComponent();
|
|
83
|
-
|
|
84
|
-
fireEvent.click(screen.getByRole('button', { name: /customize/i }));
|
|
85
|
-
|
|
86
|
-
// The checkbox for necessary cookies should be disabled
|
|
87
|
-
const necessaryCheckbox = screen.getByLabelText(/necessary cookies/i);
|
|
88
|
-
expect(necessaryCheckbox).toBeDisabled();
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it('allows toggling non-required consent options', () => {
|
|
92
|
-
renderComponent();
|
|
93
|
-
|
|
94
|
-
fireEvent.click(screen.getByRole('button', { name: /customize/i }));
|
|
95
|
-
|
|
96
|
-
// The checkbox for analytics cookies should be enabled
|
|
97
|
-
const analyticsCheckbox = screen.getByLabelText(/analytics cookies/i);
|
|
98
|
-
|
|
99
|
-
// Toggle the checkbox
|
|
100
|
-
fireEvent.click(analyticsCheckbox);
|
|
101
|
-
|
|
102
|
-
// Save preferences
|
|
103
|
-
fireEvent.click(screen.getByRole('button', { name: /save preferences/i }));
|
|
104
|
-
|
|
105
|
-
expect(mockOnSave).toHaveBeenCalled();
|
|
106
|
-
const saveCall = mockOnSave.mock.calls[0][0];
|
|
107
|
-
expect(saveCall.consents.necessary).toBeDefined();
|
|
108
|
-
expect(saveCall.consents.analytics).toBeDefined();
|
|
109
|
-
expect(saveCall.method).toBe('customize');
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
it('renders with the correct position', () => {
|
|
113
|
-
renderComponent({ position: 'top' });
|
|
114
|
-
|
|
115
|
-
const banner = screen.getByRole('dialog');
|
|
116
|
-
expect(banner).toHaveClass('top-0');
|
|
117
|
-
expect(banner).not.toHaveClass('bottom-0');
|
|
118
|
-
});
|
|
119
|
-
});
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { render, screen, fireEvent } from '@testing-library/react';
|
|
3
|
-
import { ConsentManager } from '../../../components/consent/ConsentManager';
|
|
4
|
-
import { ConsentOption, ConsentSettings } from '../../../types/consent';
|
|
5
|
-
|
|
6
|
-
describe('ConsentManager', () => {
|
|
7
|
-
const mockOnSave = jest.fn();
|
|
8
|
-
|
|
9
|
-
const consentOptions: ConsentOption[] = [
|
|
10
|
-
{
|
|
11
|
-
id: 'necessary',
|
|
12
|
-
label: 'Necessary Cookies',
|
|
13
|
-
description: 'Essential cookies for the website to function.',
|
|
14
|
-
required: true
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
id: 'analytics',
|
|
18
|
-
label: 'Analytics Cookies',
|
|
19
|
-
description: 'Cookies that help us understand how you use our website.',
|
|
20
|
-
required: false
|
|
21
|
-
}
|
|
22
|
-
];
|
|
23
|
-
|
|
24
|
-
beforeEach(() => {
|
|
25
|
-
mockOnSave.mockClear();
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('renders the consent manager correctly', () => {
|
|
29
|
-
render(
|
|
30
|
-
<ConsentManager
|
|
31
|
-
options={consentOptions}
|
|
32
|
-
onSave={mockOnSave}
|
|
33
|
-
/>
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
// Check that the title and description are rendered
|
|
37
|
-
expect(screen.getByText(/Manage Your Privacy Settings/i)).toBeInTheDocument();
|
|
38
|
-
expect(screen.getByText(/Update your consent preferences/i)).toBeInTheDocument();
|
|
39
|
-
|
|
40
|
-
// Check that the consent options are rendered
|
|
41
|
-
expect(screen.getByText(/Necessary Cookies/i)).toBeInTheDocument();
|
|
42
|
-
expect(screen.getByText(/Analytics Cookies/i)).toBeInTheDocument();
|
|
43
|
-
|
|
44
|
-
// Check that the buttons are rendered
|
|
45
|
-
expect(screen.getByRole('button', { name: /Save Preferences/i })).toBeInTheDocument();
|
|
46
|
-
expect(screen.getByRole('button', { name: /Reset to Defaults/i })).toBeInTheDocument();
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('calls onSave when Save Preferences is clicked', () => {
|
|
50
|
-
render(
|
|
51
|
-
<ConsentManager
|
|
52
|
-
options={consentOptions}
|
|
53
|
-
onSave={mockOnSave}
|
|
54
|
-
/>
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
// Click the save button
|
|
58
|
-
fireEvent.click(screen.getByRole('button', { name: /Save Preferences/i }));
|
|
59
|
-
|
|
60
|
-
// Check that onSave was called with the correct settings
|
|
61
|
-
expect(mockOnSave).toHaveBeenCalled();
|
|
62
|
-
const saveCall = mockOnSave.mock.calls[0][0];
|
|
63
|
-
expect(saveCall.consents).toBeDefined();
|
|
64
|
-
expect(saveCall.timestamp).toBeDefined();
|
|
65
|
-
expect(saveCall.version).toBe('1.0');
|
|
66
|
-
expect(saveCall.method).toBe('manager');
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
it('handles empty options array', () => {
|
|
70
|
-
render(
|
|
71
|
-
<ConsentManager
|
|
72
|
-
options={[]}
|
|
73
|
-
onSave={mockOnSave}
|
|
74
|
-
/>
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
// Should still render the manager even with empty options
|
|
78
|
-
expect(screen.getByText(/Manage Your Privacy Settings/i)).toBeInTheDocument();
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
it('allows toggling non-required consent options', () => {
|
|
82
|
-
render(
|
|
83
|
-
<ConsentManager
|
|
84
|
-
options={consentOptions}
|
|
85
|
-
onSave={mockOnSave}
|
|
86
|
-
/>
|
|
87
|
-
);
|
|
88
|
-
|
|
89
|
-
// Find the analytics checkbox (non-required)
|
|
90
|
-
const analyticsCheckboxes = screen.getAllByRole('checkbox');
|
|
91
|
-
const analyticsCheckbox = analyticsCheckboxes.find(checkbox => !checkbox.hasAttribute('disabled'));
|
|
92
|
-
|
|
93
|
-
// Toggle the checkbox
|
|
94
|
-
if (analyticsCheckbox) {
|
|
95
|
-
fireEvent.click(analyticsCheckbox);
|
|
96
|
-
|
|
97
|
-
// Save preferences
|
|
98
|
-
fireEvent.click(screen.getByRole('button', { name: /Save Preferences/i }));
|
|
99
|
-
|
|
100
|
-
// Check that onSave was called
|
|
101
|
-
expect(mockOnSave).toHaveBeenCalled();
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it('disables required consent options', () => {
|
|
106
|
-
render(
|
|
107
|
-
<ConsentManager
|
|
108
|
-
options={consentOptions}
|
|
109
|
-
onSave={mockOnSave}
|
|
110
|
-
/>
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
// Find all checkboxes
|
|
114
|
-
const checkboxes = screen.getAllByRole('checkbox');
|
|
115
|
-
|
|
116
|
-
// Find the necessary checkbox (required)
|
|
117
|
-
const necessaryCheckbox = checkboxes.find(checkbox => checkbox.hasAttribute('disabled'));
|
|
118
|
-
|
|
119
|
-
// Check thatit's disabled
|
|
120
|
-
expect(necessaryCheckbox).toBeDisabled();
|
|
121
|
-
});
|
|
122
|
-
});
|