Skip to content

Commit 5b351f2

Browse files
authored
Merge pull request #29 from mizdra/rename-lazy-to-dynamic
Rename `lazy` to `dynamic`
2 parents ad2d7f0 + c7d7827 commit 5b351f2

File tree

5 files changed

+109
-91
lines changed

5 files changed

+109
-91
lines changed

README.md

Lines changed: 52 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -63,22 +63,22 @@ Then, the utilities to define a factory are generated. You can define your prefe
6363

6464
```ts
6565
// src/app.ts
66-
import { defineBookFactory, defineAuthorFactory, lazy } from '../__generated__/fabbrica';
66+
import { defineBookFactory, defineAuthorFactory, dynamic } from '../__generated__/fabbrica';
6767
import { faker } from '@faker-js/faker';
6868

6969
const BookFactory = defineBookFactory({
7070
defaultFields: {
7171
__typename: 'Book',
72-
id: lazy(({ seq }) => `Book-${seq}`),
73-
title: lazy(() => faker.word.noun()),
72+
id: dynamic(({ seq }) => `Book-${seq}`),
73+
title: dynamic(() => faker.word.noun()),
7474
author: undefined,
7575
},
7676
});
7777
const AuthorFactory = defineAuthorFactory({
7878
defaultFields: {
7979
__typename: 'Author',
80-
id: lazy(({ seq }) => `Author-${seq}`),
81-
name: lazy(() => faker.person.firstName()),
80+
id: dynamic(({ seq }) => `Author-${seq}`),
81+
name: dynamic(() => faker.person.firstName()),
8282
books: undefined,
8383
},
8484
});
@@ -92,7 +92,7 @@ const book0 = await BookFactory.build();
9292
expect(book0).toStrictEqual({
9393
__typename: 'Book',
9494
id: 'Book-0',
95-
title: 'apple',
95+
title: expect.any(String),
9696
author: undefined,
9797
});
9898
assertType<{
@@ -109,11 +109,11 @@ const book1 = await BookFactory.build({
109109
expect(book1).toStrictEqual({
110110
__typename: 'Book',
111111
id: 'Book-1',
112-
title: 'orange',
112+
title: expect.any(String),
113113
author: {
114114
__typename: 'Author',
115115
id: 'Author-0',
116-
name: 'Tom',
116+
name: expect.any(String),
117117
books: undefined,
118118
},
119119
});
@@ -134,15 +134,33 @@ assertType<{
134134

135135
The library has several notable features. And many of them are inspired by [FactoryBot](https://thoughtbot.github.io/factory_bot/).
136136

137+
### Dynamic Fields
138+
139+
The `dynamic` function allows you to define fields with a dynamic value.
140+
141+
```ts
142+
import { dynamic } from '../__generated__/fabbrica';
143+
const BookFactory = defineBookFactory({
144+
defaultFields: {
145+
id: dynamic(() => faker.datatype.uuid()),
146+
title: 'Yuyushiki',
147+
},
148+
});
149+
expect(await BookFactory.build()).toStrictEqual({
150+
id: expect.any(String), // Randomly generated UUID
151+
title: 'Yuyushiki',
152+
});
153+
```
154+
137155
### Sequences
138156

139157
Sequences allow you to build sequentially numbered data.
140158

141159
```ts
142160
const BookFactory = defineBookFactory({
143161
defaultFields: {
144-
id: lazy(({ seq }) => `Book-${seq}`),
145-
title: lazy(async ({ seq }) => Promise.resolve(`Yuyushiki Vol.${seq}`)),
162+
id: dynamic(({ seq }) => `Book-${seq}`),
163+
title: dynamic(async ({ seq }) => Promise.resolve(`Yuyushiki Vol.${seq}`)),
146164
author: undefined,
147165
},
148166
});
@@ -165,9 +183,9 @@ Fields can be based on the values of other fields using `get` function.
165183
```ts
166184
const UserFactory = defineUserFactory({
167185
defaultFields: {
168-
id: lazy(({ seq }) => `User-${seq}`),
186+
id: dynamic(({ seq }) => `User-${seq}`),
169187
name: 'yukari',
170-
email: lazy(async ({ get }) => `${(await get('name')) ?? 'defaultName'}@yuyushiki.net`),
188+
email: dynamic(async ({ get }) => `${(await get('name')) ?? 'defaultName'}@yuyushiki.net`),
171189
},
172190
});
173191
expect(await UserFactory.build()).toStrictEqual({
@@ -189,8 +207,8 @@ You can build a list of mock data with `buildList` utility.
189207
```ts
190208
const BookFactory = defineBookFactory({
191209
defaultFields: {
192-
id: lazy(({ seq }) => `Book-${seq}`),
193-
title: lazy(({ seq }) => `Yuyushiki Vol.${seq}`),
210+
id: dynamic(({ seq }) => `Book-${seq}`),
211+
title: dynamic(({ seq }) => `Yuyushiki Vol.${seq}`),
194212
author: undefined,
195213
},
196214
});
@@ -208,16 +226,16 @@ You can build mock data of the relevant type in one shot.
208226
```ts
209227
const BookFactory = defineBookFactory({
210228
defaultFields: {
211-
id: lazy(({ seq }) => `Book-${seq}`),
212-
title: lazy(({ seq }) => `Yuyushiki Vol.${seq}`),
229+
id: dynamic(({ seq }) => `Book-${seq}`),
230+
title: dynamic(({ seq }) => `Yuyushiki Vol.${seq}`),
213231
author: undefined,
214232
},
215233
});
216234
const AuthorFactory = defineAuthorFactory({
217235
defaultFields: {
218-
id: lazy(({ seq }) => `Author-${seq}`),
236+
id: dynamic(({ seq }) => `Author-${seq}`),
219237
name: 'Komata Mikami',
220-
books: lazy(async () => BookFactory.buildList(1)), // Build mock data of related types
238+
books: dynamic(async () => BookFactory.buildList(1)), // Build mock data of related types
221239
},
222240
});
223241
expect(await AuthorFactory.build()).toStrictEqual({
@@ -236,7 +254,7 @@ However, you must prepare a custom `define<Type>Factory` to use Transient Fields
236254
```ts
237255
import {
238256
defineAuthorFactoryInternal,
239-
lazy,
257+
dynamic,
240258
DefaultFieldsResolver,
241259
Traits,
242260
AuthorFactoryDefineOptions,
@@ -260,9 +278,9 @@ function defineAuthorFactoryWithTransientFields<
260278
// Use custom `defineAuthorFactory`
261279
const AuthorFactory = defineAuthorFactoryWithTransientFields({
262280
defaultFields: {
263-
id: lazy(({ seq }) => `Author-${seq}`),
281+
id: dynamic(({ seq }) => `Author-${seq}`),
264282
name: 'Komata Mikami',
265-
books: lazy(async ({ get }) => {
283+
books: dynamic(async ({ get }) => {
266284
const bookCount = (await get('bookCount')) ?? 0;
267285
return BookFactory.buildList(bookCount);
268286
}),
@@ -291,7 +309,7 @@ import I_BANNER from '../assets/dummy/banner.png';
291309

292310
const ImageFactory = defineImageFactory({
293311
defaultFields: {
294-
id: lazy(({ seq }) => `Image-${seq}`),
312+
id: dynamic(({ seq }) => `Image-${seq}`),
295313
url: I_SPACER.src,
296314
width: I_SPACER.width,
297315
height: I_SPACER.height,
@@ -358,20 +376,20 @@ Creating a circular type with [Associations](#build-mock-data-of-related-types-a
358376
```ts
359377
const BookFactory = defineBookFactory({
360378
defaultFields: {
361-
id: lazy(({ seq }) => `Book-${seq}`),
362-
title: lazy(({ seq }) => `ゆゆ式 ${seq}巻`),
363-
// NOTE: `lazy(({ seq }) => AuthorFactory.build())` causes a circular dependency between `BookFactory` and `AuthorFactory`.
379+
id: dynamic(({ seq }) => `Book-${seq}`),
380+
title: dynamic(({ seq }) => `ゆゆ式 ${seq}巻`),
381+
// NOTE: `dynamic(({ seq }) => AuthorFactory.build())` causes a circular dependency between `BookFactory` and `AuthorFactory`.
364382
// As a result, the types of each other become undecidable and a compile error occurs.
365383
// So that the type is not undecidable, pass `undefined`.
366-
author: lazy(({ seq }) => AuthorFactory.build()),
384+
author: dynamic(({ seq }) => AuthorFactory.build()),
367385
},
368386
});
369387
const AuthorFactory = defineAuthorFactory({
370388
defaultFields: {
371-
id: lazy(({ seq }) => `Author-${seq}`),
372-
name: lazy(({ seq }) => `${seq}上小又`),
389+
id: dynamic(({ seq }) => `Author-${seq}`),
390+
name: dynamic(({ seq }) => `${seq}上小又`),
373391
// NOTE: The type is not undecidable, pass `undefined`.
374-
books: lazy(({ seq }) => BookFactory.buildList()),
392+
books: dynamic(({ seq }) => BookFactory.buildList()),
375393
},
376394
});
377395
```
@@ -394,15 +412,15 @@ This error is due to the type of each field being cycled, making the type undeci
394412
```ts
395413
const BookFactory = defineBookFactory({
396414
defaultFields: {
397-
id: lazy(({ seq }) => `Book-${seq}`),
398-
title: lazy(({ seq }) => `ゆゆ式 ${seq}巻`),
399-
author: lazy(({ seq }) => AuthorFactory.build()),
415+
id: dynamic(({ seq }) => `Book-${seq}`),
416+
title: dynamic(({ seq }) => `ゆゆ式 ${seq}巻`),
417+
author: dynamic(({ seq }) => AuthorFactory.build()),
400418
},
401419
});
402420
const AuthorFactory = defineAuthorFactory({
403421
defaultFields: {
404-
id: lazy(({ seq }) => `Author-${seq}`),
405-
name: lazy(({ seq }) => `${seq}上小又`),
422+
id: dynamic(({ seq }) => `Author-${seq}`),
423+
name: dynamic(({ seq }) => `${seq}上小又`),
406424
// Pass `undefined` to avoid type being undecidable.
407425
books: undefined,
408426
},

e2e/index.e2e.ts

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
defineBookFactory,
1010
defineImageFactory,
1111
defineUserFactory,
12-
lazy,
12+
dynamic,
1313
resetAllSequence,
1414
} from './__generated__/fabbrica.js';
1515
import { Author } from './__generated__/types.js';
@@ -19,18 +19,18 @@ describe('integration test', () => {
1919
it('circular dependent type', async () => {
2020
const BookFactory = defineBookFactory({
2121
defaultFields: {
22-
id: lazy(({ seq }) => `Book-${seq}`),
23-
title: lazy(({ seq }) => `ゆゆ式 ${seq}巻`),
24-
// NOTE: `lazy(({ seq }) => AuthorFactory.build())` causes a circular dependency between `BookFactory` and `AuthorFactory`.
22+
id: dynamic(({ seq }) => `Book-${seq}`),
23+
title: dynamic(({ seq }) => `ゆゆ式 ${seq}巻`),
24+
// NOTE: `dynamic(({ seq }) => AuthorFactory.build())` causes a circular dependency between `BookFactory` and `AuthorFactory`.
2525
// As a result, the types of each other become undecidable and a compile error occurs.
2626
// So that the type is not undecidable, pass `undefined`.
2727
author: undefined,
2828
},
2929
});
3030
const AuthorFactory = defineAuthorFactory({
3131
defaultFields: {
32-
id: lazy(({ seq }) => `Author-${seq}`),
33-
name: lazy(({ seq }) => `${seq}上小又`),
32+
id: dynamic(({ seq }) => `Author-${seq}`),
33+
name: dynamic(({ seq }) => `${seq}上小又`),
3434
// NOTE: The type is not undecidable, pass `undefined`.
3535
books: undefined,
3636
},
@@ -155,8 +155,8 @@ describe('defineTypeFactory', () => {
155155
it('accepts functional field resolvers', async () => {
156156
const BookFactory = defineBookFactory({
157157
defaultFields: {
158-
id: lazy(() => 'Book-0'),
159-
title: lazy(async () => Promise.resolve('ゆゆ式')),
158+
id: dynamic(() => 'Book-0'),
159+
title: dynamic(async () => Promise.resolve('ゆゆ式')),
160160
author: undefined,
161161
},
162162
});
@@ -193,8 +193,8 @@ describe('defineTypeFactory', () => {
193193
it('creates fields with sequential id', async () => {
194194
const BookFactory = defineBookFactory({
195195
defaultFields: {
196-
id: lazy(({ seq }) => `Book-${seq}`),
197-
title: lazy(async ({ seq }) => Promise.resolve(`ゆゆ式 ${seq}巻`)),
196+
id: dynamic(({ seq }) => `Book-${seq}`),
197+
title: dynamic(async ({ seq }) => Promise.resolve(`ゆゆ式 ${seq}巻`)),
198198
author: undefined,
199199
},
200200
});
@@ -216,10 +216,10 @@ describe('defineTypeFactory', () => {
216216
const lastNameResolver = vi.fn(() => 'Mikami');
217217
const UserFactory = defineUserFactory({
218218
defaultFields: {
219-
id: lazy(({ seq }) => `User-${seq}`),
220-
firstName: lazy(firstNameResolver),
221-
lastName: lazy(lastNameResolver),
222-
fullName: lazy(
219+
id: dynamic(({ seq }) => `User-${seq}`),
220+
firstName: dynamic(firstNameResolver),
221+
lastName: dynamic(lastNameResolver),
222+
fullName: dynamic(
223223
async ({ get }) => `${(await get('firstName')) ?? 'firstName'} ${(await get('lastName')) ?? 'lastName'}`,
224224
),
225225
},
@@ -248,7 +248,7 @@ describe('defineTypeFactory', () => {
248248
it('overrides defaultFields', async () => {
249249
const ImageFactory = defineImageFactory({
250250
defaultFields: {
251-
id: lazy(({ seq }) => `Image-${seq}`),
251+
id: dynamic(({ seq }) => `Image-${seq}`),
252252
url: '#',
253253
width: null,
254254
height: null,
@@ -281,7 +281,7 @@ describe('defineTypeFactory', () => {
281281
it('overrides fields multiple times by chaining the use methods', async () => {
282282
const ImageFactory = defineImageFactory({
283283
defaultFields: {
284-
id: lazy(({ seq }) => `Image-${seq}`),
284+
id: dynamic(({ seq }) => `Image-${seq}`),
285285
url: '#',
286286
width: null,
287287
height: null,
@@ -333,16 +333,16 @@ describe('defineTypeFactory', () => {
333333

334334
const BookFactory = defineBookFactory({
335335
defaultFields: {
336-
id: lazy(({ seq }) => `Book-${seq}`),
337-
title: lazy(({ seq }) => `ゆゆ式 ${seq}巻`),
336+
id: dynamic(({ seq }) => `Book-${seq}`),
337+
title: dynamic(({ seq }) => `ゆゆ式 ${seq}巻`),
338338
author: undefined,
339339
},
340340
});
341341
const AuthorFactory = defineAuthorFactoryWithTransientFields({
342342
defaultFields: {
343-
id: lazy(({ seq }) => `Author-${seq}`),
343+
id: dynamic(({ seq }) => `Author-${seq}`),
344344
name: '三上小又',
345-
books: lazy(async ({ get }) => {
345+
books: dynamic(async ({ get }) => {
346346
const bookCount = (await get('bookCount')) ?? 0;
347347
return BookFactory.buildList(bookCount);
348348
}),
@@ -387,7 +387,7 @@ describe('defineTypeFactory', () => {
387387
it('resets all sequence', async () => {
388388
const BookFactory = defineBookFactory({
389389
defaultFields: {
390-
id: lazy(({ seq }) => `Book-${seq}`),
390+
id: dynamic(({ seq }) => `Book-${seq}`),
391391
title: 'ゆゆ式',
392392
author: undefined,
393393
},
@@ -499,8 +499,8 @@ describe('TypeFactoryInterface', () => {
499499
},
500500
});
501501
const book = await BookFactory.build({
502-
id: lazy(() => 'Book-0'),
503-
title: lazy(async () => Promise.resolve('ゆゆ式')),
502+
id: dynamic(() => 'Book-0'),
503+
title: dynamic(async () => Promise.resolve('ゆゆ式')),
504504
author: undefined,
505505
});
506506
expect(book).toStrictEqual({
@@ -572,7 +572,7 @@ describe('TypeFactoryInterface', () => {
572572
const BookFactory = defineBookFactory({
573573
defaultFields: {
574574
id: 'Book-0',
575-
title: lazy(defaultTitleResolver),
575+
title: dynamic(defaultTitleResolver),
576576
author: undefined,
577577
},
578578
});
@@ -601,8 +601,8 @@ describe('TypeFactoryInterface', () => {
601601
},
602602
});
603603
const book = await BookFactory.build({
604-
id: lazy(({ seq }) => `Book-${seq}`),
605-
title: lazy(async ({ seq }) => Promise.resolve(`ゆゆ式 ${seq}巻`)),
604+
id: dynamic(({ seq }) => `Book-${seq}`),
605+
title: dynamic(async ({ seq }) => Promise.resolve(`ゆゆ式 ${seq}巻`)),
606606
});
607607
expect(book).toStrictEqual({
608608
id: 'Book-0',
@@ -621,16 +621,16 @@ describe('TypeFactoryInterface', () => {
621621
const lastNameResolver = vi.fn(() => 'Mikami');
622622
const UserFactory = defineUserFactory({
623623
defaultFields: {
624-
id: lazy(({ seq }) => `User-${seq}`),
624+
id: dynamic(({ seq }) => `User-${seq}`),
625625
firstName: '',
626626
lastName: '',
627627
fullName: '',
628628
},
629629
});
630630
const User = await UserFactory.build({
631-
firstName: lazy(firstNameResolver),
632-
lastName: lazy(lastNameResolver),
633-
fullName: lazy(
631+
firstName: dynamic(firstNameResolver),
632+
lastName: dynamic(lastNameResolver),
633+
fullName: dynamic(
634634
async ({ get }) => `${(await get('firstName')) ?? 'firstName'} ${(await get('lastName')) ?? 'lastName'}`,
635635
),
636636
});
@@ -657,7 +657,7 @@ describe('TypeFactoryInterface', () => {
657657
it('overrides defaultFields', async () => {
658658
const BookFactory = defineBookFactory({
659659
defaultFields: {
660-
id: lazy(({ seq }) => `Book-${seq}`),
660+
id: dynamic(({ seq }) => `Book-${seq}`),
661661
title: 'ゆゆ式',
662662
author: undefined,
663663
},
@@ -717,7 +717,7 @@ describe('TypeFactoryInterface', () => {
717717
it('resets sequence', async () => {
718718
const BookFactory = defineBookFactory({
719719
defaultFields: {
720-
id: lazy(({ seq }) => `Book-${seq}`),
720+
id: dynamic(({ seq }) => `Book-${seq}`),
721721
title: 'ゆゆ式',
722722
author: undefined,
723723
},

0 commit comments

Comments
 (0)