Skip to content

Commit c720d4f

Browse files
[MOB-9652] support for nested JSON array (#459)
* MOB-9650 Added support for nested criteria match a.b.c * fix: removed updatecart from nested criteria * [MOB-9652] support for nested JSON array * [MOB-9652] customEvent test case for nested JSON array * [MOB-9168] Automated unit tests against complex criteria (#461) * [MOB-9168] Automated unit tests against complex criteria * [MOB-9168] Automated unit tests against complex criteria
1 parent 604ea66 commit c720d4f

File tree

4 files changed

+946
-11
lines changed

4 files changed

+946
-11
lines changed

src/anonymousUserTracking/criteriaCompletionChecker.ts

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -350,16 +350,41 @@ class CriteriaCompletionChecker {
350350
);
351351

352352
if (field.includes('.')) {
353-
const fields = field.split('.');
354-
const firstElement = eventData?.[fields[0]];
355-
if (Array.isArray(firstElement)) {
356-
return firstElement?.some((item: any) => {
357-
const data = {
358-
...eventData,
359-
[fields[0]]: item
360-
};
361-
return this.evaluateFieldLogic(searchQueries, data);
362-
});
353+
const splitField = field.split('.') as string[];
354+
const fields =
355+
eventData?.eventType === TRACK_EVENT &&
356+
eventData?.eventName === splitField[0]
357+
? splitField.slice(1)
358+
: splitField;
359+
360+
let fieldValue = eventData;
361+
let isSubFieldArray = false;
362+
let isSubMatch = false;
363+
364+
fields.forEach((subField) => {
365+
const subFieldValue = fieldValue[subField];
366+
if (Array.isArray(subFieldValue)) {
367+
isSubFieldArray = true;
368+
isSubMatch = subFieldValue.some((item: any) => {
369+
const data = fields.reduceRight((acc: any, key) => {
370+
if (key === subField) {
371+
return { [key]: item };
372+
}
373+
return { [key]: acc };
374+
}, {});
375+
376+
return this.evaluateFieldLogic(searchQueries, {
377+
...eventData,
378+
...data
379+
});
380+
});
381+
} else {
382+
fieldValue = subFieldValue;
383+
}
384+
});
385+
386+
if (isSubFieldArray) {
387+
return isSubMatch;
363388
}
364389

365390
const valueFromObj = this.getFieldValue(eventData, field);

src/anonymousUserTracking/tests/complexCriteria.test.ts

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { SHARED_PREFS_EVENT_LIST_KEY } from '../../constants';
22
import CriteriaCompletionChecker from '../criteriaCompletionChecker';
3+
import {
4+
COMPLEX_CRITERIA_1,
5+
COMPLEX_CRITERIA_2,
6+
COMPLEX_CRITERIA_3
7+
} from './constants';
38

49
const localStorageMock = {
510
getItem: jest.fn(),
@@ -1598,4 +1603,252 @@ describe('complexCriteria', () => {
15981603
);
15991604
expect(result).toEqual(null);
16001605
});
1606+
1607+
// MARK: Complex criteria #1
1608+
it('should return criteriaId 290 if (1 OR 2 OR 3) AND (4 AND 5) AND (6 NOT 7) matched', () => {
1609+
(localStorage.getItem as jest.Mock).mockImplementation((key) => {
1610+
if (key === SHARED_PREFS_EVENT_LIST_KEY) {
1611+
return JSON.stringify([
1612+
{
1613+
dataFields: {
1614+
saved_cars: { color: 'black' },
1615+
'animal-found': { vaccinated: true },
1616+
eventName: 'birthday'
1617+
},
1618+
eventType: 'customEvent'
1619+
},
1620+
{
1621+
dataFields: { reason: 'testing', total: 30 },
1622+
eventType: 'purchase'
1623+
},
1624+
{
1625+
dataFields: { firstName: 'Adam' },
1626+
eventType: 'user'
1627+
}
1628+
]);
1629+
}
1630+
return null;
1631+
});
1632+
1633+
const localStoredEventList = localStorage.getItem(
1634+
SHARED_PREFS_EVENT_LIST_KEY
1635+
);
1636+
1637+
const checker = new CriteriaCompletionChecker(
1638+
localStoredEventList === null ? '' : localStoredEventList
1639+
);
1640+
const result = checker.getMatchedCriteria(
1641+
JSON.stringify(COMPLEX_CRITERIA_1)
1642+
);
1643+
expect(result).toEqual('290');
1644+
});
1645+
1646+
it('should return criteriaId null if (1 OR 2 OR 3) AND (4 AND 5) AND (6 NOT 7) - No match', () => {
1647+
(localStorage.getItem as jest.Mock).mockImplementation((key) => {
1648+
if (key === SHARED_PREFS_EVENT_LIST_KEY) {
1649+
return JSON.stringify([
1650+
{
1651+
eventType: 'user',
1652+
dataFields: {
1653+
firstName: 'Alex'
1654+
}
1655+
},
1656+
{
1657+
eventType: 'customEvent',
1658+
eventName: 'saved_cars',
1659+
dataFields: {
1660+
color: ''
1661+
}
1662+
},
1663+
{
1664+
eventType: 'customEvent',
1665+
eventName: 'animal-found',
1666+
dataFields: {
1667+
vaccinated: true
1668+
}
1669+
},
1670+
{
1671+
eventType: 'purchase',
1672+
dataFields: {
1673+
total: 30,
1674+
reason: 'testing'
1675+
}
1676+
}
1677+
]);
1678+
}
1679+
return null;
1680+
});
1681+
1682+
const localStoredEventList = localStorage.getItem(
1683+
SHARED_PREFS_EVENT_LIST_KEY
1684+
);
1685+
1686+
const checker = new CriteriaCompletionChecker(
1687+
localStoredEventList === null ? '' : localStoredEventList
1688+
);
1689+
const result = checker.getMatchedCriteria(
1690+
JSON.stringify(COMPLEX_CRITERIA_1)
1691+
);
1692+
expect(result).toEqual(null);
1693+
});
1694+
1695+
// MARK: Complex criteria #2
1696+
it('should return criteriaId 291 if (6 OR 7) OR (4 AND 5) OR (1 NOT 2 NOT 3) matched', () => {
1697+
(localStorage.getItem as jest.Mock).mockImplementation((key) => {
1698+
if (key === SHARED_PREFS_EVENT_LIST_KEY) {
1699+
return JSON.stringify([
1700+
{
1701+
eventType: 'user',
1702+
dataFields: {
1703+
firstName: 'xcode'
1704+
}
1705+
},
1706+
{
1707+
eventType: 'customEvent',
1708+
eventName: 'saved_cars',
1709+
dataFields: {
1710+
color: 'black'
1711+
}
1712+
},
1713+
{
1714+
eventType: 'customEvent',
1715+
eventName: 'animal-found',
1716+
dataFields: {
1717+
vaccinated: true
1718+
}
1719+
},
1720+
{
1721+
eventType: 'purchase',
1722+
dataFields: {
1723+
total: 110,
1724+
reason: 'testing'
1725+
}
1726+
}
1727+
]);
1728+
}
1729+
return null;
1730+
});
1731+
1732+
const localStoredEventList = localStorage.getItem(
1733+
SHARED_PREFS_EVENT_LIST_KEY
1734+
);
1735+
1736+
const checker = new CriteriaCompletionChecker(
1737+
localStoredEventList === null ? '' : localStoredEventList
1738+
);
1739+
const result = checker.getMatchedCriteria(
1740+
JSON.stringify(COMPLEX_CRITERIA_2)
1741+
);
1742+
expect(result).toEqual('291');
1743+
});
1744+
1745+
it('should return criteriaId null if (6 OR 7) OR (4 AND 5) OR (1 NOT 2 NOT 3) - No match', () => {
1746+
(localStorage.getItem as jest.Mock).mockImplementation((key) => {
1747+
if (key === SHARED_PREFS_EVENT_LIST_KEY) {
1748+
return JSON.stringify([
1749+
{
1750+
eventType: 'user',
1751+
dataFields: {
1752+
firstName: 'Alex'
1753+
}
1754+
},
1755+
{
1756+
eventType: 'purchase',
1757+
dataFields: {
1758+
total: 10,
1759+
reason: 'null'
1760+
}
1761+
}
1762+
]);
1763+
}
1764+
return null;
1765+
});
1766+
1767+
const localStoredEventList = localStorage.getItem(
1768+
SHARED_PREFS_EVENT_LIST_KEY
1769+
);
1770+
1771+
const checker = new CriteriaCompletionChecker(
1772+
localStoredEventList === null ? '' : localStoredEventList
1773+
);
1774+
const result = checker.getMatchedCriteria(
1775+
JSON.stringify(COMPLEX_CRITERIA_2)
1776+
);
1777+
expect(result).toEqual(null);
1778+
});
1779+
1780+
// MARK: Complex criteria #3
1781+
it('should return criteriaId 292 if (1 AND 2) NOR (3 OR 4 OR 5) NOR (6 NOR 7) matched', () => {
1782+
(localStorage.getItem as jest.Mock).mockImplementation((key) => {
1783+
if (key === SHARED_PREFS_EVENT_LIST_KEY) {
1784+
return JSON.stringify([
1785+
{
1786+
dataType: 'user',
1787+
dataFields: {
1788+
firstName: 'xcode',
1789+
lastName: 'ssr'
1790+
}
1791+
},
1792+
{
1793+
dataType: 'customEvent',
1794+
eventName: 'animal-found',
1795+
dataFields: {
1796+
vaccinated: true,
1797+
count: 10
1798+
}
1799+
}
1800+
]);
1801+
}
1802+
return null;
1803+
});
1804+
1805+
const localStoredEventList = localStorage.getItem(
1806+
SHARED_PREFS_EVENT_LIST_KEY
1807+
);
1808+
1809+
const checker = new CriteriaCompletionChecker(
1810+
localStoredEventList === null ? '' : localStoredEventList
1811+
);
1812+
const result = checker.getMatchedCriteria(
1813+
JSON.stringify(COMPLEX_CRITERIA_3)
1814+
);
1815+
expect(result).toEqual('292');
1816+
});
1817+
1818+
it('should return criteriaId null if (1 AND 2) NOR (3 OR 4 OR 5) NOR (6 NOR 7) - No match', () => {
1819+
(localStorage.getItem as jest.Mock).mockImplementation((key) => {
1820+
if (key === SHARED_PREFS_EVENT_LIST_KEY) {
1821+
return JSON.stringify([
1822+
{
1823+
eventType: 'user',
1824+
dataFields: {
1825+
firstName: 'Alex',
1826+
lastName: 'Aris'
1827+
}
1828+
},
1829+
{
1830+
eventType: 'customEvent',
1831+
eventName: 'animal-found',
1832+
dataFields: {
1833+
vaccinated: false,
1834+
count: 4
1835+
}
1836+
}
1837+
]);
1838+
}
1839+
return null;
1840+
});
1841+
1842+
const localStoredEventList = localStorage.getItem(
1843+
SHARED_PREFS_EVENT_LIST_KEY
1844+
);
1845+
1846+
const checker = new CriteriaCompletionChecker(
1847+
localStoredEventList === null ? '' : localStoredEventList
1848+
);
1849+
const result = checker.getMatchedCriteria(
1850+
JSON.stringify(COMPLEX_CRITERIA_3)
1851+
);
1852+
expect(result).toEqual(null);
1853+
});
16011854
});

0 commit comments

Comments
 (0)