test(customers): let the public shape guard see analytics_consent (#56)
The register route now returns analytics_consent, and customers.integration.test.ts asserts the exact key set the public customer shape may contain. That test failed in CI, which is the guard doing its job rather than a problem with it: its whole point is that the shape cannot quietly grow, and a field appearing without someone deciding it belongs there is what it exists to catch. This field does belong there, so the expected set gains it. Three cases added while here, all of them properties the compliance work depends on and none of them observable from a unit test. Analytics consent is off for a registration that does not mention it, which is what Quebec's Law 25 s.8.1 requires and needs the column default, the register route and the stored wording to agree. Opting in to marketing alone leaves analytics off, which is the bundling GDPR treats as invalid and the mistake this branch already made once. And an analytics-only opt-in works with marketing left off, so the granularity holds in both directions rather than only the convenient one. Found by CI rather than locally: the integration suite needs a database this machine has no Docker to run, which was called out as unverified when the change went up. Typechecked, linted and the 478 unit tests still pass, but the assertion itself is only proven by the next CI run. Refs #56 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
25bec50902
commit
e7196f440b
@@ -81,7 +81,7 @@ describe('POST /api/customers/register', () => {
|
||||
});
|
||||
|
||||
expect(Object.keys(res.body).sort()).toEqual([
|
||||
'created_at', 'email', 'email_verified', 'favorite_alerts',
|
||||
'analytics_consent', 'created_at', 'email', 'email_verified', 'favorite_alerts',
|
||||
'first_name', 'id', 'last_name', 'marketing_consent'
|
||||
]);
|
||||
});
|
||||
@@ -106,6 +106,44 @@ describe('POST /api/customers/register', () => {
|
||||
expect(res.body.marketing_consent).toBe(true);
|
||||
});
|
||||
|
||||
// Quebec's Law 25 s.8.1 requires profiling to be off until the person turns
|
||||
// it on, so this is a compliance property rather than a default worth
|
||||
// debating. Asserted end to end because the column default, the register
|
||||
// route and the stored wording all have to agree for it to hold.
|
||||
it('creates an account with analytics consent off by default', async () => {
|
||||
const res = await request(app).post('/api/customers/register').send({ firstName: 'Test', lastName: 'Customer',
|
||||
email: 'analytics-default@example.com',
|
||||
password: 'supersecret123'
|
||||
});
|
||||
expect(res.body.analytics_consent).toBe(false);
|
||||
});
|
||||
|
||||
// The two consents are separate purposes and must be separately refusable.
|
||||
// Taking the emails must not opt anybody into being tracked — that bundling
|
||||
// is what GDPR treats as invalid consent, and it is the mistake this branch
|
||||
// made once before it was caught.
|
||||
it('opting in to marketing alone does not opt in to analytics', async () => {
|
||||
const res = await request(app).post('/api/customers/register').send({ firstName: 'Test', lastName: 'Customer',
|
||||
email: 'marketing-only@example.com',
|
||||
password: 'supersecret123',
|
||||
marketingConsent: true
|
||||
});
|
||||
expect(res.body.marketing_consent).toBe(true);
|
||||
expect(res.body.analytics_consent).toBe(false);
|
||||
});
|
||||
|
||||
it('respects an explicit analytics opt-in, independently of marketing', async () => {
|
||||
const res = await request(app).post('/api/customers/register').send({ firstName: 'Test', lastName: 'Customer',
|
||||
email: 'analytics-only@example.com',
|
||||
password: 'supersecret123',
|
||||
analyticsConsent: true
|
||||
});
|
||||
expect(res.body.analytics_consent).toBe(true);
|
||||
// Refusing the emails while accepting the tracking has to be possible too,
|
||||
// or the consent is not granular in both directions.
|
||||
expect(res.body.marketing_consent).toBe(false);
|
||||
});
|
||||
|
||||
it('rejects a duplicate email', async () => {
|
||||
await request(app).post('/api/customers/register').send({ firstName: 'Test', lastName: 'Customer',
|
||||
email: 'dupe@example.com',
|
||||
|
||||
Reference in New Issue
Block a user