aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cypress/e2e/api.cy.ts2
-rw-r--r--docs/.vitepress/config.ts13
-rw-r--r--docs/.vitepress/versions.ts21
-rw-r--r--scripts/apidoc/faker-class.ts6
-rw-r--r--scripts/apidoc/signature.ts2
-rw-r--r--src/definitions/date.ts3
-rw-r--r--src/definitions/definitions.ts2
-rw-r--r--src/locale-proxy.ts40
-rw-r--r--src/modules/airline/index.ts2
-rw-r--r--src/modules/color/index.ts37
-rw-r--r--src/modules/commerce/index.ts10
-rw-r--r--src/modules/date/index.ts51
-rw-r--r--src/modules/finance/index.ts22
-rw-r--r--src/modules/helpers/index.ts2
-rw-r--r--src/modules/helpers/unique.ts4
-rw-r--r--src/modules/internet/index.ts2
-rw-r--r--src/modules/person/index.ts112
-rw-r--r--src/modules/random/index.ts2
-rw-r--r--test/faker.spec.ts4
-rw-r--r--test/modules/airline.spec.ts12
-rw-r--r--test/modules/finance-iban.spec.ts13
-rw-r--r--test/modules/helpers.spec.ts3
-rw-r--r--test/scripts/apidoc/verify-jsdoc-tags.spec.ts2
-rw-r--r--test/vitest-extensions.ts2
-rw-r--r--tsconfig.json1
25 files changed, 239 insertions, 131 deletions
diff --git a/cypress/e2e/api.cy.ts b/cypress/e2e/api.cy.ts
index be61f5df..e87ea856 100644
--- a/cypress/e2e/api.cy.ts
+++ b/cypress/e2e/api.cy.ts
@@ -34,7 +34,7 @@ describe('API Test', () => {
cy.get('.api-group li').each(($el) => {
const anchor = $el.find('a');
const text = anchor.text();
- const link = anchor.attr('href').split('#')[0];
+ const link = anchor.attr('href')?.split('#')[0] ?? 'MISSING';
if (checked.has(link)) {
return;
}
diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts
index 12fea107..e8484526 100644
--- a/docs/.vitepress/config.ts
+++ b/docs/.vitepress/config.ts
@@ -121,11 +121,14 @@ const config = defineConfig({
{ icon: 'github', link: 'https://github.com/faker-js/faker' },
],
- algolia: {
- apiKey: process.env.API_KEY,
- appId: process.env.APP_ID,
- indexName: 'fakerjs',
- },
+ algolia:
+ process.env.API_KEY == null || process.env.APP_ID == null
+ ? undefined
+ : {
+ apiKey: process.env.API_KEY,
+ appId: process.env.APP_ID,
+ indexName: 'fakerjs',
+ },
footer: {
message: 'Released under the MIT License.',
diff --git a/docs/.vitepress/versions.ts b/docs/.vitepress/versions.ts
index 2964557c..90b0fc8d 100644
--- a/docs/.vitepress/versions.ts
+++ b/docs/.vitepress/versions.ts
@@ -14,18 +14,23 @@ function readOtherLatestReleaseTagNames(): string[] {
.toString('utf8')
.split('\n')
.filter((tag) => semver.valid(tag))
- .reduce<Record<number, string[]>>((acc, tag) => {
- const majorVersion = semver.major(tag);
+ .filter((tag) => {
// Only consider tags for our deployed website versions,
// excluding the current major version.
- if (majorVersion >= 6 && majorVersion !== currentMajorVersion) {
- (acc[majorVersion] = acc[majorVersion] ?? []).push(tag);
+ const majorVersion = semver.major(tag);
+ return majorVersion >= 6 && majorVersion !== currentMajorVersion;
+ })
+ .reduce<Record<number, string>>((latestTagByMajor, tag) => {
+ const majorVersion = semver.major(tag);
+
+ const latestTag = latestTagByMajor[majorVersion];
+ if (latestTag == null || semver.lt(latestTag, tag)) {
+ latestTagByMajor[majorVersion] = tag;
}
- return acc;
+
+ return latestTagByMajor;
}, {});
- return Object.entries(latestReleaseTagNames)
- .map(([major, tags]) => semver.maxSatisfying(tags, `^${major}`))
- .sort(semver.rcompare);
+ return Object.values(latestReleaseTagNames).sort(semver.rcompare);
}
// Set by netlify
diff --git a/scripts/apidoc/faker-class.ts b/scripts/apidoc/faker-class.ts
index 6672896c..a9acad3c 100644
--- a/scripts/apidoc/faker-class.ts
+++ b/scripts/apidoc/faker-class.ts
@@ -28,6 +28,10 @@ export async function processFakerRandomizer(
.getChildrenByKind(ReflectionKind.Interface)
.find((clazz) => clazz.name === 'Randomizer');
+ if (randomizerClass == null) {
+ throw new Error('Randomizer class not found');
+ }
+
return processClass(randomizerClass);
}
@@ -63,7 +67,7 @@ async function processClass(
function hasConstructor(clazz: DeclarationReflection): boolean {
return clazz
.getChildrenByKind(ReflectionKind.Constructor)
- .some((constructor) => constructor.signatures.length > 0);
+ .some((constructor) => (constructor.signatures?.length ?? 0) > 0);
}
async function processConstructor(
diff --git a/scripts/apidoc/signature.ts b/scripts/apidoc/signature.ts
index 08fe5896..82d4047e 100644
--- a/scripts/apidoc/signature.ts
+++ b/scripts/apidoc/signature.ts
@@ -305,7 +305,7 @@ async function signatureTypeToText(
await Promise.all(
signature.parameters?.map(
async (p) => `${p.name}: ${await typeToText(p.type)}`
- )
+ ) ?? []
)
).join(', ')}) => ${await typeToText(signature.type)}`;
}
diff --git a/src/definitions/date.ts b/src/definitions/date.ts
index 16cfb28a..2265a025 100644
--- a/src/definitions/date.ts
+++ b/src/definitions/date.ts
@@ -26,8 +26,9 @@ export interface DateEntryDefinition {
/**
* The short name/abbreviation of the entry.
+ * If null, the locale does not support a short name/abbreviation for the entry.
*/
- abbr: string[];
+ abbr: string[] | null;
/**
* The wide name of the entry when used in context. If absent wide will be used instead.
diff --git a/src/definitions/definitions.ts b/src/definitions/definitions.ts
index ca495e34..c2a3b560 100644
--- a/src/definitions/definitions.ts
+++ b/src/definitions/definitions.ts
@@ -50,4 +50,4 @@ export type LocaleDefinition = {
system?: SystemDefinition;
vehicle?: VehicleDefinition;
word?: WordDefinition;
-} & Record<string, Record<string, unknown> | undefined>;
+} & Record<string, Record<string, unknown>>;
diff --git a/src/locale-proxy.ts b/src/locale-proxy.ts
index 67b29d47..e99ba655 100644
--- a/src/locale-proxy.ts
+++ b/src/locale-proxy.ts
@@ -55,6 +55,30 @@ export function createLocaleProxy(locale: LocaleDefinition): LocaleProxy {
}
/**
+ * Checks that the value is not null or undefined and throws an error if it is.
+ *
+ * @param value The value to check.
+ * @param path The path to the locale data.
+ */
+export function assertLocaleData<T>(
+ value: T,
+ ...path: string[]
+): asserts value is NonNullable<T> {
+ if (value === null) {
+ throw new FakerError(
+ `The locale data for '${path.join('.')}' aren't applicable to this locale.
+ If you think this is a bug, please report it at: https://github.com/faker-js/faker`
+ );
+ } else if (value === undefined) {
+ throw new FakerError(
+ `The locale data for '${path.join('.')}' are missing in this locale.
+ Please contribute the missing data to the project or use a locale/Faker instance that has these data.
+ For more information see https://fakerjs.dev/guide/localization.html`
+ );
+ }
+}
+
+/**
* Creates a proxy for a category that throws an error when accessing an undefined property.
*
* @param categoryName The name of the category.
@@ -79,20 +103,10 @@ function createCategoryProxy<
const value = target[entryName];
if (typeof entryName === 'symbol' || entryName === 'nodeType') {
return value;
- } else if (value === null) {
- throw new FakerError(
- `The locale data for '${categoryName}.${entryName.toString()}' aren't applicable to this locale.
- If you think this is a bug, please report it at: https://github.com/faker-js/faker`
- );
- } else if (value === undefined) {
- throw new FakerError(
- `The locale data for '${categoryName}.${entryName.toString()}' are missing in this locale.
- Please contribute the missing data to the project or use a locale/Faker instance that has these data.
- For more information see https://fakerjs.dev/guide/localization.html`
- );
- } else {
- return value;
}
+
+ assertLocaleData(value, categoryName, entryName.toString());
+ return value;
},
set: throwReadOnlyError,
diff --git a/src/modules/airline/index.ts b/src/modules/airline/index.ts
index 4c1ec318..e8ac47c5 100644
--- a/src/modules/airline/index.ts
+++ b/src/modules/airline/index.ts
@@ -155,7 +155,7 @@ export class AirlineModule extends ModuleBase {
): string {
const { allowNumerics = false, allowVisuallySimilarCharacters = false } =
options;
- const excludedChars = [];
+ const excludedChars: string[] = [];
if (!allowNumerics) {
excludedChars.push(...numerics);
}
diff --git a/src/modules/color/index.ts b/src/modules/color/index.ts
index 5962ef71..57b906a3 100644
--- a/src/modules/color/index.ts
+++ b/src/modules/color/index.ts
@@ -47,17 +47,19 @@ export type Casing = 'lower' | 'upper' | 'mixed';
*
* @param hexColor Hex color string to be formatted.
* @param options Options object.
- * @param options.prefix Prefix of the generated hex color. Defaults to `'0x'`.
- * @param options.casing Letter type case of the generated hex color. Defaults to `'mixed'`.
+ * @param options.prefix Prefix of the generated hex color.
+ * @param options.casing Letter type case of the generated hex color.
*/
function formatHexColor(
hexColor: string,
- options?: {
- prefix?: string;
- casing?: Casing;
+ options: {
+ prefix: string;
+ casing: Casing;
}
): string {
- switch (options?.casing) {
+ const { prefix, casing } = options;
+
+ switch (casing) {
case 'upper':
hexColor = hexColor.toUpperCase();
break;
@@ -68,8 +70,8 @@ function formatHexColor(
// Do nothing
}
- if (options?.prefix) {
- hexColor = options.prefix + hexColor;
+ if (prefix) {
+ hexColor = prefix + hexColor;
}
return hexColor;
@@ -360,19 +362,20 @@ export class ColorModule extends ModuleBase {
*/
includeAlpha?: boolean;
}): string | number[];
- rgb(options?: {
- prefix?: string;
- casing?: Casing;
- format?: 'hex' | ColorFormat;
- includeAlpha?: boolean;
- }): string | number[] {
+ rgb(
+ options: {
+ prefix?: string;
+ casing?: Casing;
+ format?: 'hex' | ColorFormat;
+ includeAlpha?: boolean;
+ } = {}
+ ): string | number[] {
const {
format = 'hex',
includeAlpha = false,
prefix = '#',
casing = 'lower',
- } = options || {};
- options = { format, includeAlpha, prefix, casing };
+ } = options;
let color: string | number[];
let cssFunction: CssFunctionType = 'rgb';
if (format === 'hex') {
@@ -380,7 +383,7 @@ export class ColorModule extends ModuleBase {
length: includeAlpha ? 8 : 6,
prefix: '',
});
- color = formatHexColor(color, options);
+ color = formatHexColor(color, { prefix, casing });
return color;
}
diff --git a/src/modules/commerce/index.ts b/src/modules/commerce/index.ts
index 1be3fcb2..425bc848 100644
--- a/src/modules/commerce/index.ts
+++ b/src/modules/commerce/index.ts
@@ -1,3 +1,4 @@
+import { FakerError } from '../../errors/faker-error';
import { deprecated } from '../../internal/deprecated';
import { ModuleBase } from '../../internal/module-base';
@@ -401,7 +402,14 @@ export class CommerceModule extends ModuleBase {
const registrantLength = groupRules.find(
([rangeMaximum]) => elementValue <= rangeMaximum
- )[1];
+ )?.[1];
+
+ if (!registrantLength) {
+ // This can only happen if the ISBN_LENGTH_RULES are corrupted
+ throw new FakerError(
+ `Unable to find a registrant length for the group ${group}`
+ );
+ }
const registrant = element.slice(0, registrantLength);
const publication = element.slice(registrantLength);
diff --git a/src/modules/date/index.ts b/src/modules/date/index.ts
index a40b4772..39c85735 100644
--- a/src/modules/date/index.ts
+++ b/src/modules/date/index.ts
@@ -3,6 +3,7 @@ import type { DateEntryDefinition } from '../../definitions';
import { FakerError } from '../../errors/faker-error';
import { deprecated } from '../../internal/deprecated';
import { SimpleModuleBase } from '../../internal/module-base';
+import { assertLocaleData } from '../../locale-proxy';
/**
* Converts date passed as a string, number or Date to a Date object.
@@ -15,6 +16,10 @@ function toDate(
date: string | Date | number | undefined,
fallback: () => Date
): Date {
+ if (date == null) {
+ return fallback();
+ }
+
date = new Date(date);
if (Number.isNaN(date.valueOf())) {
date = fallback();
@@ -383,14 +388,15 @@ export class SimpleDateModule extends SimpleModuleBase {
},
legacyTo?: string | Date | number
): Date {
- if (typeof options !== 'object' || options instanceof Date) {
+ if (options instanceof Date || typeof options !== 'object') {
deprecated({
deprecated: 'faker.date.between(from, to)',
proposed: 'faker.date.between({ from, to })',
since: '8.0',
until: '9.0',
});
- options = { from: options, to: legacyTo };
+ // We use options as fallback for legacyTo avoid TS errors for unintended usage.
+ options = { from: options, to: legacyTo ?? options };
}
const { from, to } = options;
@@ -559,14 +565,15 @@ export class SimpleDateModule extends SimpleModuleBase {
legacyTo?: string | Date | number,
legacyCount: number = 3
): Date[] {
- if (typeof options !== 'object' || options instanceof Date) {
+ if (options instanceof Date || typeof options !== 'object') {
deprecated({
deprecated: 'faker.date.betweens(from, to, count)',
proposed: 'faker.date.betweens({ from, to, count })',
since: '8.0',
until: '9.0',
});
- options = { from: options, to: legacyTo, count: legacyCount };
+ // We use options as fallback for legacyTo avoid TS errors for unintended usage.
+ options = { from: options, to: legacyTo ?? options, count: legacyCount };
}
const { from, to, count = 3 } = options;
@@ -864,12 +871,6 @@ export class SimpleDateModule extends SimpleModuleBase {
refDate?: string | Date | number;
} = {}
): Date {
- if (options.max < options.min) {
- throw new FakerError(
- `Max ${options.max} should be larger than or equal to min ${options.min}.`
- );
- }
-
const mode = options.mode === 'age' ? 'age' : 'year';
const refDate = toDate(options.refDate, this.faker.defaultRefDate);
const refYear = refDate.getUTCFullYear();
@@ -894,6 +895,12 @@ export class SimpleDateModule extends SimpleModuleBase {
);
}
+ if (max < min) {
+ throw new FakerError(
+ `Max ${options.max} should be larger than or equal to min ${options.min}.`
+ );
+ }
+
return new Date(this.faker.number.int({ min, max }));
}
}
@@ -1074,12 +1081,8 @@ export class DateModule extends SimpleDateModule {
context?: boolean;
} = {}
): string {
- const {
- // eslint-disable-next-line deprecation/deprecation
- abbr,
- abbreviated = abbr ?? false,
- context = false,
- } = options;
+ // eslint-disable-next-line deprecation/deprecation
+ const { abbr, abbreviated = abbr ?? false, context = false } = options;
if (abbr != null) {
deprecated({
@@ -1100,7 +1103,9 @@ export class DateModule extends SimpleDateModule {
type = useContext ? 'wide_context' : 'wide';
}
- return this.faker.helpers.arrayElement(source[type]);
+ const values = source[type];
+ assertLocaleData(values, 'date.month', type);
+ return this.faker.helpers.arrayElement(values);
}
/**
@@ -1260,12 +1265,8 @@ export class DateModule extends SimpleDateModule {
context?: boolean;
} = {}
): string {
- const {
- // eslint-disable-next-line deprecation/deprecation
- abbr,
- abbreviated = abbr ?? false,
- context = false,
- } = options;
+ // eslint-disable-next-line deprecation/deprecation
+ const { abbr, abbreviated = abbr ?? false, context = false } = options;
if (abbr != null) {
deprecated({
@@ -1286,6 +1287,8 @@ export class DateModule extends SimpleDateModule {
type = useContext ? 'wide_context' : 'wide';
}
- return this.faker.helpers.arrayElement(source[type]);
+ const values = source[type];
+ assertLocaleData(values, 'date.weekday', type);
+ return this.faker.helpers.arrayElement(values);
}
}
diff --git a/src/modules/finance/index.ts b/src/modules/finance/index.ts
index c443b605..33db26f0 100644
--- a/src/modules/finance/index.ts
+++ b/src/modules/finance/index.ts
@@ -24,6 +24,22 @@ export interface Currency {
}
/**
+ * Puts a space after every 4 characters.
+ *
+ * @internal
+ *
+ * @param iban The iban to pretty print.
+ */
+export function prettyPrintIban(iban: string): string {
+ let pretty = '';
+ for (let i = 0; i < iban.length; i += 4) {
+ pretty += `${iban.substring(i, i + 4)} `;
+ }
+
+ return pretty.trimEnd();
+}
+
+/**
* Module to generate finance and money related entries.
*
* ### Overview
@@ -663,9 +679,9 @@ export class FinanceModule extends ModuleBase {
*/
currencySymbol(): string {
let symbol: string;
- while (!symbol) {
+ do {
symbol = this.currency().symbol;
- }
+ } while (symbol.length === 0);
return symbol;
}
@@ -1147,7 +1163,7 @@ export class FinanceModule extends ModuleBase {
const result = `${ibanFormat.country}${checksum}${s}`;
- return formatted ? result.match(/.{1,4}/g).join(' ') : result;
+ return formatted ? prettyPrintIban(result) : result;
}
/**
diff --git a/src/modules/helpers/index.ts b/src/modules/helpers/index.ts
index 59eeadba..667f3a51 100644
--- a/src/modules/helpers/index.ts
+++ b/src/modules/helpers/index.ts
@@ -1120,7 +1120,7 @@ export class SimpleHelpersModule extends SimpleModuleBase {
) => RecordKey,
>(
method: TMethod,
- args: Parameters<TMethod> = [] as Parameters<TMethod>,
+ args: Parameters<TMethod> = [] as unknown as Parameters<TMethod>,
options: {
/**
* This parameter does nothing.
diff --git a/src/modules/helpers/unique.ts b/src/modules/helpers/unique.ts
index 44b3a71d..20805530 100644
--- a/src/modules/helpers/unique.ts
+++ b/src/modules/helpers/unique.ts
@@ -97,9 +97,9 @@ export function exec<
maxRetries = 50,
currentIterations = 0,
compare = defaultCompare,
- store,
+ store = {},
} = options;
- let { exclude } = options;
+ let { exclude = [] } = options;
options.currentIterations = currentIterations;
// Support single exclude argument as string
diff --git a/src/modules/internet/index.ts b/src/modules/internet/index.ts
index 5eb9b4bc..8cc651a3 100644
--- a/src/modules/internet/index.ts
+++ b/src/modules/internet/index.ts
@@ -620,6 +620,7 @@ export class InternetModule extends ModuleBase {
firstName + this.faker.helpers.arrayElement(['.', '_']) + lastName;
break;
case 2:
+ default:
result = `${firstName}${this.faker.helpers.arrayElement([
'.',
'_',
@@ -804,6 +805,7 @@ export class InternetModule extends ModuleBase {
firstName + this.faker.helpers.arrayElement(['.', '_']) + lastName;
break;
case 2:
+ default:
result = `${firstName}${this.faker.helpers.arrayElement([
'.',
'_',
diff --git a/src/modules/person/index.ts b/src/modules/person/index.ts
index e0f4b6b0..0c5f79c3 100644
--- a/src/modules/person/index.ts
+++ b/src/modules/person/index.ts
@@ -1,5 +1,7 @@
import type { Faker } from '../..';
+import { FakerError } from '../../errors/faker-error';
import { ModuleBase } from '../../internal/module-base';
+import { assertLocaleData } from '../../locale-proxy';
export enum Sex {
Female = 'female',
@@ -18,6 +20,7 @@ export type SexType = `${Sex}`;
* @param param2.generic Non-sex definitions.
* @param param2.female Female definitions.
* @param param2.male Male definitions.
+ * @param type Type of the definition.
*
* @returns Definition based on given sex.
*/
@@ -25,10 +28,14 @@ function selectDefinition<T>(
faker: Faker,
elementSelectorFn: (values: T[]) => string,
sex: SexType | undefined,
- // TODO @Shinigami92 2022-03-21: Remove fallback empty object when `strict: true`
- { generic, female, male }: { generic?: T[]; female?: T[]; male?: T[] } = {}
+ {
+ generic,
+ female,
+ male,
+ }: { generic?: T[] | null; female?: T[] | null; male?: T[] | null },
+ type: string
): string {
- let values: T[] | undefined;
+ let values: T[] | undefined | null;
switch (sex) {
case Sex.Female:
@@ -50,6 +57,8 @@ function selectDefinition<T>(
} else {
values = generic;
}
+
+ assertLocaleData(values, `person.{${type}, female_${type}, male_${type}}`);
}
return elementSelectorFn(values);
@@ -92,11 +101,17 @@ export class PersonModule extends ModuleBase {
const { first_name, female_first_name, male_first_name } =
this.faker.rawDefinitions.person ?? {};
- return selectDefinition(this.faker, this.faker.helpers.arrayElement, sex, {
- generic: first_name,
- female: female_first_name,
- male: male_first_name,
- });
+ return selectDefinition(
+ this.faker,
+ this.faker.helpers.arrayElement,
+ sex,
+ {
+ generic: first_name,
+ female: female_first_name,
+ male: male_first_name,
+ },
+ 'first_name'
+ );
}
/**
@@ -135,16 +150,23 @@ export class PersonModule extends ModuleBase {
generic: last_name_pattern,
female: female_last_name_pattern,
male: male_last_name_pattern,
- }
+ },
+ 'last_name_pattern'
);
return this.faker.helpers.fake(pattern);
}
- return selectDefinition(this.faker, this.faker.helpers.arrayElement, sex, {
- generic: last_name,
- female: female_last_name,
- male: male_last_name,
- });
+ return selectDefinition(
+ this.faker,
+ this.faker.helpers.arrayElement,
+ sex,
+ {
+ generic: last_name,
+ female: female_last_name,
+ male: male_last_name,
+ },
+ 'last_name'
+ );
}
/**
@@ -164,11 +186,17 @@ export class PersonModule extends ModuleBase {
const { middle_name, female_middle_name, male_middle_name } =
this.faker.rawDefinitions.person ?? {};
- return selectDefinition(this.faker, this.faker.helpers.arrayElement, sex, {
- generic: middle_name,
- female: female_middle_name,
- male: male_middle_name,
- });
+ return selectDefinition(
+ this.faker,
+ this.faker.helpers.arrayElement,
+ sex,
+ {
+ generic: middle_name,
+ female: female_middle_name,
+ male: male_middle_name,
+ },
+ 'middle_name'
+ );
}
/**
@@ -305,11 +333,17 @@ export class PersonModule extends ModuleBase {
const { prefix, female_prefix, male_prefix } =
this.faker.rawDefinitions.person ?? {};
- return selectDefinition(this.faker, this.faker.helpers.arrayElement, sex, {
- generic: prefix,
- female: female_prefix,
- male: male_prefix,
- });
+ return selectDefinition(
+ this.faker,
+ this.faker.helpers.arrayElement,
+ sex,
+ {
+ generic: prefix,
+ female: female_prefix,
+ male: male_prefix,
+ },
+ 'prefix'
+ );
}
/**
@@ -350,9 +384,13 @@ export class PersonModule extends ModuleBase {
* @since 8.0.0
*/
jobDescriptor(): string {
- return this.faker.helpers.arrayElement(
- this.faker.definitions.person.title.descriptor
- );
+ const values = this.faker.definitions.person.title.descriptor;
+
+ if (values == null) {
+ throw new FakerError('No person.title.descriptor definitions available.');
+ }
+
+ return this.faker.helpers.arrayElement(values);
}
/**
@@ -364,9 +402,13 @@ export class PersonModule extends ModuleBase {
* @since 8.0.0
*/
jobArea(): string {
- return this.faker.helpers.arrayElement(
- this.faker.definitions.person.title.level
- );
+ const values = this.faker.definitions.person.title.level;
+
+ if (values == null) {
+ throw new FakerError('No person.title.area definitions available.');
+ }
+
+ return this.faker.helpers.arrayElement(values);
}
/**
@@ -378,9 +420,13 @@ export class PersonModule extends ModuleBase {
* @since 8.0.0
*/
jobType(): string {
- return this.faker.helpers.arrayElement(
- this.faker.definitions.person.title.job
- );
+ const values = this.faker.definitions.person.title.job;
+
+ if (values == null) {
+ throw new FakerError('No person.title.job definitions available.');
+ }
+
+ return this.faker.helpers.arrayElement(values);
}
/**
diff --git a/src/modules/random/index.ts b/src/modules/random/index.ts
index 997583c1..474e8ca6 100644
--- a/src/modules/random/index.ts
+++ b/src/modules/random/index.ts
@@ -123,7 +123,7 @@ export class RandomModule extends ModuleBase {
'_',
'-',
];
- let result: string;
+ let result = '';
let iteration = 0;
diff --git a/test/faker.spec.ts b/test/faker.spec.ts
index 2ff5aab9..bd42246a 100644
--- a/test/faker.spec.ts
+++ b/test/faker.spec.ts
@@ -41,7 +41,7 @@ describe('faker', () => {
describe('rawDefinitions', () => {
it('locale rawDefinition accessibility', () => {
// Metadata
- expect(faker.rawDefinitions.metadata.title).toBeDefined();
+ expect(faker.rawDefinitions.metadata?.title).toBeDefined();
// Standard modules
expect(faker.rawDefinitions.location?.city_name).toBeDefined();
// Non-existing module
@@ -62,7 +62,7 @@ describe('faker', () => {
// Non-existing module
expect(faker.definitions.missing).toBeDefined();
// Non-existing definition in a non-existing module
- expect(() => faker.definitions.missing.missing).toThrow();
+ expect(() => faker.definitions.missing?.missing).toThrow();
// Non-existing definition in an existing module
expect(() => faker.definitions.location.missing).toThrow();
});
diff --git a/test/modules/airline.spec.ts b/test/modules/airline.spec.ts
index 5ac05a5b..bf674570 100644
--- a/test/modules/airline.spec.ts
+++ b/test/modules/airline.spec.ts
@@ -96,7 +96,7 @@ describe('airline', () => {
it('should return a random narrowbody seat when not passing an argument', () => {
const seat = faker.airline.seat();
const matchResult = seatRegex.exec(seat);
- expect(matchResult).not.toBeNull();
+ expectNotNull(matchResult);
const row = matchResult[1];
const seatLetter = matchResult[2];
expect(row).toSatisfy((row: number) => row >= 1 && row <= 35);
@@ -107,7 +107,7 @@ describe('airline', () => {
aircraftType: Aircraft.Narrowbody,
});
const matchResult = seatRegex.exec(seat);
- expect(matchResult).not.toBeNull();
+ expectNotNull(matchResult);
const row = matchResult[1];
const seatLetter = matchResult[2];
expect(row).toSatisfy((row: number) => row >= 1 && row <= 35);
@@ -116,7 +116,7 @@ describe('airline', () => {
it('should return a random regional seat', () => {
const seat = faker.airline.seat({ aircraftType: Aircraft.Regional });
const matchResult = seatRegex.exec(seat);
- expect(matchResult).not.toBeNull();
+ expectNotNull(matchResult);
const row = matchResult[1];
const seatLetter = matchResult[2];
expect(row).toSatisfy((row: number) => row >= 1 && row <= 20);
@@ -125,7 +125,7 @@ describe('airline', () => {
it('should return a random widebody seat', () => {
const seat = faker.airline.seat({ aircraftType: Aircraft.Widebody });
const matchResult = seatRegex.exec(seat);
- expect(matchResult).not.toBeNull();
+ expectNotNull(matchResult);
const row = matchResult[1];
const seatLetter = matchResult[2];
expect(row).toSatisfy((row: number) => row >= 1 && row <= 60);
@@ -179,3 +179,7 @@ describe('airline', () => {
}
);
});
+
+function expectNotNull<T>(value: T): asserts value is NonNullable<T> {
+ expect(value).not.toBeNull();
+}
diff --git a/test/modules/finance-iban.spec.ts b/test/modules/finance-iban.spec.ts
index 145a4751..4d801aa5 100644
--- a/test/modules/finance-iban.spec.ts
+++ b/test/modules/finance-iban.spec.ts
@@ -1,6 +1,7 @@
import validator from 'validator';
import { describe, expect, it } from 'vitest';
import { faker } from '../../src';
+import { prettyPrintIban } from '../../src/modules/finance';
import ibanLib from '../../src/modules/finance/iban';
import { times } from '../support/times';
@@ -36,7 +37,7 @@ describe('finance_iban', () => {
expect(iban).toSatisfy(validator.isIBAN);
- const ibanFormatted = iban.match(/.{1,4}/g).join(' ');
+ const ibanFormatted = prettyPrintIban(iban);
const bban = iban.substring(4) + iban.substring(0, 4);
expect(
@@ -96,7 +97,7 @@ describe('finance_iban', () => {
expect(iban).toSatisfy(validator.isIBAN);
- const ibanFormated = iban.match(/.{1,4}/g).join(' ');
+ const ibanFormated = prettyPrintIban(iban);
const bban = iban.substring(4) + iban.substring(0, 4);
expect(
@@ -162,7 +163,7 @@ describe('finance_iban', () => {
expect(iban).toSatisfy(validator.isIBAN);
- const ibanFormated = iban.match(/.{1,4}/g).join(' ');
+ const ibanFormated = prettyPrintIban(iban);
const bban = iban.substring(4) + iban.substring(0, 4);
expect(
@@ -232,7 +233,7 @@ describe('finance_iban', () => {
expect(iban).toSatisfy(validator.isIBAN);
- const ibanFormated = iban.match(/.{1,4}/g).join(' ');
+ const ibanFormated = prettyPrintIban(iban);
const bban = iban.substring(4) + iban.substring(0, 4);
expect(
@@ -291,7 +292,7 @@ describe('finance_iban', () => {
expect(iban).toSatisfy(validator.isIBAN);
- const ibanFormated = iban.match(/.{1,4}/g).join(' ');
+ const ibanFormated = prettyPrintIban(iban);
const bban = iban.substring(4) + iban.substring(0, 4);
expect(
@@ -336,7 +337,7 @@ describe('finance_iban', () => {
// Bank account number 16 digit
const iban = faker.finance.iban(false, 'AL');
- const ibanFormated = iban.match(/.{1,4}/g).join(' ');
+ const ibanFormated = prettyPrintIban(iban);
expect(iban).toSatisfy(validator.isIBAN);
diff --git a/test/modules/helpers.spec.ts b/test/modules/helpers.spec.ts
index 3f850086..766d0650 100644
--- a/test/modules/helpers.spec.ts
+++ b/test/modules/helpers.spec.ts
@@ -223,7 +223,6 @@ describe('helpers', () => {
});
it('should throw on an empty array', () => {
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
expect(() => faker.helpers.arrayElement([])).toThrow(
new FakerError('Cannot get value from empty dataset.')
);
@@ -1062,7 +1061,7 @@ describe('helpers', () => {
});
it('should be able to return locale definition strings', () => {
- expect(faker.definitions.cell_phone.formats).toContain(
+ expect(faker.definitions.cell_phone?.formats).toContain(
faker.helpers.fake('{{cell_phone.formats}}')
);
});
diff --git a/test/scripts/apidoc/verify-jsdoc-tags.spec.ts b/test/scripts/apidoc/verify-jsdoc-tags.spec.ts
index 7e020335..b4a9f5ff 100644
--- a/test/scripts/apidoc/verify-jsdoc-tags.spec.ts
+++ b/test/scripts/apidoc/verify-jsdoc-tags.spec.ts
@@ -160,7 +160,7 @@ describe('verify JSDoc tags', () => {
// Write temp files to disk
// Extract examples and make them runnable
- const examples = extractJoinedRawExamples(signature);
+ const examples = extractJoinedRawExamples(signature) ?? '';
// Save examples to a file to run them later in the specific tests
const dir = resolveDirToModule(moduleName);
diff --git a/test/vitest-extensions.ts b/test/vitest-extensions.ts
index e23b9c09..0a441d87 100644
--- a/test/vitest-extensions.ts
+++ b/test/vitest-extensions.ts
@@ -2,7 +2,7 @@ import { expect } from 'vitest';
expect.extend({
toContainDuplicates<T>(received: T[]) {
- const { isNot } = this;
+ const { isNot = false } = this;
const uniques = new Set(received);
const duplications = received.filter((entry) => !uniques.delete(entry));
diff --git a/tsconfig.json b/tsconfig.json
index cda27929..da5cd4e6 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -9,7 +9,6 @@
"stripInternal": true,
// We need to disable these for now, and need to tackle them in another PR
- "strictNullChecks": false,
"noImplicitAny": false,
// These are configs specifically for !build and have to be reverted in the tsconfig.build.json