make-mp-data 1.4.4 → 1.5.0

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/tests/e2e.test.js CHANGED
@@ -3,18 +3,22 @@
3
3
  /* eslint-disable no-undef */
4
4
  /* eslint-disable no-debugger */
5
5
  /* eslint-disable no-unused-vars */
6
- const generate = require('../core/index.js');
6
+ const generate = require('../index.js');
7
7
  require('dotenv').config();
8
8
  const { execSync } = require("child_process");
9
9
  const u = require('ak-tools');
10
+ const Papa = require('papaparse');
10
11
 
11
12
  const simple = require('../schemas/simple.js');
12
13
  const complex = require('../schemas/complex.js');
13
- const deep = require('../schemas/deepNest.js');
14
14
  const anon = require('../schemas/anon.js');
15
+ const funnels = require('../schemas/funnels.js');
16
+ const foobar = require('../schemas/foobar.js');
17
+ const mirror = require('../schemas/mirror.js');
18
+ const adspend = require('../schemas/adspend.js');
15
19
 
16
- const timeout = 60000;
17
- const testToken = process.env.TEST_TOKEN;
20
+ const timeout = 600000;
21
+ const testToken = process.env.TEST_TOKEN || "hello token!";
18
22
 
19
23
  describe('module', () => {
20
24
 
@@ -47,26 +51,62 @@ describe('module', () => {
47
51
  const results = await generate({ ...complex, verbose: true, writeToDisk: false, numEvents: 1100, numUsers: 100, seed: "deal with it" });
48
52
  const { eventData, groupProfilesData, lookupTableData, scdTableData, userProfilesData } = results;
49
53
  expect(eventData.length).toBeGreaterThan(980);
50
- expect(groupProfilesData[0]?.data?.length).toBe(500);
54
+ expect(groupProfilesData[0]?.length).toBe(500);
51
55
  expect(lookupTableData.length).toBe(2);
52
- expect(lookupTableData[0].data.length).toBe(1000);
56
+ expect(lookupTableData[0].length).toBe(1000);
53
57
  expect(scdTableData.length).toBe(5);
54
58
  expect(userProfilesData.length).toBe(100);
55
59
 
56
60
  }, timeout);
57
61
 
58
- test('works as module (deep nest)', async () => {
59
- console.log('MODULE TEST: DEEP NEST');
60
- const results = await generate({ ...deep, verbose: true, writeToDisk: false, numEvents: 1100, numUsers: 100, seed: "deal with it" });
61
- const { eventData, groupProfilesData, lookupTableData, scdTableData, userProfilesData } = results;
62
+ test('works as module (funnels)', async () => {
63
+ console.log('MODULE TEST: FUNNELS');
64
+ const results = await generate({ ...funnels, verbose: true, writeToDisk: false, numEvents: 1100, numUsers: 100, seed: "deal with it" });
65
+ const { eventData, groupProfilesData, scdTableData, userProfilesData } = results;
62
66
  expect(eventData.length).toBeGreaterThan(980);
63
- expect(groupProfilesData.length).toBe(0);
64
- expect(lookupTableData.length).toBe(0);
65
- expect(scdTableData.length).toBe(0);
67
+ expect(groupProfilesData.length).toBe(3);
68
+ expect(groupProfilesData[0]?.length).toBe(5000);
69
+ expect(groupProfilesData[1]?.length).toBe(500);
70
+ expect(groupProfilesData[2]?.length).toBe(50);
71
+ expect(scdTableData.length).toBe(2);
72
+ expect(scdTableData[0]?.length).toBeGreaterThan(200);
73
+ expect(scdTableData[1]?.length).toBeGreaterThan(200);
74
+ expect(userProfilesData.length).toBe(100);
75
+
76
+ }, timeout);
77
+
78
+ test('works as module (mirror)', async () => {
79
+ console.log('MODULE TEST: MIRROR');
80
+ const results = await generate({ ...mirror, verbose: true, writeToDisk: false, numEvents: 1100, numUsers: 100, seed: "deal with it" });
81
+ const { eventData, userProfilesData, mirrorEventData } = results;
82
+ expect(eventData.length).toBeGreaterThan(980);
83
+ expect(mirrorEventData.length).toBeGreaterThan(980);
84
+ expect(mirrorEventData.every(e => e.newlyCreated)).toBe(true);
85
+ expect(eventData.every(e => e.newlyCreated)).toBe(false);
66
86
  expect(userProfilesData.length).toBe(100);
67
87
 
68
88
  }, timeout);
69
89
 
90
+ test('works as module (foobar)', async () => {
91
+ console.log('MODULE TEST: FOOBAR');
92
+ const results = await generate({ ...foobar, verbose: true, writeToDisk: false, numEvents: 1100, numUsers: 100, seed: "deal with it" });
93
+ const { eventData, userProfilesData } = results;
94
+ expect(eventData.length).toBeGreaterThan(980);
95
+ expect(userProfilesData.length).toBe(100);
96
+
97
+ }, timeout);
98
+
99
+ test('works as module (adspend)', async () => {
100
+ console.log('MODULE TEST: ADSPEND');
101
+ const results = await generate({ ...adspend, verbose: true, writeToDisk: false, numEvents: 1100, numUsers: 100, seed: "deal with it" });
102
+ const { eventData, adSpendData, userProfilesData } = results;
103
+ expect(eventData.length).toBeGreaterThan(980);
104
+ expect(userProfilesData.length).toBe(100);
105
+ expect(adSpendData.length).toBe(14600);
106
+
107
+ }, timeout);
108
+
109
+
70
110
  test('fails with invalid configuration', async () => {
71
111
  try {
72
112
  await generate({ numUsers: -10 });
@@ -78,83 +118,210 @@ describe('module', () => {
78
118
 
79
119
  test('works with no params', async () => {
80
120
  const { eventData, userProfilesData, groupProfilesData, files, importResults, lookupTableData, mirrorEventData, scdTableData } = await generate({ writeToDisk: false });
81
- debugger;
121
+ expect(eventData.length).toBeGreaterThan(100000);
122
+ expect(userProfilesData.length).toBe(1000);
123
+ expect(groupProfilesData.length).toBe(0);
124
+ expect(importResults).toBe(undefined);
125
+ expect(scdTableData.length).toBe(0);
126
+ expect(lookupTableData.length).toBe(0);
127
+ expect(mirrorEventData.length).toBe(0);
82
128
  }, timeout);
83
129
 
84
130
 
85
131
 
86
132
 
133
+ });
134
+
135
+ describe('batching', () => {
136
+ test('batch writes', async () => {
137
+ const results = await generate({ ...foobar, batchSize: 1000, writeToDisk: true, numEvents: 10_000, numUsers: 5000, seed: "deal" });
138
+ const { eventData, userProfilesData } = results;
139
+ const files = (await u.ls('./data')).filter(a => a.endsWith('.json'));
140
+ const eventFiles = files.filter(a => a.includes('EVENTS'));
141
+ const userFiles = files.filter(a => a.includes('USERS'));
142
+ const evWriteDir = eventData.getWriteDir();
143
+ const usWriteDir = userProfilesData.getWriteDir();
144
+ const evWritePath = eventData.getWritePath();
145
+ const usWritePath = userProfilesData.getWritePath();
146
+
147
+ const expectedEvWriteDir = `-EVENTS.json`;
148
+ const expectedUsWriteDir = `-USERS.json`;
149
+ const expectedWritePath = `-part-`;
150
+
151
+ expect(eventFiles.length).toBe(23);
152
+ expect(userFiles.length).toBe(5);
153
+
154
+ expect(eventFiles.filter(a => a.includes('part')).length).toBe(23);
155
+ expect(userFiles.filter(a => a.includes('part')).length).toBe(5);
156
+ expect(evWriteDir.endsWith(expectedEvWriteDir)).toBe(true);
157
+ expect(usWriteDir.endsWith(expectedUsWriteDir)).toBe(true);
158
+ expect(evWritePath.includes(expectedWritePath)).toBe(true);
159
+ expect(usWritePath.includes(expectedWritePath)).toBe(true);
160
+
161
+ }, timeout);
162
+
163
+
164
+ test('dont batch', async () => {
165
+ const results = await generate({ ...foobar, writeToDisk: true, numEvents: 5000, numUsers: 1000, seed: "deal" });
166
+ const { eventData, userProfilesData } = results;
167
+ const files = await u.ls('./data');
168
+ const eventFiles = files.filter(a => a.includes('EVENTS'));
169
+ const userFiles = files.filter(a => a.includes('USERS'));
170
+ expect(eventFiles.length).toBe(1);
171
+ expect(userFiles.length).toBe(1);
172
+ expect(eventFiles.filter(a => a.includes('part')).length).toBe(0);
173
+ const evWriteDir = eventData.getWriteDir();
174
+ const usWriteDir = userProfilesData.getWriteDir();
175
+ const expectedEvWriteDir = `-EVENTS.json`;
176
+ const expectedUsWriteDir = `-USERS.json`;
177
+ expect(evWriteDir.endsWith(expectedEvWriteDir)).toBe(true);
178
+ expect(usWriteDir.endsWith(expectedUsWriteDir)).toBe(true);
179
+
180
+ const evWritePath = eventData.getWritePath();
181
+ const usWritePath = userProfilesData.getWritePath();
182
+ expect(evWritePath.endsWith(expectedEvWriteDir)).toBe(true);
183
+ expect(usWritePath.endsWith(expectedUsWriteDir)).toBe(true);
184
+
185
+ }, timeout);
186
+
187
+ test('send to mp: batches', async () => {
188
+ const results = await generate({ ...foobar, numDays: 90, hasAdSpend: true, token: testToken, batchSize: 4500, writeToDisk: true, numEvents: 10_000, numUsers: 5000, seed: "deal" });
189
+ const { importResults } = results;
190
+ const { adSpend, events, groups, users } = importResults;
191
+ expect(adSpend.success).toBeGreaterThan(0);
192
+ expect(events.success).toBeGreaterThan(0);
193
+ expect(users.success).toBeGreaterThan(0);
194
+ expect(groups[0].success).toBeGreaterThan(0);
195
+ expect(groups[1].success).toBeGreaterThan(0);
196
+ expect(adSpend.success).toBe(adSpend.total);
197
+ expect(events.success).toBe(events.total);
198
+ // expect(users.success).toBe(users.total);
199
+ expect(groups.length).toBe(2);
200
+ expect(groups[0].success).toBe(groups[0].total);
201
+ expect(groups[1].success).toBe(groups[1].total);
202
+ expect(adSpend.failed).toBe(0);
203
+ expect(events.failed).toBe(0);
204
+ expect(users.failed).toBe(0);
205
+ expect(groups[0].failed).toBe(0);
206
+ expect(groups[1].failed).toBe(0);
207
+
208
+
209
+ }, timeout);
210
+
211
+ test('send to mp: no batch', async () => {
212
+ const results = await generate({ ...foobar, numDays: 90, hasAdSpend: true, token: testToken, writeToDisk: true, numEvents: 5000, numUsers: 1000, seed: "deal" });
213
+ const { importResults } = results;
214
+ const { adSpend, events, groups, users } = importResults;
215
+ expect(adSpend.success).toBeGreaterThan(0);
216
+ expect(events.success).toBeGreaterThan(0);
217
+ expect(users.success).toBeGreaterThan(0);
218
+ expect(groups[0].success).toBeGreaterThan(0);
219
+ expect(groups[1].success).toBeGreaterThan(0);
220
+ expect(adSpend.success).toBe(adSpend.total);
221
+ expect(events.success).toBe(events.total);
222
+ expect(users.success).toBe(users.total);
223
+ expect(groups.length).toBe(2);
224
+ expect(groups[0].success).toBe(groups[0].total);
225
+ expect(groups[1].success).toBe(groups[1].total);
226
+ expect(adSpend.failed).toBe(0);
227
+ expect(events.failed).toBe(0);
228
+ expect(users.failed).toBe(0);
229
+ expect(groups[0].failed).toBe(0);
230
+ expect(groups[1].failed).toBe(0);
231
+
232
+ }, timeout);
87
233
  });
88
234
 
89
235
  describe('cli', () => {
90
- test('works as CLI (no args)', async () => {
91
- console.log('COMPLEX CLI TEST');
92
- const run = execSync(`node ./core/index.js --numEvents 1000 --numUsers 100`, { stdio: 'ignore' });
93
- // expect(run.toString().trim().includes('have a wonderful day :)')).toBe(true);
236
+
237
+ test('sanity check', async () => {
238
+ console.log('SANITY TEST');
239
+ const run = execSync(`node ./index.js`);
240
+ const ending = `enjoy your data! :)`;
241
+ expect(run.toString().trim().endsWith(ending)).toBe(true);
242
+ const files = (await u.ls('./data')).filter(a => a.includes('.csv'));
243
+ expect(files.length).toBe(2);
244
+ const users = files.filter(a => a.includes('USERS'));
245
+ const events = files.filter(a => a.includes('EVENTS'));
246
+ expect(users.length).toBe(1);
247
+ expect(events.length).toBe(1);
248
+ const eventData = (await u.load(events[0])).trim();
249
+ const userProfilesData = (await u.load(users[0])).trim();
250
+ const parsedEvents = Papa.parse(eventData, { header: true }).data;
251
+ const parsedUsers = Papa.parse(userProfilesData, { header: true }).data;
252
+ expect(parsedEvents.length).toBeGreaterThan(42000);
253
+ expect(parsedUsers.length).toBeGreaterThan(420);
254
+ expect(parsedUsers.every(u => u.distinct_id)).toBe(true);
255
+ expect(parsedEvents.every(e => e.event)).toBe(true);
256
+ expect(parsedEvents.every(e => e.time)).toBe(true);
257
+ expect(parsedEvents.every(e => e.insert_id)).toBe(true);
258
+ expect(parsedEvents.every(e => e.device_id || e.user_id)).toBe(true);
259
+ expect(parsedUsers.every(u => u.name)).toBe(true);
260
+ expect(parsedUsers.every(u => u.email)).toBe(true);
261
+ expect(parsedUsers.every(u => u.created)).toBe(true);
262
+ expect(parsedUsers.every(u => u.avatar)).toBe(false);
263
+ expect(parsedEvents.every(e => validateEvent(e))).toBe(true);
264
+ expect(parsedUsers.every(u => validateUser(u))).toBe(true);
265
+ }, timeout);
266
+
267
+ test('no args', async () => {
268
+ console.log('BARE CLI TEST');
269
+ const run = execSync(`node ./index.js --numEvents 1000 --numUsers 100`);
270
+ expect(run.toString().trim().includes('enjoy your data! :)')).toBe(true);
94
271
  const csvs = (await u.ls('./data')).filter(a => a.includes('.csv'));
95
- expect(csvs.length).toBe(4);
96
- clearData();
272
+ expect(csvs.length).toBe(2);
273
+
97
274
  }, timeout);
98
275
 
99
- test('works as CLI (complex)', async () => {
276
+ test('--complex', async () => {
100
277
  console.log('COMPLEX CLI TEST');
101
- const run = execSync(`node ./core/index.js --numEvents 1000 --numUsers 100 --seed "deal with it" --complex`, { stdio: 'ignore' });
102
- // expect(run.toString().trim().includes('have a wonderful day :)')).toBe(true);
278
+ const run = execSync(`node ./index.js --numEvents 1000 --numUsers 100 --seed "deal with it" --complex`, { stdio: "ignore" });
103
279
  const csvs = (await u.ls('./data')).filter(a => a.includes('.csv'));
104
280
  expect(csvs.length).toBe(13);
105
- clearData();
281
+
106
282
  }, timeout);
107
283
 
108
- test('works as CLI (simple)', async () => {
109
- console.log('simple CLI TEST');
110
- const run = execSync(`node ./core/index.js --numEvents 1000 --numUsers 100 --seed "deal with it" --simple`);
111
- expect(run.toString().trim().includes('have a wonderful day :)')).toBe(true);
284
+ test('--simple', async () => {
285
+ console.log('SIMPLE CLI TEST');
286
+ const run = execSync(`node ./index.js --numEvents 1000 --numUsers 100 --seed "deal with it" --simple`);
287
+ expect(run.toString().trim().includes('enjoy your data! :)')).toBe(true);
112
288
  const csvs = (await u.ls('./data')).filter(a => a.includes('.csv'));
113
- expect(csvs.length).toBe(4);
114
- clearData();
289
+ expect(csvs.length).toBe(2);
290
+
115
291
  }, timeout);
116
292
 
117
- test('works as CLI (custom)', async () => {
118
- console.log('custom CLI TEST');
119
- const run = execSync(`node ./core/index.js ./schemas/deepNest.js`);
120
- expect(run.toString().trim().includes('have a wonderful day :)')).toBe(true);
121
- const csvs = (await u.ls('./data')).filter(a => a.includes('.csv'));
122
- expect(csvs.length).toBe(3);
123
- clearData();
124
- }, timeout);
125
293
 
126
294
  });
127
295
 
128
-
129
296
  describe('options + tweaks', () => {
130
297
  test('creates sessionIds', async () => {
131
- const results = await generate({ writeToDisk: false, numEvents: 1000, numUsers: 100, sessionIds: true });
298
+ const results = await generate({ writeToDisk: false, numEvents: 1000, numUsers: 100, hasSessionIds: true });
132
299
  const { eventData } = results;
133
300
  const sessionIds = eventData.map(a => a.session_id).filter(a => a);
134
301
  expect(sessionIds.length).toBe(eventData.length);
135
302
  }, timeout);
136
303
 
137
- test('no sessionIds', async () => {
138
- const results = await generate({ writeToDisk: false, numEvents: 1000, numUsers: 100, sessionIds: false });
304
+ test('no hasSessionIds', async () => {
305
+ const results = await generate({ writeToDisk: false, numEvents: 1000, numUsers: 100, hasSessionIds: false });
139
306
  const { eventData } = results;
140
- const sessionIds = eventData.map(a => a.session_id).filter(a => a);
141
- expect(sessionIds.length).toBe(0);
307
+ const noSessionIds = eventData.map(a => a.session_id).filter(a => a);
308
+ expect(noSessionIds.length).toBe(0);
142
309
  }, timeout);
143
310
 
144
311
  test('creates anonymousIds', async () => {
145
- const results = await generate({ writeToDisk: false, numEvents: 1000, numUsers: 100, anonIds: true });
312
+ const results = await generate({ writeToDisk: false, numEvents: 1000, numUsers: 100, hasAnonIds: true });
146
313
  const { eventData } = results;
147
- const anonIds = eventData.map(a => a.device_id).filter(a => a);
314
+ const anonymousEvents = eventData.map(a => a.device_id).filter(a => a);
148
315
  const userIds = eventData.map(a => a.user_id).filter(a => a);
149
- expect(anonIds.length).toBe(eventData.length);
150
- expect(userIds.length).toBeLessThan(anonIds.length);
316
+ expect(anonymousEvents.length).toBe(eventData.length);
317
+ expect(userIds.length).toBeLessThan(anonymousEvents.length);
151
318
  }, timeout);
152
319
 
153
320
  test('no anonymousIds', async () => {
154
- const results = await generate({ writeToDisk: false, numEvents: 1000, numUsers: 100, anonIds: false });
321
+ const results = await generate({ writeToDisk: false, numEvents: 1000, numUsers: 100, hasAnonIds: false });
155
322
  const { eventData } = results;
156
- const anonIds = eventData.map(a => a.device_id).filter(a => a);
157
- expect(anonIds.length).toBe(0);
323
+ const unanonymousEvents = eventData.map(a => a.device_id).filter(a => a);
324
+ expect(unanonymousEvents.length).toBe(0);
158
325
  }, timeout);
159
326
 
160
327
  test('sends data to mixpanel', async () => {
@@ -168,7 +335,7 @@ describe('options + tweaks', () => {
168
335
 
169
336
  test('every record is valid', async () => {
170
337
  console.log('VALIDATION TEST');
171
- const results = await generate({ verbose: true, writeToDisk: false, numEvents: 10000, numUsers: 500 });
338
+ const results = await generate({ verbose: true, writeToDisk: false, numEvents: 1000, numUsers: 100 });
172
339
  const { eventData, userProfilesData } = results;
173
340
  const areEventsValid = eventData.every(validateEvent);
174
341
  const areUsersValid = userProfilesData.every(validateUser);
@@ -182,24 +349,44 @@ describe('options + tweaks', () => {
182
349
 
183
350
  test('every date is valid', async () => {
184
351
  console.log('DATE TEST');
185
- const results = await generate({ ...simple, writeToDisk: false, verbose: true });
352
+ const results = await generate({ ...simple, writeToDisk: false, verbose: true, numEvents: 1000, numUsers: 100 });
186
353
  const { eventData } = results;
187
- const invalidDates = eventData.filter(e => !validateTime(e.time));
188
- expect(eventData.every(e => validateTime(e.time))).toBe(true);
354
+ const invalidDates = eventData.filter(e => !validTime(e.time));
355
+ expect(eventData.every(e => validTime(e.time))).toBe(true);
189
356
 
190
357
  }, timeout);
191
358
 
192
359
  test('anonymous users', async () => {
193
360
  console.log('ANON TEST');
194
- const results = await generate({ ...anon, writeToDisk: false, verbose: true });
361
+ const results = await generate({ ...anon, writeToDisk: false, verbose: true, numEvents: 1000, numUsers: 100 });
195
362
  const { userProfilesData } = results;
196
363
  expect(userProfilesData.every(u => u.name === 'Anonymous User')).toBe(true);
197
364
 
198
365
  }, timeout);
199
366
 
367
+ test('no avatars (default)', async () => {
368
+ console.log('AVATAR TEST');
369
+ const results = await generate({ ...simple, writeToDisk: false, verbose: true, numEvents: 1000, numUsers: 100 });
370
+ const { userProfilesData } = results;
371
+ expect(userProfilesData.every(u => !u.avatar)).toBe(true);
372
+
373
+ }, timeout);
374
+
375
+ test('yes avatars', async () => {
376
+ console.log('AVATAR TEST');
377
+ const results = await generate({ ...simple, writeToDisk: false, verbose: true, numEvents: 1000, numUsers: 100, hasAvatar: true });
378
+ const { userProfilesData } = results;
379
+ expect(userProfilesData.every(u => u.avatar)).toBe(true);
380
+
381
+ }, timeout);
382
+
383
+ });
384
+
385
+ beforeEach(() => {
386
+ clearData();
200
387
  });
201
388
 
202
- afterAll(() => {
389
+ afterEach(() => {
203
390
  clearData();
204
391
  });
205
392
 
@@ -234,7 +421,7 @@ function validateUser(user) {
234
421
  }
235
422
 
236
423
 
237
- function validateTime(str) {
424
+ function validTime(str) {
238
425
  if (!str) return false;
239
426
  if (str.startsWith('-')) return false;
240
427
  if (!str.startsWith('20')) return false;