From 09e5a0d03f6b1e5764a833071d93718339f8089a Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Tue, 28 Nov 2023 14:57:07 +0100 Subject: [PATCH 1/3] infra(tsconfig): noImplicitAny --- scripts/apidoc/format.ts | 1 + scripts/apidoc/typedoc.ts | 3 +- scripts/generate-locales.ts | 21 +++---- test/all-functional.spec.ts | 11 ++-- test/faker.spec.ts | 4 +- test/locale-imports.spec.ts | 115 ++++++++++++++++++----------------- test/modules/helpers.spec.ts | 8 ++- test/modules/image.spec.ts | 2 +- test/simple-faker.spec.ts | 8 +-- tsconfig.build.json | 1 - tsconfig.json | 3 - 11 files changed, 89 insertions(+), 88 deletions(-) diff --git a/scripts/apidoc/format.ts b/scripts/apidoc/format.ts index a8f63ac0021..bf7f18c8d7c 100644 --- a/scripts/apidoc/format.ts +++ b/scripts/apidoc/format.ts @@ -1,5 +1,6 @@ import type { Options } from 'prettier'; import { format } from 'prettier'; +// @ts-expect-error: No types available. import prettierConfig from '../../.prettierrc.js'; /** diff --git a/scripts/apidoc/typedoc.ts b/scripts/apidoc/typedoc.ts index 12b474b0435..bb128f4be77 100644 --- a/scripts/apidoc/typedoc.ts +++ b/scripts/apidoc/typedoc.ts @@ -88,7 +88,8 @@ export function selectApiModules( .getChildrenByKind(ReflectionKind.Class) .filter( (module) => - faker[extractModuleFieldName(module)] != null || includeTestModules + faker[extractModuleFieldName(module) as keyof typeof faker] != null || + includeTestModules ); } diff --git a/scripts/generate-locales.ts b/scripts/generate-locales.ts index ebc06670124..9f8d5de0561 100644 --- a/scripts/generate-locales.ts +++ b/scripts/generate-locales.ts @@ -23,10 +23,8 @@ import { } from 'node:fs'; import { dirname, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; -import type { Options } from 'prettier'; -import { format } from 'prettier'; -import options from '../.prettierrc.js'; import type { LocaleDefinition, MetadataDefinition } from '../src/definitions'; +import { formatMarkdown, formatTypescript } from './apidoc/format.js'; // Constants @@ -78,9 +76,6 @@ const definitionsTypes: DefinitionType = { word: 'WordDefinition', }; -const prettierTsOptions: Options = { ...options, parser: 'typescript' }; -const prettierMdOptions: Options = { ...options, parser: 'markdown' }; - const scriptCommand = 'pnpm run generate:locales'; const autoGeneratedCommentHeader = `/* @@ -154,7 +149,7 @@ async function generateLocaleFile(locale: string): Promise { }); `; - content = await format(content, prettierTsOptions); + content = await formatTypescript(content); writeFileSync(resolve(pathLocale, `${locale}.ts`), content); } @@ -195,7 +190,7 @@ async function generateLocalesIndexFile( writeFileSync( resolve(path, 'index.ts'), - await format(content.join('\n'), prettierTsOptions) + await formatTypescript(content.join('\n')) ); } @@ -301,7 +296,7 @@ async function normalizeLocaleFile(filePath: string, definitionKey: string) { } const result = {} as T; - for (const key of Object.keys(localeData)) { + for (const key of Object.keys(localeData) as Array) { result[key] = normalizeDataRecursive(localeData[key]); } @@ -367,7 +362,7 @@ async function normalizeLocaleFile(filePath: string, definitionKey: string) { // In the long term we should probably define a whether we want those in the files at all. const newContent = fileContentPreData + JSON.stringify(localeData); - writeFileSync(filePath, await format(newContent, prettierTsOptions)); + writeFileSync(filePath, await formatTypescript(newContent)); } // Start of actual logic @@ -444,7 +439,7 @@ async function main(): Promise { } as const; `; - localeIndexContent = await format(localeIndexContent, prettierTsOptions); + localeIndexContent = await formatTypescript(localeIndexContent); writeFileSync(pathLocaleIndex, localeIndexContent); // src/locales/index.ts @@ -455,12 +450,12 @@ async function main(): Promise { ${localesIndexExports} `; - localesIndexContent = await format(localesIndexContent, prettierTsOptions); + localesIndexContent = await formatTypescript(localesIndexContent); writeFileSync(pathLocalesIndex, localesIndexContent); // docs/guide/localization.md - localizationLocales = await format(localizationLocales, prettierMdOptions); + localizationLocales = await formatMarkdown(localizationLocales); let localizationContent = readFileSync(pathDocsGuideLocalization, 'utf8'); localizationContent = localizationContent.replace( diff --git a/test/all-functional.spec.ts b/test/all-functional.spec.ts index d4b1308ac74..c647a2266af 100644 --- a/test/all-functional.spec.ts +++ b/test/all-functional.spec.ts @@ -35,11 +35,9 @@ function isTestableModule(moduleName: string): moduleName is keyof Faker { } function getMethodNamesOf(module: object): string[] { - return Object.keys(module).filter(isMethodOf(module)); -} - -function isMethodOf(module: object): (method: string) => boolean { - return (method: string) => typeof module[method] === 'function'; + return (Object.keys(module) as Array).filter( + (method) => typeof module[method] === 'function' + ); } type SkipConfig = Partial< @@ -81,6 +79,7 @@ function isWorkingLocaleForMethod( method: string, locale: string ): boolean { + // @ts-expect-error: We don't have types for the dynamic access const broken = BROKEN_LOCALE_METHODS[module]?.[method] ?? []; return broken !== '*' && !broken.includes(locale); } @@ -104,6 +103,7 @@ describe('BROKEN_LOCALE_METHODS test', () => { it('should not contain obsolete configuration (methods)', () => { const existingMethods = modules[module]; const configuredMethods = Object.keys( + // @ts-expect-error: We don't have types for the dynamic access // eslint-disable-next-line @typescript-eslint/no-unsafe-argument BROKEN_LOCALE_METHODS[module] ?? {} ); @@ -129,6 +129,7 @@ describe('functional tests', () => { const testAssertion = () => { // TODO @ST-DDT 2022-03-28: Use random seed once there are no more failures faker.seed(1); + // @ts-expect-error: We don't have types for the dynamic access const result = faker[module][meth](); if (meth === 'boolean') { diff --git a/test/faker.spec.ts b/test/faker.spec.ts index a098d89856e..99422cc0e6c 100644 --- a/test/faker.spec.ts +++ b/test/faker.spec.ts @@ -13,7 +13,9 @@ describe('faker', () => { }); it('should not log anything on startup', () => { - const spies: SpyInstance[] = Object.keys(console) + const spies: SpyInstance[] = ( + Object.keys(console) as Array + ) .filter((key) => typeof console[key] === 'function') .map((methodName) => vi.spyOn(console, methodName as keyof typeof console) diff --git a/test/locale-imports.spec.ts b/test/locale-imports.spec.ts index 999a7223437..b7ac6ca87c3 100644 --- a/test/locale-imports.spec.ts +++ b/test/locale-imports.spec.ts @@ -2,64 +2,67 @@ import { describe, expect, it } from 'vitest'; import type { Faker } from '../src'; import { allLocales } from '../src'; -describe.each(Object.keys(allLocales))('locale imports', (locale) => { - it(`should be possible to directly require('@faker-js/faker/locale/${locale}')`, () => { - // eslint-disable-next-line @typescript-eslint/no-var-requires, unicorn/prefer-module - const { faker } = require(`../dist/cjs/locale/${locale}`) as { - faker: Faker; - }; +describe.each(Object.keys(allLocales) as Array)( + 'locale imports', + (locale) => { + it(`should be possible to directly require('@faker-js/faker/locale/${locale}')`, () => { + // eslint-disable-next-line @typescript-eslint/no-var-requires, unicorn/prefer-module + const { faker } = require(`../dist/cjs/locale/${locale}`) as { + faker: Faker; + }; - expect(faker).toBeDefined(); - expect(faker.string.alpha()).toBeTypeOf('string'); - expect(faker.definitions.metadata.title).toBe( - allLocales[locale].metadata.title - ); - }); + expect(faker).toBeDefined(); + expect(faker.string.alpha()).toBeTypeOf('string'); + expect(faker.definitions.metadata.title).toBe( + allLocales[locale].metadata?.title + ); + }); - it(`should be possible to directly import('@faker-js/faker/locale/${locale}')`, async () => { - const { faker } = (await import(`../dist/esm/locale/${locale}`)) as { - faker: Faker; - }; + it(`should be possible to directly import('@faker-js/faker/locale/${locale}')`, async () => { + const { faker } = (await import(`../dist/esm/locale/${locale}`)) as { + faker: Faker; + }; - expect(faker).toBeDefined(); - expect(faker.string.alpha()).toBeTypeOf('string'); - expect(faker.definitions.metadata.title).toBe( - allLocales[locale].metadata.title - ); - }); + expect(faker).toBeDefined(); + expect(faker.string.alpha()).toBeTypeOf('string'); + expect(faker.definitions.metadata.title).toBe( + allLocales[locale].metadata?.title + ); + }); - it('should have complete metadata values', () => { - const metadata = allLocales[locale].metadata; - expect(metadata.title).toBeTypeOf('string'); - expect(metadata.code).toBeTypeOf('string'); - expect(metadata.code).toEqual(locale); - if (locale !== 'base') { - expect(metadata.language).toBeTypeOf('string'); - expect(metadata.language).toMatch(/^[a-z]{2}$/); - expect(metadata.script).toBeTypeOf('string'); - expect([ - 'Arab', - 'Armn', - 'Cyrl', - 'Deva', - 'Geor', - 'Grek', - 'Hans', - 'Hant', - 'Hebr', - 'Jpan', - 'Kore', - 'Latn', - 'Thaa', - 'Thai', - ]).toContain(metadata.script); - expect(metadata.endonym).toBeTypeOf('string'); - expect(metadata.dir).toBeTypeOf('string'); - expect(['ltr', 'rtl']).toContain(metadata.dir); - if (metadata.country) { - expect(metadata.country).toBeTypeOf('string'); - expect(metadata.country).toMatch(/^[A-Z]{2}$/); + it('should have complete metadata values', () => { + const metadata = allLocales[locale].metadata ?? {}; + expect(metadata.title).toBeTypeOf('string'); + expect(metadata.code).toBeTypeOf('string'); + expect(metadata.code).toEqual(locale); + if (locale !== 'base') { + expect(metadata.language).toBeTypeOf('string'); + expect(metadata.language).toMatch(/^[a-z]{2}$/); + expect(metadata.script).toBeTypeOf('string'); + expect([ + 'Arab', + 'Armn', + 'Cyrl', + 'Deva', + 'Geor', + 'Grek', + 'Hans', + 'Hant', + 'Hebr', + 'Jpan', + 'Kore', + 'Latn', + 'Thaa', + 'Thai', + ]).toContain(metadata.script); + expect(metadata.endonym).toBeTypeOf('string'); + expect(metadata.dir).toBeTypeOf('string'); + expect(['ltr', 'rtl']).toContain(metadata.dir); + if (metadata.country) { + expect(metadata.country).toBeTypeOf('string'); + expect(metadata.country).toMatch(/^[A-Z]{2}$/); + } } - } - }); -}); + }); + } +); diff --git a/test/modules/helpers.spec.ts b/test/modules/helpers.spec.ts index 766d06502c4..1a1db9c5ae2 100644 --- a/test/modules/helpers.spec.ts +++ b/test/modules/helpers.spec.ts @@ -1,6 +1,7 @@ import { describe, expect, it } from 'vitest'; import { faker, FakerError } from '../../src'; import { luhnCheck } from '../../src/modules/helpers/luhn-check'; +import type { RecordKey } from '../../src/modules/helpers/unique'; import { seededTests } from '../support/seeded-runs'; import { times } from './../support/times'; import './../vitest-extensions'; @@ -1295,8 +1296,9 @@ Try adjusting maxTime or maxRetries parameters for faker.helpers.unique().`) const maxTime = 49; const maxRetries = 49; const currentIterations = 0; - const exclude = []; - const compare = (obj, key) => (obj[key] === undefined ? -1 : 0); + const exclude: string[] = []; + const compare = (obj: Record, key: RecordKey) => + obj[key] === undefined ? -1 : 0; const options = { startTime, @@ -1318,7 +1320,7 @@ Try adjusting maxTime or maxRetries parameters for faker.helpers.unique().`) }); it('should be possible to pass a user-specific store', () => { - const store = {}; + const store: Record = {}; const method = () => 'with conflict: 0'; diff --git a/test/modules/image.spec.ts b/test/modules/image.spec.ts index 938799efc72..004905e7d7f 100644 --- a/test/modules/image.spec.ts +++ b/test/modules/image.spec.ts @@ -257,7 +257,7 @@ describe('image', () => { 'objects', 'people', 'technology', - ]; + ] satisfies Array; describe.each(categories)(`%s()`, (category) => { it(`should return a random ${category} image url`, () => { diff --git a/test/simple-faker.spec.ts b/test/simple-faker.spec.ts index 899bcafedfa..6a64f8563ff 100644 --- a/test/simple-faker.spec.ts +++ b/test/simple-faker.spec.ts @@ -4,11 +4,11 @@ import { SimpleFaker, simpleFaker } from '../src'; describe('simpleFaker', () => { it('should not log anything on startup', () => { - const spies: SpyInstance[] = Object.keys(console) + const spies: SpyInstance[] = ( + Object.keys(console) as Array + ) .filter((key) => typeof console[key] === 'function') - .map((methodName) => - vi.spyOn(console, methodName as keyof typeof console) - ); + .map((methodName) => vi.spyOn(console, methodName)); // eslint-disable-next-line @typescript-eslint/no-var-requires, unicorn/prefer-module -- Using import() requires types being build but the CI / TS-Check runs without them. require('..').simpleFaker; diff --git a/tsconfig.build.json b/tsconfig.build.json index aa1bfb29830..ce2dcfba1a7 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -8,7 +8,6 @@ "outDir": "dist/types", // This negates what is set in the extended tsconfig.json - "noImplicitAny": true, "skipLibCheck": false, "allowSyntheticDefaultImports": false, "resolveJsonModule": false diff --git a/tsconfig.json b/tsconfig.json index da5cd4e6926..a290fc07b56 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,9 +8,6 @@ "declaration": true, "stripInternal": true, - // We need to disable these for now, and need to tackle them in another PR - "noImplicitAny": false, - // These are configs specifically for !build and have to be reverted in the tsconfig.build.json "skipLibCheck": true, "allowSyntheticDefaultImports": true, From 9e52caa395d1e5aa3cb44148c8a2409eede4a6ba Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Thu, 30 Nov 2023 18:46:00 +0100 Subject: [PATCH 2/3] chore: apply review suggestions --- .prettierrc.d.ts | 4 ++++ scripts/apidoc/format.ts | 1 - scripts/generate-locales.ts | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 .prettierrc.d.ts diff --git a/.prettierrc.d.ts b/.prettierrc.d.ts new file mode 100644 index 00000000000..806a7063dff --- /dev/null +++ b/.prettierrc.d.ts @@ -0,0 +1,4 @@ +import type { Options } from 'prettier'; + +declare const options: Options; +export = options; diff --git a/scripts/apidoc/format.ts b/scripts/apidoc/format.ts index bf7f18c8d7c..a8f63ac0021 100644 --- a/scripts/apidoc/format.ts +++ b/scripts/apidoc/format.ts @@ -1,6 +1,5 @@ import type { Options } from 'prettier'; import { format } from 'prettier'; -// @ts-expect-error: No types available. import prettierConfig from '../../.prettierrc.js'; /** diff --git a/scripts/generate-locales.ts b/scripts/generate-locales.ts index 9f8d5de0561..a71adcb9357 100644 --- a/scripts/generate-locales.ts +++ b/scripts/generate-locales.ts @@ -24,7 +24,7 @@ import { import { dirname, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; import type { LocaleDefinition, MetadataDefinition } from '../src/definitions'; -import { formatMarkdown, formatTypescript } from './apidoc/format.js'; +import { formatMarkdown, formatTypescript } from './apidoc/format'; // Constants From 9ee8874e5ba32f6a86ade04270c5703cee567190 Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Thu, 30 Nov 2023 19:08:12 +0100 Subject: [PATCH 3/3] chore: introduce keys helper function --- scripts/generate-locales.ts | 3 +- src/internal/keys.ts | 13 ++++ test/all-functional.spec.ts | 5 +- test/faker.spec.ts | 5 +- test/locale-imports.spec.ts | 116 ++++++++++++++++++------------------ test/simple-faker.spec.ts | 5 +- 6 files changed, 78 insertions(+), 69 deletions(-) create mode 100644 src/internal/keys.ts diff --git a/scripts/generate-locales.ts b/scripts/generate-locales.ts index a71adcb9357..4228cc91b3b 100644 --- a/scripts/generate-locales.ts +++ b/scripts/generate-locales.ts @@ -24,6 +24,7 @@ import { import { dirname, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; import type { LocaleDefinition, MetadataDefinition } from '../src/definitions'; +import { keys } from '../src/internal/keys'; import { formatMarkdown, formatTypescript } from './apidoc/format'; // Constants @@ -296,7 +297,7 @@ async function normalizeLocaleFile(filePath: string, definitionKey: string) { } const result = {} as T; - for (const key of Object.keys(localeData) as Array) { + for (const key of keys(localeData)) { result[key] = normalizeDataRecursive(localeData[key]); } diff --git a/src/internal/keys.ts b/src/internal/keys.ts new file mode 100644 index 00000000000..d67d32e7d82 --- /dev/null +++ b/src/internal/keys.ts @@ -0,0 +1,13 @@ +/** + * Specialized version of `Object.keys()` which preserves the type information of the keys. + * + * Please note that the type information might be inaccurate for subtypes of the argument type + * and thus should only be used to cover the property access of the object. + * + * @internal + * + * @param obj The object to get the keys of. + */ +export function keys(obj: T): Array { + return Object.keys(obj) as Array; +} diff --git a/test/all-functional.spec.ts b/test/all-functional.spec.ts index c647a2266af..a883da7d2a4 100644 --- a/test/all-functional.spec.ts +++ b/test/all-functional.spec.ts @@ -1,6 +1,7 @@ import { describe, expect, it } from 'vitest'; import type { allLocales, Faker, RandomModule } from '../src'; import { allFakers, fakerEN } from '../src'; +import { keys } from '../src/internal/keys'; const IGNORED_MODULES = new Set([ 'rawDefinitions', @@ -35,9 +36,7 @@ function isTestableModule(moduleName: string): moduleName is keyof Faker { } function getMethodNamesOf(module: object): string[] { - return (Object.keys(module) as Array).filter( - (method) => typeof module[method] === 'function' - ); + return keys(module).filter((method) => typeof module[method] === 'function'); } type SkipConfig = Partial< diff --git a/test/faker.spec.ts b/test/faker.spec.ts index 99422cc0e6c..bf1bfafc4dc 100644 --- a/test/faker.spec.ts +++ b/test/faker.spec.ts @@ -2,6 +2,7 @@ import type { SpyInstance } from 'vitest'; import { describe, expect, it, vi } from 'vitest'; import { faker, Faker } from '../src'; import { FakerError } from '../src/errors/faker-error'; +import { keys } from '../src/internal/keys'; describe('faker', () => { it('should throw error if no locales passed', () => { @@ -13,9 +14,7 @@ describe('faker', () => { }); it('should not log anything on startup', () => { - const spies: SpyInstance[] = ( - Object.keys(console) as Array - ) + const spies: SpyInstance[] = keys(console) .filter((key) => typeof console[key] === 'function') .map((methodName) => vi.spyOn(console, methodName as keyof typeof console) diff --git a/test/locale-imports.spec.ts b/test/locale-imports.spec.ts index b7ac6ca87c3..1d7dc4751f1 100644 --- a/test/locale-imports.spec.ts +++ b/test/locale-imports.spec.ts @@ -1,68 +1,66 @@ import { describe, expect, it } from 'vitest'; import type { Faker } from '../src'; import { allLocales } from '../src'; +import { keys } from '../src/internal/keys'; -describe.each(Object.keys(allLocales) as Array)( - 'locale imports', - (locale) => { - it(`should be possible to directly require('@faker-js/faker/locale/${locale}')`, () => { - // eslint-disable-next-line @typescript-eslint/no-var-requires, unicorn/prefer-module - const { faker } = require(`../dist/cjs/locale/${locale}`) as { - faker: Faker; - }; +describe.each(keys(allLocales))('locale imports', (locale) => { + it(`should be possible to directly require('@faker-js/faker/locale/${locale}')`, () => { + // eslint-disable-next-line @typescript-eslint/no-var-requires, unicorn/prefer-module + const { faker } = require(`../dist/cjs/locale/${locale}`) as { + faker: Faker; + }; - expect(faker).toBeDefined(); - expect(faker.string.alpha()).toBeTypeOf('string'); - expect(faker.definitions.metadata.title).toBe( - allLocales[locale].metadata?.title - ); - }); + expect(faker).toBeDefined(); + expect(faker.string.alpha()).toBeTypeOf('string'); + expect(faker.definitions.metadata.title).toBe( + allLocales[locale].metadata?.title + ); + }); - it(`should be possible to directly import('@faker-js/faker/locale/${locale}')`, async () => { - const { faker } = (await import(`../dist/esm/locale/${locale}`)) as { - faker: Faker; - }; + it(`should be possible to directly import('@faker-js/faker/locale/${locale}')`, async () => { + const { faker } = (await import(`../dist/esm/locale/${locale}`)) as { + faker: Faker; + }; - expect(faker).toBeDefined(); - expect(faker.string.alpha()).toBeTypeOf('string'); - expect(faker.definitions.metadata.title).toBe( - allLocales[locale].metadata?.title - ); - }); + expect(faker).toBeDefined(); + expect(faker.string.alpha()).toBeTypeOf('string'); + expect(faker.definitions.metadata.title).toBe( + allLocales[locale].metadata?.title + ); + }); - it('should have complete metadata values', () => { - const metadata = allLocales[locale].metadata ?? {}; - expect(metadata.title).toBeTypeOf('string'); - expect(metadata.code).toBeTypeOf('string'); - expect(metadata.code).toEqual(locale); - if (locale !== 'base') { - expect(metadata.language).toBeTypeOf('string'); - expect(metadata.language).toMatch(/^[a-z]{2}$/); - expect(metadata.script).toBeTypeOf('string'); - expect([ - 'Arab', - 'Armn', - 'Cyrl', - 'Deva', - 'Geor', - 'Grek', - 'Hans', - 'Hant', - 'Hebr', - 'Jpan', - 'Kore', - 'Latn', - 'Thaa', - 'Thai', - ]).toContain(metadata.script); - expect(metadata.endonym).toBeTypeOf('string'); - expect(metadata.dir).toBeTypeOf('string'); - expect(['ltr', 'rtl']).toContain(metadata.dir); - if (metadata.country) { - expect(metadata.country).toBeTypeOf('string'); - expect(metadata.country).toMatch(/^[A-Z]{2}$/); - } + it('should have complete metadata values', () => { + const metadata = allLocales[locale].metadata ?? {}; + expect(metadata.title).toBeTypeOf('string'); + expect(metadata.code).toBeTypeOf('string'); + expect(metadata.code).toEqual(locale); + if (locale !== 'base') { + expect(metadata.language).toBeTypeOf('string'); + expect(metadata.language).toMatch(/^[a-z]{2}$/); + expect(metadata.script).toBeTypeOf('string'); + expect([ + 'Arab', + 'Armn', + 'Cyrl', + 'Deva', + 'Geor', + 'Grek', + 'Hans', + 'Hant', + 'Hebr', + 'Jpan', + 'Kore', + 'Latn', + 'Thaa', + 'Thai', + ]).toContain(metadata.script); + expect(metadata.endonym).toBeTypeOf('string'); + expect(metadata.dir).toBeTypeOf('string'); + expect(['ltr', 'rtl']).toContain(metadata.dir); + if (metadata.country) { + expect(metadata.country).toBeTypeOf('string'); + expect(metadata.country).toMatch(/^[A-Z]{2}$/); } - }); - } -); + } + }); +}); diff --git a/test/simple-faker.spec.ts b/test/simple-faker.spec.ts index 6a64f8563ff..ec1247cf474 100644 --- a/test/simple-faker.spec.ts +++ b/test/simple-faker.spec.ts @@ -1,12 +1,11 @@ import type { SpyInstance } from 'vitest'; import { describe, expect, it, vi } from 'vitest'; import { SimpleFaker, simpleFaker } from '../src'; +import { keys } from '../src/internal/keys'; describe('simpleFaker', () => { it('should not log anything on startup', () => { - const spies: SpyInstance[] = ( - Object.keys(console) as Array - ) + const spies: SpyInstance[] = keys(console) .filter((key) => typeof console[key] === 'function') .map((methodName) => vi.spyOn(console, methodName));