make-mp-data 1.5.55 → 2.0.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/.claude/settings.local.json +20 -0
- package/.gcloudignore +2 -1
- package/.vscode/launch.json +6 -3
- package/.vscode/settings.json +31 -2
- package/dungeons/media.js +371 -0
- package/index.js +354 -1757
- package/{components → lib/cli}/cli.js +21 -6
- package/lib/cloud-function.js +20 -0
- package/lib/core/config-validator.js +248 -0
- package/lib/core/context.js +180 -0
- package/lib/core/storage.js +268 -0
- package/{components → lib/data}/defaults.js +17 -14
- package/lib/generators/adspend.js +133 -0
- package/lib/generators/events.js +242 -0
- package/lib/generators/funnels.js +330 -0
- package/lib/generators/mirror.js +168 -0
- package/lib/generators/profiles.js +93 -0
- package/lib/generators/scd.js +102 -0
- package/lib/orchestrators/mixpanel-sender.js +222 -0
- package/lib/orchestrators/user-loop.js +194 -0
- package/lib/orchestrators/worker-manager.js +200 -0
- package/{components → lib/utils}/ai.js +8 -36
- package/{components → lib/utils}/chart.js +9 -9
- package/{components → lib/utils}/project.js +4 -4
- package/{components → lib/utils}/utils.js +35 -23
- package/package.json +19 -12
- package/scripts/dana.mjs +137 -0
- package/scripts/new-dungeon.sh +7 -6
- package/scripts/update-deps.sh +2 -1
- package/tests/cli.test.js +28 -25
- package/tests/e2e.test.js +38 -36
- package/tests/int.test.js +151 -56
- package/tests/testSoup.mjs +1 -1
- package/tests/unit.test.js +15 -14
- package/tsconfig.json +1 -1
- package/types.d.ts +76 -18
- package/vitest.config.js +47 -0
- package/dungeons/adspend.js +0 -96
- package/dungeons/anon.js +0 -104
- package/dungeons/big.js +0 -224
- package/dungeons/business.js +0 -327
- package/dungeons/complex.js +0 -396
- package/dungeons/foobar.js +0 -241
- package/dungeons/funnels.js +0 -220
- package/dungeons/gaming-experiments.js +0 -323
- package/dungeons/gaming.js +0 -314
- package/dungeons/governance.js +0 -288
- package/dungeons/mirror.js +0 -129
- package/dungeons/sanity.js +0 -118
- package/dungeons/scd.js +0 -205
- package/dungeons/session-replay.js +0 -175
- package/dungeons/simple.js +0 -150
- package/dungeons/userAgent.js +0 -190
- package/log.json +0 -1067
- package/tests/jest.config.js +0 -47
- /package/{components → lib/utils}/prompt.txt +0 -0
package/scripts/dana.mjs
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { fork } from 'child_process';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import dotenv from "dotenv";
|
|
5
|
+
dotenv.config();
|
|
6
|
+
const { NODE_ENV = "unknown" } = process.env;
|
|
7
|
+
|
|
8
|
+
import main from "../index.js";
|
|
9
|
+
import simple from '../dungeons/simple.js';
|
|
10
|
+
import complex from '../dungeons/complex.js';
|
|
11
|
+
import gaming from '../dungeons/customers/gaming.js';
|
|
12
|
+
import big from '../dungeons/big.js';
|
|
13
|
+
|
|
14
|
+
import Chance from 'chance';
|
|
15
|
+
const chance = new Chance();
|
|
16
|
+
const twentyFivePercent = () => chance.bool({ likelihood: 25 });
|
|
17
|
+
|
|
18
|
+
// --- shared options ---
|
|
19
|
+
let divisor = 1;
|
|
20
|
+
if (NODE_ENV === "dev") divisor = 1000;
|
|
21
|
+
|
|
22
|
+
const commonOptions = {
|
|
23
|
+
numEvents: 10_000_000 / divisor,
|
|
24
|
+
numUsers: 10_000_000 / 100 / divisor,
|
|
25
|
+
batchSize: 200_000,
|
|
26
|
+
hasAdSpend: false,
|
|
27
|
+
hasAnonIds: true,
|
|
28
|
+
hasSessionIds: true,
|
|
29
|
+
format: "json",
|
|
30
|
+
hasDesktopDevices: true,
|
|
31
|
+
hasIOSDevices: true,
|
|
32
|
+
hasAndroidDevices: true,
|
|
33
|
+
hasBrowser: true,
|
|
34
|
+
hasCampaigns: true,
|
|
35
|
+
verbose: true,
|
|
36
|
+
makeChart: false,
|
|
37
|
+
writeToDisk: true
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
const allSpecs = {
|
|
44
|
+
"simple-spec": { ...simple, ...commonOptions, name: "simple-spec" },
|
|
45
|
+
"complex-spec": { ...complex, ...commonOptions, name: "complex-spec" },
|
|
46
|
+
"meta-spec": { ...big, ...commonOptions, name: "meta-spec" },
|
|
47
|
+
"fun-spec": { ...gaming, ...commonOptions, name: "fun-spec" },
|
|
48
|
+
"bad-spec": {
|
|
49
|
+
...big, ...commonOptions, name: "bad-data-spec",
|
|
50
|
+
hook: function (record, type, meta) {
|
|
51
|
+
if (type === "event") {
|
|
52
|
+
if (twentyFivePercent()) delete record.event;
|
|
53
|
+
if (twentyFivePercent()) delete record.user_id;
|
|
54
|
+
if (twentyFivePercent()) delete record.session_id;
|
|
55
|
+
if (twentyFivePercent()) delete record.device_id;
|
|
56
|
+
if (twentyFivePercent()) delete record.time;
|
|
57
|
+
if (twentyFivePercent()) delete record.insert_id;
|
|
58
|
+
}
|
|
59
|
+
return record;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
for (const [name, spec] of Object.entries(allSpecs)) {
|
|
65
|
+
delete spec.groupEvents;
|
|
66
|
+
delete spec.scdProps;
|
|
67
|
+
delete spec.lookupTables;
|
|
68
|
+
delete spec.groupKeys;
|
|
69
|
+
delete spec.groupProps;
|
|
70
|
+
delete spec.mirrorProps;
|
|
71
|
+
delete spec.token;
|
|
72
|
+
delete spec.secret;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const simulations = Object.entries(allSpecs).map(([name, spec]) => ({ name, spec }));
|
|
76
|
+
|
|
77
|
+
// 1. If this process is a CHILD, just run the spec!
|
|
78
|
+
if (process.env.__SIM_CHILD) {
|
|
79
|
+
const name = process.env.__SIM_NAME;
|
|
80
|
+
const spec = allSpecs[name];
|
|
81
|
+
(async () => {
|
|
82
|
+
const result = await main(spec);
|
|
83
|
+
// Send result to parent
|
|
84
|
+
if (process.send) process.send(result);
|
|
85
|
+
else console.log(JSON.stringify(result));
|
|
86
|
+
process.exit(0);
|
|
87
|
+
})();
|
|
88
|
+
} else {
|
|
89
|
+
// 2. PARENT: fork a child for each simulation
|
|
90
|
+
const { promisify } = await import('util');
|
|
91
|
+
const limit = 5; // parallelism limit
|
|
92
|
+
let running = 0, idx = 0, results = [];
|
|
93
|
+
|
|
94
|
+
function runOne(sim) {
|
|
95
|
+
return new Promise((resolve, reject) => {
|
|
96
|
+
const child = fork(process.argv[1], [], {
|
|
97
|
+
env: { ...process.env, __SIM_CHILD: "1", __SIM_NAME: sim.name },
|
|
98
|
+
stdio: ['inherit', 'inherit', 'inherit', 'ipc']
|
|
99
|
+
});
|
|
100
|
+
child.on('message', (result) => resolve({ name: sim.name, result }));
|
|
101
|
+
child.on('error', reject);
|
|
102
|
+
child.on('exit', (code) => {
|
|
103
|
+
if (code !== 0) reject(new Error(`Child ${sim.name} exited code ${code}`));
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const queue = [...simulations];
|
|
109
|
+
const resultsList = [];
|
|
110
|
+
async function runNext() {
|
|
111
|
+
while (running < limit && queue.length > 0) {
|
|
112
|
+
const sim = queue.shift();
|
|
113
|
+
running++;
|
|
114
|
+
runOne(sim)
|
|
115
|
+
.then(res => resultsList.push(res))
|
|
116
|
+
.catch(e => console.error("Sim error:", e))
|
|
117
|
+
.finally(() => {
|
|
118
|
+
running--;
|
|
119
|
+
runNext();
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
runNext();
|
|
124
|
+
|
|
125
|
+
// Wait until all are done
|
|
126
|
+
const wait = () => new Promise(resolve => {
|
|
127
|
+
const check = () => {
|
|
128
|
+
if (resultsList.length === simulations.length) resolve(resultsList);
|
|
129
|
+
else setTimeout(check, 100);
|
|
130
|
+
};
|
|
131
|
+
check();
|
|
132
|
+
});
|
|
133
|
+
(await wait()).forEach(res => {
|
|
134
|
+
console.log(`Finished simulation: ${res.name}`);
|
|
135
|
+
// optionally: console.log(res.result);
|
|
136
|
+
});
|
|
137
|
+
}
|
package/scripts/new-dungeon.sh
CHANGED
|
@@ -8,13 +8,14 @@ random_file_name=$(mktemp ./dungeons/my-file-XXXXXXXX.js)
|
|
|
8
8
|
|
|
9
9
|
# Initial text to write to the file
|
|
10
10
|
initial_text='
|
|
11
|
+
import dayjs from "dayjs";
|
|
12
|
+
import utc from "dayjs/plugin/utc.js";
|
|
13
|
+
import "dotenv/config";
|
|
14
|
+
import * as u from "../lib/utils/utils.js";
|
|
15
|
+
import * as v from "ak-tools";
|
|
16
|
+
|
|
11
17
|
const SEED = "my-seed";
|
|
12
|
-
const dayjs = require("dayjs");
|
|
13
|
-
const utc = require("dayjs/plugin/utc");
|
|
14
18
|
dayjs.extend(utc);
|
|
15
|
-
require("dotenv").config();
|
|
16
|
-
const u = require("../components/utils");
|
|
17
|
-
const v = require("ak-tools");
|
|
18
19
|
const chance = u.initChance(SEED);
|
|
19
20
|
const num_users = 25_000
|
|
20
21
|
const days = 100
|
|
@@ -88,7 +89,7 @@ const config = {
|
|
|
88
89
|
}
|
|
89
90
|
};
|
|
90
91
|
|
|
91
|
-
|
|
92
|
+
export default config;'
|
|
92
93
|
|
|
93
94
|
# Write the initial text to the new file
|
|
94
95
|
echo "$initial_text" > "$random_file_name"
|
package/scripts/update-deps.sh
CHANGED
package/tests/cli.test.js
CHANGED
|
@@ -1,27 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
//@ts-nocheck
|
|
2
|
+
import generate from '../index.js';
|
|
3
|
+
import 'dotenv/config';
|
|
4
|
+
import { execSync } from "child_process";
|
|
5
|
+
import * as u from 'ak-tools';
|
|
6
|
+
import Papa from 'papaparse';
|
|
7
|
+
|
|
8
|
+
import simple from '../dungeons/simple.js';
|
|
9
|
+
import complex from '../dungeons/complex.js';
|
|
10
|
+
import anon from '../dungeons/anon.js';
|
|
11
|
+
import funnels from '../dungeons/funnels.js';
|
|
12
|
+
import foobar from '../dungeons/foobar.js';
|
|
13
|
+
import mirror from '../dungeons/mirror.js';
|
|
14
|
+
import adspend from '../dungeons/adspend.js';
|
|
15
|
+
import scd from '../dungeons/scd.js';
|
|
15
16
|
|
|
16
17
|
const timeout = 600000;
|
|
17
18
|
const testToken = process.env.TEST_TOKEN || "hello token!";
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
// Use sequential execution to prevent CLI tests from interfering with each other
|
|
21
|
+
// since they use execSync and create/modify files in the same directories
|
|
22
|
+
describe.sequential('cli', () => {
|
|
20
23
|
|
|
21
24
|
test('sanity check', async () => {
|
|
22
25
|
console.log('SANITY TEST');
|
|
23
|
-
const run = execSync(`node ./index.js`);
|
|
24
|
-
const ending = `
|
|
26
|
+
const run = execSync(`node ./index.js --numEvents 100 --numUsers 10`);
|
|
27
|
+
const ending = `completed successfully!`;
|
|
25
28
|
expect(run.toString().trim().endsWith(ending)).toBe(true);
|
|
26
29
|
const files = (await u.ls('./data')).filter(a => a.includes('.csv'));
|
|
27
30
|
expect(files.length).toBe(2);
|
|
@@ -33,8 +36,8 @@ describe('cli', () => {
|
|
|
33
36
|
const userProfilesData = (await u.load(users[0])).trim();
|
|
34
37
|
const parsedEvents = Papa.parse(eventData, { header: true }).data;
|
|
35
38
|
const parsedUsers = Papa.parse(userProfilesData, { header: true }).data;
|
|
36
|
-
expect(parsedEvents.length).toBeGreaterThan(
|
|
37
|
-
expect(parsedUsers.length).toBeGreaterThan(
|
|
39
|
+
expect(parsedEvents.length).toBeGreaterThan(10);
|
|
40
|
+
expect(parsedUsers.length).toBeGreaterThan(5);
|
|
38
41
|
expect(parsedUsers.every(u => u.distinct_id)).toBe(true);
|
|
39
42
|
expect(parsedEvents.every(e => e.event)).toBe(true);
|
|
40
43
|
expect(parsedEvents.every(e => e.time)).toBe(true);
|
|
@@ -50,8 +53,8 @@ describe('cli', () => {
|
|
|
50
53
|
|
|
51
54
|
test('no args', async () => {
|
|
52
55
|
console.log('BARE CLI TEST');
|
|
53
|
-
const run = execSync(`node ./index.js --numEvents
|
|
54
|
-
expect(run.toString().trim().includes('
|
|
56
|
+
const run = execSync(`node ./index.js --numEvents 100 --numUsers 10`);
|
|
57
|
+
expect(run.toString().trim().includes('completed successfully!')).toBe(true);
|
|
55
58
|
const csvs = (await u.ls('./data')).filter(a => a.includes('.csv'));
|
|
56
59
|
expect(csvs.length).toBe(2);
|
|
57
60
|
|
|
@@ -59,16 +62,16 @@ describe('cli', () => {
|
|
|
59
62
|
|
|
60
63
|
test('--complex', async () => {
|
|
61
64
|
console.log('COMPLEX CLI TEST');
|
|
62
|
-
const run = execSync(`node ./index.js --numEvents
|
|
65
|
+
const run = execSync(`node ./index.js --numEvents 100 --numUsers 10 --seed "deal with it" --complex`, { stdio: "ignore" });
|
|
63
66
|
const csvs = (await u.ls('./data')).filter(a => a.includes('.json'));
|
|
64
|
-
expect(csvs.length).
|
|
67
|
+
expect(csvs.length).toBeGreaterThan(7);
|
|
65
68
|
|
|
66
69
|
}, timeout);
|
|
67
70
|
|
|
68
71
|
test('--simple', async () => {
|
|
69
72
|
console.log('SIMPLE CLI TEST');
|
|
70
|
-
const run = execSync(`node ./index.js --numEvents
|
|
71
|
-
expect(run.toString().trim().includes('
|
|
73
|
+
const run = execSync(`node ./index.js --numEvents 100 --numUsers 10 --seed "deal with it" --simple`);
|
|
74
|
+
expect(run.toString().trim().includes('completed successfully!')).toBe(true);
|
|
72
75
|
const csvs = (await u.ls('./data')).filter(a => a.includes('.csv'));
|
|
73
76
|
expect(csvs.length).toBe(2);
|
|
74
77
|
|
package/tests/e2e.test.js
CHANGED
|
@@ -3,29 +3,30 @@
|
|
|
3
3
|
/* eslint-disable no-undef */
|
|
4
4
|
/* eslint-disable no-debugger */
|
|
5
5
|
/* eslint-disable no-unused-vars */
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
6
|
+
import generate from '../index.js';
|
|
7
|
+
import 'dotenv/config';
|
|
8
|
+
import { execSync } from "child_process";
|
|
9
|
+
import * as u from 'ak-tools';
|
|
10
|
+
import Papa from 'papaparse';
|
|
11
|
+
|
|
12
|
+
import simple from '../dungeons/simple.js';
|
|
13
|
+
import complex from '../dungeons/complex.js';
|
|
14
|
+
import anon from '../dungeons/anon.js';
|
|
15
|
+
import funnels from '../dungeons/funnels.js';
|
|
16
|
+
import foobar from '../dungeons/foobar.js';
|
|
17
|
+
import mirror from '../dungeons/mirror.js';
|
|
18
|
+
import adspend from '../dungeons/adspend.js';
|
|
19
|
+
import scd from '../dungeons/scd.js';
|
|
20
|
+
|
|
21
|
+
// 1 minute timeout
|
|
22
|
+
const timeout = 60000;
|
|
22
23
|
const testToken = process.env.TEST_TOKEN || "hello token!";
|
|
23
24
|
|
|
24
25
|
describe('module', () => {
|
|
25
26
|
|
|
26
27
|
test('works as module (no config)', async () => {
|
|
27
28
|
console.log('MODULE TEST');
|
|
28
|
-
const results = await generate({ verbose:
|
|
29
|
+
const results = await generate({ verbose: false, writeToDisk: false, numEvents: 1100, numUsers: 100, seed: "deal with it" });
|
|
29
30
|
const { eventData, groupProfilesData, lookupTableData, scdTableData, userProfilesData } = results;
|
|
30
31
|
expect(eventData.length).toBeGreaterThan(980);
|
|
31
32
|
expect(groupProfilesData.length).toBe(0);
|
|
@@ -37,7 +38,7 @@ describe('module', () => {
|
|
|
37
38
|
|
|
38
39
|
test('works as module (simple)', async () => {
|
|
39
40
|
console.log('MODULE TEST: SIMPLE');
|
|
40
|
-
const results = await generate({ ...simple, verbose:
|
|
41
|
+
const results = await generate({ ...simple, verbose: false, writeToDisk: false, numEvents: 1100, numUsers: 100, seed: "deal with it" });
|
|
41
42
|
const { eventData, groupProfilesData, lookupTableData, scdTableData, userProfilesData } = results;
|
|
42
43
|
expect(eventData.length).toBeGreaterThan(980);
|
|
43
44
|
expect(groupProfilesData.length).toBe(0);
|
|
@@ -49,7 +50,7 @@ describe('module', () => {
|
|
|
49
50
|
|
|
50
51
|
test('works as module (complex)', async () => {
|
|
51
52
|
console.log('MODULE TEST: COMPLEX');
|
|
52
|
-
const results = await generate({ ...complex, verbose:
|
|
53
|
+
const results = await generate({ ...complex, verbose: false, writeToDisk: false, numEvents: 1100, numUsers: 100, seed: "deal with it" });
|
|
53
54
|
const { eventData, groupProfilesData, lookupTableData, scdTableData, userProfilesData } = results;
|
|
54
55
|
expect(eventData.length).toBeGreaterThan(980);
|
|
55
56
|
expect(groupProfilesData[0]?.length).toBe(500);
|
|
@@ -62,7 +63,7 @@ describe('module', () => {
|
|
|
62
63
|
|
|
63
64
|
test('works as module (funnels)', async () => {
|
|
64
65
|
console.log('MODULE TEST: FUNNELS');
|
|
65
|
-
const results = await generate({ ...funnels, verbose:
|
|
66
|
+
const results = await generate({ ...funnels, verbose: false, writeToDisk: false, numEvents: 1100, numUsers: 100, seed: "deal with it" });
|
|
66
67
|
const { eventData, groupProfilesData, scdTableData, userProfilesData } = results;
|
|
67
68
|
expect(eventData.length).toBeGreaterThan(980);
|
|
68
69
|
expect(groupProfilesData.length).toBe(3);
|
|
@@ -75,7 +76,7 @@ describe('module', () => {
|
|
|
75
76
|
|
|
76
77
|
test('works as module (mirror)', async () => {
|
|
77
78
|
console.log('MODULE TEST: MIRROR');
|
|
78
|
-
const results = await generate({ ...mirror, verbose:
|
|
79
|
+
const results = await generate({ ...mirror, verbose: false, writeToDisk: false, numEvents: 1100, numUsers: 100, seed: "deal with it" });
|
|
79
80
|
const { eventData, userProfilesData, mirrorEventData } = results;
|
|
80
81
|
expect(eventData.length).toBeGreaterThan(980);
|
|
81
82
|
expect(mirrorEventData.length).toBeGreaterThan(980);
|
|
@@ -87,7 +88,7 @@ describe('module', () => {
|
|
|
87
88
|
|
|
88
89
|
test('works as module (foobar)', async () => {
|
|
89
90
|
console.log('MODULE TEST: FOOBAR');
|
|
90
|
-
const results = await generate({ ...foobar, verbose:
|
|
91
|
+
const results = await generate({ ...foobar, verbose: false, writeToDisk: false, numEvents: 1100, numUsers: 100, seed: "deal with it" });
|
|
91
92
|
const { eventData, userProfilesData } = results;
|
|
92
93
|
expect(eventData.length).toBeGreaterThan(980);
|
|
93
94
|
expect(userProfilesData.length).toBe(100);
|
|
@@ -96,7 +97,7 @@ describe('module', () => {
|
|
|
96
97
|
|
|
97
98
|
test('works as module (adspend)', async () => {
|
|
98
99
|
console.log('MODULE TEST: ADSPEND');
|
|
99
|
-
const results = await generate({ ...adspend, verbose:
|
|
100
|
+
const results = await generate({ ...adspend, verbose: false, writeToDisk: false, numEvents: 1100, numUsers: 100, seed: "deal with it" });
|
|
100
101
|
const { eventData, adSpendData, userProfilesData } = results;
|
|
101
102
|
expect(eventData.length).toBeGreaterThan(980);
|
|
102
103
|
expect(userProfilesData.length).toBe(100);
|
|
@@ -107,17 +108,18 @@ describe('module', () => {
|
|
|
107
108
|
|
|
108
109
|
test('works as module (scd)', async () => {
|
|
109
110
|
console.log('MODULE TEST: scd');
|
|
110
|
-
scd;
|
|
111
|
-
const
|
|
111
|
+
// const scdSchema = (await import('../dungeons/scd.js')).default;
|
|
112
|
+
const config = {
|
|
112
113
|
...scd,
|
|
113
114
|
token: testToken,
|
|
114
115
|
serviceAccount: process.env.SERVICE_ACCOUNT,
|
|
115
116
|
projectId: process.env.PROJECT_ID,
|
|
116
117
|
serviceSecret: process.env.SERVICE_SECRET,
|
|
117
|
-
verbose:
|
|
118
|
-
}
|
|
119
|
-
const
|
|
120
|
-
const {
|
|
118
|
+
verbose: false, writeToDisk: false, numEvents: 100, numUsers: 10, seed: "deal with it"
|
|
119
|
+
};
|
|
120
|
+
const results = await generate(config);
|
|
121
|
+
const { importResults } = results;
|
|
122
|
+
const { MRR_scd, NPS_scd, plan_scd, role_scd } = importResults;
|
|
121
123
|
expect(MRR_scd.success).toBeGreaterThan(10);
|
|
122
124
|
expect(NPS_scd.success).toBeGreaterThan(10);
|
|
123
125
|
expect(plan_scd.success).toBeGreaterThan(10);
|
|
@@ -126,7 +128,7 @@ describe('module', () => {
|
|
|
126
128
|
expect(NPS_scd.failed).toBe(0);
|
|
127
129
|
expect(plan_scd.failed).toBe(0);
|
|
128
130
|
expect(role_scd.failed).toBe(0);
|
|
129
|
-
|
|
131
|
+
|
|
130
132
|
|
|
131
133
|
}, timeout);
|
|
132
134
|
|
|
@@ -289,7 +291,7 @@ describe('options + tweaks', () => {
|
|
|
289
291
|
|
|
290
292
|
test('sends data to mixpanel', async () => {
|
|
291
293
|
console.log('NETWORK TEST');
|
|
292
|
-
const results = await generate({ verbose:
|
|
294
|
+
const results = await generate({ verbose: false, writeToDisk: false, numEvents: 1100, numUsers: 100, seed: "deal with it", token: testToken });
|
|
293
295
|
const { events, users, groups } = results.importResults;
|
|
294
296
|
expect(events.success).toBeGreaterThan(980);
|
|
295
297
|
expect(users.success).toBe(100);
|
|
@@ -298,7 +300,7 @@ describe('options + tweaks', () => {
|
|
|
298
300
|
|
|
299
301
|
test('every record is valid', async () => {
|
|
300
302
|
console.log('VALIDATION TEST');
|
|
301
|
-
const results = await generate({ verbose:
|
|
303
|
+
const results = await generate({ verbose: false, writeToDisk: false, numEvents: 1000, numUsers: 100 });
|
|
302
304
|
const { eventData, userProfilesData } = results;
|
|
303
305
|
const areEventsValid = eventData.every(validateEvent);
|
|
304
306
|
const areUsersValid = userProfilesData.every(validateUser);
|
|
@@ -312,7 +314,7 @@ describe('options + tweaks', () => {
|
|
|
312
314
|
|
|
313
315
|
test('every date is valid', async () => {
|
|
314
316
|
console.log('DATE TEST');
|
|
315
|
-
const results = await generate({ ...simple, writeToDisk: false, verbose:
|
|
317
|
+
const results = await generate({ ...simple, writeToDisk: false, verbose: false, numEvents: 1000, numUsers: 100 });
|
|
316
318
|
const { eventData } = results;
|
|
317
319
|
const invalidDates = eventData.filter(e => !validTime(e.time));
|
|
318
320
|
expect(eventData.every(e => validTime(e.time))).toBe(true);
|
|
@@ -321,7 +323,7 @@ describe('options + tweaks', () => {
|
|
|
321
323
|
|
|
322
324
|
test('anonymous users', async () => {
|
|
323
325
|
console.log('ANON TEST');
|
|
324
|
-
const results = await generate({ ...anon, writeToDisk: false, verbose:
|
|
326
|
+
const results = await generate({ ...anon, writeToDisk: false, verbose: false, numEvents: 1000, numUsers: 100 });
|
|
325
327
|
const { userProfilesData } = results;
|
|
326
328
|
expect(userProfilesData.every(u => u.name === 'Anonymous User')).toBe(true);
|
|
327
329
|
|
|
@@ -329,7 +331,7 @@ describe('options + tweaks', () => {
|
|
|
329
331
|
|
|
330
332
|
test('no avatars (default)', async () => {
|
|
331
333
|
console.log('AVATAR TEST');
|
|
332
|
-
const results = await generate({ ...simple, writeToDisk: false, verbose:
|
|
334
|
+
const results = await generate({ ...simple, writeToDisk: false, verbose: false, numEvents: 1000, numUsers: 100 });
|
|
333
335
|
const { userProfilesData } = results;
|
|
334
336
|
expect(userProfilesData.every(u => !u.avatar)).toBe(true);
|
|
335
337
|
|
|
@@ -337,7 +339,7 @@ describe('options + tweaks', () => {
|
|
|
337
339
|
|
|
338
340
|
test('yes avatars', async () => {
|
|
339
341
|
console.log('AVATAR TEST');
|
|
340
|
-
const results = await generate({ ...simple, writeToDisk: false, verbose:
|
|
342
|
+
const results = await generate({ ...simple, writeToDisk: false, verbose: false, numEvents: 1000, numUsers: 100, hasAvatar: true });
|
|
341
343
|
const { userProfilesData } = results;
|
|
342
344
|
expect(userProfilesData.every(u => u.avatar)).toBe(true);
|
|
343
345
|
|