Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 🔥 First punt at priority option #223

Open
wants to merge 45 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
6160c3c
feat: 🔥 First punt at priority option
Mar 16, 2022
485782e
Merge remote-tracking branch 'origin/main' into feat/220-unique-values
theryansmee Mar 22, 2022
6b57aa0
feat: 🔥 Clean up fakFromArray logic
theryansmee Mar 22, 2022
713c77d
feat: 🔥 Replace use of random index logic with getRandomInRange
theryansmee Mar 22, 2022
bbe7b0b
feat: 🔥 Revert rand element logic for now
theryansmee Mar 22, 2022
7f69bad
feat: 🔥 Allow devs to pass in comparison functions
theryansmee Mar 23, 2022
77831a5
feat: 🔥 Add custom comparison functions non-conforming function
theryansmee Mar 23, 2022
96acb7e
Merge remote-tracking branch 'origin/main' into feat/220-unique-values
theryansmee Mar 24, 2022
af09284
feat: 🔥 Add json check unique function. Clean up code
theryansmee Mar 24, 2022
6833592
feat: 🔥 Add generic comparison function
Apr 1, 2022
13998f6
feat: 🔥 Replace duplicate checkUnique logic with objectIsUnique
Apr 4, 2022
717bb7d
feat: 🔥 Fix function name. Update file name
Apr 4, 2022
660f53a
test: 🥳 Move error to snapshot
Apr 4, 2022
b18c227
Merge remote-tracking branch 'origin/main' into feat/220-unique-values
Apr 5, 2022
42a54d4
feat: 🔥 Fix snapshot
Apr 5, 2022
0ec65be
feat: 🔥 Move snapshots folder to tests/ route
Apr 5, 2022
ff6980a
feat: 🔥 Clean up core file
Apr 5, 2022
d57bd25
feat: 🔥 Add missing priority doc comment
Apr 5, 2022
fc5f8fc
test: 🥳 Replace flakey regex
Apr 5, 2022
67c4f5f
Merge remote-tracking branch 'origin/main' into feat/220-unique-values
Apr 19, 2022
2b84b1a
feat: 🔥 return empty array if length is 0
Apr 19, 2022
d4d1fa3
Merge remote-tracking branch 'origin/main' into feat/220-unique-values
May 3, 2022
32b84de
feat: 🔥 clean up unique validators
May 3, 2022
6f7dcc6
Merge remote-tracking branch 'origin/main' into feat/220-unique-values
May 6, 2022
2d0aecc
feat: 🔥 Add tests for unique validators
May 6, 2022
dbddca3
feat: 🔥 Fix reversed logic and corresponding tests
May 6, 2022
2331772
feat: 🔥 Combine uniqueComparer and comparisonKeys into config
May 10, 2022
b54d6b2
Merge remote-tracking branch 'origin/main' into feat/220-unique-values
May 10, 2022
39e7fa5
Merge remote-tracking branch 'origin/main' into feat/220-unique-values
May 12, 2022
e29cc7f
feat: 🔥 Simplify priority documentation comment
May 12, 2022
641a875
feat: 🔥 Tweak documentation comment to be priority specific
May 12, 2022
c48790a
feat: 🔥 Revert package.lock
May 12, 2022
f29cca6
Merge remote-tracking branch 'origin/main' into feat/220-unique-values
May 23, 2022
e7dac07
Merge remote-tracking branch 'origin/main' into feat/220-unique-values
Jun 13, 2022
77edc54
feat: 🔥 Fix merge conflicts in core
Jun 13, 2022
fee5cf6
Merge remote-tracking branch 'origin/main' into feat/220-unique-values
Sep 12, 2022
23f628e
fix: 🐞 Fix outdated tests
Sep 12, 2022
e2fb265
refactor: 💡 Remove commented out code
Sep 12, 2022
086ec7b
test: 🥳 Add basic tests for core fake function
Sep 12, 2022
2e5b650
refactor: 💡 Code review changes
Sep 18, 2022
10cd7d0
refactor: 💡 Code review changes
Sep 18, 2022
274fdc9
refactor: 💡 Change request changes
Sep 18, 2022
1143091
refactor: 💡 Code review changes
Sep 18, 2022
2a037d0
Update packages/falso/src/lib/core/core.ts
theryansmee Sep 19, 2022
8869b35
refactor: 💡 Code review changes
Sep 19, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion packages/falso/src/lib/address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,10 @@ export function randAddress<Options extends AddressOptions = never>(
return address;
};

