diff --git a/test/helpers.spec.ts b/test/helpers.spec.ts index ce8fb73387e..15c26874d2f 100644 --- a/test/helpers.spec.ts +++ b/test/helpers.spec.ts @@ -2,6 +2,7 @@ import { afterEach, describe, expect, it } from 'vitest'; import { faker, FakerError } from '../src'; import { luhnCheck } from '../src/modules/helpers/luhn-check'; import { seededTests } from './support/seededRuns'; +import './vitest-extensions'; const NON_SEEDED_BASED_RUN = 5; @@ -142,7 +143,7 @@ describe('helpers', () => { }); // Check uniqueness - expect(subset).toHaveLength(new Set(subset).size); + expect(subset).not.toContainDuplicates(); }); it('should return a subset of fixed length with random elements in the array', () => { @@ -345,8 +346,8 @@ describe('helpers', () => { const input = ['a', 'a', 'a', 'a,', 'a', 'a', 'a', 'a', 'b']; const length = 2; const unique = faker.helpers.uniqueArray(input, length); + expect(unique).not.toContainDuplicates(); expect(unique).toHaveLength(length); - expect(new Set(unique).size).toBe(length); }); it('definition array returns unique array', () => { @@ -355,31 +356,30 @@ describe('helpers', () => { faker.definitions.hacker.noun, length ); + expect(unique).not.toContainDuplicates(); expect(unique).toHaveLength(length); - expect(new Set(unique).size).toBe(length); }); it('function returns unique array', () => { const length = faker.datatype.number({ min: 1, max: 6 }); const unique = faker.helpers.uniqueArray(faker.lorem.word, length); + expect(unique).not.toContainDuplicates(); expect(unique).toHaveLength(length); - expect(new Set(unique).size).toBe(length); }); it('empty array returns empty array', () => { const input = []; const length = faker.datatype.number({ min: 1, max: 6 }); const unique = faker.helpers.uniqueArray(input, length); - expect(unique).toHaveLength(input.length); - expect(new Set(unique).size).toBe(input.length); + expect(unique).toHaveLength(0); }); it('length longer than source returns max length', () => { const input = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']; const length = input.length + 1; const unique = faker.helpers.uniqueArray(input, length); + expect(unique).not.toContainDuplicates(); expect(unique).toHaveLength(input.length); - expect(new Set(unique).size).toBe(input.length); }); it('works as expected when seeded', () => { diff --git a/test/locales.spec.ts b/test/locales.spec.ts index 17115809405..9e290c5a559 100644 --- a/test/locales.spec.ts +++ b/test/locales.spec.ts @@ -2,6 +2,7 @@ import { describe, expect, it } from 'vitest'; import type { LocaleDefinition } from '../src'; import { faker } from '../src'; import allLocales from '../src/locales'; +import './vitest-extensions'; // Remark: actual use of locales functionality is currently tested in all.functional.js test @@ -32,16 +33,7 @@ describe('locale', () => { describe(definitionName, () => { function testArraySample(arr: T[]) { it('should not have duplicate entries', () => { - const uniques = new Set(arr); - const duplications = arr.filter( - (entry) => !uniques.delete(entry) - ); - const uniqueDuplication = [...new Set(duplications)]; - - expect( - uniqueDuplication, - `Duplicated values are: [${uniqueDuplication.join(', ')}]` - ).toEqual([]); + expect(arr).not.toContainDuplicates(); }); } diff --git a/test/vitest-extensions.ts b/test/vitest-extensions.ts new file mode 100644 index 00000000000..b33919efb00 --- /dev/null +++ b/test/vitest-extensions.ts @@ -0,0 +1,33 @@ +import { expect } from 'vitest'; + +expect.extend({ + toContainDuplicates(received: T[]) { + const { isNot } = this; + + const uniques = new Set(received); + const duplications = received.filter((entry) => !uniques.delete(entry)); + const uniqueDuplication = [...new Set(duplications)]; + + return { + pass: uniqueDuplication.length !== 0, + message: () => + isNot + ? `Duplicated values are [${uniqueDuplication.join(', ')}]` + : `No duplicate values in [${received.join(', ')}]`, + }; + }, +}); + +interface CustomMatchers { + toContainDuplicates(): void; +} + +declare global { + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace Vi { + // eslint-disable-next-line @typescript-eslint/no-empty-interface + interface Assertion extends CustomMatchers {} + // eslint-disable-next-line @typescript-eslint/no-empty-interface + interface AsymmetricMatchersContaining extends CustomMatchers {} + } +}