@adtrackify/at-service-common 4.0.7 → 4.0.9
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/dist/cjs/__tests__/identity-cache/helpers.spec.d.ts +1 -0
- package/dist/cjs/__tests__/identity-cache/helpers.spec.js +594 -0
- package/dist/cjs/__tests__/identity-cache/helpers.spec.js.map +1 -0
- package/dist/cjs/__tests__/identity-cache/identity-cache-dynamodb-db-service.spec.d.ts +1 -0
- package/dist/cjs/__tests__/identity-cache/identity-cache-dynamodb-db-service.spec.js +556 -0
- package/dist/cjs/__tests__/identity-cache/identity-cache-dynamodb-db-service.spec.js.map +1 -0
- package/dist/cjs/__tests__/identity-cache/identity-cache-dynamodb-service-v2-comparison.spec.js +23 -25
- package/dist/cjs/__tests__/identity-cache/identity-cache-dynamodb-service-v2-comparison.spec.js.map +1 -1
- package/dist/cjs/__tests__/identity-cache/identity-cache-dynamodb-service.spec.js +11 -12
- package/dist/cjs/__tests__/identity-cache/identity-cache-dynamodb-service.spec.js.map +1 -1
- package/dist/cjs/__tests__/identity-cache/identity-cache-tier-routing.spec.js +64 -21
- package/dist/cjs/__tests__/identity-cache/identity-cache-tier-routing.spec.js.map +1 -1
- package/dist/cjs/__tests__/identity-cache/identity-gateway-service.spec.js +1617 -14
- package/dist/cjs/__tests__/identity-cache/identity-gateway-service.spec.js.map +1 -1
- package/dist/cjs/__tests__/identity-cache/trait-merging-and-staleness.spec.js +711 -0
- package/dist/cjs/__tests__/identity-cache/trait-merging-and-staleness.spec.js.map +1 -1
- package/dist/cjs/helpers/identity-cache-helper.d.ts +9 -0
- package/dist/cjs/helpers/identity-cache-helper.js +54 -1
- package/dist/cjs/helpers/identity-cache-helper.js.map +1 -1
- package/dist/cjs/services/db/identity-cache-dynamodb-service/helpers.d.ts +17 -4
- package/dist/cjs/services/db/identity-cache-dynamodb-service/helpers.js +35 -33
- package/dist/cjs/services/db/identity-cache-dynamodb-service/helpers.js.map +1 -1
- package/dist/cjs/services/db/identity-cache-dynamodb-service/identity-cache-dynamodb-db-service.d.ts +4 -2
- package/dist/cjs/services/db/identity-cache-dynamodb-service/identity-cache-dynamodb-db-service.js +63 -8
- package/dist/cjs/services/db/identity-cache-dynamodb-service/identity-cache-dynamodb-db-service.js.map +1 -1
- package/dist/cjs/services/db/identity-cache-dynamodb-service/identity-gateway-service.d.ts +1 -0
- package/dist/cjs/services/db/identity-cache-dynamodb-service/identity-gateway-service.js +97 -53
- package/dist/cjs/services/db/identity-cache-dynamodb-service/identity-gateway-service.js.map +1 -1
- package/dist/cjs/services/db/identity-cache-dynamodb-service/index.d.ts +1 -0
- package/dist/cjs/services/db/identity-cache-dynamodb-service/index.js +1 -0
- package/dist/cjs/services/db/identity-cache-dynamodb-service/index.js.map +1 -1
- package/dist/cjs/services/db/identity-cache-dynamodb-service/types.d.ts +16 -0
- package/dist/cjs/services/db/identity-cache-dynamodb-service/types.js +9 -1
- package/dist/cjs/services/db/identity-cache-dynamodb-service/types.js.map +1 -1
- package/dist/esm/__tests__/identity-cache/helpers.spec.d.ts +1 -0
- package/dist/esm/__tests__/identity-cache/helpers.spec.js +592 -0
- package/dist/esm/__tests__/identity-cache/helpers.spec.js.map +1 -0
- package/dist/esm/__tests__/identity-cache/identity-cache-dynamodb-db-service.spec.d.ts +1 -0
- package/dist/esm/__tests__/identity-cache/identity-cache-dynamodb-db-service.spec.js +554 -0
- package/dist/esm/__tests__/identity-cache/identity-cache-dynamodb-db-service.spec.js.map +1 -0
- package/dist/esm/__tests__/identity-cache/identity-cache-dynamodb-service-v2-comparison.spec.js +23 -25
- package/dist/esm/__tests__/identity-cache/identity-cache-dynamodb-service-v2-comparison.spec.js.map +1 -1
- package/dist/esm/__tests__/identity-cache/identity-cache-dynamodb-service.spec.js +11 -12
- package/dist/esm/__tests__/identity-cache/identity-cache-dynamodb-service.spec.js.map +1 -1
- package/dist/esm/__tests__/identity-cache/identity-cache-tier-routing.spec.js +65 -22
- package/dist/esm/__tests__/identity-cache/identity-cache-tier-routing.spec.js.map +1 -1
- package/dist/esm/__tests__/identity-cache/identity-gateway-service.spec.js +1617 -14
- package/dist/esm/__tests__/identity-cache/identity-gateway-service.spec.js.map +1 -1
- package/dist/esm/__tests__/identity-cache/trait-merging-and-staleness.spec.js +712 -1
- package/dist/esm/__tests__/identity-cache/trait-merging-and-staleness.spec.js.map +1 -1
- package/dist/esm/helpers/identity-cache-helper.d.ts +9 -0
- package/dist/esm/helpers/identity-cache-helper.js +52 -1
- package/dist/esm/helpers/identity-cache-helper.js.map +1 -1
- package/dist/esm/services/db/identity-cache-dynamodb-service/helpers.d.ts +17 -4
- package/dist/esm/services/db/identity-cache-dynamodb-service/helpers.js +33 -31
- package/dist/esm/services/db/identity-cache-dynamodb-service/helpers.js.map +1 -1
- package/dist/esm/services/db/identity-cache-dynamodb-service/identity-cache-dynamodb-db-service.d.ts +4 -2
- package/dist/esm/services/db/identity-cache-dynamodb-service/identity-cache-dynamodb-db-service.js +57 -2
- package/dist/esm/services/db/identity-cache-dynamodb-service/identity-cache-dynamodb-db-service.js.map +1 -1
- package/dist/esm/services/db/identity-cache-dynamodb-service/identity-gateway-service.d.ts +1 -0
- package/dist/esm/services/db/identity-cache-dynamodb-service/identity-gateway-service.js +98 -54
- package/dist/esm/services/db/identity-cache-dynamodb-service/identity-gateway-service.js.map +1 -1
- package/dist/esm/services/db/identity-cache-dynamodb-service/index.d.ts +1 -0
- package/dist/esm/services/db/identity-cache-dynamodb-service/index.js +1 -0
- package/dist/esm/services/db/identity-cache-dynamodb-service/index.js.map +1 -1
- package/dist/esm/services/db/identity-cache-dynamodb-service/types.d.ts +16 -0
- package/dist/esm/services/db/identity-cache-dynamodb-service/types.js +8 -0
- package/dist/esm/services/db/identity-cache-dynamodb-service/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ADDRESS_INFO_SOURCE } from '@adtrackify/at-tracking-event-types';
|
|
2
2
|
import { mergeIdentityTraits } from '@adtrackify/at-shared-utils';
|
|
3
|
-
import { isIdentityCacheStale, isClickInfosStale, IDENTITY_CACHE_STALENESS_TIER, } from '../../helpers/identity-cache-helper';
|
|
3
|
+
import { isIdentityCacheStale, isClickInfosStale, IDENTITY_CACHE_STALENESS_TIER, extractStaleTraitNames, mergeAndComputeIdentityStaleness, } from '../../helpers/identity-cache-helper';
|
|
4
4
|
describe('Identity Trait Merging Tests', () => {
|
|
5
5
|
afterEach(() => {
|
|
6
6
|
jest.resetModules();
|
|
@@ -1056,4 +1056,715 @@ describe('Three-Tier Staleness Model Tests', () => {
|
|
|
1056
1056
|
});
|
|
1057
1057
|
});
|
|
1058
1058
|
});
|
|
1059
|
+
describe('extractStaleTraitNames function', () => {
|
|
1060
|
+
it('should return empty array when nothing is stale', () => {
|
|
1061
|
+
const cachedIdentity = {
|
|
1062
|
+
identityId: 'test-id',
|
|
1063
|
+
traits: { emails: ['test@email.com'] },
|
|
1064
|
+
};
|
|
1065
|
+
const incomingIdentity = {
|
|
1066
|
+
identityId: 'test-id',
|
|
1067
|
+
traits: { emails: ['test@email.com'] },
|
|
1068
|
+
};
|
|
1069
|
+
const tracker = isIdentityCacheStale(cachedIdentity, incomingIdentity);
|
|
1070
|
+
const staleTraits = extractStaleTraitNames(tracker);
|
|
1071
|
+
expect(staleTraits).toEqual([]);
|
|
1072
|
+
});
|
|
1073
|
+
it('should return identity-defining trait names when stale', () => {
|
|
1074
|
+
const cachedIdentity = {
|
|
1075
|
+
identityId: 'test-id',
|
|
1076
|
+
traits: { emails: ['old@email.com'] },
|
|
1077
|
+
};
|
|
1078
|
+
const incomingIdentity = {
|
|
1079
|
+
identityId: 'test-id',
|
|
1080
|
+
traits: { emails: ['old@email.com', 'new@email.com'] },
|
|
1081
|
+
};
|
|
1082
|
+
const tracker = isIdentityCacheStale(cachedIdentity, incomingIdentity);
|
|
1083
|
+
const staleTraits = extractStaleTraitNames(tracker);
|
|
1084
|
+
expect(staleTraits).toContain('emails');
|
|
1085
|
+
});
|
|
1086
|
+
it('should return multiple stale trait names', () => {
|
|
1087
|
+
const cachedIdentity = {
|
|
1088
|
+
identityId: 'test-id',
|
|
1089
|
+
traits: {
|
|
1090
|
+
emails: ['old@email.com'],
|
|
1091
|
+
phones: ['+1234567890'],
|
|
1092
|
+
},
|
|
1093
|
+
};
|
|
1094
|
+
const incomingIdentity = {
|
|
1095
|
+
identityId: 'test-id',
|
|
1096
|
+
traits: {
|
|
1097
|
+
emails: ['old@email.com', 'new@email.com'],
|
|
1098
|
+
phones: ['+1234567890', '+9876543210'],
|
|
1099
|
+
},
|
|
1100
|
+
};
|
|
1101
|
+
const tracker = isIdentityCacheStale(cachedIdentity, incomingIdentity);
|
|
1102
|
+
const staleTraits = extractStaleTraitNames(tracker);
|
|
1103
|
+
expect(staleTraits).toContain('emails');
|
|
1104
|
+
expect(staleTraits).toContain('phones');
|
|
1105
|
+
});
|
|
1106
|
+
it('should return volatile trait names when stale', () => {
|
|
1107
|
+
const cachedIdentity = {
|
|
1108
|
+
identityId: 'test-id',
|
|
1109
|
+
traits: {
|
|
1110
|
+
ipAddress: '192.168.1.1',
|
|
1111
|
+
userAgent: 'old-agent',
|
|
1112
|
+
},
|
|
1113
|
+
};
|
|
1114
|
+
const incomingIdentity = {
|
|
1115
|
+
identityId: 'test-id',
|
|
1116
|
+
traits: {
|
|
1117
|
+
ipAddress: '10.0.0.1',
|
|
1118
|
+
userAgent: 'new-agent',
|
|
1119
|
+
},
|
|
1120
|
+
};
|
|
1121
|
+
const tracker = isIdentityCacheStale(cachedIdentity, incomingIdentity);
|
|
1122
|
+
const staleTraits = extractStaleTraitNames(tracker);
|
|
1123
|
+
expect(staleTraits).toContain('ipAddress');
|
|
1124
|
+
expect(staleTraits).toContain('userAgent');
|
|
1125
|
+
});
|
|
1126
|
+
});
|
|
1127
|
+
describe('mergeAndComputeIdentityStaleness function', () => {
|
|
1128
|
+
describe('NONE tier - cache is fresh', () => {
|
|
1129
|
+
it('should return NONE tier when incoming is subset of cached', () => {
|
|
1130
|
+
const incomingIdentity = {
|
|
1131
|
+
identityId: 'test-id',
|
|
1132
|
+
traits: { emails: ['shared@email.com'] },
|
|
1133
|
+
};
|
|
1134
|
+
const cachedIdentity = {
|
|
1135
|
+
identityId: 'test-id',
|
|
1136
|
+
traits: {
|
|
1137
|
+
emails: ['shared@email.com', 'other@email.com'],
|
|
1138
|
+
phones: ['+1234567890'],
|
|
1139
|
+
},
|
|
1140
|
+
};
|
|
1141
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1142
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.NONE);
|
|
1143
|
+
expect(result.isCacheStale).toBe(false);
|
|
1144
|
+
expect(result.staleTraits).toEqual([]);
|
|
1145
|
+
expect(result.mergedIdentity.traits?.emails).toEqual(['shared@email.com', 'other@email.com']);
|
|
1146
|
+
expect(result.mergedIdentity.traits?.phones).toEqual(['+1234567890']);
|
|
1147
|
+
});
|
|
1148
|
+
it('should return NONE tier when identities are identical', () => {
|
|
1149
|
+
const incomingIdentity = {
|
|
1150
|
+
identityId: 'test-id',
|
|
1151
|
+
traits: {
|
|
1152
|
+
emails: ['test@email.com'],
|
|
1153
|
+
phones: ['+1234567890'],
|
|
1154
|
+
},
|
|
1155
|
+
};
|
|
1156
|
+
const cachedIdentity = {
|
|
1157
|
+
identityId: 'test-id',
|
|
1158
|
+
traits: {
|
|
1159
|
+
emails: ['test@email.com'],
|
|
1160
|
+
phones: ['+1234567890'],
|
|
1161
|
+
},
|
|
1162
|
+
};
|
|
1163
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1164
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.NONE);
|
|
1165
|
+
expect(result.isCacheStale).toBe(false);
|
|
1166
|
+
expect(result.staleTraits).toEqual([]);
|
|
1167
|
+
});
|
|
1168
|
+
it('should return NONE tier with identical click info', () => {
|
|
1169
|
+
const incomingIdentity = {
|
|
1170
|
+
identityId: 'test-id',
|
|
1171
|
+
traits: {
|
|
1172
|
+
emails: ['test@email.com'],
|
|
1173
|
+
click: { gclid: 'same_gclid', fbp: 'fb.1.123.456' },
|
|
1174
|
+
},
|
|
1175
|
+
};
|
|
1176
|
+
const cachedIdentity = {
|
|
1177
|
+
identityId: 'test-id',
|
|
1178
|
+
traits: {
|
|
1179
|
+
emails: ['test@email.com'],
|
|
1180
|
+
click: { gclid: 'same_gclid', fbp: 'fb.1.123.456' },
|
|
1181
|
+
},
|
|
1182
|
+
};
|
|
1183
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1184
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.NONE);
|
|
1185
|
+
expect(result.isCacheStale).toBe(false);
|
|
1186
|
+
});
|
|
1187
|
+
});
|
|
1188
|
+
describe('VOLATILE_ONLY tier - treat as cache hit', () => {
|
|
1189
|
+
it('should return VOLATILE_ONLY tier when only ipAddress is new', () => {
|
|
1190
|
+
const incomingIdentity = {
|
|
1191
|
+
identityId: 'test-id',
|
|
1192
|
+
traits: {
|
|
1193
|
+
emails: ['test@email.com'],
|
|
1194
|
+
ipAddress: '10.0.0.1',
|
|
1195
|
+
},
|
|
1196
|
+
};
|
|
1197
|
+
const cachedIdentity = {
|
|
1198
|
+
identityId: 'test-id',
|
|
1199
|
+
traits: {
|
|
1200
|
+
emails: ['test@email.com'],
|
|
1201
|
+
},
|
|
1202
|
+
};
|
|
1203
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1204
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.VOLATILE_ONLY);
|
|
1205
|
+
expect(result.isCacheStale).toBe(false);
|
|
1206
|
+
expect(result.staleTraits).toContain('ipAddress');
|
|
1207
|
+
});
|
|
1208
|
+
it('should return VOLATILE_ONLY tier when only userAgent is new', () => {
|
|
1209
|
+
const incomingIdentity = {
|
|
1210
|
+
identityId: 'test-id',
|
|
1211
|
+
traits: {
|
|
1212
|
+
emails: ['test@email.com'],
|
|
1213
|
+
userAgent: 'new-agent',
|
|
1214
|
+
},
|
|
1215
|
+
};
|
|
1216
|
+
const cachedIdentity = {
|
|
1217
|
+
identityId: 'test-id',
|
|
1218
|
+
traits: {
|
|
1219
|
+
emails: ['test@email.com'],
|
|
1220
|
+
},
|
|
1221
|
+
};
|
|
1222
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1223
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.VOLATILE_ONLY);
|
|
1224
|
+
expect(result.isCacheStale).toBe(false);
|
|
1225
|
+
expect(result.staleTraits).toContain('userAgent');
|
|
1226
|
+
});
|
|
1227
|
+
it('should return VOLATILE_ONLY tier when only IP-sourced address is new', () => {
|
|
1228
|
+
const incomingIdentity = {
|
|
1229
|
+
identityId: 'test-id',
|
|
1230
|
+
traits: {
|
|
1231
|
+
emails: ['test@email.com'],
|
|
1232
|
+
addresses: [{ city: 'NewIPCity', s: ADDRESS_INFO_SOURCE.IP_ADDRESS }],
|
|
1233
|
+
},
|
|
1234
|
+
};
|
|
1235
|
+
const cachedIdentity = {
|
|
1236
|
+
identityId: 'test-id',
|
|
1237
|
+
traits: {
|
|
1238
|
+
emails: ['test@email.com'],
|
|
1239
|
+
addresses: [],
|
|
1240
|
+
},
|
|
1241
|
+
};
|
|
1242
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1243
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.VOLATILE_ONLY);
|
|
1244
|
+
expect(result.isCacheStale).toBe(false);
|
|
1245
|
+
});
|
|
1246
|
+
});
|
|
1247
|
+
describe('ADDRESS_UPDATE tier - cache write only, skip Neptune', () => {
|
|
1248
|
+
it('should return ADDRESS_UPDATE tier when non-IP address is new', () => {
|
|
1249
|
+
const incomingIdentity = {
|
|
1250
|
+
identityId: 'test-id',
|
|
1251
|
+
traits: {
|
|
1252
|
+
emails: ['test@email.com'],
|
|
1253
|
+
addresses: [{ city: 'Boston', s: ADDRESS_INFO_SOURCE.INPUT }],
|
|
1254
|
+
},
|
|
1255
|
+
};
|
|
1256
|
+
const cachedIdentity = {
|
|
1257
|
+
identityId: 'test-id',
|
|
1258
|
+
traits: {
|
|
1259
|
+
emails: ['test@email.com'],
|
|
1260
|
+
addresses: [],
|
|
1261
|
+
},
|
|
1262
|
+
};
|
|
1263
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1264
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.ADDRESS_UPDATE);
|
|
1265
|
+
expect(result.isCacheStale).toBe(true);
|
|
1266
|
+
expect(result.staleTraits).toContain('addresses');
|
|
1267
|
+
});
|
|
1268
|
+
it('should return ADDRESS_UPDATE even with volatile traits stale', () => {
|
|
1269
|
+
const incomingIdentity = {
|
|
1270
|
+
identityId: 'test-id',
|
|
1271
|
+
traits: {
|
|
1272
|
+
emails: ['test@email.com'],
|
|
1273
|
+
ipAddress: '10.0.0.1',
|
|
1274
|
+
addresses: [{ city: 'Boston', s: ADDRESS_INFO_SOURCE.INPUT }],
|
|
1275
|
+
},
|
|
1276
|
+
};
|
|
1277
|
+
const cachedIdentity = {
|
|
1278
|
+
identityId: 'test-id',
|
|
1279
|
+
traits: {
|
|
1280
|
+
emails: ['test@email.com'],
|
|
1281
|
+
ipAddress: '192.168.1.1',
|
|
1282
|
+
addresses: [],
|
|
1283
|
+
},
|
|
1284
|
+
};
|
|
1285
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1286
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.ADDRESS_UPDATE);
|
|
1287
|
+
expect(result.isCacheStale).toBe(true);
|
|
1288
|
+
});
|
|
1289
|
+
});
|
|
1290
|
+
describe('IDENTITY_STALE tier - full Neptune resolution', () => {
|
|
1291
|
+
it('should return IDENTITY_STALE tier when email is new', () => {
|
|
1292
|
+
const incomingIdentity = {
|
|
1293
|
+
identityId: 'test-id',
|
|
1294
|
+
traits: { emails: ['old@email.com', 'new@email.com'] },
|
|
1295
|
+
};
|
|
1296
|
+
const cachedIdentity = {
|
|
1297
|
+
identityId: 'test-id',
|
|
1298
|
+
traits: { emails: ['old@email.com'] },
|
|
1299
|
+
};
|
|
1300
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1301
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.IDENTITY_STALE);
|
|
1302
|
+
expect(result.isCacheStale).toBe(true);
|
|
1303
|
+
expect(result.staleTraits).toContain('emails');
|
|
1304
|
+
});
|
|
1305
|
+
it('should return IDENTITY_STALE tier when phone is new', () => {
|
|
1306
|
+
const incomingIdentity = {
|
|
1307
|
+
identityId: 'test-id',
|
|
1308
|
+
traits: { phones: ['+1234567890', '+9876543210'] },
|
|
1309
|
+
};
|
|
1310
|
+
const cachedIdentity = {
|
|
1311
|
+
identityId: 'test-id',
|
|
1312
|
+
traits: { phones: ['+1234567890'] },
|
|
1313
|
+
};
|
|
1314
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1315
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.IDENTITY_STALE);
|
|
1316
|
+
expect(result.isCacheStale).toBe(true);
|
|
1317
|
+
expect(result.staleTraits).toContain('phones');
|
|
1318
|
+
});
|
|
1319
|
+
it('should return IDENTITY_STALE tier when identityId changes', () => {
|
|
1320
|
+
const incomingIdentity = {
|
|
1321
|
+
identityId: 'new-id',
|
|
1322
|
+
traits: { emails: ['test@email.com'] },
|
|
1323
|
+
};
|
|
1324
|
+
const cachedIdentity = {
|
|
1325
|
+
identityId: 'old-id',
|
|
1326
|
+
traits: { emails: ['test@email.com'] },
|
|
1327
|
+
};
|
|
1328
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1329
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.IDENTITY_STALE);
|
|
1330
|
+
expect(result.isCacheStale).toBe(true);
|
|
1331
|
+
expect(result.staleTraits).toContain('identityId');
|
|
1332
|
+
});
|
|
1333
|
+
it('should return IDENTITY_STALE tier when click info is new', () => {
|
|
1334
|
+
const incomingIdentity = {
|
|
1335
|
+
identityId: 'test-id',
|
|
1336
|
+
traits: { click: { gclid: 'new_gclid' } },
|
|
1337
|
+
};
|
|
1338
|
+
const cachedIdentity = {
|
|
1339
|
+
identityId: 'test-id',
|
|
1340
|
+
traits: {},
|
|
1341
|
+
};
|
|
1342
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1343
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.IDENTITY_STALE);
|
|
1344
|
+
expect(result.isCacheStale).toBe(true);
|
|
1345
|
+
expect(result.staleTraits).toContain('clickInfos');
|
|
1346
|
+
});
|
|
1347
|
+
it('should return IDENTITY_STALE even with ADDRESS_UPDATE also present', () => {
|
|
1348
|
+
const incomingIdentity = {
|
|
1349
|
+
identityId: 'test-id',
|
|
1350
|
+
traits: {
|
|
1351
|
+
emails: ['old@email.com', 'new@email.com'],
|
|
1352
|
+
addresses: [{ city: 'Boston', s: ADDRESS_INFO_SOURCE.INPUT }],
|
|
1353
|
+
},
|
|
1354
|
+
};
|
|
1355
|
+
const cachedIdentity = {
|
|
1356
|
+
identityId: 'test-id',
|
|
1357
|
+
traits: {
|
|
1358
|
+
emails: ['old@email.com'],
|
|
1359
|
+
addresses: [],
|
|
1360
|
+
},
|
|
1361
|
+
};
|
|
1362
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1363
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.IDENTITY_STALE);
|
|
1364
|
+
expect(result.isCacheStale).toBe(true);
|
|
1365
|
+
expect(result.staleTraits).toContain('emails');
|
|
1366
|
+
expect(result.staleTraits).toContain('addresses');
|
|
1367
|
+
});
|
|
1368
|
+
});
|
|
1369
|
+
describe('Merged identity structure', () => {
|
|
1370
|
+
it('should preserve incoming identityId in merged identity', () => {
|
|
1371
|
+
const incomingIdentity = {
|
|
1372
|
+
identityId: 'incoming-id',
|
|
1373
|
+
traits: { emails: ['test@email.com'] },
|
|
1374
|
+
};
|
|
1375
|
+
const cachedIdentity = {
|
|
1376
|
+
identityId: 'cached-id',
|
|
1377
|
+
traits: { phones: ['+1234567890'] },
|
|
1378
|
+
};
|
|
1379
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1380
|
+
expect(result.mergedIdentity.identityId).toBe('incoming-id');
|
|
1381
|
+
});
|
|
1382
|
+
it('should merge traits from both incoming and cached', () => {
|
|
1383
|
+
const incomingIdentity = {
|
|
1384
|
+
identityId: 'test-id',
|
|
1385
|
+
traits: {
|
|
1386
|
+
emails: ['incoming@email.com'],
|
|
1387
|
+
userIds: ['user1'],
|
|
1388
|
+
},
|
|
1389
|
+
};
|
|
1390
|
+
const cachedIdentity = {
|
|
1391
|
+
identityId: 'test-id',
|
|
1392
|
+
traits: {
|
|
1393
|
+
emails: ['cached@email.com'],
|
|
1394
|
+
phones: ['+1234567890'],
|
|
1395
|
+
},
|
|
1396
|
+
};
|
|
1397
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1398
|
+
expect(result.mergedIdentity.traits?.emails).toContain('incoming@email.com');
|
|
1399
|
+
expect(result.mergedIdentity.traits?.emails).toContain('cached@email.com');
|
|
1400
|
+
expect(result.mergedIdentity.traits?.userIds).toEqual(['user1']);
|
|
1401
|
+
expect(result.mergedIdentity.traits?.phones).toEqual(['+1234567890']);
|
|
1402
|
+
});
|
|
1403
|
+
});
|
|
1404
|
+
describe('staleTracker output', () => {
|
|
1405
|
+
it('should include full staleTracker with all flags', () => {
|
|
1406
|
+
const incomingIdentity = {
|
|
1407
|
+
identityId: 'test-id',
|
|
1408
|
+
traits: {
|
|
1409
|
+
emails: ['old@email.com', 'new@email.com'],
|
|
1410
|
+
ipAddress: '10.0.0.1',
|
|
1411
|
+
},
|
|
1412
|
+
};
|
|
1413
|
+
const cachedIdentity = {
|
|
1414
|
+
identityId: 'test-id',
|
|
1415
|
+
traits: {
|
|
1416
|
+
emails: ['old@email.com'],
|
|
1417
|
+
},
|
|
1418
|
+
};
|
|
1419
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1420
|
+
expect(result.staleTracker).toBeDefined();
|
|
1421
|
+
expect(result.staleTracker.isEmailsStale).toBe(true);
|
|
1422
|
+
expect(result.staleTracker.isIpAddressStale).toBe(true);
|
|
1423
|
+
expect(result.staleTracker.isPhonesStale).toBe(false);
|
|
1424
|
+
});
|
|
1425
|
+
});
|
|
1426
|
+
describe('Edge cases - empty traits', () => {
|
|
1427
|
+
it('should handle empty traits on incoming identity', () => {
|
|
1428
|
+
const incomingIdentity = {
|
|
1429
|
+
identityId: 'test-id',
|
|
1430
|
+
traits: {},
|
|
1431
|
+
};
|
|
1432
|
+
const cachedIdentity = {
|
|
1433
|
+
identityId: 'test-id',
|
|
1434
|
+
traits: {
|
|
1435
|
+
emails: ['cached@email.com'],
|
|
1436
|
+
phones: ['+1234567890'],
|
|
1437
|
+
userIds: ['user1'],
|
|
1438
|
+
},
|
|
1439
|
+
};
|
|
1440
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1441
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.NONE);
|
|
1442
|
+
expect(result.isCacheStale).toBe(false);
|
|
1443
|
+
expect(result.staleTraits).toEqual([]);
|
|
1444
|
+
expect(result.mergedIdentity.traits?.emails).toEqual(['cached@email.com']);
|
|
1445
|
+
expect(result.mergedIdentity.traits?.phones).toEqual(['+1234567890']);
|
|
1446
|
+
expect(result.mergedIdentity.traits?.userIds).toEqual(['user1']);
|
|
1447
|
+
});
|
|
1448
|
+
it('should handle empty traits on cached identity', () => {
|
|
1449
|
+
const incomingIdentity = {
|
|
1450
|
+
identityId: 'test-id',
|
|
1451
|
+
traits: {
|
|
1452
|
+
emails: ['new@email.com'],
|
|
1453
|
+
phones: ['+1234567890'],
|
|
1454
|
+
},
|
|
1455
|
+
};
|
|
1456
|
+
const cachedIdentity = {
|
|
1457
|
+
identityId: 'test-id',
|
|
1458
|
+
traits: {},
|
|
1459
|
+
};
|
|
1460
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1461
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.IDENTITY_STALE);
|
|
1462
|
+
expect(result.isCacheStale).toBe(true);
|
|
1463
|
+
expect(result.staleTraits).toContain('emails');
|
|
1464
|
+
expect(result.staleTraits).toContain('phones');
|
|
1465
|
+
expect(result.mergedIdentity.traits?.emails).toEqual(['new@email.com']);
|
|
1466
|
+
expect(result.mergedIdentity.traits?.phones).toEqual(['+1234567890']);
|
|
1467
|
+
});
|
|
1468
|
+
it('should handle both identities with empty traits', () => {
|
|
1469
|
+
const incomingIdentity = {
|
|
1470
|
+
identityId: 'test-id',
|
|
1471
|
+
traits: {},
|
|
1472
|
+
};
|
|
1473
|
+
const cachedIdentity = {
|
|
1474
|
+
identityId: 'test-id',
|
|
1475
|
+
traits: {},
|
|
1476
|
+
};
|
|
1477
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1478
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.NONE);
|
|
1479
|
+
expect(result.isCacheStale).toBe(false);
|
|
1480
|
+
expect(result.staleTraits).toEqual([]);
|
|
1481
|
+
});
|
|
1482
|
+
});
|
|
1483
|
+
describe('Edge cases - null/undefined handling', () => {
|
|
1484
|
+
it('should handle undefined traits on incoming identity', () => {
|
|
1485
|
+
const incomingIdentity = {
|
|
1486
|
+
identityId: 'test-id',
|
|
1487
|
+
};
|
|
1488
|
+
const cachedIdentity = {
|
|
1489
|
+
identityId: 'test-id',
|
|
1490
|
+
traits: {
|
|
1491
|
+
emails: ['cached@email.com'],
|
|
1492
|
+
},
|
|
1493
|
+
};
|
|
1494
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1495
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.NONE);
|
|
1496
|
+
expect(result.isCacheStale).toBe(false);
|
|
1497
|
+
});
|
|
1498
|
+
it('should handle undefined traits on cached identity', () => {
|
|
1499
|
+
const incomingIdentity = {
|
|
1500
|
+
identityId: 'test-id',
|
|
1501
|
+
traits: {
|
|
1502
|
+
emails: ['new@email.com'],
|
|
1503
|
+
},
|
|
1504
|
+
};
|
|
1505
|
+
const cachedIdentity = {
|
|
1506
|
+
identityId: 'test-id',
|
|
1507
|
+
};
|
|
1508
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1509
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.IDENTITY_STALE);
|
|
1510
|
+
expect(result.isCacheStale).toBe(true);
|
|
1511
|
+
expect(result.staleTraits).toContain('emails');
|
|
1512
|
+
});
|
|
1513
|
+
it('should handle both identities with undefined traits', () => {
|
|
1514
|
+
const incomingIdentity = {
|
|
1515
|
+
identityId: 'test-id',
|
|
1516
|
+
};
|
|
1517
|
+
const cachedIdentity = {
|
|
1518
|
+
identityId: 'test-id',
|
|
1519
|
+
};
|
|
1520
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1521
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.NONE);
|
|
1522
|
+
expect(result.isCacheStale).toBe(false);
|
|
1523
|
+
expect(result.staleTraits).toEqual([]);
|
|
1524
|
+
});
|
|
1525
|
+
it('should handle null values in array traits gracefully', () => {
|
|
1526
|
+
const incomingIdentity = {
|
|
1527
|
+
identityId: 'test-id',
|
|
1528
|
+
traits: {
|
|
1529
|
+
emails: ['valid@email.com', null, 'new@email.com'],
|
|
1530
|
+
},
|
|
1531
|
+
};
|
|
1532
|
+
const cachedIdentity = {
|
|
1533
|
+
identityId: 'test-id',
|
|
1534
|
+
traits: {
|
|
1535
|
+
emails: ['valid@email.com'],
|
|
1536
|
+
},
|
|
1537
|
+
};
|
|
1538
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1539
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.IDENTITY_STALE);
|
|
1540
|
+
expect(result.isCacheStale).toBe(true);
|
|
1541
|
+
});
|
|
1542
|
+
});
|
|
1543
|
+
describe('Edge cases - click trait merging', () => {
|
|
1544
|
+
it('should detect staleness when incoming has new click info', () => {
|
|
1545
|
+
const incomingIdentity = {
|
|
1546
|
+
identityId: 'test-id',
|
|
1547
|
+
traits: {
|
|
1548
|
+
click: {
|
|
1549
|
+
gclid: 'new_gclid',
|
|
1550
|
+
fbp: 'fb.1.new.123',
|
|
1551
|
+
},
|
|
1552
|
+
},
|
|
1553
|
+
};
|
|
1554
|
+
const cachedIdentity = {
|
|
1555
|
+
identityId: 'test-id',
|
|
1556
|
+
traits: {},
|
|
1557
|
+
};
|
|
1558
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1559
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.IDENTITY_STALE);
|
|
1560
|
+
expect(result.isCacheStale).toBe(true);
|
|
1561
|
+
expect(result.staleTraits).toContain('clickInfos');
|
|
1562
|
+
});
|
|
1563
|
+
it('should preserve cached click info when merging', () => {
|
|
1564
|
+
const incomingIdentity = {
|
|
1565
|
+
identityId: 'test-id',
|
|
1566
|
+
traits: {
|
|
1567
|
+
click: {
|
|
1568
|
+
gclid: 'incoming_gclid',
|
|
1569
|
+
},
|
|
1570
|
+
},
|
|
1571
|
+
};
|
|
1572
|
+
const cachedIdentity = {
|
|
1573
|
+
identityId: 'test-id',
|
|
1574
|
+
traits: {
|
|
1575
|
+
click: {
|
|
1576
|
+
gclid: 'cached_gclid',
|
|
1577
|
+
fbp: 'fb.1.cached.456',
|
|
1578
|
+
},
|
|
1579
|
+
},
|
|
1580
|
+
};
|
|
1581
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1582
|
+
expect(result.mergedIdentity.traits?.click?.gclid).toBe('cached_gclid');
|
|
1583
|
+
expect(result.mergedIdentity.traits?.click?.fbp).toBe('fb.1.cached.456');
|
|
1584
|
+
});
|
|
1585
|
+
it('should not be stale when click timestamps differ but values are same', () => {
|
|
1586
|
+
const incomingIdentity = {
|
|
1587
|
+
identityId: 'test-id',
|
|
1588
|
+
traits: {
|
|
1589
|
+
click: {
|
|
1590
|
+
fbp: 'fb.1.same.123',
|
|
1591
|
+
fbpCollectedAt: '2024-06-01T00:00:00Z',
|
|
1592
|
+
},
|
|
1593
|
+
},
|
|
1594
|
+
};
|
|
1595
|
+
const cachedIdentity = {
|
|
1596
|
+
identityId: 'test-id',
|
|
1597
|
+
traits: {
|
|
1598
|
+
click: {
|
|
1599
|
+
fbp: 'fb.1.same.123',
|
|
1600
|
+
fbpCollectedAt: '2024-01-01T00:00:00Z',
|
|
1601
|
+
},
|
|
1602
|
+
},
|
|
1603
|
+
};
|
|
1604
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1605
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.NONE);
|
|
1606
|
+
expect(result.isCacheStale).toBe(false);
|
|
1607
|
+
});
|
|
1608
|
+
it('should detect staleness when fbc changes (incoming has new fbc, cached has none)', () => {
|
|
1609
|
+
const incomingIdentity = {
|
|
1610
|
+
identityId: 'test-id',
|
|
1611
|
+
traits: {
|
|
1612
|
+
click: {
|
|
1613
|
+
fbc: 'fb.1.1234.new_fbclid',
|
|
1614
|
+
},
|
|
1615
|
+
},
|
|
1616
|
+
};
|
|
1617
|
+
const cachedIdentity = {
|
|
1618
|
+
identityId: 'test-id',
|
|
1619
|
+
traits: {
|
|
1620
|
+
click: {},
|
|
1621
|
+
},
|
|
1622
|
+
};
|
|
1623
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1624
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.IDENTITY_STALE);
|
|
1625
|
+
expect(result.isCacheStale).toBe(true);
|
|
1626
|
+
expect(result.staleTraits).toContain('clickInfos');
|
|
1627
|
+
});
|
|
1628
|
+
});
|
|
1629
|
+
describe('staleTraits extraction comprehensive tests', () => {
|
|
1630
|
+
it('should return empty array when NONE tier', () => {
|
|
1631
|
+
const incomingIdentity = {
|
|
1632
|
+
identityId: 'test-id',
|
|
1633
|
+
traits: { emails: ['test@email.com'] },
|
|
1634
|
+
};
|
|
1635
|
+
const cachedIdentity = {
|
|
1636
|
+
identityId: 'test-id',
|
|
1637
|
+
traits: { emails: ['test@email.com', 'other@email.com'] },
|
|
1638
|
+
};
|
|
1639
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1640
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.NONE);
|
|
1641
|
+
expect(result.staleTraits).toEqual([]);
|
|
1642
|
+
});
|
|
1643
|
+
it('should return volatile trait names for VOLATILE_ONLY tier', () => {
|
|
1644
|
+
const incomingIdentity = {
|
|
1645
|
+
identityId: 'test-id',
|
|
1646
|
+
traits: {
|
|
1647
|
+
emails: ['test@email.com'],
|
|
1648
|
+
ipAddress: '10.0.0.1',
|
|
1649
|
+
userAgent: 'new-agent',
|
|
1650
|
+
},
|
|
1651
|
+
};
|
|
1652
|
+
const cachedIdentity = {
|
|
1653
|
+
identityId: 'test-id',
|
|
1654
|
+
traits: {
|
|
1655
|
+
emails: ['test@email.com'],
|
|
1656
|
+
},
|
|
1657
|
+
};
|
|
1658
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1659
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.VOLATILE_ONLY);
|
|
1660
|
+
expect(result.staleTraits).toContain('ipAddress');
|
|
1661
|
+
expect(result.staleTraits).toContain('userAgent');
|
|
1662
|
+
expect(result.staleTraits).not.toContain('emails');
|
|
1663
|
+
});
|
|
1664
|
+
it('should return address trait name for ADDRESS_UPDATE tier', () => {
|
|
1665
|
+
const incomingIdentity = {
|
|
1666
|
+
identityId: 'test-id',
|
|
1667
|
+
traits: {
|
|
1668
|
+
emails: ['test@email.com'],
|
|
1669
|
+
addresses: [{ city: 'Boston', s: ADDRESS_INFO_SOURCE.INPUT }],
|
|
1670
|
+
},
|
|
1671
|
+
};
|
|
1672
|
+
const cachedIdentity = {
|
|
1673
|
+
identityId: 'test-id',
|
|
1674
|
+
traits: {
|
|
1675
|
+
emails: ['test@email.com'],
|
|
1676
|
+
addresses: [],
|
|
1677
|
+
},
|
|
1678
|
+
};
|
|
1679
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1680
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.ADDRESS_UPDATE);
|
|
1681
|
+
expect(result.staleTraits).toContain('addresses');
|
|
1682
|
+
});
|
|
1683
|
+
it('should return all stale identity trait names for IDENTITY_STALE tier', () => {
|
|
1684
|
+
const incomingIdentity = {
|
|
1685
|
+
identityId: 'test-id',
|
|
1686
|
+
traits: {
|
|
1687
|
+
emails: ['old@email.com', 'new@email.com'],
|
|
1688
|
+
phones: ['+1234567890', '+9876543210'],
|
|
1689
|
+
userIds: ['user1', 'user2'],
|
|
1690
|
+
},
|
|
1691
|
+
};
|
|
1692
|
+
const cachedIdentity = {
|
|
1693
|
+
identityId: 'test-id',
|
|
1694
|
+
traits: {
|
|
1695
|
+
emails: ['old@email.com'],
|
|
1696
|
+
phones: ['+1234567890'],
|
|
1697
|
+
userIds: ['user1'],
|
|
1698
|
+
},
|
|
1699
|
+
};
|
|
1700
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1701
|
+
expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.IDENTITY_STALE);
|
|
1702
|
+
expect(result.staleTraits).toContain('emails');
|
|
1703
|
+
expect(result.staleTraits).toContain('phones');
|
|
1704
|
+
expect(result.staleTraits).toContain('userIds');
|
|
1705
|
+
});
|
|
1706
|
+
});
|
|
1707
|
+
describe('Merge behavior verification', () => {
|
|
1708
|
+
it('should merge incoming and cached array traits (emails, phones, userIds)', () => {
|
|
1709
|
+
const incomingIdentity = {
|
|
1710
|
+
identityId: 'incoming-id',
|
|
1711
|
+
traits: {
|
|
1712
|
+
emails: ['incoming@email.com', 'shared@email.com'],
|
|
1713
|
+
userIds: ['incominguser'],
|
|
1714
|
+
},
|
|
1715
|
+
};
|
|
1716
|
+
const cachedIdentity = {
|
|
1717
|
+
identityId: 'cached-id',
|
|
1718
|
+
traits: {
|
|
1719
|
+
emails: ['cached@email.com', 'shared@email.com'],
|
|
1720
|
+
phones: ['+1234567890'],
|
|
1721
|
+
userIds: ['cacheduser'],
|
|
1722
|
+
},
|
|
1723
|
+
};
|
|
1724
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1725
|
+
expect(result.mergedIdentity.traits?.emails).toContain('incoming@email.com');
|
|
1726
|
+
expect(result.mergedIdentity.traits?.emails).toContain('cached@email.com');
|
|
1727
|
+
expect(result.mergedIdentity.traits?.emails).toContain('shared@email.com');
|
|
1728
|
+
expect(result.mergedIdentity.traits?.phones).toEqual(['+1234567890']);
|
|
1729
|
+
expect(result.mergedIdentity.traits?.userIds).toContain('incominguser');
|
|
1730
|
+
expect(result.mergedIdentity.traits?.userIds).toContain('cacheduser');
|
|
1731
|
+
});
|
|
1732
|
+
it('should preserve identityId from incoming identity', () => {
|
|
1733
|
+
const incomingIdentity = {
|
|
1734
|
+
identityId: 'incoming-id-123',
|
|
1735
|
+
traits: { emails: ['test@email.com'] },
|
|
1736
|
+
};
|
|
1737
|
+
const cachedIdentity = {
|
|
1738
|
+
identityId: 'cached-id-456',
|
|
1739
|
+
traits: { phones: ['+1234567890'] },
|
|
1740
|
+
};
|
|
1741
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1742
|
+
expect(result.mergedIdentity.identityId).toBe('incoming-id-123');
|
|
1743
|
+
});
|
|
1744
|
+
it('should merge addresses from both identities', () => {
|
|
1745
|
+
const incomingIdentity = {
|
|
1746
|
+
identityId: 'test-id',
|
|
1747
|
+
traits: {
|
|
1748
|
+
addresses: [
|
|
1749
|
+
{ city: 'IncomingCity', s: ADDRESS_INFO_SOURCE.INPUT },
|
|
1750
|
+
],
|
|
1751
|
+
},
|
|
1752
|
+
};
|
|
1753
|
+
const cachedIdentity = {
|
|
1754
|
+
identityId: 'test-id',
|
|
1755
|
+
traits: {
|
|
1756
|
+
addresses: [
|
|
1757
|
+
{ city: 'CachedCity', s: ADDRESS_INFO_SOURCE.INPUT },
|
|
1758
|
+
],
|
|
1759
|
+
},
|
|
1760
|
+
};
|
|
1761
|
+
const result = mergeAndComputeIdentityStaleness(incomingIdentity, cachedIdentity);
|
|
1762
|
+
expect(result.mergedIdentity.traits?.addresses).toHaveLength(2);
|
|
1763
|
+
expect(result.mergedIdentity.traits?.addresses).toEqual(expect.arrayContaining([
|
|
1764
|
+
expect.objectContaining({ city: 'IncomingCity' }),
|
|
1765
|
+
expect.objectContaining({ city: 'CachedCity' }),
|
|
1766
|
+
]));
|
|
1767
|
+
});
|
|
1768
|
+
});
|
|
1769
|
+
});
|
|
1059
1770
|
//# sourceMappingURL=trait-merging-and-staleness.spec.js.map
|