return fake(factory, options);
return fake(factory, options, checkUnique);
}

const checkUnique: (item: Address, items: Address[]) => boolean = (
item: Address,
items: Address[]
) => items.some((i) => i.street + i.zipCode === item.street + item.zipCode);
4 changes: 2 additions & 2 deletions packages/falso/src/lib/between-date.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { fake, FakeOptions } from './core/core';
import { checkUniqueDate, fake, FakeOptions } from './core/core';
import { randNumber } from './number';

interface BetweenOptions extends FakeOptions {
Expand Down Expand Up @@ -39,5 +39,5 @@ export function randBetweenDate<Options extends BetweenOptions = never>(
);
};

return fake(generator, options);
return fake(generator, options, checkUniqueDate);
}
90 changes: 82 additions & 8 deletions packages/falso/src/lib/core/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { random } from '../random';

export interface FakeOptions {
length?: number;
priority?: 'length' | 'unique';
}

type Return<T, O extends FakeOptions> = [O] extends [never]
Expand All @@ -11,21 +12,94 @@ type Return<T, O extends FakeOptions> = [O] extends [never]
: T;

export function fake<T, Options extends FakeOptions>(
data: T[] | ((i: number) => T),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you remove the index variable?

options?: Options
data: T[] | (() => T),
options?: Options,
comparisonFunction: (item: T, items: T[]) => boolean = checkUniquePrimitive
): Return<T, Options> {
const dataSource = Array.isArray(data) ? () => randElement(data) : data;
if (Array.isArray(data)) {
return fakeFromArray(data, options) as any;
}

return fakeFromFunction(data, comparisonFunction, options) as any;
}

export function fakeFromFunction<T, Options extends FakeOptions>(
data: () => T,
comparisonFunction: (item: T, items: T[]) => boolean,
options?: Options
) {
if (!options?.length) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are handling the length options both here and in the fake function, please choose one place

return data();
}

const priority = options?.priority ?? 'length';

if (priority === 'length') {
return Array.from({ length: options.length }, (_, index) => data());
}

const items: T[] = [];

let attempts = 0;
const maxAttempts = options.length * 2;

while (items.length < options.length && attempts < maxAttempts) {
const item = data();

if (!comparisonFunction(item, items)) {
items.push(item);
}

attempts++;
}

return items;
}

export function fakeFromArray<T, Options extends FakeOptions>(
data: T[],
options?: Options
) {
if (!options?.length) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment as above

return dataSource(0) as any;
return randElement(data);
}

const priority = options?.priority ?? 'length';

if (priority === 'length') {
return Array.from({ length: options.length }, () => randElement(data));
}

return Array.from({ length: options.length }, (_, index) =>
dataSource(index)
) as any;
const clonedData: T[] = JSON.parse(JSON.stringify(data));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use structuredClone instead.

Copy link
Collaborator Author

@theryansmee theryansmee Sep 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shaharkazaz - structuredClone isn't available in our version of node / typescript. We would need to upgrade - is this ok?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@NetanelBasal any objection to upgrading and releasing a new major?

const newArray: T[] = [];

while (clonedData.length && newArray.length !== options.length) {
const randomIndex = Math.floor(random() * clonedData.length);
const item = clonedData[randomIndex];

newArray.push(item);
clonedData.splice(randomIndex, 1);
}

return newArray;
}

export function randElement<T>(arr: T[]) {
export const checkUniquePrimitive: <T>(item: T, items: T[]) => boolean = (
item,
items
) => items.includes(item);

export const checkUniqueDate: (date: Date, dates: Date[]) => boolean = (
date,
dates
) => dates.some((d) => d.valueOf() === date.valueOf());

export const checkUniqueObjectWithId: <T extends { id: string }>(
item: T,
items: T[]
) => boolean = (item, items) => items.some((i) => i.id === item.id);
theryansmee marked this conversation as resolved.
Show resolved Hide resolved

export function randElement<T>(arr: T[]): T {
shaharkazaz marked this conversation as resolved.
Show resolved Hide resolved
return arr[Math.floor(random() * arr.length)];
}

Expand Down
7 changes: 6 additions & 1 deletion packages/falso/src/lib/credit-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,10 @@ export function randCreditCard<Options extends CreditCardOptions = never>(
};
};

return fake(factory, options);
return fake(factory, options, checkUnique);
}

