From 1e4f57df3620daae37a2ef2f253faadbe78a6761 Mon Sep 17 00:00:00 2001 From: Thomas Phillips Date: Tue, 10 Oct 2023 17:31:12 +1300 Subject: [PATCH] feat(internet): Add RFC 5737 testing IPv4 support --- src/modules/internet/index.ts | 23 +++++++++++++++- .../__snapshots__/internet.spec.ts.snap | 24 ++++++++++++++--- test/modules/internet.spec.ts | 27 ++++++++++++++++++- 3 files changed, 69 insertions(+), 5 deletions(-) diff --git a/src/modules/internet/index.ts b/src/modules/internet/index.ts index 6e8f822f22f..bf90f042b29 100644 --- a/src/modules/internet/index.ts +++ b/src/modules/internet/index.ts @@ -989,12 +989,33 @@ export class InternetModule { /** * Generates a random IPv4 address. * + * @param options Optional options object. + * @param options.testRange The test-net range to use. Defaults to undefined, which generates any IP address. + * * @example * faker.internet.ipv4() // '245.108.222.0' + * faker.internet.ipv4({ testRange: 1 }) // '192.0.2.32' + * faker.internet.ipv4({ testRange: 2 }) // '198.51.100.59' + * faker.internet.ipv4({ testRange: 3 }) // '203.0.113.97' * * @since 6.1.1 */ - ipv4(): string { + ipv4( + options: { + /** + * Which TEST-NET range to use + * + * @default undefined (generates any random IP address) + */ + testRange?: 1 | 2 | 3; + } = {} + ): string { + const { testRange = undefined } = options; + if (testRange) { + const ranges = ['192.0.2', '198.51.100', '203.0.113']; + return `${ranges[testRange - 1]}.${this.faker.number.int(255)}`; + } + return Array.from({ length: 4 }, () => this.faker.number.int(255)).join( '.' ); diff --git a/test/modules/__snapshots__/internet.spec.ts.snap b/test/modules/__snapshots__/internet.spec.ts.snap index c8c6d8bbc36..c9a845c75c3 100644 --- a/test/modules/__snapshots__/internet.spec.ts.snap +++ b/test/modules/__snapshots__/internet.spec.ts.snap @@ -82,7 +82,13 @@ exports[`internet > 42 > httpStatusCode > with options 1`] = `410`; exports[`internet > 42 > ip 1`] = `"203.243.46.187"`; -exports[`internet > 42 > ipv4 1`] = `"95.203.243.46"`; +exports[`internet > 42 > ipv4 > noArgs 1`] = `"95.203.243.46"`; + +exports[`internet > 42 > ipv4 > with test-net range 1 1`] = `"192.0.2.95"`; + +exports[`internet > 42 > ipv4 > with test-net range 2 1`] = `"198.51.100.95"`; + +exports[`internet > 42 > ipv4 > with test-net range 3 1`] = `"203.0.113.95"`; exports[`internet > 42 > ipv6 1`] = `"8be4:abdd:3932:1ad7:d3fe:01ff:ce40:4f4d"`; @@ -224,7 +230,13 @@ exports[`internet > 1211 > httpStatusCode > with options 1`] = `429`; exports[`internet > 1211 > ip 1`] = `"adb4:2f0e:3f4a:973f:ab0a:eefc:e96d:fcf4"`; -exports[`internet > 1211 > ipv4 1`] = `"237.117.228.199"`; +exports[`internet > 1211 > ipv4 > noArgs 1`] = `"237.117.228.199"`; + +exports[`internet > 1211 > ipv4 > with test-net range 1 1`] = `"192.0.2.237"`; + +exports[`internet > 1211 > ipv4 > with test-net range 2 1`] = `"198.51.100.237"`; + +exports[`internet > 1211 > ipv4 > with test-net range 3 1`] = `"203.0.113.237"`; exports[`internet > 1211 > ipv6 1`] = `"eadb:42f0:e3f4:a973:fab0:aeef:ce96:dfcf"`; @@ -366,7 +378,13 @@ exports[`internet > 1337 > httpStatusCode > with options 1`] = `407`; exports[`internet > 1337 > ip 1`] = `"143.40.54.71"`; -exports[`internet > 1337 > ipv4 1`] = `"67.143.40.54"`; +exports[`internet > 1337 > ipv4 > noArgs 1`] = `"67.143.40.54"`; + +exports[`internet > 1337 > ipv4 > with test-net range 1 1`] = `"192.0.2.67"`; + +exports[`internet > 1337 > ipv4 > with test-net range 2 1`] = `"198.51.100.67"`; + +exports[`internet > 1337 > ipv4 > with test-net range 3 1`] = `"203.0.113.67"`; exports[`internet > 1337 > ipv6 1`] = `"5c34:6ba0:75bd:57f5:a62b:82d7:2af3:9cbb"`; diff --git a/test/modules/internet.spec.ts b/test/modules/internet.spec.ts index 79d329de3ea..3499f55b9ef 100644 --- a/test/modules/internet.spec.ts +++ b/test/modules/internet.spec.ts @@ -16,7 +16,6 @@ describe('internet', () => { 'domainSuffix', 'domainWord', 'ip', - 'ipv4', 'ipv6', 'port', 'userAgent' @@ -154,6 +153,13 @@ describe('internet', () => { protocol: 'http', }); }); + + t.describe('ipv4', (t) => { + t.it('noArgs') + .it('with test-net range 1', { testRange: 1 }) + .it('with test-net range 2', { testRange: 2 }) + .it('with test-net range 3', { testRange: 3 }); + }); }); describe.each(times(NON_SEEDED_BASED_RUN).map(() => faker.seed()))( @@ -614,6 +620,25 @@ describe('internet', () => { expect(+part).toBeLessThanOrEqual(255); } }); + it.each([1, 2, 3])( + 'should return a random testing-safe IPv4 with four parts, from the specified test-net range', + (range) => { + const ip = faker.internet.ipv4({ testRange: range as 1 | 2 | 3 }); + const ranges = ['192.0.2', '198.51.100', '203.0.113']; + + expect(ip).toBeTruthy(); + expect(ip).toBeTypeOf('string'); + expect(ip).toSatisfy((value: string) => validator.isIP(value, 4)); + + const parts = ip.split('.'); + + expect(parts).toHaveLength(4); + expect(parts.slice(0, 3).join('.')).toBe(ranges[range - 1]); + expect(parts[3]).toMatch(/^\d+$/); + expect(+parts[3]).toBeGreaterThanOrEqual(0); + expect(+parts[3]).toBeLessThanOrEqual(255); + } + ); }); describe('ipv6()', () => {