pkg-stats 0.4.0 → 0.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/README.md +23 -4
- package/dist/__tests__/output.js +8 -0
- package/dist/__tests__/output.test.js +7 -0
- package/dist/cli-options.js +15 -3
- package/dist/colors.js +8 -5
- package/dist/format.js +3 -0
- package/dist/mode/compare-packages.js +11 -17
- package/dist/mode/package-info.js +64 -0
- package/dist/mode/package-stats.js +19 -19
- package/dist/output.js +28 -0
- package/dist/render.js +23 -0
- package/dist/stats.js +8 -3
- package/dist/style.js +16 -0
- package/dist/types.js +1 -0
- package/dist/version.js +0 -3
- package/package.json +1 -1
- package/dist/__tests__/chart.test.js +0 -7
package/README.md
CHANGED
@@ -2,15 +2,34 @@
|
|
2
2
|
|
3
3
|
Beautiful NPM package download stats.
|
4
4
|
|
5
|
+
### Single package
|
6
|
+
|
5
7
|
```
|
6
8
|
npx pkg-stats react
|
7
9
|
```
|
8
10
|
|
9
11
|
<div align='center'>
|
10
|
-
<img src="https://raw.githubusercontent.com/mdjastrzebski/pkg-stats/main/docs/public/example-
|
12
|
+
<img src="https://raw.githubusercontent.com/mdjastrzebski/pkg-stats/main/docs/public/example-package.png" alt="Display single package stats" style="max-width: 610px; aspect-ratio: 610x374;" />
|
13
|
+
</div>
|
14
|
+
|
15
|
+
#### Options:
|
16
|
+
|
17
|
+
- `--major`, `--minor`, `--patch` - group by major, minor or patch version
|
18
|
+
- `--top <number>` (alias `-t`) - show top N versions
|
19
|
+
- `--color <scheme>` (alias `-c`) - specify color scheme
|
20
|
+
- available schemes: `atlas`, `cristal`, `fruit`, `insta`, `mind`, `morning`, `passion`, `pastel`, `rainbow`, `retro`, `summer`, `teen`, `vice`
|
21
|
+
|
22
|
+
|
23
|
+
### Compare packages
|
24
|
+
|
25
|
+
```
|
26
|
+
npx pkg-stats moment date-fns dayjs luxon @js-joda/core
|
27
|
+
```
|
28
|
+
|
29
|
+
<div align='center'>
|
30
|
+
<img src="https://raw.githubusercontent.com/mdjastrzebski/pkg-stats/main/docs/public/example-compare.png" alt="Compare package stats" style="max-width: 610px; aspect-ratio: 610x374;" />
|
11
31
|
</div>
|
12
32
|
|
13
|
-
|
33
|
+
#### Options:
|
14
34
|
|
15
|
-
-
|
16
|
-
- top version: `--top <number>` (alias `-t`)
|
35
|
+
- `--color <scheme>` (alias `-c`) - specify color scheme
|
@@ -0,0 +1,8 @@
|
|
1
|
+
import { expect, test } from 'vitest';
|
2
|
+
import { formatBar } from '../output.js';
|
3
|
+
|
4
|
+
test('renderChart basic tests', () => {
|
5
|
+
expect(formatBar(0.0, { length: 10 })).toMatchInlineSnapshot(`"▏ "`);
|
6
|
+
expect(formatBar(0.5, { length: 10 })).toMatchInlineSnapshot(`"█████ "`);
|
7
|
+
expect(formatBar(1.0, { length: 10 })).toMatchInlineSnapshot(`"██████████"`);
|
8
|
+
});
|
@@ -0,0 +1,7 @@
|
|
1
|
+
import { expect, test } from 'vitest';
|
2
|
+
import { formatBar } from '../output.js';
|
3
|
+
test('renderChart basic tests', () => {
|
4
|
+
expect(formatBar(0.0, { length: 10 })).toMatchInlineSnapshot(`"▏ "`);
|
5
|
+
expect(formatBar(0.5, { length: 10 })).toMatchInlineSnapshot(`"█████ "`);
|
6
|
+
expect(formatBar(1.0, { length: 10 })).toMatchInlineSnapshot(`"██████████"`);
|
7
|
+
});
|
package/dist/cli-options.js
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import chalk from 'chalk';
|
2
2
|
import meow from 'meow';
|
3
3
|
import redent from 'redent';
|
4
|
-
import { COLOR_SCHEMES } from './colors.js';
|
4
|
+
import { COLOR_SCHEMES, getColorOfDay } from './colors.js';
|
5
5
|
const colorCommand = chalk.hex('#22c1c3');
|
6
6
|
const colorOption = chalk.hex('#fdbb2d');
|
7
7
|
const HELP = `
|
@@ -14,6 +14,7 @@ Options:
|
|
14
14
|
${colorOption('--patch')} Group by patch version
|
15
15
|
${colorOption('-t, --top')} <number> Show top <number> most downloaded versions
|
16
16
|
${colorOption('-a, --all')} Include all versions in output, even those with minimal downloads
|
17
|
+
${colorOption('-x, --extended')} Show extended stats
|
17
18
|
${colorOption('-c, --color')} <scheme> ${wrapOption(`Choose color scheme from: ${COLOR_SCHEMES.sort().join(', ')}`, 50, 24)}
|
18
19
|
|
19
20
|
Examples:
|
@@ -77,6 +78,10 @@ export function parseCliOptions(argv) {
|
|
77
78
|
type: 'boolean',
|
78
79
|
shortFlag: 'a',
|
79
80
|
},
|
81
|
+
extended: {
|
82
|
+
type: 'boolean',
|
83
|
+
shortFlag: 'x',
|
84
|
+
},
|
80
85
|
color: {
|
81
86
|
shortFlag: 'c',
|
82
87
|
type: 'string',
|
@@ -100,7 +105,14 @@ export function parseCliOptions(argv) {
|
|
100
105
|
? 'patch'
|
101
106
|
: undefined,
|
102
107
|
top: cli.flags.top,
|
103
|
-
all: cli.flags.all,
|
104
|
-
|
108
|
+
all: cli.flags.all ?? false,
|
109
|
+
extended: cli.flags.extended ?? false,
|
110
|
+
color: coalesceColor(cli.flags.color) ?? getColorOfDay(),
|
105
111
|
};
|
106
112
|
}
|
113
|
+
function coalesceColor(color) {
|
114
|
+
if (color && COLOR_SCHEMES.includes(color)) {
|
115
|
+
return color;
|
116
|
+
}
|
117
|
+
return undefined;
|
118
|
+
}
|
package/dist/colors.js
CHANGED
@@ -27,17 +27,20 @@ const gradients = {
|
|
27
27
|
summer: { colors: ['#fdbb2d', '#22c1c3'], options: {} },
|
28
28
|
rainbow: {
|
29
29
|
colors: ['#ff0100', '#ff0000'],
|
30
|
-
options: { interpolation: 'hsv', hsvSpin: 'long',
|
30
|
+
options: { interpolation: 'hsv', hsvSpin: 'long', min: 7, extra: 1 },
|
31
31
|
},
|
32
32
|
pastel: {
|
33
33
|
colors: ['#74ebd5', '#74ecd5'],
|
34
|
-
options: { interpolation: 'hsv', hsvSpin: 'long',
|
34
|
+
options: { interpolation: 'hsv', hsvSpin: 'long', extra: 1 },
|
35
35
|
},
|
36
36
|
};
|
37
37
|
export const COLOR_SCHEMES = Object.keys(gradients);
|
38
|
+
export function getPrimaryColor(colorScheme) {
|
39
|
+
return gradients[colorScheme].colors[0];
|
40
|
+
}
|
38
41
|
export function getColors(count, colorScheme) {
|
39
|
-
const { colors, options } = gradients[colorScheme
|
40
|
-
const paddedCount = count + (options.
|
42
|
+
const { colors, options } = gradients[colorScheme];
|
43
|
+
const paddedCount = Math.max(count + (options.extra ?? 0), options.min ?? 0);
|
41
44
|
if (paddedCount < colors.length) {
|
42
45
|
return colors;
|
43
46
|
}
|
@@ -47,7 +50,7 @@ export function getColors(count, colorScheme) {
|
|
47
50
|
: gradient.rgb(paddedCount);
|
48
51
|
return tinyColors.map((c) => c.toHexString());
|
49
52
|
}
|
50
|
-
function getColorOfDay() {
|
53
|
+
export function getColorOfDay() {
|
51
54
|
const date = new Date();
|
52
55
|
const index = date.getDate() + date.getMonth() * 30 + date.getFullYear() * 360;
|
53
56
|
return COLOR_SCHEMES[index % COLOR_SCHEMES.length];
|
package/dist/format.js
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
import chalk from 'chalk';
|
2
|
-
import {
|
3
|
-
import { getColors } from '../colors.js';
|
4
|
-
import { formatDownloads } from '../format.js';
|
2
|
+
import { formatPercentage } from '../format.js';
|
5
3
|
import { fetchNpmLastWeekDownloads } from '../npm-api.js';
|
4
|
+
import { printChart } from '../output.js';
|
6
5
|
export async function comparePackages(packageNames, options) {
|
7
6
|
const rawPackages = await Promise.all(packageNames.map((packageName) => fetchPackageData(packageName)));
|
8
7
|
const packagesToDisplay = rawPackages
|
@@ -13,20 +12,15 @@ export async function comparePackages(packageNames, options) {
|
|
13
12
|
process.exit(1);
|
14
13
|
}
|
15
14
|
console.log(chalk.bold(`\nNPM weekly downloads\n`));
|
16
|
-
const maxDownloads = Math.max(...packagesToDisplay.map((
|
17
|
-
const
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
const maxDownloadsLength = Math.max(...displayData.map((item) => item.downloads.length));
|
26
|
-
const colors = getColors(packagesToDisplay.length, options.color);
|
27
|
-
displayData.forEach((item, i) => {
|
28
|
-
const color = chalk.hex(colors[i]);
|
29
|
-
console.log(`${item.name.padStart(2 + maxNameLength)} ${color(item.chart)} ${color(item.downloads.padStart(maxDownloadsLength))}`);
|
15
|
+
const maxDownloads = Math.max(...packagesToDisplay.map((item) => item.downloads));
|
16
|
+
const items = packagesToDisplay.map((item) => ({
|
17
|
+
label: item.packageName,
|
18
|
+
value: item.downloads,
|
19
|
+
extended: options.extended ? formatPercentage(item.downloads / maxDownloads) : undefined,
|
20
|
+
}));
|
21
|
+
printChart(items, {
|
22
|
+
colorScheme: options.color,
|
23
|
+
indent: 2,
|
30
24
|
});
|
31
25
|
}
|
32
26
|
async function fetchPackageData(packageName) {
|
@@ -0,0 +1,64 @@
|
|
1
|
+
import chalk from 'chalk';
|
2
|
+
import { renderChart } from '../chart.js';
|
3
|
+
import { getColors } from '../colors.js';
|
4
|
+
import { formatDownloads } from '../format.js';
|
5
|
+
import { fetchNpmLastWeekDownloads } from '../npm-api.js';
|
6
|
+
import { filterStats, groupStats } from '../stats.js';
|
7
|
+
import { parseVersion, versionCompare } from '../version.js';
|
8
|
+
export async function fetchPackageInfo(packageName, options) {
|
9
|
+
const data = await fetchNpmLastWeekDownloads(packageName);
|
10
|
+
if (!Object.keys(data.downloads).length) {
|
11
|
+
throw new Error(`No data found for package "${packageName}".`);
|
12
|
+
}
|
13
|
+
const npmStats = Object.keys(data.downloads)
|
14
|
+
.map((versionString) => {
|
15
|
+
const version = parseVersion(versionString);
|
16
|
+
return {
|
17
|
+
...version,
|
18
|
+
downloads: data.downloads[versionString],
|
19
|
+
};
|
20
|
+
})
|
21
|
+
.sort(versionCompare);
|
22
|
+
const { type, stats } = groupStats(npmStats, options.group);
|
23
|
+
const totalDownloads = Object.values(stats).reduce((sum, version) => sum + version.downloads, 0);
|
24
|
+
return {
|
25
|
+
name: packageName,
|
26
|
+
totalDownloads,
|
27
|
+
groupingType: type,
|
28
|
+
stats: stats.map((stat) => ({
|
29
|
+
version: stat.versionString,
|
30
|
+
downloads: stat.downloads,
|
31
|
+
})),
|
32
|
+
};
|
33
|
+
}
|
34
|
+
export function printPackageInfo({ name, stats, totalDownloads, groupingType }, options) {
|
35
|
+
const statsToDisplay = filterStats(stats, {
|
36
|
+
totalDownloads,
|
37
|
+
all: options.all,
|
38
|
+
top: options.top,
|
39
|
+
});
|
40
|
+
const colors = getColors(statsToDisplay.length, options.color);
|
41
|
+
const primaryColor = chalk.hex(colors[0]);
|
42
|
+
console.log(chalk.bold(`\nNPM weekly downloads for ${primaryColor(name)}\n`));
|
43
|
+
console.log(`Total: ${primaryColor(totalDownloads.toLocaleString())} last week\n`);
|
44
|
+
console.log(options.top
|
45
|
+
? `Top ${options.top} ${groupingType} versions:\n`
|
46
|
+
: `By ${groupingType} version:\n`);
|
47
|
+
const maxDownloads = Math.max(...stats.map((v) => v.downloads));
|
48
|
+
const displayData = statsToDisplay.map((item) => {
|
49
|
+
const versionParts = item.version.split('.');
|
50
|
+
return {
|
51
|
+
version: versionParts.length < 3 ? `${item.version}.x` : item.version,
|
52
|
+
chart: renderChart(item.downloads / maxDownloads),
|
53
|
+
downloads: formatDownloads(item.downloads, maxDownloads),
|
54
|
+
};
|
55
|
+
});
|
56
|
+
const maxVersionLength = Math.max(...displayData.map((item) => item.version.length));
|
57
|
+
const maxDownloadsLength = Math.max(...displayData.map((item) => item.downloads.length));
|
58
|
+
displayData.forEach((item, i) => {
|
59
|
+
const color = chalk.hex(colors[i]);
|
60
|
+
console.log(`${item.version.padStart(2 + maxVersionLength)} ${color(item.chart)} ${color(item.downloads.padStart(maxDownloadsLength))}`);
|
61
|
+
});
|
62
|
+
console.log(chalk.bold(`\nNPM weekly downloads for ${chalk.green(name)}\n`));
|
63
|
+
console.log(`Total: ${chalk.green(totalDownloads.toLocaleString())} last week\n`);
|
64
|
+
}
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import chalk from 'chalk';
|
2
|
-
import {
|
3
|
-
import {
|
4
|
-
import { formatDownloads } from '../format.js';
|
2
|
+
import { getPrimaryColor } from '../colors.js';
|
3
|
+
import { formatPercentage } from '../format.js';
|
5
4
|
import { fetchNpmLastWeekDownloads } from '../npm-api.js';
|
5
|
+
import { printChart } from '../output.js';
|
6
6
|
import { filterStats, groupStats } from '../stats.js';
|
7
7
|
import { parseVersion, versionCompare } from '../version.js';
|
8
8
|
export async function printPackageStats(packageName, options) {
|
@@ -34,24 +34,24 @@ export async function printPackageStats(packageName, options) {
|
|
34
34
|
all: options.all,
|
35
35
|
top: options.top,
|
36
36
|
});
|
37
|
-
const
|
38
|
-
|
37
|
+
const downloadToDisplay = statsToDisplay.reduce((sum, version) => sum + version.downloads, 0);
|
38
|
+
if (totalDownloads - downloadToDisplay > 0) {
|
39
|
+
statsToDisplay.push({
|
40
|
+
versionString: 'rest',
|
41
|
+
downloads: totalDownloads - downloadToDisplay,
|
42
|
+
});
|
43
|
+
}
|
44
|
+
const primaryColor = chalk.hex(getPrimaryColor(options.color));
|
39
45
|
console.log(chalk.bold(`\nNPM weekly downloads for ${primaryColor(packageName)}\n`));
|
40
46
|
console.log(`Total: ${primaryColor(totalDownloads.toLocaleString())} last week\n`);
|
41
47
|
console.log(options.top ? `Top ${options.top} ${type} versions:\n` : `By ${type} version:\n`);
|
42
|
-
const
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
});
|
51
|
-
const maxVersionLength = Math.max(...displayData.map((item) => item.version.length));
|
52
|
-
const maxDownloadsLength = Math.max(...displayData.map((item) => item.downloads.length));
|
53
|
-
displayData.forEach((item, i) => {
|
54
|
-
const color = chalk.hex(colors[i]);
|
55
|
-
console.log(`${item.version.padStart(2 + maxVersionLength)} ${color(item.chart)} ${color(item.downloads.padStart(maxDownloadsLength))}`);
|
48
|
+
const items = statsToDisplay.map((item) => ({
|
49
|
+
label: item.versionString,
|
50
|
+
value: item.downloads,
|
51
|
+
extended: options.extended ? formatPercentage(item.downloads / totalDownloads) : undefined,
|
52
|
+
}));
|
53
|
+
printChart(items, {
|
54
|
+
colorScheme: options.color,
|
55
|
+
indent: 2,
|
56
56
|
});
|
57
57
|
}
|
package/dist/output.js
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
import chalk from 'chalk';
|
2
|
+
import { getColors } from './colors.js';
|
3
|
+
import { formatDownloads } from './format.js';
|
4
|
+
export function printChart(items, options) {
|
5
|
+
const maxLabelLength = Math.max(...items.map((item) => item.label.length));
|
6
|
+
const maxValue = Math.max(...items.map((item) => item.value));
|
7
|
+
const maxValueLength = formatDownloads(maxValue, maxValue).length;
|
8
|
+
const maxExtendedLength = Math.max(...items.map((item) => item.extended?.length ?? 0));
|
9
|
+
const colors = getColors(items.length, options.colorScheme);
|
10
|
+
const indent = options.indent ?? 0;
|
11
|
+
items.forEach((item, i) => {
|
12
|
+
const color = chalk.hex(colors[i]);
|
13
|
+
const label = ' '.repeat(indent) + item.label.padStart(maxLabelLength);
|
14
|
+
const bar = formatBar(item.value / maxValue);
|
15
|
+
const value = formatDownloads(item.value, maxValue).padStart(maxValueLength);
|
16
|
+
const extended = item.extended
|
17
|
+
? chalk.dim(` ${item.extended}`.padStart(maxExtendedLength + 1))
|
18
|
+
: '';
|
19
|
+
console.log(`${label} ${color(bar)} ${color(value)}${extended}`);
|
20
|
+
});
|
21
|
+
}
|
22
|
+
export function formatBar(value, { length = 50 } = {}) {
|
23
|
+
const filledChars = Math.round(value * length);
|
24
|
+
if (filledChars === 0) {
|
25
|
+
return '▏' + ' '.repeat(length - 1);
|
26
|
+
}
|
27
|
+
return '█'.repeat(filledChars) + ' '.repeat(length - filledChars);
|
28
|
+
}
|
package/dist/render.js
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
import { style } from './style.js';
|
2
|
+
export function renderChart(value) {
|
3
|
+
const filledValues = Math.round(value * style.chart.width * style.chart.pattern.length);
|
4
|
+
if (filledValues === 0) {
|
5
|
+
return '▏' + (style.rightLabel === 'align-right' ? ' '.repeat(style.chart.width - 1) : '');
|
6
|
+
}
|
7
|
+
const fullBlocks = Math.floor(filledValues / style.chart.pattern.length);
|
8
|
+
const partialBlock = filledValues % style.chart.pattern.length;
|
9
|
+
const hasPartialBlock = partialBlock > 0;
|
10
|
+
return (style.chart.pattern.at(-1).repeat(fullBlocks) +
|
11
|
+
(hasPartialBlock ? style.chart.pattern.at(partialBlock) : '') +
|
12
|
+
(style.rightLabel === 'align-right'
|
13
|
+
? ' '.repeat(style.chart.width - fullBlocks - (hasPartialBlock ? 1 : 0))
|
14
|
+
: ''));
|
15
|
+
}
|
16
|
+
// export type RenderChartLineOptions = {
|
17
|
+
// value: number;
|
18
|
+
// leftLabel: string;
|
19
|
+
// rightLabel: string;
|
20
|
+
// };
|
21
|
+
// export function renderChartLine({ value, leftLabel, rightLabel }: RenderChartLineOptions) {
|
22
|
+
// return `${leftLabel}${renderChart(value)}${rightLabel}`;
|
23
|
+
// }
|
package/dist/stats.js
CHANGED
@@ -22,7 +22,7 @@ export function groupStats(stats, type) {
|
|
22
22
|
function groupByMajor(stats) {
|
23
23
|
const result = {};
|
24
24
|
for (const versionStats of stats) {
|
25
|
-
const key = `${versionStats.major}`;
|
25
|
+
const key = `${versionStats.major}.x`;
|
26
26
|
const entry = result[key] ?? {
|
27
27
|
version: { major: versionStats.major },
|
28
28
|
versionString: key,
|
@@ -36,7 +36,7 @@ function groupByMajor(stats) {
|
|
36
36
|
function groupByMinor(stats) {
|
37
37
|
const result = {};
|
38
38
|
for (const versionStats of stats) {
|
39
|
-
const key = `${versionStats.major}.${versionStats.minor}`;
|
39
|
+
const key = `${versionStats.major}.${versionStats.minor}.x`;
|
40
40
|
const entry = result[key] ?? {
|
41
41
|
version: { major: versionStats.major, minor: versionStats.minor },
|
42
42
|
versionString: key,
|
@@ -73,7 +73,12 @@ export function filterStats(stats, options) {
|
|
73
73
|
return pickTopStats(stats, options.top);
|
74
74
|
}
|
75
75
|
const downloadThreshold = 0.005 * options.totalDownloads; // 0.5%
|
76
|
-
|
76
|
+
const filtered = stats.filter((stat) => stat.downloads >= downloadThreshold);
|
77
|
+
// If we were to skip only a single state, we rather display it than replace it with "rest".
|
78
|
+
if (filtered.length + 1 >= stats.length) {
|
79
|
+
return stats;
|
80
|
+
}
|
81
|
+
return filtered;
|
77
82
|
}
|
78
83
|
function pickTopStats(stats, top) {
|
79
84
|
const sortedStats = stats.sort((a, b) => b.downloads - a.downloads);
|
package/dist/style.js
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
export const style = {
|
2
|
+
chart: {
|
3
|
+
width: 50,
|
4
|
+
//pattern: ['⏹'],
|
5
|
+
//pattern: ['⏺'],
|
6
|
+
//pattern: ['█'],
|
7
|
+
//pattern: [' ', '▎', '▌', '▊', '█'],
|
8
|
+
//pattern: [' ', '▩'],
|
9
|
+
//pattern: [' ', '▰'],
|
10
|
+
//pattern: [' ', '∎'],
|
11
|
+
pattern: [' ', '█'],
|
12
|
+
//pattern: [' ', '▓'],
|
13
|
+
zeroPattern: '▏',
|
14
|
+
},
|
15
|
+
rightLabel: 'align-right',
|
16
|
+
};
|
package/dist/types.js
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
package/dist/version.js
CHANGED
@@ -18,8 +18,5 @@ export function versionCompare(a, b) {
|
|
18
18
|
if (a.patch !== undefined && b.patch !== undefined && a.patch !== b.patch) {
|
19
19
|
return b.patch - a.patch;
|
20
20
|
}
|
21
|
-
if (a.preRelease !== undefined && b.preRelease !== undefined) {
|
22
|
-
return a.preRelease.localeCompare(b.preRelease);
|
23
|
-
}
|
24
21
|
return 0;
|
25
22
|
}
|
package/package.json
CHANGED
@@ -1,7 +0,0 @@
|
|
1
|
-
import { expect, test } from 'vitest';
|
2
|
-
import { renderChart } from '../chart.js';
|
3
|
-
test('renderChart basic tests', () => {
|
4
|
-
expect(renderChart(0.0, { length: 10 })).toMatchInlineSnapshot(`"▏ "`);
|
5
|
-
expect(renderChart(0.5, { length: 10 })).toMatchInlineSnapshot(`"█████ "`);
|
6
|
-
expect(renderChart(1.0, { length: 10 })).toMatchInlineSnapshot(`"██████████"`);
|
7
|
-
});
|