const checkUnique: (card: CreditCard, cards: CreditCard[]) => boolean = (
card,
cards
) => cards.some((c) => c.number === card.number);
13 changes: 12 additions & 1 deletion packages/falso/src/lib/flight-details.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Airline, randFlightNumber } from './flight-number';
import { randFullName } from './full-name';
import { randSeatNumber } from './seat-number';
import { Airport, randAirport } from './airport';
import { CreditCard } from './credit-card';

export interface FlightDetailsOptions extends FakeOptions {
airline?: Airline;
Expand Down Expand Up @@ -71,5 +72,15 @@ export function randFlightDetails<Options extends FlightDetailsOptions = never>(
};
};

return fake(factory, options);
return fake(factory, options, checkUnique);
}

const checkUnique: (
flight: FlightDetails,
flights: FlightDetails[]
) => boolean = (flight, flights) =>
flights.some(
(f) =>
f.passenger + f.flightNumber + f.date ===
flight.passenger + flight.flightNumber + flight.date
);
2 changes: 0 additions & 2 deletions packages/falso/src/lib/float.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,3 @@ export function randFloat<Options extends RandomFloatOptions = never>(
};
return fake(() => getRandomInRange(o), options);
}

randFloat();
4 changes: 2 additions & 2 deletions packages/falso/src/lib/full-address.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FakeOptions, fake } from './core/core';
import { fake } from './core/core';
import { AddressOptions, randAddress } from './address';

