diff options
Diffstat (limited to 'test/modules')
| -rw-r--r-- | test/modules/__snapshots__/person.spec.ts.snap | 2 | ||||
| -rw-r--r-- | test/modules/helpers-eval.spec.ts | 162 | ||||
| -rw-r--r-- | test/modules/helpers.spec.ts | 37 |
3 files changed, 182 insertions, 19 deletions
diff --git a/test/modules/__snapshots__/person.spec.ts.snap b/test/modules/__snapshots__/person.spec.ts.snap index 6f3e0963..a85f4ccb 100644 --- a/test/modules/__snapshots__/person.spec.ts.snap +++ b/test/modules/__snapshots__/person.spec.ts.snap @@ -50,7 +50,7 @@ exports[`person > 42 > suffix > with sex 1`] = `"III"`; exports[`person > 42 > zodiacSign 1`] = `"Gemini"`; -exports[`person > 1211 > bio 1`] = `"infrastructure supporter, photographer 🙆♀️"`; +exports[`person > 1211 > bio 1`] = `"teletype lover, dreamer 👄"`; exports[`person > 1211 > firstName > noArgs 1`] = `"Tito"`; diff --git a/test/modules/helpers-eval.spec.ts b/test/modules/helpers-eval.spec.ts new file mode 100644 index 00000000..40612c37 --- /dev/null +++ b/test/modules/helpers-eval.spec.ts @@ -0,0 +1,162 @@ +import { describe, expect, it, vi } from 'vitest'; +import { faker, FakerError } from '../../src'; +import { fakeEval } from '../../src/modules/helpers/eval'; + +describe('fakeEval()', () => { + it('does not allow empty string input', () => { + expect(() => fakeEval('', faker)).toThrowError( + new FakerError('Eval expression cannot be empty.') + ); + }); + + it('does not allow empty entrypoints', () => { + expect(() => fakeEval('foobar', faker, [])).toThrowError( + new FakerError('Eval entrypoints cannot be empty.') + ); + }); + + it('supports single pattern part invocations', () => { + const actual = fakeEval('string', faker); + expect(actual).toBeTypeOf('object'); + expect(actual).toBe(faker.string); + }); + + it('supports simple method calls', () => { + const spy = vi.spyOn(faker.string, 'numeric'); + const actual = fakeEval('string.numeric', faker); + expect(spy).toHaveBeenCalledWith(); + expect(actual).toBeTypeOf('string'); + expect(actual).toMatch(/^\d$/); + }); + + it('supports method calls without arguments', () => { + const spy = vi.spyOn(faker.string, 'numeric'); + const actual = fakeEval('string.numeric()', faker); + expect(spy).toHaveBeenCalledWith(); + expect(actual).toBeTypeOf('string'); + expect(actual).toMatch(/^\d$/); + }); + + it('supports method calls with simple arguments', () => { + const spy = vi.spyOn(faker.string, 'numeric'); + const actual = fakeEval('string.numeric(5)', faker); + expect(spy).toHaveBeenCalledWith(5); + expect(actual).toBeTypeOf('string'); + expect(actual).toMatch(/^\d{5}$/); + }); + + it('supports method calls with complex arguments', () => { + const spy = vi.spyOn(faker.string, 'numeric'); + const actual = fakeEval( + 'string.numeric({ "length": 5, "allowLeadingZeros": true, "exclude": ["5"] })', + faker + ); + expect(spy).toHaveBeenCalledWith({ + length: 5, + allowLeadingZeros: true, + exclude: ['5'], + }); + expect(actual).toBeTypeOf('string'); + expect(actual).toMatch(/^[0-46-9]{5}$/); + }); + + it('supports method calls with multiple arguments', () => { + const spy = vi.spyOn(faker.helpers, 'mustache'); + const actual = fakeEval( + 'helpers.mustache("{{foo}}", { "foo": "bar" })', + faker + ); + expect(spy).toHaveBeenCalledWith('{{foo}}', { foo: 'bar' }); + expect(actual).toBeTypeOf('string'); + expect(actual).toBe('bar'); + }); + + it('supports method calls with unquoted string argument', () => { + const spy = vi.spyOn(faker.helpers, 'slugify'); + const actual = fakeEval('helpers.slugify(This Works)', faker); + expect(spy).toHaveBeenCalledWith('This Works'); + expect(actual).toBeTypeOf('string'); + expect(actual).toBe('This-Works'); + }); + + it('supports method calls with wrongly quoted argument', () => { + const spy = vi.spyOn(faker.helpers, 'slugify'); + const actual = fakeEval("helpers.slugify('')", faker); + expect(spy).toHaveBeenCalledWith("''"); + expect(actual).toBeTypeOf('string'); + expect(actual).toBe(''); + }); + + it('should be able to return empty strings', () => { + const actual = fakeEval('string.alphanumeric(0)', faker); + expect(actual).toBeTypeOf('string'); + expect(actual).toBe(''); + }); + + it('supports returning complex objects', () => { + const actual = fakeEval('airline.airline', faker); + expect(actual).toBeTypeOf('object'); + expect(faker.definitions.airline.airline).toContain(actual); + }); + + it('supports patterns after a function call', () => { + const actual = fakeEval('airline.airline().name', faker); + expect(actual).toBeTypeOf('string'); + expect(faker.definitions.airline.airline.map(({ name }) => name)).toContain( + actual + ); // function().name + }); + + it('supports patterns after a function reference', () => { + const actual = fakeEval('airline.airline.iataCode', faker); + expect(actual).toBeTypeOf('string'); + expect( + faker.definitions.airline.airline.map(({ iataCode }) => iataCode) + ).toContain(actual); + }); + + it('requires a dot after a function call', () => { + expect(() => fakeEval('airline.airline()iataCode', faker)).toThrowError( + new FakerError( + "Expected dot ('.'), open parenthesis ('('), or nothing after function call but got 'i'" + ) + ); + }); + + it('requires a function for parameters', () => { + // TODO @ST-DDT 2023-12-11: Replace in v9 + // expect(faker.definitions.person.first_name).toBeDefined(); + //expect(() => fakeEval('person.first_name()', faker)).toThrow( + // new FakerError(`Cannot resolve expression 'person.first_name'`) + // ); + const actual = fakeEval('person.first_name()', faker); + expect(faker.definitions.person.first_name).toContain(actual); + }); + + it('requires a valid expression (missing value)', () => { + expect(() => fakeEval('foo.bar', faker)).toThrow( + new FakerError(`Cannot resolve expression 'foo.bar'`) + ); + }); + + it('requires a valid expression (trailing dot)', () => { + expect(() => fakeEval('airline.airline.', faker)).toThrowError( + new FakerError("Found dot without property name in 'airline.'") + ); + expect(() => fakeEval('airline.airline.()', faker)).toThrowError( + new FakerError("Found dot without property name in 'airline.()'") + ); + expect(() => fakeEval('airline.airline.().iataCode', faker)).toThrowError( + new FakerError("Found dot without property name in 'airline.().iataCode'") + ); + }); + + it('requires a valid expression (unclosed parenthesis)', () => { + expect(() => fakeEval('airline.airline(', faker)).toThrowError( + new FakerError("Missing closing parenthesis in '('") + ); + expect(() => fakeEval('airline.airline(.iataCode', faker)).toThrowError( + new FakerError("Missing closing parenthesis in '(.iataCode'") + ); + }); +}); diff --git a/test/modules/helpers.spec.ts b/test/modules/helpers.spec.ts index 1a1db9c5..1b9ba3ae 100644 --- a/test/modules/helpers.spec.ts +++ b/test/modules/helpers.spec.ts @@ -1027,34 +1027,35 @@ describe('helpers', () => { it('does not allow invalid module name', () => { expect(() => faker.helpers.fake('{{foo.bar}}')).toThrow( - new FakerError(`Invalid module method or definition: foo.bar -- faker.foo.bar is not a function -- faker.definitions.foo.bar is not an array`) + new FakerError(`Cannot resolve expression 'foo.bar'`) ); }); - it('does not allow missing method name', () => { - expect(() => faker.helpers.fake('{{location}}')).toThrow( - new FakerError(`Invalid module method or definition: location -- faker.location is not a function -- faker.definitions.location is not an array`) - ); + it('does allow missing method name', () => { + const actual = faker.helpers.fake('{{location}}'); + expect(actual).toBe('[object Object]'); }); it('does not allow invalid method name', () => { expect(() => faker.helpers.fake('{{location.foo}}')).toThrow( - new FakerError(`Invalid module method or definition: location.foo -- faker.location.foo is not a function -- faker.definitions.location.foo is not an array`) + new FakerError(`Cannot resolve expression 'location.foo'`) ); }); - it('does not allow invalid definitions data', () => { - expect(() => faker.helpers.fake('{{finance.credit_card}}')).toThrow( - new FakerError(`Invalid module method or definition: finance.credit_card -- faker.finance.credit_card is not a function -- faker.definitions.finance.credit_card is not an array`) - ); + it('should support complex data', () => { + const actual = faker.helpers.fake('{{science.unit}}'); + expect(actual).toBe('[object Object]'); + }); + + it('should support resolving a value in a complex object', () => { + const complex = faker.helpers.fake('{{airline.airline}}'); + expect(complex).toBe('[object Object]'); + + const actual = faker.helpers.fake('{{airline.airline.iataCode}}'); + expect(actual).toBeTypeOf('string'); + expect( + faker.definitions.airline.airline.map(({ iataCode }) => iataCode) + ).toContain(actual); }); it('should be able to return empty strings', () => { |
