Skip to content

Commit

Permalink
infra(unicorn): consistent-function-scoping (#3255)
Browse files Browse the repository at this point in the history
  • Loading branch information
ST-DDT authored Nov 14, 2024
1 parent a54c1ed commit 188309a
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 90 deletions.
1 change: 0 additions & 1 deletion eslint.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,6 @@ const config: ReturnType<typeof tseslint.config> = tseslint.config(

// TODO @Shinigami92 2023-09-23: The following rules currently conflict with our code.
// Each rule should be checked whether it should be enabled/configured and the problems fixed, or stay disabled permanently.
'unicorn/consistent-function-scoping': 'off',
'unicorn/prefer-export-from': 'off',
'unicorn/prevent-abbreviations': 'off',
},
Expand Down
26 changes: 17 additions & 9 deletions src/modules/color/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,15 @@ function toBinary(values: number[]): string {
return binary.join(' ');
}

/**
* Converts the given value to a percentage (`round(value * 100)`).
*
* @param value The value to convert to a percentage.
*/
function toPercentage(value: number): number {
return Math.round(value * 100);
}

/**
* Converts an array of numbers into CSS accepted format.
*
Expand All @@ -113,7 +122,6 @@ function toCSS(
cssFunction: CssFunctionType = 'rgb',
space: CssSpaceType = 'sRGB'
): string {
const percentage = (value: number) => Math.round(value * 100);
switch (cssFunction) {
case 'rgba': {
return `rgba(${values[0]}, ${values[1]}, ${values[2]}, ${values[3]})`;
Expand All @@ -124,35 +132,35 @@ function toCSS(
}

case 'cmyk': {
return `cmyk(${percentage(values[0])}%, ${percentage(
return `cmyk(${toPercentage(values[0])}%, ${toPercentage(
values[1]
)}%, ${percentage(values[2])}%, ${percentage(values[3])}%)`;
)}%, ${toPercentage(values[2])}%, ${toPercentage(values[3])}%)`;
}

case 'hsl': {
return `hsl(${values[0]}deg ${percentage(values[1])}% ${percentage(
return `hsl(${values[0]}deg ${toPercentage(values[1])}% ${toPercentage(
values[2]
)}%)`;
}

case 'hsla': {
return `hsl(${values[0]}deg ${percentage(values[1])}% ${percentage(
return `hsl(${values[0]}deg ${toPercentage(values[1])}% ${toPercentage(
values[2]
)}% / ${percentage(values[3])})`;
)}% / ${toPercentage(values[3])})`;
}

case 'hwb': {
return `hwb(${values[0]} ${percentage(values[1])}% ${percentage(
return `hwb(${values[0]} ${toPercentage(values[1])}% ${toPercentage(
values[2]
)}%)`;
}

case 'lab': {
return `lab(${percentage(values[0])}% ${values[1]} ${values[2]})`;
return `lab(${toPercentage(values[0])}% ${values[1]} ${values[2]})`;
}

case 'lch': {
return `lch(${percentage(values[0])}% ${values[1]} ${values[2]})`;
return `lch(${toPercentage(values[0])}% ${values[1]} ${values[2]})`;
}

case 'rgb': {
Expand Down
18 changes: 13 additions & 5 deletions src/modules/food/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
import { ModuleBase } from '../../internal/module-base';

/**
* Converts the given string to title case.
*
* @param text The text to convert.
*/
function toTitleCase(text: string): string {
return text
.split(' ')
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ');
}

/**
* Module for generating food-related data.
*
Expand Down Expand Up @@ -47,11 +60,6 @@ export class FoodModule extends ModuleBase {
*/
dish(): string {
// A 50/50 mix of specific dishes and dish_patterns
const toTitleCase = (s: string) =>
s
.split(' ')
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
.join(' ');
if (this.faker.datatype.boolean()) {
return toTitleCase(
this.faker.helpers.fake(this.faker.definitions.food.dish_pattern)
Expand Down
83 changes: 53 additions & 30 deletions src/modules/internet/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { FakerError } from '../../errors/faker-error';
import type { Faker } from '../../faker';
import { toBase64Url } from '../../internal/base64';
import { deprecated } from '../../internal/deprecated';
import { ModuleBase } from '../../internal/module-base';
Expand Down Expand Up @@ -102,6 +103,50 @@ const ipv4Networks: Record<IPv4Network, string> = {
[IPv4Network.Multicast]: '224.0.0.0/4',
};

/**
* Checks whether the given string is a valid slug for `domainWord`s.
*
* @param slug The slug to check.
*/
function isValidDomainWordSlug(slug: string): boolean {
return /^[a-z][a-z-]*[a-z]$/i.exec(slug) !== null;
}

/**
* Tries various ways to produce a valid domain word slug, falling back to a random string if needed.
*
* @param faker The faker instance to use.
* @param word The initial word to slugify.
*/
function makeValidDomainWordSlug(faker: Faker, word: string): string {
const slug1 = faker.helpers.slugify(word);
if (isValidDomainWordSlug(slug1)) {
return slug1;
}

const slug2 = faker.helpers.slugify(faker.lorem.word());
if (isValidDomainWordSlug(slug2)) {
return slug2;
}

return faker.string.alpha({
casing: 'lower',
length: faker.number.int({ min: 4, max: 8 }),
});
}

/**
* Generates a random color in hex format with the given base color.
*
* @param faker The faker instance to use.
* @param base The base color to use.
*/
function colorFromBase(faker: Faker, base: number): string {
return Math.floor((faker.number.int(256) + base) / 2)
.toString(16)
.padStart(2, '0');
}

/**
* Module to generate internet related entries.
*
Expand Down Expand Up @@ -597,29 +642,12 @@ export class InternetModule extends ModuleBase {
domainWord(): string {
// 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());
const word1 = makeValidDomainWordSlug(
this.faker,
this.faker.word.adjective()
);
const word2 = makeValidDomainWordSlug(this.faker, this.faker.word.noun());
return `${word1}-${word2}`.toLowerCase();
}

Expand Down Expand Up @@ -819,14 +847,9 @@ export class InternetModule extends ModuleBase {
): string {
const { redBase = 0, greenBase = 0, blueBase = 0 } = options;

const colorFromBase = (base: number): string =>
Math.floor((this.faker.number.int(256) + base) / 2)
.toString(16)
.padStart(2, '0');

const red = colorFromBase(redBase);
const green = colorFromBase(greenBase);
const blue = colorFromBase(blueBase);
const red = colorFromBase(this.faker, redBase);
const green = colorFromBase(this.faker, greenBase);
const blue = colorFromBase(this.faker, blueBase);

return `#${red}${green}${blue}`;
}
Expand Down
21 changes: 12 additions & 9 deletions src/modules/system/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,17 +263,17 @@ export class SystemModule extends ModuleBase {

let suffix: string;
let prefix = '';
const digit = () => this.faker.string.numeric({ allowLeadingZeros: true });
switch (interfaceSchema) {
case 'index': {
suffix = digit();
suffix = this.faker.string.numeric();
break;
}

case 'slot': {
suffix = `${digit()}${
this.faker.helpers.maybe(() => `f${digit()}`) ?? ''
}${this.faker.helpers.maybe(() => `d${digit()}`) ?? ''}`;
suffix = `${this.faker.string.numeric()}${
this.faker.helpers.maybe(() => `f${this.faker.string.numeric()}`) ??
''
}${this.faker.helpers.maybe(() => `d${this.faker.string.numeric()}`) ?? ''}`;
break;
}

Expand All @@ -283,10 +283,13 @@ export class SystemModule extends ModuleBase {
}

case 'pci': {
prefix = this.faker.helpers.maybe(() => `P${digit()}`) ?? '';
suffix = `${digit()}s${digit()}${
this.faker.helpers.maybe(() => `f${digit()}`) ?? ''
}${this.faker.helpers.maybe(() => `d${digit()}`) ?? ''}`;
prefix =
this.faker.helpers.maybe(() => `P${this.faker.string.numeric()}`) ??
'';
suffix = `${this.faker.string.numeric()}s${this.faker.string.numeric()}${
this.faker.helpers.maybe(() => `f${this.faker.string.numeric()}`) ??
''
}${this.faker.helpers.maybe(() => `d${this.faker.string.numeric()}`) ?? ''}`;
break;
}
}
Expand Down
26 changes: 13 additions & 13 deletions test/modules/date.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,19 @@ const converterMap = [
const NON_SEEDED_BASED_RUN = 5;
const refDate = '2021-02-21T17:09:15.711Z';

function calculateAge(birthdate: Date, refDate: Date): number {
let age = refDate.getFullYear() - birthdate.getFullYear();
if (
refDate.getMonth() < birthdate.getMonth() ||
(refDate.getMonth() === birthdate.getMonth() &&
refDate.getDate() < birthdate.getDate())
) {
age--;
}

return age;
}

describe('date', () => {
seededTests(faker, 'date', (t) => {
t.describe('anytime', (t) => {
Expand Down Expand Up @@ -530,19 +543,6 @@ describe('date', () => {
});

describe('birthdate', () => {
function calculateAge(birthdate: Date, refDate: Date): number {
let age = refDate.getFullYear() - birthdate.getFullYear();
if (
refDate.getMonth() < birthdate.getMonth() ||
(refDate.getMonth() === birthdate.getMonth() &&
refDate.getDate() < birthdate.getDate())
) {
age--;
}

return age;
}

it('returns a random birthdate', () => {
const birthdate = faker.date.birthdate();
expect(birthdate).toBeInstanceOf(Date);
Expand Down
23 changes: 12 additions & 11 deletions test/modules/git.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ const NON_SEEDED_BASED_RUN = 5;

const refDate = '2020-01-01T00:00:00.000Z';

function isValidCommitAuthor(email: string): boolean {
// `validator.isEmail()` does not support display names
// that contain unquoted characters like . output by Git so we need
// to quote the display name
const quotedEmail = email.replace(/^(.*) </, '"$1" <');
return validator.isEmail(quotedEmail, {
require_display_name: true,
});
}

describe('git', () => {
seededTests(faker, 'git', (t) => {
t.itEach('branch', 'commitMessage');
Expand Down Expand Up @@ -56,27 +66,18 @@ describe('git', () => {
expect(parts.length).toBeLessThanOrEqual(7);

expect(parts[0]).toMatch(/^commit [a-f0-9]+$/);
const isValidAuthor = (email: string) => {
// `validator.isEmail()` does not support display names
// that contain unquoted characters like . output by Git so we need
// to quote the display name
const quotedEmail = email.replace(/^(.*) </, '"$1" <');
return validator.isEmail(quotedEmail, {
require_display_name: true,
});
};

const authorRegex = /^Author: .*$/;
if (parts.length === 7) {
expect(parts[1]).toMatch(/^Merge: [a-f0-9]+ [a-f0-9]+$/);
expect(parts[2]).toMatch(authorRegex);
expect(parts[2].substring(8)).toSatisfy(isValidAuthor);
expect(parts[2].substring(8)).toSatisfy(isValidCommitAuthor);
expect(parts[3]).toMatch(/^Date: .+$/);
expect(parts[4]).toBe('');
expect(parts[5]).toMatch(/^\s{4}.+$/);
} else {
expect(parts[1]).toMatch(authorRegex);
expect(parts[1].substring(8)).toSatisfy(isValidAuthor);
expect(parts[1].substring(8)).toSatisfy(isValidCommitAuthor);
expect(parts[2]).toMatch(/^Date: .+$/);
expect(parts[3]).toBe('');
expect(parts[4]).toMatch(/^\s{4}.+$/);
Expand Down
16 changes: 8 additions & 8 deletions test/modules/number.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ import { seededTests } from '../support/seeded-runs';
import { MERSENNE_MAX_VALUE } from '../utils/mersenne-test-utils';
import { times } from './../support/times';

function isFloat(value: number): boolean {
return value % 1 !== 0;
}

function isBinary(str: string): boolean {
return [...str].every((char) => char === '0' || char === '1');
}

describe('number', () => {
seededTests(faker, 'number', (t) => {
t.describeEach(
Expand Down Expand Up @@ -259,10 +267,6 @@ describe('number', () => {
});

describe('float', () => {
function isFloat(value: number) {
return value % 1 !== 0;
}

it('should return a float between 0 and 1 (inclusive) by default', () => {
const actual = faker.number.float();

Expand Down Expand Up @@ -405,10 +409,6 @@ describe('number', () => {
});

describe('binary', () => {
function isBinary(str: string) {
return [...str].every((char) => char === '0' || char === '1');
}

it('generates single binary character when no additional argument was provided', () => {
const binary = faker.number.binary();

Expand Down
Loading

0 comments on commit 188309a

Please sign in to comment.