Skip to content

Commit 50c4f2a

Browse files
authored
✨ Add support for string-unit on object/anything arbitrary (#5366)
**Description** <!-- Please provide a short description and potentially linked issues justifying the need for this PR --> The `unit` field has been added pretty recently to `string` in order to offer ways for our users to control in a more granular way what kind of "character" they would like to be generated for their strings. In order not to mix "character" with the characters in JavaScript and to allow any feasible grapheme or combination of code-points to be a valid "character" we refer to them as "unit". This PR adds supports for units of strings from object builders. <!-- * 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: New flags for finer control on some 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? -->
1 parent 4244de4 commit 50c4f2a

File tree

4 files changed

+29
-7
lines changed

4 files changed

+29
-7
lines changed

.changeset/chilly-apes-watch.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"fast-check": minor
3+
---
4+
5+
✨ Add support for string-`unit` on `object`/`anything` arbitrary

packages/fast-check/src/arbitrary/_internals/helpers/QualifiedObjectConstraints.ts

+11-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { fullUnicodeString } from '../../fullUnicodeString';
66
import { maxSafeInteger } from '../../maxSafeInteger';
77
import { oneof } from '../../oneof';
88
import { string } from '../../string';
9+
import type { StringConstraints } from '../../string';
910
import { boxedArbitraryBuilder } from '../builders/BoxedArbitraryBuilder';
1011
import type { DepthSize, SizeForArbitrary } from './MaxLengthFromMinLength';
1112

@@ -107,10 +108,17 @@ export interface ObjectConstraints {
107108
/**
108109
* Replace the arbitrary of strings defaulted for key and values by one able to generate unicode strings with non-ascii characters.
109110
* If you override key and/or values constraint, this flag will not apply to your override.
111+
* @deprecated Prefer using `stringUnit` to customize the kind of strings that will be generated by default.
110112
* @defaultValue false
111113
* @remarks Since 3.19.0
112114
*/
113115
withUnicodeString?: boolean;
116+
/**
117+
* Replace the default unit for strings.
118+
* @defaultValue undefined
119+
* @remarks Since 3.23.0
120+
*/
121+
stringUnit?: StringConstraints['unit'];
114122
}
115123

116124
/** @internal */
@@ -121,7 +129,7 @@ type ObjectConstraintsOptionalValues = 'depthSize' | 'maxDepth' | 'maxKeys' | 's
121129
* @internal
122130
*/
123131
export type QualifiedObjectConstraints = Required<
124-
Omit<ObjectConstraints, 'withBoxedValues' | 'withUnicodeString' | ObjectConstraintsOptionalValues>
132+
Omit<ObjectConstraints, 'withBoxedValues' | 'withUnicodeString' | 'stringUnit' | ObjectConstraintsOptionalValues>
125133
> &
126134
Pick<ObjectConstraints, ObjectConstraintsOptionalValues>;
127135

@@ -160,8 +168,8 @@ export function toQualifiedObjectConstraints(settings: ObjectConstraints = {}):
160168
function orDefault<T>(optionalValue: T | undefined, defaultValue: T): T {
161169
return optionalValue !== undefined ? optionalValue : defaultValue;
162170
}
163-
const stringArbitrary = settings.withUnicodeString ? fullUnicodeString : string;
164-
const valueConstraints = { size: settings.size };
171+
const stringArbitrary = 'stringUnit' in settings ? string : settings.withUnicodeString ? fullUnicodeString : string;
172+
const valueConstraints = { size: settings.size, unit: settings.stringUnit };
165173
return {
166174
key: orDefault(settings.key, stringArbitrary(valueConstraints)),
167175
values: boxArbitrariesIfNeeded(

packages/fast-check/test/unit/arbitrary/_internals/builders/AnyArbitraryBuilder.spec.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,13 @@ describe('anyArbitraryBuilder (integration)', () => {
103103
withSparseArray: fc.boolean(),
104104
withTypedArray: fc.boolean(),
105105
withUnicodeString: fc.boolean(),
106+
stringUnit: fc.constantFrom<ObjectConstraints['stringUnit']>(
107+
'grapheme',
108+
'grapheme-composite',
109+
'grapheme-ascii',
110+
'binary',
111+
'binary-ascii',
112+
),
106113
},
107114
{ requiredKeys: [] },
108115
)
@@ -149,7 +156,7 @@ describe('anyArbitraryBuilder (integration)', () => {
149156
if (!extra.withTypedArray) {
150157
expect(isTypedArray(v)).toBe(false);
151158
}
152-
if (!extra.withUnicodeString) {
159+
if (!extra.withUnicodeString && !('stringUnit' in extra)) {
153160
expect(stringify(v)).toSatisfy(doesNotIncludeAnySurrogateCharacter);
154161
}
155162
// No check for !extra.withObjectString as nothing prevent normal string builders to build such strings

website/docs/core-blocks/arbitraries/composites/object.md

+5-3
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ Generate objects (key/values).
165165
**Signatures:**
166166

167167
- `fc.object()`
168-
- `fc.object({key?, depthSize?, maxDepth?, maxKeys?, size?, withBigInt?, withBoxedValues?, withDate?, withMap?, withNullPrototype?, withObjectString?, withSet?, withTypedArray?, withSparseArray?, withUnicodeString?, values?})`
168+
- `fc.object({key?, depthSize?, maxDepth?, maxKeys?, size?, withBigInt?, withBoxedValues?, withDate?, withMap?, withNullPrototype?, withObjectString?, withSet?, withTypedArray?, withSparseArray?, withUnicodeString?, stringUnit?, values?})`
169169

170170
**with:**
171171

@@ -183,7 +183,8 @@ Generate objects (key/values).
183183
- `withSet?` — default: `false`_enable `Set` - eg.: `new Set([1, 2, 3])`_
184184
- `withTypedArray?` — default: `false`_enable typed arrays for ints, uints and floats - eg.: `Int8Array.from([1, 2, 3])`_
185185
- `withSparseArray?` — default: `false`_enable sparse arrays - eg.: `[1,,,3]`_
186-
- `withUnicodeString?` — default: `false`_change the default for `key` and `values` so that they produce unicode strings with non-ascii characters_
186+
- `withUnicodeString?` — default: `false`_change the default for `key` and `values` so that they produce unicode strings with non-ascii characters — shadowed by `stringUnit`_
187+
- `stringUnit?` — default: `undefined`_customize the set of characters being used by the `string` arbitrary_
187188
- `values?` — default: _booleans, numbers, strings, null and undefined__array of arbitraries producing the root* values - *non-object ones_
188189

189190
**Usages:**
@@ -276,7 +277,7 @@ Generate any kind of entities.
276277
**Signatures:**
277278

278279
- `fc.anything()`
279-
- `fc.anything({key?, depthSize?, maxDepth?, maxKeys?, size?, withBigInt?, withBoxedValues?, withDate?, withMap?, withNullPrototype?, withObjectString?, withSet?, withTypedArray?, withSparseArray?, withUnicodeString?, values?})`
280+
- `fc.anything({key?, depthSize?, maxDepth?, maxKeys?, size?, withBigInt?, withBoxedValues?, withDate?, withMap?, withNullPrototype?, withObjectString?, withSet?, withTypedArray?, withSparseArray?, withUnicodeString?, stringUnit?, values?})`
280281

281282
**with:**
282283

@@ -295,6 +296,7 @@ Generate any kind of entities.
295296
- `withTypedArray?` — default: `false`_enable typed arrays for ints, uints and floats - eg.: `Int8Array.from([1, 2, 3])`_
296297
- `withSparseArray?` — default: `false`_enable sparse arrays - eg.: `[1,,,3]`_
297298
- `withUnicodeString?` — default: `false`_change the default for `key` and `values` so that they produce unicode strings with non-ascii characters_
299+
- `stringUnit?` — default: `undefined`_customize the set of characters being used by the `string` arbitrary — shadowed by `stringUnit`_
298300
- `values?` — default: _booleans, numbers, strings, null and undefined__array of arbitraries producing the root* values - *non-object ones_
299301

300302
**Usages:**

0 commit comments

Comments
 (0)