Repository: dubzzz/fast-check
Pull request #1200 (2020-12-01 05:21:03)

⬆️ Bump ts-jest from 26.4.1 to 26.4.4 in /example
Bumps [ts-jest](https://github.com/kulshekhar/ts-jest) from 26.4.1 to 26.4.4.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/kulshekhar/ts-jest/blob/master/CHANGELOG.md">ts-jest's changelog</a>.</em></p>
<blockquote>
<h2><a href="https://github.com/kulshekhar/ts-jest/compare/v26.4.3...v26.4.4">26.4.4</a> (2020-11-08)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>revert usage of <code>@jest/create-cache-key-function</code> (<a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/issues/2108">#2108</a>) (<a href="https://github.com/kulshekhar/ts-jest/commit/dee823172ce1e8eb9e0b2dd3aeed1ab4033bd0d9">dee8231</a>), closes <a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/issues/2080">#2080</a> <a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/issues/2090">#2090</a> <a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/issues/2104">#2104</a></li>
</ul>
<h3>Features</h3>
<ul>
<li><strong>testing:</strong> expose all types for util <code>mocked</code> (<a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/issues/2096">#2096</a>) (<a href="https://github.com/kulshekhar/ts-jest/commit/b1d072b52b9a7665b3a6914b0895f84f6ee3f8c0">b1d072b</a>), closes <a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/issues/2086">#2086</a></li>
</ul>
<h2><a href="https://github.com/kulshekhar/ts-jest/compare/v26.4.2...v26.4.3">26.4.3</a> (2020-10-26)</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>compiler:</strong> only exclude test files when initializing compiler (<a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/issues/2062">#2062</a>) (<a href="https://github.com/kulshekhar/ts-jest/commit/7264c137114b6dd895624e3476dd7ec57b64ee13">7264c13</a>), closes <a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/issues/2061">#2061</a>, <a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/issues/2068">#2068</a>, <a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/issues/2072">#2072</a>, <a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/issues/2073">#2073</a></li>
<li><strong>config:</strong> resolve <code>.babelrc</code> file path before attempting to read it (<a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/issues/2071">#2071</a>) (<a href="https://github.com/kulshekhar/ts-jest/commit/681bfef41744f09cd50b71072f4d001cb58da82e">681bfef</a>), closes <a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/issues/2064">#2064</a></li>
</ul>
<h3>Features</h3>
<ul>
<li><strong>config:</strong> allow to override resolve tsconfig behavior (<a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/issues/2063">#2063</a>) (<a href="https://github.com/kulshekhar/ts-jest/commit/9f46acefceb1fa71ee2e8b3b3c172ceb0544b4c4">9f46ace</a>)</li>
</ul>
<h2><a href="https://github.com/kulshekhar/ts-jest/compare/v26.4.1...v26.4.2">26.4.2</a> (2020-10-23)</h2>
<h3>Features</h3>
<ul>
<li><strong>config:</strong> expose several typings as public apis (<a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/issues/2054">#2054</a>) (<a href="https://github.com/kulshekhar/ts-jest/commit/3b6b7055e2b9c74e81fb91596c807ace02ab77a1">3b6b705</a>)</li>
</ul>
<h3>Performance Improvements</h3>
<ul>
<li><strong>compiler:</strong> speed up bootstrap time for <code>isolatedModules:false</code> (<a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/issues/2055">#2055</a>) (<a href="https://github.com/kulshekhar/ts-jest/commit/230b5ddbee55357d25dd190cd45aa8a30d7f31e0">230b5dd</a>)</li>
</ul>
<h3>DEPRECATIONS</h3>
<ul>
<li><strong>config</strong>: deprecate <code>tsConfig</code> in favor of <code>tsconfig</code> (<a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/pull/1997">#1997</a>)</li>
<li><strong>config</strong>: deprecate <code>packageJson</code> since internal codes don't use it anymore (<a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/pull/2034">#2034</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/kulshekhar/ts-jest/commit/5ebab219202d64b1bdba7185041cbe5337ff87ec"><code>5ebab21</code></a> chore(release): 26.4.4 (<a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/issues/2115">#2115</a>)</li>
<li><a href="https://github.com/kulshekhar/ts-jest/commit/dee823172ce1e8eb9e0b2dd3aeed1ab4033bd0d9"><code>dee8231</code></a> fix: revert usage of <code>@jest/create-cache-key-function</code> (<a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/issues/2108">#2108</a>)</li>
<li><a href="https://github.com/kulshekhar/ts-jest/commit/a42de7a14ab80d3336afbdd5e863efa7d6246ff1"><code>a42de7a</code></a> chore: removes redundant type definition install instruction  (<a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/issues/2114">#2114</a>)</li>
<li><a href="https://github.com/kulshekhar/ts-jest/commit/dc3da3cd047cf1ac026ad9d8ef90dbca6733879a"><code>dc3da3c</code></a> build(deps-dev): bump eslint-plugin-jsdoc from 30.7.6 to 30.7.7 (<a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/issues/2111">#2111</a>)</li>
<li><a href="https://github.com/kulshekhar/ts-jest/commit/5c36c9a2fae14d1b67815a79cf5492594a7727e4"><code>5c36c9a</code></a> build(deps-dev): bump @types/babel__core from 7.1.11 to 7.1.12 (<a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/issues/2112">#2112</a>)</li>
<li><a href="https://github.com/kulshekhar/ts-jest/commit/8ceda8e58b9df713b06c9737317ecb99161bb4dd"><code>8ceda8e</code></a> build(deps-dev): bump conventional-changelog-cli from 2.1.0 to 2.1.1 (<a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/issues/2110">#2110</a>)</li>
<li><a href="https://github.com/kulshekhar/ts-jest/commit/f4cc91cfea071273e3403f7c5379ea0f63dc53db"><code>f4cc91c</code></a> build(deps-dev): bump @jest/transform from 26.6.1 to 26.6.2 (<a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/issues/2109">#2109</a>)</li>
<li><a href="https://github.com/kulshekhar/ts-jest/commit/8832c45c7dbd179a81364dd45c6d98abec170739"><code>8832c45</code></a> build(ci): migrate linux tests to GitHub workflow actions (<a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/issues/2092">#2092</a>)</li>
<li><a href="https://github.com/kulshekhar/ts-jest/commit/7361e8bc6d8f00aad2574ac434bde6c2932bfefc"><code>7361e8b</code></a> build(deps-dev): bump @jest/types from 26.6.1 to 26.6.2 (<a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/issues/2100">#2100</a>)</li>
<li><a href="https://github.com/kulshekhar/ts-jest/commit/f49bb22aa5ae2a3f07619fda6b3f06cde18e5adb"><code>f49bb22</code></a> build(deps-dev): bump @typescript-eslint/eslint-plugin (<a href="https://github-redirect.dependabot.com/kulshekhar/ts-jest/issues/2098">#2098</a>)</li>
<li>Additional commits viewable in <a href="https://github.com/kulshekhar/ts-jest/compare/v26.4.1...v26.4.4">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=ts-jest&package-manager=npm_and_yarn&previous-version=26.4.1&new-version=26.4.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/configuring-github-dependabot-security-updates)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>

codesandbox[bot]: This pull request is automatically built and testable in [CodeSandbox](https://codesandbox.io).

  To see build info of the built libraries, click [here](https://ci.codesandbox.io/status/dubzzz/fast-check/pr/1200/builds/78478) or the icon next to each commit SHA.

Latest deployment of this branch, based on commit c83ec0db6afcba6671b82ad9a074f62f83bb8b7d:

|Sandbox| Source |
|--|--|
|[Vanilla](https://codesandbox.io/s/vanilla-kn47k)| Configuration |
|[fast-check-examples](https://codesandbox.io/s/fast-check-examples-nlx9s)| Configuration |

coveralls: 
[![Coverage Status](https://coveralls.io/builds/35346228/badge)](https://coveralls.io/builds/35346228)

Coverage decreased (-0.06%) to 96.441% when pulling **c83ec0db6afcba6671b82ad9a074f62f83bb8b7d on dependabot/npm_and_yarn/example/ts-jest-26.4.4** into **fcdd995c85b268aec5c6a280fec1da2c3b92895e on master**.


Patch:
diff --git a/example/package.json b/example/package.json
index a0c1ca9c..d2b99655 100644
--- a/example/package.json
+++ b/example/package.json
@@ -21,7 +21,7 @@
     "@types/lodash": "^4.14.165",
     "@types/react": "^16.9.55",
     "jest": "^26.6.2",
-    "ts-jest": "^26.4.1",
+    "ts-jest": "^26.4.4",
     "typescript": "^4.0.5"
   },
   "author": "Nicolas DUBIEN <github@dubien.org>",
diff --git a/example/yarn.lock b/example/yarn.lock
index 550446bb..6339a36a 100644
--- a/example/yarn.lock
+++ b/example/yarn.lock
@@ -2465,19 +2465,7 @@ jest-snapshot@^26.6.2:
     pretty-format "^26.6.2"
     semver "^7.3.2"
 
-jest-util@^26.1.0:
-  version "26.3.0"
-  resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.3.0.tgz#a8974b191df30e2bf523ebbfdbaeb8efca535b3e"
-  integrity sha512-4zpn6bwV0+AMFN0IYhH/wnzIQzRaYVrz1A8sYnRnj4UXDXbOVtWmlaZkO9mipFqZ13okIfN87aDoJWB7VH6hcw==
-  dependencies:
-    "@jest/types" "^26.3.0"
-    "@types/node" "*"
-    chalk "^4.0.0"
-    graceful-fs "^4.2.4"
-    is-ci "^2.0.0"
-    micromatch "^4.0.2"
-
-jest-util@^26.6.2:
+jest-util@^26.1.0, jest-util@^26.6.2:
   version "26.6.2"
   resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.6.2.tgz#907535dbe4d5a6cb4c47ac9b926f6af29576cbc1"
   integrity sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q==
@@ -3779,10 +3767,10 @@ tr46@^2.0.2:
   dependencies:
     punycode "^2.1.1"
 
-ts-jest@^26.4.1:
-  version "26.4.1"
-  resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-26.4.1.tgz#08ec0d3fc2c3a39e4a46eae5610b69fafa6babd0"
-  integrity sha512-F4aFq01aS6mnAAa0DljNmKr/Kk9y4HVZ1m6/rtJ0ED56cuxINGq3Q9eVAh+z5vcYKe5qnTMvv90vE8vUMFxomg==
+ts-jest@^26.4.4:
+  version "26.4.4"
+  resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-26.4.4.tgz#61f13fb21ab400853c532270e52cc0ed7e502c49"
+  integrity sha512-3lFWKbLxJm34QxyVNNCgXX1u4o/RV0myvA2y2Bxm46iGIjKlaY0own9gIckbjZJPn+WaJEnfPPJ20HHGpoq4yg==
   dependencies:
     "@types/jest" "26.x"
     bs-logger "0.x"
diff --git a/src/check/arbitrary/FloatNextArbitrary.ts b/src/check/arbitrary/FloatNextArbitrary.ts
index 9c5dae4c..a55f3b78 100644
--- a/src/check/arbitrary/FloatNextArbitrary.ts
+++ b/src/check/arbitrary/FloatNextArbitrary.ts
@@ -196,7 +196,7 @@ export function floatNext(constraints: FloatNextConstraints = {}): Arbitrary<num
     throw new Error('fc.floatNext constraints.min must be smaller or equal to constraints.max');
   }
   if (noNaN) {
-    return integer(minIndex, maxIndex).map(indexToFloat);
+    return integer({ min: minIndex, max: maxIndex }).map(indexToFloat);
   }
   // In case maxIndex > 0 or in other words max > 0,
   //   values will be [min, ..., +0, ..., max, NaN]
@@ -205,7 +205,7 @@ export function floatNext(constraints: FloatNextConstraints = {}): Arbitrary<num
   //   values will be [NaN, min, ..., max] with max <= +0
   const minIndexWithNaN = maxIndex > 0 ? minIndex : minIndex - 1;
   const maxIndexWithNaN = maxIndex > 0 ? maxIndex + 1 : maxIndex;
-  return integer(minIndexWithNaN, maxIndexWithNaN).map((index) => {
+  return integer({ min: minIndexWithNaN, max: maxIndexWithNaN }).map((index) => {
     if (index > maxIndex || index < minIndex) return Number.NaN;
     else return indexToFloat(index);
   });


Test patch:
diff --git a/test/unit/check/arbitrary/FloatNextArbitrary.itest.spec.ts b/test/unit/check/arbitrary/FloatNextArbitrary.itest.spec.ts
new file mode 100644
index 00000000..065ccdc7
--- /dev/null
+++ b/test/unit/check/arbitrary/FloatNextArbitrary.itest.spec.ts
@@ -0,0 +1,34 @@
+import * as fc from '../../../../lib/fast-check';
+
+import { floatNext, FloatNextConstraints } from '../../../../src/check/arbitrary/FloatNextArbitrary';
+import { floatNextConstraints, is32bits } from './generic/FloatingPointHelpers';
+import * as genericHelper from './generic/GenericArbitraryHelper';
+
+describe('FloatNextArbitrary', () => {
+  describe('floatNext', () => {
+    describe('Is valid arbitrary?', () => {
+      genericHelper.isValidArbitrary((ct?: FloatNextConstraints) => floatNext(ct), {
+        isStrictlySmallerValue: (fa, fb) =>
+          Math.abs(fa) < Math.abs(fb) || //              Case 1: abs(a) < abs(b)
+          (Object.is(fa, +0) && Object.is(fb, -0)) || // Case 2: +0 < -0  --> we shrink from -0 to +0
+          (!Number.isNaN(fa) && Number.isNaN(fb)), //    Case 3: notNaN < NaN, NaN is one of the extreme values
+        isValidValue: (g: number, ct?: FloatNextConstraints) => {
+          if (typeof g !== 'number') return false; // should always produce numbers
+          if (!is32bits(g)) return false; // should always produce 32-bit floats
+          if (Number.isNaN(g)) {
+            if (ct !== undefined && ct.noNaN) return false; // should not produce NaN if explicitely asked not too
+            return true;
+          }
+          if (ct !== undefined && ct.min !== undefined && g < ct.min) return false; // should always be greater than min when specified
+          if (ct !== undefined && ct.max !== undefined && g > ct.max) return false; // should always be smaller than max when specified
+          if (ct !== undefined && ct.noDefaultInfinity) {
+            if (ct.min === undefined && g === Number.NEGATIVE_INFINITY) return false; // should not produce -infinity when noInfity and min unset
+            if (ct.max === undefined && g === Number.POSITIVE_INFINITY) return false; // should not produce +infinity when noInfity and max unset
+          }
+          return true;
+        },
+        seedGenerator: fc.option(floatNextConstraints(), { nil: undefined }),
+      });
+    });
+  });
+});
diff --git a/test/unit/check/arbitrary/FloatNextArbitrary.spec.ts b/test/unit/check/arbitrary/FloatNextArbitrary.utest.spec.ts
similarity index 59%
rename from test/unit/check/arbitrary/FloatNextArbitrary.spec.ts
rename to test/unit/check/arbitrary/FloatNextArbitrary.utest.spec.ts
index c625d137..1b5beafe 100644
--- a/test/unit/check/arbitrary/FloatNextArbitrary.spec.ts
+++ b/test/unit/check/arbitrary/FloatNextArbitrary.utest.spec.ts
@@ -10,52 +10,61 @@ import {
   floatNext,
   FloatNextConstraints,
 } from '../../../../src/check/arbitrary/FloatNextArbitrary';
-import * as genericHelper from './generic/GenericArbitraryHelper';
-
-const float32raw = () => {
-  return fc.integer().map((n32) => new Float32Array(new Int32Array([n32]).buffer)[0]);
-};
-const float64raw = () => {
-  return fc
-    .tuple(fc.integer(), fc.integer())
-    .map(([na32, nb32]) => new Float64Array(new Int32Array([na32, nb32]).buffer)[0]);
-};
-const floatNextConstraints = () => {
-  return fc
-    .record(
-      { min: float32raw(), max: float32raw(), noDefaultInfinity: fc.boolean(), noNaN: fc.boolean() },
-      { withDeletedKeys: true }
-    )
-    .filter((ct) => (ct.min === undefined || !Number.isNaN(ct.min)) && (ct.max === undefined || !Number.isNaN(ct.max)))
-    .filter((ct) => {
-      if (!ct.noDefaultInfinity) return true;
-      if (ct.min === Number.POSITIVE_INFINITY && ct.max === undefined) return false;
-      if (ct.min === undefined && ct.max === Number.NEGATIVE_INFINITY) return false;
-      return true;
-    })
-    .map((ct) => {
-      if (ct.min === undefined || ct.max === undefined) return ct;
-      const { min, max } = ct;
-      if (min < max) return ct;
-      if (min === max && (min !== 0 || 1 / min <= 1 / max)) return ct;
-      return { ...ct, min: max, max: min };
-    });
-};
+import {
+  floatNextConstraints,
+  float32raw,
+  isNotNaN32bits,
+  float64raw,
+  isStrictlySmaller,
+  isFiniteNotNaN32bits,
+  defaultRecordConstraints,
+} from './generic/FloatingPointHelpers';
+
+import { mocked } from 'ts-jest/utils';
+import { arbitraryFor } from './generic/ArbitraryBuilder';
+import * as stubRng from '../../stubs/generators';
+
+import * as IntegerArbitraryMock from '../../../../src/check/arbitrary/IntegerArbitrary';
+jest.mock('../../../../src/check/arbitrary/IntegerArbitrary');
 
-const isStrictlySmaller = (fa: number, fb: number) => {
-  if (fa === 0 && fb === 0) return 1 / fa < 1 / fb;
-  return fa < fb;
-};
+const mrng = () => stubRng.mutable.nocall();
 
-const is32bits = (f64: number) => Object.is(new Float32Array([f64])[0], f64);
-const isNotNaN32bits = (f64: number) => !Number.isNaN(f64) && is32bits(f64);
-const isFiniteNotNaN32bits = (f64: number) => Number.isFinite(f64) && isNotNaN32bits(f64);
+function minMaxForConstraints(ct: FloatNextConstraints) {
+  const noDefaultInfinity = ct.noDefaultInfinity;
+  const {
+    min = noDefaultInfinity ? -MAX_VALUE_32 : Number.NEGATIVE_INFINITY,
+    max = noDefaultInfinity ? MAX_VALUE_32 : Number.POSITIVE_INFINITY,
+  } = ct;
+  return { min, max };
+}
+
+function mockNoOpIntegerArb(opts: { single?: boolean } = {}) {
+  // Mocking integer: not expecting any call there
+  const { integer } = mocked(IntegerArbitraryMock);
+  if (opts.single) integer.mockImplementationOnce(() => arbitraryFor([]));
+  else integer.mockImplementation(() => arbitraryFor([]));
+  return integer;
+}
+
+beforeEach(() => {
+  jest.clearAllMocks();
+  jest.resetAllMocks();
+});
+const previousGlobal = fc.readConfigureGlobal();
+fc.configureGlobal({
+  ...previousGlobal,
+  beforeEach: () => {
+    jest.clearAllMocks();
+    jest.resetAllMocks();
+  },
+});
 
 describe('FloatNextArbitrary', () => {
   describe('floatNext', () => {
     it('Should accept any valid range of 32-bit floating point numbers (including infinity)', () =>
       fc.assert(
         fc.property(floatNextConstraints(), (ct) => {
+          mockNoOpIntegerArb();
           expect(floatNext(ct)).toBeDefined();
         })
       ));
@@ -66,6 +75,7 @@ describe('FloatNextArbitrary', () => {
           fc.record({ noDefaultInfinity: fc.boolean(), noNaN: fc.boolean() }, { withDeletedKeys: true }),
           (f, otherCt) => {
             fc.pre(isNotNaN32bits(f));
+            mockNoOpIntegerArb();
             expect(floatNext({ ...otherCt, min: f, max: f })).toBeDefined();
           }
         )
@@ -74,6 +84,7 @@ describe('FloatNextArbitrary', () => {
       fc.assert(
         fc.property(float64raw(), (f64) => {
           fc.pre(!isNotNaN32bits(f64));
+          mockNoOpIntegerArb();
           expect(() => floatNext({ min: f64 })).toThrowError();
         })
       ));
@@ -81,6 +92,7 @@ describe('FloatNextArbitrary', () => {
       fc.assert(
         fc.property(float64raw(), (f64) => {
           fc.pre(!isNotNaN32bits(f64));
+          mockNoOpIntegerArb();
           expect(() => floatNext({ max: f64 })).toThrowError();
         })
       ));
@@ -90,38 +102,115 @@ describe('FloatNextArbitrary', () => {
           fc.pre(isNotNaN32bits(fa32));
           fc.pre(isNotNaN32bits(fb32));
           fc.pre(!Object.is(fa32, fb32)); // Object.is can distinguish -0 from 0, while !== cannot
+          mockNoOpIntegerArb();
           const min = isStrictlySmaller(fa32, fb32) ? fb32 : fa32;
           const max = isStrictlySmaller(fa32, fb32) ? fa32 : fb32;
           expect(() => floatNext({ min, max })).toThrowError();
         })
       ));
     it('Should reject impossible noDefaultInfinity-based ranges', () => {
+      mockNoOpIntegerArb();
       expect(() => floatNext({ min: Number.POSITIVE_INFINITY, noDefaultInfinity: true })).toThrowError();
       expect(() => floatNext({ max: Number.NEGATIVE_INFINITY, noDefaultInfinity: true })).toThrowError();
     });
-    describe('Is valid arbitrary?', () => {
-      genericHelper.isValidArbitrary((ct?: FloatNextConstraints) => floatNext(ct), {
-        isStrictlySmallerValue: (fa, fb) =>
-          Math.abs(fa) < Math.abs(fb) || //              Case 1: abs(a) < abs(b)
-          (Object.is(fa, +0) && Object.is(fb, -0)) || // Case 2: +0 < -0  --> we shrink from -0 to +0
-          (!Number.isNaN(fa) && Number.isNaN(fb)), //    Case 3: notNaN < NaN, NaN is one of the extreme values
-        isValidValue: (g: number, ct?: FloatNextConstraints) => {
-          if (typeof g !== 'number') return false; // should always produce numbers
-          if (!is32bits(g)) return false; // should always produce 32-bit floats
-          if (Number.isNaN(g)) {
-            if (ct !== undefined && ct.noNaN) return false; // should not produce NaN if explicitely asked not too
-            return true;
-          }
-          if (ct !== undefined && ct.min !== undefined && g < ct.min) return false; // should always be greater than min when specified
-          if (ct !== undefined && ct.max !== undefined && g > ct.max) return false; // should always be smaller than max when specified
-          if (ct !== undefined && ct.noDefaultInfinity) {
-            if (ct.min === undefined && g === Number.NEGATIVE_INFINITY) return false; // should not produce -infinity when noInfity and min unset
-            if (ct.max === undefined && g === Number.POSITIVE_INFINITY) return false; // should not produce +infinity when noInfity and max unset
-          }
-          return true;
-        },
-        seedGenerator: fc.option(floatNextConstraints(), { nil: undefined }),
-      });
+    it('Should properly convert integer value for index between min and max into its associated float value', () =>
+      fc.assert(
+        fc.property(fc.option(floatNextConstraints(), { nil: undefined }), fc.maxSafeNat(), (ct, mod) => {
+          // Arrange
+          const { integer } = mocked(IntegerArbitraryMock);
+          const { min, max } = minMaxForConstraints(ct || {});
+          const minIndex = floatToIndex(min);
+          const maxIndex = floatToIndex(max);
+          const arbitraryGeneratedIndex = (mod % (maxIndex - minIndex + 1)) + minIndex;
+          integer.mockImplementationOnce(() => arbitraryFor([{ value: arbitraryGeneratedIndex }]));
+
+          // Act
+          const arb = floatNext(ct);
+          const { value_: f } = arb.generate(mrng());
+
+          // Assert
+          expect(f).toBe(indexToFloat(arbitraryGeneratedIndex));
+        })
+      ));
+
+    describe('with NaN', () => {
+      const withNaNRecordConstraints = { ...defaultRecordConstraints, noNaN: fc.constant(false) };
+
+      it('Should ask for a range with one extra value (far from zero)', () =>
+        fc.assert(
+          fc.property(floatNextConstraints(withNaNRecordConstraints), fc.maxSafeInteger(), (ct) => {
+            // Arrange
+            const { max } = minMaxForConstraints(ct);
+            const integer = mockNoOpIntegerArb();
+
+            // Act
+            floatNext({ ...ct, noNaN: true });
+            floatNext(ct);
+
+            // Assert
+            expect(integer).toHaveBeenCalledTimes(2);
+            const integerConstraintsNoNaN = integer.mock.calls[0][0];
+            const integerConstraintsWithNaN = integer.mock.calls[1][0];
+            if (max > 0) {
+              // max > 0  --> NaN will be added as the greatest value
+              expect(integerConstraintsWithNaN.min).toBe(integerConstraintsNoNaN.min);
+              expect(integerConstraintsWithNaN.max).toBe(integerConstraintsNoNaN.max! + 1);
+            } else {
+              // max <= 0 --> NaN will be added as the smallest value
+              expect(integerConstraintsWithNaN.min).toBe(integerConstraintsNoNaN.min! - 1);
+              expect(integerConstraintsWithNaN.max).toBe(integerConstraintsNoNaN.max);
+            }
+          })
+        ));
+      it('Should properly convert the extra value to NaN', () =>
+        fc.assert(
+          fc.property(floatNextConstraints(withNaNRecordConstraints), fc.maxSafeNat(), (ct) => {
+            // Arrange
+            // Setup mocks for integer
+            const arbitraryGenerated = { value: Number.NaN };
+            const integer = mockNoOpIntegerArb({ single: true });
+            integer.mockImplementationOnce(() => arbitraryFor([arbitraryGenerated]));
+            // Call float next to find out the value required for NaN
+            floatNext({ ...ct, noNaN: true });
+            const arb = floatNext(ct);
+            // Extract NaN "index"
+            const { min: minNonNaN } = integer.mock.calls[0][0];
+            const { min: minNaN, max: maxNaN } = integer.mock.calls[1][0];
+            const indexForNaN = minNonNaN !== minNaN ? minNaN : maxNaN;
+            if (indexForNaN === undefined) throw new Error('No value available for NaN');
+            arbitraryGenerated.value = indexForNaN;
+
+            // Act
+            const { value_: f } = arb.generate(mrng());
+
+            // Assert
+            expect(f).toBe(Number.NaN);
+          })
+        ));
+    });
+
+    describe('without NaN', () => {
+      // eslint-disable-next-line @typescript-eslint/no-unused-vars
+      const { noNaN, ...noNaNRecordConstraints } = defaultRecordConstraints;
+
+      it('Should ask integers between the indexes corresponding to min and max', () =>
+        fc.assert(
+          fc.property(floatNextConstraints(noNaNRecordConstraints), (ctDraft) => {
+            // Arrange
+            const ct = { ...ctDraft, noNaN: true };
+            const integer = mockNoOpIntegerArb();
+            const { min, max } = minMaxForConstraints(ct);
+            const minIndex = floatToIndex(min);
+            const maxIndex = floatToIndex(max);
+
+            // Act
+            floatNext(ct);
+
+            // Assert
+            expect(integer).toHaveBeenCalledTimes(1);
+            expect(integer).toHaveBeenCalledWith({ min: minIndex, max: maxIndex });
+          })
+        ));
     });
   });
 
diff --git a/test/unit/check/arbitrary/generic/FloatingPointHelpers.ts b/test/unit/check/arbitrary/generic/FloatingPointHelpers.ts
new file mode 100644
index 00000000..31399dda
--- /dev/null
+++ b/test/unit/check/arbitrary/generic/FloatingPointHelpers.ts
@@ -0,0 +1,57 @@
+import * as fc from '../../../../../lib/fast-check';
+import { FloatNextConstraints } from '../../../../../src/check/arbitrary/FloatNextArbitrary';
+
+export function float32raw(): fc.Arbitrary<number> {
+  return fc.integer().map((n32) => new Float32Array(new Int32Array([n32]).buffer)[0]);
+}
+
+export function float64raw(): fc.Arbitrary<number> {
+  return fc
+    .tuple(fc.integer(), fc.integer())
+    .map(([na32, nb32]) => new Float64Array(new Int32Array([na32, nb32]).buffer)[0]);
+}
+
+export const defaultRecordConstraints = {
+  min: float32raw(),
+  max: float32raw(),
+  noDefaultInfinity: fc.boolean(),
+  noNaN: fc.boolean(),
+};
+
+export function floatNextConstraints(
+  recordConstraints: Partial<typeof defaultRecordConstraints> = defaultRecordConstraints
+): fc.Arbitrary<FloatNextConstraints> {
+  return fc
+    .record(recordConstraints, { withDeletedKeys: true })
+    .filter((ct) => (ct.min === undefined || !Number.isNaN(ct.min)) && (ct.max === undefined || !Number.isNaN(ct.max)))
+    .filter((ct) => {
+      if (!ct.noDefaultInfinity) return true;
+      if (ct.min === Number.POSITIVE_INFINITY && ct.max === undefined) return false;
+      if (ct.min === undefined && ct.max === Number.NEGATIVE_INFINITY) return false;
+      return true;
+    })
+    .map((ct) => {
+      if (ct.min === undefined || ct.max === undefined) return ct;
+      const { min, max } = ct;
+      if (min < max) return ct;
+      if (min === max && (min !== 0 || 1 / min <= 1 / max)) return ct;
+      return { ...ct, min: max, max: min };
+    });
+}
+
+export function isStrictlySmaller(fa: number, fb: number): boolean {
+  if (fa === 0 && fb === 0) return 1 / fa < 1 / fb;
+  return fa < fb;
+}
+
+export function is32bits(f64: number): boolean {
+  return Object.is(new Float32Array([f64])[0], f64);
+}
+
+export function isNotNaN32bits(f64: number): boolean {
+  return !Number.isNaN(f64) && is32bits(f64);
+}
+
+export function isFiniteNotNaN32bits(f64: number): boolean {
+  return Number.isFinite(f64) && isNotNaN32bits(f64);
+}