From 525fedc91bd02f53330cfb40fe228b148dcf562b Mon Sep 17 00:00:00 2001 From: Matt Mayer <152770+matthewmayer@users.noreply.github.com> Date: Fri, 8 Nov 2024 17:57:53 +0700 Subject: [PATCH] fix(internet): ensure domainWord always returns a valid value in all locales (#3253) --- src/modules/internet/index.ts | 29 ++++++++++++++++++++++++++--- test/modules/internet.spec.ts | 13 ++++++++++++- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/modules/internet/index.ts b/src/modules/internet/index.ts index 58c6e586aab..115bd21581d 100644 --- a/src/modules/internet/index.ts +++ b/src/modules/internet/index.ts @@ -595,9 +595,32 @@ export class InternetModule extends ModuleBase { * @since 2.0.1 */ domainWord(): string { - return this.faker.helpers - .slugify(`${this.faker.word.adjective()}-${this.faker.word.noun()}`) - .toLowerCase(); + // Generate an ASCII "word" in the form `noun-adjective` + // For locales with non-ASCII characters, we fall back to lorem words, or a random string + const isValidSlug = (slug: string): boolean => { + return /^[a-z][a-z-]*[a-z]$/i.exec(slug) !== null; + }; + + const makeValidSlug = (word: string): string => { + const slug1 = this.faker.helpers.slugify(word); + if (isValidSlug(slug1)) { + return slug1; + } + + const slug2 = this.faker.helpers.slugify(this.faker.lorem.word()); + if (isValidSlug(slug2)) { + return slug2; + } + + return this.faker.string.alpha({ + casing: 'lower', + length: this.faker.number.int({ min: 4, max: 8 }), + }); + }; + + const word1 = makeValidSlug(this.faker.word.adjective()); + const word2 = makeValidSlug(this.faker.word.noun()); + return `${word1}-${word2}`.toLowerCase(); } /** diff --git a/test/modules/internet.spec.ts b/test/modules/internet.spec.ts index 84ded3d4480..cade8ddf102 100644 --- a/test/modules/internet.spec.ts +++ b/test/modules/internet.spec.ts @@ -1,6 +1,6 @@ import validator from 'validator'; import { describe, expect, it } from 'vitest'; -import { allFakers, faker } from '../../src'; +import { allFakers, faker, fakerKO } from '../../src'; import { FakerError } from '../../src/errors/faker-error'; import { IPv4Network } from '../../src/modules/internet'; import { seededTests } from '../support/seeded-runs'; @@ -667,6 +667,17 @@ describe('internet', () => { validator.isFQDN(value, { require_tld: false }) ); }); + + it('should return a lower-case domain in non-ASCII locales', () => { + const domainWord = fakerKO.internet.domainWord(); + + expect(domainWord).toBeTruthy(); + expect(domainWord).toBeTypeOf('string'); + expect(domainWord).toSatisfy(validator.isSlug); + expect(domainWord).toSatisfy((value: string) => + validator.isFQDN(value, { require_tld: false }) + ); + }); }); describe('ip()', () => {