/**
Expand Down Expand Up @@ -29,7 +29,7 @@ export function randFullAddress<Options extends AddressOptions = never>(
const includeCounty: boolean = options?.includeCounty ?? true;
const includeCountry: boolean = options?.includeCountry ?? true;

const factory = () => {
const factory: () => string = () => {
const { street, city, county, country, zipCode } = randAddress({
includeCounty,
includeCountry,
Expand Down
6 changes: 4 additions & 2 deletions packages/falso/src/lib/future-date.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { randBetweenDate } from './between-date';
import { fake, FakeOptions } from './core/core';
import { checkUniqueDate, fake, FakeOptions } from './core/core';

interface FutureOptions extends FakeOptions {
years?: number;
Expand Down Expand Up @@ -35,5 +35,7 @@ export function randFutureDate<Options extends FutureOptions = never>(
const yearsInMilliseconds = years * 365 * 24 * 60 * 60 * 1000;
const from = new Date();
const to = new Date(from.getTime() + yearsInMilliseconds);
return fake(() => randBetweenDate({ from, to }), options);
const factory: () => Date = () => randBetweenDate({ from, to });

return fake(factory, options, checkUniqueDate);
}
7 changes: 6 additions & 1 deletion packages/falso/src/lib/json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,5 +88,10 @@ export function randJSON<Options extends RandomJSONOptions = never>(
return generatedObject;
};

return fake(factory, options);
return fake(factory, options, checkUnique);
}

const checkUnique: (item: object, items: object[]) => boolean = (
item: object,
items: object[]
) => items.some((i) => JSON.stringify(i) === JSON.stringify(item));
6 changes: 5 additions & 1 deletion packages/falso/src/lib/nearby-gpscoordinate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,9 @@ import { randLongitude } from './longitude';
export function randNearbyGPSCoordinate<Options extends FakeOptions = never>(
options?: Options
) {
return fake(() => [randLatitude(), randLongitude()], options);
return fake(() => [randLatitude(), randLongitude()], options, checkUnique);
}

const checkUnique: (coordinate: number[], coordinates: number[][]) => boolean =
(coordinate, coordinates) =>
coordinates.some((c) => c.join('') === c.join(''));
4 changes: 2 additions & 2 deletions packages/falso/src/lib/past-date.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { randBetweenDate } from './between-date';
import { fake, FakeOptions } from './core/core';
import { checkUniqueDate, fake, FakeOptions } from './core/core';

interface PastOptions extends FakeOptions {
years?: number;
Expand Down Expand Up @@ -36,5 +36,5 @@ export function randPastDate<Options extends PastOptions = never>(
const to = new Date();
const from = new Date(to.getTime() - yearsInMilliseconds);

return fake(() => randBetweenDate({ from, to }), options);
return fake(() => randBetweenDate({ from, to }), options, checkUniqueDate);
}
8 changes: 5 additions & 3 deletions packages/falso/src/lib/post.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FakeOptions, fake } from './core/core';
import { FakeOptions, fake, checkUniqueObjectWithId } from './core/core';
import { randUser, User } from './user';
import { randUuid } from './uuid';
import { randText } from './text';
Expand Down Expand Up @@ -28,7 +28,7 @@ export interface Post {
export function randPost<Options extends FakeOptions = never>(
options?: Options
) {
return fake(() => {
const factory = () => {
const post: Post = {
id: randUuid(),
title: randText({ charCount: 40 }),
Expand All @@ -43,5 +43,7 @@ export function randPost<Options extends FakeOptions = never>(
};

return post;
}, options);
};

return fake(factory, options, checkUniqueObjectWithId);
}
36 changes: 20 additions & 16 deletions packages/falso/src/lib/product.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { FakeOptions, fake, getRandomInRange } from './core/core';
import {
FakeOptions,
fake,
getRandomInRange,
checkUniqueObjectWithId,
} from './core/core';
import { randUuid } from './uuid';
import { randProductName } from './product-name';
import { randProductDescription } from './product-description';
Expand Down Expand Up @@ -35,19 +40,18 @@ export interface Product {
export function randProduct<Options extends FakeOptions = never>(
options?: Options
) {
return fake(
() => ({
id: randUuid(),
title: randProductName(),
description: randProductDescription(),
price: getRandomInRange({ fraction: 2 }).toString(),
category: randProductCategory(),
image: randImg(),
rating: {
rate: getRandomInRange({ min: 0.1, max: 5.0, fraction: 1 }).toString(),
count: getRandomInRange({ min: 0, max: 10000 }).toString(),
},
}),
options
);
const factory = () => ({
id: randUuid(),
title: randProductName(),
description: randProductDescription(),
price: getRandomInRange({ fraction: 2 }).toString(),
category: randProductCategory(),
image: randImg(),
rating: {
rate: getRandomInRange({ min: 0.1, max: 5.0, fraction: 1 }).toString(),
count: getRandomInRange({ min: 0, max: 10000 }).toString(),
},
});

return fake(factory, options, checkUniqueObjectWithId);
}
4 changes: 2 additions & 2 deletions packages/falso/src/lib/recent-date.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { randBetweenDate } from './between-date';
import { fake, FakeOptions } from './core/core';
import { checkUniqueDate, fake, FakeOptions } from './core/core';

interface RecentOptions extends FakeOptions {
days?: number;
Expand Down Expand Up @@ -36,5 +36,5 @@ export function randRecentDate<Options extends RecentOptions = never>(
const to = new Date();
const from = new Date(to.getTime() - daysInMilliseconds);

return fake(() => randBetweenDate({ from, to }), options);
return fake(() => randBetweenDate({ from, to }), options, checkUniqueDate);
}
4 changes: 2 additions & 2 deletions packages/falso/src/lib/soon-date.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { randBetweenDate } from './between-date';
import { fake, FakeOptions } from './core/core';
import { checkUniqueDate, fake, FakeOptions } from './core/core';

interface SoonOptions extends FakeOptions {
days?: number;
Expand Down Expand Up @@ -35,5 +35,5 @@ export function randSoonDate<Options extends SoonOptions = never>(
const daysInMilliseconds = days * 24 * 60 * 60 * 1000;
const from = new Date();
const to = new Date(from.getTime() + daysInMilliseconds);
return fake(() => randBetweenDate({ from, to }), options);
return fake(() => randBetweenDate({ from, to }), options, checkUniqueDate);
}
9 changes: 7 additions & 2 deletions packages/falso/src/lib/superhero.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { fake, FakeOptions, randElement } from './core/core';
import {
fake,
FakeOptions,
checkUniqueObjectWithId,
randElement,
} from './core/core';
import { data } from './superhero.json';
import { randUuid } from './uuid';

Expand Down Expand Up @@ -50,5 +55,5 @@ export function randSuperhero<Options extends SuperheroOptions = never>(
};
};

return fake(factory, options);
return fake(factory, options, checkUniqueObjectWithId);
}
16 changes: 8 additions & 8 deletions packages/falso/src/lib/todo.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { fake, FakeOptions } from './core/core';
import { fake, FakeOptions, checkUniqueObjectWithId } from './core/core';
import { randUuid } from './uuid';
import { randBoolean } from './boolean';
import { randText } from './text';
Expand Down Expand Up @@ -26,11 +26,11 @@ export interface Todo {
export function randTodo<Options extends FakeOptions = never>(
options?: Options
) {
return fake(() => {
return {
id: randUuid(),
title: randText({ charCount: 40 }),
completed: randBoolean(),
} as Todo;
}, options);
const factory: () => Todo = () => ({
id: randUuid(),
title: randText({ charCount: 40 }),
completed: randBoolean(),
});

return fake(factory, options, checkUniqueObjectWithId);
}
Loading