Skip to content

feat(helpers): add length range support in arrayElements #1772

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jan 26, 2023
32 changes: 23 additions & 9 deletions src/modules/helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -561,36 +561,50 @@ export class HelpersModule {
*
* @template T The type of the entries to pick from.
* @param array Array to pick the value from.
* @param count Number of elements to pick.
* @param count Number or range of elements to pick.
* When not provided, random number of elements will be picked.
* When value exceeds array boundaries, it will be limited to stay inside.
*
* @example
* faker.helpers.arrayElements(['cat', 'dog', 'mouse']) // ['mouse', 'cat']
* faker.helpers.arrayElements([1, 2, 3, 4, 5], 2) // [4, 2]
* faker.helpers.arrayElements([1, 2, 3, 4, 5], { min: 2, max: 4 }) // [3, 5, 1]
*
* @since 6.3.0
*/
arrayElements<T>(
// TODO @Shinigami92 2022-04-30: We want to remove this default value, but currently it's not possible because some definitions could be empty
// See https://github.com/faker-js/faker/issues/893
array: ReadonlyArray<T> = ['a', 'b', 'c'] as unknown as ReadonlyArray<T>,
count?: number
count?:
| number
| {
/**
* The minimum number of elements to pick.
*/
min: number;
/**
* The maximum number of elements to pick.
*/
max: number;
}
): T[] {
if (typeof count !== 'number') {
count =
let numElements = this.rangeToNumber(count);

if (typeof numElements !== 'number') {
numElements =
array.length === 0
? 0
: this.faker.number.int({ min: 1, max: array.length });
} else if (count > array.length) {
count = array.length;
} else if (count < 0) {
count = 0;
} else if (numElements > array.length) {
numElements = array.length;
} else if (numElements < 0) {
numElements = 0;
}

const arrayCopy = array.slice(0);
let i = array.length;
const min = i - count;
const min = i - numElements;
let temp: T;
let index: number;

Expand Down
42 changes: 42 additions & 0 deletions test/__snapshots__/helpers.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,21 @@ exports[`helpers > 42 > arrayElement > with array 1`] = `"o"`;

exports[`helpers > 42 > arrayElements > noArgs 1`] = `
[
"a",
"b",
"c",
]
`;

exports[`helpers > 42 > arrayElements > with array 1`] = `
[
" ",
"l",
"o",
"!",
"H",
"l",
"o",
"r",
"W",
"e",
Expand All @@ -29,6 +37,13 @@ exports[`helpers > 42 > arrayElements > with array and count 1`] = `
]
`;

exports[`helpers > 42 > arrayElements > with array and count range 1`] = `
[
"d",
"l",
]
`;

exports[`helpers > 42 > fake > with a dynamic template 1`] = `"my string: Cky2eiXX/J"`;

exports[`helpers > 42 > fake > with a static template 1`] = `"my test string"`;
Expand Down Expand Up @@ -218,6 +233,16 @@ exports[`helpers > 1211 > arrayElements > with array and count 1`] = `
]
`;

exports[`helpers > 1211 > arrayElements > with array and count range 1`] = `
[
"H",
"e",
"o",
"l",
" ",
]
`;

exports[`helpers > 1211 > fake > with a dynamic template 1`] = `"my string: wKti5-}$_/"`;

exports[`helpers > 1211 > fake > with a static template 1`] = `"my test string"`;
Expand Down Expand Up @@ -382,12 +407,22 @@ exports[`helpers > 1337 > arrayElement > with array 1`] = `"l"`;

exports[`helpers > 1337 > arrayElements > noArgs 1`] = `
[
"c",
"a",
"b",
]
`;

exports[`helpers > 1337 > arrayElements > with array 1`] = `
[
"!",
"r",
"o",
" ",
"d",
"H",
"l",
"o",
"l",
"l",
"e",
Expand All @@ -403,6 +438,13 @@ exports[`helpers > 1337 > arrayElements > with array and count 1`] = `
]
`;

exports[`helpers > 1337 > arrayElements > with array and count range 1`] = `
[
"e",
"W",
]
`;

exports[`helpers > 1337 > fake > with a dynamic template 1`] = `"my string: 9U/4:SK$>6"`;

exports[`helpers > 1337 > fake > with a static template 1`] = `"my test string"`;
Expand Down
26 changes: 25 additions & 1 deletion test/helpers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,11 @@ describe('helpers', () => {
t.describe('arrayElements', (t) => {
t.it('noArgs')
.it('with array', 'Hello World!'.split(''))
.it('with array and count', 'Hello World!'.split(''), 3);
.it('with array and count', 'Hello World!'.split(''), 3)
.it('with array and count range', 'Hello World!'.split(''), {
min: 1,
max: 5,
});
});

t.describe('shuffle', (t) => {
Expand Down Expand Up @@ -281,6 +285,26 @@ describe('helpers', () => {
expect(subset).toHaveLength(new Set(subset).size);
});

it('should return a subset with random elements in the array for a length range', () => {
const testArray = ['hello', 'to', 'you', 'my', 'friend'];
const subset = faker.helpers.arrayElements(testArray, {
min: 2,
max: 4,
});

// Check length
expect(subset.length).toBeGreaterThanOrEqual(2);
expect(subset.length).toBeLessThanOrEqual(4);

// Check elements
subset.forEach((element) => {
expect(testArray).toContain(element);
});

// Check uniqueness
expect(subset).toHaveLength(new Set(subset).size);
});

it('should return an empty array when receiving an empty array', () => {
const result = faker.helpers.arrayElements([]);

Expand Down