Skip to content

Commit

Permalink
chore: merge master
Browse files Browse the repository at this point in the history
  • Loading branch information
oscb committed Dec 5, 2023
2 parents 18cd387 + 1ab0660 commit 785f6d0
Show file tree
Hide file tree
Showing 13 changed files with 1,173 additions and 28 deletions.
2 changes: 0 additions & 2 deletions packages/core/src/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* eslint-disable @typescript-eslint/no-unused-vars */

import type { SegmentClient } from './analytics';
import { Timeline } from './timeline';
import {
Expand Down
60 changes: 36 additions & 24 deletions packages/core/src/plugins/ConsentPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export class ConsentPlugin extends Plugin {
}

async execute(event: SegmentEvent): Promise<SegmentEvent> {
if ((event as TrackEventType).event === CONSENT_PREF_UPDATE_EVENT) {
if (this.isConsentUpdateEvent(event)) {
return event;
}

Expand All @@ -77,18 +77,36 @@ export class ConsentPlugin extends Plugin {
}

private injectConsentFilterIfApplicable = (plugin: Plugin) => {
if (
this.isDestinationPlugin(plugin) &&
plugin.key !== SEGMENT_DESTINATION_KEY
) {
const settings = this.analytics?.settings.get()?.[plugin.key];

if (this.isDestinationPlugin(plugin)) {
plugin.add(
new ConsentFilterPlugin(
this.containsConsentSettings(settings)
? settings.consentSettings.categories
: []
)
new ConsentFilterPlugin((event) => {
const settings = this.analytics?.settings.get() || {};
const preferences = event.context?.consent?.categoryPreferences || {};

if (plugin.key === SEGMENT_DESTINATION_KEY) {
return (
this.isConsentUpdateEvent(event) ||
!(
Object.values(preferences).every((consented) => !consented) &&
Object.entries(settings)
.filter(([k]) => k !== SEGMENT_DESTINATION_KEY)
.every(([_, v]) => this.containsConsentSettings(v))
)
);
}

const integrationSettings = settings?.[plugin.key];

if (this.containsConsentSettings(integrationSettings)) {
const categories = integrationSettings.consentSettings.categories;
return (
!this.isConsentUpdateEvent(event) &&
categories.every((category) => preferences?.[category])
);
}

return true;
})
);
}
};
Expand All @@ -105,6 +123,10 @@ export class ConsentPlugin extends Plugin {
?.categories === 'object'
);
};

private isConsentUpdateEvent(event: SegmentEvent): boolean {
return (event as TrackEventType).event === CONSENT_PREF_UPDATE_EVENT;
}
}

/**
Expand All @@ -114,21 +136,11 @@ export class ConsentPlugin extends Plugin {
class ConsentFilterPlugin extends Plugin {
type = PluginType.before;

constructor(private categories: string[]) {
constructor(private shouldAllowEvent: (event: SegmentEvent) => boolean) {
super();
}

execute(event: SegmentEvent): SegmentEvent | undefined {
const preferences = event.context?.consent?.categoryPreferences;

// if consent plugin is active but the setup isn't properly configured - events are blocked by default
if (!preferences || this.categories.length === 0) {
return undefined;
}

// all categories this destination is tagged with must be present, and allowed in consent preferences
return this.categories.every((category) => preferences?.[category])
? event
: undefined;
return this.shouldAllowEvent(event) ? event : undefined;
}
}
Submodule analytics-swift-consent added at 8e2324
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { createTestClient } from '../../../__tests__/__helpers__/setupSegmentClient';
import { ConsentPlugin } from '../../ConsentPlugin';

import {
setupTestDestinations,
createConsentProvider,
createSegmentWatcher,
} from './utils';
import consentNotEnabledAtSegment from './mockSettings/ConsentNotEnabledAtSegment.json';

describe('Consent not enabled at Segment', () => {
const createClient = () =>
createTestClient(
{
settings: consentNotEnabledAtSegment.integrations,
},
{ autoAddSegmentDestination: true }
);

test('no to all', async () => {
const { client } = createClient();
const testDestinations = setupTestDestinations(client);
const mockConsentStatuses = {
C0001: false,
C0002: false,
C0003: false,
C0004: false,
C0005: false,
};

client.add({
plugin: new ConsentPlugin(
createConsentProvider(mockConsentStatuses),
Object.keys(mockConsentStatuses)
),
});

await client.init();

const segmentDestination = createSegmentWatcher(client);

await client.track('test');

expect(segmentDestination).toHaveBeenCalled();
expect(testDestinations.dest1.track).toHaveBeenCalled();
expect(testDestinations.dest2.track).toHaveBeenCalled();
expect(testDestinations.dest3.track).toHaveBeenCalled();
expect(testDestinations.dest4.track).toHaveBeenCalled();
expect(testDestinations.dest5.track).toHaveBeenCalled();
});

test('yes to some', async () => {
const { client } = createClient();
const testDestinations = setupTestDestinations(client);
const mockConsentStatuses = {
C0001: false,
C0002: true,
C0003: false,
C0004: true,
C0005: true,
};

client.add({
plugin: new ConsentPlugin(
createConsentProvider(mockConsentStatuses),
Object.keys(mockConsentStatuses)
),
});

await client.init();

const segmentDestination = createSegmentWatcher(client);

await client.track('test');

expect(segmentDestination).toHaveBeenCalled();
expect(testDestinations.dest1.track).toHaveBeenCalled();
expect(testDestinations.dest2.track).toHaveBeenCalled();
expect(testDestinations.dest3.track).toHaveBeenCalled();
expect(testDestinations.dest4.track).toHaveBeenCalled();
expect(testDestinations.dest5.track).toHaveBeenCalled();
});

test('yes to all', async () => {
const { client } = createClient();
const testDestinations = setupTestDestinations(client);
const mockConsentStatuses = {
C0001: true,
C0002: true,
C0003: true,
C0004: true,
C0005: true,
};

client.add({
plugin: new ConsentPlugin(
createConsentProvider(mockConsentStatuses),
Object.keys(mockConsentStatuses)
),
});

await client.init();

const segmentDestination = createSegmentWatcher(client);

await client.track('test');

expect(segmentDestination).toHaveBeenCalled();
expect(testDestinations.dest1.track).toHaveBeenCalled();
expect(testDestinations.dest2.track).toHaveBeenCalled();
expect(testDestinations.dest3.track).toHaveBeenCalled();
expect(testDestinations.dest4.track).toHaveBeenCalled();
expect(testDestinations.dest5.track).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import { createTestClient } from '../../../__tests__/__helpers__/setupSegmentClient';
import { ConsentPlugin } from '../../ConsentPlugin';

import {
setupTestDestinations,
createConsentProvider,
createSegmentWatcher,
} from './utils';
import destinationsMultipleCategories from './mockSettings/DestinationsMultipleCategories.json';

describe('Destinations multiple categories', () => {
const createClient = () =>
createTestClient(
{
settings: destinationsMultipleCategories.integrations,
},
{ autoAddSegmentDestination: true }
);

test('no to all', async () => {
const { client } = createClient();
const testDestinations = setupTestDestinations(client);
const mockConsentStatuses = {
C0001: false,
C0002: false,
C0003: false,
C0004: false,
C0005: false,
};

client.add({
plugin: new ConsentPlugin(
createConsentProvider(mockConsentStatuses),
Object.keys(mockConsentStatuses)
),
});

await client.init();

const segmentDestination = createSegmentWatcher(client);

await client.track('test');

expect(segmentDestination).not.toHaveBeenCalled();
expect(testDestinations.dest1.track).not.toHaveBeenCalled();
expect(testDestinations.dest2.track).not.toHaveBeenCalled();
});

test('yes to 1', async () => {
const { client } = createClient();
const testDestinations = setupTestDestinations(client);
const mockConsentStatuses = {
C0001: true,
C0002: false,
C0003: false,
C0004: false,
C0005: false,
};

client.add({
plugin: new ConsentPlugin(
createConsentProvider(mockConsentStatuses),
Object.keys(mockConsentStatuses)
),
});

await client.init();

const segmentDestination = createSegmentWatcher(client);

await client.track('test');

expect(segmentDestination).toHaveBeenCalled();
expect(testDestinations.dest1.track).not.toHaveBeenCalled();
expect(testDestinations.dest2.track).toHaveBeenCalled();
});

test('yes to 2', async () => {
const { client } = createClient();
const testDestinations = setupTestDestinations(client);
const mockConsentStatuses = {
C0001: false,
C0002: true,
C0003: false,
C0004: false,
C0005: false,
};

client.add({
plugin: new ConsentPlugin(
createConsentProvider(mockConsentStatuses),
Object.keys(mockConsentStatuses)
),
});

await client.init();

const segmentDestination = createSegmentWatcher(client);

await client.track('test');

expect(segmentDestination).toHaveBeenCalled();
expect(testDestinations.dest1.track).not.toHaveBeenCalled();
expect(testDestinations.dest2.track).not.toHaveBeenCalled();
});

test('yes to all', async () => {
const { client } = createClient();
const testDestinations = setupTestDestinations(client);
const mockConsentStatuses = {
C0001: true,
C0002: true,
C0003: true,
C0004: true,
C0005: true,
};

client.add({
plugin: new ConsentPlugin(
createConsentProvider(mockConsentStatuses),
Object.keys(mockConsentStatuses)
),
});

await client.init();

const segmentDestination = createSegmentWatcher(client);

await client.track('test');

expect(segmentDestination).toHaveBeenCalled();
expect(testDestinations.dest1.track).toHaveBeenCalled();
expect(testDestinations.dest2.track).toHaveBeenCalled();
});
});
Loading

0 comments on commit 785f6d0

Please sign in to comment.