Skip to content

fix(compat/random): compatibility issues with random function - #1767

Merged
raon0211 merged 3 commits into
toss:mainfrom
Antoliny0919:fix-compability-random
Jun 24, 2026
Merged

raon0211 merged 3 commits into
toss:mainfrom
Antoliny0919:fix-compability-random

Conversation

@Antoliny0919

@Antoliny0919 Antoliny0919 commented Jun 13, 2026 •

Copy link
Copy Markdown
Contributor

Incorrect Range(floating=true) -> b15a478

Summary

Currently, when floating is true, values are returned in a range 1 higher than max.
e.g. when min=1, max=2 with floating enabled, values like 2.xx can be returned.

Reproduce

import { random as loRandom } from 'lodash';
import { random as esRandom } from './src/compat/math/random';

const call = 500;

function checkOver(value) {
  if (value > 2) {
    return true;
  }
}

let loOver2 = 0;
let esOver2 = 0;

for (let i = 0; i < call; i++) {
  const value = loRandom(1, 2, true);
  if (checkOver(value)) {
    loOver2 += 1;
  }
}

for (let i = 0; i < call; i++) {
  const value = esRandom(1, 2, true);
  if (checkOver(value)) {
    esOver2 += 1;
  }
}

console.log(loOver2); // 0
console.log(esOver2); // 246

Return integer when float value in parameter -> fdf699b

Summary

  • random(1.5, 2.5)
  • random(1.5)
  • random(1.5, 2)

In all of the above cases, integers are returned.
However, Lodash returns a float if at least one float value is included in the arguments.

REproduce

import { random as loRandom } from 'lodash';
import { random as esCompatRandom } from './src/compat/math/random';

const call = 500;

let loIsInteger = 0;
let esCompatIsInteger = 0;

for (let i = 0; i < call; i++) {
  const value = loRandom(1.5, 2.5);
  if (Number.isInteger(value)) {
    loIsInteger += 1;
  }
}

for (let i = 0; i < call; i++) {
  const value = esCompatRandom(1.5, 2.5);
  if (Number.isInteger(value)) {
    esCompatIsInteger += 1;
  }
}

console.log(loIsInteger); // 0
console.log(esCompatIsInteger); // 500

Return integer when (max=1, floating=true) case -> dafe6d4

Summary

Returns an integer when called with (max=some..., floating=true)
Shouldn't it return a float since floating=true 😁

Reproduce

import { random as loRandom } from 'lodash';
import { random as esCompatRandom } from './src/compat/math/random';

const call = 500;

let loIsInteger = 0;
let esCompatIsInteger = 0;

for (let i = 0; i < call; i++) {
  const value = loRandom(2, true);
  if (Number.isInteger(value)) {
    loIsInteger += 1;
  }
}

for (let i = 0; i < call; i++) {
  const value = esCompatRandom(2, true);
  if (Number.isInteger(value)) {
    esCompatIsInteger += 1;
  }
}

console.log(loIsInteger); // 0
console.log(esCompatIsInteger); // 500

@vercel

vercel Bot commented Jun 13, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
es-toolkit Ready Ready Preview, Comment Jun 23, 2026 5:18am

Request Review

@Antoliny0919

Antoliny0919 commented Jun 17, 2026 •

Copy link
Copy Markdown
Contributor Author

I came across a useful tool for checking compat(skill)-> https://github.com/toss/es-toolkit/blob/main/.claude/skills/compat-review/SKILL.md
What do you think about making it available to run on PR 🤔
We could trigger it when a specific label is applied.

Having it automatically generate a report would make it much easier for reviewers to evaluate the changes.

}
});

it('should support floats', () => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test actually comes from lodash, so I'd rather not change it much — especially the expect assertions. Could we keep those as-is and just add more tests on top instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course! I'll take a look over the weekend 😁

expect(samples.every(v => v >= 0 && v <= max)).toBeTruthy();
});

it('should support floats', () => {

@Antoliny0919 Antoliny0919 Jun 23, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

* @see https://github.com/lodash/lodash/blob/6a2cc1dfcf7634fea70d1bc5bd22db453df67b42/test/chunk.spec.js#L1

One thing I'm curious about: I noticed that some compat tests include links to the corresponding Lodash test cases, but many others (such as random) don't.

Is there a general convention around this?

If the goal is to keep Lodash's original test cases intact, would it make sense to split them into two describe blocks?

first describe: test cases from Lodash
second describe: additional test cases added by es-toolkit

I'm not sure why some tests have links while others don't, but it feels like we could benefit from a bit more consistency. Separating the tests might also make their purpose clearer.

(Though I admit that could turn into a somewhat tedious task... maybe manageable with a little help from AI 🤔)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally, every test should have a link pointing to its equivalent Lodash test. I think some contributors just omitted them along the way as we received contributions from many different people.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, I've taken a look 😁
It might take a bit of time, but I'll work on it.

While working on this, I felt it would be better to keep the two tests separated. When we revisit them in the future, it will be much easier to identify which tests originated from Lodash and which ones were added by us. I think that distinction will make the test suite much easier to understand and maintain.

@raon0211
raon0211 merged commit e008a28 into toss:main Jun 24, 2026
10 checks passed

This branch was successfully deployed

1 active deployment
Preview — f66f887b Deployed Jun 23, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants