diff options
| author | Matt Mayer <[email protected]> | 2022-12-04 03:15:36 +0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-12-03 21:15:36 +0100 |
| commit | 4ed45fa33f80c59625a285d06abe31ce2f524357 (patch) | |
| tree | a01624a3f23004160fcbe63533358ae8819d67ca | |
| parent | 5e51335e19426820874c75678ee5a7ebd332a911 (diff) | |
| download | faker-4ed45fa33f80c59625a285d06abe31ce2f524357.tar.xz faker-4ed45fa33f80c59625a285d06abe31ce2f524357.zip | |
fix(internet): userName, email and slugify return only ascii (#1554)
| -rw-r--r-- | src/modules/helpers/index.ts | 6 | ||||
| -rw-r--r-- | src/modules/internet/char-mappings.ts | 285 | ||||
| -rw-r--r-- | src/modules/internet/index.ts | 81 | ||||
| -rw-r--r-- | test/__snapshots__/internet.spec.ts.snap | 96 | ||||
| -rw-r--r-- | test/helpers.spec.ts | 14 | ||||
| -rw-r--r-- | test/internet.spec.ts | 98 |
6 files changed, 542 insertions, 38 deletions
diff --git a/src/modules/helpers/index.ts b/src/modules/helpers/index.ts index 6caa8eff..7f2c5898 100644 --- a/src/modules/helpers/index.ts +++ b/src/modules/helpers/index.ts @@ -33,8 +33,10 @@ export class HelpersModule { */ slugify(string: string = ''): string { return string - .replace(/ /g, '-') - .replace(/[^\一-龠\ぁ-ゔ\ァ-ヴー\w\.\-]+/g, ''); + .normalize('NFKD') //for example è decomposes to as e + ̀ + .replace(/[\u0300-\u036f]/g, '') // removes combining marks + .replace(/ /g, '-') // replaces spaces with hyphens + .replace(/[^\w\.\-]+/g, ''); // removes all non-word characters except for dots and hyphens } /** diff --git a/src/modules/internet/char-mappings.ts b/src/modules/internet/char-mappings.ts new file mode 100644 index 00000000..6b784379 --- /dev/null +++ b/src/modules/internet/char-mappings.ts @@ -0,0 +1,285 @@ +// Selectively sourced from https://github.com/sindresorhus/transliterate/blob/08bbfd3a13ac393d945a430ed5ec62f044a08d70/replacements.js (under MIT license) +const cyrillicMapping: { [key: string]: string } = Object.fromEntries([ + ['А', 'A'], + ['а', 'a'], + ['Б', 'B'], + ['б', 'b'], + ['В', 'V'], + ['в', 'v'], + ['Г', 'G'], + ['г', 'g'], + ['Д', 'D'], + ['д', 'd'], + ['ъе', 'ye'], + ['Ъе', 'Ye'], + ['ъЕ', 'yE'], + ['ЪЕ', 'YE'], + ['Е', 'E'], + ['е', 'e'], + ['Ё', 'Yo'], + ['ё', 'yo'], + ['Ж', 'Zh'], + ['ж', 'zh'], + ['З', 'Z'], + ['з', 'z'], + ['И', 'I'], + ['и', 'i'], + ['ый', 'iy'], + ['Ый', 'Iy'], + ['ЫЙ', 'IY'], + ['ыЙ', 'iY'], + ['Й', 'Y'], + ['й', 'y'], + ['К', 'K'], + ['к', 'k'], + ['Л', 'L'], + ['л', 'l'], + ['М', 'M'], + ['м', 'm'], + ['Н', 'N'], + ['н', 'n'], + ['О', 'O'], + ['о', 'o'], + ['П', 'P'], + ['п', 'p'], + ['Р', 'R'], + ['р', 'r'], + ['С', 'S'], + ['с', 's'], + ['Т', 'T'], + ['т', 't'], + ['У', 'U'], + ['у', 'u'], + ['Ф', 'F'], + ['ф', 'f'], + ['Х', 'Kh'], + ['х', 'kh'], + ['Ц', 'Ts'], + ['ц', 'ts'], + ['Ч', 'Ch'], + ['ч', 'ch'], + ['Ш', 'Sh'], + ['ш', 'sh'], + ['Щ', 'Sch'], + ['щ', 'sch'], + ['Ъ', ''], + ['ъ', ''], + ['Ы', 'Y'], + ['ы', 'y'], + ['Ь', ''], + ['ь', ''], + ['Э', 'E'], + ['э', 'e'], + ['Ю', 'Yu'], + ['ю', 'yu'], + ['Я', 'Ya'], + ['я', 'ya'], +]); +const greekMapping: { [key: string]: string } = Object.fromEntries([ + ['α', 'a'], + ['β', 'v'], + ['γ', 'g'], + ['δ', 'd'], + ['ε', 'e'], + ['ζ', 'z'], + ['η', 'i'], + ['θ', 'th'], + ['ι', 'i'], + ['κ', 'k'], + ['λ', 'l'], + ['μ', 'm'], + ['ν', 'n'], + ['ξ', 'ks'], + ['ο', 'o'], + ['π', 'p'], + ['ρ', 'r'], + ['σ', 's'], + ['τ', 't'], + ['υ', 'y'], + ['φ', 'f'], + ['χ', 'x'], + ['ψ', 'ps'], + ['ω', 'o'], + ['ά', 'a'], + ['έ', 'e'], + ['ί', 'i'], + ['ό', 'o'], + ['ύ', 'y'], + ['ή', 'i'], + ['ώ', 'o'], + ['ς', 's'], + ['ϊ', 'i'], + ['ΰ', 'y'], + ['ϋ', 'y'], + ['ΐ', 'i'], + ['Α', 'A'], + ['Β', 'B'], + ['Γ', 'G'], + ['Δ', 'D'], + ['Ε', 'E'], + ['Ζ', 'Z'], + ['Η', 'I'], + ['Θ', 'TH'], + ['Ι', 'I'], + ['Κ', 'K'], + ['Λ', 'L'], + ['Μ', 'M'], + ['Ν', 'N'], + ['Ξ', 'KS'], + ['Ο', 'O'], + ['Π', 'P'], + ['Ρ', 'R'], + ['Σ', 'S'], + ['Τ', 'T'], + ['Υ', 'Y'], + ['Φ', 'F'], + ['Χ', 'X'], + ['Ψ', 'PS'], + ['Ω', 'O'], + ['Ά', 'A'], + ['Έ', 'E'], + ['Ί', 'I'], + ['Ό', 'O'], + ['Ύ', 'Y'], + ['Ή', 'I'], + ['Ώ', 'O'], + ['Ϊ', 'I'], + ['Ϋ', 'Y'], +]); +const arabicMapping: { [key: string]: string } = Object.fromEntries([ + ['ء', 'e'], + ['آ', 'a'], + ['أ', 'a'], + ['ؤ', 'w'], + ['إ', 'i'], + ['ئ', 'y'], + ['ا', 'a'], + ['ب', 'b'], + ['ة', 't'], + ['ت', 't'], + ['ث', 'th'], + ['ج', 'j'], + ['ح', 'h'], + ['خ', 'kh'], + ['د', 'd'], + ['ذ', 'dh'], + ['ر', 'r'], + ['ز', 'z'], + ['س', 's'], + ['ش', 'sh'], + ['ص', 's'], + ['ض', 'd'], + ['ط', 't'], + ['ظ', 'z'], + ['ع', 'e'], + ['غ', 'gh'], + ['ـ', '_'], + ['ف', 'f'], + ['ق', 'q'], + ['ك', 'k'], + ['ل', 'l'], + ['م', 'm'], + ['ن', 'n'], + ['ه', 'h'], + ['و', 'w'], + ['ى', 'a'], + ['ي', 'y'], + ['َ', 'a'], + ['ُ', 'u'], + ['ِ', 'i'], +]); +const armenianMapping: { [key: string]: string } = Object.fromEntries([ + ['ա', 'a'], + ['Ա', 'A'], + ['բ', 'b'], + ['Բ', 'B'], + ['գ', 'g'], + ['Գ', 'G'], + ['դ', 'd'], + ['Դ', 'D'], + ['ե', 'ye'], + ['Ե', 'Ye'], + ['զ', 'z'], + ['Զ', 'Z'], + ['է', 'e'], + ['Է', 'E'], + ['ը', 'y'], + ['Ը', 'Y'], + ['թ', 't'], + ['Թ', 'T'], + ['ժ', 'zh'], + ['Ժ', 'Zh'], + ['ի', 'i'], + ['Ի', 'I'], + ['լ', 'l'], + ['Լ', 'L'], + ['խ', 'kh'], + ['Խ', 'Kh'], + ['ծ', 'ts'], + ['Ծ', 'Ts'], + ['կ', 'k'], + ['Կ', 'K'], + ['հ', 'h'], + ['Հ', 'H'], + ['ձ', 'dz'], + ['Ձ', 'Dz'], + ['ղ', 'gh'], + ['Ղ', 'Gh'], + ['ճ', 'tch'], + ['Ճ', 'Tch'], + ['մ', 'm'], + ['Մ', 'M'], + ['յ', 'y'], + ['Յ', 'Y'], + ['ն', 'n'], + ['Ն', 'N'], + ['շ', 'sh'], + ['Շ', 'Sh'], + ['ո', 'vo'], + ['Ո', 'Vo'], + ['չ', 'ch'], + ['Չ', 'Ch'], + ['պ', 'p'], + ['Պ', 'P'], + ['ջ', 'j'], + ['Ջ', 'J'], + ['ռ', 'r'], + ['Ռ', 'R'], + ['ս', 's'], + ['Ս', 'S'], + ['վ', 'v'], + ['Վ', 'V'], + ['տ', 't'], + ['Տ', 'T'], + ['ր', 'r'], + ['Ր', 'R'], + ['ց', 'c'], + ['Ց', 'C'], + ['ու', 'u'], + ['ՈՒ', 'U'], + ['Ու', 'U'], + ['փ', 'p'], + ['Փ', 'P'], + ['ք', 'q'], + ['Ք', 'Q'], + ['օ', 'o'], + ['Օ', 'O'], + ['ֆ', 'f'], + ['Ֆ', 'F'], + ['և', 'yev'], +]); +const farsiMapping: { [key: string]: string } = Object.fromEntries([ + ['چ', 'ch'], + ['ک', 'k'], + ['گ', 'g'], + ['پ', 'p'], + ['ژ', 'zh'], + ['ی', 'y'], +]); +export const charMapping: { [key: string]: string } = { + ...cyrillicMapping, + ...greekMapping, + ...arabicMapping, + ...farsiMapping, + ...armenianMapping, +}; diff --git a/src/modules/internet/index.ts b/src/modules/internet/index.ts index a32045d9..dc3eaa62 100644 --- a/src/modules/internet/index.ts +++ b/src/modules/internet/index.ts @@ -1,4 +1,5 @@ import type { Faker } from '../..'; +import { charMapping } from './char-mappings'; import * as random_ua from './user-agent'; export type EmojiType = @@ -81,10 +82,7 @@ export class InternetModule { this.faker.definitions.internet.free_email ); - let localPart: string = this.faker.helpers.slugify( - this.userName(firstName, lastName) - ); - + let localPart: string = this.userName(firstName, lastName); if (options?.allowSpecialCharacters) { const usernameChars: string[] = '._-'.split(''); const specialChars: string[] = ".!#$%&'*+-/=?^_`{|}~".split(''); @@ -125,14 +123,20 @@ export class InternetModule { } /** - * Generates a username using the given person's name as base. + * Generates a username using the given person's name as base. The resuling username may use neither, one or both of the names provided. This will always return a plain ASCII string. Some basic stripping of accents and transliteration of characters will be done. * * @param firstName The optional first name to use. If not specified, a random one will be chosen. * @param lastName The optional last name to use. If not specified, a random one will be chosen. * + * @see faker.internet.displayName() + * * @example * faker.internet.userName() // 'Nettie_Zboncak40' - * faker.internet.userName('Jeanne', 'Doe') // 'Jeanne98' + * faker.internet.userName('Jeanne', 'Doe') // 'Jeanne98' - note surname is not used + * faker.internet.userName('John', 'Doe') // 'John.Doe' + * faker.internet.userName('Hélene', 'Müller') // 'Helene_Muller11' + * faker.internet.userName('Фёдор', 'Достоевский') // 'Fedor.Dostoevskii50' + * faker.internet.userName('大羽', '陳') // 'hlzp8d.tpv45' - note neither name is used * * @since 2.0.1 */ @@ -155,6 +159,71 @@ export class InternetModule { ])}${lastName}${this.faker.number.int(99)}`; break; } + + // There may still be non-ascii characters in the result. + // First remove simple accents etc + result = result + .normalize('NFKD') //for example è decomposes to as e + ̀ + .replace(/[\u0300-\u036f]/g, ''); // removes combining marks + + result = result + .split('') + .map((char) => { + // If we have a mapping for this character, (for Cyrillic, Greek etc) use it + if (charMapping[char]) { + return charMapping[char]; + } + if (char.charCodeAt(0) < 0x80) { + // Keep ASCII characters + return char; + } + // Final fallback return the Unicode char code value for Chinese, Japanese, Korean etc, base-36 encoded + return char.charCodeAt(0).toString(36); + }) + .join(''); + result = result.toString().replace(/'/g, ''); + result = result.replace(/ /g, ''); + + return result; + } + + /** + * Generates a display name using the given person's name as base. The resulting display name may use one or both of the provided names. If the input names include Unicode characters, the resulting display name will contain Unicode characters. It will not contain spaces. + * + * @param firstName The optional first name to use. If not specified, a random one will be chosen. + * @param lastName The optional last name to use. If not specified, a random one will be chosen. + * + * @see faker.internet.userName() + * + * @example + * faker.internet.displayName() // 'Nettie_Zboncak40' + * faker.internet.displayName('Jeanne', 'Doe') // 'Jeanne98' - note surname not used. + * faker.internet.displayName('John', 'Doe') // 'John.Doe' + * faker.internet.displayName('Hélene', 'Müller') // 'Hélene_Müller11' + * faker.internet.displayName('Фёдор', 'Достоевский') // 'Фёдор.Достоевский50' + * faker.internet.displayName('大羽', '陳') // '大羽.陳' + * + * @since 8.0.0 + */ + displayName(firstName?: string, lastName?: string): string { + let result: string; + firstName = firstName || this.faker.person.firstName(); + lastName = lastName || this.faker.person.lastName(); + switch (this.faker.number.int(2)) { + case 0: + result = `${firstName}${this.faker.number.int(99)}`; + break; + case 1: + result = + firstName + this.faker.helpers.arrayElement(['.', '_']) + lastName; + break; + case 2: + result = `${firstName}${this.faker.helpers.arrayElement([ + '.', + '_', + ])}${lastName}${this.faker.number.int(99)}`; + break; + } result = result.toString().replace(/'/g, ''); result = result.replace(/ /g, ''); return result; diff --git a/test/__snapshots__/internet.spec.ts.snap b/test/__snapshots__/internet.spec.ts.snap index 4b87bff9..5b33c9e2 100644 --- a/test/__snapshots__/internet.spec.ts.snap +++ b/test/__snapshots__/internet.spec.ts.snap @@ -6,6 +6,24 @@ exports[`internet > 42 > color > noArgs 1`] = `"#30667a"`; exports[`internet > 42 > color > with color base 1`] = `"#6298ac"`; +exports[`internet > 42 > displayName > noArgs 1`] = `"Garnet.Schinner73"`; + +exports[`internet > 42 > displayName > noArgs 2`] = `"Garnet.Schinner73"`; + +exports[`internet > 42 > displayName > noArgs 3`] = `"Garnet.Schinner73"`; + +exports[`internet > 42 > displayName > noArgs 4`] = `"Garnet.Schinner73"`; + +exports[`internet > 42 > displayName > with Chinese names 1`] = `"大羽_陳"`; + +exports[`internet > 42 > displayName > with Cyrillic names 1`] = `"Фёдор_Достоевский"`; + +exports[`internet > 42 > displayName > with Latin names 1`] = `"Jane_Doe"`; + +exports[`internet > 42 > displayName > with accented names 1`] = `"Hélene_Müller"`; + +exports[`internet > 42 > displayName > with names 1`] = `"Jane_Doe"`; + exports[`internet > 42 > domainName 1`] = `"hasty-shin.org"`; exports[`internet > 42 > domainSuffix 1`] = `"info"`; @@ -62,6 +80,20 @@ exports[`internet > 42 > userAgent 1`] = `"Mozilla/5.0 (Windows; U; Windows NT 6 exports[`internet > 42 > userName > noArgs 1`] = `"Garnet.Schinner73"`; +exports[`internet > 42 > userName > noArgs 2`] = `"Garnet.Schinner73"`; + +exports[`internet > 42 > userName > noArgs 3`] = `"Garnet.Schinner73"`; + +exports[`internet > 42 > userName > noArgs 4`] = `"Garnet.Schinner73"`; + +exports[`internet > 42 > userName > with Chinese names 1`] = `"hlzp8d_tpv"`; + +exports[`internet > 42 > userName > with Cyrillic names 1`] = `"Fedor_Dostoevskii"`; + +exports[`internet > 42 > userName > with Latin names 1`] = `"Jane_Doe"`; + +exports[`internet > 42 > userName > with accented names 1`] = `"Helene_Muller"`; + exports[`internet > 42 > userName > with names 1`] = `"Jane_Doe"`; exports[`internet > 1211 > avatar 1`] = `"https://cloudflare-ipfs.com/ipfs/Qmd3W5DuhgHirLHGVixi6V76LhCkZUz6pnFt5AJBiyvHye/avatar/1160.jpg"`; @@ -70,6 +102,24 @@ exports[`internet > 1211 > color > noArgs 1`] = `"#773a72"`; exports[`internet > 1211 > color > with color base 1`] = `"#a96ca4"`; +exports[`internet > 1211 > displayName > noArgs 1`] = `"Tito_Koelpin22"`; + +exports[`internet > 1211 > displayName > noArgs 2`] = `"Tito_Koelpin22"`; + +exports[`internet > 1211 > displayName > noArgs 3`] = `"Tito_Koelpin22"`; + +exports[`internet > 1211 > displayName > noArgs 4`] = `"Tito_Koelpin22"`; + +exports[`internet > 1211 > displayName > with Chinese names 1`] = `"大羽.陳89"`; + +exports[`internet > 1211 > displayName > with Cyrillic names 1`] = `"Фёдор.Достоевский89"`; + +exports[`internet > 1211 > displayName > with Latin names 1`] = `"Jane.Doe89"`; + +exports[`internet > 1211 > displayName > with accented names 1`] = `"Hélene.Müller89"`; + +exports[`internet > 1211 > displayName > with names 1`] = `"Jane.Doe89"`; + exports[`internet > 1211 > domainName 1`] = `"vibrant-infix.org"`; exports[`internet > 1211 > domainSuffix 1`] = `"org"`; @@ -126,6 +176,20 @@ exports[`internet > 1211 > userAgent 1`] = `"Mozilla/5.0 (Macintosh; U; Intel Ma exports[`internet > 1211 > userName > noArgs 1`] = `"Tito_Koelpin22"`; +exports[`internet > 1211 > userName > noArgs 2`] = `"Tito_Koelpin22"`; + +exports[`internet > 1211 > userName > noArgs 3`] = `"Tito_Koelpin22"`; + +exports[`internet > 1211 > userName > noArgs 4`] = `"Tito_Koelpin22"`; + +exports[`internet > 1211 > userName > with Chinese names 1`] = `"hlzp8d.tpv89"`; + +exports[`internet > 1211 > userName > with Cyrillic names 1`] = `"Fedor.Dostoevskii89"`; + +exports[`internet > 1211 > userName > with Latin names 1`] = `"Jane.Doe89"`; + +exports[`internet > 1211 > userName > with accented names 1`] = `"Helene.Muller89"`; + exports[`internet > 1211 > userName > with names 1`] = `"Jane.Doe89"`; exports[`internet > 1337 > avatar 1`] = `"https://cloudflare-ipfs.com/ipfs/Qmd3W5DuhgHirLHGVixi6V76LhCkZUz6pnFt5AJBiyvHye/avatar/327.jpg"`; @@ -134,6 +198,24 @@ exports[`internet > 1337 > color > noArgs 1`] = `"#214814"`; exports[`internet > 1337 > color > with color base 1`] = `"#537a46"`; +exports[`internet > 1337 > displayName > noArgs 1`] = `"Devyn21"`; + +exports[`internet > 1337 > displayName > noArgs 2`] = `"Devyn21"`; + +exports[`internet > 1337 > displayName > noArgs 3`] = `"Devyn21"`; + +exports[`internet > 1337 > displayName > noArgs 4`] = `"Devyn21"`; + +exports[`internet > 1337 > displayName > with Chinese names 1`] = `"大羽56"`; + +exports[`internet > 1337 > displayName > with Cyrillic names 1`] = `"Фёдор56"`; + +exports[`internet > 1337 > displayName > with Latin names 1`] = `"Jane56"`; + +exports[`internet > 1337 > displayName > with accented names 1`] = `"Hélene56"`; + +exports[`internet > 1337 > displayName > with names 1`] = `"Jane56"`; + exports[`internet > 1337 > domainName 1`] = `"fair-migration.com"`; exports[`internet > 1337 > domainSuffix 1`] = `"biz"`; @@ -190,4 +272,18 @@ exports[`internet > 1337 > userAgent 1`] = `"Mozilla/5.0 (Windows; U; Windows NT exports[`internet > 1337 > userName > noArgs 1`] = `"Devyn21"`; +exports[`internet > 1337 > userName > noArgs 2`] = `"Devyn21"`; + +exports[`internet > 1337 > userName > noArgs 3`] = `"Devyn21"`; + +exports[`internet > 1337 > userName > noArgs 4`] = `"Devyn21"`; + +exports[`internet > 1337 > userName > with Chinese names 1`] = `"hlzp8d56"`; + +exports[`internet > 1337 > userName > with Cyrillic names 1`] = `"Fedor56"`; + +exports[`internet > 1337 > userName > with Latin names 1`] = `"Jane56"`; + +exports[`internet > 1337 > userName > with accented names 1`] = `"Helene56"`; + exports[`internet > 1337 > userName > with names 1`] = `"Jane56"`; diff --git a/test/helpers.spec.ts b/test/helpers.spec.ts index c56d2589..530c3b49 100644 --- a/test/helpers.spec.ts +++ b/test/helpers.spec.ts @@ -180,9 +180,19 @@ describe('helpers', () => { }); describe('slugify()', () => { - it('removes unwanted characters from URI string', () => { - expect(faker.helpers.slugify('Aiden.Harªann')).toBe('Aiden.Harann'); + it('removes non-word characters from strings except . and -', () => { + expect(faker.helpers.slugify('foo bar')).toBe('foo-bar'); + expect(faker.helpers.slugify('Faker is cool')).toBe('Faker-is-cool'); + expect(faker.helpers.slugify('super*star')).toBe('superstar'); expect(faker.helpers.slugify("d'angelo.net")).toBe('dangelo.net'); + expect(faker.helpers.slugify('hello你好')).toBe('hello'); + }); + + it('strips simple diacritics from strings', () => { + expect(faker.helpers.slugify('Aiden.Harªann')).toBe('Aiden.Haraann'); + expect(faker.helpers.slugify('Adèle.Argüello')).toBe( + 'Adele.Arguello' + ); }); }); diff --git a/test/internet.spec.ts b/test/internet.spec.ts index 02f0edaa..45ed1963 100644 --- a/test/internet.spec.ts +++ b/test/internet.spec.ts @@ -38,7 +38,17 @@ describe('internet', () => { }); t.describe('userName', (t) => { - t.it('noArgs').it('with names', 'Jane', 'Doe'); + t.it('noArgs').it('with Latin names', 'Jane', 'Doe'); + t.it('noArgs').it('with accented names', 'Hélene', 'Müller'); + t.it('noArgs').it('with Cyrillic names', 'Фёдор', 'Достоевский'); + t.it('noArgs').it('with Chinese names', '大羽', '陳'); + }); + + t.describe('displayName', (t) => { + t.it('noArgs').it('with Latin names', 'Jane', 'Doe'); + t.it('noArgs').it('with accented names', 'Hélene', 'Müller'); + t.it('noArgs').it('with Cyrillic names', 'Фёдор', 'Достоевский'); + t.it('noArgs').it('with Chinese names', '大羽', '陳'); }); t.describe('password', (t) => { @@ -98,6 +108,20 @@ describe('internet', () => { expect(faker.definitions.internet.free_email).toContain(suffix); }); + it('should return a valid email in every locale', () => { + for (const locale of Object.keys(faker.locales)) { + faker.setLocale(locale); + const email = faker.internet.email(); + + expect(email).toBeTruthy(); + expect(email).toBeTypeOf('string'); + expect(email).toSatisfy( + validator.isEmail, + `locale: ${locale} has invalid email: ${email}` + ); + } + }); + it('should return an email with given firstName', () => { const email = faker.internet.email('Aiden.Harann55'); @@ -130,19 +154,6 @@ describe('internet', () => { expect(faker.definitions.internet.free_email).toContain(suffix); }); - it('should return an email with japanese characters', () => { - const email = faker.internet.email('思源_唐3'); - - expect(email).toBeTruthy(); - expect(email).toBeTypeOf('string'); - expect(email).toSatisfy(validator.isEmail); - - const [prefix, suffix] = email.split('@'); - - expect(prefix).toMatch(/^思源_唐3/); - expect(faker.definitions.internet.free_email).toContain(suffix); - }); - it('should return an email with special characters', () => { const email = faker.internet.email('Mike', 'Smith', null, { allowSpecialCharacters: true, @@ -203,20 +214,6 @@ describe('internet', () => { expect(prefix).toMatch(/^Aiden([._]Harann)?\d*/); }); - it('should return an email with the example suffix and japanese characters', () => { - const email = faker.internet.exampleEmail('思源_唐3'); - - expect(email).toBeTruthy(); - expect(email).toBeTypeOf('string'); - expect(email).toSatisfy(validator.isEmail); - - const [prefix, suffix] = email.split('@'); - - expect(suffix).toMatch(/^example\.(com|net|org)$/); - expect(faker.definitions.internet.example_email).toContain(suffix); - expect(prefix).toMatch(/^思源_唐3/); - }); - it('should return an email with special characters', () => { const email = faker.internet.exampleEmail('Mike', 'Smith', { allowSpecialCharacters: true, @@ -262,6 +259,51 @@ describe('internet', () => { /^Aiden((\d{1,2})|([._]Harann\d{1,2})|([._](Harann)))/ ); }); + + it('should strip accents', () => { + const username = faker.internet.userName('Adèle', 'Smith'); + expect(username).includes('Adele'); + }); + + it('should transliterate Cyrillic', () => { + const username = faker.internet.userName('Амос', 'Васильев'); + expect(username).includes('Amos'); + }); + + it('should provide a fallback for Chinese etc', () => { + const username = faker.internet.userName('大羽', '陳'); + expect(username).includes('hlzp8d'); + }); + }); + + describe('displayName()', () => { + it('should return a random display name', () => { + const displayName = faker.internet.displayName(); + + expect(displayName).toBeTruthy(); + expect(displayName).toBeTypeOf('string'); + expect(displayName).toMatch(/\w/); + }); + + it('should return a random display name with given firstName', () => { + const displayName = faker.internet.displayName('Aiden'); + + expect(displayName).toBeTruthy(); + expect(displayName).toBeTypeOf('string'); + expect(displayName).toMatch(/\w/); + expect(displayName).includes('Aiden'); + }); + + it('should return a random display name with given firstName and lastName', () => { + const displayName = faker.internet.displayName('Aiden', 'Harann'); + + expect(displayName).toBeTruthy(); + expect(displayName).toBeTypeOf('string'); + expect(displayName).includes('Aiden'); + expect(displayName).toMatch( + /^Aiden((\d{1,2})|([._]Harann\d{1,2})|([._](Harann)))/ + ); + }); }); describe('protocol()', () => { |
