make-mp-data 1.1.17 → 1.1.19
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/index.js +14 -9
- package/package.json +1 -1
- package/tests/e2e.test.js +23 -4
- package/utils.js +55 -48
package/index.js
CHANGED
|
@@ -22,22 +22,20 @@ const {
|
|
|
22
22
|
makeProducts,
|
|
23
23
|
date,
|
|
24
24
|
progress,
|
|
25
|
-
person,
|
|
26
25
|
choose,
|
|
27
26
|
range,
|
|
28
27
|
exhaust,
|
|
29
28
|
openFinder,
|
|
30
29
|
applySkew,
|
|
31
30
|
boxMullerRandom,
|
|
32
|
-
getUniqueKeys
|
|
31
|
+
getUniqueKeys,
|
|
32
|
+
person
|
|
33
33
|
} = require("./utils.js");
|
|
34
34
|
const dayjs = require("dayjs");
|
|
35
35
|
const utc = require("dayjs/plugin/utc");
|
|
36
36
|
dayjs.extend(utc);
|
|
37
37
|
const cliParams = require("./cli.js");
|
|
38
38
|
const { makeName, md5 } = require('ak-tools');
|
|
39
|
-
|
|
40
|
-
Array.prototype.pickOne = pick;
|
|
41
39
|
const NOW = dayjs().unix();
|
|
42
40
|
let VERBOSE = false;
|
|
43
41
|
|
|
@@ -329,6 +327,9 @@ async function main(config) {
|
|
|
329
327
|
};
|
|
330
328
|
}
|
|
331
329
|
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
|
|
332
333
|
function makeProfile(props, defaults) {
|
|
333
334
|
//build the spec
|
|
334
335
|
const profile = {
|
|
@@ -378,7 +379,7 @@ function makeSCD(props, distinct_id, mutations, $created) {
|
|
|
378
379
|
* @param {Boolean} isFirstEvent=false
|
|
379
380
|
*/
|
|
380
381
|
function makeEvent(distinct_id, anonymousIds, sessionIds, earliestTime, events, superProps, groupKeys, isFirstEvent = false) {
|
|
381
|
-
let chosenEvent =
|
|
382
|
+
let chosenEvent = chance.pickone(events);
|
|
382
383
|
|
|
383
384
|
//allow for a string shorthand
|
|
384
385
|
if (typeof chosenEvent === "string") {
|
|
@@ -422,7 +423,7 @@ function makeEvent(distinct_id, anonymousIds, sessionIds, earliestTime, events,
|
|
|
422
423
|
const groupKey = groupPair[0];
|
|
423
424
|
const groupCardinality = groupPair[1];
|
|
424
425
|
|
|
425
|
-
event[groupKey] = weightedRange(1, groupCardinality)
|
|
426
|
+
event[groupKey] = pick(weightedRange(1, groupCardinality))
|
|
426
427
|
}
|
|
427
428
|
|
|
428
429
|
//make $insert_id
|
|
@@ -479,8 +480,8 @@ function AKsTimeSoup(earliestTime, latestTime = NOW, peakDays = PEAK_DAYS) {
|
|
|
479
480
|
|
|
480
481
|
if (typeof earliestTime !== "number") {
|
|
481
482
|
if (parseInt(earliestTime) > 0) earliestTime = parseInt(earliestTime);
|
|
482
|
-
if (dayjs(earliestTime).isValid()) earliestTime = dayjs(earliestTime).unix();
|
|
483
|
-
}
|
|
483
|
+
if (dayjs(earliestTime).isValid()) earliestTime = dayjs(earliestTime).unix();
|
|
484
|
+
}
|
|
484
485
|
|
|
485
486
|
while (!validTime) {
|
|
486
487
|
|
|
@@ -506,7 +507,7 @@ function AKsTimeSoup(earliestTime, latestTime = NOW, peakDays = PEAK_DAYS) {
|
|
|
506
507
|
// Generate a random time within business hours with a higher concentration in the middle of the period
|
|
507
508
|
const businessStart = dayjs.unix(selectedDay).hour(peakStartHour).minute(0).second(0).unix();
|
|
508
509
|
const businessEnd = dayjs.unix(selectedDay).hour(peakEndHour).minute(0).second(0).unix();
|
|
509
|
-
|
|
510
|
+
|
|
510
511
|
if (selectedDay === peakDays[0]) {
|
|
511
512
|
// Use a skewed distribution for peak days
|
|
512
513
|
eventTime = chance.normal({ mean: (businessEnd + businessStart) / integer(1, 4), dev: (businessEnd - businessStart) / integer(2, 8) });
|
|
@@ -519,9 +520,13 @@ function AKsTimeSoup(earliestTime, latestTime = NOW, peakDays = PEAK_DAYS) {
|
|
|
519
520
|
if (chance.bool({ likelihood: 42 })) eventTime = Math.min(Math.max(eventTime, businessStart), businessEnd);
|
|
520
521
|
|
|
521
522
|
if (eventTime > 0) validTime = true;
|
|
523
|
+
const parsedTime = dayjs.unix(eventTime).toISOString();
|
|
524
|
+
if (!parsedTime.startsWith('20')) validTime = false;
|
|
522
525
|
|
|
523
526
|
}
|
|
524
527
|
chosenTime = dayjs.unix(eventTime).toISOString();
|
|
528
|
+
if (eventTime < 0) debugger;
|
|
529
|
+
if (!chosenTime.startsWith('20')) debugger;
|
|
525
530
|
return chosenTime;
|
|
526
531
|
}
|
|
527
532
|
|
package/package.json
CHANGED
package/tests/e2e.test.js
CHANGED
|
@@ -8,6 +8,8 @@ require('dotenv').config();
|
|
|
8
8
|
const { execSync } = require("child_process");
|
|
9
9
|
const u = require('ak-tools');
|
|
10
10
|
|
|
11
|
+
const simple = require('../examples/simple');
|
|
12
|
+
|
|
11
13
|
const timeout = 60000;
|
|
12
14
|
const testToken = process.env.TEST_TOKEN;
|
|
13
15
|
|
|
@@ -16,7 +18,7 @@ describe('e2e', () => {
|
|
|
16
18
|
|
|
17
19
|
test('works as module', async () => {
|
|
18
20
|
console.log('MODULE TEST');
|
|
19
|
-
const results = await generate({ writeToDisk: false, numEvents: 1100, numUsers: 100, seed: "deal with it" });
|
|
21
|
+
const results = await generate({ verbose: false, writeToDisk: false, numEvents: 1100, numUsers: 100, seed: "deal with it" });
|
|
20
22
|
const { eventData, groupProfilesData, lookupTableData, scdTableData, userProfilesData } = results;
|
|
21
23
|
expect(eventData.length).toBeGreaterThan(980);
|
|
22
24
|
expect(groupProfilesData.length).toBe(0);
|
|
@@ -28,7 +30,7 @@ describe('e2e', () => {
|
|
|
28
30
|
|
|
29
31
|
test('works as CLI', async () => {
|
|
30
32
|
console.log('CLI TEST');
|
|
31
|
-
const run = execSync(`node ./index.js --numEvents 1000 --numUsers 100 --seed "deal with it"`);
|
|
33
|
+
const run = execSync(`node ./index.js --numEvents 1000 --numUsers 100 --seed "deal with it" --verbose false`);
|
|
32
34
|
expect(run.toString().trim().includes('have a wonderful day :)')).toBe(true);
|
|
33
35
|
const csvs = (await u.ls('./data')).filter(a => a.includes('.csv'));
|
|
34
36
|
expect(csvs.length).toBe(5);
|
|
@@ -36,7 +38,7 @@ describe('e2e', () => {
|
|
|
36
38
|
|
|
37
39
|
test('sends data to mixpanel', async () => {
|
|
38
40
|
console.log('NETWORK TEST');
|
|
39
|
-
const results = await generate({ writeToDisk: false, numEvents: 1100, numUsers: 100, seed: "deal with it", token: testToken });
|
|
41
|
+
const results = await generate({verbose: false, writeToDisk: false, numEvents: 1100, numUsers: 100, seed: "deal with it", token: testToken });
|
|
40
42
|
const { events, users, groups } = results.import;
|
|
41
43
|
expect(events.success).toBeGreaterThan(980);
|
|
42
44
|
expect(users.success).toBe(100);
|
|
@@ -45,7 +47,7 @@ describe('e2e', () => {
|
|
|
45
47
|
|
|
46
48
|
test('every record is valid', async () => {
|
|
47
49
|
console.log('VALIDATION TEST');
|
|
48
|
-
const results = await generate({ writeToDisk: false, numEvents: 10000, numUsers: 500 });
|
|
50
|
+
const results = await generate({verbose: false, writeToDisk: false, numEvents: 10000, numUsers: 500 });
|
|
49
51
|
const { eventData, userProfilesData } = results;
|
|
50
52
|
const areEventsValid = eventData.every(validateEvent);
|
|
51
53
|
const areUsersValid = userProfilesData.every(validateUser);
|
|
@@ -57,6 +59,15 @@ describe('e2e', () => {
|
|
|
57
59
|
expect(areUsersValid).toBe(true);
|
|
58
60
|
}, timeout);
|
|
59
61
|
|
|
62
|
+
test('every date is valid', async () => {
|
|
63
|
+
console.log('DATE TEST');
|
|
64
|
+
const results = await generate({ ...simple, writeToDisk: false, verbose: false });
|
|
65
|
+
const { eventData } = results;
|
|
66
|
+
const invalidDates = eventData.filter(e => !validateTime(e.time));
|
|
67
|
+
expect(eventData.every(e => validateTime(e.time))).toBe(true);
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
}, timeout)
|
|
60
71
|
|
|
61
72
|
});
|
|
62
73
|
|
|
@@ -128,4 +139,12 @@ function validateUser(user) {
|
|
|
128
139
|
if (!user.$email) return false;
|
|
129
140
|
if (!user.$created) return false;
|
|
130
141
|
return true;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
function validateTime(str) {
|
|
146
|
+
if (!str) return false;
|
|
147
|
+
if (str.startsWith('-')) return false;
|
|
148
|
+
if (!str.startsWith('20')) return false;
|
|
149
|
+
return true;
|
|
131
150
|
}
|
package/utils.js
CHANGED
|
@@ -7,18 +7,23 @@ const dayjs = require('dayjs');
|
|
|
7
7
|
const utc = require('dayjs/plugin/utc');
|
|
8
8
|
dayjs.extend(utc);
|
|
9
9
|
|
|
10
|
-
function pick() {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
function pick(items) {
|
|
11
|
+
if (!Array.isArray(items)) {
|
|
12
|
+
try {
|
|
13
|
+
const choice = chance.pickone(this);
|
|
14
|
+
return choice;
|
|
15
|
+
}
|
|
16
|
+
catch (e) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
17
19
|
}
|
|
20
|
+
return chance.pickone(items);
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
function date(inTheLast = 30, isPast = true, format = 'YYYY-MM-DD') {
|
|
21
24
|
const now = dayjs.utc();
|
|
25
|
+
// dates must be in the the last 10 years
|
|
26
|
+
if (Math.abs(inTheLast) > 365 * 10) inTheLast = chance.integer({ min: 1, max: 180 });
|
|
22
27
|
return function () {
|
|
23
28
|
try {
|
|
24
29
|
const when = chance.integer({ min: 0, max: Math.abs(inTheLast) });
|
|
@@ -216,48 +221,8 @@ function progress(thing, p) {
|
|
|
216
221
|
process.stdout.write(`${thing} processed ... ${comma(p)}`);
|
|
217
222
|
}
|
|
218
223
|
|
|
219
|
-
function person(bornDaysAgo = 30) {
|
|
220
|
-
//names and photos
|
|
221
|
-
const gender = chance.pickone(['male', 'female']);
|
|
222
|
-
const first = chance.first({ gender });
|
|
223
|
-
const last = chance.last();
|
|
224
|
-
const $name = `${first} ${last}`;
|
|
225
|
-
const $email = `${first[0]}.${last}@${chance.domain()}.com`;
|
|
226
|
-
const avatarPrefix = `https://randomuser.me/api/portraits`;
|
|
227
|
-
const randomAvatarNumber = chance.integer({
|
|
228
|
-
min: 1,
|
|
229
|
-
max: 99
|
|
230
|
-
});
|
|
231
|
-
const avPath = gender === 'male' ? `/men/${randomAvatarNumber}.jpg` : `/women/${randomAvatarNumber}.jpg`;
|
|
232
|
-
const $avatar = avatarPrefix + avPath;
|
|
233
|
-
const $created = date(bornDaysAgo, true, null)();
|
|
234
|
-
|
|
235
|
-
//anon Ids
|
|
236
|
-
const anonymousIds = [];
|
|
237
|
-
const clusterSize = integer(2, 10);
|
|
238
|
-
for (let i = 0; i < clusterSize; i++) {
|
|
239
|
-
anonymousIds.push(uid(42));
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
//session Ids
|
|
243
|
-
const sessionIds = [];
|
|
244
|
-
const sessionSize = integer(5, 30);
|
|
245
|
-
for (let i = 0; i < sessionSize; i++) {
|
|
246
|
-
sessionIds.push([uid(5), uid(5), uid(5), uid(5)].join("-"));
|
|
247
|
-
}
|
|
248
|
-
|
|
249
224
|
|
|
250
225
|
|
|
251
|
-
return {
|
|
252
|
-
$name,
|
|
253
|
-
$email,
|
|
254
|
-
$avatar,
|
|
255
|
-
$created,
|
|
256
|
-
anonymousIds,
|
|
257
|
-
sessionIds
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
|
|
261
226
|
function range(a, b, step = 1) {
|
|
262
227
|
step = !step ? 1 : step;
|
|
263
228
|
b = b / step;
|
|
@@ -368,6 +333,48 @@ function generateName() {
|
|
|
368
333
|
|
|
369
334
|
}
|
|
370
335
|
|
|
336
|
+
function person(bornDaysAgo = 30) {
|
|
337
|
+
//names and photos
|
|
338
|
+
const gender = chance.pickone(['male', 'female']);
|
|
339
|
+
const first = chance.first({ gender });
|
|
340
|
+
const last = chance.last();
|
|
341
|
+
const $name = `${first} ${last}`;
|
|
342
|
+
const $email = `${first[0]}.${last}@${chance.domain()}.com`;
|
|
343
|
+
const avatarPrefix = `https://randomuser.me/api/portraits`;
|
|
344
|
+
const randomAvatarNumber = chance.integer({
|
|
345
|
+
min: 1,
|
|
346
|
+
max: 99
|
|
347
|
+
});
|
|
348
|
+
const avPath = gender === 'male' ? `/men/${randomAvatarNumber}.jpg` : `/women/${randomAvatarNumber}.jpg`;
|
|
349
|
+
const $avatar = avatarPrefix + avPath;
|
|
350
|
+
const $created = date(bornDaysAgo, true, null)();
|
|
351
|
+
|
|
352
|
+
//anon Ids
|
|
353
|
+
const anonymousIds = [];
|
|
354
|
+
const clusterSize = integer(2, 10);
|
|
355
|
+
for (let i = 0; i < clusterSize; i++) {
|
|
356
|
+
anonymousIds.push(uid(42));
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
//session Ids
|
|
360
|
+
const sessionIds = [];
|
|
361
|
+
const sessionSize = integer(5, 30);
|
|
362
|
+
for (let i = 0; i < sessionSize; i++) {
|
|
363
|
+
sessionIds.push([uid(5), uid(5), uid(5), uid(5)].join("-"));
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
return {
|
|
369
|
+
$name,
|
|
370
|
+
$email,
|
|
371
|
+
$avatar,
|
|
372
|
+
$created,
|
|
373
|
+
anonymousIds,
|
|
374
|
+
sessionIds
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
|
|
371
378
|
module.exports = {
|
|
372
379
|
weightedRange,
|
|
373
380
|
pick,
|
|
@@ -376,7 +383,6 @@ module.exports = {
|
|
|
376
383
|
makeProducts,
|
|
377
384
|
date,
|
|
378
385
|
progress,
|
|
379
|
-
person,
|
|
380
386
|
choose,
|
|
381
387
|
range,
|
|
382
388
|
exhaust,
|
|
@@ -387,4 +393,5 @@ module.exports = {
|
|
|
387
393
|
getUniqueKeys,
|
|
388
394
|
makeHashTags,
|
|
389
395
|
generateName,
|
|
396
|
+
person
|
|
390
397
|
};
|