forked from snowplow/snowplow-javascript-tracker
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdata.test.ts
More file actions
139 lines (112 loc) · 3.7 KB
/
Copy pathdata.test.ts
File metadata and controls
139 lines (112 loc) · 3.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import { evaluateDataSelector, extractSelectorDetails, isDataSelector } from '../src/data';
import type { DataSelector } from '../src/types';
describe('DataSelector behavior', () => {
const fake_selector = 'css_path_val';
let elem: HTMLDivElement;
beforeAll(() => {
// sample element we'll be selecting from
elem = document.createElement('div');
elem.textContent = 'text_content_val\n';
elem.setAttribute('id', 'id_attr');
elem.className = 'class_prop';
elem.dataset.dsAttr = 'ds_val';
const child = document.createElement('span');
child.textContent = 'child_text_val';
elem.appendChild(child);
});
it.each([
['attributes', ['id'], 'id_attr'],
['properties', ['className'], 'class_prop'],
['dataset', ['dsAttr'], 'ds_val'],
['child_text', { inner: 'span' }, 'child_text_val'],
['content', { inner: 'text_content\\S+' }, 'text_content_val'],
['selector', true, fake_selector],
])('extracts %p', (source, params, value) => {
const selector = { [source]: params } as DataSelector;
expect(isDataSelector(selector)).toBe(true);
const result = evaluateDataSelector(elem, fake_selector, selector);
const expected = Array.isArray(params) ? params : params === true ? [source] : Object.keys(params);
expect(result).toEqual(
expected.map((attribute) => ({
source,
attribute,
value,
}))
);
});
it('handles callbacks', () => {
const sel = jest.fn().mockReturnValueOnce({ attribute: 'value', complex: { nested: 'data' } });
expect(isDataSelector(sel)).toBe(true);
const result = evaluateDataSelector(elem, fake_selector, sel);
expect(sel).toBeCalledWith(elem);
expect(result).toEqual([
{
source: 'callback',
attribute: 'attribute',
value: 'value',
},
{
source: 'callback',
attribute: 'complex',
value: '{"nested":"data"}',
},
]);
});
it('handles callback failures', () => {
const sel = jest.fn<Record<string, string>, Element[]>(() => {
throw new Error('deliberate failure');
});
expect(isDataSelector(sel)).toBe(true);
const result = evaluateDataSelector(elem, fake_selector, sel);
expect(sel).toBeCalledWith(elem);
expect(result).toEqual([
{
source: 'error',
attribute: 'message',
value: 'deliberate failure',
},
]);
});
it('flattens correctly', () => {
const result = extractSelectorDetails(elem, fake_selector, [
{ attributes: ['id'] },
{ properties: ['className'] },
{ properties: ['DOES_NOT_EXIST'] },
]);
expect(result).toHaveLength(2);
});
it('doesnt mix properties and attributes', () => {
const result = evaluateDataSelector(elem, fake_selector, {
attributes: ['className', 'class'],
properties: ['className', 'class'],
});
expect(result).toHaveLength(2);
expect(result).toContainEqual({
source: 'properties',
attribute: 'className',
value: 'class_prop',
});
expect(result).toContainEqual({
source: 'attributes',
attribute: 'class',
value: 'class_prop',
});
});
it('produces successful matches', () => {
const result = evaluateDataSelector(elem, fake_selector, {
attributes: ['id'],
match: { id: 'id_attr' },
});
expect(result).toHaveLength(1);
});
it('filters unsuccessful matches', () => {
const result = evaluateDataSelector(elem, fake_selector, {
attributes: ['id'],
match: { id: 'NOT_REAL_VALUE' },
});
expect(result).toHaveLength(0);
});
it.each([null, {}, { notASelector: [] }])('ignores empty: %j', (invalid) => {
expect(isDataSelector(invalid)).toBe(false);
});
});