Skip to content

Commit

Permalink
✨ Add option to generate unicode values in json (#5011)
Browse files Browse the repository at this point in the history
**Description**

Same idea as for #5010 but extended to `json` and `jsonValue`.

With this new flag, we also deprecate unicode versions as they don't
need to live on their own anymore. As such they can just be replaced by
the default version. The flag is by default to true but will be moved to
false in v4.

<!-- Please provide a short description and potentially linked issues
hustifying the need for this PR -->

<!-- * Your PR is fixing a bug or regression? Check for existing issues
related to this bug and link them -->
<!-- * Your PR is adding a new feature? Make sure there is a related
issue or discussion attached to it -->

<!-- You can provide any additional context to help into understanding
what's this PR is attempting to solve: reproduction of a bug, code
snippets... -->

**Checklist** — _Don't delete this checklist and make sure you do the
following before opening the PR_

- [x] The name of my PR follows [gitmoji](https://gitmoji.dev/)
specification
- [x] My PR references one of several related issues (if any)
- [x] New features or breaking changes must come with an associated
Issue or Discussion
- [x] My PR does not add any new dependency without an associated Issue
or Discussion
- [x] My PR includes bumps details, please run `yarn bump` and flag the
impacts properly
- [x] My PR adds relevant tests and they would have failed without my PR
(when applicable)

<!-- More about contributing at
https://github.com/dubzzz/fast-check/blob/main/CONTRIBUTING.md -->

**Advanced**

<!-- How to fill the advanced section is detailed below! -->

- [x] Category: ✨ Introduce new features
- [x] Impacts: Deprecate arbitraries

<!-- [Category] Please use one of the categories below, it will help us
into better understanding the urgency of the PR -->
<!-- * ✨ Introduce new features -->
<!-- * 📝 Add or update documentation -->
<!-- * ✅ Add or update tests -->
<!-- * 🐛 Fix a bug -->
<!-- * 🏷️ Add or update types -->
<!-- * ⚡️ Improve performance -->
<!-- * _Other(s):_ ... -->

<!-- [Impacts] Please provide a comma separated list of the potential
impacts that might be introduced by this change -->
<!-- * Generated values: Can your change impact any of the existing
generators in terms of generated values, if so which ones? when? -->
<!-- * Shrink values: Can your change impact any of the existing
generators in terms of shrink values, if so which ones? when? -->
<!-- * Performance: Can it require some typings changes on user side?
Please give more details -->
<!-- * Typings: Is there a potential performance impact? In which cases?
-->
  • Loading branch information
dubzzz authored May 22, 2024
1 parent 50394c8 commit 49abe92
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 17 deletions.
8 changes: 8 additions & 0 deletions .yarn/versions/dd3b347d.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
releases:
fast-check: minor

declined:
- "@fast-check/ava"
- "@fast-check/jest"
- "@fast-check/vitest"
- "@fast-check/worker"
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ import type { ObjectConstraints } from './QualifiedObjectConstraints';
/**
* Shared constraints for:
* - {@link json},
* - {@link unicodeJson},
* - {@link jsonValue},
* - {@link unicodeJsonValue}
*
* @remarks Since 2.5.0
* @public
Expand All @@ -29,6 +27,36 @@ export interface JsonSharedConstraints {
* @remarks Since 2.5.0
*/
maxDepth?: number;
/**
* Only generate instances having keys and values made of ascii strings (when true)
* @defaultValue true
* @remarks Since 3.19.0
*/
noUnicodeString?: boolean;
}

/**
* Shared constraints for:
* - {@link unicodeJson},
* - {@link unicodeJsonValue}
*
* @remarks Since 3.19.0
* @public
*/
export interface UnicodeJsonSharedConstraints {
/**
* Limit the depth of the object by increasing the probability to generate simple values (defined via values)
* as we go deeper in the object.
*
* @remarks Since 2.20.0
*/
depthSize?: DepthSize;
/**
* Maximal depth allowed
* @defaultValue Number.POSITIVE_INFINITY — _defaulting seen as "max non specified" when `defaultSizeToMaxWhenMaxSpecified=true`_
* @remarks Since 2.5.0
*/
maxDepth?: number;
}

/**
Expand Down
5 changes: 4 additions & 1 deletion packages/fast-check/src/arbitrary/jsonValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { string } from './string';
import type { JsonSharedConstraints, JsonValue } from './_internals/helpers/JsonConstraintsBuilder';
import { jsonConstraintsBuilder } from './_internals/helpers/JsonConstraintsBuilder';
import { anything } from './anything';
import { fullUnicodeString } from './fullUnicodeString';

export type { JsonSharedConstraints, JsonValue };

Expand All @@ -20,5 +21,7 @@ export type { JsonSharedConstraints, JsonValue };
* @public
*/
export function jsonValue(constraints: JsonSharedConstraints = {}): Arbitrary<JsonValue> {
return anything(jsonConstraintsBuilder(string(), constraints)) as Arbitrary<JsonValue>;
const noUnicodeString = constraints.noUnicodeString === undefined || constraints.noUnicodeString === true;
const stringArbitrary = noUnicodeString ? string() : fullUnicodeString();
return anything(jsonConstraintsBuilder(stringArbitrary, constraints)) as Arbitrary<JsonValue>;
}
7 changes: 4 additions & 3 deletions packages/fast-check/src/arbitrary/unicodeJson.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { Arbitrary } from '../check/arbitrary/definition/Arbitrary';
import { unicodeJsonValue } from './unicodeJsonValue';
import type { JsonSharedConstraints } from './_internals/helpers/JsonConstraintsBuilder';
import type { UnicodeJsonSharedConstraints } from './_internals/helpers/JsonConstraintsBuilder';

export type { JsonSharedConstraints };
export type { UnicodeJsonSharedConstraints };

/**
* For any JSON strings with unicode support
Expand All @@ -11,10 +11,11 @@ export type { JsonSharedConstraints };
*
* @param constraints - Constraints to be applied onto the generated instance (since 2.5.0)
*
* @deprecated Prefer using {@link json} with `noUnicodeString: false`, it will generate even more unicode strings: includings some having characters outside of BMP plan
* @remarks Since 0.0.7
* @public
*/
export function unicodeJson(constraints: JsonSharedConstraints = {}): Arbitrary<string> {
export function unicodeJson(constraints: UnicodeJsonSharedConstraints = {}): Arbitrary<string> {
const arb = unicodeJsonValue(constraints);
return arb.map(JSON.stringify);
}
7 changes: 4 additions & 3 deletions packages/fast-check/src/arbitrary/unicodeJsonValue.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { Arbitrary } from '../check/arbitrary/definition/Arbitrary';
import { unicodeString } from './unicodeString';
import type { JsonSharedConstraints, JsonValue } from './_internals/helpers/JsonConstraintsBuilder';
import type { UnicodeJsonSharedConstraints, JsonValue } from './_internals/helpers/JsonConstraintsBuilder';
import { jsonConstraintsBuilder } from './_internals/helpers/JsonConstraintsBuilder';
import { anything } from './anything';

export type { JsonSharedConstraints, JsonValue };
export type { UnicodeJsonSharedConstraints, JsonValue };

/**
* For any JSON compliant values with unicode support
Expand All @@ -16,9 +16,10 @@ export type { JsonSharedConstraints, JsonValue };
*
* @param constraints - Constraints to be applied onto the generated instance
*
* @deprecated Prefer using {@link jsonValue} with `noUnicodeString: false`, it will generate even more unicode strings: includings some having characters outside of BMP plan
* @remarks Since 2.20.0
* @public
*/
export function unicodeJsonValue(constraints: JsonSharedConstraints = {}): Arbitrary<JsonValue> {
export function unicodeJsonValue(constraints: UnicodeJsonSharedConstraints = {}): Arbitrary<JsonValue> {
return anything(jsonConstraintsBuilder(unicodeString(), constraints)) as Arbitrary<JsonValue>;
}
2 changes: 2 additions & 0 deletions packages/fast-check/src/fast-check-default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ import { mixedCase } from './arbitrary/mixedCase';
import type { ObjectConstraints } from './arbitrary/object';
import { object } from './arbitrary/object';
import type { JsonSharedConstraints } from './arbitrary/json';
import type { UnicodeJsonSharedConstraints } from './arbitrary/unicodeJson';
import { json } from './arbitrary/json';
import { anything } from './arbitrary/anything';
import { unicodeJsonValue } from './arbitrary/unicodeJsonValue';
Expand Down Expand Up @@ -277,6 +278,7 @@ export type {
IntArrayConstraints,
IntegerConstraints,
JsonSharedConstraints,
UnicodeJsonSharedConstraints,
LoremConstraints,
MixedCaseConstraints,
NatConstraints,
Expand Down
1 change: 1 addition & 0 deletions packages/fast-check/test/unit/arbitrary/jsonValue.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ describe('jsonValue (integration)', () => {
{
depthSize: fc.oneof(fc.double({ min: 0.1, noNaN: true }), sizeArb),
maxDepth: fc.nat({ max: 5 }),
noUnicodeString: fc.boolean(),
},
{ requiredKeys: [] },
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { describe, it, expect } from 'vitest';
import fc from 'fast-check';

import type { JsonSharedConstraints } from '../../../src/arbitrary/unicodeJsonValue';
import type { UnicodeJsonSharedConstraints } from '../../../src/arbitrary/unicodeJsonValue';
import { unicodeJsonValue } from '../../../src/arbitrary/unicodeJsonValue';
import {
assertProduceCorrectValues,
Expand All @@ -14,7 +14,7 @@ import { isObjectWithNumericKeys } from './__test-helpers__/ObjectWithNumericKey
import { sizeArb } from './__test-helpers__/SizeHelpers';

describe('unicodeJsonValue (integration)', () => {
type Extra = JsonSharedConstraints | undefined;
type Extra = UnicodeJsonSharedConstraints | undefined;
const extraParameters: fc.Arbitrary<Extra> = fc.option(
fc
.record(
Expand Down
32 changes: 26 additions & 6 deletions website/docs/core-blocks/arbitraries/fake-data/file.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,13 @@ All the string values (from keys to values) are generated using `fc.string()`.
**Signatures:**

- `fc.json()`
- `fc.json({depthSize?, maxDepth?})`
- `fc.json({depthSize?, maxDepth?, noUnicodeString?})`

**with:**

- `depthSize?` — default: `undefined` [more](/docs/configuration/larger-entries-by-default/#depth-size-explained)_how much we allow our recursive structures to be deep?_
- `maxDepth?` — default: `Number.POSITIVE_INFINITY`_maximal depth of generated objects_
- `noUnicodeString?` — default: `true`_toggle on/off the generation of strings used either as keys or values of the instance and including non-ascii characters_

**Usages:**

Expand All @@ -76,6 +77,15 @@ fc.json();
// • "[null,-1.5485504457576672e+192,null,{},-1.417727947024272e-287,null,null,null]"
// • …

fc.json({ noUnicodeString: false });
// Examples of generated values:
// • "{}"
// • "[{\"󜁳򁿳򎗯􈤘񖇅\":null,\"򈷩𫨹􏥃򤵪񥉨񢦜꣙\":[null,\"򉲨򛨰𜥲񆠉򁀿񇆾􀤯񾱄\"],\"__def\":\"񥛡\",\"𴂏򰷳𩪎񡨫\":true,\"2􏿺\":\"\",\"􍥚󛂾𓴒\":false},[3.5931489320423776e+139,[true,\"󌘅񪜆󗛃󎩻𙹖򞠚򺳵񨶖\",false,{\"􊆪򓔝򘥬𔧥󴓌򩁆\":null,\"\":\"󌽡𗀥󚨿󊭹򎻎񀓜򧅘򏜣󨓚񯄈\",\"𽸧򽂵񯆎񷡰𑴵񞱒\":[true,\"򀲑򿒦\",true,\"􊔹񒚡𣉟𳡸񮋳󳝶\",false,-4.119935921393037e+259,null,-8.9364525362984475e+248]},\"򸀿󳿴񥘡򪠾򃰧򣖏\",\"󱝇򹢖𬂏񠤫󴕠򒐧\"]],[false,-6.0502670401327095e+112,1.1096547717393745e-177,null,null,null,false,[null,\"󘳑㨦𭦄񱹂𚃜򅅪󪃗򟓓󊕝򠗺\",1.288654068889961e-213,null,1.6406299790913147e-206]]]"
// • "\"򁤇𫍯􏿬$񞋰%򟱉򳟔󽐾\""
// • "[null,[{\"壏\":true,\"𮀳񠍞󗈌\":\"耕򰶤䰅𸬣\",\"\":null,\"𘥣񯙝𖹟󗨟𯵽򿈤􊇦󣌙󸫨󸅔\":true,\"󒾠򈄕󬀘𚨶󍋤񃞜𮢌􇶸񏭘\":null,\"񮹷񀚤󷅓󰪼􀆌𥰂𫃩𧆔𹷹󭼜\":true,\"󛶋򣄚񼇏򡭇󹃤󢁬𞲢\":-4.059178361848322e-91,\"򉁀򠾫𓦞𑬞󵫽򏥷񹺏􌗈\":true},null],[3.6448982683876056e+131]]"
// • "[null,false]"
// • …

fc.json({ maxDepth: 0 });
// Examples of generated values: "null", "\"T\"", "-1.6050118268310372e-215", "true", "\"Ep\""…

Expand Down Expand Up @@ -109,12 +119,13 @@ As `JSON.parse` preserves `-0`, `jsonValue` can also have `-0` as a value.
**Signatures:**

- `fc.jsonValue()`
- `fc.jsonValue({depthSize?, maxDepth?})`
- `fc.jsonValue({depthSize?, maxDepth?, noUnicodeString?})`

**with:**

- `depthSize?` — default: `undefined` [more](/docs/configuration/larger-entries-by-default/#depth-size-explained)_how much we allow our recursive structures to be deep?_
- `maxDepth?` — default: `Number.POSITIVE_INFINITY`_maximal depth for generated objects (Map and Set included into objects)_
- `noUnicodeString?` — default: `true`_toggle on/off the generation of strings used either as keys or values of the instance and including non-ascii characters_

**Usages:**

Expand All @@ -128,6 +139,15 @@ fc.jsonValue();
// • [null,true,true,"`l+$I","kSros",null]
// • …

fc.jsonValue({ noUnicodeString: false });
// Examples of generated values:
// • ["򴾼󹤷𡅤񤱓򛗡"]
// • {"􎵔򲁼򀎈𸝔􃌅􊿛񹙦":[false],"򨊗𤮈𡈡󵑑񗀏򏗔𙔔𐸵񇘼":556603.8398649627,"􏿽+򸑽":{"񐀞󴕃󙉅񂊠𴛐󻕀㢋񦔘":true,"񊈒􋚭󷪙𫪀󌧶񉝒𱣆":null,"":5.539268054957889e+74,"򦹷":"񜝍⌳򻍜񇓷񖋦","񥸱񥊔򦹗":4.847354156832373e-25,"񜂑򹏁󞦐":"𻬫𳤲󵹃򕏧񁃵","𓧎𖰦":false,"󛻳򏜚񃛷񌛑𝜀󞅤񪉺":false}}
// • [null,["󿦼񌅡󯻾𝀹򲓋񁆺񐿏󃢰",-2.4628931920258706e-282,null,false,2.681696006505804e-238,"򢰮"]]
// • "򐐩"
// • []
// • …

fc.jsonValue({ maxDepth: 0 });
// Examples of generated values: true, null, false, "prototype", "L4)5M"…

Expand Down Expand Up @@ -210,8 +230,8 @@ All the string values (from keys to values) are generated using `fc.unicodeStrin

**Signatures:**

- `fc.unicodeJson()`
- `fc.unicodeJson({depthSize?, maxDepth?})`
- `fc.unicodeJson()`_deprecated since v3.19.0 ([#5011](https://github.com/dubzzz/fast-check/pull/5011))_
- `fc.unicodeJson({depthSize?, maxDepth?})`_deprecated since v3.19.0 ([#5011](https://github.com/dubzzz/fast-check/pull/5011))_

**with:**

Expand Down Expand Up @@ -268,8 +288,8 @@ As `JSON.parse` preserves `-0`, `unicodeJsonValue` can also have `-0` as a value

**Signatures:**

- `fc.unicodeJsonValue()`
- `fc.unicodeJsonValue({depthSize?, maxDepth?})`
- `fc.unicodeJsonValue()`_deprecated since v3.19.0 ([#5011](https://github.com/dubzzz/fast-check/pull/5011))_
- `fc.unicodeJsonValue({depthSize?, maxDepth?})`_deprecated since v3.19.0 ([#5011](https://github.com/dubzzz/fast-check/pull/5011))_

**with:**

Expand Down

0 comments on commit 49abe92

Please sign in to comment.