Skip to content

Commit 2123d11

Browse files
Richienbsindresorhus
andauthoredMay 10, 2022
Require Node.js 14.16 (#44)
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
1 parent 62e78ab commit 2123d11

File tree

9 files changed

+139
-124
lines changed

9 files changed

+139
-124
lines changed
 

‎.github/workflows/main.yml

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ jobs:
1010
fail-fast: false
1111
matrix:
1212
node-version:
13-
- 14
14-
- 12
13+
- 18
14+
- 16
1515
steps:
16-
- uses: actions/checkout@v2
17-
- uses: actions/setup-node@v1
16+
- uses: actions/checkout@v3
17+
- uses: actions/setup-node@v3
1818
with:
1919
node-version: ${{ matrix.node-version }}
2020
- run: npm install

‎browser.js

+12-23
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,23 @@
11
/* eslint-env browser */
22
import {createStringGenerator, createAsyncStringGenerator} from './core.js';
33

4-
const toHex = uInt8Array => uInt8Array.map(byte => byte.toString(16).padStart(2, '0')).join('');
5-
6-
const decoder = new TextDecoder('utf8');
7-
const toBase64 = uInt8Array => btoa(decoder.decode(uInt8Array));
4+
const toHex = uInt8Array => [...uInt8Array].map(byte => byte.toString(16).padStart(2, '0')).join('');
5+
const toBase64 = uInt8Array => btoa(String.fromCodePoint(...uInt8Array));
86

97
// `crypto.getRandomValues` throws an error if too much entropy is requested at once. (https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues#exceptions)
10-
const maxEntropy = 65536;
8+
const maxEntropy = 65_536;
119

1210
function getRandomValues(byteLength) {
13-
const generatedBytes = [];
11+
const generatedBytes = new Uint8Array(byteLength);
1412

15-
while (byteLength > 0) {
16-
const bytesToGenerate = Math.min(byteLength, maxEntropy);
17-
generatedBytes.push(crypto.getRandomValues(new Uint8Array({length: bytesToGenerate})));
18-
byteLength -= bytesToGenerate;
13+
for (let totalGeneratedBytes = 0; totalGeneratedBytes < byteLength; totalGeneratedBytes += maxEntropy) {
14+
generatedBytes.set(
15+
crypto.getRandomValues(new Uint8Array(Math.min(maxEntropy, byteLength - totalGeneratedBytes))),
16+
totalGeneratedBytes,
17+
);
1918
}
2019

21-
const result = new Uint8Array(generatedBytes.reduce((sum, {byteLength}) => sum + byteLength, 0)); // eslint-disable-line unicorn/no-array-reduce
22-
let currentIndex = 0;
23-
24-
for (const bytes of generatedBytes) {
25-
result.set(bytes, currentIndex);
26-
currentIndex += bytes.byteLength;
27-
}
28-
29-
return result;
20+
return generatedBytes;
3021
}
3122

3223
function specialRandomBytes(byteLength, type, length) {
@@ -36,7 +27,5 @@ function specialRandomBytes(byteLength, type, length) {
3627
return convert(generatedBytes).slice(0, length);
3728
}
3829

39-
const cryptoRandomString = createStringGenerator(specialRandomBytes, getRandomValues);
40-
cryptoRandomString.async = createAsyncStringGenerator(specialRandomBytes, getRandomValues);
41-
42-
export default cryptoRandomString;
30+
export default createStringGenerator(specialRandomBytes, getRandomValues);
31+
export const cryptoRandomStringAsync = createAsyncStringGenerator(specialRandomBytes, getRandomValues);

‎core.js

+14-12
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
const urlSafeCharacters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~'.split('');
2-
const numericCharacters = '0123456789'.split('');
3-
const distinguishableCharacters = 'CDEHKMPRTUWXY012458'.split('');
4-
const asciiPrintableCharacters = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'.split('');
5-
const alphanumericCharacters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.split('');
1+
const urlSafeCharacters = [...'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~'];
2+
const numericCharacters = [...'0123456789'];
3+
const distinguishableCharacters = [...'CDEHKMPRTUWXY012458'];
4+
const asciiPrintableCharacters = [...'!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'];
5+
const alphanumericCharacters = [...'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'];
6+
7+
const readUInt16LE = (uInt8Array, offset) => uInt8Array[offset] + (uInt8Array[offset + 1] << 8); // eslint-disable-line no-bitwise
68

79
const generateForCustomCharacters = (length, characters, randomBytes) => {
810
// Generating entropy is faster than complex math operations, so we use the simplest way
911
const characterCount = characters.length;
10-
const maxValidSelector = (Math.floor(0x10000 / characterCount) * characterCount) - 1; // Using values above this will ruin distribution when using modular division
12+
const maxValidSelector = (Math.floor(0x1_00_00 / characterCount) * characterCount) - 1; // Using values above this will ruin distribution when using modular division
1113
const entropyLength = 2 * Math.ceil(1.1 * length); // Generating a bit more than required so chances we need more than one pass will be really low
1214
let string = '';
1315
let stringLength = 0;
@@ -17,7 +19,7 @@ const generateForCustomCharacters = (length, characters, randomBytes) => {
1719
let entropyPosition = 0;
1820

1921
while (entropyPosition < entropyLength && stringLength < length) {
20-
const entropyValue = entropy.readUInt16LE(entropyPosition);
22+
const entropyValue = readUInt16LE(entropy, entropyPosition);
2123
entropyPosition += 2;
2224
if (entropyValue > maxValidSelector) { // Skip values which will ruin distribution when using modular division
2325
continue;
@@ -34,7 +36,7 @@ const generateForCustomCharacters = (length, characters, randomBytes) => {
3436
const generateForCustomCharactersAsync = async (length, characters, randomBytesAsync) => {
3537
// Generating entropy is faster than complex math operations, so we use the simplest way
3638
const characterCount = characters.length;
37-
const maxValidSelector = (Math.floor(0x10000 / characterCount) * characterCount) - 1; // Using values above this will ruin distribution when using modular division
39+
const maxValidSelector = (Math.floor(0x1_00_00 / characterCount) * characterCount) - 1; // Using values above this will ruin distribution when using modular division
3840
const entropyLength = 2 * Math.ceil(1.1 * length); // Generating a bit more than required so chances we need more than one pass will be really low
3941
let string = '';
4042
let stringLength = 0;
@@ -44,7 +46,7 @@ const generateForCustomCharactersAsync = async (length, characters, randomBytesA
4446
let entropyPosition = 0;
4547

4648
while (entropyPosition < entropyLength && stringLength < length) {
47-
const entropyValue = entropy.readUInt16LE(entropyPosition);
49+
const entropyValue = readUInt16LE(entropy, entropyPosition);
4850
entropyPosition += 2;
4951
if (entropyValue > maxValidSelector) { // Skip values which will ruin distribution when using modular division
5052
continue;
@@ -66,7 +68,7 @@ const allowedTypes = new Set([
6668
'numeric',
6769
'distinguishable',
6870
'ascii-printable',
69-
'alphanumeric'
71+
'alphanumeric',
7072
]);
7173

7274
const createGenerator = (generateForCustomCharacters, specialRandomBytes, randomBytes) => ({length, type, characters}) => {
@@ -122,11 +124,11 @@ const createGenerator = (generateForCustomCharacters, specialRandomBytes, random
122124
throw new TypeError('Expected `characters` string length to be greater than or equal to 1');
123125
}
124126

125-
if (characters.length > 0x10000) {
127+
if (characters.length > 0x1_00_00) {
126128
throw new TypeError('Expected `characters` string length to be less or equal to 65536');
127129
}
128130

129-
return generateForCustomCharacters(length, characters.split(''), randomBytes);
131+
return generateForCustomCharacters(length, characters, randomBytes);
130132
};
131133

132134
export function createStringGenerator(specialRandomBytes, randomBytes) {

‎index.d.ts

+25-29
Original file line numberDiff line numberDiff line change
@@ -68,42 +68,38 @@ interface CharactersOption {
6868

6969
export type Options = BaseOptions & MergeExclusive<TypeOption, CharactersOption>;
7070

71-
declare const cryptoRandomString: {
72-
/**
73-
Generate a [cryptographically strong](https://en.wikipedia.org/wiki/Strong_cryptography) random string.
74-
75-
@returns A randomized string.
71+
/**
72+
Generate a [cryptographically strong](https://en.wikipedia.org/wiki/Strong_cryptography) random string.
7673
77-
@example
78-
```
79-
import cryptoRandomString from 'crypto-random-string';
74+
@returns A randomized string.
8075
81-
cryptoRandomString({length: 10});
82-
//=> '2cf05d94db'
83-
```
84-
*/
85-
(options: Options): string;
76+
@example
77+
```
78+
import cryptoRandomString from 'crypto-random-string';
8679
87-
/**
88-
Asynchronously generate a [cryptographically strong](https://en.wikipedia.org/wiki/Strong_cryptography) random string.
80+
cryptoRandomString({length: 10});
81+
//=> '2cf05d94db'
82+
```
83+
*/
84+
export default function cryptoRandomString(options: Options): string;
8985

90-
For most use-cases, there's really no good reason to use this async version. From the Node.js docs:
86+
/**
87+
Asynchronously generate a [cryptographically strong](https://en.wikipedia.org/wiki/Strong_cryptography) random string.
9188
92-
> The `crypto.randomBytes()` method will not complete until there is sufficient entropy available. This should normally never take longer than a few milliseconds. The only time when generating the random bytes may conceivably block for a longer period of time is right after boot, when the whole system is still low on entropy.
89+
For most use-cases, there's really no good reason to use this async version. From the Node.js docs:
9390
94-
In general, anything async comes with some overhead on it's own.
91+
> The `crypto.randomBytes()` method will not complete until there is sufficient entropy available. This should normally never take longer than a few milliseconds. The only time when generating the random bytes may conceivably block for a longer period of time is right after boot, when the whole system is still low on entropy.
9592
96-
@returns A promise which resolves to a randomized string.
93+
In general, anything async comes with some overhead on it's own.
9794
98-
@example
99-
```
100-
import cryptoRandomString from 'crypto-random-string';
95+
@returns A promise which resolves to a randomized string.
10196
102-
await cryptoRandomString.async({length: 10});
103-
//=> '2cf05d94db'
104-
```
105-
*/
106-
async(options: Options): Promise<string>;
107-
};
97+
@example
98+
```
99+
import {cryptoRandomStringAsync} from 'crypto-random-string';
108100
109-
export default cryptoRandomString;
101+
await cryptoRandomStringAsync({length: 10});
102+
//=> '2cf05d94db'
103+
```
104+
*/
105+
export function cryptoRandomStringAsync(options: Options): Promise<string>;

‎index.js

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1+
// TODO: When targeting Node.js 16, remove `cryptoRandomStringAsync` and use `crypto.webcrypto.getRandomValues` to interop with the browser code.
2+
// TODO: Later, when targeting Node.js 18, only use the browser code
13
import {promisify} from 'node:util';
2-
import crypto from 'node:crypto';
4+
import {randomBytes} from 'node:crypto';
35
import {createStringGenerator, createAsyncStringGenerator} from './core.js';
46

5-
const randomBytesAsync = promisify(crypto.randomBytes);
7+
const randomBytesAsync = promisify(randomBytes);
68

7-
const cryptoRandomString = createStringGenerator((byteLength, type, length) => crypto.randomBytes(byteLength).toString(type).slice(0, length), crypto.randomBytes);
8-
cryptoRandomString.async = createAsyncStringGenerator(async (byteLength, type, length) => {
9+
export default createStringGenerator((byteLength, type, length) => randomBytes(byteLength).toString(type).slice(0, length), size => new Uint8Array(randomBytes(size)));
10+
export const cryptoRandomStringAsync = createAsyncStringGenerator(async (byteLength, type, length) => {
911
const buffer = await randomBytesAsync(byteLength);
1012
return buffer.toString(type).slice(0, length);
11-
}, randomBytesAsync);
12-
13-
export default cryptoRandomString;
13+
}, async size => new Uint8Array(await randomBytesAsync(size)));

‎index.test-d.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import {expectType, expectError} from 'tsd';
2-
import cryptoRandomString from './index.js';
2+
import cryptoRandomString, {cryptoRandomStringAsync} from './index.js';
33

44
expectType<string>(cryptoRandomString({length: 10}));
55
expectType<string>(cryptoRandomString({length: 10, type: 'url-safe'}));
66
expectType<string>(cryptoRandomString({length: 10, type: 'numeric'}));
77
expectType<string>(cryptoRandomString({length: 10, characters: '1234'}));
8-
expectType<Promise<string>>(cryptoRandomString.async({length: 10}));
8+
expectType<Promise<string>>(cryptoRandomStringAsync({length: 10}));
99

1010
expectError(cryptoRandomString({type: 'url-safe'}));
1111
expectError(cryptoRandomString({length: 10, type: 'url-safe', characters: '1234'}));

‎package.json

+6-5
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"browser": "./browser.js"
1818
},
1919
"engines": {
20-
"node": ">=12"
20+
"node": ">=14.16"
2121
},
2222
"scripts": {
2323
"test": "xo && ava && tsd"
@@ -45,11 +45,12 @@
4545
"protect"
4646
],
4747
"dependencies": {
48-
"type-fest": "^1.0.1"
48+
"type-fest": "^2.12.2"
4949
},
5050
"devDependencies": {
51-
"ava": "^3.15.0",
52-
"tsd": "^0.14.0",
53-
"xo": "^0.38.2"
51+
"ava": "^4.2.0",
52+
"dot-prop": "^7.2.0",
53+
"tsd": "^0.20.0",
54+
"xo": "^0.48.0"
5455
}
5556
}

‎readme.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ cryptoRandomString({length: 10, characters: 'abc'});
4848

4949
Returns a randomized string. [Hex](https://en.wikipedia.org/wiki/Hexadecimal) by default.
5050

51-
### cryptoRandomString.async(options)
51+
### cryptoRandomStringAsync(options)
5252

5353
Returns a promise which resolves to a randomized string. [Hex](https://en.wikipedia.org/wiki/Hexadecimal) by default.
5454

@@ -58,6 +58,13 @@ For most use-cases, there's really no good reason to use this async version. Fro
5858
5959
In general, anything async comes with some overhead on it's own.
6060

61+
```js
62+
import {cryptoRandomStringAsync} from 'crypto-random-string';
63+
64+
await cryptoRandomStringAsync({length: 10});
65+
//=> '2cf05d94db'
66+
```
67+
6168
#### options
6269

6370
Type: `object`

‎test.js

+61-41
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,119 @@
1+
import {webcrypto} from 'node:crypto';
2+
import {hasProperty, setProperty} from 'dot-prop';
13
import test from 'ava';
2-
import cryptoRandomString from './index.js';
4+
import browserCryptoRandomString, {cryptoRandomStringAsync as browserCryptoRandomStringAsync} from './browser.js';
5+
import nodeCryptoRandomString, {cryptoRandomStringAsync as nodeCryptoRandomStringAsync} from './index.js';
6+
7+
if (!hasProperty(globalThis, 'crypto')) {
8+
setProperty(globalThis, 'crypto', webcrypto);
9+
}
310

411
// Probabilistic, result is always less than or equal to actual set size, chance it is less is below 1e-256 for sizes up to 32656.
5-
const generatedCharacterSetSize = (options, targetSize) => {
12+
const generatedCharacterSetSize = (cryptoRandomString, options, targetSize) => {
613
const set = new Set();
714
const length = targetSize * 640;
815
const string = cryptoRandomString({...options, length});
916

10-
for (let i = 0; i < length; i++) {
11-
set.add(string[i]);
17+
for (let index = 0; index < length; index++) {
18+
set.add(string[index]);
1219
}
1320

1421
return set.size;
1522
};
1623

17-
test('main', t => {
24+
function runTest(title, macro) {
25+
test(`Node.js: ${title}`, macro, {
26+
cryptoRandomString: nodeCryptoRandomString,
27+
cryptoRandomStringAsync: nodeCryptoRandomStringAsync,
28+
});
29+
test(`Browser: ${title}`, macro, {
30+
cryptoRandomString: browserCryptoRandomString,
31+
cryptoRandomStringAsync: browserCryptoRandomStringAsync,
32+
});
33+
}
34+
35+
runTest('main', test.macro((t, {cryptoRandomString}) => {
1836
t.is(cryptoRandomString({length: 0}).length, 0);
1937
t.is(cryptoRandomString({length: 10}).length, 10);
2038
t.is(cryptoRandomString({length: 100}).length, 100);
2139
t.regex(cryptoRandomString({length: 100}), /^[a-f\d]*$/); // Sanity check, probabilistic
22-
t.is(generatedCharacterSetSize({}, 16), 16);
23-
});
24-
25-
test('async', async t => {
26-
t.is((await cryptoRandomString.async({length: 0})).length, 0);
27-
t.is((await cryptoRandomString.async({length: 10})).length, 10);
28-
t.is((await cryptoRandomString.async({length: 100})).length, 100);
29-
t.regex(await cryptoRandomString.async({length: 100}), /^[a-f\d]*$/); // Sanity check, probabilistic
30-
});
31-
32-
test('hex', t => {
40+
t.is(generatedCharacterSetSize(cryptoRandomString, {}, 16), 16);
41+
}));
42+
43+
runTest('async', test.macro(async (t, {cryptoRandomStringAsync}) => {
44+
/* eslint-disable unicorn/no-await-expression-member */
45+
t.is((await cryptoRandomStringAsync({length: 0})).length, 0);
46+
t.is((await cryptoRandomStringAsync({length: 10})).length, 10);
47+
t.is((await cryptoRandomStringAsync({length: 100})).length, 100);
48+
/* eslint-enable unicorn/no-await-expression-member */
49+
t.regex(await cryptoRandomStringAsync({length: 100}), /^[a-f\d]*$/); // Sanity check, probabilistic
50+
}));
51+
52+
runTest('hex', test.macro((t, {cryptoRandomString}) => {
3353
t.is(cryptoRandomString({length: 0, type: 'hex'}).length, 0);
3454
t.is(cryptoRandomString({length: 10, type: 'hex'}).length, 10);
3555
t.is(cryptoRandomString({length: 100, type: 'hex'}).length, 100);
3656
t.regex(cryptoRandomString({length: 100, type: 'hex'}), /^[a-f\d]*$/); // Sanity check, probabilistic
37-
t.is(generatedCharacterSetSize({type: 'hex'}, 16), 16);
38-
});
57+
t.is(generatedCharacterSetSize(cryptoRandomString, {type: 'hex'}, 16), 16);
58+
}));
3959

40-
test('base64', t => {
60+
runTest('base64', test.macro((t, {cryptoRandomString}) => {
4161
t.is(cryptoRandomString({length: 0, type: 'base64'}).length, 0);
4262
t.is(cryptoRandomString({length: 10, type: 'base64'}).length, 10);
4363
t.is(cryptoRandomString({length: 100, type: 'base64'}).length, 100);
4464
t.regex(cryptoRandomString({length: 100, type: 'base64'}), /^[a-zA-Z\d/+]*$/); // Sanity check, probabilistic
45-
t.is(generatedCharacterSetSize({type: 'base64'}, 64), 64);
46-
});
65+
t.is(generatedCharacterSetSize(cryptoRandomString, {type: 'base64'}, 64), 64);
66+
}));
4767

48-
test('url-safe', t => {
68+
runTest('url-safe', test.macro((t, {cryptoRandomString}) => {
4969
t.is(cryptoRandomString({length: 0, type: 'url-safe'}).length, 0);
5070
t.is(cryptoRandomString({length: 10, type: 'url-safe'}).length, 10);
5171
t.is(cryptoRandomString({length: 100, type: 'url-safe'}).length, 100);
5272
t.regex(cryptoRandomString({length: 100, type: 'url-safe'}), /^[\w.~-]*$/); // Sanity check, probabilistic
53-
t.is(generatedCharacterSetSize({type: 'url-safe'}, 66), 66);
54-
});
73+
t.is(generatedCharacterSetSize(cryptoRandomString, {type: 'url-safe'}, 66), 66);
74+
}));
5575

56-
test('numeric', t => {
76+
runTest('numeric', test.macro((t, {cryptoRandomString}) => {
5777
t.is(cryptoRandomString({length: 0, type: 'numeric'}).length, 0);
5878
t.is(cryptoRandomString({length: 10, type: 'numeric'}).length, 10);
5979
t.is(cryptoRandomString({length: 100, type: 'numeric'}).length, 100);
6080
t.regex(cryptoRandomString({length: 100, type: 'numeric'}), /^\d*$/); // Sanity check, probabilistic
61-
t.is(generatedCharacterSetSize({type: 'numeric'}, 10), 10);
62-
});
81+
t.is(generatedCharacterSetSize(cryptoRandomString, {type: 'numeric'}, 10), 10);
82+
}));
6383

64-
test('distinguishable', t => {
84+
runTest('distinguishable', test.macro((t, {cryptoRandomString}) => {
6585
t.is(cryptoRandomString({length: 0, type: 'distinguishable'}).length, 0);
6686
t.is(cryptoRandomString({length: 10, type: 'distinguishable'}).length, 10);
6787
t.is(cryptoRandomString({length: 100, type: 'distinguishable'}).length, 100);
6888
t.regex(cryptoRandomString({length: 100, type: 'distinguishable'}), /^[CDEHKMPRTUWXY012458]*$/); // Sanity check, probabilistic
69-
t.is(generatedCharacterSetSize({type: 'distinguishable'}, 19), 19);
70-
});
89+
t.is(generatedCharacterSetSize(cryptoRandomString, {type: 'distinguishable'}, 19), 19);
90+
}));
7191

72-
test('ascii-printable', t => {
92+
runTest('ascii-printable', test.macro((t, {cryptoRandomString}) => {
7393
t.is(cryptoRandomString({length: 0, type: 'ascii-printable'}).length, 0);
7494
t.is(cryptoRandomString({length: 10, type: 'ascii-printable'}).length, 10);
7595
t.is(cryptoRandomString({length: 100, type: 'ascii-printable'}).length, 100);
7696
t.regex(cryptoRandomString({length: 100, type: 'ascii-printable'}), /^[!"#$%&'()*+,-./\w:;<=>?@[\\\]^`{|}~]*$/); // Sanity check, probabilistic
77-
});
97+
}));
7898

79-
test('alphanumeric', t => {
99+
runTest('alphanumeric', test.macro((t, {cryptoRandomString}) => {
80100
t.is(cryptoRandomString({length: 0, type: 'alphanumeric'}).length, 0);
81101
t.is(cryptoRandomString({length: 10, type: 'alphanumeric'}).length, 10);
82102
t.is(cryptoRandomString({length: 100, type: 'alphanumeric'}).length, 100);
83103
t.regex(cryptoRandomString({length: 100, type: 'alphanumeric'}), /^[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789]*$/); // Sanity check, probabilistic
84-
t.is(generatedCharacterSetSize({type: 'alphanumeric'}, 19), 62);
85-
});
104+
t.is(generatedCharacterSetSize(cryptoRandomString, {type: 'alphanumeric'}, 19), 62);
105+
}));
86106

87-
test('characters', t => {
107+
runTest('characters', test.macro((t, {cryptoRandomString}) => {
88108
t.is(cryptoRandomString({length: 0, characters: '1234'}).length, 0);
89109
t.is(cryptoRandomString({length: 10, characters: '1234'}).length, 10);
90110
t.is(cryptoRandomString({length: 100, characters: '1234'}).length, 100);
91111
t.regex(cryptoRandomString({length: 100, characters: '1234'}), /^[1-4]*$/); // Sanity check, probabilistic
92-
t.is(generatedCharacterSetSize({characters: '1234'}, 4), 4);
93-
t.is(generatedCharacterSetSize({characters: '0123456789'}, 10), 10);
94-
});
112+
t.is(generatedCharacterSetSize(cryptoRandomString, {characters: '1234'}, 4), 4);
113+
t.is(generatedCharacterSetSize(cryptoRandomString, {characters: '0123456789'}, 10), 10);
114+
}));
95115

96-
test('argument errors', t => {
116+
runTest('argument errors', test.macro((t, {cryptoRandomString}) => {
97117
t.throws(() => {
98118
cryptoRandomString({length: Number.POSITIVE_INFINITY});
99119
});
@@ -113,4 +133,4 @@ test('argument errors', t => {
113133
t.throws(() => {
114134
cryptoRandomString({length: 0, type: 'unknown'});
115135
});
116-
});
136+
}));

0 commit comments

Comments
 (0)
Please sign in to comment.