diff options
| author | Matt Mayer <[email protected]> | 2023-07-27 12:16:21 -0400 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-07-27 16:16:21 +0000 |
| commit | 3dece0904933f9632afabdacd0f2b5b32d8bde2a (patch) | |
| tree | d3851f4461667c225e98b6264b922c66d68ef1a6 | |
| parent | 052a00c27d1e6ef03850f24a2a3da51dad8d90da (diff) | |
| download | faker-3dece0904933f9632afabdacd0f2b5b32d8bde2a.tar.xz faker-3dece0904933f9632afabdacd0f2b5b32d8bde2a.zip | |
fix(helpers): prevent uniqueArray from hanging (#2239)
| -rw-r--r-- | src/modules/helpers/index.ts | 10 | ||||
| -rw-r--r-- | test/helpers.spec.ts | 8 |
2 files changed, 17 insertions, 1 deletions
diff --git a/src/modules/helpers/index.ts b/src/modules/helpers/index.ts index 92647942..28c63693 100644 --- a/src/modules/helpers/index.ts +++ b/src/modules/helpers/index.ts @@ -649,6 +649,11 @@ export class HelpersModule { * and outputs a unique array of strings based on that source. * This method does not store the unique state between invocations. * + * If there are not enough unique values to satisfy the length, if + * the source is an array, it will only return as many items as are + * in the array. If the source is a function, it will return after + * a maximum number of attempts has been reached. + * * @template T The type of the elements. * * @param source The strings to choose from or a function that generates a string. @@ -671,8 +676,11 @@ export class HelpersModule { const set = new Set<T>(); try { if (typeof source === 'function') { - while (set.size < length) { + const maxAttempts = 1000 * length; + let attempts = 0; + while (set.size < length && attempts < maxAttempts) { set.add(source()); + attempts++; } } } catch { diff --git a/test/helpers.spec.ts b/test/helpers.spec.ts index 67a2de3d..c7003dc8 100644 --- a/test/helpers.spec.ts +++ b/test/helpers.spec.ts @@ -806,6 +806,14 @@ describe('helpers', () => { expect(unique).toHaveLength(input.length); }); + it('function with length longer than possible values returns', () => { + const fn = () => faker.helpers.arrayElement(['a', 'b']); + const length = 3; + const unique = faker.helpers.uniqueArray(fn, length); + expect(unique).not.toContainDuplicates(); + expect(unique).toHaveLength(2); + }); + it('works as expected when seeded', () => { const input = ['a', 'a', 'a', 'a', 'a', 'f', 'g', 'h', 'i', 'j']; const length = 5; |
