npm install --save-dev valimock @faker-js/fakeryarn add -D valimock @faker-js/fakerNote
Tested against valibot >= 1.4.0 and @faker-js/faker >= 10.0.0. Older
versions of either may still work β the peer-dependency ranges remain
permissive β but the test matrix runs against current majors.
Import and optionally configure a new instance of the Valimock class, then pass along your valibot schema to mock(), that's it!
import {
parse,
array,
union,
string,
pipe,
url,
number,
maxValue
} from "valibot";
import { Valimock } from "valimock";
describe(`example test`, () => {
it(`should generate valid mock data`, () => {
const schema = array(
union([pipe(string(), url()), pipe(number(), maxValue(20))])
);
const result = new Valimock().mock(schema);
expect(parse(schema, result)).toStrictEqual(result);
});
});Note
For async schemas, you will need to use parseAsync(). Be aware that async schemas generate a Promise and may need to be await'ed depending on usage.
Please see the __tests__ folder for more usage examples of different schema types.
new Valimock(options) accepts a partial options object:
| option | type | default | purpose |
|---|---|---|---|
faker |
Faker |
default Faker instance | Faker instance used for all generation; supply your own to control locale or seeding centrally |
seed |
number | number[] |
undefined |
Re-seeds Faker at the start of every top-level mock() call for deterministic output |
stringMap |
Record<string, () => string> |
undefined |
Per-key string overrides (when generating strings inside an object). Wins over the built-in format/key-name routing. |
stringActions |
Record<string, StringActionHandler> |
{} |
Handlers for string pipe actions Valimock doesn't know, keyed by action type. See Extending string generation. |
stringFormats |
Record<string, StringFormatGenerator> |
{} |
Generators for the format names your stringActions handlers record in ctx.format. |
customMocks |
Record<string, (schema, options, mock) => unknown> |
{} |
Generators for Valibot schema types Valimock doesn't yet support. Keyed by schema.type; mock recurses into nested schemas with the same instance. |
recordKeysLength |
number |
1 |
How many entries to generate for a record() schema |
mapEntriesLength |
number |
1 |
How many entries to generate for a map() schema |
throwOnUnknownType |
boolean |
false |
When true, throw a MockError for unrecognized schema types instead of warning |
onWarn |
(message: string) => void |
console.warn |
Diagnostic sink. Receives unhandled-action notices, retry-budget exhaustion, and generation errors. Set to () => {} to silence. |
mockeryMapper |
MockeryMapper |
built-in defaults | Deprecated. Prefer stringMap or contributing an action handler. Still consulted for backwards compatibility; emits a one-time warning when invoked. |
Libraries that ship their own string actions (v.pipe(v.string(), did()))
can teach Valimock to generate matching values without replacing the whole
string generator. A stringActions handler runs when its action type is
found in a pipe and records what it learned on the StringContext, usually
by naming a format; a stringFormats generator with that name then produces
the value. Everything else (length bounds, stringMap, key-name heuristics)
keeps working around them.
import { Valimock } from "valimock";
const mock = new Valimock({
stringActions: {
// `did()` is a validation action with `type: "did"`.
did: (ctx) => {
ctx.format = `did`;
},
// Handlers can read the action's requirement and stash it for the
// generator in `ctx.custom`.
accept: (ctx, action) => {
ctx.format = `mime`;
ctx.custom.accept = (action as { requirement: string[] }).requirement;
}
},
stringFormats: {
did: (ctx) => `did:plc:${ctx.faker.string.alphanumeric(24).toLowerCase()}`,
mime: (ctx) => ctx.faker.helpers.arrayElement(ctx.custom.accept as string[])
}
});Both tables are merged over the built-in registries, so an entry can also override how Valimock handles one of its own actions.
Valimock's string mocking is built around a small pipeline (src/schemas/string/)
with a per-action registry. Adding support for a new Valibot action is a
one-line addition to the registry, or a stringActions entry from userland.
See Contributing below.
Any schema type Valimock doesn't yet support can be handled by supplying a
customMocks entry keyed by the schema's type field. The entry receives
the schema, the instance options, and a mock function that recurses into
nested schemas with the same instance, so container types can be mocked
without constructing a second Valimock. When Valimock has no built-in
mocker and no matching customMocks entry (notably for v.custom(...)), it
emits an onWarn notice and returns undefined rather than silently
producing an invalid value. Set throwOnUnknownType: true to turn that into
a thrown MockError.
| Any | Array | Bigint | Blob | Boolean | Custom | Date |
|---|---|---|---|---|---|---|
| β | β | β | β | β | β | β |
| Enum | ExactOptional | File | Function | Instance | Intersect | Lazy |
| β | β | β | β | β | β | β |
| Literal | LooseObject | LooseTuple | Map | NaN | Never | Null |
| β | β | β | β | β | β | β |
| Nullable | Nullish | NonNullable | NonNullish | NonOptional | Number | Object |
| β | β | β | β | β | β | β |
| ObjectWithRest | Optional | Picklist | Promise | Record | Set | StrictObject |
| β | β | β | β | β | β | β |
| StrictTuple | String | Symbol | Tuple | TupleWithRest | Undefined | Undefinedable |
| β | β | β | β | β | β | β |
| Union | Unknown | Variant | Void | |||
| β | β | β | β |
Legend: β implemented Β· β partial Β· β not implemented Β· β user-supplied via customMocks
custom schemas run an arbitrary user predicate that Valimock has no general
way to satisfy. Provide a matching customMocks entry keyed by the schema's
type ("custom", or a more specific tag if you wrap multiple custom()
calls in a brand) to produce a value that will pass the predicate.
For environment-dependent schemas (blob, file, function, promise,
instance), Valimock returns a structural placeholder when the relevant
global isn't available (e.g. Blob / File outside Node β₯18 / browsers /
jsdom). The onWarn sink surfaces a notice in those cases.
empty |
includes |
length |
maxLength |
minLength |
nonEmpty |
|---|---|---|---|---|---|
| β | β | β | β | β | β |
size |
minSize |
maxSize |
notSize |
|---|---|---|---|
| β | β | β | β |
gtValue |
ltValue |
maxValue |
minValue |
value |
values |
|---|---|---|---|---|---|
| β | β | β | β | β | β |
maxValue |
minValue |
value |
|---|---|---|
| β | β | β |
finite |
gtValue |
integer |
ltValue |
maxValue |
minValue |
multipleOf |
notValue |
notValues |
safeInteger |
value |
values |
|---|---|---|---|---|---|---|---|---|---|---|---|
| β | β | β | β | β | β | β | β | β | β | β | β |
base64 |
bic |
bytes |
creditCard |
cuid2 |
decimal |
digits |
domain |
email |
emoji |
empty |
endsWith |
excludes |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| β | β | β | β | β | β | β | β | β | β | β | β | β |
graphemes |
hash |
hexColor |
hexadecimal |
imei |
includes |
ip |
ipv4 |
ipv6 |
isbn |
isoDate |
isoDateTime |
isoDateTimeSecond |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| β | β | β | β | β | β | β | β | β | β | β | β | β |
isoTime |
isoTimeSecond |
isoTimestamp |
isoWeek |
isrc |
jwsCompact |
length |
mac |
mac48 |
mac64 |
maxBytes |
maxGraphemes |
maxLength |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| β | β | β | β | β | β | β | β | β | β | β | β | β |
maxWords |
minBytes |
minGraphemes |
minLength |
minWords |
nanoid |
nonEmpty |
notBytes |
notGraphemes |
notLength |
notValue |
notValues |
notWords |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| β | β | β | β | β | β | β | β | β | β | β | β | β |
octal |
regex |
rfcEmail |
slug |
startsWith |
ulid |
url |
uuid |
value |
values |
words |
|---|---|---|---|---|---|---|---|---|---|---|
| β | β | β | β | β | β | β | β | β | β | β |
Not yet implemented (string): notEntries. The bytes / graphemes /
words families currently treat each unit as .length (correct for ASCII
output, approximate for multi-byte content); a future enhancement may
distinguish them via Intl.Segmenter.
When Valimock encounters an action it doesn't know how to handle inside a
string pipe, it emits an onWarn notice and ignores the action β the
generated value satisfies the rest of the constraints but may not match
the unhandled one. Override options.onWarn to route those notices into
your test reporter or set throwOnUnknownType: true for strict mode.
The project uses Vite+ as a unified toolchain (Oxlint + Oxfmt
- tsdown + Vitest) and Bumpy for versioning and release.
vp install # install dependencies
vp check --fix # format + lint + typecheck (with autofixes)
vp test # run Vitest
yarn bumpy add # create a bump file for your PRAdding support for a new Valibot string action is typically a two-line
change: register a handler in src/schemas/string/actionHandlers.ts
and (if the action is a format selector) add the matching generator to
src/schemas/string/formatGenerators.ts.
The property-based block in src/__tests__/mockString.spec.ts
will exercise the new combination automatically once the action appears
in its formats table.
Valimock's implementation is based on @anatine/zod-mock
Released under the MIT license Β© Drake Costa.