Initial commit: breakpilot-compliance - Compliance SDK Platform
Services: Admin-Compliance, Backend-Compliance, AI-Compliance-SDK, Consent-SDK, Developer-Portal, PCA-Platform, DSMS Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
212
consent-sdk/src/core/ConsentStorage.test.ts
Normal file
212
consent-sdk/src/core/ConsentStorage.test.ts
Normal file
@@ -0,0 +1,212 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { ConsentStorage } from './ConsentStorage';
|
||||
import type { ConsentConfig, ConsentState } from '../types';
|
||||
|
||||
describe('ConsentStorage', () => {
|
||||
let storage: ConsentStorage;
|
||||
const mockConfig: ConsentConfig = {
|
||||
apiEndpoint: 'https://api.example.com',
|
||||
siteId: 'test-site',
|
||||
debug: false,
|
||||
consent: {
|
||||
rememberDays: 365,
|
||||
},
|
||||
};
|
||||
|
||||
const mockConsent: ConsentState = {
|
||||
categories: {
|
||||
essential: true,
|
||||
functional: true,
|
||||
analytics: false,
|
||||
marketing: false,
|
||||
social: false,
|
||||
},
|
||||
vendors: {},
|
||||
timestamp: '2024-01-15T10:00:00.000Z',
|
||||
version: '1.0.0',
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
storage = new ConsentStorage(mockConfig);
|
||||
});
|
||||
|
||||
describe('constructor', () => {
|
||||
it('should create storage with site-specific key', () => {
|
||||
expect(storage).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('get', () => {
|
||||
it('should return null when no consent stored', () => {
|
||||
const result = storage.get();
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('should return consent when valid data exists', () => {
|
||||
storage.set(mockConsent);
|
||||
const result = storage.get();
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(result?.categories.essential).toBe(true);
|
||||
expect(result?.categories.analytics).toBe(false);
|
||||
});
|
||||
|
||||
it('should return null and clear when version mismatch', () => {
|
||||
// Manually set invalid version in storage
|
||||
const storageKey = `bp_consent_${mockConfig.siteId}`;
|
||||
localStorage.setItem(
|
||||
storageKey,
|
||||
JSON.stringify({
|
||||
version: 'invalid',
|
||||
consent: mockConsent,
|
||||
signature: 'test',
|
||||
})
|
||||
);
|
||||
|
||||
const result = storage.get();
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('should return null and clear when signature invalid', () => {
|
||||
const storageKey = `bp_consent_${mockConfig.siteId}`;
|
||||
localStorage.setItem(
|
||||
storageKey,
|
||||
JSON.stringify({
|
||||
version: '1',
|
||||
consent: mockConsent,
|
||||
signature: 'invalid-signature',
|
||||
})
|
||||
);
|
||||
|
||||
const result = storage.get();
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('should return null when JSON is invalid', () => {
|
||||
const storageKey = `bp_consent_${mockConfig.siteId}`;
|
||||
localStorage.setItem(storageKey, 'invalid-json');
|
||||
|
||||
const result = storage.get();
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('set', () => {
|
||||
it('should store consent in localStorage', () => {
|
||||
storage.set(mockConsent);
|
||||
|
||||
const storageKey = `bp_consent_${mockConfig.siteId}`;
|
||||
const stored = localStorage.getItem(storageKey);
|
||||
|
||||
expect(stored).toBeDefined();
|
||||
expect(stored).toContain('"version":"1"');
|
||||
});
|
||||
|
||||
it('should set a cookie for SSR support', () => {
|
||||
storage.set(mockConsent);
|
||||
|
||||
expect(document.cookie).toContain(`bp_consent_${mockConfig.siteId}`);
|
||||
});
|
||||
|
||||
it('should include signature in stored data', () => {
|
||||
storage.set(mockConsent);
|
||||
|
||||
const storageKey = `bp_consent_${mockConfig.siteId}`;
|
||||
const stored = JSON.parse(localStorage.getItem(storageKey) || '{}');
|
||||
|
||||
expect(stored.signature).toBeDefined();
|
||||
expect(typeof stored.signature).toBe('string');
|
||||
});
|
||||
});
|
||||
|
||||
describe('clear', () => {
|
||||
it('should remove consent from localStorage', () => {
|
||||
storage.set(mockConsent);
|
||||
storage.clear();
|
||||
|
||||
const result = storage.get();
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('should clear the cookie', () => {
|
||||
storage.set(mockConsent);
|
||||
storage.clear();
|
||||
|
||||
// Cookie should be cleared (expired)
|
||||
expect(document.cookie).toContain('expires=');
|
||||
});
|
||||
});
|
||||
|
||||
describe('exists', () => {
|
||||
it('should return false when no consent exists', () => {
|
||||
expect(storage.exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true when consent exists', () => {
|
||||
storage.set(mockConsent);
|
||||
expect(storage.exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('signature verification', () => {
|
||||
it('should detect tampered consent data', () => {
|
||||
storage.set(mockConsent);
|
||||
|
||||
const storageKey = `bp_consent_${mockConfig.siteId}`;
|
||||
const stored = JSON.parse(localStorage.getItem(storageKey) || '{}');
|
||||
|
||||
// Tamper with the data
|
||||
stored.consent.categories.marketing = true;
|
||||
localStorage.setItem(storageKey, JSON.stringify(stored));
|
||||
|
||||
const result = storage.get();
|
||||
expect(result).toBeNull(); // Signature mismatch should clear
|
||||
});
|
||||
});
|
||||
|
||||
describe('debug mode', () => {
|
||||
it('should log when debug is enabled', () => {
|
||||
const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||
|
||||
const debugStorage = new ConsentStorage({
|
||||
...mockConfig,
|
||||
debug: true,
|
||||
});
|
||||
|
||||
debugStorage.set(mockConsent);
|
||||
|
||||
expect(consoleSpy).toHaveBeenCalled();
|
||||
consoleSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
describe('cookie settings', () => {
|
||||
it('should set Secure flag on HTTPS', () => {
|
||||
storage.set(mockConsent);
|
||||
expect(document.cookie).toContain('Secure');
|
||||
});
|
||||
|
||||
it('should set SameSite=Lax', () => {
|
||||
storage.set(mockConsent);
|
||||
expect(document.cookie).toContain('SameSite=Lax');
|
||||
});
|
||||
|
||||
it('should set expiration based on rememberDays', () => {
|
||||
storage.set(mockConsent);
|
||||
expect(document.cookie).toContain('expires=');
|
||||
});
|
||||
});
|
||||
|
||||
describe('different sites', () => {
|
||||
it('should isolate storage by siteId', () => {
|
||||
const storage1 = new ConsentStorage({ ...mockConfig, siteId: 'site-1' });
|
||||
const storage2 = new ConsentStorage({ ...mockConfig, siteId: 'site-2' });
|
||||
|
||||
storage1.set(mockConsent);
|
||||
|
||||
expect(storage1.exists()).toBe(true);
|
||||
expect(storage2.exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user