Skip to content

Commit 8542ef3

Browse files
authored
infra(unicorn): no-array-reduce (#2479)
1 parent 9498203 commit 8542ef3

6 files changed

Lines changed: 76 additions & 60 deletions

File tree

.eslintrc.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ module.exports = defineConfig({
5050
'unicorn/consistent-function-scoping': 'off',
5151
'unicorn/import-style': 'off',
5252
'unicorn/no-array-callback-reference': 'off',
53-
'unicorn/no-array-reduce': 'off',
5453
'unicorn/no-await-expression-member': 'off',
5554
'unicorn/no-object-as-default-parameter': 'off',
5655
'unicorn/no-useless-switch-case': 'off',

scripts/apidoc/writer.ts

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -63,20 +63,17 @@ export async function writeApiDocsModule(
6363
text: moduleName,
6464
link: `/api/${lowerModuleName}.html`,
6565
methods,
66-
diff: methods.reduce(
67-
(data, method) => ({
68-
...data,
69-
[method.name]: methodDiffHash(method),
66+
diff: {
67+
moduleHash: diffHash({
68+
name: moduleName,
69+
field: lowerModuleName,
70+
deprecated,
71+
comment,
7072
}),
71-
{
72-
moduleHash: diffHash({
73-
name: moduleName,
74-
field: lowerModuleName,
75-
deprecated,
76-
comment,
77-
}),
78-
}
79-
),
73+
...Object.fromEntries(
74+
methods.map((method) => [method.name, methodDiffHash(method)])
75+
),
76+
},
8077
};
8178
}
8279

src/internal/group-by.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* Groups the values by the key function.
3+
*
4+
* @internal
5+
*
6+
* @param values The values to group.
7+
* @param keyFunction The function to get the key from the value.
8+
*/
9+
export function groupBy<TValue>(
10+
values: ReadonlyArray<TValue>,
11+
keyFunction: (value: TValue) => string | number
12+
): Record<string, TValue[]> {
13+
const result: Record<string, TValue[]> = {};
14+
15+
for (const value of values) {
16+
const key = keyFunction(value);
17+
if (result[key] === undefined) {
18+
result[key] = [];
19+
}
20+
21+
result[key].push(value);
22+
}
23+
24+
return result;
25+
}

src/modules/word/filter-word-list-by-length.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { FakerError } from '../../errors/faker-error';
2+
import { groupBy } from '../../internal/group-by';
23

34
/**
45
* The error handling strategies for the `filterWordListByLength` function.
@@ -13,14 +14,7 @@ const STRATEGIES = {
1314
wordList: ReadonlyArray<string>,
1415
length: { min: number; max: number }
1516
): string[] => {
16-
const wordsByLength = wordList.reduce<Record<number, string[]>>(
17-
(data, word) => {
18-
(data[word.length] = data[word.length] ?? []).push(word);
19-
return data;
20-
},
21-
{}
22-
);
23-
17+
const wordsByLength = groupBy(wordList, (word) => word.length);
2418
const lengths = Object.keys(wordsByLength).map(Number);
2519
const min = Math.min(...lengths);
2620
const max = Math.max(...lengths);

test/all-functional.spec.ts

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,36 @@ const IGNORED_MODULES = new Set([
1010
'_defaultRefDate',
1111
]);
1212

13-
function isTestableModule(mod: string) {
14-
return !IGNORED_MODULES.has(mod);
13+
function getMethodNamesByModules(faker: Faker): { [module: string]: string[] } {
14+
return Object.fromEntries(
15+
Object.keys(faker)
16+
.filter(isTestableModule)
17+
.sort()
18+
.map<[string, string[]]>((moduleName) => [
19+
moduleName,
20+
getMethodNamesOf(faker[moduleName]),
21+
])
22+
.filter(([module, methods]) => {
23+
if (methods.length === 0) {
24+
console.log(`Skipping ${module} - No testable methods`);
25+
return false;
26+
}
27+
28+
return true;
29+
})
30+
);
31+
}
32+
33+
function isTestableModule(moduleName: string): moduleName is keyof Faker {
34+
return !IGNORED_MODULES.has(moduleName);
35+
}
36+
37+
function getMethodNamesOf(module: object): string[] {
38+
return Object.keys(module).filter(isMethodOf(module));
1539
}
1640

17-
function isMethodOf(mod: string) {
18-
return (meth: string) => typeof fakerEN[mod][meth] === 'function';
41+
function isMethodOf(module: object): (method: string) => boolean {
42+
return (method: string) => typeof module[method] === 'function';
1943
}
2044

2145
type SkipConfig<TModule> = Partial<
@@ -53,36 +77,17 @@ const BROKEN_LOCALE_METHODS = {
5377
};
5478

5579
function isWorkingLocaleForMethod(
56-
mod: string,
57-
meth: string,
80+
module: string,
81+
method: string,
5882
locale: string
5983
): boolean {
60-
const broken = BROKEN_LOCALE_METHODS[mod]?.[meth] ?? [];
84+
const broken = BROKEN_LOCALE_METHODS[module]?.[method] ?? [];
6185
return broken !== '*' && !broken.includes(locale);
6286
}
6387

6488
// Basic smoke tests to make sure each method is at least implemented and returns a value.
6589

66-
function modulesList(): { [module: string]: string[] } {
67-
const modules = Object.keys(fakerEN)
68-
.sort()
69-
.filter(isTestableModule)
70-
.reduce((result, mod) => {
71-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
72-
const methods = Object.keys(fakerEN[mod]).filter(isMethodOf(mod));
73-
if (methods.length > 0) {
74-
result[mod] = methods;
75-
} else {
76-
console.log(`Skipping ${mod} - No testable methods`);
77-
}
78-
79-
return result;
80-
}, {});
81-
82-
return modules;
83-
}
84-
85-
const modules = modulesList();
90+
const modules = getMethodNamesByModules(fakerEN);
8691

8792
describe('BROKEN_LOCALE_METHODS test', () => {
8893
it('should not contain obsolete configuration (modules)', () => {

test/scripts/apidoc/verify-jsdoc-tags.spec.ts

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,28 +47,24 @@ describe('verify JSDoc tags', () => {
4747
}
4848

4949
const allowedReferences = new Set(
50-
Object.values(modules).reduce<string[]>((acc, [module, methods]) => {
50+
Object.values(modules).flatMap(([module, methods]) => {
5151
const moduleFieldName = extractModuleFieldName(module);
52-
return [
53-
...acc,
54-
...Object.keys(methods).map(
55-
(methodName) => `faker.${moduleFieldName}.${methodName}`
56-
),
57-
];
58-
}, [])
52+
return Object.keys(methods).map(
53+
(methodName) => `faker.${moduleFieldName}.${methodName}`
54+
);
55+
})
5956
);
6057
const allowedLinks = new Set(
61-
Object.values(modules).reduce<string[]>((acc, [module, methods]) => {
58+
Object.values(modules).flatMap(([module, methods]) => {
6259
const moduleFieldName = extractModuleFieldName(module);
6360
return [
64-
...acc,
6561
`/api/${moduleFieldName}.html`,
6662
...Object.keys(methods).map(
6763
(methodName) =>
6864
`/api/${moduleFieldName}.html#${methodName.toLowerCase()}`
6965
),
7066
];
71-
}, [])
67+
})
7268
);
7369

7470
function assertDescription(description: string, isHtml: boolean): void {

0 commit comments

Comments
 (0)