make-mp-data 1.4.2 → 1.4.4
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/README.md +3 -2
- package/{chart.js → core/chart.js} +11 -4
- package/{cli.js → core/cli.js} +84 -6
- package/{defaults.js → core/defaults.js} +48 -62
- package/{index.js → core/index.js} +113 -89
- package/{utils.js → core/utils.js} +139 -69
- package/package.json +7 -8
- package/schemas/anon.js +104 -0
- package/schemas/complex.js +11 -2
- package/schemas/deepNest.js +5 -1
- package/schemas/foobar.js +2 -2
- package/schemas/funnels.js +1 -1
- package/schemas/simple.js +1 -1
- package/scratch.mjs +18 -5
- package/scripts/jsdoctest.js +1 -1
- package/tests/e2e.test.js +25 -7
- package/{testSoup.mjs → tests/testSoup.mjs} +2 -2
- package/tests/unit.test.js +153 -6
- package/tsconfig.json +1 -1
- package/types.d.ts +2 -1
- /package/{testCases.mjs → tests/testCases.mjs} +0 -0
package/package.json
CHANGED
|
@@ -1,26 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "make-mp-data",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.04",
|
|
4
4
|
"description": "builds all mixpanel primitives for a given project",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "types.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"start": "node index.js",
|
|
8
|
+
"start": "node ./core/index.js",
|
|
9
9
|
"dev": "nodemon scratch.mjs --ignore /data",
|
|
10
|
-
"complex": "nodemon index.js --complex --e 10000 --u 100",
|
|
11
|
-
"simple": "nodemon index.js --simple --e 10000 --u 100",
|
|
10
|
+
"complex": "nodemon ./core/index.js --complex --e 10000 --u 100",
|
|
11
|
+
"simple": "nodemon ./core/index.js --simple --e 10000 --u 100",
|
|
12
12
|
"prune": "rm -f ./data/* && rm -f ./tmp/*",
|
|
13
13
|
"post": "npm publish",
|
|
14
14
|
"test": "NODE_ENV=test jest --runInBand",
|
|
15
|
-
"deps": "sh ./scripts/deps.sh"
|
|
16
|
-
"udacity": "nodemon index.js ./customers/udacity.js"
|
|
15
|
+
"deps": "sh ./scripts/deps.sh"
|
|
17
16
|
},
|
|
18
17
|
"repository": {
|
|
19
18
|
"type": "git",
|
|
20
19
|
"url": "git+https://github.com/ak--47/make-mp-data.git"
|
|
21
20
|
},
|
|
22
21
|
"bin": {
|
|
23
|
-
"make-mp-data": "./index.js"
|
|
22
|
+
"make-mp-data": "./core/index.js"
|
|
24
23
|
},
|
|
25
24
|
"keywords": [
|
|
26
25
|
"mixpanel",
|
|
@@ -47,7 +46,7 @@
|
|
|
47
46
|
"chartjs-node-canvas": "^4.1.6",
|
|
48
47
|
"dayjs": "^1.11.11",
|
|
49
48
|
"dotenv": "^16.4.5",
|
|
50
|
-
"mixpanel-import": "^2.5.
|
|
49
|
+
"mixpanel-import": "^2.5.552",
|
|
51
50
|
"yargs": "^17.7.2"
|
|
52
51
|
},
|
|
53
52
|
"devDependencies": {
|
package/schemas/anon.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This is the default configuration file for the data generator in SIMPLE mode
|
|
3
|
+
* notice how the config object is structured, and see it's type definition in ./types.d.ts
|
|
4
|
+
* feel free to modify this file to customize the data you generate
|
|
5
|
+
* see helper functions in utils.js for more ways to generate data
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
const Chance = require('chance');
|
|
12
|
+
const chance = new Chance();
|
|
13
|
+
const dayjs = require("dayjs");
|
|
14
|
+
const utc = require("dayjs/plugin/utc");
|
|
15
|
+
dayjs.extend(utc);
|
|
16
|
+
const { uid, comma } = require('ak-tools');
|
|
17
|
+
const { pickAWinner, weightedRange, date, integer } = require('../core/utils');
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
/** @type {import('../types').Config} */
|
|
22
|
+
const config = {
|
|
23
|
+
token: "",
|
|
24
|
+
seed: "foo bar",
|
|
25
|
+
numDays: 365, //how many days worth of data
|
|
26
|
+
numEvents: 100000, //how many events
|
|
27
|
+
numUsers: 10000, //how many users
|
|
28
|
+
format: 'json', //csv or json
|
|
29
|
+
region: "US",
|
|
30
|
+
anonIds: true, //if true, anonymousIds are created for each user
|
|
31
|
+
sessionIds: false, //if true, sessionIds are created for each user
|
|
32
|
+
isAnonymous: true,
|
|
33
|
+
hasLocation: true,
|
|
34
|
+
events: [
|
|
35
|
+
{
|
|
36
|
+
event: "foo",
|
|
37
|
+
weight: 10,
|
|
38
|
+
properties: {}
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
event: "bar",
|
|
42
|
+
weight: 9,
|
|
43
|
+
properties: {}
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
event: "baz",
|
|
47
|
+
weight: 8,
|
|
48
|
+
properties: {}
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
event: "qux",
|
|
52
|
+
weight: 7,
|
|
53
|
+
properties: {}
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
event: "garply",
|
|
57
|
+
weight: 6,
|
|
58
|
+
properties: {}
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
event: "durtle",
|
|
62
|
+
weight: 5,
|
|
63
|
+
properties: {}
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
event: "linny",
|
|
67
|
+
weight: 4,
|
|
68
|
+
properties: {}
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
event: "fonk",
|
|
72
|
+
weight: 3,
|
|
73
|
+
properties: {}
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
event: "crumn",
|
|
77
|
+
weight: 2,
|
|
78
|
+
properties: {}
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
event: "yak",
|
|
82
|
+
weight: 1,
|
|
83
|
+
properties: {}
|
|
84
|
+
}
|
|
85
|
+
],
|
|
86
|
+
superProps: {},
|
|
87
|
+
userProps: {
|
|
88
|
+
title: chance.profession.bind(chance),
|
|
89
|
+
luckyNumber: weightedRange(42, 420),
|
|
90
|
+
spiritAnimal: ["duck", "dog", "otter", "penguin", "cat", "elephant", "lion", "cheetah", "giraffe", "zebra", "rhino", "hippo", "whale", "dolphin", "shark", "octopus", "squid", "jellyfish", "starfish", "seahorse", "crab", "lobster", "shrimp", "clam", "snail", "slug", "butterfly", "moth", "bee", "wasp", "ant", "beetle", "ladybug", "caterpillar", "centipede", "millipede", "scorpion", "spider", "tarantula", "tick", "mite", "mosquito", "fly", "dragonfly", "damselfly", "grasshopper", "cricket", "locust", "mantis", "cockroach", "termite", "praying mantis", "walking stick", "stick bug", "leaf insect", "lacewing", "aphid", "cicada", "thrips", "psyllid", "scale insect", "whitefly", "mealybug", "planthopper", "leafhopper", "treehopper", "flea", "louse", "bedbug", "flea beetle", "weevil", "longhorn beetle", "leaf beetle", "tiger beetle", "ground beetle", "lady beetle", "firefly", "click beetle", "rove beetle", "scarab beetle", "dung beetle", "stag beetle", "rhinoceros beetle", "hercules beetle", "goliath beetle", "jewel beetle", "tortoise beetle"]
|
|
91
|
+
},
|
|
92
|
+
scdProps: {},
|
|
93
|
+
mirrorProps: {},
|
|
94
|
+
groupKeys: [],
|
|
95
|
+
groupProps: {},
|
|
96
|
+
lookupTables: [],
|
|
97
|
+
hook: function (record, type, meta) {
|
|
98
|
+
return record;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
module.exports = config;
|
package/schemas/complex.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
const Chance = require('chance');
|
|
10
10
|
const chance = new Chance();
|
|
11
|
-
const { weightedRange, date, integer } = require('../utils.js');
|
|
11
|
+
const { weightedRange, date, integer } = require('../core/utils.js');
|
|
12
12
|
const u = require('ak-tools');
|
|
13
13
|
|
|
14
14
|
/** @type {import('../types.js').Config} */
|
|
@@ -23,6 +23,15 @@ const config = {
|
|
|
23
23
|
anonIds: true, //if true, anonymousIds are created for each user
|
|
24
24
|
sessionIds: true, //if true, sessionIds are created for each user
|
|
25
25
|
|
|
26
|
+
hasLocation: true,
|
|
27
|
+
hasAndroidDevices: true,
|
|
28
|
+
hasIOSDevices: true,
|
|
29
|
+
hasDesktopDevices: true,
|
|
30
|
+
hasBrowser: true,
|
|
31
|
+
hasCampaigns: true,
|
|
32
|
+
isAnonymous: false,
|
|
33
|
+
hasAdSpend: true,
|
|
34
|
+
|
|
26
35
|
events: [
|
|
27
36
|
{
|
|
28
37
|
"event": "checkout",
|
|
@@ -122,7 +131,7 @@ const config = {
|
|
|
122
131
|
}
|
|
123
132
|
],
|
|
124
133
|
superProps: {
|
|
125
|
-
|
|
134
|
+
linked_device: deviceAttributes()
|
|
126
135
|
// emotions: generateEmoji(),
|
|
127
136
|
|
|
128
137
|
},
|
package/schemas/deepNest.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
const Chance = require('chance');
|
|
2
2
|
const chance = new Chance();
|
|
3
|
+
const u = require('../core/utils');
|
|
4
|
+
|
|
5
|
+
const plans = ['free', 'premium', 'casual', 'influencer'];
|
|
6
|
+
const marketingChannels = ["Organic", "Organic", "Organic", "Organic", "Instagram Ads", "Facebook Ads", "Google Ads", "Youtube Ads", "Instagram Post", "Instagram Post", "Facebook Post"];
|
|
3
7
|
|
|
4
8
|
const config = {
|
|
5
9
|
token: "",
|
|
@@ -35,7 +39,7 @@ function generateVideoMeta() {
|
|
|
35
39
|
availableFormats: chance.pickset(formats, int(1, formats.length)),
|
|
36
40
|
availableAspectRatios: chance.pickset(ratios, int(1, ratios.length)),
|
|
37
41
|
availableContainerFormats: chance.pickset(containers, int(1, containers.length)),
|
|
38
|
-
observedLatencyTimestamps: chance.pickset(
|
|
42
|
+
observedLatencyTimestamps: chance.pickset(u.range(1, 300000), int(1, 40))
|
|
39
43
|
},
|
|
40
44
|
videoStats: {
|
|
41
45
|
numberOfPlays: int(10, 10000000),
|
package/schemas/foobar.js
CHANGED
|
@@ -14,7 +14,7 @@ const dayjs = require("dayjs");
|
|
|
14
14
|
const utc = require("dayjs/plugin/utc");
|
|
15
15
|
dayjs.extend(utc);
|
|
16
16
|
const { uid, comma } = require('ak-tools');
|
|
17
|
-
const { pickAWinner, weightedRange, date, integer } = require('../utils');
|
|
17
|
+
const { pickAWinner, weightedRange, date, integer } = require('../core/utils');
|
|
18
18
|
|
|
19
19
|
const itemCategories = ["Books", "Movies", "Music", "Games", "Electronics", "Computers", "Smart Home", "Home", "Garden", "Pet", "Beauty", "Health", "Toys", "Kids", "Baby", "Handmade", "Sports", "Outdoors", "Automotive", "Industrial", "Entertainment", "Art", "Food", "Appliances", "Office", "Wedding", "Software"];
|
|
20
20
|
|
|
@@ -31,7 +31,7 @@ const config = {
|
|
|
31
31
|
region: "US",
|
|
32
32
|
anonIds: true, //if true, anonymousIds are created for each user
|
|
33
33
|
sessionIds: false, //if true, sessionIds are created for each user
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
events: [
|
|
36
36
|
{
|
|
37
37
|
event: "foo",
|
package/schemas/funnels.js
CHANGED
|
@@ -14,7 +14,7 @@ const dayjs = require("dayjs");
|
|
|
14
14
|
const utc = require("dayjs/plugin/utc");
|
|
15
15
|
dayjs.extend(utc);
|
|
16
16
|
const { uid, comma } = require('ak-tools');
|
|
17
|
-
const { pickAWinner, weightedRange, date, integer } = require('../utils');
|
|
17
|
+
const { pickAWinner, weightedRange, date, integer } = require('../core/utils');
|
|
18
18
|
|
|
19
19
|
const itemCategories = ["Books", "Movies", "Music", "Games", "Electronics", "Computers", "Smart Home", "Home", "Garden", "Pet", "Beauty", "Health", "Toys", "Kids", "Baby", "Handmade", "Sports", "Outdoors", "Automotive", "Industrial", "Entertainment", "Art", "Food", "Appliances", "Office", "Wedding", "Software"];
|
|
20
20
|
|
package/schemas/simple.js
CHANGED
|
@@ -14,7 +14,7 @@ const dayjs = require("dayjs");
|
|
|
14
14
|
const utc = require("dayjs/plugin/utc");
|
|
15
15
|
dayjs.extend(utc);
|
|
16
16
|
const { uid, comma } = require('ak-tools');
|
|
17
|
-
const { pickAWinner, weightedRange, date, integer } = require('../utils');
|
|
17
|
+
const { pickAWinner, weightedRange, date, integer } = require('../core/utils');
|
|
18
18
|
|
|
19
19
|
const itemCategories = ["Books", "Movies", "Music", "Games", "Electronics", "Computers", "Smart Home", "Home", "Garden", "Pet", "Beauty", "Health", "Toys", "Kids", "Baby", "Handmade", "Sports", "Outdoors", "Automotive", "Industrial", "Entertainment", "Art", "Food", "Appliances", "Office", "Wedding", "Software"];
|
|
20
20
|
|
package/scratch.mjs
CHANGED
|
@@ -1,23 +1,36 @@
|
|
|
1
|
-
import main from "./index.js";
|
|
1
|
+
import main from "./core/index.js";
|
|
2
2
|
import amir from './customers/amir.js';
|
|
3
3
|
import simple from './schemas/simple.js';
|
|
4
4
|
import funnels from './schemas/funnels.js';
|
|
5
5
|
import foobar from './schemas/foobar.js';
|
|
6
6
|
import complex from './schemas/complex.js';
|
|
7
7
|
import deepNest from './schemas/deepNest.js';
|
|
8
|
+
import anon from './schemas/anon.js';
|
|
8
9
|
import execSync from 'child_process';
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
/** @type {main.Config} */
|
|
12
|
-
const spec = {
|
|
13
|
-
...
|
|
13
|
+
const spec = {
|
|
14
|
+
...complex,
|
|
14
15
|
writeToDisk: false,
|
|
15
16
|
verbose: true,
|
|
16
17
|
makeChart: false,
|
|
17
|
-
|
|
18
|
+
numUsers: 100,
|
|
19
|
+
numEvents: 10000,
|
|
20
|
+
numDays: 90,
|
|
21
|
+
token: ""
|
|
18
22
|
};
|
|
19
23
|
|
|
20
24
|
|
|
21
25
|
execSync.execSync('npm run prune');
|
|
22
|
-
const { eventData,
|
|
26
|
+
const { eventData,
|
|
27
|
+
groupProfilesData,
|
|
28
|
+
lookupTableData,
|
|
29
|
+
mirrorEventData,
|
|
30
|
+
scdTableData,
|
|
31
|
+
userProfilesData,
|
|
32
|
+
importResults,
|
|
33
|
+
files,
|
|
34
|
+
adSpendData
|
|
35
|
+
} = await main(spec);
|
|
23
36
|
debugger;
|
package/scripts/jsdoctest.js
CHANGED
package/tests/e2e.test.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/* eslint-disable no-undef */
|
|
4
4
|
/* eslint-disable no-debugger */
|
|
5
5
|
/* eslint-disable no-unused-vars */
|
|
6
|
-
const generate = require('../index.js');
|
|
6
|
+
const generate = require('../core/index.js');
|
|
7
7
|
require('dotenv').config();
|
|
8
8
|
const { execSync } = require("child_process");
|
|
9
9
|
const u = require('ak-tools');
|
|
@@ -11,6 +11,7 @@ const u = require('ak-tools');
|
|
|
11
11
|
const simple = require('../schemas/simple.js');
|
|
12
12
|
const complex = require('../schemas/complex.js');
|
|
13
13
|
const deep = require('../schemas/deepNest.js');
|
|
14
|
+
const anon = require('../schemas/anon.js');
|
|
14
15
|
|
|
15
16
|
const timeout = 60000;
|
|
16
17
|
const testToken = process.env.TEST_TOKEN;
|
|
@@ -86,30 +87,39 @@ describe('module', () => {
|
|
|
86
87
|
});
|
|
87
88
|
|
|
88
89
|
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);
|
|
94
|
+
const csvs = (await u.ls('./data')).filter(a => a.includes('.csv'));
|
|
95
|
+
expect(csvs.length).toBe(4);
|
|
96
|
+
clearData();
|
|
97
|
+
}, timeout);
|
|
98
|
+
|
|
89
99
|
test('works as CLI (complex)', async () => {
|
|
90
100
|
console.log('COMPLEX CLI TEST');
|
|
91
|
-
const run = execSync(`node ./index.js --numEvents 1000 --numUsers 100 --seed "deal with it" --complex`, { stdio: 'ignore' });
|
|
101
|
+
const run = execSync(`node ./core/index.js --numEvents 1000 --numUsers 100 --seed "deal with it" --complex`, { stdio: 'ignore' });
|
|
92
102
|
// expect(run.toString().trim().includes('have a wonderful day :)')).toBe(true);
|
|
93
103
|
const csvs = (await u.ls('./data')).filter(a => a.includes('.csv'));
|
|
94
|
-
expect(csvs.length).toBe(
|
|
104
|
+
expect(csvs.length).toBe(13);
|
|
95
105
|
clearData();
|
|
96
106
|
}, timeout);
|
|
97
107
|
|
|
98
108
|
test('works as CLI (simple)', async () => {
|
|
99
109
|
console.log('simple CLI TEST');
|
|
100
|
-
const run = execSync(`node ./index.js --numEvents 1000 --numUsers 100 --seed "deal with it"`);
|
|
110
|
+
const run = execSync(`node ./core/index.js --numEvents 1000 --numUsers 100 --seed "deal with it" --simple`);
|
|
101
111
|
expect(run.toString().trim().includes('have a wonderful day :)')).toBe(true);
|
|
102
112
|
const csvs = (await u.ls('./data')).filter(a => a.includes('.csv'));
|
|
103
|
-
expect(csvs.length).toBe(
|
|
113
|
+
expect(csvs.length).toBe(4);
|
|
104
114
|
clearData();
|
|
105
115
|
}, timeout);
|
|
106
116
|
|
|
107
117
|
test('works as CLI (custom)', async () => {
|
|
108
118
|
console.log('custom CLI TEST');
|
|
109
|
-
const run = execSync(`node ./index.js ./schemas/deepNest.js`);
|
|
119
|
+
const run = execSync(`node ./core/index.js ./schemas/deepNest.js`);
|
|
110
120
|
expect(run.toString().trim().includes('have a wonderful day :)')).toBe(true);
|
|
111
121
|
const csvs = (await u.ls('./data')).filter(a => a.includes('.csv'));
|
|
112
|
-
expect(csvs.length).toBe(
|
|
122
|
+
expect(csvs.length).toBe(3);
|
|
113
123
|
clearData();
|
|
114
124
|
}, timeout);
|
|
115
125
|
|
|
@@ -179,6 +189,14 @@ describe('options + tweaks', () => {
|
|
|
179
189
|
|
|
180
190
|
}, timeout);
|
|
181
191
|
|
|
192
|
+
test('anonymous users', async () => {
|
|
193
|
+
console.log('ANON TEST');
|
|
194
|
+
const results = await generate({ ...anon, writeToDisk: false, verbose: true });
|
|
195
|
+
const { userProfilesData } = results;
|
|
196
|
+
expect(userProfilesData.every(u => u.name === 'Anonymous User')).toBe(true);
|
|
197
|
+
|
|
198
|
+
}, timeout);
|
|
199
|
+
|
|
182
200
|
});
|
|
183
201
|
|
|
184
202
|
afterAll(() => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { generateLineChart } from '
|
|
2
|
-
import { TimeSoup } from '
|
|
1
|
+
import { generateLineChart } from '../core/chart.js';
|
|
2
|
+
import { TimeSoup } from '../core/utils.js';
|
|
3
3
|
import dayjs from 'dayjs';
|
|
4
4
|
import { progress } from 'ak-tools';
|
|
5
5
|
import TEST_CASES from './testCases.mjs';
|
package/tests/unit.test.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const generate = require('../index.js');
|
|
1
|
+
const generate = require('../core/index.js');
|
|
2
2
|
const dayjs = require("dayjs");
|
|
3
3
|
const utc = require("dayjs/plugin/utc");
|
|
4
4
|
const fs = require('fs');
|
|
@@ -44,8 +44,9 @@ const { applySkew,
|
|
|
44
44
|
validateTime,
|
|
45
45
|
interruptArray,
|
|
46
46
|
optimizedBoxMuller,
|
|
47
|
-
inferFunnels
|
|
48
|
-
|
|
47
|
+
inferFunnels,
|
|
48
|
+
datesBetween
|
|
49
|
+
} = require('../core/utils.js');
|
|
49
50
|
|
|
50
51
|
|
|
51
52
|
describe('timesoup', () => {
|
|
@@ -231,6 +232,152 @@ describe('generation', () => {
|
|
|
231
232
|
expect(createdDate.isValid()).toBeTruthy();
|
|
232
233
|
expect(createdDate.isBefore(dayjs.unix(global.NOW))).toBeTruthy();
|
|
233
234
|
});
|
|
235
|
+
|
|
236
|
+
test('winner: return func', () => {
|
|
237
|
+
const items = ['a', 'b', 'c'];
|
|
238
|
+
const result = pickAWinner(items, 0);
|
|
239
|
+
expect(typeof result).toBe('function');
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
test('winner: first most', () => {
|
|
243
|
+
const items = ['a', 'b', 'c'];
|
|
244
|
+
const mostChosenIndex = 0;
|
|
245
|
+
const pickFunction = pickAWinner(items, mostChosenIndex);
|
|
246
|
+
const weightedList = pickFunction();
|
|
247
|
+
|
|
248
|
+
// Expect the most chosen item to appear at least once
|
|
249
|
+
expect(weightedList.includes(items[mostChosenIndex])).toBeTruthy();
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
test('winner: second most', () => {
|
|
253
|
+
const items = ['a', 'b', 'c'];
|
|
254
|
+
const mostChosenIndex = 0;
|
|
255
|
+
const pickFunction = pickAWinner(items, mostChosenIndex);
|
|
256
|
+
const weightedList = pickFunction();
|
|
257
|
+
|
|
258
|
+
const secondMostChosenIndex = (mostChosenIndex + 1) % items.length;
|
|
259
|
+
|
|
260
|
+
// Expect the second most chosen item to appear at least once
|
|
261
|
+
expect(weightedList.includes(items[secondMostChosenIndex])).toBeTruthy();
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
test('winner: third most', () => {
|
|
265
|
+
const items = ['a', 'b', 'c'];
|
|
266
|
+
const mostChosenIndex = 0;
|
|
267
|
+
const pickFunction = pickAWinner(items, mostChosenIndex);
|
|
268
|
+
const weightedList = pickFunction();
|
|
269
|
+
|
|
270
|
+
const thirdMostChosenIndex = (mostChosenIndex + 2) % items.length;
|
|
271
|
+
|
|
272
|
+
// Expect the third most chosen item to appear at least once
|
|
273
|
+
expect(weightedList.includes(items[thirdMostChosenIndex])).toBeTruthy();
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
test('winner: exceed array bounds', () => {
|
|
277
|
+
const items = ['a', 'b', 'c'];
|
|
278
|
+
const mostChosenIndex = 0;
|
|
279
|
+
const pickFunction = pickAWinner(items, mostChosenIndex);
|
|
280
|
+
const weightedList = pickFunction();
|
|
281
|
+
|
|
282
|
+
// Ensure all indices are within the bounds of the array
|
|
283
|
+
weightedList.forEach(item => {
|
|
284
|
+
expect(items.includes(item)).toBeTruthy();
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
test('winner: single item array', () => {
|
|
289
|
+
const items = ['a'];
|
|
290
|
+
const mostChosenIndex = 0;
|
|
291
|
+
const pickFunction = pickAWinner(items, mostChosenIndex);
|
|
292
|
+
const weightedList = pickFunction();
|
|
293
|
+
|
|
294
|
+
// Since there's only one item, all winner: he same
|
|
295
|
+
weightedList.forEach(item => {
|
|
296
|
+
expect(item).toBe('a');
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
test('winner: empty array', () => {
|
|
301
|
+
const items = [];
|
|
302
|
+
const pickFunction = pickAWinner(items, 0);
|
|
303
|
+
const weightedList = pickFunction();
|
|
304
|
+
|
|
305
|
+
// Expect the result to be an empty array
|
|
306
|
+
expect(weightedList.length).toBe(0);
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
test('dates: same start end', () => {
|
|
310
|
+
const start = '2023-06-10';
|
|
311
|
+
const end = '2023-06-10';
|
|
312
|
+
const result = datesBetween(start, end);
|
|
313
|
+
expect(result).toEqual([]);
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
test('dates: start after end', () => {
|
|
317
|
+
const start = '2023-06-12';
|
|
318
|
+
const end = '2023-06-10';
|
|
319
|
+
const result = datesBetween(start, end);
|
|
320
|
+
expect(result).toEqual([]);
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
test('dates: correct', () => {
|
|
324
|
+
const start = '2023-06-10';
|
|
325
|
+
const end = '2023-06-13';
|
|
326
|
+
const result = datesBetween(start, end);
|
|
327
|
+
expect(result).toEqual([
|
|
328
|
+
'2023-06-10T12:00:00.000Z',
|
|
329
|
+
'2023-06-11T12:00:00.000Z',
|
|
330
|
+
'2023-06-12T12:00:00.000Z'
|
|
331
|
+
]);
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
test('dates: unix times', () => {
|
|
335
|
+
const start = dayjs('2023-06-10').unix();
|
|
336
|
+
const end = dayjs('2023-06-13').unix();
|
|
337
|
+
const result = datesBetween(start, end);
|
|
338
|
+
expect(result).toEqual([
|
|
339
|
+
'2023-06-10T12:00:00.000Z',
|
|
340
|
+
'2023-06-11T12:00:00.000Z',
|
|
341
|
+
'2023-06-12T12:00:00.000Z'
|
|
342
|
+
]);
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
test('dates: mixed formats', () => {
|
|
346
|
+
const start = '2023-06-10';
|
|
347
|
+
const end = dayjs('2023-06-13').unix();
|
|
348
|
+
const result = datesBetween(start, end);
|
|
349
|
+
expect(result).toEqual([
|
|
350
|
+
'2023-06-10T12:00:00.000Z',
|
|
351
|
+
'2023-06-11T12:00:00.000Z',
|
|
352
|
+
'2023-06-12T12:00:00.000Z'
|
|
353
|
+
]);
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
test('dates: invalid dates', () => {
|
|
357
|
+
const start = 'invalid-date';
|
|
358
|
+
const end = '2023-06-13';
|
|
359
|
+
const result = datesBetween(start, end);
|
|
360
|
+
expect(result).toEqual([]);
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
test('dates: same day', () => {
|
|
364
|
+
const start = '2023-06-10T08:00:00.000Z';
|
|
365
|
+
const end = '2023-06-10T20:00:00.000Z';
|
|
366
|
+
const result = datesBetween(start, end);
|
|
367
|
+
expect(result).toEqual([]);
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
test('dates: leap years', () => {
|
|
371
|
+
const start = '2024-02-28';
|
|
372
|
+
const end = '2024-03-02';
|
|
373
|
+
const result = datesBetween(start, end);
|
|
374
|
+
expect(result).toEqual([
|
|
375
|
+
'2024-02-28T12:00:00.000Z',
|
|
376
|
+
'2024-02-29T12:00:00.000Z',
|
|
377
|
+
'2024-03-01T12:00:00.000Z'
|
|
378
|
+
]);
|
|
379
|
+
});
|
|
380
|
+
|
|
234
381
|
});
|
|
235
382
|
|
|
236
383
|
describe('validation', () => {
|
|
@@ -431,9 +578,9 @@ describe('utilities', () => {
|
|
|
431
578
|
});
|
|
432
579
|
|
|
433
580
|
test('applySkew: skews', () => {
|
|
434
|
-
const value =
|
|
581
|
+
const value = optimizedBoxMuller();
|
|
435
582
|
const skewedValue = applySkew(value, .25);
|
|
436
|
-
expect(Math.abs(skewedValue)).toBeLessThanOrEqual(Math.abs(value));
|
|
583
|
+
expect(Math.abs(skewedValue)).toBeLessThanOrEqual(Math.abs(value) + 1);
|
|
437
584
|
});
|
|
438
585
|
|
|
439
586
|
test('mapToRange: works', () => {
|
|
@@ -553,7 +700,7 @@ describe('utilities', () => {
|
|
|
553
700
|
test('progress: outputs correctly', () => {
|
|
554
701
|
// @ts-ignore
|
|
555
702
|
const mockStdoutWrite = jest.spyOn(process.stdout, 'write').mockImplementation(() => { });
|
|
556
|
-
progress('test', 50);
|
|
703
|
+
progress([['test', 50]]);
|
|
557
704
|
expect(mockStdoutWrite).toHaveBeenCalled();
|
|
558
705
|
mockStdoutWrite.mockRestore();
|
|
559
706
|
});
|
package/tsconfig.json
CHANGED
package/types.d.ts
CHANGED
|
File without changes
|