diff options
| author | Shinigami <[email protected]> | 2022-01-21 22:29:24 +0100 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-01-21 22:29:24 +0100 |
| commit | 60c90028ba76b7e291fdb8152425b93c41b117c9 (patch) | |
| tree | cfaf146a883f902acc351c7c2cba095c459ec36f /test | |
| parent | 2da0cec2f91f54f56b509414a8b29b3831d58412 (diff) | |
| download | faker-60c90028ba76b7e291fdb8152425b93c41b117c9.tar.xz faker-60c90028ba76b7e291fdb8152425b93c41b117c9.zip | |
chore(test): migrate to vitest (#235)
Diffstat (limited to 'test')
59 files changed, 4550 insertions, 12468 deletions
diff --git a/test/address.spec.ts b/test/address.spec.ts new file mode 100644 index 00000000..7b615926 --- /dev/null +++ b/test/address.spec.ts @@ -0,0 +1,782 @@ +import type { JestMockCompat } from 'vitest'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { faker } from '../lib'; + +describe('address', () => { + describe('city()', () => { + let spy_address_cityPrefix: JestMockCompat<[], string>; + let spy_name_firstName: JestMockCompat<[gender?: string | number], string>; + let spy_name_lastName: JestMockCompat<[gender?: string | number], string>; + let spy_address_citySuffix: JestMockCompat<[], string>; + + beforeEach(() => { + spy_address_cityPrefix = vi.spyOn(faker.address, 'cityPrefix'); + spy_name_firstName = vi.spyOn(faker.name, 'firstName'); + spy_name_lastName = vi.spyOn(faker.name, 'lastName'); + spy_address_citySuffix = vi.spyOn(faker.address, 'citySuffix'); + }); + + afterEach(() => { + // faker.datatype.number.restore(); + spy_address_cityPrefix.mockRestore(); + spy_name_firstName.mockRestore(); + spy_name_lastName.mockRestore(); + spy_address_citySuffix.mockRestore(); + }); + + it('occasionally returns prefix + first name + suffix', () => { + const spy_datatype_number = vi + .spyOn(faker.datatype, 'number') + .mockImplementation(() => 0); + + const city = faker.address.city(); + expect(city).toBeTruthy(); + + expect(spy_address_cityPrefix).toHaveBeenCalledOnce(); + expect(spy_name_firstName).toHaveBeenCalledOnce(); + expect(spy_address_citySuffix).toHaveBeenCalledOnce(); + + spy_datatype_number.mockRestore(); + }); + + it('occasionally returns prefix + first name', () => { + const spy_datatype_number = vi + .spyOn(faker.datatype, 'number') + .mockImplementation(() => 1); + + const city = faker.address.city(); + expect(city).toBeTruthy(); + + expect(spy_address_cityPrefix).toHaveBeenCalledOnce(); + expect(spy_name_firstName).toHaveBeenCalledOnce(); + + spy_datatype_number.mockRestore(); + }); + + it('occasionally returns first name + suffix', () => { + const spy_datatype_number = vi + .spyOn(faker.datatype, 'number') + .mockImplementation(() => 2); + + const city = faker.address.city(); + expect(city).toBeTruthy(); + + expect(spy_address_citySuffix).toHaveBeenCalledOnce(); + + spy_datatype_number.mockRestore(); + }); + + it('occasionally returns last name + suffix', () => { + const spy_datatype_number = vi + .spyOn(faker.datatype, 'number') + .mockImplementation(() => 3); + + const city = faker.address.city(); + expect(city).toBeTruthy(); + + expect(spy_address_cityPrefix).not.toHaveBeenCalled(); + expect(spy_name_firstName).not.toHaveBeenCalled(); + expect(spy_name_lastName).toHaveBeenCalled(); + expect(spy_address_citySuffix).toHaveBeenCalled(); + + spy_datatype_number.mockRestore(); + }); + }); + + describe('streetName()', () => { + let spy_name_firstName: JestMockCompat<[gender?: string | number], string>; + let spy_name_lastName: JestMockCompat<[gender?: string | number], string>; + let spy_address_streetSuffix: JestMockCompat<[], string>; + + beforeEach(() => { + spy_name_firstName = vi.spyOn(faker.name, 'firstName'); + spy_name_lastName = vi.spyOn(faker.name, 'lastName'); + spy_address_streetSuffix = vi.spyOn(faker.address, 'streetSuffix'); + }); + + afterEach(() => { + spy_name_firstName.mockRestore(); + spy_name_lastName.mockRestore(); + spy_address_streetSuffix.mockRestore(); + }); + + it('occasionally returns last name + suffix', () => { + const spy_datatype_number = vi + .spyOn(faker.datatype, 'number') + .mockImplementation(() => 0); + + const street_name = faker.address.streetName(); + expect(street_name).toBeTruthy(); + + expect(spy_name_firstName).not.toHaveBeenCalled(); + expect(spy_name_lastName).toHaveBeenCalledOnce(); + expect(spy_address_streetSuffix).toHaveBeenCalledOnce(); + + spy_datatype_number.mockRestore(); + }); + + it('occasionally returns first name + suffix', () => { + const spy_datatype_number = vi + .spyOn(faker.datatype, 'number') + .mockImplementation(() => 1); + + const street_name = faker.address.streetName(); + expect(street_name).toBeTruthy(); + + expect(spy_name_firstName).toHaveBeenCalledOnce(); + expect(spy_name_lastName).not.toHaveBeenCalled(); + expect(spy_address_streetSuffix).toHaveBeenCalledOnce(); + + spy_datatype_number.mockRestore(); + }); + + it('trims trailing whitespace from the name', () => { + spy_address_streetSuffix.mockRestore(); + + spy_address_streetSuffix.mockImplementation(() => ''); + + const street_name = faker.address.streetName(); + expect(street_name).not.match(/ $/); + + spy_address_streetSuffix.mockRestore(); + }); + }); + + describe('streetAddress()', () => { + const errorExpectDigits = (expected) => { + return 'The street number should be had ' + expected + ' digits'; + }; + + let spy_address_streetName: JestMockCompat<[], string>; + let spy_address_secondaryAddress: JestMockCompat<[], string>; + + beforeEach(() => { + spy_address_streetName = vi.spyOn(faker.address, 'streetName'); + spy_address_secondaryAddress = vi.spyOn( + faker.address, + 'secondaryAddress' + ); + }); + + afterEach(() => { + spy_address_streetName.mockRestore(); + spy_address_secondaryAddress.mockRestore(); + }); + + it('occasionally returns a 5-digit street number', () => { + const spy_datatype_number = vi + .spyOn(faker.datatype, 'number') + .mockImplementation(() => 0); + + const address = faker.address.streetAddress(); + const expected = 5; + const parts = address.split(' '); + + expect(parts[0].length, errorExpectDigits(expected)).toBe(expected); + expect(spy_address_streetName).toHaveBeenCalled(); + + spy_datatype_number.mockRestore(); + }); + + it('occasionally returns a 4-digit street number', () => { + const spy_datatype_number = vi + .spyOn(faker.datatype, 'number') + .mockImplementation(() => 1); + + const address = faker.address.streetAddress(); + const parts = address.split(' '); + const expected = 4; + + expect(parts[0].length, errorExpectDigits(expected)).toBe(expected); + expect(spy_address_streetName).toHaveBeenCalled(); + + spy_datatype_number.mockRestore(); + }); + + it('occasionally returns a 3-digit street number', () => { + const spy_datatype_number = vi + .spyOn(faker.datatype, 'number') + .mockImplementation(() => 2); + + const address = faker.address.streetAddress(); + const parts = address.split(' '); + const expected = 3; + + expect(parts[0].length, errorExpectDigits(expected)).toBe(expected); + expect(spy_address_streetName).toHaveBeenCalled(); + expect(spy_address_secondaryAddress).not.toHaveBeenCalled(); + + spy_datatype_number.mockRestore(); + }); + + describe('when useFulladdress is true', () => { + it('adds a secondary address to the result', () => { + faker.address.streetAddress(true); + + expect(spy_address_secondaryAddress).toHaveBeenCalled(); + }); + }); + }); + + describe('secondaryAddress()', () => { + it('randomly chooses an Apt or Suite number', () => { + const spy_random_arrayElement = vi.spyOn(faker.random, 'arrayElement'); + + const address = faker.address.secondaryAddress(); + + const expected_array = ['Apt. ###', 'Suite ###']; + + expect(address).toBeTruthy(); + expect(spy_random_arrayElement).toHaveBeenCalledWith(expected_array); + }); + }); + + describe('county()', () => { + it('returns random county', () => { + const spy_address_county = vi.spyOn(faker.address, 'county'); + + const county = faker.address.county(); + + expect(county).toBeTruthy(); + expect(spy_address_county).toHaveBeenCalled(); + }); + }); + + describe('country()', () => { + it('returns random country', () => { + const spy_address_country = vi.spyOn(faker.address, 'country'); + + const country = faker.address.country(); + + expect(country).toBeTruthy(); + expect(spy_address_country).toHaveBeenCalled(); + }); + }); + + describe('countryCode()', () => { + it('returns random countryCode', () => { + const spy_address_countryCode = vi.spyOn(faker.address, 'countryCode'); + + const countryCode = faker.address.countryCode(); + + expect(countryCode).toBeTruthy(); + expect(spy_address_countryCode).toHaveBeenCalled(); + }); + + it('returns random alpha-3 countryCode', () => { + const spy_address_countryCode = vi.spyOn(faker.address, 'countryCode'); + + const countryCode = faker.address.countryCode('alpha-3'); + + expect(countryCode).toBeTruthy(); + expect(spy_address_countryCode).toHaveBeenCalled(); + expect( + countryCode.length, + 'The countryCode should be had 3 characters' + ).toBe(3); + }); + }); + + describe('state()', () => { + it('returns random state', () => { + const spy_address_state = vi.spyOn(faker.address, 'state'); + + const state = faker.address.state(); + + expect(state).toBeTruthy(); + expect(spy_address_state).toHaveBeenCalled(); + }); + }); + + describe('zipCode()', () => { + it('returns random zipCode', () => { + const spy_address_zipCode = vi.spyOn(faker.address, 'zipCode'); + + const zipCode = faker.address.zipCode(); + + expect(zipCode).toBeTruthy(); + expect(spy_address_zipCode).toHaveBeenCalled(); + }); + + it('returns random zipCode - user specified format', () => { + let zipCode = faker.address.zipCode('?#? #?#'); + + expect(zipCode).match(/^[A-Za-z]\d[A-Za-z]\s\d[A-Za-z]\d$/); + + // try another format + zipCode = faker.address.zipCode('###-###'); + + expect(zipCode).match(/^\d{3}-\d{3}$/); + }); + + it('returns zipCode with proper locale format', () => { + // we'll use the en_CA locale.. + faker.locale = 'en_CA'; + const zipCode = faker.address.zipCode(); + + expect(zipCode).match(/^[A-Za-z]\d[A-Za-z]\s?\d[A-Za-z]\d$/); + }); + }); + + describe('zipCodeByState()', () => { + it('returns zipCode valid for specified State', () => { + faker.locale = 'en_US'; + const states = ['IL', 'GA', 'WA']; + + const zipCode1 = faker.address.zipCodeByState(states[0]); + expect(zipCode1).greaterThanOrEqual(60001); + expect(zipCode1).lessThanOrEqual(62999); + + const zipCode2 = faker.address.zipCodeByState(states[1]); + expect(zipCode2).greaterThanOrEqual(30001); + expect(zipCode2).lessThanOrEqual(31999); + + const zipCode3 = faker.address.zipCodeByState(states[2]); + expect(zipCode3).greaterThanOrEqual(98001); + expect(zipCode3).lessThanOrEqual(99403); + }); + + it('returns undefined if state is invalid', () => { + const state = 'XX'; + const spy_address_zipCode = vi.spyOn(faker.address, 'zipCode'); + + faker.address.zipCodeByState(state); + expect(spy_address_zipCode).toHaveBeenCalled(); + + spy_address_zipCode.mockRestore(); + }); + + it('returns undefined if state is valid but localeis invalid', () => { + faker.locale = 'zh_CN'; + const state = 'IL'; + + const spy_address_zipCode = vi.spyOn(faker.address, 'zipCode'); + + faker.address.zipCodeByState(state); + expect(spy_address_zipCode).toHaveBeenCalled(); + + spy_address_zipCode.mockRestore(); + }); + }); + + describe('latitude()', () => { + it('returns random latitude', () => { + const spy_datatype_number = vi.spyOn(faker.datatype, 'number'); + + for (let i = 0; i < 100; i++) { + const latitude = faker.address.latitude(); + + expect(typeof latitude).toBe('string'); + + const latitude_float = parseFloat(latitude); + + expect(latitude_float).greaterThanOrEqual(-90.0); + expect(latitude_float).lessThanOrEqual(90.0); + expect(spy_datatype_number).toHaveBeenCalled(); + + spy_datatype_number.mockRestore(); + } + }); + + it('returns latitude with min and max and default precision', () => { + const spy_datatype_number = vi.spyOn(faker.datatype, 'number'); + + for (let i = 0; i < 100; i++) { + const latitude = faker.address.latitude(-5, 5); + + expect(typeof latitude).toBe('string'); + expect( + latitude.split('.')[1].length, + 'The precision of latitude should be had of 4 digits' + ).toBe(4); + + const latitude_float = parseFloat(latitude); + + expect(latitude_float).greaterThanOrEqual(-5); + expect(latitude_float).lessThanOrEqual(5); + expect(spy_datatype_number).toHaveBeenCalled(); + + spy_datatype_number.mockRestore(); + } + }); + + it('returns random latitude with custom precision', () => { + const spy_datatype_number = vi.spyOn(faker.datatype, 'number'); + + for (let i = 0; i < 100; i++) { + const latitude = faker.address.latitude(undefined, undefined, 7); + + expect(typeof latitude).toBe('string'); + expect( + latitude.split('.')[1].length, + 'The precision of latitude should be had of 7 digits' + ).toBe(7); + + const latitude_float = parseFloat(latitude); + + expect(latitude_float).greaterThanOrEqual(-180); + expect(latitude_float).lessThanOrEqual(180); + expect(spy_datatype_number).toHaveBeenCalled(); + + spy_datatype_number.mockRestore(); + } + }); + }); + + describe('longitude()', () => { + it('returns random longitude', () => { + const spy_datatype_number = vi.spyOn(faker.datatype, 'number'); + + for (let i = 0; i < 100; i++) { + const longitude = faker.address.longitude(); + + expect(typeof longitude).toBe('string'); + + const longitude_float = parseFloat(longitude); + + expect(longitude_float).greaterThanOrEqual(-180); + expect(longitude_float).lessThanOrEqual(180); + expect(spy_datatype_number).toHaveBeenCalled(); + + spy_datatype_number.mockRestore(); + } + }); + + it('returns random longitude with min and max and default precision', () => { + const spy_datatype_number = vi.spyOn(faker.datatype, 'number'); + + for (let i = 0; i < 100; i++) { + const longitude = faker.address.longitude(100, -30); + + expect(typeof longitude).toBe('string'); + expect( + longitude.split('.')[1].length, + 'The precision of longitude should be had of 4 digits' + ).toBe(4); + + const longitude_float = parseFloat(longitude); + + expect(longitude_float).greaterThanOrEqual(-30); + expect(longitude_float).lessThanOrEqual(100); + expect(spy_datatype_number).toHaveBeenCalled(); + + spy_datatype_number.mockRestore(); + } + }); + + it('returns random longitude with custom precision', () => { + const spy_datatype_number = vi.spyOn(faker.datatype, 'number'); + + for (let i = 0; i < 100; i++) { + const longitude = faker.address.longitude(undefined, undefined, 7); + + expect(typeof longitude).toBe('string'); + expect( + longitude.split('.')[1].length, + 'The precision of longitude should be had of 7 digits' + ).toBe(7); + + const longitude_float = parseFloat(longitude); + + expect(longitude_float).greaterThanOrEqual(-180); + expect(longitude_float).lessThanOrEqual(180); + expect(spy_datatype_number).toHaveBeenCalled(); + + spy_datatype_number.mockRestore(); + } + }); + }); + + describe('direction()', () => { + it('returns random direction', () => { + // TODO @Shinigami92 2022-01-20: This test does nothing and should be rewritten + const spy_address_direction = vi + .spyOn(faker.address, 'direction') + .mockReturnValue('North'); + + const direction = faker.address.direction(); + const expected = 'North'; + + expect( + direction, + 'The random direction should be equals ' + expected + ).toBe(expected); + + spy_address_direction.mockRestore(); + }); + + it('returns abbreviation when useAbbr is false', () => { + // TODO @Shinigami92 2022-01-20: This test does nothing and should be rewritten + const spy_address_direction = vi + .spyOn(faker.address, 'direction') + .mockReturnValue('N'); + + const direction = faker.address.direction(false); + const expected = 'N'; + + expect( + direction, + 'The abbreviation of direction when useAbbr is false should be equals ' + + expected + + '. Current is ' + + direction + ).toBe(expected); + + spy_address_direction.mockRestore(); + }); + + it('returns abbreviation when useAbbr is true', () => { + const direction = faker.address.direction(true); + const expectedType = 'string'; + const lengthDirection = direction.length; + const prefixErrorMessage = + 'The abbreviation of direction when useAbbr is true should'; + + expect( + typeof direction, + prefixErrorMessage + ' be typeof string. Current is' + typeof direction + ).toBe(expectedType); + expect( + lengthDirection <= 2, + prefixErrorMessage + + ' have a length less or equals 2. Current is ' + + lengthDirection + ).toBe(true); + }); + + it('returns abbreviation when useAbbr is true', () => { + const spy_address_direction = vi + .spyOn(faker.address, 'direction') + .mockReturnValue('N'); + + const direction = faker.address.direction(true); + const expected = 'N'; + + expect( + direction, + 'The abbreviation of direction when useAbbr is true should be equals ' + + expected + + '. Current is ' + + direction + ).toBe(expected); + + spy_address_direction.mockRestore(); + }); + }); + + describe('ordinalDirection()', () => { + it('returns random ordinal direction', () => { + const spy_address_ordinalDirection = vi + .spyOn(faker.address, 'ordinalDirection') + .mockReturnValue('West'); + + const ordinalDirection = faker.address.ordinalDirection(); + const expected = 'West'; + + expect( + ordinalDirection, + 'The ransom ordinal direction should be equals ' + + expected + + '. Current is ' + + ordinalDirection + ).toBe(expected); + + spy_address_ordinalDirection.mockRestore(); + }); + + it('returns abbreviation when useAbbr is true', () => { + const spy_address_ordinalDirection = vi + .spyOn(faker.address, 'ordinalDirection') + .mockReturnValue('W'); + + const ordinalDirection = faker.address.ordinalDirection(true); + const expected = 'W'; + + expect( + ordinalDirection, + 'The ordinal direction when useAbbr is true should be equals ' + + expected + + '. Current is ' + + ordinalDirection + ).toBe(expected); + + spy_address_ordinalDirection.mockRestore(); + }); + + it('returns abbreviation when useAbbr is true', () => { + const ordinalDirection = faker.address.ordinalDirection(true); + const expectedType = 'string'; + const ordinalDirectionLength = ordinalDirection.length; + const prefixErrorMessage = + 'The ordinal direction when useAbbr is true should'; + + expect( + typeof ordinalDirection, + prefixErrorMessage + + ' be had typeof equals ' + + expectedType + + '.Current is ' + + typeof ordinalDirection + ).toBe(expectedType); + expect( + ordinalDirectionLength <= 2, + prefixErrorMessage + + ' have a length less or equals 2. Current is ' + + ordinalDirectionLength + ).toBe(true); + }); + }); + + describe('cardinalDirection()', () => { + it('returns random cardinal direction', () => { + const spy_address_cardinalDirection = vi + .spyOn(faker.address, 'cardinalDirection') + .mockReturnValue('Northwest'); + + const cardinalDirection = faker.address.cardinalDirection(); + const expected = 'Northwest'; + + expect( + cardinalDirection, + 'The random cardinal direction should be equals ' + + expected + + '. Current is ' + + cardinalDirection + ).toBe(expected); + + spy_address_cardinalDirection.mockRestore(); + }); + + it('returns abbreviation when useAbbr is true', () => { + const spy_address_cardinalDirection = vi + .spyOn(faker.address, 'cardinalDirection') + .mockReturnValue('NW'); + + const cardinalDirection = faker.address.cardinalDirection(true); + const expected = 'NW'; + + expect( + cardinalDirection, + 'The cardinal direction when useAbbr is true should be equals ' + + expected + + '. Current is ' + + cardinalDirection + ).toBe(expected); + + spy_address_cardinalDirection.mockRestore(); + }); + + it('returns abbreviation when useAbbr is true', () => { + const cardinalDirection = faker.address.cardinalDirection(true); + const expectedType = 'string'; + const cardinalDirectionLength = cardinalDirection.length; + const prefixErrorMessage = + 'The cardinal direction when useAbbr is true should'; + + expect( + typeof cardinalDirection, + prefixErrorMessage + + ' be had typeof equals ' + + expectedType + + '.Current is ' + + typeof cardinalDirection + ).toBe(expectedType); + expect( + cardinalDirectionLength <= 2, + prefixErrorMessage + + ' have a length less or equals 2. Current is ' + + cardinalDirectionLength + ).toBe(true); + }); + }); + + describe('nearbyGPSCoordinate()', () => { + it('returns random gps coordinate within a distance of another one', () => { + function haversine(lat1, lon1, lat2, lon2, isMetric) { + function degreesToRadians(degrees) { + return degrees * (Math.PI / 180.0); + } + function kilometersToMiles(miles) { + return miles * 0.621371; + } + const R = 6378.137; + const dLat = degreesToRadians(lat2 - lat1); + const dLon = degreesToRadians(lon2 - lon1); + const a = + Math.sin(dLat / 2) * Math.sin(dLat / 2) + + Math.cos(degreesToRadians(lat1)) * + Math.cos(degreesToRadians(lat2)) * + Math.sin(dLon / 2) * + Math.sin(dLon / 2); + const distance = R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + + return isMetric ? distance : kilometersToMiles(distance); + } + + let latFloat1: number; + let lonFloat1: number; + let isMetric: boolean; + + for (let i = 0; i < 10000; i++) { + latFloat1 = parseFloat(faker.address.latitude()); + lonFloat1 = parseFloat(faker.address.longitude()); + const radius = Math.random() * 99 + 1; // range of [1, 100) + isMetric = Math.round(Math.random()) == 1; + + const coordinate = faker.address.nearbyGPSCoordinate( + [latFloat1, lonFloat1], + radius, + isMetric + ); + + expect(coordinate.length).toBe(2); + expect(typeof coordinate[0]).toBe('string'); + expect(typeof coordinate[1]).toBe('string'); + + const latFloat2 = parseFloat(coordinate[0]); + expect(latFloat2).greaterThanOrEqual(-90.0); + expect(latFloat2).lessThanOrEqual(90.0); + + const lonFloat2 = parseFloat(coordinate[1]); + expect(lonFloat2).greaterThanOrEqual(-180.0); + expect(lonFloat2).lessThanOrEqual(180.0); + + // Due to floating point math, and constants that are not extremely precise, + // returned points will not be strictly within the given radius of the input + // coordinate. Using a error of 1.0 to compensate. + const error = 1.0; + const actualDistance = haversine( + latFloat1, + lonFloat1, + latFloat2, + lonFloat2, + isMetric + ); + expect(actualDistance).lessThanOrEqual(radius + error); + } + + // test once with undefined radius + const coordinate = faker.address.nearbyGPSCoordinate( + [latFloat1, lonFloat1], + undefined, + isMetric + ); + expect(coordinate.length).toBe(2); + expect(typeof coordinate[0]).toBe('string'); + expect(typeof coordinate[1]).toBe('string'); + }); + }); + + describe('timeZone()', () => { + it('returns random timeZone', () => { + const spy_address_timeZone = vi.spyOn(faker.address, 'timeZone'); + + const timeZone = faker.address.timeZone(); + + expect(timeZone).toBeTruthy(); + expect(spy_address_timeZone).toHaveBeenCalled(); + + spy_address_timeZone.mockRestore(); + }); + }); +}); diff --git a/test/address.unit.js b/test/address.unit.js deleted file mode 100644 index 95334a61..00000000 --- a/test/address.unit.js +++ /dev/null @@ -1,678 +0,0 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var sinon = require('sinon'); - var faker = require('../lib').faker; -} - -describe('address.js', function () { - describe('city()', function () { - beforeEach(function () { - sinon.spy(faker.address, 'cityPrefix'); - sinon.spy(faker.name, 'firstName'); - sinon.spy(faker.name, 'lastName'); - sinon.spy(faker.address, 'citySuffix'); - }); - - afterEach(function () { - faker.datatype.number.restore(); - faker.address.cityPrefix.restore(); - faker.name.firstName.restore(); - faker.name.lastName.restore(); - faker.address.citySuffix.restore(); - }); - - it('occasionally returns prefix + first name + suffix', function () { - sinon.stub(faker.datatype, 'number').returns(0); - - var city = faker.address.city(); - assert.ok(city); - - assert.ok(faker.address.cityPrefix.calledOnce); - assert.ok(faker.name.firstName.calledOnce); - assert.ok(faker.address.citySuffix.calledOnce); - }); - - it('occasionally returns prefix + first name', function () { - sinon.stub(faker.datatype, 'number').returns(1); - - var city = faker.address.city(); - assert.ok(city); - - assert.ok(faker.address.cityPrefix.calledOnce); - assert.ok(faker.name.firstName.calledOnce); - }); - - it('occasionally returns first name + suffix', function () { - sinon.stub(faker.datatype, 'number').returns(2); - - var city = faker.address.city(); - assert.ok(city); - - assert.ok(faker.address.citySuffix.calledOnce); - }); - - it('occasionally returns last name + suffix', function () { - sinon.stub(faker.datatype, 'number').returns(3); - - var city = faker.address.city(); - assert.ok(city); - - assert.ok(!faker.address.cityPrefix.called); - assert.ok(!faker.name.firstName.called); - assert.ok(faker.name.lastName.calledOnce); - assert.ok(faker.address.citySuffix.calledOnce); - }); - }); - - describe('streetName()', function () { - beforeEach(function () { - sinon.spy(faker.name, 'firstName'); - sinon.spy(faker.name, 'lastName'); - sinon.spy(faker.address, 'streetSuffix'); - }); - - afterEach(function () { - faker.name.firstName.restore(); - faker.name.lastName.restore(); - faker.address.streetSuffix.restore(); - }); - - it('occasionally returns last name + suffix', function () { - sinon.stub(faker.datatype, 'number').returns(0); - - var street_name = faker.address.streetName(); - assert.ok(street_name); - assert.ok(!faker.name.firstName.called); - assert.ok(faker.name.lastName.calledOnce); - assert.ok(faker.address.streetSuffix.calledOnce); - - faker.datatype.number.restore(); - }); - - it('occasionally returns first name + suffix', function () { - sinon.stub(faker.datatype, 'number').returns(1); - - var street_name = faker.address.streetName(); - assert.ok(street_name); - - assert.ok(faker.name.firstName.calledOnce); - assert.ok(!faker.name.lastName.called); - assert.ok(faker.address.streetSuffix.calledOnce); - - faker.datatype.number.restore(); - }); - - it('trims trailing whitespace from the name', function () { - faker.address.streetSuffix.restore(); - - sinon.stub(faker.address, 'streetSuffix').returns(''); - var street_name = faker.address.streetName(); - assert.ok(!street_name.match(/ $/)); - }); - }); - - describe('streetAddress()', function () { - var errorExpectDigits = function (expected) { - return 'The street number should be had ' + expected + ' digits'; - }; - - beforeEach(function () { - sinon.spy(faker.address, 'streetName'); - sinon.spy(faker.address, 'secondaryAddress'); - }); - - afterEach(function () { - faker.address.streetName.restore(); - faker.address.secondaryAddress.restore(); - }); - - it('occasionally returns a 5-digit street number', function () { - sinon.stub(faker.datatype, 'number').returns(0); - var address = faker.address.streetAddress(); - var expected = 5; - var parts = address.split(' '); - - assert.strictEqual( - parts[0].length, - expected, - errorExpectDigits(expected) - ); - assert.ok(faker.address.streetName.called); - - faker.datatype.number.restore(); - }); - - it('occasionally returns a 4-digit street number', function () { - sinon.stub(faker.datatype, 'number').returns(1); - var address = faker.address.streetAddress(); - var parts = address.split(' '); - var expected = 4; - - assert.strictEqual( - parts[0].length, - expected, - errorExpectDigits(expected) - ); - assert.ok(faker.address.streetName.called); - - faker.datatype.number.restore(); - }); - - it('occasionally returns a 3-digit street number', function () { - sinon.stub(faker.datatype, 'number').returns(2); - var address = faker.address.streetAddress(); - var parts = address.split(' '); - var expected = 3; - - assert.strictEqual( - parts[0].length, - expected, - errorExpectDigits(expected) - ); - assert.ok(faker.address.streetName.called); - assert.ok(!faker.address.secondaryAddress.called); - - faker.datatype.number.restore(); - }); - - context('when useFulladdress is true', function () { - it('adds a secondary address to the result', function () { - faker.address.streetAddress(true); - - assert.ok(faker.address.secondaryAddress.called); - }); - }); - }); - - describe('secondaryAddress()', function () { - it('randomly chooses an Apt or Suite number', function () { - sinon.spy(faker.random, 'arrayElement'); - - var address = faker.address.secondaryAddress(); - - var expected_array = ['Apt. ###', 'Suite ###']; - - assert.ok(address); - assert.ok(faker.random.arrayElement.calledWith(expected_array)); - faker.random.arrayElement.restore(); - }); - }); - - describe('county()', function () { - it('returns random county', function () { - sinon.spy(faker.address, 'county'); - var county = faker.address.county(); - assert.ok(county); - assert.ok(faker.address.county.called); - faker.address.county.restore(); - }); - }); - - describe('country()', function () { - it('returns random country', function () { - sinon.spy(faker.address, 'country'); - var country = faker.address.country(); - assert.ok(country); - assert.ok(faker.address.country.called); - faker.address.country.restore(); - }); - }); - - describe('countryCode()', function () { - it('returns random countryCode', function () { - sinon.spy(faker.address, 'countryCode'); - var countryCode = faker.address.countryCode(); - assert.ok(countryCode); - assert.ok(faker.address.countryCode.called); - faker.address.countryCode.restore(); - }); - - it('returns random alpha-3 countryCode', function () { - sinon.spy(faker.address, 'countryCode'); - var countryCode = faker.address.countryCode('alpha-3'); - assert.ok(countryCode); - assert.ok(faker.address.countryCode.called); - assert.strictEqual( - countryCode.length, - 3, - 'The countryCode should be had 3 characters' - ); - faker.address.countryCode.restore(); - }); - }); - - describe('state()', function () { - it('returns random state', function () { - sinon.spy(faker.address, 'state'); - var state = faker.address.state(); - assert.ok(state); - assert.ok(faker.address.state.called); - faker.address.state.restore(); - }); - }); - - describe('zipCode()', function () { - it('returns random zipCode', function () { - sinon.spy(faker.address, 'zipCode'); - var zipCode = faker.address.zipCode(); - assert.ok(zipCode); - assert.ok(faker.address.zipCode.called); - faker.address.zipCode.restore(); - }); - - it('returns random zipCode - user specified format', function () { - var zipCode = faker.address.zipCode('?#? #?#'); - assert.ok(zipCode.match(/^[A-Za-z]\d[A-Za-z]\s\d[A-Za-z]\d$/)); - // try another format - zipCode = faker.address.zipCode('###-###'); - assert.ok(zipCode.match(/^\d{3}-\d{3}$/)); - }); - - it('returns zipCode with proper locale format', function () { - // we'll use the en_CA locale.. - faker.locale = 'en_CA'; - var zipCode = faker.address.zipCode(); - assert.ok(zipCode.match(/^[A-Za-z]\d[A-Za-z]\s?\d[A-Za-z]\d$/)); - }); - }); - - describe('zipCodeByState()', function () { - it('returns zipCode valid for specified State', function () { - faker.locale = 'en_US'; - var states = ['IL', 'GA', 'WA']; - - var zipCode1 = faker.address.zipCodeByState(states[0]); - assert.ok(zipCode1 >= 60001); - assert.ok(zipCode1 <= 62999); - var zipCode2 = faker.address.zipCodeByState(states[1]); - assert.ok(zipCode2 >= 30001); - assert.ok(zipCode2 <= 31999); - var zipCode3 = faker.address.zipCodeByState(states[2]); - assert.ok(zipCode3 >= 98001); - assert.ok(zipCode3 <= 99403); - }); - - it('returns undefined if state is invalid', function () { - var state = 'XX'; - sinon.spy(faker.address, 'zipCode'); - faker.address.zipCodeByState(state); - assert.ok(faker.address.zipCode.called); - faker.address.zipCode.restore(); - }); - - it('returns undefined if state is valid but localeis invalid', function () { - faker.locale = 'zh_CN'; - var state = 'IL'; - sinon.spy(faker.address, 'zipCode'); - faker.address.zipCodeByState(state); - assert.ok(faker.address.zipCode.called); - faker.address.zipCode.restore(); - }); - }); - - describe('latitude()', function () { - it('returns random latitude', function () { - for (var i = 0; i < 100; i++) { - sinon.spy(faker.datatype, 'number'); - var latitude = faker.address.latitude(); - assert.ok(typeof latitude === 'string'); - var latitude_float = parseFloat(latitude); - assert.ok(latitude_float >= -90.0); - assert.ok(latitude_float <= 90.0); - assert.ok(faker.datatype.number.called); - faker.datatype.number.restore(); - } - }); - - it('returns latitude with min and max and default precision', function () { - for (var i = 0; i < 100; i++) { - sinon.spy(faker.datatype, 'number'); - var latitude = faker.address.latitude(-5, 5); - assert.ok(typeof latitude === 'string'); - assert.strictEqual( - latitude.split('.')[1].length, - 4, - 'The precision of latitude should be had of 4 digits' - ); - var latitude_float = parseFloat(latitude); - assert.ok(latitude_float >= -5); - assert.ok(latitude_float <= 5); - assert.ok(faker.datatype.number.called); - faker.datatype.number.restore(); - } - }); - - it('returns random latitude with custom precision', function () { - for (var i = 0; i < 100; i++) { - sinon.spy(faker.datatype, 'number'); - var latitude = faker.address.latitude(undefined, undefined, 7); - assert.ok(typeof latitude === 'string'); - assert.strictEqual( - latitude.split('.')[1].length, - 7, - 'The precision of latitude should be had of 7 digits' - ); - var latitude_float = parseFloat(latitude); - assert.ok(latitude_float >= -180); - assert.ok(latitude_float <= 180); - assert.ok(faker.datatype.number.called); - faker.datatype.number.restore(); - } - }); - }); - - describe('longitude()', function () { - it('returns random longitude', function () { - for (var i = 0; i < 100; i++) { - sinon.spy(faker.datatype, 'number'); - var longitude = faker.address.longitude(); - assert.ok(typeof longitude === 'string'); - var longitude_float = parseFloat(longitude); - assert.ok(longitude_float >= -180.0); - assert.ok(longitude_float <= 180.0); - assert.ok(faker.datatype.number.called); - faker.datatype.number.restore(); - } - }); - - it('returns random longitude with min and max and default precision', function () { - for (var i = 0; i < 100; i++) { - sinon.spy(faker.datatype, 'number'); - var longitude = faker.address.longitude(100, -30); - assert.ok(typeof longitude === 'string'); - assert.strictEqual( - longitude.split('.')[1].length, - 4, - 'The precision of longitude should be had of 4 digits' - ); - var longitude_float = parseFloat(longitude); - assert.ok(longitude_float >= -30); - assert.ok(longitude_float <= 100); - assert.ok(faker.datatype.number.called); - faker.datatype.number.restore(); - } - }); - - it('returns random longitude with custom precision', function () { - for (var i = 0; i < 100; i++) { - sinon.spy(faker.datatype, 'number'); - var longitude = faker.address.longitude(undefined, undefined, 7); - assert.ok(typeof longitude === 'string'); - assert.strictEqual( - longitude.split('.')[1].length, - 7, - 'The precision of longitude should be had of 7 digits' - ); - var longitude_float = parseFloat(longitude); - assert.ok(longitude_float >= -180); - assert.ok(longitude_float <= 180); - assert.ok(faker.datatype.number.called); - faker.datatype.number.restore(); - } - }); - }); - - describe('direction()', function () { - it('returns random direction', function () { - sinon.stub(faker.address, 'direction').returns('North'); - var direction = faker.address.direction(); - var expected = 'North'; - - assert.strictEqual( - direction, - expected, - 'The random direction should be equals ' + expected - ); - faker.address.direction.restore(); - }); - - it('returns abbreviation when useAbbr is false', function () { - sinon.stub(faker.address, 'direction').returns('N'); - var direction = faker.address.direction(false); - var expected = 'N'; - assert.strictEqual( - direction, - expected, - 'The abbreviation of direction when useAbbr is false should be equals ' + - expected + - '. Current is ' + - direction - ); - faker.address.direction.restore(); - }); - - it('returns abbreviation when useAbbr is true', function () { - var direction = faker.address.direction(true); - var expectedType = 'string'; - var lengthDirection = direction.length; - var prefixErrorMessage = - 'The abbreviation of direction when useAbbr is true should'; - assert.strictEqual( - typeof direction, - expectedType, - prefixErrorMessage + ' be typeof string. Current is' + typeof direction - ); - assert.strictEqual( - lengthDirection <= 2, - true, - prefixErrorMessage + - ' have a length less or equals 2. Current is ' + - lengthDirection - ); - }); - - it('returns abbreviation when useAbbr is true', function () { - sinon.stub(faker.address, 'direction').returns('N'); - var direction = faker.address.direction(true); - var expected = 'N'; - assert.strictEqual( - direction, - expected, - 'The abbreviation of direction when useAbbr is true should be equals ' + - expected + - '. Current is ' + - direction - ); - faker.address.direction.restore(); - }); - }); - - describe('ordinalDirection()', function () { - it('returns random ordinal direction', function () { - sinon.stub(faker.address, 'ordinalDirection').returns('West'); - var ordinalDirection = faker.address.ordinalDirection(); - var expected = 'West'; - - assert.strictEqual( - ordinalDirection, - expected, - 'The ransom ordinal direction should be equals ' + - expected + - '. Current is ' + - ordinalDirection - ); - faker.address.ordinalDirection.restore(); - }); - - it('returns abbreviation when useAbbr is true', function () { - sinon.stub(faker.address, 'ordinalDirection').returns('W'); - var ordinalDirection = faker.address.ordinalDirection(true); - var expected = 'W'; - - assert.strictEqual( - ordinalDirection, - expected, - 'The ordinal direction when useAbbr is true should be equals ' + - expected + - '. Current is ' + - ordinalDirection - ); - faker.address.ordinalDirection.restore(); - }); - - it('returns abbreviation when useAbbr is true', function () { - var ordinalDirection = faker.address.ordinalDirection(true); - var expectedType = 'string'; - var ordinalDirectionLength = ordinalDirection.length; - var prefixErrorMessage = - 'The ordinal direction when useAbbr is true should'; - - assert.strictEqual( - typeof ordinalDirection, - expectedType, - prefixErrorMessage + - ' be had typeof equals ' + - expectedType + - '.Current is ' + - typeof ordinalDirection - ); - assert.strictEqual( - ordinalDirectionLength <= 2, - true, - prefixErrorMessage + - ' have a length less or equals 2. Current is ' + - ordinalDirectionLength - ); - }); - }); - - describe('cardinalDirection()', function () { - it('returns random cardinal direction', function () { - sinon.stub(faker.address, 'cardinalDirection').returns('Northwest'); - var cardinalDirection = faker.address.cardinalDirection(); - var expected = 'Northwest'; - - assert.strictEqual( - cardinalDirection, - expected, - 'The random cardinal direction should be equals ' + - expected + - '. Current is ' + - cardinalDirection - ); - faker.address.cardinalDirection.restore(); - }); - - it('returns abbreviation when useAbbr is true', function () { - sinon.stub(faker.address, 'cardinalDirection').returns('NW'); - var cardinalDirection = faker.address.cardinalDirection(true); - var expected = 'NW'; - - assert.strictEqual( - cardinalDirection, - expected, - 'The cardinal direction when useAbbr is true should be equals ' + - expected + - '. Current is ' + - cardinalDirection - ); - faker.address.cardinalDirection.restore(); - }); - - it('returns abbreviation when useAbbr is true', function () { - var cardinalDirection = faker.address.cardinalDirection(true); - var expectedType = 'string'; - var cardinalDirectionLength = cardinalDirection.length; - var prefixErrorMessage = - 'The cardinal direction when useAbbr is true should'; - - assert.strictEqual( - typeof cardinalDirection, - expectedType, - prefixErrorMessage + - ' be had typeof equals ' + - expectedType + - '.Current is ' + - typeof ordinalDirection - ); - assert.strictEqual( - cardinalDirectionLength <= 2, - true, - prefixErrorMessage + - ' have a length less or equals 2. Current is ' + - cardinalDirectionLength - ); - }); - }); - - describe('nearbyGPSCoordinate()', function () { - it('returns random gps coordinate within a distance of another one', function () { - function haversine(lat1, lon1, lat2, lon2, isMetric) { - function degreesToRadians(degrees) { - return degrees * (Math.PI / 180.0); - } - function kilometersToMiles(miles) { - return miles * 0.621371; - } - var R = 6378.137; - var dLat = degreesToRadians(lat2 - lat1); - var dLon = degreesToRadians(lon2 - lon1); - var a = - Math.sin(dLat / 2) * Math.sin(dLat / 2) + - Math.cos(degreesToRadians(lat1)) * - Math.cos(degreesToRadians(lat2)) * - Math.sin(dLon / 2) * - Math.sin(dLon / 2); - var distance = R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); - - return isMetric ? distance : kilometersToMiles(distance); - } - for (var i = 0; i < 10000; i++) { - var latFloat1 = parseFloat(faker.address.latitude()); - var lonFloat1 = parseFloat(faker.address.longitude()); - var radius = Math.random() * 99 + 1; // range of [1, 100) - var isMetric = Math.round(Math.random()) == 1; - - var coordinate = faker.address.nearbyGPSCoordinate( - [latFloat1, lonFloat1], - radius, - isMetric - ); - assert.ok(coordinate.length === 2); - assert.ok(typeof coordinate[0] === 'string'); - assert.ok(typeof coordinate[1] === 'string'); - - var latFloat2 = parseFloat(coordinate[0]); - assert.ok(latFloat2 >= -90.0); - assert.ok(latFloat2 <= 90.0); - - var lonFloat2 = parseFloat(coordinate[1]); - assert.ok(lonFloat2 >= -180.0); - assert.ok(lonFloat2 <= 180.0); - - // Due to floating point math, and constants that are not extremely precise, - // returned points will not be strictly within the given radius of the input - // coordinate. Using a error of 1.0 to compensate. - var error = 1.0; - var actualDistance = haversine( - latFloat1, - lonFloat1, - latFloat2, - lonFloat2, - isMetric - ); - assert.ok(actualDistance <= radius + error); - } - - // test once with undefined radius - var coordinate = faker.address.nearbyGPSCoordinate( - [latFloat1, lonFloat1], - undefined, - isMetric - ); - assert.ok(coordinate.length === 2); - assert.ok(typeof coordinate[0] === 'string'); - assert.ok(typeof coordinate[1] === 'string'); - }); - }); - - describe('timeZone()', function () { - it('returns random timeZone', function () { - sinon.spy(faker.address, 'timeZone'); - var timeZone = faker.address.timeZone(); - assert.ok(timeZone); - assert.ok(faker.address.timeZone.called); - faker.address.timeZone.restore(); - }); - }); -}); diff --git a/test/all.functional.js b/test/all.functional.js deleted file mode 100644 index 36ddad42..00000000 --- a/test/all.functional.js +++ /dev/null @@ -1,55 +0,0 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var sinon = require('sinon'); - var faker = require('../lib').faker; -} - -var functionalHelpers = require('./support/function-helpers.js'); - -var modules = functionalHelpers.modulesList(); - -describe('functional tests', function () { - for (var locale in faker.locales) { - faker.locale = locale; - Object.keys(modules).forEach(function (module) { - describe(module, function () { - modules[module].forEach(function (meth) { - it(meth + '()', function () { - var result = faker[module][meth](); - if (meth === 'boolean') { - assert.ok(result === true || result === false); - } else { - assert.ok(result); - } - }); - }); - }); - }); - } -}); - -describe('faker.fake functional tests', function () { - for (var locale in faker.locales) { - faker.locale = locale; - faker.seed(1); - Object.keys(modules).forEach(function (module) { - describe(module, function () { - modules[module].forEach(function (meth) { - it(meth + '()', function () { - var result = faker.fake('{{' + module + '.' + meth + '}}'); - // just make sure any result is returned - // an undefined result usually means an error - assert.ok(typeof result !== 'undefined'); - /* - if (meth === 'boolean') { - assert.ok(result === true || result === false); - } else { - assert.ok(result); - } - */ - }); - }); - }); - }); - } -}); diff --git a/test/all_functional.spec.ts b/test/all_functional.spec.ts new file mode 100644 index 00000000..779d8335 --- /dev/null +++ b/test/all_functional.spec.ts @@ -0,0 +1,107 @@ +import { describe, expect, it } from 'vitest'; +import { faker } from '../lib'; + +const IGNORED_MODULES = [ + 'locales', + 'locale', + 'localeFallback', + 'definitions', + 'fake', + 'helpers', + 'mersenne', +]; + +const IGNORED_METHODS = { + system: ['directoryPath', 'filePath'], // these are TODOs +}; + +function isTestableModule(mod: string) { + return IGNORED_MODULES.indexOf(mod) === -1; +} + +function isMethodOf(mod: string) { + return (meth: string) => typeof faker[mod][meth] === 'function'; +} + +function isTestableMethod(mod: string) { + return (meth: string) => + !(mod in IGNORED_METHODS && IGNORED_METHODS[mod].indexOf(meth) >= 0); +} + +function both( + pred1: (meth: string) => boolean, + pred2: (meth: string) => boolean +) { + return (value) => pred1(value) && pred2(value); +} + +// Basic smoke tests to make sure each method is at least implemented and returns a value. + +function modulesList() { + const modules = Object.keys(faker) + .filter(isTestableModule) + .reduce((result, mod) => { + result[mod] = Object.keys(faker[mod]).filter( + both(isMethodOf(mod), isTestableMethod(mod)) + ); + return result; + }, {}); + + return modules; +} + +const modules = modulesList(); + +describe('functional tests', () => { + for (const locale in faker.locales) { + faker.locale = locale; + Object.keys(modules).forEach((module) => { + describe(module, () => { + // if there is nothing to test, create a dummy test so the test runner doesn't complain + if (Object.keys(modules[module]).length === 0) { + it.todo(`${module} was empty`); + } + + modules[module].forEach((meth) => { + it(meth + '()', () => { + const result = faker[module][meth](); + if (meth === 'boolean') { + expect(typeof result).toBe('boolean'); + } else { + expect(result).toBeTruthy(); + } + }); + }); + }); + }); + } +}); + +describe('faker.fake functional tests', () => { + for (const locale in faker.locales) { + faker.locale = locale; + faker.seed(1); + Object.keys(modules).forEach((module) => { + describe(module, () => { + // if there is nothing to test, create a dummy test so the test runner doesn't complain + if (Object.keys(modules[module]).length === 0) { + it.todo(`${module} was empty`); + } + + modules[module].forEach((meth) => { + it(meth + '()', () => { + const result = faker.fake('{{' + module + '.' + meth + '}}'); + // just make sure any result is returned + // an undefined result usually means an error + expect(result).toBeDefined(); + // if (meth === 'boolean') { + // expect(typeof result).toBe('boolean'); + // } else { + // expect(result).toBeTruthy(); + // } + }); + }); + }); + }); + } +}); diff --git a/test/animal.spec.ts b/test/animal.spec.ts new file mode 100644 index 00000000..a2c63eab --- /dev/null +++ b/test/animal.spec.ts @@ -0,0 +1,11 @@ +import { describe, expect, it } from 'vitest'; +import { faker } from '../lib'; + +describe('animal', () => { + describe('dog()', () => { + it('returns random value from dog array', () => { + const dog = faker.animal.dog(); + expect(faker.definitions.animal.dog).toContain(dog); + }); + }); +}); diff --git a/test/animal.unit.js b/test/animal.unit.js deleted file mode 100644 index 17d7aa8a..00000000 --- a/test/animal.unit.js +++ /dev/null @@ -1,14 +0,0 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var sinon = require('sinon'); - var faker = require('../lib').faker; -} - -describe('animal.js', function () { - describe('dog()', function () { - it('returns random value from dog array', function () { - var dog = faker.animal.dog(); - assert.ok(faker.definitions.animal.dog.indexOf(dog) !== -1); - }); - }); -}); diff --git a/test/browser.unit.html b/test/browser.unit.html deleted file mode 100644 index c9606103..00000000 --- a/test/browser.unit.html +++ /dev/null @@ -1,33 +0,0 @@ -<html> - <head> - <meta charset="utf-8" /> - <title>Mocha Tests</title> - <link rel="stylesheet" href="../node_modules/mocha/mocha.css" /> - </head> - <body> - <div id="mocha"></div> - <script src="../node_modules/mocha/mocha.js"></script> - <script src="../faker.js"></script> - <script src="./support/chai.js"></script> - <script src="./support/sinon-1.5.2.js"></script> - <script> - assert = chai.assert; - </script> - <script> - mocha.setup('bdd'); - </script> - <script src="all.functional.js"></script> - <script src="address.unit.js"></script> - <script src="company.unit.js"></script> - <script src="helpers.unit.js"></script> - <script src="internet.unit.js"></script> - <script src="database.unit.js"></script> - <script src="datatype.unit.js"></script> - <script src="lorem.unit.js"></script> - <script src="name.unit.js"></script> - <script src="phone_number.unit.js"></script> - <script> - mocha.run(); - </script> - </body> -</html> diff --git a/test/commerce.spec.ts b/test/commerce.spec.ts new file mode 100644 index 00000000..4f3cde72 --- /dev/null +++ b/test/commerce.spec.ts @@ -0,0 +1,158 @@ +import { describe, expect, it, vi } from 'vitest'; +import { faker } from '../lib'; + +describe('commerce', () => { + describe('color()', () => { + it('returns random value from commerce.color array', () => { + const color = faker.commerce.color(); + expect(faker.definitions.commerce.color).toContain(color); + }); + }); + + describe('department(max, fixedValue)', () => { + it('should use the default amounts when not passing arguments', () => { + const department = faker.commerce.department(); + expect(department.split(' ')).toHaveLength(1); + }); + + /* + + it("should return only one value if we specify a maximum of one", function() { + sinon.spy(faker.random, 'arrayElement'); + + const department = faker.commerce.department(1); + + assert.strictEqual(department.split(" ").length, 1); + assert.ok(faker.random.arrayElement.calledOnce); + + faker.random.arrayElement.restore(); + }); + + it("should return the maximum value if we specify the fixed value", function() { + sinon.spy(faker.random, 'arrayElement'); + + const department = faker.commerce.department(5, true); + + console.log(department); + + // account for the separator + assert.strictEqual(department.split(" ").length, 6); + // Sometimes it will generate duplicates that aren't used in the final string, + // so we check if arrayElement has been called exactly or more than 5 times + assert.ok(faker.random.arrayElement.callCount >= 5); + + faker.random.arrayElement.restore(); + }); + */ + }); + + describe('productName()', () => { + it('returns name comprising of an adjective, material and product', () => { + const spy_random_arrayElement = vi.spyOn(faker.random, 'arrayElement'); + const spy_commerce_productAdjective = vi.spyOn( + faker.commerce, + 'productAdjective' + ); + const spy_commerce_productMaterial = vi.spyOn( + faker.commerce, + 'productMaterial' + ); + const spy_commerce_product = vi.spyOn(faker.commerce, 'product'); + + const name = faker.commerce.productName(); + + expect(name.split(' ').length).greaterThanOrEqual(3); + + expect(spy_random_arrayElement).toHaveBeenCalledTimes(3); + expect(spy_commerce_productAdjective).toHaveBeenCalledOnce(); + expect(spy_commerce_productMaterial).toHaveBeenCalledOnce(); + expect(spy_commerce_product).toHaveBeenCalledOnce(); + + spy_random_arrayElement.mockRestore(); + spy_commerce_productAdjective.mockRestore(); + spy_commerce_productMaterial.mockRestore(); + spy_commerce_product.mockRestore(); + }); + }); + + describe('price(min, max, dec, symbol)', () => { + it('should use the default amounts when not passing arguments', () => { + const price = faker.commerce.price(); + + expect(price).toBeTruthy(); + // TODO @Shinigami92 2022-01-20: I converted the price string to number to satisfy TS + expect(+price > 0, 'the amount should be greater than 0').toBe(true); + expect(+price < 1001, 'the amount should be less than 1000').toBe(true); + }); + + it('should use the default decimal location when not passing arguments', () => { + const price = faker.commerce.price(); + + const decimal = '.'; + const expected = price.length - 3; + const actual = price.indexOf(decimal); + + expect( + actual, + 'The expected location of the decimal is ' + + expected + + ' but it was ' + + actual + + ' amount ' + + price + ).toBe(expected); + }); + + it('should not include a currency symbol by default', () => { + const amount = faker.commerce.price(); + + const regexp = new RegExp(/[0-9.]/); + + const expected = true; + const actual = regexp.test(amount); + + expect( + actual, + 'The expected match should not include a currency symbol' + ).toBe(expected); + }); + + it('it should handle negative amounts, but return 0', () => { + const amount = faker.commerce.price(-200, -1); + + expect(amount).toBeTruthy(); + // TODO @Shinigami92 2022-01-20: I converted the price string to number to satisfy TS + expect(+amount === 0.0, 'the amount should equal 0').toBe(true); + }); + + it('it should handle argument dec', () => { + const price = faker.commerce.price(100, 100, 1); + + expect(price).toBeTruthy(); + expect(price, 'the price should be equal 100.0').toStrictEqual('100.0'); + }); + + it('it should handle argument dec = 0', () => { + const price = faker.commerce.price(100, 100, 0); + + expect(price).toBeTruthy(); + expect(price, 'the price should be equal 100').toStrictEqual('100'); + }); + }); + + describe('productDescription()', () => { + it('returns a random product description', () => { + const spy_commerce_productDescription = vi.spyOn( + faker.commerce, + 'productDescription' + ); + + const description = faker.commerce.productDescription(); + + expect(typeof description).toBe('string'); + expect(spy_commerce_productDescription).toHaveBeenCalledOnce(); + + spy_commerce_productDescription.mockRestore(); + }); + }); +}); diff --git a/test/commerce.unit.js b/test/commerce.unit.js deleted file mode 100644 index 5df8d400..00000000 --- a/test/commerce.unit.js +++ /dev/null @@ -1,157 +0,0 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var sinon = require('sinon'); - var faker = require('../lib').faker; -} - -describe('commerce.js', function () { - describe('color()', function () { - it('returns random value from commerce.color array', function () { - var color = faker.commerce.color(); - assert.ok(faker.definitions.commerce.color.indexOf(color) !== -1); - }); - }); - - describe('department(max, fixedValue)', function () { - it('should use the default amounts when not passing arguments', function () { - var department = faker.commerce.department(); - assert.ok(department.split(' ').length === 1); - }); - - /* - - it("should return only one value if we specify a maximum of one", function() { - sinon.spy(faker.random, 'arrayElement'); - - var department = faker.commerce.department(1); - - assert.strictEqual(department.split(" ").length, 1); - assert.ok(faker.random.arrayElement.calledOnce); - - faker.random.arrayElement.restore(); - }); - - it("should return the maximum value if we specify the fixed value", function() { - sinon.spy(faker.random, 'arrayElement'); - - var department = faker.commerce.department(5, true); - - console.log(department); - - // account for the separator - assert.strictEqual(department.split(" ").length, 6); - // Sometimes it will generate duplicates that aren't used in the final string, - // so we check if arrayElement has been called exactly or more than 5 times - assert.ok(faker.random.arrayElement.callCount >= 5); - - faker.random.arrayElement.restore(); - }); - */ - }); - - describe('productName()', function () { - it('returns name comprising of an adjective, material and product', function () { - sinon.spy(faker.random, 'arrayElement'); - sinon.spy(faker.commerce, 'productAdjective'); - sinon.spy(faker.commerce, 'productMaterial'); - sinon.spy(faker.commerce, 'product'); - var name = faker.commerce.productName(); - - assert.ok(name.split(' ').length >= 3); - assert.ok(faker.random.arrayElement.calledThrice); - assert.ok(faker.commerce.productAdjective.calledOnce); - assert.ok(faker.commerce.productMaterial.calledOnce); - assert.ok(faker.commerce.product.calledOnce); - - faker.random.arrayElement.restore(); - faker.commerce.productAdjective.restore(); - faker.commerce.productMaterial.restore(); - faker.commerce.product.restore(); - }); - }); - - describe('price(min, max, dec, symbol)', function () { - it('should use the default amounts when not passing arguments', function () { - var price = faker.commerce.price(); - - assert.ok(price); - assert.strictEqual( - price > 0, - true, - 'the amount should be greater than 0' - ); - assert.strictEqual( - price < 1001, - true, - 'the amount should be less than 1000' - ); - }); - - it('should use the default decimal location when not passing arguments', function () { - var price = faker.commerce.price(); - - var decimal = '.'; - var expected = price.length - 3; - var actual = price.indexOf(decimal); - - assert.strictEqual( - actual, - expected, - 'The expected location of the decimal is ' + - expected + - ' but it was ' + - actual + - ' amount ' + - price - ); - }); - - it('should not include a currency symbol by default', function () { - var amount = faker.commerce.price(); - - var regexp = new RegExp(/[0-9.]/); - - var expected = true; - var actual = regexp.test(amount); - - assert.strictEqual( - actual, - expected, - 'The expected match should not include a currency symbol' - ); - }); - - it('it should handle negative amounts, but return 0', function () { - var amount = faker.commerce.price(-200, -1); - - assert.ok(amount); - assert.strictEqual(amount == 0.0, true, 'the amount should equal 0'); - }); - - it('it should handle argument dec', function () { - var price = faker.commerce.price(100, 100, 1); - - assert.ok(price); - assert.strictEqual(price, '100.0', 'the price should be equal 100.0'); - }); - - it('it should handle argument dec = 0', function () { - var price = faker.commerce.price(100, 100, 0); - - assert.ok(price); - assert.strictEqual(price, '100', 'the price should be equal 100'); - }); - }); - - describe('productDescription()', function () { - it('returns a random product description', function () { - sinon.spy(faker.commerce, 'productDescription'); - var description = faker.commerce.productDescription(); - - assert.ok(typeof description === 'string'); - assert.ok(faker.commerce.productDescription.calledOnce); - - faker.commerce.productDescription.restore(); - }); - }); -}); diff --git a/test/company.spec.ts b/test/company.spec.ts new file mode 100644 index 00000000..4fe37eee --- /dev/null +++ b/test/company.spec.ts @@ -0,0 +1,120 @@ +import { describe, expect, it, vi } from 'vitest'; +import { faker } from '../lib'; + +describe('company', () => { + describe('companyName()', () => { + it('sometimes returns three last names', () => { + const spy_name_lastName = vi.spyOn(faker.name, 'lastName'); + const spy_datatype_number = vi + .spyOn(faker.datatype, 'number') + .mockReturnValue(2); + + const name = faker.company.companyName(); + const parts = name.split(' '); + + expect(parts.length).toBe(4); // account for word 'and' + expect(spy_name_lastName).toHaveBeenCalledTimes(3); + + spy_datatype_number.mockRestore(); + spy_name_lastName.mockRestore(); + }); + + it('sometimes returns two last names separated by a hyphen', () => { + const spy_name_lastName = vi.spyOn(faker.name, 'lastName'); + const spy_datatype_number = vi + .spyOn(faker.datatype, 'number') + .mockReturnValue(1); + + const name = faker.company.companyName(); + const parts = name.split('-'); + + expect(parts.length).greaterThanOrEqual(2); + expect(spy_name_lastName).toHaveBeenCalledTimes(2); + + spy_datatype_number.mockRestore(); + spy_name_lastName.mockRestore(); + }); + + it('sometimes returns a last name with a company suffix', () => { + const spy_company_companySuffix = vi.spyOn( + faker.company, + 'companySuffix' + ); + const spy_name_lastName = vi.spyOn(faker.name, 'lastName'); + const spy_datatype_number = vi + .spyOn(faker.datatype, 'number') + .mockReturnValue(0); + + const name = faker.company.companyName(); + const parts = name.split(' '); + + expect(parts.length).greaterThanOrEqual(2); + expect(spy_name_lastName).toHaveBeenCalledOnce(); + expect(spy_company_companySuffix).toHaveBeenCalledOnce(); + + spy_datatype_number.mockRestore(); + spy_name_lastName.mockRestore(); + spy_company_companySuffix.mockRestore(); + }); + }); + + describe('companySuffix()', () => { + it('returns random value from company.suffixes array', () => { + const suffix = faker.company.companySuffix(); + expect(faker.company.suffixes()).toContain(suffix); + }); + }); + + describe('catchPhrase()', () => { + it('returns phrase comprising of a catch phrase adjective, descriptor, and noun', () => { + const spy_random_arrayElement = vi.spyOn(faker.random, 'arrayElement'); + const spy_company_catchPhraseAdjective = vi.spyOn( + faker.company, + 'catchPhraseAdjective' + ); + const spy_company_catchPhraseDescriptor = vi.spyOn( + faker.company, + 'catchPhraseDescriptor' + ); + const spy_company_catchPhraseNoun = vi.spyOn( + faker.company, + 'catchPhraseNoun' + ); + + const phrase = faker.company.catchPhrase(); + + expect(phrase.split(' ').length).greaterThanOrEqual(3); + expect(spy_random_arrayElement).toHaveBeenCalledTimes(3); + expect(spy_company_catchPhraseAdjective).toHaveBeenCalledOnce(); + expect(spy_company_catchPhraseDescriptor).toHaveBeenCalledOnce(); + expect(spy_company_catchPhraseNoun).toHaveBeenCalledOnce(); + + spy_random_arrayElement.mockRestore(); + spy_company_catchPhraseAdjective.mockRestore(); + spy_company_catchPhraseDescriptor.mockRestore(); + spy_company_catchPhraseNoun.mockRestore(); + }); + }); + + describe('bs()', () => { + it('returns phrase comprising of a BS buzz, adjective, and noun', () => { + const spy_random_arrayElement = vi.spyOn(faker.random, 'arrayElement'); + const spy_company_bsBuzz = vi.spyOn(faker.company, 'bsBuzz'); + const spy_company_bsAdjective = vi.spyOn(faker.company, 'bsAdjective'); + const spy_company_bsNoun = vi.spyOn(faker.company, 'bsNoun'); + + const bs = faker.company.bs(); + + expect(typeof bs).toBe('string'); + expect(spy_random_arrayElement).toHaveBeenCalledTimes(3); + expect(spy_company_bsBuzz).toHaveBeenCalledOnce(); + expect(spy_company_bsAdjective).toHaveBeenCalledOnce(); + expect(spy_company_bsNoun).toHaveBeenCalledOnce(); + + spy_random_arrayElement.mockRestore(); + spy_company_bsBuzz.mockRestore(); + spy_company_bsAdjective.mockRestore(); + spy_company_bsNoun.mockRestore(); + }); + }); +}); diff --git a/test/company.unit.js b/test/company.unit.js deleted file mode 100644 index eccadb9f..00000000 --- a/test/company.unit.js +++ /dev/null @@ -1,100 +0,0 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var sinon = require('sinon'); - var faker = require('../lib').faker; -} - -describe('company.js', function () { - describe('companyName()', function () { - it('sometimes returns three last names', function () { - sinon.spy(faker.name, 'lastName'); - sinon.stub(faker.datatype, 'number').returns(2); - var name = faker.company.companyName(); - var parts = name.split(' '); - - assert.strictEqual(parts.length, 4); // account for word 'and' - assert.ok(faker.name.lastName.calledThrice); - - faker.datatype.number.restore(); - faker.name.lastName.restore(); - }); - - it('sometimes returns two last names separated by a hyphen', function () { - sinon.spy(faker.name, 'lastName'); - sinon.stub(faker.datatype, 'number').returns(1); - var name = faker.company.companyName(); - var parts = name.split('-'); - - assert.ok(parts.length >= 2); - assert.ok(faker.name.lastName.calledTwice); - - faker.datatype.number.restore(); - faker.name.lastName.restore(); - }); - - it('sometimes returns a last name with a company suffix', function () { - sinon.spy(faker.company, 'companySuffix'); - sinon.spy(faker.name, 'lastName'); - sinon.stub(faker.datatype, 'number').returns(0); - var name = faker.company.companyName(); - var parts = name.split(' '); - - assert.ok(parts.length >= 2); - assert.ok(faker.name.lastName.calledOnce); - assert.ok(faker.company.companySuffix.calledOnce); - - faker.datatype.number.restore(); - faker.name.lastName.restore(); - faker.company.companySuffix.restore(); - }); - }); - - describe('companySuffix()', function () { - it('returns random value from company.suffixes array', function () { - var suffix = faker.company.companySuffix(); - assert.ok(faker.company.suffixes().indexOf(suffix) !== -1); - }); - }); - - describe('catchPhrase()', function () { - it('returns phrase comprising of a catch phrase adjective, descriptor, and noun', function () { - sinon.spy(faker.random, 'arrayElement'); - sinon.spy(faker.company, 'catchPhraseAdjective'); - sinon.spy(faker.company, 'catchPhraseDescriptor'); - sinon.spy(faker.company, 'catchPhraseNoun'); - var phrase = faker.company.catchPhrase(); - - assert.ok(phrase.split(' ').length >= 3); - assert.ok(faker.random.arrayElement.calledThrice); - assert.ok(faker.company.catchPhraseAdjective.calledOnce); - assert.ok(faker.company.catchPhraseDescriptor.calledOnce); - assert.ok(faker.company.catchPhraseNoun.calledOnce); - - faker.random.arrayElement.restore(); - faker.company.catchPhraseAdjective.restore(); - faker.company.catchPhraseDescriptor.restore(); - faker.company.catchPhraseNoun.restore(); - }); - }); - - describe('bs()', function () { - it('returns phrase comprising of a BS buzz, adjective, and noun', function () { - sinon.spy(faker.random, 'arrayElement'); - sinon.spy(faker.company, 'bsBuzz'); - sinon.spy(faker.company, 'bsAdjective'); - sinon.spy(faker.company, 'bsNoun'); - var bs = faker.company.bs(); - - assert.ok(typeof bs === 'string'); - assert.ok(faker.random.arrayElement.calledThrice); - assert.ok(faker.company.bsBuzz.calledOnce); - assert.ok(faker.company.bsAdjective.calledOnce); - assert.ok(faker.company.bsNoun.calledOnce); - - faker.random.arrayElement.restore(); - faker.company.bsBuzz.restore(); - faker.company.bsAdjective.restore(); - faker.company.bsNoun.restore(); - }); - }); -}); diff --git a/test/database.spec.ts b/test/database.spec.ts new file mode 100644 index 00000000..1d551339 --- /dev/null +++ b/test/database.spec.ts @@ -0,0 +1,82 @@ +import { describe, expect, it, vi } from 'vitest'; +import { faker } from '../lib'; + +describe('database', () => { + describe('column()', () => { + it('returns a column name', () => { + const spy_database_column = vi + .spyOn(faker.database, 'column') + .mockReturnValue('title'); + + const column = faker.database.column(); + const expected = 'title'; + + expect( + column, + 'The column name should be equals ' + + expected + + '. Current is ' + + column + ).toBe(expected); + + spy_database_column.mockRestore(); + }); + }); + + describe('collation()', () => { + it('returns a collation', () => { + const spy_database_collation = vi + .spyOn(faker.database, 'collation') + .mockReturnValue('utf8_bin'); + + const collation = faker.database.collation(); + const expected = 'utf8_bin'; + + expect( + collation, + 'The collation should be equals ' + + expected + + '. Current is ' + + collation + ).toBe(expected); + + spy_database_collation.mockRestore(); + }); + }); + + describe('engine()', () => { + it('returns an engine', () => { + const spy_database_engine = vi + .spyOn(faker.database, 'engine') + .mockReturnValue('InnoDB'); + + const engine = faker.database.engine(); + const expected = 'InnoDB'; + + expect( + engine, + 'The db engine should be equals ' + expected + '. Current is ' + engine + ).toBe(expected); + + spy_database_engine.mockRestore(); + }); + }); + + describe('type()', () => { + it('returns a column type', () => { + const spy_database_type = vi + .spyOn(faker.database, 'type') + .mockReturnValue('int'); + + const type = faker.database.type(); + const expected = 'int'; + + expect( + type, + 'The column type should be equals ' + expected + '. Current is ' + type + ).toBe(expected); + + spy_database_type.mockRestore(); + }); + }); +}); diff --git a/test/database.unit.js b/test/database.unit.js deleted file mode 100644 index 78420fcb..00000000 --- a/test/database.unit.js +++ /dev/null @@ -1,73 +0,0 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var sinon = require('sinon'); - var faker = require('../lib').faker; -} - -describe('database.js', function () { - describe('column()', function () { - it('returns a column name', function () { - sinon.stub(faker.database, 'column').returns('title'); - var column = faker.database.column(); - var expected = 'title'; - - assert.strictEqual( - column, - expected, - 'The column name should be equals ' + - expected + - '. Current is ' + - column - ); - faker.database.column.restore(); - }); - }); - - describe('collation()', function () { - it('returns a collation', function () { - sinon.stub(faker.database, 'collation').returns('utf8_bin'); - var collation = faker.database.collation(); - var expected = 'utf8_bin'; - - assert.strictEqual( - collation, - expected, - 'The collation should be equals ' + - expected + - '. Current is ' + - collation - ); - faker.database.collation.restore(); - }); - }); - - describe('engine()', function () { - it('returns an engine', function () { - sinon.stub(faker.database, 'engine').returns('InnoDB'); - var engine = faker.database.engine(); - var expected = 'InnoDB'; - - assert.strictEqual( - engine, - expected, - 'The db engine should be equals ' + expected + '. Current is ' + engine - ); - faker.database.engine.restore(); - }); - }); - - describe('type()', function () { - it('returns a column type', function () { - sinon.stub(faker.database, 'type').returns('int'); - var type = faker.database.type(); - var expected = 'int'; - - assert.strictEqual( - type, - expected, - 'The column type should be equals ' + expected + '. Current is ' + type - ); - faker.database.type.restore(); - }); - }); -}); diff --git a/test/datatype.spec.ts b/test/datatype.spec.ts new file mode 100644 index 00000000..38314951 --- /dev/null +++ b/test/datatype.spec.ts @@ -0,0 +1,306 @@ +import { describe, expect, it, vi } from 'vitest'; +import { faker } from '../lib'; + +describe('datatype', () => { + describe('number', () => { + it('returns a random number given a maximum value as Number', () => { + const max = 10; + expect(faker.datatype.number(max)).lessThanOrEqual(max); + }); + + it('returns a random number given a maximum value as Object', () => { + const options = { max: 10 }; + expect(faker.datatype.number(options)).lessThanOrEqual(options.max); + }); + + it('returns a random number given a maximum value of 0', () => { + const options = { max: 0 }; + expect(faker.datatype.number(options)).toBe(0); + }); + + it('returns a random number given a negative number minimum and maximum value of 0', () => { + const options = { min: -100, max: 0 }; + expect(faker.datatype.number(options)).lessThanOrEqual(options.max); + }); + + it('returns a random number between a range', () => { + const options = { min: 22, max: 33 }; + for (let i = 0; i < 100; i++) { + const randomNumber = faker.datatype.number(options); + expect(randomNumber).greaterThanOrEqual(options.min); + expect(randomNumber).lessThanOrEqual(options.max); + } + }); + + it('provides numbers with a given precision', () => { + const options = { min: 0, max: 1.5, precision: 0.5 }; + const results = Array.from( + new Set( + Array.from({ length: 50 }, () => faker.datatype.number(options)) + ) + ).sort(); + + expect(results).toContain(0.5); + expect(results).toContain(1.0); + + expect(results[0]).toBe(0); + expect(results[results.length - 1]).toBe(1.5); + }); + + it('provides numbers with a with exact precision', () => { + const options = { min: 0.5, max: 0.99, precision: 0.01 }; + for (let i = 0; i < 100; i++) { + const number = faker.datatype.number(options); + expect(number).toBe(Number(number.toFixed(2))); + } + }); + + it('should not modify the input object', () => { + const min = 1; + const max = 2; + const opts = { + min: min, + max: max, + }; + + faker.datatype.number(opts); + + expect(opts.min).toBe(min); + expect(opts.max).toBe(max); + }); + }); + + describe('float', () => { + it('returns a random float with a default precision value (0.01)', () => { + const number = faker.datatype.float(); + expect(number).toBe(Number(number.toFixed(2))); + }); + + it('returns a random float given a precision value', () => { + const number = faker.datatype.float(0.001); + expect(number).toBe(Number(number.toFixed(3))); + }); + + it('returns a random number given a maximum value as Object', () => { + const options = { max: 10 }; + expect(faker.datatype.float(options)).lessThanOrEqual(options.max); + }); + + it('returns a random number given a maximum value of 0', () => { + const options = { max: 0 }; + expect(faker.datatype.float(options)).toBe(0); + }); + + it('returns a random number given a negative number minimum and maximum value of 0', () => { + const options = { min: -100, max: 0 }; + expect(faker.datatype.float(options)).lessThanOrEqual(options.max); + }); + + it('returns a random number between a range', () => { + const options = { min: 22, max: 33 }; + for (let i = 0; i < 5; i++) { + const randomNumber = faker.datatype.float(options); + expect(randomNumber).greaterThanOrEqual(options.min); + expect(randomNumber).lessThanOrEqual(options.max); + } + }); + + it('provides numbers with a given precision', () => { + const options = { min: 0, max: 1.5, precision: 0.5 }; + const results = Array.from( + new Set(Array.from({ length: 50 }, () => faker.datatype.float(options))) + ).sort(); + + expect(results).toContain(0.5); + expect(results).toContain(1.0); + + expect(results[0]).toBe(0); + expect(results[results.length - 1]).toBe(1.5); + }); + + it('provides numbers with a with exact precision', () => { + const options = { min: 0.5, max: 0.99, precision: 0.01 }; + for (let i = 0; i < 100; i++) { + const number = faker.datatype.float(options); + expect(number).toBe(Number(number.toFixed(2))); + } + }); + + it('should not modify the input object', () => { + const min = 1; + const max = 2; + const opts = { + min: min, + max: max, + }; + + faker.datatype.float(opts); + + expect(opts.min).toBe(min); + expect(opts.max).toBe(max); + }); + }); + + describe('datetime', () => { + it('check validity of date and if returned value is created by Date()', () => { + const date = faker.datatype.datetime(); + expect(typeof date).toBe('object'); + expect(date.getTime()).not.toBeNaN(); + expect(Object.prototype.toString.call(date)).toBe('[object Date]'); + }); + + it('basic test with stubbed value', () => { + const today = new Date(); + const spy_datatype_number = vi + .spyOn(faker.datatype, 'number') + .mockReturnValue(today.getTime()); + + const date = faker.datatype.datetime(); + expect(today.valueOf()).toBe(date.valueOf()); + + spy_datatype_number.mockRestore(); + }); + + //generating a datetime with seeding is currently not working + }); + + describe('string', () => { + it('should generate a string value', () => { + const generatedString = faker.datatype.string(); + expect(typeof generatedString).toBe('string'); + expect(generatedString).toHaveLength(10); + }); + + it('should generate a string value, checks seeding', () => { + faker.seed(100); + const generatedString = faker.datatype.string(); + expect(generatedString).toBe('S_:GHQo.!/'); + }); + + it('returns empty string if negative length is passed', () => { + const negativeValue = faker.datatype.number({ min: -1000, max: -1 }); + const generatedString = faker.datatype.string(negativeValue); + expect(generatedString).toBe(''); + expect(generatedString).toHaveLength(0); + }); + + it('returns string with length of 2^20 if bigger length value is passed', () => { + const overMaxValue = Math.pow(2, 28); + const generatedString = faker.datatype.string(overMaxValue); + expect(generatedString).toHaveLength(Math.pow(2, 20)); + }); + }); + + describe('boolean', () => { + it('generates a boolean value', () => { + const bool = faker.datatype.boolean(); + expect(typeof bool).toBe('boolean'); + }); + it('generates a boolean value, checks seeding', () => { + faker.seed(1); + const bool = faker.datatype.boolean(); + expect(bool).toBe(false); + }); + }); + + describe('UUID', () => { + it('generates a valid UUID', () => { + const UUID = faker.datatype.uuid(); + const RFC4122 = + /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/; + expect(UUID).match(RFC4122); + }); + }); + + describe('hexaDecimal', () => { + const hexaDecimal = faker.datatype.hexaDecimal; + + it('generates single hex character when no additional argument was provided', () => { + const hex = hexaDecimal(); + expect(hex).match(/^(0x)[0-9a-f]{1}$/i); + }); + + it('generates a random hex string', () => { + const hex = hexaDecimal(5); + expect(hex).match(/^(0x)[0-9a-f]+$/i); + }); + }); + + describe('json', () => { + it('generates a valid json object', () => { + const jsonObject = faker.datatype.json(); + expect(typeof jsonObject).toBe('string'); + expect(JSON.parse(jsonObject)).toBeTruthy(); + }); + + it('generates a valid json object, with seeding', () => { + faker.seed(10); + const jsonObject = faker.datatype.json(); + const parsedObject = JSON.parse(jsonObject); + expect(typeof jsonObject).toBe('string'); + expect(parsedObject.foo).toBe('<"N[JfnOW5'); + expect(parsedObject.bar).toStrictEqual(19806); + expect(parsedObject.bike).toBe('g909).``yl'); + expect(parsedObject.a).toStrictEqual(33607); + expect(parsedObject.b).toBe('sl3Y#dr<dv'); + expect(parsedObject.name).toBe('c-SG.iCW_1'); + expect(parsedObject.prop).toStrictEqual(82608); + }); + }); + + describe('array', () => { + it('generates an array', () => { + // TODO @Shinigami92 2022-01-20: Currently this test seems to just do: + // => expect(typeof faker.datatype.array).toBe('function') + + const stubArray = [0, 1, 3, 4, 5, 6, 1, 'a', 'b', 'c']; + const spy_datatype_array = vi + .spyOn(faker.datatype, 'array') + .mockReturnValue(stubArray); + + const generatedArray = faker.datatype.array(); + + expect(generatedArray).toHaveLength(stubArray.length); + expect(stubArray).toStrictEqual(generatedArray); + + spy_datatype_array.mockRestore(); + }); + + it('generates an array with passed size', () => { + const randomSize = faker.datatype.number(); + const generatedArray = faker.datatype.array(randomSize); + expect(generatedArray).toHaveLength(randomSize); + }); + + it('generates an array with 1 element, with seeding', () => { + faker.seed(10); + const generatedArray = faker.datatype.array(1); + expect(generatedArray[0]).toBe('<"N[JfnOW5'); + }); + }); + + describe('bigInt', () => { + it('should generate a bigInt value', () => { + const generateBigInt = faker.datatype.bigInt(); + expect(typeof generateBigInt).toBe('bigint'); + }); + + it('Generate and compare two numbers of data type BigInt, with seeding', () => { + faker.seed(123); + const generateBigInt1 = faker.datatype.bigInt(); + faker.seed(123); + const generateBigInt2 = faker.datatype.bigInt(); + expect(generateBigInt1).toBe(generateBigInt2); + }); + + it('summing with the Number datatype should be an error', (done) => { + // TODO @Shinigami92 2022-01-20: Maybe we can remove this test, we should not test JS itself + try { + // @ts-expect-error + faker.datatype.bigInt() + 10; + } catch (error) { + done(); + } + }); + }); +}); diff --git a/test/datatype.unit.js b/test/datatype.unit.js deleted file mode 100644 index 3efa6b39..00000000 --- a/test/datatype.unit.js +++ /dev/null @@ -1,302 +0,0 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var sinon = require('sinon'); - var _ = require('lodash'); - var faker = require('../lib').faker; - var mersenne = require('../vendor/mersenne'); -} - -describe('datatype.js', function () { - describe('number', function () { - it('returns a random number given a maximum value as Number', function () { - var max = 10; - assert.ok(faker.datatype.number(max) <= max); - }); - - it('returns a random number given a maximum value as Object', function () { - var options = { max: 10 }; - assert.ok(faker.datatype.number(options) <= options.max); - }); - - it('returns a random number given a maximum value of 0', function () { - var options = { max: 0 }; - assert.ok(faker.datatype.number(options) === 0); - }); - - it('returns a random number given a negative number minimum and maximum value of 0', function () { - var options = { min: -100, max: 0 }; - assert.ok(faker.datatype.number(options) <= options.max); - }); - - it('returns a random number between a range', function () { - var options = { min: 22, max: 33 }; - for (var i = 0; i < 100; i++) { - var randomNumber = faker.datatype.number(options); - assert.ok(randomNumber >= options.min); - assert.ok(randomNumber <= options.max); - } - }); - - it('provides numbers with a given precision', function () { - var options = { min: 0, max: 1.5, precision: 0.5 }; - var results = _.chain(_.range(50)) - .map(function () { - return faker.datatype.number(options); - }) - .uniq() - .value() - .sort(); - - assert.ok(_.includes(results, 0.5)); - assert.ok(_.includes(results, 1.0)); - - assert.strictEqual(results[0], 0); - assert.strictEqual(_.last(results), 1.5); - }); - - it('provides numbers with a with exact precision', function () { - var options = { min: 0.5, max: 0.99, precision: 0.01 }; - for (var i = 0; i < 100; i++) { - var number = faker.datatype.number(options); - assert.strictEqual(number, Number(number.toFixed(2))); - } - }); - - it('should not modify the input object', function () { - var min = 1; - var max = 2; - var opts = { - min: min, - max: max, - }; - - faker.datatype.number(opts); - - assert.strictEqual(opts.min, min); - assert.strictEqual(opts.max, max); - }); - }); - - describe('float', function () { - it('returns a random float with a default precision value (0.01)', function () { - var number = faker.datatype.float(); - assert.strictEqual(number, Number(number.toFixed(2))); - }); - - it('returns a random float given a precision value', function () { - var number = faker.datatype.float(0.001); - assert.strictEqual(number, Number(number.toFixed(3))); - }); - - it('returns a random number given a maximum value as Object', function () { - var options = { max: 10 }; - assert.ok(faker.datatype.float(options) <= options.max); - }); - - it('returns a random number given a maximum value of 0', function () { - var options = { max: 0 }; - assert.ok(faker.datatype.float(options) === 0); - }); - - it('returns a random number given a negative number minimum and maximum value of 0', function () { - var options = { min: -100, max: 0 }; - assert.ok(faker.datatype.float(options) <= options.max); - }); - - it('returns a random number between a range', function () { - var options = { min: 22, max: 33 }; - for (var i = 0; i < 5; i++) { - var randomNumber = faker.datatype.float(options); - assert.ok(randomNumber >= options.min); - assert.ok(randomNumber <= options.max); - } - }); - - it('provides numbers with a given precision', function () { - var options = { min: 0, max: 1.5, precision: 0.5 }; - var results = _.chain(_.range(50)) - .map(function () { - return faker.datatype.float(options); - }) - .uniq() - .value() - .sort(); - - assert.ok(_.includes(results, 0.5)); - assert.ok(_.includes(results, 1.0)); - - assert.strictEqual(results[0], 0); - assert.strictEqual(_.last(results), 1.5); - }); - - it('provides numbers with a with exact precision', function () { - var options = { min: 0.5, max: 0.99, precision: 0.01 }; - for (var i = 0; i < 100; i++) { - var number = faker.datatype.float(options); - assert.strictEqual(number, Number(number.toFixed(2))); - } - }); - - it('should not modify the input object', function () { - var min = 1; - var max = 2; - var opts = { - min: min, - max: max, - }; - - faker.datatype.float(opts); - - assert.strictEqual(opts.min, min); - assert.strictEqual(opts.max, max); - }); - }); - - describe('datetime', function () { - it('check validity of date and if returned value is created by Date()', function () { - var date = faker.datatype.datetime(); - assert.strictEqual(typeof date, 'object'); - assert.ok(!isNaN(date.getTime())); - assert.strictEqual(Object.prototype.toString.call(date), '[object Date]'); - }); - it('basic test with stubbed value', function () { - var today = new Date(); - sinon.stub(faker.datatype, 'number').returns(today); - var date = faker.datatype.datetime(); - assert.strictEqual(today.valueOf(), date.valueOf()); - faker.datatype.number.restore(); - }); - - //generating a datetime with seeding is currently not working - }); - - describe('string', function () { - it('should generate a string value', function () { - var generateString = faker.datatype.string(); - assert.strictEqual(typeof generateString, 'string'); - assert.strictEqual(generateString.length, 10); - }); - - it('should generate a string value, checks seeding', function () { - faker.seed(100); - var generateString = faker.datatype.string(); - assert.strictEqual(generateString, 'S_:GHQo.!/'); - }); - - it('returns empty string if negative length is passed', function () { - var negativeValue = faker.datatype.number({ min: -1000, max: -1 }); - var generateString = faker.datatype.string(negativeValue); - assert.strictEqual(generateString, ''); - assert.strictEqual(generateString.length, 0); - }); - - it('returns string with length of 2^20 if bigger length value is passed', function () { - var overMaxValue = Math.pow(2, 28); - var generateString = faker.datatype.string(overMaxValue); - assert.strictEqual(generateString.length, Math.pow(2, 20)); - }); - }); - - describe('boolean', function () { - it('generates a boolean value', function () { - var bool = faker.datatype.boolean(); - assert.strictEqual(typeof bool, 'boolean'); - }); - it('generates a boolean value, checks seeding', function () { - faker.seed(1); - var bool = faker.datatype.boolean(); - assert.strictEqual(bool, false); - }); - }); - - describe('UUID', function () { - it('generates a valid UUID', function () { - var UUID = faker.datatype.uuid(); - var RFC4122 = - /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/; - assert.ok(RFC4122.test(UUID)); - }); - }); - - describe('hexaDecimal', function () { - var hexaDecimal = faker.datatype.hexaDecimal; - - it('generates single hex character when no additional argument was provided', function () { - var hex = hexaDecimal(); - assert.ok(hex.match(/^(0x)[0-9a-f]{1}$/i)); - }); - - it('generates a random hex string', function () { - var hex = hexaDecimal(5); - assert.ok(hex.match(/^(0x)[0-9a-f]+$/i)); - }); - }); - - describe('json', function () { - it('generates a valid json object', function () { - var jsonObject = faker.datatype.json(); - assert.strictEqual(typeof jsonObject, 'string'); - assert.ok(JSON.parse(jsonObject)); - }); - - it('generates a valid json object, with seeding', function () { - faker.seed(10); - var jsonObject = faker.datatype.json(); - var parsedObject = JSON.parse(jsonObject); - assert.strictEqual(typeof jsonObject, 'string'); - assert.strictEqual(parsedObject.foo, '<"N[JfnOW5'); - assert.strictEqual(parsedObject.bar, 19806); - assert.strictEqual(parsedObject.bike, 'g909).``yl'); - assert.strictEqual(parsedObject.a, 33607); - assert.strictEqual(parsedObject.b, 'sl3Y#dr<dv'); - assert.strictEqual(parsedObject.name, 'c-SG.iCW_1'); - assert.strictEqual(parsedObject.prop, 82608); - }); - }); - - describe('array', function () { - it('generates an array', function () { - var stubArray = [0, 1, 3, 4, 5, 6, 1, 'a', 'b', 'c']; - sinon.stub(faker.datatype, 'array').returns(stubArray); - var generatedArray = faker.datatype.array(); - assert.strictEqual(generatedArray.length, stubArray.length); - assert.strictEqual(stubArray, generatedArray); - faker.datatype.array.restore(); - }); - - it('generates an array with passed size', function () { - var randomSize = faker.datatype.number(); - var generatedArray = faker.datatype.array(randomSize); - assert.strictEqual(generatedArray.length, randomSize); - }); - - it('generates an array with 1 element, with seeding', function () { - faker.seed(10); - var generatedArray = faker.datatype.array(1); - assert.strictEqual(generatedArray[0], '<"N[JfnOW5'); - }); - }); - - describe('bigInt', function () { - it('should generate a bigInt value', function () { - var generateBigInt = faker.datatype.bigInt(); - assert.strictEqual(typeof generateBigInt, 'bigint'); - }); - - it('Generate and compare two numbers of data type BigInt, with seeding', function () { - faker.seed(123); - var generateBigInt1 = faker.datatype.bigInt(); - faker.seed(123); - var generateBigInt2 = faker.datatype.bigInt(); - assert.strictEqual(generateBigInt1, generateBigInt2); - }); - - it('summing with the Number datatype should be an error', function (done) { - try { - faker.datatype.bigInt() + 10; - } catch (error) { - done(); - } - }); - }); -}); diff --git a/test/date.spec.ts b/test/date.spec.ts new file mode 100644 index 00000000..8f7aa214 --- /dev/null +++ b/test/date.spec.ts @@ -0,0 +1,235 @@ +import { describe, expect, it } from 'vitest'; +import { faker } from '../lib'; + +describe('date', () => { + describe('past()', () => { + it('returns a date N years into the past', () => { + const date = faker.date.past(75); + expect(date).lessThan(new Date()); + }); + + it('returns a past date when N = 0', () => { + const refDate = new Date(); + const date = faker.date.past(0, refDate.toJSON()); + + expect(date).lessThan(refDate); // date should be before the date given + }); + + it('returns a date N years before the date given', () => { + const refDate = new Date(2120, 11, 9, 10, 0, 0, 0); // set the date beyond the usual calculation (to make sure this is working correctly) + + const date = faker.date.past(75, refDate.toJSON()); + + // date should be before date given but after the current time + expect(date).lessThan(refDate); + expect(date).greaterThan(new Date()); + }); + }); + + describe('future()', () => { + it('returns a date N years into the future', () => { + const date = faker.date.future(75); + + expect(date).greaterThan(new Date()); + }); + + it('returns a future date when N = 0', () => { + const refDate = new Date(); + const date = faker.date.future(0, refDate.toJSON()); + + expect(date).greaterThan(refDate); // date should be after the date given + }); + + it('returns a date N years after the date given', () => { + const refDate = new Date(1880, 11, 9, 10, 0, 0, 0); // set the date beyond the usual calculation (to make sure this is working correctly) + + const date = faker.date.future(75, refDate.toJSON()); + + // date should be after the date given, but before the current time + expect(date).greaterThan(refDate); + expect(date).lessThan(new Date()); + }); + }); + + describe('recent()', () => { + it('returns a date N days from the recent past', () => { + const date = faker.date.recent(30); + + expect(date).lessThanOrEqual(new Date()); + }); + + it('returns a date N days from the recent past, starting from refDate', () => { + const days = 30; + const refDate = new Date(2120, 11, 9, 10, 0, 0, 0); // set the date beyond the usual calculation (to make sure this is working correctly) + + const date = faker.date.recent( + days, + // @ts-expect-error + refDate + ); + + const lowerBound = new Date( + refDate.getTime() - days * 24 * 60 * 60 * 1000 + ); + + expect( + lowerBound, + '`recent()` date should not be further back than `n` days ago' + ).lessThanOrEqual(date); + expect( + date, + '`recent()` date should not be ahead of the starting date reference' + ).lessThanOrEqual(refDate); + }); + }); + + describe('soon()', () => { + it('returns a date N days into the future', () => { + const date = faker.date.soon(30); + + expect(date).greaterThanOrEqual(new Date()); + }); + + it('returns a date N days from the recent future, starting from refDate', () => { + const days = 30; + const refDate = new Date(1880, 11, 9, 10, 0, 0, 0); // set the date beyond the usual calculation (to make sure this is working correctly) + + const date = faker.date.soon( + days, + // @ts-expect-error + refDate + ); + + const upperBound = new Date( + refDate.getTime() + days * 24 * 60 * 60 * 1000 + ); + + expect( + date, + '`soon()` date should not be further ahead than `n` days ago' + ).lessThanOrEqual(upperBound); + expect( + refDate, + '`soon()` date should not be behind the starting date reference' + ).lessThanOrEqual(date); + }); + }); + + describe('between()', () => { + it('returns a random date between the dates given', () => { + const from = new Date(1990, 5, 7, 9, 11, 0, 0); + const to = new Date(2000, 6, 8, 10, 12, 0, 0); + + const date = faker.date.between( + //@ts-expect-error + from, + to + ); + + expect(date).greaterThan(from); + expect(date).lessThan(to); + }); + }); + + describe('betweens()', () => { + it('returns an array of 3 dates ( by default ) of sorted randoms dates between the dates given', () => { + const from = new Date(1990, 5, 7, 9, 11, 0, 0); + const to = new Date(2000, 6, 8, 10, 12, 0, 0); + + const dates = faker.date.betweens( + // @ts-expect-error + from, + to + ); + + expect(dates[0]).greaterThan(from); + expect(dates[0]).lessThan(to); + expect(dates[1]).greaterThan(dates[0]); + expect(dates[2]).greaterThan(dates[1]); + }); + }); + + describe('month()', () => { + it('returns random value from date.month.wide array by default', () => { + const month = faker.date.month(); + expect(faker.definitions.date.month.wide).toContain(month); + }); + + it('returns random value from date.month.wide_context array for context option', () => { + const month = faker.date.month({ context: true }); + expect(faker.definitions.date.month.wide_context).toContain(month); + }); + + it('returns random value from date.month.abbr array for abbr option', () => { + const month = faker.date.month({ abbr: true }); + expect(faker.definitions.date.month.abbr).toContain(month); + }); + + it('returns random value from date.month.abbr_context array for abbr and context option', () => { + const month = faker.date.month({ abbr: true, context: true }); + expect(faker.definitions.date.month.abbr_context).toContain(month); + }); + + it('returns random value from date.month.wide array for context option when date.month.wide_context array is missing', () => { + const backup_wide_context = faker.definitions.date.month.wide_context; + faker.definitions.date.month.wide_context = undefined; + + const month = faker.date.month({ context: true }); + expect(faker.definitions.date.month.wide).toContain(month); + + faker.definitions.date.month.wide_context = backup_wide_context; + }); + + it('returns random value from date.month.abbr array for abbr and context option when date.month.abbr_context array is missing', () => { + const backup_abbr_context = faker.definitions.date.month.abbr_context; + faker.definitions.date.month.abbr_context = undefined; + + const month = faker.date.month({ abbr: true, context: true }); + expect(faker.definitions.date.month.abbr).toContain(month); + + faker.definitions.date.month.abbr_context = backup_abbr_context; + }); + }); + + describe('weekday()', () => { + it('returns random value from date.weekday.wide array by default', () => { + const weekday = faker.date.weekday(); + expect(faker.definitions.date.weekday.wide).toContain(weekday); + }); + + it('returns random value from date.weekday.wide_context array for context option', () => { + const weekday = faker.date.weekday({ context: true }); + expect(faker.definitions.date.weekday.wide_context).toContain(weekday); + }); + + it('returns random value from date.weekday.abbr array for abbr option', () => { + const weekday = faker.date.weekday({ abbr: true }); + expect(faker.definitions.date.weekday.abbr).toContain(weekday); + }); + + it('returns random value from date.weekday.abbr_context array for abbr and context option', () => { + const weekday = faker.date.weekday({ abbr: true, context: true }); + expect(faker.definitions.date.weekday.abbr_context).toContain(weekday); + }); + + it('returns random value from date.weekday.wide array for context option when date.weekday.wide_context array is missing', () => { + const backup_wide_context = faker.definitions.date.weekday.wide_context; + faker.definitions.date.weekday.wide_context = undefined; + + const weekday = faker.date.weekday({ context: true }); + expect(faker.definitions.date.weekday.wide).toContain(weekday); + + faker.definitions.date.weekday.wide_context = backup_wide_context; + }); + + it('returns random value from date.weekday.abbr array for abbr and context option when date.weekday.abbr_context array is missing', () => { + const backup_abbr_context = faker.definitions.date.weekday.abbr_context; + faker.definitions.date.weekday.abbr_context = undefined; + + const weekday = faker.date.weekday({ abbr: true, context: true }); + expect(faker.definitions.date.weekday.abbr).toContain(weekday); + + faker.definitions.date.weekday.abbr_context = backup_abbr_context; + }); + }); +}); diff --git a/test/date.unit.js b/test/date.unit.js deleted file mode 100644 index 88bbcac3..00000000 --- a/test/date.unit.js +++ /dev/null @@ -1,219 +0,0 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var sinon = require('sinon'); - var faker = require('../lib').faker; -} - -describe('date.js', function () { - describe('past()', function () { - it('returns a date N years into the past', function () { - var date = faker.date.past(75); - assert.ok(date < new Date()); - }); - - it('returns a past date when N = 0', function () { - var refDate = new Date(); - var date = faker.date.past(0, refDate.toJSON()); - - assert.ok(date < refDate); // date should be before the date given - }); - - it('returns a date N years before the date given', function () { - var refDate = new Date(2120, 11, 9, 10, 0, 0, 0); // set the date beyond the usual calculation (to make sure this is working correctly) - - var date = faker.date.past(75, refDate.toJSON()); - - assert.ok(date < refDate && date > new Date()); // date should be before date given but after the current time - }); - }); - - describe('future()', function () { - it('returns a date N years into the future', function () { - var date = faker.date.future(75); - - assert.ok(date > new Date()); - }); - - it('returns a future date when N = 0', function () { - var refDate = new Date(); - var date = faker.date.future(0, refDate.toJSON()); - - assert.ok(date > refDate); // date should be after the date given - }); - - it('returns a date N years after the date given', function () { - var refDate = new Date(1880, 11, 9, 10, 0, 0, 0); // set the date beyond the usual calculation (to make sure this is working correctly) - - var date = faker.date.future(75, refDate.toJSON()); - - assert.ok(date > refDate && date < new Date()); // date should be after the date given, but before the current time - }); - }); - - describe('recent()', function () { - it('returns a date N days from the recent past', function () { - var date = faker.date.recent(30); - - assert.ok(date <= new Date()); - }); - - it('returns a date N days from the recent past, starting from refDate', function () { - var days = 30; - var refDate = new Date(2120, 11, 9, 10, 0, 0, 0); // set the date beyond the usual calculation (to make sure this is working correctly) - - var date = faker.date.recent(days, refDate); - - var lowerBound = new Date(refDate.getTime() - days * 24 * 60 * 60 * 1000); - - assert.ok( - lowerBound <= date, - '`recent()` date should not be further back than `n` days ago' - ); - assert.ok( - date <= refDate, - '`recent()` date should not be ahead of the starting date reference' - ); - }); - }); - - describe('soon()', function () { - it('returns a date N days into the future', function () { - var date = faker.date.soon(30); - - assert.ok(date >= new Date()); - }); - - it('returns a date N days from the recent future, starting from refDate', function () { - var days = 30; - var refDate = new Date(1880, 11, 9, 10, 0, 0, 0); // set the date beyond the usual calculation (to make sure this is working correctly) - - var date = faker.date.soon(days, refDate); - - var upperBound = new Date(refDate.getTime() + days * 24 * 60 * 60 * 1000); - - assert.ok( - date <= upperBound, - '`soon()` date should not be further ahead than `n` days ago' - ); - assert.ok( - refDate <= date, - '`soon()` date should not be behind the starting date reference' - ); - }); - }); - - describe('between()', function () { - it('returns a random date between the dates given', function () { - var from = new Date(1990, 5, 7, 9, 11, 0, 0); - var to = new Date(2000, 6, 8, 10, 12, 0, 0); - - var date = faker.date.between(from, to); - - assert.ok(date > from && date < to); - }); - }); - - describe('betweens()', function () { - it('returns an array of 3 dates ( by default ) of sorted randoms dates between the dates given', function () { - var from = new Date(1990, 5, 7, 9, 11, 0, 0); - var to = new Date(2000, 6, 8, 10, 12, 0, 0); - - var dates = faker.date.betweens(from, to); - - assert.ok(dates[0] > from && dates[0] < to); - assert.ok(dates[1] > dates[0] && dates[2] > dates[1]); - }); - }); - - describe('month()', function () { - it('returns random value from date.month.wide array by default', function () { - var month = faker.date.month(); - assert.ok(faker.definitions.date.month.wide.indexOf(month) !== -1); - }); - - it('returns random value from date.month.wide_context array for context option', function () { - var month = faker.date.month({ context: true }); - assert.ok( - faker.definitions.date.month.wide_context.indexOf(month) !== -1 - ); - }); - - it('returns random value from date.month.abbr array for abbr option', function () { - var month = faker.date.month({ abbr: true }); - assert.ok(faker.definitions.date.month.abbr.indexOf(month) !== -1); - }); - - it('returns random value from date.month.abbr_context array for abbr and context option', function () { - var month = faker.date.month({ abbr: true, context: true }); - assert.ok( - faker.definitions.date.month.abbr_context.indexOf(month) !== -1 - ); - }); - - it('returns random value from date.month.wide array for context option when date.month.wide_context array is missing', function () { - var backup_wide_context = faker.definitions.date.month.wide_context; - faker.definitions.date.month.wide_context = undefined; - - var month = faker.date.month({ context: true }); - assert.ok(faker.definitions.date.month.wide.indexOf(month) !== -1); - - faker.definitions.date.month.wide_context = backup_wide_context; - }); - - it('returns random value from date.month.abbr array for abbr and context option when date.month.abbr_context array is missing', function () { - var backup_abbr_context = faker.definitions.date.month.abbr_context; - faker.definitions.date.month.abbr_context = undefined; - - var month = faker.date.month({ abbr: true, context: true }); - assert.ok(faker.definitions.date.month.abbr.indexOf(month) !== -1); - - faker.definitions.date.month.abbr_context = backup_abbr_context; - }); - }); - - describe('weekday()', function () { - it('returns random value from date.weekday.wide array by default', function () { - var weekday = faker.date.weekday(); - assert.ok(faker.definitions.date.weekday.wide.indexOf(weekday) !== -1); - }); - - it('returns random value from date.weekday.wide_context array for context option', function () { - var weekday = faker.date.weekday({ context: true }); - assert.ok( - faker.definitions.date.weekday.wide_context.indexOf(weekday) !== -1 - ); - }); - - it('returns random value from date.weekday.abbr array for abbr option', function () { - var weekday = faker.date.weekday({ abbr: true }); - assert.ok(faker.definitions.date.weekday.abbr.indexOf(weekday) !== -1); - }); - - it('returns random value from date.weekday.abbr_context array for abbr and context option', function () { - var weekday = faker.date.weekday({ abbr: true, context: true }); - assert.ok( - faker.definitions.date.weekday.abbr_context.indexOf(weekday) !== -1 - ); - }); - - it('returns random value from date.weekday.wide array for context option when date.weekday.wide_context array is missing', function () { - var backup_wide_context = faker.definitions.date.weekday.wide_context; - faker.definitions.date.weekday.wide_context = undefined; - - var weekday = faker.date.weekday({ context: true }); - assert.ok(faker.definitions.date.weekday.wide.indexOf(weekday) !== -1); - - faker.definitions.date.weekday.wide_context = backup_wide_context; - }); - - it('returns random value from date.weekday.abbr array for abbr and context option when date.weekday.abbr_context array is missing', function () { - var backup_abbr_context = faker.definitions.date.weekday.abbr_context; - faker.definitions.date.weekday.abbr_context = undefined; - - var weekday = faker.date.weekday({ abbr: true, context: true }); - assert.ok(faker.definitions.date.weekday.abbr.indexOf(weekday) !== -1); - - faker.definitions.date.weekday.abbr_context = backup_abbr_context; - }); - }); -}); diff --git a/test/fake.spec.ts b/test/fake.spec.ts new file mode 100644 index 00000000..6e04a3a1 --- /dev/null +++ b/test/fake.spec.ts @@ -0,0 +1,50 @@ +import { describe, expect, it } from 'vitest'; +import { faker } from '../lib'; + +describe('fake', () => { + describe('fake()', () => { + it('replaces a token with a random value for a method with no parameters', () => { + const name = faker.fake('{{phone.phoneNumber}}'); + expect(name).match(/\d/); + }); + + it('replaces multiple tokens with random values for methods with no parameters', () => { + const name = faker.fake( + '{{helpers.randomize}}{{helpers.randomize}}{{helpers.randomize}}' + ); + expect(name).match(/[abc]{3}/); + }); + + it('replaces a token with a random value for a methods with a simple parameter', () => { + const random = faker.fake('{{helpers.slugify("Will This Work")}}'); + expect(random).toBe('Will-This-Work'); + }); + + it('replaces a token with a random value for a method with an array parameter', () => { + const arr = ['one', 'two', 'three']; + const random = faker.fake( + '{{helpers.randomize(["one", "two", "three"])}}' + ); + expect(arr).toContain(random); + }); + + it('does not allow undefined parameters', () => { + expect(() => + // @ts-expect-error + faker.fake() + ).toThrowError(Error('string parameter is required!')); + }); + + it('does not allow invalid module name', () => { + expect(() => faker.fake('{{foo.bar}}')).toThrowError( + Error('Invalid module: foo') + ); + }); + + it('does not allow invalid method name', () => { + expect(() => faker.fake('{{address.foo}}')).toThrowError( + Error('Invalid method: address.foo') + ); + }); + }); +}); diff --git a/test/fake.unit.js b/test/fake.unit.js deleted file mode 100644 index 75741e61..00000000 --- a/test/fake.unit.js +++ /dev/null @@ -1,51 +0,0 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var sinon = require('sinon'); - var faker = require('../lib').faker; -} - -describe('fake.js', function () { - describe('fake()', function () { - it('replaces a token with a random value for a method with no parameters', function () { - var name = faker.fake('{{phone.phoneNumber}}'); - assert.ok(name.match(/\d/)); - }); - - it('replaces multiple tokens with random values for methods with no parameters', function () { - var name = faker.fake( - '{{helpers.randomize}}{{helpers.randomize}}{{helpers.randomize}}' - ); - assert.ok(name.match(/[abc]{3}/)); - }); - - it('replaces a token with a random value for a methods with a simple parameter', function () { - var arr = ['one', 'two', 'three']; - var random = faker.fake('{{helpers.slugify("Will This Work")}}'); - assert.ok(random === 'Will-This-Work'); - }); - - it('replaces a token with a random value for a method with an array parameter', function () { - var arr = ['one', 'two', 'three']; - var random = faker.fake('{{helpers.randomize(["one", "two", "three"])}}'); - assert.ok(arr.indexOf(random) > -1); - }); - - it('does not allow undefined parameters', function () { - assert.throws(function () { - faker.fake(); - }, Error); - }); - - it('does not allow invalid module name', function () { - assert.throws(function () { - faker.fake('{{foo.bar}}'); - }, Error); - }); - - it('does not allow invalid method name', function () { - assert.throws(function () { - faker.fake('{{address.foo}}'); - }, Error); - }); - }); -}); diff --git a/test/finance.spec.ts b/test/finance.spec.ts new file mode 100644 index 00000000..fb6b7f87 --- /dev/null +++ b/test/finance.spec.ts @@ -0,0 +1,462 @@ +import type { JestMockCompat } from 'vitest'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { faker } from '../lib'; +import { luhnCheck } from './support/luhnCheck'; + +faker.seed(1234); + +describe('finance', () => { + describe('account( length )', () => { + it('should supply a default length if no length is passed', () => { + const account = faker.finance.account(); + + const expected = 8; + const actual = account.length; + + expect( + actual, + 'The expected default account length is ' + + expected + + ' but it was ' + + actual + ).toBe(expected); + }); + + it('should supply a length if a length is passed', () => { + const expected = 9; + + const account = faker.finance.account(expected); + + const actual = account.length; + + expect( + actual, + 'The expected default account length is ' + + expected + + ' but it was ' + + actual + ).toBe(expected); + }); + + it('should supply a default length if a zero is passed', () => { + const expected = 8; + + const account = faker.finance.account(0); + + const actual = account.length; + + expect( + actual, + 'The expected default account length is ' + + expected + + ' but it was ' + + actual + ).toBe(expected); + }); + }); + + describe('accountName()', () => { + it('should return an account name', () => { + const actual = faker.finance.accountName(); + + expect(actual).toBeTruthy(); + }); + }); + + describe('routingNumber()', () => { + it('should return a routing number', () => { + const actual = faker.finance.routingNumber(); + + expect(actual).toBeTruthy(); + }); + }); + + describe('mask( length, parens, ellipsis )', () => { + it('should set a default length', () => { + const expected = 4; //default account mask length + + const mask = faker.finance.mask(null, false, false); + + const actual = mask.length; + + expect( + actual, + 'The expected default mask length is ' + + expected + + ' but it was ' + + actual + ).toBe(expected); + }); + + it('should set a specified length', () => { + let expected = faker.datatype.number(20); + + expected = + expected === 0 || !expected || typeof expected == 'undefined' + ? 4 + : expected; + + const mask = faker.finance.mask(expected, false, false); + + const actual = mask.length; //picks 4 if the random number generator picks 0 + + expect( + actual, + 'The expected default mask length is ' + + expected + + ' but it was ' + + actual + ).toBe(expected); + }); + + it('should set a default length of 4 for a zero value', () => { + const expected = 4; + + faker.finance.mask(0, false, false); + + const actual = 4; //picks 4 if the random number generator picks 0 + + expect( + actual, + 'The expected default mask length is ' + + expected + + ' but it was ' + + actual + ).toBe(expected); + }); + + it('should by default include parentheses around a partial account number', () => { + const expected = true; + + const mask = faker.finance.mask(null, null, false); + + const regexp = new RegExp(/(\(\d{4}?\))/); + const actual = regexp.test(mask); + + expect( + actual, + 'The expected match for parentheses is ' + + expected + + ' but it was ' + + actual + ).toBe(expected); + }); + + it('should by default include an ellipsis', () => { + const expected = true; + + const mask = faker.finance.mask(null, false, null); + + const regexp = new RegExp(/(\.\.\.\d{4})/); + const actual = regexp.test(mask); + + expect( + actual, + 'The expected match for parentheses is ' + + expected + + ' but it was ' + + actual + ).toBe(expected); + }); + + it('should work when random variables are passed into the arguments', () => { + const length = faker.datatype.number(20); + const ellipsis = length % 2 === 0 ? true : false; + const parens = !ellipsis; + + const mask = faker.finance.mask(length, ellipsis, parens); + expect(mask).toBeTruthy(); + }); + }); + + describe('amount(min, max, dec, symbol)', () => { + it('should use the default amounts when not passing arguments', () => { + const amount = faker.finance.amount(); + + expect(amount).toBeTruthy(); + expect(+amount, 'the amount should be greater than 0').greaterThan(0); + expect(+amount, 'the amount should be less than 1001').lessThan(1001); + }); + + it('should use the default decimal location when not passing arguments', () => { + let amount = faker.finance.amount(); + + amount = faker.finance.amount(100, 100, 1); + + expect(amount).toBeTruthy(); + expect(amount, 'the amount should be equal 100.0').toStrictEqual('100.0'); + }); + + //TODO: add support for more currency and decimal options + it('should not include a currency symbol by default', () => { + const amount = faker.finance.amount(); + + expect( + amount, + 'The expected match should not include a currency symbol' + ).match(/[0-9.]/); + }); + + it('it should handle negative amounts', () => { + const amount = faker.finance.amount(-200, -1); + + expect(amount).toBeTruthy(); + expect(+amount, 'the amount should be less than 0').lessThan(0); + expect(+amount, 'the amount should be greater than -201').greaterThan( + -201 + ); + }); + + it('it should handle argument dec', () => { + const amount = faker.finance.amount(100, 100, 1); + + expect(amount).toBeTruthy(); + expect(amount, 'the amount should be equal 100.0').toStrictEqual('100.0'); + }); + + it('it should handle argument dec = 0', () => { + const amount = faker.finance.amount(100, 100, 0); + + expect(amount).toBeTruthy(); + expect(amount, 'the amount should be equal 100').toStrictEqual('100'); + }); + + it('it should return a string', () => { + const amount = faker.finance.amount(100, 100, 0); + + expect(amount).toBeTruthy(); + expect(typeof amount, 'the amount type should be string').toBe('string'); + }); + + [false, undefined].forEach((autoFormat) => { + it(`should return unformatted if autoformat is ${autoFormat}`, () => { + const number = 6000; + const amount = faker.finance.amount( + number, + number, + 0, + undefined, + autoFormat + ); + + expect(amount).toStrictEqual(number.toString()); + }); + }); + + it('should return the number formatted on the current locale', () => { + const number = 6000; + const decimalPlaces = 2; + const expected = number.toLocaleString(undefined, { + minimumFractionDigits: decimalPlaces, + }); + + const amount = faker.finance.amount( + number, + number, + decimalPlaces, + undefined, + true + ); + + expect(amount).toStrictEqual(expected); + }); + }); + + describe('transactionType()', () => { + it('should return a random transaction type', () => { + const transactionType = faker.finance.transactionType(); + + expect(transactionType).toBeTruthy(); + }); + }); + + describe('currencyCode()', () => { + it('returns a random currency code with a format', () => { + const currencyCode = faker.finance.currencyCode(); + + expect(currencyCode).match(/^[A-Z]{3}$/); + }); + }); + + describe('bitcoinAddress()', () => { + it('returns a random bitcoin address', () => { + const bitcoinAddress = faker.finance.bitcoinAddress(); + + /** + * Note: Although the total length of a Bitcoin address can be 25-33 characters, regex quantifiers only check the preceding token + * Therefore we take one from the total length of the address not including the first character ([13]) + */ + + expect(bitcoinAddress).match(/^[13][a-km-zA-HJ-NP-Z1-9]{24,33}$/); + }); + }); + + describe('litecoinAddress()', () => { + it('returns a random litecoin address', () => { + const litecoinAddress = faker.finance.litecoinAddress(); + + expect(litecoinAddress).match(/^[LM3][1-9a-km-zA-HJ-NP-Z]{25,32}$/); + }); + }); + + describe('ethereumAddress()', () => { + it('returns a random ethereum address', () => { + const ethereumAddress = faker.finance.ethereumAddress(); + expect(ethereumAddress).match(/^(0x)[0-9a-f]{40}$/); + }); + }); + + describe('creditCardNumber()', () => { + it('returns a random credit card number', () => { + let number = faker.finance.creditCardNumber(); + number = number.replace(/\D/g, ''); // remove formating + console.log('version:', process.version, number, number.length); + expect(number.length).greaterThanOrEqual(13); + expect(number.length).lessThanOrEqual(20); + expect(number).match(/^[0-9]{13,20}$/); + expect(luhnCheck(number)).toBeTruthy(); + }); + + it('returns a valid credit card number', () => { + expect(luhnCheck(faker.finance.creditCardNumber(''))).toBeTruthy(); + expect(luhnCheck(faker.finance.creditCardNumber())).toBeTruthy(); + expect(luhnCheck(faker.finance.creditCardNumber())).toBeTruthy(); + expect(luhnCheck(faker.finance.creditCardNumber('visa'))).toBeTruthy(); + expect( + luhnCheck(faker.finance.creditCardNumber('mastercard')) + ).toBeTruthy(); + expect( + luhnCheck(faker.finance.creditCardNumber('discover')) + ).toBeTruthy(); + expect(luhnCheck(faker.finance.creditCardNumber())).toBeTruthy(); + expect(luhnCheck(faker.finance.creditCardNumber())).toBeTruthy(); + }); + it('returns a correct credit card number when issuer provided', () => { + //TODO: implement checks for each format with regexp + const visa = faker.finance.creditCardNumber('visa'); + expect(visa).match(/^4(([0-9]){12}|([0-9]){3}(\-([0-9]){4}){3})$/); + expect(luhnCheck(visa)).toBeTruthy(); + + const mastercard = faker.finance.creditCardNumber('mastercard'); + expect(mastercard).match(/^(5[1-5]\d{2}|6771)(\-\d{4}){3}$/); + expect(luhnCheck(mastercard)).toBeTruthy(); + + const discover = faker.finance.creditCardNumber('discover'); + + expect(luhnCheck(discover)).toBeTruthy(); + + const american_express = + faker.finance.creditCardNumber('american_express'); + expect(luhnCheck(american_express)).toBeTruthy(); + const diners_club = faker.finance.creditCardNumber('diners_club'); + expect(luhnCheck(diners_club)).toBeTruthy(); + const jcb = faker.finance.creditCardNumber('jcb'); + expect(luhnCheck(jcb)).toBeTruthy(); + const switchC = faker.finance.creditCardNumber('mastercard'); + expect(luhnCheck(switchC)).toBeTruthy(); + const solo = faker.finance.creditCardNumber('solo'); + expect(luhnCheck(solo)).toBeTruthy(); + const maestro = faker.finance.creditCardNumber('maestro'); + expect(luhnCheck(maestro)).toBeTruthy(); + const laser = faker.finance.creditCardNumber('laser'); + expect(luhnCheck(laser)).toBeTruthy(); + const instapayment = faker.finance.creditCardNumber('instapayment'); + expect(luhnCheck(instapayment)).toBeTruthy(); + }); + it('returns custom formated strings', () => { + let number = faker.finance.creditCardNumber('###-###-##L'); + expect(number).match(/^\d{3}\-\d{3}\-\d{3}$/); + expect(luhnCheck(number)).toBeTruthy(); + + number = faker.finance.creditCardNumber('234[5-9]#{999}L'); + expect(number).match(/^234[5-9]\d{1000}$/); + expect(luhnCheck(number)).toBeTruthy(); + }); + }); + + describe('creditCardCVV()', () => { + it('returns a random credit card CVV', () => { + const cvv = faker.finance.creditCardCVV(); + expect(cvv).toHaveLength(3); + expect(cvv).match(/^[0-9]{3}$/); + }); + }); + + describe('iban()', () => { + const ibanLib = require('../lib/iban').default; + it('returns a random yet formally correct IBAN number', () => { + const iban = + // @ts-expect-error + faker.finance.iban(); + const bban = iban.substring(4) + iban.substring(0, 4); + + expect( + ibanLib.mod97(ibanLib.toDigitString(bban)), + 'the result should be equal to 1' + ).toStrictEqual(1); + }); + it('returns a specific and formally correct IBAN number', () => { + const iban = faker.finance.iban(false, 'DE'); + const bban = iban.substring(4) + iban.substring(0, 4); + const countryCode = iban.substring(0, 2); + + expect(countryCode).toBe('DE'); + expect( + ibanLib.mod97(ibanLib.toDigitString(bban)), + 'the result should be equal to 1' + ).toStrictEqual(1); + }); + it('throws an error if the passed country code is not supported', () => { + expect(() => faker.finance.iban(false, 'AA')).toThrowError( + Error('Country code AA not supported.') + ); + }); + }); + + describe('bic()', () => { + const ibanLib = require('../lib/iban').default; + it('returns a random yet formally correct BIC number', () => { + const bic = faker.finance.bic(); + const expr = new RegExp( + '^[A-Z]{4}(' + + ibanLib.iso3166.join('|') + + ')[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3})?$', + 'i' + ); + + expect(bic).match(expr); + }); + }); + + describe('transactionDescription()', () => { + let spy_helpers_createTransaction: JestMockCompat< + [], + { + amount: string; + date: Date; + business: string; + name: string; + type: string; + account: string; + } + >; + + beforeEach(() => { + spy_helpers_createTransaction = vi.spyOn( + faker.helpers, + 'createTransaction' + ); + }); + + afterEach(() => { + spy_helpers_createTransaction.mockRestore(); + }); + + it('returns a random transaction description', () => { + const transactionDescription = faker.finance.transactionDescription(); + + expect(transactionDescription).toBeTruthy(); + expect(spy_helpers_createTransaction).toHaveBeenCalledOnce(); + }); + }); +}); diff --git a/test/finance.unit.js b/test/finance.unit.js deleted file mode 100644 index fc5fd2d1..00000000 --- a/test/finance.unit.js +++ /dev/null @@ -1,482 +0,0 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var sinon = require('sinon'); - var faker = require('../lib').faker; -} - -faker.seed(1234); - -describe('finance.js', function () { - describe('account( length )', function () { - it('should supply a default length if no length is passed', function () { - var account = faker.finance.account(); - - var expected = 8; - var actual = account.length; - - assert.strictEqual( - actual, - expected, - 'The expected default account length is ' + - expected + - ' but it was ' + - actual - ); - }); - - it('should supply a length if a length is passed', function () { - var expected = 9; - - var account = faker.finance.account(expected); - - var actual = account.length; - - assert.strictEqual( - actual, - expected, - 'The expected default account length is ' + - expected + - ' but it was ' + - actual - ); - }); - - it('should supply a default length if a zero is passed', function () { - var expected = 8; - - var account = faker.finance.account(0); - - var actual = account.length; - - assert.strictEqual( - actual, - expected, - 'The expected default account length is ' + - expected + - ' but it was ' + - actual - ); - }); - }); - - describe('accountName()', function () { - it('should return an account name', function () { - var actual = faker.finance.accountName(); - - assert.ok(actual); - }); - }); - - describe('routingNumber()', function () { - it('should return a routing number', function () { - var actual = faker.finance.routingNumber(); - - assert.ok(actual); - }); - }); - - describe('mask( length, parens, ellipsis )', function () { - it('should set a default length', function () { - var expected = 4; //default account mask length - - var mask = faker.finance.mask(null, false, false); - - var actual = mask.length; - - assert.strictEqual( - actual, - expected, - 'The expected default mask length is ' + - expected + - ' but it was ' + - actual - ); - }); - - it('should set a specified length', function () { - var expected = faker.datatype.number(20); - - expected = - expected == 0 || !expected || typeof expected == 'undefined' - ? 4 - : expected; - - var mask = faker.finance.mask(expected, false, false); - - var actual = mask.length; //picks 4 if the random number generator picks 0 - - assert.strictEqual( - actual, - expected, - 'The expected default mask length is ' + - expected + - ' but it was ' + - actual - ); - }); - - it('should set a default length of 4 for a zero value', function () { - var expected = 4; - - faker.finance.mask(0, false, false); - - var actual = 4; //picks 4 if the random number generator picks 0 - - assert.strictEqual( - actual, - expected, - 'The expected default mask length is ' + - expected + - ' but it was ' + - actual - ); - }); - - it('should by default include parentheses around a partial account number', function () { - var expected = true; - - var mask = faker.finance.mask(null, null, false); - - var regexp = new RegExp(/(\(\d{4}?\))/); - var actual = regexp.test(mask); - - assert.strictEqual( - actual, - expected, - 'The expected match for parentheses is ' + - expected + - ' but it was ' + - actual - ); - }); - - it('should by default include an ellipsis', function () { - var expected = true; - - var mask = faker.finance.mask(null, false, null); - - var regexp = new RegExp(/(\.\.\.\d{4})/); - var actual = regexp.test(mask); - - assert.strictEqual( - actual, - expected, - 'The expected match for parentheses is ' + - expected + - ' but it was ' + - actual - ); - }); - - it('should work when random variables are passed into the arguments', function () { - var length = faker.datatype.number(20); - var ellipsis = length % 2 === 0 ? true : false; - var parens = !ellipsis; - - var mask = faker.finance.mask(length, ellipsis, parens); - assert.ok(mask); - }); - }); - - describe('amount(min, max, dec, symbol)', function () { - it('should use the default amounts when not passing arguments', function () { - var amount = faker.finance.amount(); - - assert.ok(amount); - assert.strictEqual( - amount > 0, - true, - 'the amount should be greater than 0' - ); - assert.strictEqual( - amount < 1001, - true, - 'the amount should be greater than 0' - ); - }); - - it('should use the default decimal location when not passing arguments', function () { - var amount = faker.finance.amount(); - - var decimal = '.'; - var expected = amount.length - 3; - var amount = faker.finance.amount(100, 100, 1); - - assert.ok(amount); - assert.strictEqual(amount, '100.0', 'the amount should be equal 100.0'); - }); - - //TODO: add support for more currency and decimal options - it('should not include a currency symbol by default', function () { - var amount = faker.finance.amount(); - - var regexp = new RegExp(/[0-9.]/); - - var expected = true; - var actual = regexp.test(amount); - - assert.strictEqual( - actual, - expected, - 'The expected match should not include a currency symbol' - ); - }); - - it('it should handle negative amounts', function () { - var amount = faker.finance.amount(-200, -1); - - assert.ok(amount); - assert.strictEqual( - amount < 0, - true, - 'the amount should be greater than 0' - ); - assert.strictEqual( - amount > -201, - true, - 'the amount should be greater than 0' - ); - }); - - it('it should handle argument dec', function () { - var amount = faker.finance.amount(100, 100, 1); - - assert.ok(amount); - assert.strictEqual(amount, '100.0', 'the amount should be equal 100.0'); - }); - - it('it should handle argument dec = 0', function () { - var amount = faker.finance.amount(100, 100, 0); - - assert.ok(amount); - assert.strictEqual(amount, '100', 'the amount should be equal 100'); - }); - - it('it should return a string', function () { - var amount = faker.finance.amount(100, 100, 0); - - var typeOfAmount = typeof amount; - - assert.ok(amount); - assert.strictEqual( - typeOfAmount, - 'string', - 'the amount type should be number' - ); - }); - - [false, undefined].forEach(function (autoFormat) { - it(`should return unformatted if autoformat is ${autoFormat}`, function () { - const number = 6000; - const amount = faker.finance.amount( - number, - number, - 0, - undefined, - autoFormat - ); - - assert.strictEqual(amount, number.toString()); - }); - }); - - // TODO @Shinigami92 2022-01-18: See https://github.com/faker-js/faker/pull/179 - if (require('os').platform() !== 'win32') { - it('should return the number formatted on the current locale', function () { - const number = 6000, - decimalPlaces = 2; - const expected = number.toLocaleString(undefined, { - minimumFractionDigits: decimalPlaces, - }); - - const amount = faker.finance.amount( - number, - number, - decimalPlaces, - undefined, - true - ); - - assert.strictEqual(amount, expected); - }); - } - }); - - describe('transactionType()', function () { - it('should return a random transaction type', function () { - var transactionType = faker.finance.transactionType(); - - assert.ok(transactionType); - }); - }); - - describe('currencyCode()', function () { - it('returns a random currency code with a format', function () { - var currencyCode = faker.finance.currencyCode(); - - assert.ok(currencyCode.match(/^[A-Z]{3}$/)); - }); - }); - - describe('bitcoinAddress()', function () { - it('returns a random bitcoin address', function () { - var bitcoinAddress = faker.finance.bitcoinAddress(); - - /** - * Note: Although the total length of a Bitcoin address can be 25-33 characters, regex quantifiers only check the preceding token - * Therefore we take one from the total length of the address not including the first character ([13]) - */ - - assert.ok(bitcoinAddress.match(/^[13][a-km-zA-HJ-NP-Z1-9]{24,33}$/)); - }); - }); - - describe('litecoinAddress()', function () { - it('returns a random litecoin address', function () { - var litecoinAddress = faker.finance.litecoinAddress(); - - assert.ok(litecoinAddress.match(/^[LM3][1-9a-km-zA-HJ-NP-Z]{25,32}$/)); - }); - }); - - describe('ethereumAddress()', function () { - it('returns a random ethereum address', function () { - var ethereumAddress = faker.finance.ethereumAddress(); - assert.ok(ethereumAddress.match(/^(0x)[0-9a-f]{40}$/)); - }); - }); - - describe('creditCardNumber()', function () { - var luhnFormula = require('./support/luhnCheck.js'); - - it('returns a random credit card number', function () { - var number = faker.finance.creditCardNumber(); - number = number.replace(/\D/g, ''); // remove formating - console.log('version:', process.version, number, number.length); - assert.ok(number.length >= 13 && number.length <= 20); - assert.ok(number.match(/^[0-9]{13,20}$/)); - assert.ok(luhnFormula(number)); - }); - - it('returns a valid credit card number', function () { - assert.ok(luhnFormula(faker.finance.creditCardNumber(''))); - assert.ok(luhnFormula(faker.finance.creditCardNumber())); - assert.ok(luhnFormula(faker.finance.creditCardNumber())); - assert.ok(luhnFormula(faker.finance.creditCardNumber('visa'))); - assert.ok(luhnFormula(faker.finance.creditCardNumber('mastercard'))); - assert.ok(luhnFormula(faker.finance.creditCardNumber('discover'))); - assert.ok(luhnFormula(faker.finance.creditCardNumber())); - assert.ok(luhnFormula(faker.finance.creditCardNumber())); - }); - it('returns a correct credit card number when issuer provided', function () { - //TODO: implement checks for each format with regexp - var visa = faker.finance.creditCardNumber('visa'); - assert.ok(visa.match(/^4(([0-9]){12}|([0-9]){3}(\-([0-9]){4}){3})$/)); - assert.ok(luhnFormula(visa)); - - var mastercard = faker.finance.creditCardNumber('mastercard'); - assert.ok(mastercard.match(/^(5[1-5]\d{2}|6771)(\-\d{4}){3}$/)); - assert.ok(luhnFormula(mastercard)); - - var discover = faker.finance.creditCardNumber('discover'); - - assert.ok(luhnFormula(discover)); - - var american_express = faker.finance.creditCardNumber('american_express'); - assert.ok(luhnFormula(american_express)); - var diners_club = faker.finance.creditCardNumber('diners_club'); - assert.ok(luhnFormula(diners_club)); - var jcb = faker.finance.creditCardNumber('jcb'); - assert.ok(luhnFormula(jcb)); - var switchC = faker.finance.creditCardNumber('mastercard'); - assert.ok(luhnFormula(switchC)); - var solo = faker.finance.creditCardNumber('solo'); - assert.ok(luhnFormula(solo)); - var maestro = faker.finance.creditCardNumber('maestro'); - assert.ok(luhnFormula(maestro)); - var laser = faker.finance.creditCardNumber('laser'); - assert.ok(luhnFormula(laser)); - var instapayment = faker.finance.creditCardNumber('instapayment'); - assert.ok(luhnFormula(instapayment)); - }); - it('returns custom formated strings', function () { - var number = faker.finance.creditCardNumber('###-###-##L'); - assert.ok(number.match(/^\d{3}\-\d{3}\-\d{3}$/)); - assert.ok(luhnFormula(number)); - number = faker.finance.creditCardNumber('234[5-9]#{999}L'); - assert.ok(number.match(/^234[5-9]\d{1000}$/)); - assert.ok(luhnFormula(number)); - }); - }); - - describe('creditCardCVV()', function () { - it('returns a random credit card CVV', function () { - var cvv = faker.finance.creditCardCVV(); - assert.ok(cvv.length === 3); - assert.ok(cvv.match(/^[0-9]{3}$/)); - }); - }); - - describe('iban()', function () { - var ibanLib = require('../lib/iban').default; - it('returns a random yet formally correct IBAN number', function () { - var iban = faker.finance.iban(); - var bban = iban.substring(4) + iban.substring(0, 4); - - assert.strictEqual( - ibanLib.mod97(ibanLib.toDigitString(bban)), - 1, - 'the result should be equal to 1' - ); - }); - it('returns a specific and formally correct IBAN number', function () { - var iban = faker.finance.iban(false, 'DE'); - var bban = iban.substring(4) + iban.substring(0, 4); - var countryCode = iban.substring(0, 2); - - assert.equal(countryCode, 'DE'); - assert.equal( - ibanLib.mod97(ibanLib.toDigitString(bban)), - 1, - 'the result should be equal to 1' - ); - }); - it('throws an error if the passed country code is not supported', function () { - assert.throws(function () { - faker.finance.iban(false, 'AA'); - }, /Country code AA not supported/); - }); - }); - - describe('bic()', function () { - var ibanLib = require('../lib/iban').default; - it('returns a random yet formally correct BIC number', function () { - var bic = faker.finance.bic(); - var expr = new RegExp( - '^[A-Z]{4}(' + - ibanLib.iso3166.join('|') + - ')[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3})?$', - 'i' - ); - - assert.ok(bic.match(expr)); - }); - }); - - describe('transactionDescription()', function () { - beforeEach(function () { - sinon.spy(faker.helpers, 'createTransaction'); - }); - - afterEach(function () { - faker.helpers.createTransaction.restore(); - }); - - it('returns a random transaction description', function () { - var transactionDescription = faker.finance.transactionDescription(); - - assert.ok(transactionDescription); - assert.ok(faker.helpers.createTransaction.calledOnce); - }); - }); -}); diff --git a/test/finance_iban.unit.js b/test/finance_iban.spec.ts index df3141ed..0a1f9e23 100644 --- a/test/finance_iban.unit.js +++ b/test/finance_iban.spec.ts @@ -1,15 +1,19 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var faker = require('../lib').faker; -} +import { expect } from 'vitest'; +import { describe, it } from 'vitest'; +import { faker } from '../lib'; +import ibanLib from '../lib/iban'; function getAnIbanByCountry(countryCode) { - var iban = faker.finance.iban(); - var maxTry = 100000; - var countTry = maxTry; - while (countTry && iban.substring(0, 2) != countryCode) { + let iban = + // @ts-expect-error + faker.finance.iban(); + const maxTry = 100000; + let countTry = maxTry; + while (countTry && iban.substring(0, 2) !== countryCode) { faker.seed(100000 - countTry); - iban = faker.finance.iban(); + iban = + // @ts-expect-error + faker.finance.iban(); countTry--; } @@ -27,8 +31,8 @@ function getAnIbanByCountry(countryCode) { return iban; } -describe('finance_iban.js', function () { - describe('issue_944 IBAN Georgia', function () { +describe('finance_iban.js', () => { + describe('issue_944 IBAN Georgia', () => { // Georgia // https://transferwise.com/fr/iban/georgia // Length 22 @@ -39,54 +43,50 @@ describe('finance_iban.js', function () { // example IBAN GE29 NB00 0000 0101 9049 17 - var ibanLib = require('../lib/iban').default; - - it('IBAN for Georgia is correct', function () { + it('IBAN for Georgia is correct', () => { faker.seed(17); - var iban = getAnIbanByCountry('GE'); - var ibanFormated = iban.match(/.{1,4}/g).join(' '); - var bban = iban.substring(4) + iban.substring(0, 4); + const iban = getAnIbanByCountry('GE'); + const ibanFormated = iban.match(/.{1,4}/g).join(' '); + const bban = iban.substring(4) + iban.substring(0, 4); - assert.equal( + expect( 22, - iban.length, 'GE IBAN would be 22 chars length, given is ' + iban.length - ); + ).toBe(iban.length); - assert.ok( - iban.substring(0, 2).match(/^[A-Z]{2}$/), + expect( + iban.substring(0, 2), iban.substring(0, 2) + ' must contains only characters in GE IBAN ' + ibanFormated - ); - assert.ok( - iban.substring(2, 4).match(/^\d{2}$/), + ).match(/^[A-Z]{2}$/); + expect( + iban.substring(2, 4), iban.substring(2, 4) + ' must contains only digit in GE IBAN ' + ibanFormated - ); - assert.ok( - iban.substring(4, 6).match(/^[A-Z]{2}$/), + ).match(/^\d{2}$/); + expect( + iban.substring(4, 6), iban.substring(4, 6) + ' must contains only characters in GE IBAN ' + ibanFormated - ); - assert.ok( - iban.substring(6, 24).match(/^\d{16}$/), + ).match(/^[A-Z]{2}$/); + expect( + iban.substring(6, 24), iban.substring(6, 24) + ' must contains only characters in GE IBAN ' + ibanFormated - ); + ).match(/^\d{16}$/); - assert.equal( + expect( ibanLib.mod97(ibanLib.toDigitString(bban)), - 1, 'the result should be equal to 1' - ); + ).toBe(1); }); }); - describe('issue_945 IBAN Pakistan', function () { + describe('issue_945 IBAN Pakistan', () => { // https://transferwise.com/fr/iban/pakistan // Example IBAN Pakistan // PK36SCBL0000001123456702 @@ -99,54 +99,52 @@ describe('finance_iban.js', function () { // Account Code 16 digits // Total Length 24 chars - var ibanLib = require('../lib/iban').default; + const ibanLib = require('../lib/iban').default; - it('IBAN for Pakistan is correct', function () { + it('IBAN for Pakistan is correct', () => { faker.seed(28); - var iban = getAnIbanByCountry('PK'); - var ibanFormated = iban.match(/.{1,4}/g).join(' '); - var bban = iban.substring(4) + iban.substring(0, 4); + const iban = getAnIbanByCountry('PK'); + const ibanFormated = iban.match(/.{1,4}/g).join(' '); + const bban = iban.substring(4) + iban.substring(0, 4); - assert.equal( + expect( 24, - iban.length, 'PK IBAN would be 24 chars length, given is ' + iban.length - ); + ).toBe(iban.length); - assert.ok( - iban.substring(0, 2).match(/^[A-Z]{2}$/), + expect( + iban.substring(0, 2), iban.substring(0, 2) + ' must contains only characters in PK IBAN ' + ibanFormated - ); - assert.ok( - iban.substring(2, 4).match(/^\d{2}$/), + ).match(/^[A-Z]{2}$/); + expect( + iban.substring(2, 4), iban.substring(2, 4) + ' must contains only digit in PK IBAN ' + ibanFormated - ); - assert.ok( - iban.substring(4, 8).match(/^[A-Z]{4}$/), + ).match(/^\d{2}$/); + expect( + iban.substring(4, 8), iban.substring(4, 8) + ' must contains only characters in PK IBAN ' + ibanFormated - ); - assert.ok( - iban.substring(8, 24).match(/^\d{16}$/), + ).match(/^[A-Z]{4}$/); + expect( + iban.substring(8, 24), iban.substring(8, 24) + ' must contains only digits in PK IBAN ' + ibanFormated - ); + ).match(/^\d{16}$/); - assert.equal( + expect( ibanLib.mod97(ibanLib.toDigitString(bban)), - 1, 'the result should be equal to 1' - ); + ).toBe(1); }); }); - describe('issue_946 IBAN Turkish', function () { + describe('issue_946 IBAN Turkish', () => { // https://transferwise.com/fr/iban/turkey // Un IBAN en Turquie est constitué de 26 caractères : // @@ -165,71 +163,69 @@ describe('finance_iban.js', function () { // Chiffre d'indicatif national 0 // Numéro de compte bancaire 0519786457841326 - var ibanLib = require('../lib/iban').default; + const ibanLib = require('../lib/iban').default; - it('IBAN for Turkish is correct', function () { + it('IBAN for Turkish is correct', () => { faker.seed(37); - var iban = getAnIbanByCountry('TR'); - var ibanFormated = iban.match(/.{1,4}/g).join(' '); - var bban = iban.substring(4) + iban.substring(0, 4); + const iban = getAnIbanByCountry('TR'); + const ibanFormated = iban.match(/.{1,4}/g).join(' '); + const bban = iban.substring(4) + iban.substring(0, 4); - assert.equal( + expect( 26, - iban.length, 'PK IBAN would be 26 chars length, given is ' + iban.length - ); + ).toBe(iban.length); - assert.ok( - iban.substring(0, 2).match(/^[A-Z]{2}$/), + expect( + iban.substring(0, 2), 'Country Code:' + iban.substring(0, 2) + ' must contains only characters in PK IBAN ' + ibanFormated - ); - assert.ok( - iban.substring(2, 4).match(/^\d{2}$/), + ).match(/^[A-Z]{2}$/); + expect( + iban.substring(2, 4), 'Control key:' + iban.substring(2, 4) + ' must contains only digit in PK IBAN ' + ibanFormated - ); - assert.ok( - iban.substring(4, 9).match(/^\d{5}$/), + ).match(/^\d{2}$/); + expect( + iban.substring(4, 9), 'Swift Bank Code:' + iban.substring(4, 9) + ' must contains only digits in PK IBAN ' + ibanFormated - ); - assert.ok( - iban.substring(9, 10).match(/^\d{1}$/), + ).match(/^\d{5}$/); + expect( + iban.substring(9, 10), 'National Digit:' + iban.substring(9, 10) + ' must contains only digits in PK IBAN ' + ibanFormated - ); - assert.ok( - iban.substring(10, 26).match(/^\d{16}$/), + ).match(/^\d{1}$/); + expect( + iban.substring(10, 26), 'Account Code:' + iban.substring(10, 26) + ' must contains only digits in PK IBAN ' + ibanFormated - ); + ).match(/^\d{16}$/); - assert.ok( - iban.substring(2, 26).match(/^\d{24}$/), + expect( + iban.substring(2, 26), 'No character after TR ' + ibanFormated - ); + ).match(/^\d{24}$/); - assert.equal( + expect( ibanLib.mod97(ibanLib.toDigitString(bban)), - 1, 'the result should be equal to 1' - ); + ).toBe(1); }); }); - describe('issue_846 IBAN Azerbaijan', function () { + describe('issue_846 IBAN Azerbaijan', () => { // Azerbaijan // https://transferwise.com/fr/iban/azerbaijan // Length 28 @@ -240,50 +236,48 @@ describe('finance_iban.js', function () { // example IBAN AZ21 NABZ 0000 0000 1370 1000 1944 - var ibanLib = require('../lib/iban').default; + const ibanLib = require('../lib/iban').default; - it('IBAN for Azerbaijan is correct', function () { + it('IBAN for Azerbaijan is correct', () => { faker.seed(21); - var iban = getAnIbanByCountry('AZ'); - var ibanFormated = iban.match(/.{1,4}/g).join(' '); - var bban = iban.substring(4) + iban.substring(0, 4); + const iban = getAnIbanByCountry('AZ'); + const ibanFormated = iban.match(/.{1,4}/g).join(' '); + const bban = iban.substring(4) + iban.substring(0, 4); - assert.equal( + expect( 28, - iban.length, 'AZ IBAN would be 28 chars length, given is ' + iban.length - ); + ).toBe(iban.length); - assert.ok( - iban.substring(0, 2).match(/^[A-Z]{2}$/), + expect( + iban.substring(0, 2), iban.substring(0, 2) + ' must contains only characters in AZ IBAN ' + ibanFormated - ); - assert.ok( - iban.substring(2, 4).match(/^\d{2}$/), + ).match(/^[A-Z]{2}$/); + expect( + iban.substring(2, 4), iban.substring(2, 4) + ' must contains only digit in AZ IBAN ' + ibanFormated - ); - assert.ok( - iban.substring(4, 8).match(/^[A-Z]{4}$/), + ).match(/^\d{2}$/); + expect( + iban.substring(4, 8), iban.substring(4, 8) + ' must contains only characters in AZ IBAN ' + ibanFormated - ); - assert.ok( - iban.substring(8, 28).match(/^\d{20}$/), + ).match(/^[A-Z]{4}$/); + expect( + iban.substring(8, 28), iban.substring(8, 28) + ' must contains 20 characters in AZ IBAN ' + ibanFormated - ); + ).match(/^\d{20}$/); - assert.equal( + expect( ibanLib.mod97(ibanLib.toDigitString(bban)), - 1, 'the result should be equal to 1' - ); + ).toBe(1); }); }); }); diff --git a/test/git.spec.ts b/test/git.spec.ts new file mode 100644 index 00000000..f8c776f2 --- /dev/null +++ b/test/git.spec.ts @@ -0,0 +1,152 @@ +import type { JestMockCompat } from 'vitest'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { faker } from '../lib'; + +describe('git.js', () => { + describe('branch()', () => { + let spy_hacker_noun: JestMockCompat<[], string>; + let spy_hacker_verb: JestMockCompat<[], string>; + + beforeEach(() => { + spy_hacker_noun = vi.spyOn(faker.hacker, 'noun'); + spy_hacker_verb = vi.spyOn(faker.hacker, 'verb'); + }); + + afterEach(() => { + spy_hacker_noun.mockRestore(); + spy_hacker_verb.mockRestore(); + }); + + it('returns a branch with hacker noun and verb', () => { + faker.git.branch(); + + expect(spy_hacker_noun).toHaveBeenCalledOnce(); + expect(spy_hacker_verb).toHaveBeenCalledOnce(); + }); + }); + + describe('commitEntry()', () => { + let spy_git_commitMessage: JestMockCompat<[], string>; + let spy_git_commitSha: JestMockCompat<[], string>; + let spy_internet_email: JestMockCompat< + [firstName?: string, lastName?: string, provider?: string], + string + >; + let spy_name_firstName: JestMockCompat<[gender?: string | number], string>; + let spy_name_lastName: JestMockCompat<[gender?: string | number], string>; + let spy_datatype_number: JestMockCompat< + [ + options?: + | number + | { + min?: number; + max?: number; + precision?: number; + } + ], + number + >; + + beforeEach(() => { + spy_git_commitMessage = vi.spyOn(faker.git, 'commitMessage'); + spy_git_commitSha = vi.spyOn(faker.git, 'commitSha'); + spy_internet_email = vi.spyOn(faker.internet, 'email'); + spy_name_firstName = vi.spyOn(faker.name, 'firstName'); + spy_name_lastName = vi.spyOn(faker.name, 'lastName'); + spy_datatype_number = vi.spyOn(faker.datatype, 'number'); + }); + + afterEach(() => { + spy_git_commitMessage.mockRestore(); + spy_git_commitSha.mockRestore(); + spy_internet_email.mockRestore(); + spy_name_firstName.mockRestore(); + spy_name_lastName.mockRestore(); + spy_datatype_number.mockRestore(); + }); + + it('returns merge entry at random', () => { + faker.git.commitEntry(); + + expect(spy_datatype_number).toHaveBeenCalled(); + }); + + it('returns a commit entry with git commit message and sha', () => { + faker.git.commitEntry(); + + expect(spy_git_commitMessage).toHaveBeenCalledOnce(); + expect(spy_git_commitSha).toHaveBeenCalledOnce(); + }); + + it('returns a commit entry with internet email', () => { + faker.git.commitEntry(); + + expect(spy_internet_email).toHaveBeenCalledOnce(); + }); + + it('returns a commit entry with name first and last', () => { + faker.git.commitEntry(); + + expect(spy_name_firstName).toHaveBeenCalledTimes(2); + expect(spy_name_lastName).toHaveBeenCalledTimes(2); + }); + + describe("with options['merge'] equal to true", () => { + let spy_git_shortSha: JestMockCompat<[], string>; + + beforeEach(() => { + spy_git_shortSha = vi.spyOn(faker.git, 'shortSha'); + }); + + afterEach(() => { + spy_git_shortSha.mockRestore(); + }); + + it('returns a commit entry with merge details', () => { + faker.git.commitEntry({ merge: true }); + + expect(spy_git_shortSha).toHaveBeenCalledTimes(2); + }); + }); + }); + + describe('commitMessage()', () => { + let spy_hacker_verb: JestMockCompat<[], string>; + let spy_hacker_adjective: JestMockCompat<[], string>; + let spy_hacker_noun: JestMockCompat<[], string>; + + beforeEach(() => { + spy_hacker_verb = vi.spyOn(faker.hacker, 'verb'); + spy_hacker_adjective = vi.spyOn(faker.hacker, 'adjective'); + spy_hacker_noun = vi.spyOn(faker.hacker, 'noun'); + }); + + afterEach(() => { + spy_hacker_verb.mockRestore(); + spy_hacker_adjective.mockRestore(); + spy_hacker_noun.mockRestore(); + }); + + it('returns a commit message with hacker noun, adj and verb', () => { + faker.git.commitMessage(); + + expect(spy_hacker_verb).toHaveBeenCalledOnce(); + expect(spy_hacker_adjective).toHaveBeenCalledOnce(); + expect(spy_hacker_noun).toHaveBeenCalledOnce(); + }); + }); + + describe('commitSha()', () => { + it('returns a random commit SHA', () => { + const commitSha = faker.git.commitSha(); + expect(commitSha).match(/^[a-f0-9]{40}$/); + }); + }); + + describe('shortSha()', () => { + it('returns a random short SHA', () => { + const shortSha = faker.git.shortSha(); + expect(shortSha).match(/^[a-f0-9]{7}$/); + }); + }); +}); diff --git a/test/git.unit.js b/test/git.unit.js deleted file mode 100644 index e5603bef..00000000 --- a/test/git.unit.js +++ /dev/null @@ -1,124 +0,0 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var sinon = require('sinon'); - var faker = require('../lib').faker; -} - -describe('git.js', function () { - describe('branch()', function () { - beforeEach(function () { - sinon.spy(faker.hacker, 'noun'); - sinon.spy(faker.hacker, 'verb'); - }); - - afterEach(function () { - faker.hacker.noun.restore(); - faker.hacker.verb.restore(); - }); - - it('returns a branch with hacker noun and verb', function () { - faker.git.branch(); - - assert.ok(faker.hacker.noun.calledOnce); - assert.ok(faker.hacker.verb.calledOnce); - }); - }); - - describe('commitEntry()', function () { - beforeEach(function () { - sinon.spy(faker.git, 'commitMessage'); - sinon.spy(faker.git, 'commitSha'); - sinon.spy(faker.internet, 'email'); - sinon.spy(faker.name, 'firstName'); - sinon.spy(faker.name, 'lastName'); - sinon.spy(faker.datatype, 'number'); - }); - - afterEach(function () { - faker.git.commitMessage.restore(); - faker.git.commitSha.restore(); - faker.internet.email.restore(); - faker.name.firstName.restore(); - faker.name.lastName.restore(); - faker.datatype.number.restore(); - }); - - it('returns merge entry at random', function () { - faker.git.commitEntry(); - - assert.ok(faker.datatype.number.called); - }); - - it('returns a commit entry with git commit message and sha', function () { - faker.git.commitEntry(); - - assert.ok(faker.git.commitMessage.calledOnce); - assert.ok(faker.git.commitSha.calledOnce); - }); - - it('returns a commit entry with internet email', function () { - faker.git.commitEntry(); - - assert.ok(faker.internet.email.calledOnce); - }); - - it('returns a commit entry with name first and last', function () { - faker.git.commitEntry(); - - assert.ok(faker.name.firstName.calledTwice); - assert.ok(faker.name.lastName.calledTwice); - }); - - context("with options['merge'] equal to true", function () { - beforeEach(function () { - sinon.spy(faker.git, 'shortSha'); - }); - - afterEach(function () { - faker.git.shortSha.restore(); - }); - - it('returns a commit entry with merge details', function () { - faker.git.commitEntry({ merge: true }); - - assert.ok(faker.git.shortSha.calledTwice); - }); - }); - }); - - describe('commitMessage()', function () { - beforeEach(function () { - sinon.spy(faker.hacker, 'verb'); - sinon.spy(faker.hacker, 'adjective'); - sinon.spy(faker.hacker, 'noun'); - }); - - afterEach(function () { - faker.hacker.verb.restore(); - faker.hacker.adjective.restore(); - faker.hacker.noun.restore(); - }); - - it('returns a commit message with hacker noun, adj and verb', function () { - faker.git.commitMessage(); - - assert.ok(faker.hacker.verb.calledOnce); - assert.ok(faker.hacker.adjective.calledOnce); - assert.ok(faker.hacker.noun.calledOnce); - }); - }); - - describe('commitSha()', function () { - it('returns a random commit SHA', function () { - var commitSha = faker.git.commitSha(); - assert.ok(commitSha.match(/^[a-f0-9]{40}$/)); - }); - }); - - describe('shortSha()', function () { - it('returns a random short SHA', function () { - var shortSha = faker.git.shortSha(); - assert.ok(shortSha.match(/^[a-f0-9]{7}$/)); - }); - }); -}); diff --git a/test/helpers.spec.ts b/test/helpers.spec.ts new file mode 100644 index 00000000..65e040dc --- /dev/null +++ b/test/helpers.spec.ts @@ -0,0 +1,289 @@ +import { describe, expect, it, vi } from 'vitest'; +import { faker } from '../lib'; +import { luhnCheck } from './support/luhnCheck'; + +describe('helpers.js', () => { + describe('replaceSymbolWithNumber()', () => { + describe('when no symbol passed in', () => { + it("uses '#' by default", () => { + const num = faker.helpers.replaceSymbolWithNumber('#AB'); + expect(num).match(/\dAB/); + }); + }); + + describe('when symbol passed in', () => { + it('replaces that symbol with integers', () => { + const num = faker.helpers.replaceSymbolWithNumber('#AB', 'A'); + expect(num).match(/#\dB/); + }); + }); + }); + + describe('replaceSymbols()', () => { + describe("when '*' passed", () => { + it('replaces it with alphanumeric', () => { + const num = faker.helpers.replaceSymbols('*AB'); + expect(num).match(/\wAB/); + }); + }); + }); + + describe('shuffle()', () => { + it('the output is the same length as the input', () => { + const spy_datatype_number = vi.spyOn(faker.datatype, 'number'); + + const shuffled = faker.helpers.shuffle(['a', 'b']); + + expect(shuffled).toHaveLength(2); + expect(spy_datatype_number).toHaveBeenCalledWith(1); + + spy_datatype_number.mockRestore(); + }); + + it('empty array returns empty array', () => { + const shuffled = faker.helpers.shuffle([]); + expect(shuffled).toHaveLength(0); + }); + + it('mutates the input array in place', () => { + const input = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']; + const shuffled = faker.helpers.shuffle(input); + expect(shuffled).deep.eq(input); + }); + + it('all items shuffled as expected when seeded', () => { + const input = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']; + faker.seed(100); + const shuffled = faker.helpers.shuffle(input); + expect(shuffled).deep.eq([ + 'b', + 'e', + 'a', + 'd', + 'j', + 'i', + 'h', + 'c', + 'g', + 'f', + ]); + }); + }); + + describe('uniqueArray()', () => { + it('custom array returns unique array', () => { + const input = ['a', 'a', 'a', 'a,', 'a', 'a', 'a', 'a', 'b']; + const length = 2; + const unique = faker.helpers.uniqueArray(input, length); + expect(unique).toHaveLength(length); + expect(new Set(unique).size).toBe(length); + }); + + it('definition array returns unique array', () => { + const length = faker.datatype.number({ min: 1, max: 6 }); + const unique = faker.helpers.uniqueArray( + faker.definitions.hacker.noun, + length + ); + 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).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); + }); + + 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).toHaveLength(input.length); + expect(new Set(unique).size).toBe(input.length); + }); + + it('works as expected when seeded', () => { + const input = ['a', 'a', 'a', 'a', 'a', 'f', 'g', 'h', 'i', 'j']; + const length = 5; + faker.seed(100); + const unique = faker.helpers.uniqueArray(input, length); + expect(unique).deep.eq(['g', 'a', 'i', 'f', 'j']); + }); + }); + + describe('slugify()', () => { + it('removes unwanted characters from URI string', () => { + expect(faker.helpers.slugify('Aiden.Harªann')).toBe('Aiden.Harann'); + expect(faker.helpers.slugify("d'angelo.net")).toBe('dangelo.net'); + }); + }); + + describe('mustache()', () => { + it('returns empty string with no arguments', () => { + expect( + // @ts-expect-error + faker.helpers.mustache() + ).toBe(''); + }); + }); + + describe('repeatString()', () => { + it('returns empty string with no arguments', () => { + expect( + // @ts-expect-error + faker.helpers.repeatString() + ).toBe(''); + }); + }); + + describe('replaceSymbols()', () => { + it('returns empty string with no arguments', () => { + expect(faker.helpers.replaceSymbols()).toBe(''); + }); + }); + + /* + describe("replaceCreditCardSymbols()", () =>{ + it("returns empty string with no arguments", () =>{ + assert.equal(faker.helpers.replaceCreditCardSymbols(), ""); + }); + }); + */ + + describe('createCard()', () => { + it('returns an object', () => { + const card = faker.helpers.createCard(); + expect(typeof card).toBe('object'); + }); + }); + + describe('contextualCard()', () => { + it('returns an object', () => { + const card = faker.helpers.contextualCard(); + expect(typeof card).toBe('object'); + }); + }); + + describe('userCard()', () => { + it('returns an object', () => { + const card = faker.helpers.userCard(); + expect(typeof card).toBe('object'); + }); + }); + + // Make sure we keep this function for backward-compatibility. + describe('randomize()', () => { + it('returns a random element from an array', () => { + const arr = ['a', 'b', 'c']; + const elem = faker.helpers.randomize(arr); + expect(elem).toBeTruthy(); + expect(arr).toContain(elem); + }); + }); + + describe('replaceCreditCardSymbols()', () => { + it('returns a credit card number given a schema', () => { + const number = faker.helpers.replaceCreditCardSymbols( + '6453-####-####-####-###L' + ); + expect(number).match( + /^6453\-([0-9]){4}\-([0-9]){4}\-([0-9]){4}\-([0-9]){4}$/ + ); + expect(luhnCheck(number)).toBeTruthy(); + }); + it('supports different symbols', () => { + const number = faker.helpers.replaceCreditCardSymbols( + '6453-****-****-****-***L', + '*' + ); + expect(number).match( + /^6453\-([0-9]){4}\-([0-9]){4}\-([0-9]){4}\-([0-9]){4}$/ + ); + expect(luhnCheck(number)).toBeTruthy(); + }); + it('handles regexp style input', () => { + let number = faker.helpers.replaceCreditCardSymbols( + '6453-*{4}-*{4}-*{4}-*{3}L', + '*' + ); + expect(number).match( + /^6453\-([0-9]){4}\-([0-9]){4}\-([0-9]){4}\-([0-9]){4}$/ + ); + expect(luhnCheck(number)).toBeTruthy(); + number = faker.helpers.replaceCreditCardSymbols( + '645[5-9]-#{4,6}-#{1,2}-#{4,6}-#{3}L' + ); + expect(number).match( + /^645[5-9]\-([0-9]){4,6}\-([0-9]){1,2}\-([0-9]){4,6}\-([0-9]){4}$/ + ); + expect(luhnCheck(number)).toBeTruthy(); + }); + }); + + describe('regexpStyleStringParse()', () => { + it('returns an empty string when called without param', () => { + expect(faker.helpers.regexpStyleStringParse()).toBe(''); + }); + + it('deals with range repeat', () => { + const string = faker.helpers.regexpStyleStringParse('#{5,10}'); + expect(string.length).lessThanOrEqual(10); + expect(string.length).greaterThanOrEqual(5); + expect(string).match(/^\#{5,10}$/); + }); + + it('flips the range when min > max', () => { + const string = faker.helpers.regexpStyleStringParse('#{10,5}'); + expect(string.length).lessThanOrEqual(10); + expect(string.length).greaterThanOrEqual(5); + expect(string).match(/^\#{5,10}$/); + }); + + it('repeats string {n} number of times', () => { + expect(faker.helpers.regexpStyleStringParse('%{10}')).toBe( + faker.helpers.repeatString('%', 10) + ); + expect(faker.helpers.regexpStyleStringParse('%{30}')).toBe( + faker.helpers.repeatString('%', 30) + ); + expect(faker.helpers.regexpStyleStringParse('%{5}')).toBe( + faker.helpers.repeatString('%', 5) + ); + }); + + it('creates a numerical range', () => { + const string = faker.helpers.regexpStyleStringParse('Hello[0-9]'); + expect(string).match(/^Hello[0-9]$/); + }); + + it('deals with multiple tokens in one string', () => { + const string = faker.helpers.regexpStyleStringParse( + 'Test#{5}%{2,5}Testing**[1-5]**{10}END' + ); + expect(string).match(/^Test\#{5}%{2,5}Testing\*\*[1-5]\*\*{10}END$/); + }); + }); + + describe('createTransaction()', () => { + it('should create a random transaction', () => { + const transaction = faker.helpers.createTransaction(); + expect(transaction).toBeTruthy(); + expect(transaction.amount).toBeTruthy(); + expect(transaction.date).toBeTruthy(); + expect(transaction.business).toBeTruthy(); + expect(transaction.name).toBeTruthy(); + expect(transaction.type).toBeTruthy(); + expect(transaction.account).toBeTruthy(); + }); + }); +}); diff --git a/test/helpers.unit.js b/test/helpers.unit.js deleted file mode 100644 index b25daa22..00000000 --- a/test/helpers.unit.js +++ /dev/null @@ -1,284 +0,0 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var sinon = require('sinon'); - var faker = require('../lib').faker; -} - -describe('helpers.js', function () { - describe('replaceSymbolWithNumber()', function () { - context('when no symbol passed in', function () { - it("uses '#' by default", function () { - var num = faker.helpers.replaceSymbolWithNumber('#AB'); - assert.ok(num.match(/\dAB/)); - }); - }); - - context('when symbol passed in', function () { - it('replaces that symbol with integers', function () { - var num = faker.helpers.replaceSymbolWithNumber('#AB', 'A'); - assert.ok(num.match(/#\dB/)); - }); - }); - }); - - describe('replaceSymbols()', function () { - context("when '*' passed", function () { - it('replaces it with alphanumeric', function () { - var num = faker.helpers.replaceSymbols('*AB'); - assert.ok(num.match(/\wAB/)); - }); - }); - }); - - describe('shuffle()', function () { - it('the output is the same length as the input', function () { - sinon.spy(faker.datatype, 'number'); - var shuffled = faker.helpers.shuffle(['a', 'b']); - assert.ok(shuffled.length === 2); - assert.ok(faker.datatype.number.calledWith(1)); - faker.datatype.number.restore(); - }); - - it('empty array returns empty array', function () { - var shuffled = faker.helpers.shuffle([]); - assert.ok(shuffled.length === 0); - }); - - it('mutates the input array in place', function () { - var input = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']; - var shuffled = faker.helpers.shuffle(input); - assert.deepStrictEqual(shuffled, input); - }); - - it('all items shuffled as expected when seeded', function () { - var input = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']; - faker.seed(100); - var shuffled = faker.helpers.shuffle(input); - assert.deepStrictEqual(shuffled, [ - 'b', - 'e', - 'a', - 'd', - 'j', - 'i', - 'h', - 'c', - 'g', - 'f', - ]); - }); - }); - - describe('uniqueArray()', function () { - it('custom array returns unique array', function () { - var input = ['a', 'a', 'a', 'a,', 'a', 'a', 'a', 'a', 'b']; - var length = 2; - var unique = faker.helpers.uniqueArray(input, length); - assert.strictEqual(unique.length, length); - assert.strictEqual(new Set(unique).size, length); - }); - - it('definition array returns unique array', function () { - var length = faker.datatype.number({ min: 1, max: 6 }); - var unique = faker.helpers.uniqueArray( - faker.definitions.hacker.noun, - length - ); - assert.strictEqual(unique.length, length); - assert.strictEqual(new Set(unique).size, length); - }); - - it('function returns unique array', function () { - var length = faker.datatype.number({ min: 1, max: 6 }); - var unique = faker.helpers.uniqueArray(faker.lorem.word, length); - assert.strictEqual(unique.length, length); - assert.strictEqual(new Set(unique).size, length); - }); - - it('empty array returns empty array', function () { - var input = []; - var length = faker.datatype.number({ min: 1, max: 6 }); - var unique = faker.helpers.uniqueArray(input, length); - assert.strictEqual(unique.length, input.length); - assert.strictEqual(new Set(unique).size, input.length); - }); - - it('length longer than source returns max length', function () { - var input = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']; - var length = input.length + 1; - var unique = faker.helpers.uniqueArray(input, length); - assert.strictEqual(unique.length, input.length); - assert.strictEqual(new Set(unique).size, input.length); - }); - - it('works as expected when seeded', function () { - var input = ['a', 'a', 'a', 'a', 'a', 'f', 'g', 'h', 'i', 'j']; - var length = 5; - faker.seed(100); - var unique = faker.helpers.uniqueArray(input, length); - assert.deepStrictEqual(unique, ['g', 'a', 'i', 'f', 'j']); - }); - }); - - describe('slugify()', function () { - it('removes unwanted characters from URI string', function () { - assert.strictEqual( - faker.helpers.slugify('Aiden.Harªann'), - 'Aiden.Harann' - ); - assert.strictEqual(faker.helpers.slugify("d'angelo.net"), 'dangelo.net'); - }); - }); - - describe('mustache()', function () { - it('returns empty string with no arguments', function () { - assert.strictEqual(faker.helpers.mustache(), ''); - }); - }); - - describe('repeatString()', function () { - it('returns empty string with no arguments', function () { - assert.strictEqual(faker.helpers.repeatString(), ''); - }); - }); - - describe('replaceSymbols()', function () { - it('returns empty string with no arguments', function () { - assert.strictEqual(faker.helpers.replaceSymbols(), ''); - }); - }); - - /* - describe("replaceCreditCardSymbols()", function () { - it("returns empty string with no arguments", function () { - assert.equal(faker.helpers.replaceCreditCardSymbols(), ""); - }); - }); - */ - - describe('createCard()', function () { - it('returns an object', function () { - var card = faker.helpers.createCard(); - assert.ok(typeof card === 'object'); - }); - }); - - describe('contextualCard()', function () { - it('returns an object', function () { - var card = faker.helpers.contextualCard(); - assert.ok(typeof card === 'object'); - }); - }); - - describe('userCard()', function () { - it('returns an object', function () { - var card = faker.helpers.userCard(); - assert.ok(typeof card === 'object'); - }); - }); - - // Make sure we keep this function for backward-compatibility. - describe('randomize()', function () { - it('returns a random element from an array', function () { - var arr = ['a', 'b', 'c']; - var elem = faker.helpers.randomize(arr); - assert.ok(elem); - assert.ok(arr.indexOf(elem) !== -1); - }); - }); - - describe('replaceCreditCardSymbols()', function () { - var luhnCheck = require('./support/luhnCheck.js'); - it('returns a credit card number given a schema', function () { - var number = faker.helpers.replaceCreditCardSymbols( - '6453-####-####-####-###L' - ); - assert.ok( - number.match(/^6453\-([0-9]){4}\-([0-9]){4}\-([0-9]){4}\-([0-9]){4}$/) - ); - assert.ok(luhnCheck(number)); - }); - it('supports different symbols', function () { - var number = faker.helpers.replaceCreditCardSymbols( - '6453-****-****-****-***L', - '*' - ); - assert.ok( - number.match(/^6453\-([0-9]){4}\-([0-9]){4}\-([0-9]){4}\-([0-9]){4}$/) - ); - assert.ok(luhnCheck(number)); - }); - it('handles regexp style input', function () { - var number = faker.helpers.replaceCreditCardSymbols( - '6453-*{4}-*{4}-*{4}-*{3}L', - '*' - ); - assert.ok( - number.match(/^6453\-([0-9]){4}\-([0-9]){4}\-([0-9]){4}\-([0-9]){4}$/) - ); - assert.ok(luhnCheck(number)); - number = faker.helpers.replaceCreditCardSymbols( - '645[5-9]-#{4,6}-#{1,2}-#{4,6}-#{3}L' - ); - assert.ok( - number.match( - /^645[5-9]\-([0-9]){4,6}\-([0-9]){1,2}\-([0-9]){4,6}\-([0-9]){4}$/ - ) - ); - assert.ok(luhnCheck(number)); - }); - }); - - describe('regexpStyleStringParse()', function () { - it('returns an empty string when called without param', function () { - assert.ok(faker.helpers.regexpStyleStringParse() === ''); - }); - it('deals with range repeat', function () { - var string = faker.helpers.regexpStyleStringParse('#{5,10}'); - assert.ok(string.length <= 10 && string.length >= 5); - assert.ok(string.match(/^\#{5,10}$/)); - }); - it('flips the range when min > max', function () { - var string = faker.helpers.regexpStyleStringParse('#{10,5}'); - assert.ok(string.length <= 10 && string.length >= 5); - assert.ok(string.match(/^\#{5,10}$/)); - }); - it('repeats string {n} number of times', function () { - assert.ok( - faker.helpers.regexpStyleStringParse('%{10}') === - faker.helpers.repeatString('%', 10) - ); - assert.ok( - faker.helpers.regexpStyleStringParse('%{30}') === - faker.helpers.repeatString('%', 30) - ); - assert.ok( - faker.helpers.regexpStyleStringParse('%{5}') === - faker.helpers.repeatString('%', 5) - ); - }); - it('creates a numerical range', function () { - var string = faker.helpers.regexpStyleStringParse('Hello[0-9]'); - assert.ok(string.match(/^Hello[0-9]$/)); - }); - it('deals with multiple tokens in one string', function () { - var string = faker.helpers.regexpStyleStringParse( - 'Test#{5}%{2,5}Testing**[1-5]**{10}END' - ); - assert.ok(string.match(/^Test\#{5}%{2,5}Testing\*\*[1-5]\*\*{10}END$/)); - }); - }); - - describe('createTransaction()', function () { - it('should create a random transaction', function () { - var transaction = faker.helpers.createTransaction(); - assert.ok(transaction); - assert.ok(transaction.amount); - assert.ok(transaction.date); - assert.ok(transaction.business); - assert.ok(transaction.name); - assert.ok(transaction.type); - assert.ok(transaction.account); - }); - }); -}); diff --git a/test/image.spec.ts b/test/image.spec.ts new file mode 100644 index 00000000..f585aa1e --- /dev/null +++ b/test/image.spec.ts @@ -0,0 +1,349 @@ +import { describe, expect, it } from 'vitest'; +import { faker } from '../lib'; + +describe('image', () => { + describe('lorempicsum', () => { + describe('imageUrl()', () => { + it('returns a random image url from lorempixel', () => { + const imageUrl = faker.image.lorempicsum.imageUrl(); + + expect(imageUrl).toBe('https://picsum.photos/640/480'); + }); + + it('returns a random image url from lorem picsum with width and height', () => { + const imageUrl = faker.image.lorempicsum.imageUrl(100, 100); + + expect(imageUrl).toBe('https://picsum.photos/100/100'); + }); + + it('returns a random image url grayscaled', () => { + const imageUrl = faker.image.lorempicsum.imageUrl(100, 100, true); + + expect(imageUrl).toBe('https://picsum.photos/100/100?grayscale'); + }); + + it('returns a random image url grayscaled and blurred', () => { + const imageUrl = faker.image.lorempicsum.imageUrl(100, 100, true, 2); + + expect(imageUrl).toBe('https://picsum.photos/100/100?grayscale&blur=2'); + }); + + it('returns a random image url blurred', () => { + const imageUrl = faker.image.lorempicsum.imageUrl( + 100, + 100, + undefined, + 2 + ); + + expect(imageUrl).toBe('https://picsum.photos/100/100?blur=2'); + }); + + it('returns a random image url with seed', () => { + const imageUrl = faker.image.lorempicsum.imageUrl( + 100, + 100, + undefined, + undefined, + 'picsum' + ); + + expect(imageUrl).toBe('https://picsum.photos/seed/picsum/100/100'); + }); + }); + + describe('avatar()', () => { + it('return a random avatar from cloudflare-ipfs', () => { + expect( + faker.image.lorempicsum + .avatar() + .includes( + 'cloudflare-ipfs.com/ipfs/Qmd3W5DuhgHirLHGVixi6V76LhCkZUz6pnFt5AJBiyvHye/avatar' + ) + ).toBeTruthy(); + }); + }); + + describe('imageGrayscale()', () => { + it('returns a random URL with grayscale image', () => { + const imageUrl = faker.image.lorempicsum.imageGrayscale(100, 100, true); + + expect(imageUrl).toBe('https://picsum.photos/100/100?grayscale'); + }); + }); + + describe('imageBlurred()', () => { + it('returns a random image url blurred', () => { + const imageUrl = faker.image.lorempicsum.imageBlurred(100, 100, 2); + + expect(imageUrl).toBe('https://picsum.photos/100/100?blur=2'); + }); + }); + + describe('imageRandomSeeded()', () => { + it('returns a random image url blurred', () => { + const imageUrl = faker.image.lorempicsum.imageRandomSeeded( + 100, + 100, + undefined, + undefined, + 'picsum' + ); + + expect(imageUrl).toBe('https://picsum.photos/seed/picsum/100/100'); + }); + }); + }); + + describe('lorempixel', () => { + describe('imageUrl()', () => { + it('returns a random image url from lorempixel', () => { + const imageUrl = faker.image.lorempixel.imageUrl(); + + expect(imageUrl).toBe('https://lorempixel.com/640/480'); + }); + + it('returns a random image url from lorempixel with width and height', () => { + const imageUrl = faker.image.lorempixel.imageUrl(100, 100); + + expect(imageUrl).toBe('https://lorempixel.com/100/100'); + }); + + it('returns a random image url for a specified category', () => { + const imageUrl = faker.image.lorempixel.imageUrl(100, 100, 'abstract'); + + expect(imageUrl).toBe('https://lorempixel.com/100/100/abstract'); + }); + }); + + describe('avatar()', () => { + it('return a random avatar from cloudflare-ipfs', () => { + expect( + faker.image.lorempixel + .avatar() + .includes( + 'cloudflare-ipfs.com/ipfs/Qmd3W5DuhgHirLHGVixi6V76LhCkZUz6pnFt5AJBiyvHye/avatar' + ) + ).toBeTruthy(); + }); + }); + + describe('abstract()', () => { + it('returns a random abstract image url', () => { + const abstract = faker.image.lorempixel.abstract(); + expect(abstract).toBe('https://lorempixel.com/640/480/abstract'); + }); + }); + + describe('animals()', () => { + it('returns a random animals image url', () => { + const animals = faker.image.lorempixel.animals(); + expect(animals).toBe('https://lorempixel.com/640/480/animals'); + }); + }); + + describe('business()', () => { + it('returns a random business image url', () => { + const business = faker.image.lorempixel.business(); + expect(business).toBe('https://lorempixel.com/640/480/business'); + }); + }); + + describe('cats()', () => { + it('returns a random cats image url', () => { + const cats = faker.image.lorempixel.cats(); + expect(cats).toBe('https://lorempixel.com/640/480/cats'); + }); + }); + + describe('city()', () => { + it('returns a random city image url', () => { + const city = faker.image.lorempixel.city(); + expect(city).toBe('https://lorempixel.com/640/480/city'); + }); + }); + + describe('food()', () => { + it('returns a random food image url', () => { + const food = faker.image.lorempixel.food(); + expect(food).toBe('https://lorempixel.com/640/480/food'); + }); + }); + + describe('nightlife()', () => { + it('returns a random nightlife image url', () => { + const nightlife = faker.image.lorempixel.nightlife(); + expect(nightlife).toBe('https://lorempixel.com/640/480/nightlife'); + }); + }); + + describe('fashion()', () => { + it('returns a random fashion image url', () => { + const fashion = faker.image.lorempixel.fashion(); + expect(fashion).toBe('https://lorempixel.com/640/480/fashion'); + }); + }); + + describe('people()', () => { + it('returns a random people image url', () => { + const people = faker.image.lorempixel.people(); + expect(people).toBe('https://lorempixel.com/640/480/people'); + }); + }); + + describe('nature()', () => { + it('returns a random nature image url', () => { + const nature = faker.image.lorempixel.nature(); + expect(nature).toBe('https://lorempixel.com/640/480/nature'); + }); + }); + + describe('sports()', () => { + it('returns a random sports image url', () => { + const sports = faker.image.lorempixel.sports(); + expect(sports).toBe('https://lorempixel.com/640/480/sports'); + }); + }); + + describe('technics()', () => { + it('returns a random technics image url', () => { + const technics = faker.image.lorempixel.technics(); + expect(technics).toBe('https://lorempixel.com/640/480/technics'); + }); + }); + + describe('transport()', () => { + it('returns a random transport image url', () => { + const transport = faker.image.lorempixel.transport(); + expect(transport).toBe('https://lorempixel.com/640/480/transport'); + }); + }); + }); + + describe('unsplash', () => { + describe('imageUrl()', () => { + it('returns a random image url from unsplash', () => { + const imageUrl = faker.image.unsplash.imageUrl(); + + expect(imageUrl).toBe('https://source.unsplash.com/640x480'); + }); + + it('returns a random image url from unsplash with width and height', () => { + const imageUrl = faker.image.unsplash.imageUrl(100, 100); + + expect(imageUrl).toBe('https://source.unsplash.com/100x100'); + }); + + it('returns a random image url for a specified category', () => { + const imageUrl = faker.image.unsplash.imageUrl(100, 100, 'food'); + + expect(imageUrl).toBe( + 'https://source.unsplash.com/category/food/100x100' + ); + }); + + it('returns a random image url with correct keywords for a specified category', () => { + const imageUrl = faker.image.unsplash.imageUrl( + 100, + 100, + 'food', + 'keyword1,keyword2' + ); + + expect(imageUrl).toBe( + 'https://source.unsplash.com/category/food/100x100?keyword1,keyword2' + ); + }); + + it('returns a random image url without keyword which format is wrong for a specified category', () => { + const imageUrl = faker.image.unsplash.imageUrl( + 100, + 100, + 'food', + 'keyword1,?ds)0123$*908932409' + ); + + expect(imageUrl).toBe( + 'https://source.unsplash.com/category/food/100x100' + ); + }); + }); + + describe('image()', () => { + it('returns a searching image url with keyword', () => { + const food = faker.image.unsplash.image( + 100, + 200, + 'keyword1,keyword2,keyword3' + ); + expect(food).toBe( + 'https://source.unsplash.com/100x200?keyword1,keyword2,keyword3' + ); + }); + }); + + describe('food()', () => { + it('returns a random food image url', () => { + const food = faker.image.unsplash.food(); + expect(food).toBe('https://source.unsplash.com/category/food/640x480'); + }); + }); + + describe('people()', () => { + it('returns a random people image url', () => { + const people = faker.image.unsplash.people(); + expect(people).toBe( + 'https://source.unsplash.com/category/people/640x480' + ); + }); + }); + + describe('nature()', () => { + it('returns a random nature image url', () => { + const nature = faker.image.unsplash.nature(); + expect(nature).toBe( + 'https://source.unsplash.com/category/nature/640x480' + ); + }); + }); + + describe('technology()', () => { + it('returns a random technology image url', () => { + const transport = faker.image.unsplash.technology(); + expect(transport).toBe( + 'https://source.unsplash.com/category/technology/640x480' + ); + }); + }); + describe('objects()', () => { + it('returns a random objects image url', () => { + const transport = faker.image.unsplash.objects(); + expect(transport).toBe( + 'https://source.unsplash.com/category/objects/640x480' + ); + }); + }); + describe('buildings()', () => { + it('returns a random buildings image url', () => { + const transport = faker.image.unsplash.buildings(); + expect(transport).toBe( + 'https://source.unsplash.com/category/buildings/640x480' + ); + }); + }); + }); + describe('dataUri', () => { + it('returns a blank data', () => { + const dataUri = faker.image.dataUri(200, 300); + expect(dataUri).toBe( + 'data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20baseProfile%3D%22full%22%20width%3D%22200%22%20height%3D%22300%22%3E%3Crect%20width%3D%22100%25%22%20height%3D%22100%25%22%20fill%3D%22grey%22%2F%3E%3Ctext%20x%3D%22100%22%20y%3D%22150%22%20font-size%3D%2220%22%20alignment-baseline%3D%22middle%22%20text-anchor%3D%22middle%22%20fill%3D%22white%22%3E200x300%3C%2Ftext%3E%3C%2Fsvg%3E' + ); + }); + it('returns a customed background color data URI', () => { + const dataUri = faker.image.dataUri(200, 300, 'red'); + expect(dataUri).toBe( + 'data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20baseProfile%3D%22full%22%20width%3D%22200%22%20height%3D%22300%22%3E%3Crect%20width%3D%22100%25%22%20height%3D%22100%25%22%20fill%3D%22red%22%2F%3E%3Ctext%20x%3D%22100%22%20y%3D%22150%22%20font-size%3D%2220%22%20alignment-baseline%3D%22middle%22%20text-anchor%3D%22middle%22%20fill%3D%22white%22%3E200x300%3C%2Ftext%3E%3C%2Fsvg%3E' + ); + }); + }); +}); diff --git a/test/image.unit.js b/test/image.unit.js deleted file mode 100644 index 46678db8..00000000 --- a/test/image.unit.js +++ /dev/null @@ -1,348 +0,0 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var sinon = require('sinon'); - var faker = require('../lib').faker; -} - -describe('image.js', function () { - describe('lorempicsum', function () { - describe('imageUrl()', function () { - it('returns a random image url from lorempixel', function () { - var imageUrl = faker.image.lorempicsum.imageUrl(); - - assert.strictEqual(imageUrl, 'https://picsum.photos/640/480'); - }); - it('returns a random image url from lorem picsum with width and height', function () { - var imageUrl = faker.image.lorempicsum.imageUrl(100, 100); - - assert.strictEqual(imageUrl, 'https://picsum.photos/100/100'); - }); - it('returns a random image url grayscaled', function () { - var imageUrl = faker.image.lorempicsum.imageUrl(100, 100, true); - - assert.strictEqual(imageUrl, 'https://picsum.photos/100/100?grayscale'); - }); - - it('returns a random image url grayscaled and blurred', function () { - var imageUrl = faker.image.lorempicsum.imageUrl(100, 100, true, 2); - - assert.strictEqual( - imageUrl, - 'https://picsum.photos/100/100?grayscale&blur=2' - ); - }); - - it('returns a random image url blurred', function () { - var imageUrl = faker.image.lorempicsum.imageUrl(100, 100, undefined, 2); - - assert.strictEqual(imageUrl, 'https://picsum.photos/100/100?blur=2'); - }); - - it('returns a random image url with seed', function () { - var imageUrl = faker.image.lorempicsum.imageUrl( - 100, - 100, - undefined, - undefined, - 'picsum' - ); - - assert.strictEqual( - imageUrl, - 'https://picsum.photos/seed/picsum/100/100' - ); - }); - }); - describe('avatar()', function () { - it('return a random avatar from cloudflare-ipfs', function () { - assert.notStrictEqual( - -1, - faker.image.lorempicsum - .avatar() - .indexOf( - 'cloudflare-ipfs.com/ipfs/Qmd3W5DuhgHirLHGVixi6V76LhCkZUz6pnFt5AJBiyvHye/avatar' - ) - ); - }); - }); - - describe('imageGrayscale()', function () { - it('returns a random URL with grayscale image', function () { - var imageUrl = faker.image.lorempicsum.imageGrayscale(100, 100, true); - - assert.strictEqual(imageUrl, 'https://picsum.photos/100/100?grayscale'); - }); - }); - describe('imageBlurred()', function () { - it('returns a random image url blurred', function () { - var imageUrl = faker.image.lorempicsum.imageBlurred(100, 100, 2); - - assert.strictEqual(imageUrl, 'https://picsum.photos/100/100?blur=2'); - }); - }); - describe('imageRandomSeeded()', function () { - it('returns a random image url blurred', function () { - var imageUrl = faker.image.lorempicsum.imageRandomSeeded( - 100, - 100, - undefined, - undefined, - 'picsum' - ); - - assert.strictEqual( - imageUrl, - 'https://picsum.photos/seed/picsum/100/100' - ); - }); - }); - }); - - describe('lorempixel', function () { - describe('imageUrl()', function () { - it('returns a random image url from lorempixel', function () { - var imageUrl = faker.image.lorempixel.imageUrl(); - - assert.strictEqual(imageUrl, 'https://lorempixel.com/640/480'); - }); - it('returns a random image url from lorempixel with width and height', function () { - var imageUrl = faker.image.lorempixel.imageUrl(100, 100); - - assert.strictEqual(imageUrl, 'https://lorempixel.com/100/100'); - }); - it('returns a random image url for a specified category', function () { - var imageUrl = faker.image.lorempixel.imageUrl(100, 100, 'abstract'); - - assert.strictEqual(imageUrl, 'https://lorempixel.com/100/100/abstract'); - }); - }); - describe('avatar()', function () { - it('return a random avatar from cloudflare-ipfs', function () { - assert.notStrictEqual( - -1, - faker.image.lorempixel - .avatar() - .indexOf( - 'cloudflare-ipfs.com/ipfs/Qmd3W5DuhgHirLHGVixi6V76LhCkZUz6pnFt5AJBiyvHye/avatar' - ) - ); - }); - }); - describe('abstract()', function () { - it('returns a random abstract image url', function () { - var abstract = faker.image.lorempixel.abstract(); - assert.strictEqual(abstract, 'https://lorempixel.com/640/480/abstract'); - }); - }); - describe('animals()', function () { - it('returns a random animals image url', function () { - var animals = faker.image.lorempixel.animals(); - assert.strictEqual(animals, 'https://lorempixel.com/640/480/animals'); - }); - }); - describe('business()', function () { - it('returns a random business image url', function () { - var business = faker.image.lorempixel.business(); - assert.strictEqual(business, 'https://lorempixel.com/640/480/business'); - }); - }); - describe('cats()', function () { - it('returns a random cats image url', function () { - var cats = faker.image.lorempixel.cats(); - assert.strictEqual(cats, 'https://lorempixel.com/640/480/cats'); - }); - }); - describe('city()', function () { - it('returns a random city image url', function () { - var city = faker.image.lorempixel.city(); - assert.strictEqual(city, 'https://lorempixel.com/640/480/city'); - }); - }); - describe('food()', function () { - it('returns a random food image url', function () { - var food = faker.image.lorempixel.food(); - assert.strictEqual(food, 'https://lorempixel.com/640/480/food'); - }); - }); - describe('nightlife()', function () { - it('returns a random nightlife image url', function () { - var nightlife = faker.image.lorempixel.nightlife(); - assert.strictEqual( - nightlife, - 'https://lorempixel.com/640/480/nightlife' - ); - }); - }); - describe('fashion()', function () { - it('returns a random fashion image url', function () { - var fashion = faker.image.lorempixel.fashion(); - assert.strictEqual(fashion, 'https://lorempixel.com/640/480/fashion'); - }); - }); - describe('people()', function () { - it('returns a random people image url', function () { - var people = faker.image.lorempixel.people(); - assert.strictEqual(people, 'https://lorempixel.com/640/480/people'); - }); - }); - describe('nature()', function () { - it('returns a random nature image url', function () { - var nature = faker.image.lorempixel.nature(); - assert.strictEqual(nature, 'https://lorempixel.com/640/480/nature'); - }); - }); - describe('sports()', function () { - it('returns a random sports image url', function () { - var sports = faker.image.lorempixel.sports(); - assert.strictEqual(sports, 'https://lorempixel.com/640/480/sports'); - }); - }); - describe('technics()', function () { - it('returns a random technics image url', function () { - var technics = faker.image.lorempixel.technics(); - assert.strictEqual(technics, 'https://lorempixel.com/640/480/technics'); - }); - }); - describe('transport()', function () { - it('returns a random transport image url', function () { - var transport = faker.image.lorempixel.transport(); - assert.strictEqual( - transport, - 'https://lorempixel.com/640/480/transport' - ); - }); - }); - }); - - describe('unsplash', function () { - describe('imageUrl()', function () { - it('returns a random image url from unsplash', function () { - var imageUrl = faker.image.unsplash.imageUrl(); - - assert.strictEqual(imageUrl, 'https://source.unsplash.com/640x480'); - }); - it('returns a random image url from unsplash with width and height', function () { - var imageUrl = faker.image.unsplash.imageUrl(100, 100); - - assert.strictEqual(imageUrl, 'https://source.unsplash.com/100x100'); - }); - it('returns a random image url for a specified category', function () { - var imageUrl = faker.image.unsplash.imageUrl(100, 100, 'food'); - - assert.strictEqual( - imageUrl, - 'https://source.unsplash.com/category/food/100x100' - ); - }); - it('returns a random image url with correct keywords for a specified category', function () { - var imageUrl = faker.image.unsplash.imageUrl( - 100, - 100, - 'food', - 'keyword1,keyword2' - ); - - assert.strictEqual( - imageUrl, - 'https://source.unsplash.com/category/food/100x100?keyword1,keyword2' - ); - }); - it('returns a random image url without keyword which format is wrong for a specified category', function () { - var imageUrl = faker.image.unsplash.imageUrl( - 100, - 100, - 'food', - 'keyword1,?ds)0123$*908932409' - ); - - assert.strictEqual( - imageUrl, - 'https://source.unsplash.com/category/food/100x100' - ); - }); - }); - describe('image()', function () { - it('returns a searching image url with keyword', function () { - var food = faker.image.unsplash.image( - 100, - 200, - 'keyword1,keyword2,keyword3' - ); - assert.strictEqual( - food, - 'https://source.unsplash.com/100x200?keyword1,keyword2,keyword3' - ); - }); - }); - describe('food()', function () { - it('returns a random food image url', function () { - var food = faker.image.unsplash.food(); - assert.strictEqual( - food, - 'https://source.unsplash.com/category/food/640x480' - ); - }); - }); - describe('people()', function () { - it('returns a random people image url', function () { - var people = faker.image.unsplash.people(); - assert.strictEqual( - people, - 'https://source.unsplash.com/category/people/640x480' - ); - }); - }); - describe('nature()', function () { - it('returns a random nature image url', function () { - var nature = faker.image.unsplash.nature(); - assert.strictEqual( - nature, - 'https://source.unsplash.com/category/nature/640x480' - ); - }); - }); - describe('technology()', function () { - it('returns a random technology image url', function () { - var transport = faker.image.unsplash.technology(); - assert.strictEqual( - transport, - 'https://source.unsplash.com/category/technology/640x480' - ); - }); - }); - describe('objects()', function () { - it('returns a random objects image url', function () { - var transport = faker.image.unsplash.objects(); - assert.strictEqual( - transport, - 'https://source.unsplash.com/category/objects/640x480' - ); - }); - }); - describe('buildings()', function () { - it('returns a random buildings image url', function () { - var transport = faker.image.unsplash.buildings(); - assert.strictEqual( - transport, - 'https://source.unsplash.com/category/buildings/640x480' - ); - }); - }); - }); - describe('dataUri', function () { - it('returns a blank data', function () { - var dataUri = faker.image.dataUri(200, 300); - assert.strictEqual( - dataUri, - 'data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20baseProfile%3D%22full%22%20width%3D%22200%22%20height%3D%22300%22%3E%3Crect%20width%3D%22100%25%22%20height%3D%22100%25%22%20fill%3D%22grey%22%2F%3E%3Ctext%20x%3D%22100%22%20y%3D%22150%22%20font-size%3D%2220%22%20alignment-baseline%3D%22middle%22%20text-anchor%3D%22middle%22%20fill%3D%22white%22%3E200x300%3C%2Ftext%3E%3C%2Fsvg%3E' - ); - }); - it('returns a customed background color data URI', function () { - var dataUri = faker.image.dataUri(200, 300, 'red'); - assert.strictEqual( - dataUri, - 'data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20baseProfile%3D%22full%22%20width%3D%22200%22%20height%3D%22300%22%3E%3Crect%20width%3D%22100%25%22%20height%3D%22100%25%22%20fill%3D%22red%22%2F%3E%3Ctext%20x%3D%22100%22%20y%3D%22150%22%20font-size%3D%2220%22%20alignment-baseline%3D%22middle%22%20text-anchor%3D%22middle%22%20fill%3D%22white%22%3E200x300%3C%2Ftext%3E%3C%2Fsvg%3E' - ); - }); - }); -}); diff --git a/test/internet.spec.ts b/test/internet.spec.ts new file mode 100644 index 00000000..9df1e805 --- /dev/null +++ b/test/internet.spec.ts @@ -0,0 +1,271 @@ +import { describe, expect, it, vi } from 'vitest'; +import { faker } from '../lib'; + +describe('internet.js', () => { + describe('email()', () => { + it('returns an email', () => { + const spy_internet_userName = vi + .spyOn(faker.internet, 'userName') + .mockReturnValue('Aiden.Harann55'); + + const email = faker.internet.email('Aiden.Harann55'); + const res = email.split('@')[0]; + + expect(res).toBe('Aiden.Harann55'); + + spy_internet_userName.mockRestore(); + }); + + it('returns an email with japanese characters', () => { + const spy_internet_userName = vi + .spyOn(faker.internet, 'userName') + .mockReturnValue('思源_唐3'); + + const email = faker.internet.email('思源_唐3'); + const res = email.split('@')[0]; + + expect(res).toBe('思源_唐3'); + + spy_internet_userName.mockRestore(); + }); + }); + + describe('exampleEmail', () => { + it('returns an email with the correct name', () => { + const spy_internet_userName = vi + .spyOn(faker.internet, 'userName') + .mockReturnValue('Aiden.Harann55'); + + const email = faker.internet.email('Aiden.Harann55'); + const res = email.split('@')[0]; + + expect(res).toBe('Aiden.Harann55'); + + spy_internet_userName.mockRestore(); + }); + + it('uses the example.[org|com|net] host', () => { + const email = faker.internet.exampleEmail(); + expect(email).match(/@example\.(org|com|net)$/); + }); + }); + + describe('userName()', () => { + it('occasionally returns a single firstName', () => { + const spy_datatype_number = vi + .spyOn(faker.datatype, 'number') + .mockReturnValue(0); + const spy_name_firstName = vi.spyOn(faker.name, 'firstName'); + + const username = faker.internet.userName(); + + expect(username).toBeTruthy(); + expect(spy_name_firstName).toHaveBeenCalled(); + + spy_datatype_number.mockRestore(); + spy_name_firstName.mockRestore(); + }); + + it('occasionally returns a firstName with a period or hyphen and a lastName', () => { + const spy_datatype_number = vi + .spyOn(faker.datatype, 'number') + .mockReturnValue(1); + const spy_name_firstName = vi.spyOn(faker.name, 'firstName'); + const spy_name_lastName = vi.spyOn(faker.name, 'lastName'); + const spy_random_arrayElement = vi.spyOn(faker.random, 'arrayElement'); + + const username = faker.internet.userName(); + + expect(username).toBeTruthy(); + expect(spy_name_firstName).toHaveBeenCalled(); + expect(spy_name_lastName).toHaveBeenCalled(); + expect(spy_random_arrayElement).toHaveBeenCalledWith(['.', '_']); + + spy_datatype_number.mockRestore(); + spy_name_firstName.mockRestore(); + spy_name_lastName.mockRestore(); + spy_random_arrayElement.mockRestore(); + }); + }); + + describe('domainName()', () => { + it('returns a domainWord plus a random suffix', () => { + const spy_internet_domainWord = vi + .spyOn(faker.internet, 'domainWord') + .mockReturnValue('bar'); + const spy_internet_domainSuffix = vi + .spyOn(faker.internet, 'domainSuffix') + .mockReturnValue('net'); + + const domain_name = faker.internet.domainName(); + + expect(domain_name).toBe('bar.net'); + + spy_internet_domainWord.mockRestore(); + spy_internet_domainSuffix.mockRestore(); + }); + }); + + describe('domainWord()', () => { + it('returns a lower-case adjective + noun', () => { + const spy_word_adjective = vi + .spyOn(faker.word, 'adjective') + .mockReturnValue('RANDOM'); + const spy_word_noun = vi + .spyOn(faker.word, 'noun') + .mockReturnValue('WORD'); + + const domain_word = faker.internet.domainWord(); + + expect(domain_word).toBeTruthy(); + expect(domain_word).toBe('random-word'); + + spy_word_adjective.mockRestore(); + spy_word_noun.mockRestore(); + }); + + describe('when the firstName used contains a apostrophe', () => { + it('should remove the apostrophe', () => { + const spy_word_adjective = vi + .spyOn(faker.word, 'adjective') + .mockReturnValue("an'other"); + const spy_word_noun = vi + .spyOn(faker.word, 'noun') + .mockReturnValue("no'un"); + + const domain_word = faker.internet.domainWord(); + + expect(domain_word).toBe('another-noun'); + + spy_word_adjective.mockRestore(); + spy_word_noun.mockRestore(); + }); + }); + }); + + describe('protocol()', () => { + it('returns a valid protocol', () => { + const protocol = faker.internet.protocol(); + expect(protocol).toBeTruthy(); + }); + + it('should occasionally return http', () => { + const spy_datatype_number = vi + .spyOn(faker.datatype, 'number') + .mockReturnValue(0); + + const protocol = faker.internet.protocol(); + + expect(protocol).toBeTruthy(); + expect(protocol).toBe('http'); + + spy_datatype_number.mockRestore(); + }); + + it('should occasionally return https', () => { + const spy_datatype_number = vi + .spyOn(faker.datatype, 'number') + .mockReturnValue(1); + + const protocol = faker.internet.protocol(); + + expect(protocol).toBeTruthy(); + expect(protocol).toBe('https'); + + spy_datatype_number.mockRestore(); + }); + }); + + describe('httpMethod()', () => { + it('returns a valid http method', () => { + const httpMethods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH']; + const method = faker.internet.httpMethod(); + expect(httpMethods).toContain(method); + }); + }); + + describe('url()', () => { + it('returns a valid url', () => { + vi.spyOn(faker.internet, 'protocol').mockReturnValue('http'); + vi.spyOn(faker.internet, 'domainWord').mockReturnValue('bar'); + vi.spyOn(faker.internet, 'domainSuffix').mockReturnValue('net'); + + const url = faker.internet.url(); + + expect(url).toBeTruthy(); + expect(url).toBe('http://bar.net'); + }); + }); + + describe('ip()', () => { + it('returns a random IP address with four parts', () => { + const ip = faker.internet.ip(); + const parts = ip.split('.'); + expect(parts).toHaveLength(4); + }); + }); + + describe('ipv6()', () => { + it('returns a random IPv6 address with eight parts', () => { + const ip = faker.internet.ipv6(); + const parts = ip.split(':'); + expect(parts).toHaveLength(8); + }); + }); + + describe('port()', () => { + it('returns a random port number', () => { + const port = faker.internet.port(); + expect(Number.isInteger(port)).toBe(true); + expect(port).greaterThanOrEqual(0); + expect(port).lessThanOrEqual(65535); + }); + }); + + describe('userAgent()', () => { + it('returns a valid user-agent', () => { + const ua = faker.internet.userAgent(); + expect(ua).toBeTruthy(); + }); + + it('is deterministic', () => { + faker.seed(1); + const ua1 = faker.internet.userAgent(); + faker.seed(1); + const ua2 = faker.internet.userAgent(); + expect(ua1).toBe(ua2); + }); + }); + + describe('color()', () => { + it('returns a valid hex value (like #ffffff)', () => { + const color = faker.internet.color(100, 100, 100); + expect(color).match(/^#[a-f0-9]{6}$/); + }); + }); + + describe('mac()', () => { + it('returns a random MAC address with 6 hexadecimal digits', () => { + const mac = faker.internet.mac(); + expect(mac).match(/^([a-f0-9]{2}:){5}[a-f0-9]{2}$/); + }); + + it('uses the dash separator if we pass it in as our separator', () => { + const mac = faker.internet.mac('-'); + expect(mac).match(/^([a-f0-9]{2}-){5}[a-f0-9]{2}$/); + }); + + it('uses no separator if we pass in an empty string', () => { + const mac = faker.internet.mac(''); + expect(mac).match(/^[a-f0-9]{12}$/); + }); + + it('uses the default colon (:) if we provide an unacceptable separator', () => { + let mac = faker.internet.mac('!'); + expect(mac).match(/^([a-f0-9]{2}:){5}[a-f0-9]{2}$/); + + mac = faker.internet.mac('&'); + expect(mac).match(/^([a-f0-9]{2}:){5}[a-f0-9]{2}$/); + }); + }); +}); diff --git a/test/internet.unit.js b/test/internet.unit.js deleted file mode 100644 index 12333067..00000000 --- a/test/internet.unit.js +++ /dev/null @@ -1,232 +0,0 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var sinon = require('sinon'); - var faker = require('../lib').faker; -} - -describe('internet.js', function () { - describe('email()', function () { - it('returns an email', function () { - sinon.stub(faker.internet, 'userName').returns('Aiden.Harann55'); - var email = faker.internet.email('Aiden.Harann55'); - var res = email.split('@'); - res = res[0]; - assert.strictEqual(res, 'Aiden.Harann55'); - faker.internet.userName.restore(); - }); - - it('returns an email with japanese characters', function () { - sinon.stub(faker.internet, 'userName').returns('思源_唐3'); - var email = faker.internet.email('思源_唐3'); - var res = email.split('@'); - res = res[0]; - assert.equal(res, '思源_唐3'); - faker.internet.userName.restore(); - }); - }); - - describe('exampleEmail', function () { - it('returns an email with the correct name', function () { - sinon.stub(faker.internet, 'userName').returns('Aiden.Harann55'); - var email = faker.internet.email('Aiden.Harann55'); - var res = email.split('@'); - res = res[0]; - assert.strictEqual(res, 'Aiden.Harann55'); - faker.internet.userName.restore(); - }); - - it('uses the example.[org|com|net] host', function () { - var email = faker.internet.exampleEmail(); - assert.ok(email.match(/@example\.(org|com|net)$/)); - }); - }); - - describe('userName()', function () { - it('occasionally returns a single firstName', function () { - sinon.stub(faker.datatype, 'number').returns(0); - sinon.spy(faker.name, 'firstName'); - var username = faker.internet.userName(); - - assert.ok(username); - assert.ok(faker.name.firstName.called); - - faker.datatype.number.restore(); - faker.name.firstName.restore(); - }); - - it('occasionally returns a firstName with a period or hyphen and a lastName', function () { - sinon.stub(faker.datatype, 'number').returns(1); - sinon.spy(faker.name, 'firstName'); - sinon.spy(faker.name, 'lastName'); - sinon.spy(faker.random, 'arrayElement'); - var username = faker.internet.userName(); - - assert.ok(username); - assert.ok(faker.name.firstName.called); - assert.ok(faker.name.lastName.called); - assert.ok(faker.random.arrayElement.calledWith(['.', '_'])); - - faker.datatype.number.restore(); - faker.name.firstName.restore(); - faker.name.lastName.restore(); - faker.random.arrayElement.restore(); - }); - }); - - describe('domainName()', function () { - it('returns a domainWord plus a random suffix', function () { - sinon.stub(faker.internet, 'domainWord').returns('bar'); - sinon.stub(faker.internet, 'domainSuffix').returns('net'); - - var domain_name = faker.internet.domainName(); - - assert.strictEqual(domain_name, 'bar.net'); - - faker.internet.domainWord.restore(); - faker.internet.domainSuffix.restore(); - }); - }); - - describe('domainWord()', function () { - it('returns a lower-case adjective + noun', function () { - sinon.stub(faker.word, 'adjective').returns('RANDOM'); - sinon.stub(faker.word, 'noun').returns('WORD'); - var domain_word = faker.internet.domainWord(); - - assert.ok(domain_word); - assert.strictEqual(domain_word, 'random-word'); - - faker.word.adjective.restore(); - faker.word.noun.restore(); - }); - describe('when the firstName used contains a apostrophe', function () { - sinon.stub(faker.word, 'adjective').returns("an'other"); - sinon.stub(faker.word, 'noun').returns("no'un"); - var domain_word = faker.internet.domainWord(); - - it('should remove the apostrophe', function () { - assert.strictEqual(domain_word, 'another-noun'); - }); - - faker.word.adjective.restore(); - faker.word.noun.restore(); - }); - }); - - describe('protocol()', function () { - it('returns a valid protocol', function () { - var protocol = faker.internet.protocol(); - assert.ok(protocol); - }); - - it('should occasionally return http', function () { - sinon.stub(faker.datatype, 'number').returns(0); - var protocol = faker.internet.protocol(); - assert.ok(protocol); - assert.strictEqual(protocol, 'http'); - - faker.datatype.number.restore(); - }); - - it('should occasionally return https', function () { - sinon.stub(faker.datatype, 'number').returns(1); - var protocol = faker.internet.protocol(); - assert.ok(protocol); - assert.strictEqual(protocol, 'https'); - - faker.datatype.number.restore(); - }); - }); - - describe('httpMethod()', function () { - it('returns a valid http method', function () { - var httpMethods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH']; - var method = faker.internet.httpMethod(); - assert.ok(httpMethods.includes(method)); - }); - }); - - describe('url()', function () { - it('returns a valid url', function () { - sinon.stub(faker.internet, 'protocol').returns('http'); - sinon.stub(faker.internet, 'domainWord').returns('bar'); - sinon.stub(faker.internet, 'domainSuffix').returns('net'); - - var url = faker.internet.url(); - - assert.ok(url); - assert.strictEqual(url, 'http://bar.net'); - }); - }); - - describe('ip()', function () { - it('returns a random IP address with four parts', function () { - var ip = faker.internet.ip(); - var parts = ip.split('.'); - assert.strictEqual(parts.length, 4); - }); - }); - - describe('ipv6()', function () { - it('returns a random IPv6 address with eight parts', function () { - var ip = faker.internet.ipv6(); - var parts = ip.split(':'); - assert.strictEqual(parts.length, 8); - }); - }); - - describe('port()', function () { - it('returns a random port number', function () { - var port = faker.internet.port(); - assert.ok(Number.isInteger(port)); - assert.ok(0 <= port && port <= 65535); - }); - }); - - describe('userAgent()', function () { - it('returns a valid user-agent', function () { - var ua = faker.internet.userAgent(); - assert.ok(ua); - }); - - it('is deterministic', function () { - faker.seed(1); - var ua1 = faker.internet.userAgent(); - faker.seed(1); - var ua2 = faker.internet.userAgent(); - assert.strictEqual(ua1, ua2); - }); - }); - - describe('color()', function () { - it('returns a valid hex value (like #ffffff)', function () { - var color = faker.internet.color(100, 100, 100); - assert.ok(color.match(/^#[a-f0-9]{6}$/)); - }); - }); - - describe('mac()', function () { - it('returns a random MAC address with 6 hexadecimal digits', function () { - var mac = faker.internet.mac(); - assert.ok(mac.match(/^([a-f0-9]{2}:){5}[a-f0-9]{2}$/)); - }); - - it('uses the dash separator if we pass it in as our separator', function () { - var mac = faker.internet.mac('-'); - assert.ok(mac.match(/^([a-f0-9]{2}-){5}[a-f0-9]{2}$/)); - }); - - it('uses no separator if we pass in an empty string', function () { - var mac = faker.internet.mac(''); - assert.ok(mac.match(/^[a-f0-9]{12}$/)); - }); - - it('uses the default colon (:) if we provide an unacceptable separator', function () { - var mac = faker.internet.mac('!'); - assert.ok(mac.match(/^([a-f0-9]{2}:){5}[a-f0-9]{2}$/)); - - mac = faker.internet.mac('&'); - assert.ok(mac.match(/^([a-f0-9]{2}:){5}[a-f0-9]{2}$/)); - }); - }); -}); diff --git a/test/locales.spec.ts b/test/locales.spec.ts new file mode 100644 index 00000000..942d4837 --- /dev/null +++ b/test/locales.spec.ts @@ -0,0 +1,15 @@ +import { describe, expect, it } from 'vitest'; +import { faker } from '../lib'; + +// Remark: actual use of locales functionality is currently tested in all.functional.js test + +describe('locale', () => { + describe('setLocale()', () => { + it('setLocale() changes faker.locale', () => { + for (const locale in faker.locales) { + faker.setLocale(locale); + expect(faker.locale).toBe(locale); + } + }); + }); +}); diff --git a/test/locales.unit.js b/test/locales.unit.js deleted file mode 100644 index d81386fc..00000000 --- a/test/locales.unit.js +++ /dev/null @@ -1,20 +0,0 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var sinon = require('sinon'); - var faker = require('../lib').faker; -} - -// TODO: make some tests for getting / setting locales - -// Remark: actual use of locales functionality is currently tested in all.functional.js test - -describe('locale', function () { - describe('setLocale()', function () { - it('setLocale() changes faker.locale', function () { - for (var locale in faker.locales) { - faker.setLocale(locale); - assert.strictEqual(faker.locale, locale); - } - }); - }); -}); diff --git a/test/lorem.unit.js b/test/lorem.spec.ts index e3c9f0ef..b2f740da 100644 --- a/test/lorem.unit.js +++ b/test/lorem.spec.ts @@ -1,94 +1,96 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var sinon = require('sinon'); - var faker = require('../lib').faker; -} - -describe('lorem.js', function () { - describe('word()', function () { - context("when no 'length' param passed in", function () { - it('returns a word with a random length', function () { - var str = faker.lorem.word(); - assert.ok(typeof str === 'string'); +import type { JestMockCompat } from 'vitest'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { faker } from '../lib'; + +describe('lorem.js', () => { + describe('word()', () => { + describe("when no 'length' param passed in", () => { + it('returns a word with a random length', () => { + const str = faker.lorem.word(); + expect(typeof str).toBe('string'); }); }); - context("when 'length' param passed in", function () { - it('returns a word with the requested length', function () { - var str = faker.lorem.word(5); - assert.ok(typeof str === 'string'); - assert.strictEqual(str.length, 5); + describe("when 'length' param passed in", () => { + it('returns a word with the requested length', () => { + const str = faker.lorem.word(5); + expect(typeof str).toBe('string'); + expect(str).toHaveLength(5); }); }); }); - describe('words()', function () { - beforeEach(function () { - sinon.spy(faker.helpers, 'shuffle'); + describe('words()', () => { + let spy_helpers_shuffle: JestMockCompat<[o?: unknown[]], unknown[]>; + + beforeEach(() => { + spy_helpers_shuffle = vi.spyOn(faker.helpers, 'shuffle'); }); - afterEach(function () { - faker.helpers.shuffle.restore(); + afterEach(() => { + spy_helpers_shuffle.mockRestore(); }); - context("when no 'num' param passed in", function () { - it('returns three words', function () { - var str = faker.lorem.words(); - var words = str.split(' '); - assert.ok(Array.isArray(words)); - assert.strictEqual(true, words.length >= 3); + describe("when no 'num' param passed in", () => { + it('returns three words', () => { + const str = faker.lorem.words(); + const words = str.split(' '); + expect(Array.isArray(words)).toBe(true); + expect(words.length).greaterThanOrEqual(3); // assert.ok(faker.helpers.shuffle.called); }); }); - context("when 'num' param passed in", function () { - it('returns requested number of words', function () { - var str = faker.lorem.words(7); - var words = str.split(' '); - assert.ok(Array.isArray(words)); - assert.strictEqual(words.length, 7); + describe("when 'num' param passed in", () => { + it('returns requested number of words', () => { + const str = faker.lorem.words(7); + const words = str.split(' '); + expect(Array.isArray(words)).toBe(true); + expect(words).toHaveLength(7); }); }); }); - describe('slug()', function () { - beforeEach(function () { - sinon.spy(faker.helpers, 'shuffle'); + describe('slug()', () => { + let spy_helpers_shuffle: JestMockCompat<[o?: unknown[]], unknown[]>; + + beforeEach(() => { + spy_helpers_shuffle = vi.spyOn(faker.helpers, 'shuffle'); }); - afterEach(function () { - faker.helpers.shuffle.restore(); + afterEach(() => { + spy_helpers_shuffle.mockRestore(); }); - var validateSlug = function (wordCount, str) { - assert.strictEqual(1, str.match(/^[a-z][a-z-]*[a-z]$/).length); - assert.strictEqual(wordCount - 1, str.match(/-/g).length); + const validateSlug = (wordCount, str) => { + expect(str.match(/^[a-z][a-z-]*[a-z]$/).length).toBe(1); + expect(str.match(/-/g).length).toBe(wordCount - 1); }; - context("when no 'wordCount' param passed in", function () { - it('returns a slug with three words', function () { - var str = faker.lorem.slug(); + describe("when no 'wordCount' param passed in", () => { + it('returns a slug with three words', () => { + const str = faker.lorem.slug(); validateSlug(3, str); }); }); - context("when 'wordCount' param passed in", function () { - it('returns a slug with requested number of words', function () { - var str = faker.lorem.slug(7); + describe("when 'wordCount' param passed in", () => { + it('returns a slug with requested number of words', () => { + const str = faker.lorem.slug(7); validateSlug(7, str); }); }); }); /* - describe("sentence()", function () { - context("when no 'wordCount' or 'range' param passed in", function () { - it("returns a string of at least three words", function () { + describe("sentence()", () =>{ + context("when no 'wordCount' or 'range' param passed in", () =>{ + it("returns a string of at least three words", () =>{ sinon.spy(faker.lorem, 'words'); sinon.stub(faker.random, 'number').returns(2); - var sentence = faker.lorem.sentence(); + const sentence = faker.lorem.sentence(); assert.ok(typeof sentence === 'string'); - var parts = sentence.split(' '); + const parts = sentence.split(' '); assert.strictEqual(parts.length, 5); // default 3 plus stubbed 2. assert.ok(faker.lorem.words.calledWith(5)); @@ -97,14 +99,14 @@ describe('lorem.js', function () { }); }); - context("when 'wordCount' param passed in", function () { - it("returns a string of at least the requested number of words", function () { + context("when 'wordCount' param passed in", () =>{ + it("returns a string of at least the requested number of words", () =>{ sinon.spy(faker.lorem, 'words'); sinon.stub(faker.random, 'number').withArgs(7).returns(2); - var sentence = faker.lorem.sentence(10); + const sentence = faker.lorem.sentence(10); assert.ok(typeof sentence === 'string'); - var parts = sentence.split(' '); + const parts = sentence.split(' '); assert.strictEqual(parts.length, 12); // requested 10 plus stubbed 2. assert.ok(faker.lorem.words.calledWith(12)); @@ -113,15 +115,15 @@ describe('lorem.js', function () { }); }); - context("when 'wordCount' and 'range' params passed in", function () { - it("returns a string of at least the requested number of words", function () { + context("when 'wordCount' and 'range' params passed in", () =>{ + it("returns a string of at least the requested number of words", () =>{ sinon.spy(faker.lorem, 'words'); sinon.stub(faker.random, 'number').withArgs(4).returns(4); - var sentence = faker.lorem.sentence(10, 4); + const sentence = faker.lorem.sentence(10, 4); assert.ok(typeof sentence === 'string'); - var parts = sentence.split(' '); + const parts = sentence.split(' '); assert.strictEqual(parts.length, 14); // requested 10 plus stubbed 4. assert.ok(faker.random.number.calledWith(4)); // random.number should be called with the 'range' we passed. assert.ok(faker.lorem.words.calledWith(14)); @@ -135,14 +137,14 @@ describe('lorem.js', function () { }); */ /* - describe("sentences()", function () { - context("when no 'sentenceCount' param passed in", function () { - it("returns newline-separated string of three sentences", function () { + describe("sentences()", () =>{ + context("when no 'sentenceCount' param passed in", () =>{ + it("returns newline-separated string of three sentences", () =>{ sinon.spy(faker.lorem, 'sentence'); - var sentences = faker.lorem.sentences(); + const sentences = faker.lorem.sentences(); assert.ok(typeof sentences === 'string'); - var parts = sentences.split('\n'); + const parts = sentences.split('\n'); assert.strictEqual(parts.length, 3); assert.ok(faker.lorem.sentence.calledThrice); @@ -150,13 +152,13 @@ describe('lorem.js', function () { }); }); - context("when 'sentenceCount' param passed in", function () { - it("returns newline-separated string of requested number of sentences", function () { + context("when 'sentenceCount' param passed in", () =>{ + it("returns newline-separated string of requested number of sentences", () =>{ sinon.spy(faker.lorem, 'sentence'); - var sentences = faker.lorem.sentences(5); + const sentences = faker.lorem.sentences(5); assert.ok(typeof sentences === 'string'); - var parts = sentences.split('\n'); + const parts = sentences.split('\n'); assert.strictEqual(parts.length, 5); faker.lorem.sentence.restore(); @@ -165,15 +167,15 @@ describe('lorem.js', function () { }); */ /* - describe("paragraph()", function () { - context("when no 'wordCount' param passed in", function () { - it("returns a string of at least three sentences", function () { + describe("paragraph()", () =>{ + context("when no 'wordCount' param passed in", () =>{ + it("returns a string of at least three sentences", () =>{ sinon.spy(faker.lorem, 'sentences'); sinon.stub(faker.random, 'number').returns(2); - var paragraph = faker.lorem.paragraph(); + const paragraph = faker.lorem.paragraph(); assert.ok(typeof paragraph === 'string'); - var parts = paragraph.split('\n'); + const parts = paragraph.split('\n'); assert.strictEqual(parts.length, 5); // default 3 plus stubbed 2. assert.ok(faker.lorem.sentences.calledWith(5)); @@ -182,14 +184,14 @@ describe('lorem.js', function () { }); }); - context("when 'wordCount' param passed in", function () { - it("returns a string of at least the requested number of sentences", function () { + context("when 'wordCount' param passed in", () =>{ + it("returns a string of at least the requested number of sentences", () =>{ sinon.spy(faker.lorem, 'sentences'); sinon.stub(faker.random, 'number').returns(2); - var paragraph = faker.lorem.paragraph(10); + const paragraph = faker.lorem.paragraph(10); assert.ok(typeof paragraph === 'string'); - var parts = paragraph.split('\n'); + const parts = paragraph.split('\n'); assert.strictEqual(parts.length, 12); // requested 10 plus stubbed 2. assert.ok(faker.lorem.sentences.calledWith(12)); @@ -202,14 +204,14 @@ describe('lorem.js', function () { /* - describe("paragraphs()", function () { - context("when no 'paragraphCount' param passed in", function () { - it("returns newline-separated string of three paragraphs", function () { + describe("paragraphs()", () =>{ + context("when no 'paragraphCount' param passed in", () =>{ + it("returns newline-separated string of three paragraphs", () =>{ sinon.spy(faker.lorem, 'paragraph'); - var paragraphs = faker.lorem.paragraphs(); + const paragraphs = faker.lorem.paragraphs(); assert.ok(typeof paragraphs === 'string'); - var parts = paragraphs.split('\n \r'); + const parts = paragraphs.split('\n \r'); assert.strictEqual(parts.length, 3); assert.ok(faker.lorem.paragraph.calledThrice); @@ -217,13 +219,13 @@ describe('lorem.js', function () { }); }); - context("when 'paragraphCount' param passed in", function () { - it("returns newline-separated string of requested number of paragraphs", function () { + context("when 'paragraphCount' param passed in", () =>{ + it("returns newline-separated string of requested number of paragraphs", () =>{ sinon.spy(faker.lorem, 'paragraph'); - var paragraphs = faker.lorem.paragraphs(5); + const paragraphs = faker.lorem.paragraphs(5); assert.ok(typeof paragraphs === 'string'); - var parts = paragraphs.split('\n \r'); + const parts = paragraphs.split('\n \r'); assert.strictEqual(parts.length, 5); faker.lorem.paragraph.restore(); diff --git a/test/mocha.opts b/test/mocha.opts deleted file mode 100644 index 2fc3747d..00000000 --- a/test/mocha.opts +++ /dev/null @@ -1,5 +0,0 @@ ---reporter spec ---ui bdd ---globals state,newBlocks,params,type,__coverage__ ---timeout 6500 ---slow 200 diff --git a/test/music.spec.ts b/test/music.spec.ts new file mode 100644 index 00000000..a2351dfd --- /dev/null +++ b/test/music.spec.ts @@ -0,0 +1,14 @@ +import { describe, expect, it } from 'vitest'; +import { faker } from '../lib'; + +faker.seed(1234); + +describe('music', () => { + describe('genre()', () => { + it('returns a genre', () => { + const genre = faker.music.genre(); + + expect(genre).toBe('Electronic'); + }); + }); +}); diff --git a/test/music.unit.js b/test/music.unit.js deleted file mode 100644 index e7d1d97b..00000000 --- a/test/music.unit.js +++ /dev/null @@ -1,17 +0,0 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var sinon = require('sinon'); - var faker = require('../lib').faker; -} - -describe('music.js', function () { - describe('genre()', function () { - it('returns a genre', function () { - sinon.stub(faker.music, 'genre').returns('Rock'); - var genre = faker.music.genre(); - - assert.strictEqual(genre, 'Rock'); - faker.music.genre.restore(); - }); - }); -}); diff --git a/test/name.spec.ts b/test/name.spec.ts new file mode 100644 index 00000000..b8f30ab2 --- /dev/null +++ b/test/name.spec.ts @@ -0,0 +1,335 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { faker } from '../lib'; + +function assertInArray<T>(value: T, array: readonly T[]): void { + const idx = array.indexOf(value); + expect(idx).not.toBe(-1); +} + +describe('name', () => { + describe('firstName()', () => { + it('returns a random name', () => { + const spy_name_firstName = vi + .spyOn(faker.name, 'firstName') + .mockReturnValue('foo'); + + const first_name = faker.name.firstName(); + + expect(first_name).toBe('foo'); + + spy_name_firstName.mockRestore(); + }); + + it('returns a gender-specific name when passed a number', () => { + for (let q = 0; q < 30; q++) { + const gender = Math.floor(Math.random() * 2); + const name = faker.name.firstName(gender); + if (gender === 0) { + assertInArray(name, faker.definitions.name.male_first_name); + } else { + assertInArray(name, faker.definitions.name.female_first_name); + } + } + }); + + it('returns a gender-specific name when passed a string', () => { + for (let q = 0; q < 30; q++) { + const gender = Math.floor(Math.random() * 2); + const genderString = gender === 0 ? 'male' : 'female'; + const name = faker.name.firstName(genderString); + assertInArray( + name, + faker.definitions.name[genderString + '_first_name'] + ); + } + }); + }); + + describe('lastName()', () => { + it('returns a random name', () => { + const spy_name_lastName = vi + .spyOn(faker.name, 'lastName') + .mockReturnValue('foo'); + + const last_name = faker.name.lastName(); + + expect(last_name).toBe('foo'); + + spy_name_lastName.mockRestore(); + }); + }); + + describe('middleName()', () => { + it('returns a random middle name', () => { + const spy_name_middleName = vi + .spyOn(faker.name, 'middleName') + .mockReturnValue('foo'); + + const middle_name = faker.name.middleName(); + + expect(middle_name).toBe('foo'); + + spy_name_middleName.mockRestore(); + }); + + describe('when using a locale with gender specific middle names', () => { + let oldLocale: string; + + beforeEach(() => { + oldLocale = faker.locale; + faker.locale = 'TEST'; + + // @ts-expect-error + faker.locales.TEST = { + name: { + male_middle_name: ['Genaddiesvich'], + female_middle_name: ['Genaddievna'], + }, + }; + }); + + afterEach(() => { + faker.locale = oldLocale; + // @ts-expect-error + delete faker.locale.TEST; + }); + + it('returns male prefix', () => { + const middle_name = faker.name.middleName(0); + + expect(middle_name).toBe('Genaddiesvich'); + }); + + it('returns female prefix', () => { + const middle_name = faker.name.middleName(1); + + expect(middle_name).toBe('Genaddievna'); + }); + }); + }); + + describe('findName()', () => { + it('usually returns a first name and last name', () => { + const spy_datatype_number = vi + .spyOn(faker.datatype, 'number') + .mockReturnValue(5); + + const name = faker.name.findName(); + + expect(name).toBeTruthy(); + + const parts = name.split(' '); + + expect(parts).toHaveLength(2); + + spy_datatype_number.mockRestore(); + }); + + it('occasionally returns a first name and last name with a prefix', () => { + const spy_datatype_number = vi + .spyOn(faker.datatype, 'number') + .mockReturnValue(0); + + const name = faker.name.findName(); + const parts = name.split(' '); + + expect(parts.length).greaterThanOrEqual(3); + + spy_datatype_number.mockRestore(); + }); + + it('occasionally returns a male full name with a prefix', () => { + const spy_datatype_number = vi + .spyOn(faker.datatype, 'number') + .mockImplementation((opt) => + opt === 8 + ? 0 // with prefix + : opt === 1 + ? 0 // gender male + : undefined + ); + + const spy_name_prefix = vi + .spyOn(faker.name, 'prefix') + .mockImplementation((arg) => (arg === 0 ? 'X' : undefined)); + const spy_name_firstName = vi + .spyOn(faker.name, 'firstName') + .mockImplementation((arg) => (arg === 0 ? 'Y' : undefined)); + const spy_name_lastName = vi + .spyOn(faker.name, 'lastName') + .mockImplementation((arg) => (arg === 0 ? 'Z' : undefined)); + + const name = faker.name.findName(); + + expect(name).toBe('X Y Z'); + + spy_datatype_number.mockRestore(); + spy_name_prefix.mockRestore(); + spy_name_firstName.mockRestore(); + spy_name_lastName.mockRestore(); + }); + + it('occasionally returns a female full name with a prefix', () => { + const spy_datatype_number = vi + .spyOn(faker.datatype, 'number') + .mockImplementation((opt) => + opt === 8 + ? 0 // with prefix + : opt === 1 + ? 1 // gender female + : undefined + ); + + const spy_name_prefix = vi + .spyOn(faker.name, 'prefix') + .mockImplementation((arg) => (arg === 1 ? 'J' : undefined)); + const spy_name_firstName = vi + .spyOn(faker.name, 'firstName') + .mockImplementation((arg) => (arg === 1 ? 'K' : undefined)); + const spy_name_lastName = vi + .spyOn(faker.name, 'lastName') + .mockImplementation((arg) => (arg === 1 ? 'L' : undefined)); + + const name = faker.name.findName(); + + expect(name).toBe('J K L'); + + spy_datatype_number.mockRestore(); + spy_name_prefix.mockRestore(); + spy_name_firstName.mockRestore(); + spy_name_lastName.mockRestore(); + }); + + it('occasionally returns a first name and last name with a suffix', () => { + const spy_datatype_number = vi + .spyOn(faker.datatype, 'number') + .mockReturnValue(1); + const spy_name_suffix = vi + .spyOn(faker.name, 'suffix') + .mockReturnValue('Jr.'); + + const name = faker.name.findName(); + const parts = name.split(' '); + + expect(parts.length).greaterThanOrEqual(3); + expect(parts[parts.length - 1]).toBe('Jr.'); + + spy_name_suffix.mockRestore(); + spy_datatype_number.mockRestore(); + }); + + it.todo( + 'needs to work with specific locales and respect the fallbacks', + () => { + faker.locale = 'en_US'; + // this will throw if this is broken + const name = faker.name.findName(); + // TODO @Shinigami92 2022-01-20: This test doesn't check anything + } + ); + }); + + describe('title()', () => { + it('returns a random title', () => { + const spy_name_title = vi + .spyOn(faker.name, 'title') + .mockReturnValue('Lead Solutions Supervisor'); + + const title = faker.name.title(); + + expect(title).toBe('Lead Solutions Supervisor'); + + spy_name_title.mockRestore(); + }); + }); + + describe('jobTitle()', () => { + it('returns a job title consisting of a descriptor, area, and type', () => { + const spy_random_arrayElement = vi.spyOn(faker.random, 'arrayElement'); + const spy_name_jobDescriptor = vi.spyOn(faker.name, 'jobDescriptor'); + const spy_name_jobArea = vi.spyOn(faker.name, 'jobArea'); + const spy_name_jobType = vi.spyOn(faker.name, 'jobType'); + + const jobTitle = faker.name.jobTitle(); + + expect(typeof jobTitle).toBe('string'); + expect(spy_random_arrayElement).toHaveBeenCalledTimes(3); + expect(spy_name_jobDescriptor).toHaveBeenCalledOnce(); + expect(spy_name_jobArea).toHaveBeenCalledOnce(); + expect(spy_name_jobType).toHaveBeenCalledOnce(); + + spy_random_arrayElement.mockRestore(); + spy_name_jobDescriptor.mockRestore(); + spy_name_jobArea.mockRestore(); + spy_name_jobType.mockRestore(); + }); + }); + + describe('prefix()', () => { + describe('when using a locale with gender specific name prefixes', () => { + let oldLocale: string; + + beforeEach(() => { + oldLocale = faker.locale; + faker.locale = 'TEST'; + + // @ts-expect-error + faker.locales.TEST = { + name: { + male_prefix: ['Mp'], + female_prefix: ['Fp'], + }, + }; + }); + + afterEach(() => { + faker.locale = oldLocale; + // @ts-expect-error + delete faker.locale.TEST; + }); + + it('returns male prefix', () => { + const prefix = faker.name.prefix(0); + expect(prefix).toBe('Mp'); + }); + + it('returns female prefix', () => { + const prefix = faker.name.prefix(1); + expect(prefix).toBe('Fp'); + }); + + it('returns either prefix', () => { + const prefix = faker.name.prefix(); + expect(['Mp', 'Fp']).toContain(prefix); + }); + }); + + describe('when using a locale without gender specific name prefixes', () => { + let oldLocale: string; + + beforeEach(() => { + oldLocale = faker.locale; + faker.locale = 'TEST'; + + // @ts-expect-error + faker.locales.TEST = { + name: { + prefix: ['P'], + }, + }; + }); + + afterEach(() => { + faker.locale = oldLocale; + // @ts-expect-error + delete faker.locale.TEST; + }); + + it('returns a prefix', () => { + const prefix = faker.name.prefix(); + + expect(prefix).toBe('P'); + }); + }); + }); +}); diff --git a/test/name.unit.js b/test/name.unit.js deleted file mode 100644 index 040cac47..00000000 --- a/test/name.unit.js +++ /dev/null @@ -1,282 +0,0 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var sinon = require('sinon'); - var faker = require('../lib').faker; -} - -function assertInArray(value, array) { - var idx = array.indexOf(value); - assert.notEqual(idx, -1); -} - -describe('name.js', function () { - describe('firstName()', function () { - it('returns a random name', function () { - sinon.stub(faker.name, 'firstName').returns('foo'); - var first_name = faker.name.firstName(); - - assert.strictEqual(first_name, 'foo'); - - faker.name.firstName.restore(); - }); - - it('returns a gender-specific name when passed a number', function () { - for (var q = 0; q < 30; q++) { - var gender = Math.floor(Math.random() * 2); - var name = faker.name.firstName(gender); - if (gender === 0) { - assertInArray(name, faker.definitions.name.male_first_name); - } else { - assertInArray(name, faker.definitions.name.female_first_name); - } - } - }); - - it('returns a gender-specific name when passed a string', function () { - for (var q = 0; q < 30; q++) { - var gender = Math.floor(Math.random() * 2); - var genderString = gender === 0 ? 'male' : 'female'; - var name = faker.name.firstName(genderString); - assertInArray( - name, - faker.definitions.name[genderString + '_first_name'] - ); - } - }); - }); - - describe('lastName()', function () { - it('returns a random name', function () { - sinon.stub(faker.name, 'lastName').returns('foo'); - - var last_name = faker.name.lastName(); - - assert.strictEqual(last_name, 'foo'); - - faker.name.lastName.restore(); - }); - }); - - describe('middleName()', function () { - it('returns a random middle name', function () { - sinon.stub(faker.name, 'middleName').returns('foo'); - - var middle_name = faker.name.middleName(); - - assert.strictEqual(middle_name, 'foo'); - - faker.name.middleName.restore(); - }); - - describe('when using a locale with gender specific middle names', function () { - beforeEach(function () { - this.oldLocale = faker.locale; - faker.locale = 'TEST'; - - faker.locales['TEST'] = { - name: { - male_middle_name: ['Genaddiesvich'], - female_middle_name: ['Genaddievna'], - }, - }; - }); - - afterEach(function () { - faker.locale = this.oldLocale; - delete faker.locale['TEST']; - }); - - it('returns male prefix', function () { - var middle_name = faker.name.middleName(0); - - assert.strictEqual(middle_name, 'Genaddiesvich'); - }); - - it('returns female prefix', function () { - var middle_name = faker.name.middleName(1); - - assert.strictEqual(middle_name, 'Genaddievna'); - }); - }); - }); - - describe('findName()', function () { - it('usually returns a first name and last name', function () { - sinon.stub(faker.datatype, 'number').returns(5); - var name = faker.name.findName(); - assert.ok(name); - var parts = name.split(' '); - - assert.strictEqual(parts.length, 2); - - faker.datatype.number.restore(); - }); - - it('occasionally returns a first name and last name with a prefix', function () { - sinon.stub(faker.datatype, 'number').returns(0); - var name = faker.name.findName(); - var parts = name.split(' '); - - assert.ok(parts.length >= 3); - - faker.datatype.number.restore(); - }); - - it('occasionally returns a male full name with a prefix', function () { - sinon - .stub(faker.datatype, 'number') - .withArgs(8) - .returns(0) // with prefix - .withArgs(1) - .returns(0); // gender male - - sinon.stub(faker.name, 'prefix').withArgs(0).returns('X'); - sinon.stub(faker.name, 'firstName').withArgs(0).returns('Y'); - sinon.stub(faker.name, 'lastName').withArgs(0).returns('Z'); - - var name = faker.name.findName(); - - assert.strictEqual(name, 'X Y Z'); - - faker.datatype.number.restore(); - faker.name.prefix.restore(); - faker.name.firstName.restore(); - faker.name.lastName.restore(); - }); - - it('occasionally returns a female full name with a prefix', function () { - sinon - .stub(faker.datatype, 'number') - .withArgs(8) - .returns(0) // with prefix - .withArgs(1) - .returns(1); // gender female - - sinon.stub(faker.name, 'prefix').withArgs(1).returns('J'); - sinon.stub(faker.name, 'firstName').withArgs(1).returns('K'); - sinon.stub(faker.name, 'lastName').withArgs(1).returns('L'); - - var name = faker.name.findName(); - - assert.strictEqual(name, 'J K L'); - - faker.datatype.number.restore(); - faker.name.prefix.restore(); - faker.name.firstName.restore(); - faker.name.lastName.restore(); - }); - - it('occasionally returns a first name and last name with a suffix', function () { - sinon.stub(faker.datatype, 'number').returns(1); - sinon.stub(faker.name, 'suffix').returns('Jr.'); - var name = faker.name.findName(); - var parts = name.split(' '); - - assert.ok(parts.length >= 3); - assert.strictEqual(parts[parts.length - 1], 'Jr.'); - - faker.name.suffix.restore(); - faker.datatype.number.restore(); - }); - - it('needs to work with specific locales and respect the fallbacks', function () { - faker.locale = 'en_US'; - // this will throw if this is broken - var name = faker.name.findName(); - }); - }); - - describe('title()', function () { - it('returns a random title', function () { - sinon.stub(faker.name, 'title').returns('Lead Solutions Supervisor'); - - var title = faker.name.title(); - - assert.strictEqual(title, 'Lead Solutions Supervisor'); - - faker.name.title.restore(); - }); - }); - - describe('jobTitle()', function () { - it('returns a job title consisting of a descriptor, area, and type', function () { - sinon.spy(faker.random, 'arrayElement'); - sinon.spy(faker.name, 'jobDescriptor'); - sinon.spy(faker.name, 'jobArea'); - sinon.spy(faker.name, 'jobType'); - var jobTitle = faker.name.jobTitle(); - - assert.ok(typeof jobTitle === 'string'); - assert.ok(faker.random.arrayElement.calledThrice); - assert.ok(faker.name.jobDescriptor.calledOnce); - assert.ok(faker.name.jobArea.calledOnce); - assert.ok(faker.name.jobType.calledOnce); - - faker.random.arrayElement.restore(); - faker.name.jobDescriptor.restore(); - faker.name.jobArea.restore(); - faker.name.jobType.restore(); - }); - }); - - describe('prefix()', function () { - describe('when using a locale with gender specific name prefixes', function () { - beforeEach(function () { - this.oldLocale = faker.locale; - faker.locale = 'TEST'; - - faker.locales['TEST'] = { - name: { - male_prefix: ['Mp'], - female_prefix: ['Fp'], - }, - }; - }); - - afterEach(function () { - faker.locale = this.oldLocale; - delete faker.locale['TEST']; - }); - - it('returns male prefix', function () { - var prefix = faker.name.prefix(0); - assert.strictEqual(prefix, 'Mp'); - }); - - it('returns female prefix', function () { - var prefix = faker.name.prefix(1); - - assert.strictEqual(prefix, 'Fp'); - }); - - it('returns either prefix', function () { - var prefix = faker.name.prefix(); - assert(['Mp', 'Fp'].indexOf(prefix) >= 0); - }); - }); - - describe('when using a locale without gender specific name prefixes', function () { - beforeEach(function () { - this.oldLocale = faker.locale; - faker.locale = 'TEST'; - - faker.locales['TEST'] = { - name: { - prefix: ['P'], - }, - }; - }); - - afterEach(function () { - faker.locale = this.oldLocale; - delete faker.locale['TEST']; - }); - - it('returns a prefix', function () { - var prefix = faker.name.prefix(); - - assert.strictEqual(prefix, 'P'); - }); - }); - }); -}); diff --git a/test/phone_number.spec.ts b/test/phone_number.spec.ts new file mode 100644 index 00000000..2aef409c --- /dev/null +++ b/test/phone_number.spec.ts @@ -0,0 +1,47 @@ +import { describe, expect, it, vi } from 'vitest'; +import { faker } from '../lib'; + +describe('phone_number.js', () => { + describe('phoneNumber()', () => { + it('returns a random phoneNumber with a random format', () => { + const spy_helpers_replaceSymbolWithNumber = vi.spyOn( + faker.helpers, + 'replaceSymbolWithNumber' + ); + + const phone_number = faker.phone.phoneNumber(); + + expect(phone_number).match(/\d/); + expect(spy_helpers_replaceSymbolWithNumber).toHaveBeenCalled(); + + spy_helpers_replaceSymbolWithNumber.mockRestore(); + }); + }); + + describe('phoneNumberFormat()', () => { + it('returns phone number with requested format (Array index)', () => { + faker.locale = 'en'; + for (let i = 0; i < 10; i++) { + const phone_number = faker.phone.phoneNumberFormat(1); + expect(phone_number).match(/\(\d\d\d\) \d\d\d-\d\d\d\d/); + } + }); + + it('returns phone number with proper format US (Array index)', () => { + faker.locale = 'en'; + for (let i = 0; i < 25; i++) { + const phone_number = faker.phone.phoneNumberFormat(1); + console.log(phone_number); + expect(phone_number).match(/\([2-9]\d\d\) [2-9]\d\d-\d\d\d\d/); + } + }); + + it('returns phone number with proper format CA (Array index)', () => { + faker.locale = 'en_CA'; + for (let i = 0; i < 25; i++) { + const phone_number = faker.phone.phoneNumberFormat(1); + expect(phone_number).match(/\([2-9]\d\d\)[2-9]\d\d-\d\d\d\d/); + } + }); + }); +}); diff --git a/test/phone_number.unit.js b/test/phone_number.unit.js deleted file mode 100644 index 7cb3af41..00000000 --- a/test/phone_number.unit.js +++ /dev/null @@ -1,46 +0,0 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var sinon = require('sinon'); - var faker = require('../lib').faker; -} - -describe('phone_number.js', function () { - describe('phoneNumber()', function () { - it('returns a random phoneNumber with a random format', function () { - sinon.spy(faker.helpers, 'replaceSymbolWithNumber'); - var phone_number = faker.phone.phoneNumber(); - - assert.ok(phone_number.match(/\d/)); - assert.ok(faker.helpers.replaceSymbolWithNumber.called); - - faker.helpers.replaceSymbolWithNumber.restore(); - }); - }); - - describe('phoneNumberFormat()', function () { - it('returns phone number with requested format (Array index)', function () { - faker.locale = 'en'; - for (var i = 0; i < 10; i++) { - var phone_number = faker.phone.phoneNumberFormat(1); - assert.ok(phone_number.match(/\(\d\d\d\) \d\d\d-\d\d\d\d/)); - } - }); - - it('returns phone number with proper format US (Array index)', function () { - faker.locale = 'en'; - for (var i = 0; i < 25; i++) { - var phone_number = faker.phone.phoneNumberFormat(1); - console.log(phone_number); - assert.ok(phone_number.match(/\([2-9]\d\d\) [2-9]\d\d-\d\d\d\d/)); - } - }); - - it('returns phone number with proper format CA (Array index)', function () { - faker.locale = 'en_CA'; - for (var i = 0; i < 25; i++) { - var phone_number = faker.phone.phoneNumberFormat(1); - assert.ok(phone_number.match(/\([2-9]\d\d\)[2-9]\d\d-\d\d\d\d/)); - } - }); - }); -}); diff --git a/test/random.spec.ts b/test/random.spec.ts new file mode 100644 index 00000000..f2e17a7e --- /dev/null +++ b/test/random.spec.ts @@ -0,0 +1,259 @@ +import { describe, expect, it, vi } from 'vitest'; +import { faker } from '../lib'; +import { Mersenne } from '../lib/mersenne'; + +const mersenne = new Mersenne(); + +describe('random.js', () => { + describe('number', () => { + it('random.number() uses datatype module and prints deprecation warning', () => { + const spy_console_log = vi.spyOn(console, 'log'); + const spy_datatype_number = vi.spyOn(faker.datatype, 'number'); + faker.random.number(); + expect(spy_datatype_number).toHaveBeenCalled(); + expect(spy_console_log).toHaveBeenCalledWith( + 'Deprecation Warning: faker.random.number is now located in faker.datatype.number' + ); + spy_datatype_number.mockRestore(); + spy_console_log.mockRestore(); + }); + + it('should return deterministic results when seeded with integer', () => { + faker.seed(100); + const name = faker.name.findName(); + expect(name).toBe('Eva Jenkins'); + }); + + it('should return deterministic results when seeded with 0', () => { + faker.seed(0); + const name = faker.name.findName(); + expect(name).toBe('Lola Sporer'); + }); + + it('should return deterministic results when seeded with array - one element', () => { + faker.seed([10]); + const name = faker.name.findName(); + expect(name).toBe('Duane Kshlerin'); + }); + + it('should return deterministic results when seeded with array - multiple elements', () => { + faker.seed([10, 100, 1000]); + const name = faker.name.findName(); + expect(name).toBe('Alma Shanahan'); + }); + }); + + describe('float', () => { + it('random.float() uses datatype module and prints deprecation warning', () => { + const spy_console_log = vi.spyOn(console, 'log'); + const spy_datatype_float = vi.spyOn(faker.datatype, 'float'); + faker.random.float(); + expect(spy_datatype_float).toHaveBeenCalled(); + expect(spy_console_log).toHaveBeenCalledWith( + 'Deprecation Warning: faker.random.float is now located in faker.datatype.float' + ); + spy_datatype_float.mockRestore(); + spy_console_log.mockRestore(); + }); + }); + + describe('arrayElement', () => { + it('returns a random element in the array', () => { + const testArray = ['hello', 'to', 'you', 'my', 'friend']; + expect( + testArray.indexOf(faker.random.arrayElement(testArray)) + ).greaterThan(-1); + }); + + it('returns a random element in the array when there is only 1', () => { + const testArray = ['hello']; + expect( + testArray.indexOf(faker.random.arrayElement(testArray)) + ).greaterThan(-1); + }); + }); + + describe('arrayElements', () => { + it('returns a subset with random elements in the array', () => { + const testArray = ['hello', 'to', 'you', 'my', 'friend']; + const subset = faker.random.arrayElements(testArray); + + // Check length + expect(subset.length).greaterThanOrEqual(1); + expect(subset.length).lessThanOrEqual(testArray.length); + + // Check elements + subset.forEach((element) => { + expect(testArray).toContain(element); + }); + + // Check uniqueness + subset.forEach((element) => { + expect(!Object.hasOwnProperty(element)).toBe(true); + subset[element] = true; + }, {}); + }); + + it('returns a subset of fixed length with random elements in the array', () => { + const testArray = ['hello', 'to', 'you', 'my', 'friend']; + const subset = faker.random.arrayElements(testArray, 3); + + // Check length + expect(subset).toHaveLength(3); + + // Check elements + subset.forEach((element) => { + expect(testArray).toContain(element); + }); + + // Check uniqueness + subset.forEach((element) => { + expect(!Object.hasOwnProperty(element)).toBe(true); + subset[element] = true; + }, {}); + }); + }); + + describe('UUID', () => { + it('random.uuid() uses datatype module and prints deprecation warning', () => { + const spy_console_log = vi.spyOn(console, 'log'); + const spy_datatype_uuid = vi.spyOn(faker.datatype, 'uuid'); + faker.random.uuid(); + expect(spy_datatype_uuid).toHaveBeenCalled(); + expect(spy_console_log).toHaveBeenCalledWith( + 'Deprecation Warning: faker.random.uuid is now located in faker.datatype.uuid' + ); + spy_datatype_uuid.mockRestore(); + spy_console_log.mockRestore(); + }); + }); + + describe('boolean', () => { + it('random.boolean() uses datatype module and prints deprecation warning', () => { + const spy_console_log = vi.spyOn(console, 'log'); + const spy_datatype_boolean = vi.spyOn(faker.datatype, 'boolean'); + faker.random.boolean(); + expect(spy_datatype_boolean).toHaveBeenCalled(); + expect(spy_console_log).toHaveBeenCalledWith( + 'Deprecation Warning: faker.random.boolean is now located in faker.datatype.boolean' + ); + spy_datatype_boolean.mockRestore(); + spy_console_log.mockRestore(); + }); + }); + + describe('semver', () => { + const semver = faker.system.semver(); + + it('should generate a string', () => { + expect(typeof semver).toBe('string'); + }); + + it('should generate a valid semver', () => { + expect(semver).match(/^\d+\.\d+\.\d+$/); + }); + }); + + describe('alpha', () => { + const alpha = faker.random.alpha; + + it('should return single letter when no count provided', () => { + expect(alpha()).toHaveLength(1); + }); + + it('should return lowercase letter when no upcase option provided', () => { + expect(alpha()).match(/[a-z]/); + }); + + it('should return uppercase when upcase option is true', () => { + expect( + alpha( + // @ts-expect-error + { upcase: true } + ) + ).match(/[A-Z]/); + }); + + it('should generate many random letters', () => { + expect(alpha(5)).toHaveLength(5); + }); + + it('should be able to ban some characters', () => { + const alphaText = alpha( + 5, + // @ts-expect-error + { bannedChars: ['a', 'p'] } + ); + expect(alphaText).toHaveLength(5); + expect(alphaText).match(/[b-oq-z]/); + }); + it('should be able handle mistake in banned characters array', () => { + const alphaText = alpha( + 5, + // @ts-expect-error + { bannedChars: ['a', 'a', 'p'] } + ); + expect(alphaText).toHaveLength(5); + expect(alphaText).match(/[b-oq-z]/); + }); + }); + + describe('alphaNumeric', () => { + const alphaNumeric = faker.random.alphaNumeric; + + it('should generate single character when no additional argument was provided', () => { + expect(alphaNumeric()).toHaveLength(1); + }); + + it('should generate many random characters', () => { + expect(alphaNumeric(5)).toHaveLength(5); + }); + + it('should be able to ban some characters', () => { + const alphaText = alphaNumeric(5, { bannedChars: ['a', 'p'] }); + expect(alphaText).toHaveLength(5); + expect(alphaText).match(/[b-oq-z]/); + }); + it('should be able handle mistake in banned characters array', () => { + const alphaText = alphaNumeric(5, { bannedChars: ['a', 'p', 'a'] }); + expect(alphaText).toHaveLength(5); + expect(alphaText).match(/[b-oq-z]/); + }); + }); + + describe('hexaDecimal', () => { + it('random.hexaDecimal() uses datatype module and prints deprecation warning', () => { + const spy_console_log = vi.spyOn(console, 'log'); + const spy_datatype_hexaDecimal = vi.spyOn(faker.datatype, 'hexaDecimal'); + faker.random.hexaDecimal(); + expect(spy_datatype_hexaDecimal).toHaveBeenCalled(); + expect(spy_console_log).toHaveBeenCalledWith( + 'Deprecation Warning: faker.random.hexaDecimal is now located in faker.datatype.hexaDecimal' + ); + spy_datatype_hexaDecimal.mockRestore(); + spy_console_log.mockRestore(); + }); + }); + + describe('mersenne twister', () => { + it('returns a random number without given min / max arguments', () => { + const randomNumber = mersenne.rand(); + expect(typeof randomNumber).toBe('number'); + }); + + it('throws an error when attempting to seed() a non-integer', () => { + expect(() => + mersenne.seed( + // @ts-expect-error + 'abc' + ) + ).toThrowError(Error('seed(S) must take numeric argument; is string')); + }); + + it('throws an error when attempting to seed() a non-integer', () => { + expect(() => mersenne.seed_array('abc')).toThrowError( + Error('seed_array(A) must take array of numbers; is string') + ); + }); + }); +}); diff --git a/test/random.unit.js b/test/random.unit.js deleted file mode 100644 index c57a8dbc..00000000 --- a/test/random.unit.js +++ /dev/null @@ -1,251 +0,0 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var sinon = require('sinon'); - var _ = require('lodash'); - var faker = require('../lib').faker; - var mersenne = new (require('../lib/mersenne').Mersenne)(); -} - -describe('random.js', function () { - describe('number', function () { - it('random.number() uses datatype module and prints deprecation warning', function () { - sinon.spy(console, 'log'); - sinon.spy(faker.datatype, 'number'); - faker.random.number(); - assert.ok(faker.datatype.number.called); - assert.ok( - console.log.calledWith( - 'Deprecation Warning: faker.random.number is now located in faker.datatype.number' - ) - ); - faker.datatype.number.restore(); - console.log.restore(); - }); - - it('should return deterministic results when seeded with integer', function () { - faker.seed(100); - var name = faker.name.findName(); - assert.strictEqual(name, 'Eva Jenkins'); - }); - - it('should return deterministic results when seeded with 0', function () { - faker.seed(0); - var name = faker.name.findName(); - assert.strictEqual(name, 'Lola Sporer'); - }); - - it('should return deterministic results when seeded with array - one element', function () { - faker.seed([10]); - var name = faker.name.findName(); - assert.strictEqual(name, 'Duane Kshlerin'); - }); - - it('should return deterministic results when seeded with array - multiple elements', function () { - faker.seed([10, 100, 1000]); - var name = faker.name.findName(); - assert.strictEqual(name, 'Alma Shanahan'); - }); - }); - - describe('float', function () { - it('random.float() uses datatype module and prints deprecation warning', function () { - sinon.spy(console, 'log'); - sinon.spy(faker.datatype, 'float'); - faker.random.float(); - assert.ok(faker.datatype.float.called); - assert.ok( - console.log.calledWith( - 'Deprecation Warning: faker.random.float is now located in faker.datatype.float' - ) - ); - faker.datatype.float.restore(); - console.log.restore(); - }); - }); - - describe('arrayElement', function () { - it('returns a random element in the array', function () { - var testArray = ['hello', 'to', 'you', 'my', 'friend']; - assert.ok(testArray.indexOf(faker.random.arrayElement(testArray)) > -1); - }); - - it('returns a random element in the array when there is only 1', function () { - var testArray = ['hello']; - assert.ok(testArray.indexOf(faker.random.arrayElement(testArray)) > -1); - }); - }); - - describe('arrayElements', function () { - it('returns a subset with random elements in the array', function () { - var testArray = ['hello', 'to', 'you', 'my', 'friend']; - var subset = faker.random.arrayElements(testArray); - - // Check length - assert.ok(subset.length >= 1 && subset.length <= testArray.length); - - // Check elements - subset.forEach(function (element) { - assert.ok(testArray.indexOf(element) > -1); - }); - - // Check uniqueness - subset.forEach(function (element) { - assert.ok(!this.hasOwnProperty(element)); - this[element] = true; - }, {}); - }); - - it('returns a subset of fixed length with random elements in the array', function () { - var testArray = ['hello', 'to', 'you', 'my', 'friend']; - var subset = faker.random.arrayElements(testArray, 3); - - // Check length - assert.ok(subset.length === 3); - - // Check elements - subset.forEach(function (element) { - assert.ok(testArray.indexOf(element) > -1); - }); - - // Check uniqueness - subset.forEach(function (element) { - assert.ok(!this.hasOwnProperty(element)); - this[element] = true; - }, {}); - }); - }); - - describe('UUID', function () { - it('random.uuid() uses datatype module and prints deprecation warning', function () { - sinon.spy(console, 'log'); - sinon.spy(faker.datatype, 'uuid'); - faker.random.uuid(); - assert.ok(faker.datatype.uuid.called); - assert.ok( - console.log.calledWith( - 'Deprecation Warning: faker.random.uuid is now located in faker.datatype.uuid' - ) - ); - faker.datatype.uuid.restore(); - console.log.restore(); - }); - }); - - describe('boolean', function () { - it('random.boolean() uses datatype module and prints deprecation warning', function () { - sinon.spy(console, 'log'); - sinon.spy(faker.datatype, 'boolean'); - faker.random.boolean(); - assert.ok(faker.datatype.boolean.called); - assert.ok( - console.log.calledWith( - 'Deprecation Warning: faker.random.boolean is now located in faker.datatype.boolean' - ) - ); - faker.datatype.boolean.restore(); - console.log.restore(); - }); - }); - - describe('semver', function () { - var semver = faker.system.semver(); - - it('should generate a string', function () { - assert.ok(typeof semver === 'string'); - }); - - it('should generate a valid semver', function () { - assert.ok(/^\d+\.\d+\.\d+$/.test(semver)); - }); - }); - - describe('alpha', function () { - var alpha = faker.random.alpha; - - it('should return single letter when no count provided', function () { - assert.ok(alpha().length === 1); - }); - - it('should return lowercase letter when no upcase option provided', function () { - assert.ok(alpha().match(/[a-z]/)); - }); - - it('should return uppercase when upcase option is true', function () { - assert.ok(alpha({ upcase: true }).match(/[A-Z]/)); - }); - - it('should generate many random letters', function () { - assert.ok(alpha(5).length === 5); - }); - - it('should be able to ban some characters', function () { - var alphaText = alpha(5, { bannedChars: ['a', 'p'] }); - assert.ok(alphaText.length === 5); - assert.ok(alphaText.match(/[b-oq-z]/)); - }); - it('should be able handle mistake in banned characters array', function () { - var alphaText = alpha(5, { bannedChars: ['a', 'a', 'p'] }); - assert.ok(alphaText.length === 5); - assert.ok(alphaText.match(/[b-oq-z]/)); - }); - }); - - describe('alphaNumeric', function () { - var alphaNumeric = faker.random.alphaNumeric; - - it('should generate single character when no additional argument was provided', function () { - assert.ok(alphaNumeric().length === 1); - }); - - it('should generate many random characters', function () { - assert.ok(alphaNumeric(5).length === 5); - }); - - it('should be able to ban some characters', function () { - var alphaText = alphaNumeric(5, { bannedChars: ['a', 'p'] }); - assert.ok(alphaText.length === 5); - assert.ok(alphaText.match(/[b-oq-z]/)); - }); - it('should be able handle mistake in banned characters array', function () { - var alphaText = alphaNumeric(5, { bannedChars: ['a', 'p', 'a'] }); - assert.ok(alphaText.length === 5); - assert.ok(alphaText.match(/[b-oq-z]/)); - }); - }); - - describe('hexaDecimal', function () { - it('random.hexaDecimal() uses datatype module and prints deprecation warning', function () { - sinon.spy(console, 'log'); - sinon.spy(faker.datatype, 'hexaDecimal'); - faker.random.hexaDecimal(); - assert.ok(faker.datatype.hexaDecimal.called); - assert.ok( - console.log.calledWith( - 'Deprecation Warning: faker.random.hexaDecimal is now located in faker.datatype.hexaDecimal' - ) - ); - faker.datatype.hexaDecimal.restore(); - console.log.restore(); - }); - }); - - describe('mersenne twister', function () { - it('returns a random number without given min / max arguments', function () { - var max = 10; - var randomNumber = mersenne.rand(); - assert.ok(typeof randomNumber === 'number'); - }); - - it('throws an error when attempting to seed() a non-integer', function () { - assert.throws(function () { - mersenne.seed('abc'); - }, Error); - }); - - it('throws an error when attempting to seed() a non-integer', function () { - assert.throws(function () { - mersenne.seed_array('abc'); - }, Error); - }); - }); -}); diff --git a/test/run.js b/test/run.js deleted file mode 100755 index ff0c0051..00000000 --- a/test/run.js +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env node -process.env.NODE_ENV = 'test'; - -var fs = require('fs'); -var Mocha = require('mocha'); -var optimist = require('optimist'); -var walk_dir = require('./support/walk_dir'); - -var argv = optimist - .usage('Usage: $0 -t [types] --reporter [reporter] --timeout [timeout]') - .default({ types: 'unit,functional', reporter: 'spec', timeout: 6000 }) - .describe( - 'types', - 'The types of tests to run, separated by commas. E.g., unit,functional,acceptance' - ) - .describe('reporter', 'The mocha test reporter to use.') - .describe('timeout', 'The mocha timeout to use per test (ms).') - .boolean('help') - .alias('types', 'T') - .alias('timeout', 't') - .alias('reporter', 'R') - .alias('help', 'h').argv; - -var mocha = new Mocha({ - timeout: argv.timeout, - reporter: argv.reporter, - ui: 'bdd', -}); - -var valid_test_types = ['unit', 'functional', 'acceptance', 'integration']; -var requested_types = argv.types.split(','); -var types_to_use = []; - -valid_test_types.forEach(function (valid_test_type) { - if (requested_types.indexOf(valid_test_type) !== -1) { - types_to_use.push(valid_test_type); - } -}); - -if (argv.help || types_to_use.length === 0) { - console.log('\n' + optimist.help()); - process.exit(); -} - -var is_valid_file = function (file) { - for (var i = 0; i < types_to_use.length; i++) { - var test_type = types_to_use[i]; - var ext = test_type + '.js'; - - if (file.indexOf(ext) !== -1) { - return true; - } - } - - return false; -}; - -function run(cb) { - walk_dir.walk('test', is_valid_file, function (err, files) { - if (err) { - return cb(err); - } - - files.forEach(function (file) { - mocha.addFile(file); - }); - - cb(); - }); -} - -run(function (err) { - mocha.run(function (failures) { - process.exit(failures); - }); -}); diff --git a/test/support/chai.js b/test/support/chai.js deleted file mode 100644 index 8795090d..00000000 --- a/test/support/chai.js +++ /dev/null @@ -1,3484 +0,0 @@ -!(function (name, definition) { - if (typeof define == 'function' && typeof define.amd == 'object') - define(definition); - else this[name] = definition(); -})('chai', function () { - // CommonJS require() - - function require(p) { - var path = require.resolve(p), - mod = require.modules[path]; - if (!mod) throw new Error('failed to require "' + p + '"'); - if (!mod.exports) { - mod.exports = {}; - mod.call(mod.exports, mod, mod.exports, require.relative(path)); - } - return mod.exports; - } - - require.modules = {}; - - require.resolve = function (path) { - var orig = path, - reg = path + '.js', - index = path + '/index.js'; - return ( - (require.modules[reg] && reg) || (require.modules[index] && index) || orig - ); - }; - - require.register = function (path, fn) { - require.modules[path] = fn; - }; - - require.relative = function (parent) { - return function (p) { - if ('.' != p[0]) return require(p); - - var path = parent.split('/'), - segs = p.split('/'); - path.pop(); - - for (var i = 0; i < segs.length; i++) { - var seg = segs[i]; - if ('..' == seg) path.pop(); - else if ('.' != seg) path.push(seg); - } - - return require(path.join('/')); - }; - }; - - require.register('assertion.js', function (module, exports, require) { - /*! - * chai - * http://chaijs.com - * Copyright(c) 2011-2012 Jake Luer <[email protected]> - * MIT Licensed - */ - - /*! - * Module dependencies. - */ - - var AssertionError = require('./browser/error'), - toString = Object.prototype.toString, - util = require('./utils'), - flag = util.flag; - - /*! - * Module export. - */ - - module.exports = Assertion; - - /*! - * Assertion Constructor - * - * Creates object for chaining. - * - * @api private - */ - - function Assertion(obj, msg, stack) { - flag(this, 'ssfi', stack || arguments.callee); - flag(this, 'object', obj); - flag(this, 'message', msg); - } - - /*! - * ### Assertion.includeStack - * - * User configurable property, influences whether stack trace - * is included in Assertion error message. Default of false - * suppresses stack trace in the error message - * - * Assertion.includeStack = true; // enable stack on error - * - * @api public - */ - - Assertion.includeStack = false; - - Assertion.addProperty = function (name, fn) { - util.addProperty(this.prototype, name, fn); - }; - - Assertion.addMethod = function (name, fn) { - util.addMethod(this.prototype, name, fn); - }; - - Assertion.addChainableMethod = function (name, fn, chainingBehavior) { - util.addChainableMethod(this.prototype, name, fn, chainingBehavior); - }; - - Assertion.overwriteProperty = function (name, fn) { - util.overwriteProperty(this.prototype, name, fn); - }; - - Assertion.overwriteMethod = function (name, fn) { - util.overwriteMethod(this.prototype, name, fn); - }; - - /*! - * ### .assert(expression, message, negateMessage, expected, actual) - * - * Executes an expression and check expectations. Throws AssertionError for reporting if test doesn't pass. - * - * @name assert - * @param {Philosophical} expression to be tested - * @param {String} message to display if fails - * @param {String} negatedMessage to display if negated expression fails - * @param {Mixed} expected value (remember to check for negation) - * @param {Mixed} actual (optional) will default to `this.obj` - * @api private - */ - - Assertion.prototype.assert = function ( - expr, - msg, - negateMsg, - expected, - _actual - ) { - var msg = util.getMessage(this, arguments), - actual = util.getActual(this, arguments), - ok = util.test(this, arguments); - - if (!ok) { - throw new AssertionError({ - message: msg, - actual: actual, - expected: expected, - stackStartFunction: Assertion.includeStack - ? this.assert - : flag(this, 'ssfi'), - }); - } - }; - - /*! - * - * ### ._obj - * - * Quick reference to stored `actual` value for plugin developers. - * - * @api private - */ - - Object.defineProperty(Assertion.prototype, '_obj', { - get: function () { - return flag(this, 'object'); - }, - set: function (val) { - flag(this, 'object', val); - }, - }); - - /** - * ### Language Chains - * - * The following are provide as chainable getters to - * improve the readability of your assertions. They - * do not provide an testing capability unless they - * have been overwritten by a plugin. - * - * **Chains** - * - * - to - * - be - * - been - * - is - * - and - * - have - * - with - * - * @name language chains - * @api public - */ - - ['to', 'be', 'been', 'is', 'and', 'have', 'with'].forEach(function (chain) { - Object.defineProperty(Assertion.prototype, chain, { - get: function () { - return this; - }, - configurable: true, - }); - }); - - /** - * ### .not - * - * Negates any of assertions following in the chain. - * - * expect(foo).to.not.equal('bar'); - * expect(goodFn).to.not.throw(Error); - * expect({ foo: 'baz' }).to.have.property('foo') - * .and.not.equal('bar'); - * - * @name not - * @api public - */ - - Object.defineProperty(Assertion.prototype, 'not', { - get: function () { - flag(this, 'negate', true); - return this; - }, - configurable: true, - }); - - /** - * ### .deep - * - * Sets the `deep` flag, later used by the `equal` and - * `property` assertions. - * - * expect(foo).to.deep.equal({ bar: 'baz' }); - * expect({ foo: { bar: { baz: 'quux' } } }) - * .to.have.deep.property('foo.bar.baz', 'quux'); - * - * @name deep - * @api public - */ - - Object.defineProperty(Assertion.prototype, 'deep', { - get: function () { - flag(this, 'deep', true); - return this; - }, - configurable: true, - }); - - /** - * ### .a(type) - * - * The `a` and `an` assertions are aliases that can be - * used either as language chains or to assert a value's - * type (as revealed by `Object.prototype.toString`). - * - * // typeof - * expect('test').to.be.a('string'); - * expect({ foo: 'bar' }).to.be.an('object'); - * expect(null).to.be.a('null'); - * expect(undefined).to.be.an('undefined'); - * - * // language chain - * expect(foo).to.be.an.instanceof(Foo); - * - * @name a - * @alias an - * @param {String} type - * @api public - */ - - function an(type) { - var obj = flag(this, 'object'), - klassStart = type.charAt(0).toUpperCase(), - klass = klassStart + type.slice(1), - article = ~['A', 'E', 'I', 'O', 'U'].indexOf(klassStart) ? 'an ' : 'a '; - - this.assert( - '[object ' + klass + ']' === toString.call(obj), - 'expected #{this} to be ' + article + type, - 'expected #{this} not to be ' + article + type, - '[object ' + klass + ']', - toString.call(obj) - ); - } - - Assertion.addChainableMethod('an', an); - Assertion.addChainableMethod('a', an); - - /** - * ### .include(value) - * - * The `include` and `contain` assertions can be used as either property - * based language chains or as methods to assert the inclusion of an object - * in an array or a substring in a string. When used as language chains, - * they toggle the `contain` flag for the `keys` assertion. - * - * expect([1,2,3]).to.include(2); - * expect('foobar').to.contain('foo'); - * expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo'); - * - * @name include - * @alias contain - * @param {Object|String|Number} obj - * @api public - */ - - function includeChainingBehavior() { - flag(this, 'contains', true); - } - - function include(val) { - var obj = flag(this, 'object'); - this.assert( - ~obj.indexOf(val), - 'expected #{this} to include ' + util.inspect(val), - 'expected #{this} to not include ' + util.inspect(val) - ); - } - - Assertion.addChainableMethod('include', include, includeChainingBehavior); - Assertion.addChainableMethod('contain', include, includeChainingBehavior); - - /** - * ### .ok - * - * Asserts that the target is truthy. - * - * expect('everything').to.be.ok; - * expect(1).to.be.ok; - * expect(false).to.not.be.ok; - * expect(undefined).to.not.be.ok; - * expect(null).to.not.be.ok; - * - * @name ok - * @api public - */ - - Object.defineProperty(Assertion.prototype, 'ok', { - get: function () { - this.assert( - flag(this, 'object'), - 'expected #{this} to be truthy', - 'expected #{this} to be falsy' - ); - - return this; - }, - configurable: true, - }); - - /** - * ### .true - * - * Asserts that the target is `true`. - * - * expect(true).to.be.true; - * expect(1).to.not.be.true; - * - * @name true - * @api public - */ - - Object.defineProperty(Assertion.prototype, 'true', { - get: function () { - this.assert( - true === flag(this, 'object'), - 'expected #{this} to be true', - 'expected #{this} to be false', - this.negate ? false : true - ); - - return this; - }, - configurable: true, - }); - - /** - * ### .false - * - * Asserts that the target is `false`. - * - * expect(false).to.be.false; - * expect(0).to.not.be.false; - * - * @name false - * @api public - */ - - Object.defineProperty(Assertion.prototype, 'false', { - get: function () { - this.assert( - false === flag(this, 'object'), - 'expected #{this} to be false', - 'expected #{this} to be true', - this.negate ? true : false - ); - - return this; - }, - configurable: true, - }); - - /** - * ### .null - * - * Asserts that the target is `null`. - * - * expect(null).to.be.null; - * expect(undefined).not.to.be.null; - * - * @name null - * @api public - */ - - Object.defineProperty(Assertion.prototype, 'null', { - get: function () { - this.assert( - null === flag(this, 'object'), - 'expected #{this} to be null', - 'expected #{this} not to be null', - this.negate ? false : true - ); - - return this; - }, - configurable: true, - }); - - /** - * ### .undefined - * - * Asserts that the target is `undefined`. - * - * expect(undefined).to.be.undefined; - * expect(null).to.not.be.undefined; - * - * @name undefined - * @api public - */ - - Object.defineProperty(Assertion.prototype, 'undefined', { - get: function () { - this.assert( - undefined === flag(this, 'object'), - 'expected #{this} to be undefined', - 'expected #{this} not to be undefined', - this.negate ? false : true - ); - - return this; - }, - configurable: true, - }); - - /** - * ### .exist - * - * Asserts that the target is neither `null` nor `undefined`. - * - * var foo = 'hi' - * , bar = null - * , baz; - * - * expect(foo).to.exist; - * expect(bar).to.not.exist; - * expect(baz).to.not.exist; - * - * @name exist - * @api public - */ - - Object.defineProperty(Assertion.prototype, 'exist', { - get: function () { - this.assert( - null != flag(this, 'object'), - 'expected #{this} to exist', - 'expected #{this} to not exist' - ); - - return this; - }, - configurable: true, - }); - - /** - * ### .empty - * - * Asserts that the target's length is `0`. For arrays, it checks - * the `length` property. For objects, it gets the count of - * enumerable keys. - * - * expect([]).to.be.empty; - * expect('').to.be.empty; - * expect({}).to.be.empty; - * - * @name empty - * @api public - */ - - Object.defineProperty(Assertion.prototype, 'empty', { - get: function () { - var obj = flag(this, 'object'), - expected = obj; - - if (Array.isArray(obj) || 'string' === typeof object) { - expected = obj.length; - } else if (typeof obj === 'object') { - expected = Object.keys(obj).length; - } - - this.assert( - !expected, - 'expected #{this} to be empty', - 'expected #{this} not to be empty' - ); - - return this; - }, - configurable: true, - }); - - /** - * ### .arguments - * - * Asserts that the target is an arguments object. - * - * function test () { - * expect(arguments).to.be.arguments; - * } - * - * @name arguments - * @alias Arguments - * @api public - */ - - function checkArguments() { - var obj = flag(this, 'object'), - type = Object.prototype.toString.call(obj); - this.assert( - '[object Arguments]' === type, - 'expected #{this} to be arguments but got ' + type, - 'expected #{this} to not be arguments' - ); - } - - Assertion.addProperty('arguments', checkArguments); - Assertion.addProperty('Arguments', checkArguments); - - /** - * ### .equal(value) - * - * Asserts that the target is strictly equal (`===`) to `value`. - * Alternately, if the `deep` flag is set, asserts that - * the target is deeply equal to `value`. - * - * expect('hello').to.equal('hello'); - * expect(42).to.equal(42); - * expect(1).to.not.equal(true); - * expect({ foo: 'bar' }).to.not.equal({ foo: 'bar' }); - * expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' }); - * - * @name equal - * @param {Mixed} value - * @api public - */ - - Assertion.prototype.equal = function (val) { - var obj = flag(this, 'object'); - if (flag(this, 'deep')) { - return this.eql(val); - } else { - this.assert( - val === obj, - 'expected #{this} to equal #{exp}', - 'expected #{this} to not equal #{exp}', - val - ); - } - - return this; - }; - - /** - * ### .eql(value) - * - * Asserts that the target is deeply equal to `value`. - * - * expect({ foo: 'bar' }).to.eql({ foo: 'bar' }); - * expect([ 1, 2, 3 ]).to.eql([ 1, 2, 3 ]); - * - * @name eql - * @param {Mixed} value - * @api public - */ - - Assertion.prototype.eql = function (obj) { - this.assert( - util.eql(obj, flag(this, 'object')), - 'expected #{this} to deeply equal #{exp}', - 'expected #{this} to not deeply equal #{exp}', - obj - ); - - return this; - }; - - /** - * ### .above(value) - * - * Asserts that the target is greater than `value`. - * - * expect(10).to.be.above(5); - * - * @name above - * @alias gt - * @param {Number} value - * @api public - */ - - Assertion.prototype.above = function (val) { - this.assert( - flag(this, 'object') > val, - 'expected #{this} to be above ' + val, - 'expected #{this} to be below ' + val - ); - - return this; - }; - - /** - * ### .below(value) - * - * Asserts that the target is less than `value`. - * - * expect(5).to.be.below(10); - * - * @name below - * @alias lt - * @param {Number} value - * @api public - */ - - Assertion.prototype.below = function (val) { - this.assert( - flag(this, 'object') < val, - 'expected #{this} to be below ' + val, - 'expected #{this} to be above ' + val - ); - - return this; - }; - - /** - * ### .within(start, finish) - * - * Asserts that the target is within a range. - * - * expect(7).to.be.within(5,10); - * - * @name within - * @param {Number} start lowerbound inclusive - * @param {Number} finish upperbound inclusive - * @api public - */ - - Assertion.prototype.within = function (start, finish) { - var obj = flag(this, 'object'), - range = start + '..' + finish; - - this.assert( - obj >= start && obj <= finish, - 'expected #{this} to be within ' + range, - 'expected #{this} to not be within ' + range - ); - - return this; - }; - - /** - * ### .instanceof(constructor) - * - * Asserts that the target is an instance of `constructor`. - * - * var Tea = function (name) { this.name = name; } - * , Chai = new Tea('chai'); - * - * expect(Chai).to.be.an.instanceof(Tea); - * expect([ 1, 2, 3 ]).to.be.instanceof(Array); - * - * @name instanceof - * @param {Constructor} constructor - * @alias instanceOf - * @api public - */ - - Assertion.prototype.instanceOf = function (constructor) { - var name = util.getName(constructor); - this.assert( - flag(this, 'object') instanceof constructor, - 'expected #{this} to be an instance of ' + name, - 'expected #{this} to not be an instance of ' + name - ); - - return this; - }; - - /** - * ### .property(name, [value]) - * - * Asserts that the target has a property `name`, optionally asserting that - * the value of that property is strictly equal to `value`. - * If the `deep` flag is set, you can use dot- and bracket-notation for deep - * references into objects and arrays. - * - * // simple referencing - * var obj = { foo: 'bar' }; - * expect(obj).to.have.property('foo'); - * expect(obj).to.have.property('foo', 'bar'); - * expect(obj).to.have.property('foo').to.be.a('string'); - * - * // deep referencing - * var deepObj = { - * green: { tea: 'matcha' } - * , teas: [ 'chai', 'matcha', { tea: 'konacha' } ] - * }; - - * expect(deepObj).to.have.deep.property('green.tea', 'matcha'); - * expect(deepObj).to.have.deep.property('teas[1]', 'matcha'); - * expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha'); - * - * @name property - * @param {String} name - * @param {Mixed} value (optional) - * @returns value of property for chaining - * @api public - */ - - Assertion.prototype.property = function (name, val) { - var obj = flag(this, 'object'), - value = flag(this, 'deep') ? util.getPathValue(name, obj) : obj[name], - descriptor = flag(this, 'deep') ? 'deep property ' : 'property ', - negate = flag(this, 'negate'); - - if (negate && undefined !== val) { - if (undefined === value) { - throw new Error( - util.inspect(obj) + ' has no ' + descriptor + util.inspect(name) - ); - } - } else { - this.assert( - undefined !== value, - 'expected #{this} to have a ' + descriptor + util.inspect(name), - 'expected #{this} to not have ' + descriptor + util.inspect(name) - ); - } - - if (undefined !== val) { - this.assert( - val === value, - 'expected #{this} to have a ' + - descriptor + - util.inspect(name) + - ' of #{exp}, but got #{act}', - 'expected #{this} to not have a ' + - descriptor + - util.inspect(name) + - ' of #{act}', - val, - value - ); - } - - flag(this, 'object', value); - return this; - }; - - /** - * ### .ownProperty(name) - * - * Asserts that the target has an own property `name`. - * - * expect('test').to.have.ownProperty('length'); - * - * @name ownProperty - * @alias haveOwnProperty - * @param {String} name - * @api public - */ - - Assertion.prototype.ownProperty = function (name) { - var obj = flag(this, 'object'); - this.assert( - obj.hasOwnProperty(name), - 'expected #{this} to have own property ' + util.inspect(name), - 'expected #{this} to not have own property ' + util.inspect(name) - ); - return this; - }; - - /** - * ### .length(value) - * - * Asserts that the target's `length` property has the expected value. - * - * expect([1,2,3]).to.have.length(3); - * expect('foobar').to.have.length(6); - * - * @name length - * @alias lengthOf - * @param {Number} length - * @api public - */ - - Assertion.prototype.length = function (n) { - var obj = flag(this, 'object'); - new Assertion(obj).to.have.property('length'); - var len = obj.length; - - this.assert( - len == n, - 'expected #{this} to have a length of #{exp} but got #{act}', - 'expected #{this} to not have a length of #{act}', - n, - len - ); - - return this; - }; - - /** - * ### .match(regexp) - * - * Asserts that the target matches a regular expression. - * - * expect('foobar').to.match(/^foo/); - * - * @name match - * @param {RegExp} RegularExpression - * @api public - */ - - Assertion.prototype.match = function (re) { - var obj = flag(this, 'object'); - this.assert( - re.exec(obj), - 'expected #{this} to match ' + re, - 'expected #{this} not to match ' + re - ); - - return this; - }; - - /** - * ### .string(string) - * - * Asserts that the string target contains another string. - * - * expect('foobar').to.have.string('bar'); - * - * @name string - * @param {String} string - * @api public - */ - - Assertion.prototype.string = function (str) { - var obj = flag(this, 'object'); - new Assertion(obj).is.a('string'); - - this.assert( - ~obj.indexOf(str), - 'expected #{this} to contain ' + util.inspect(str), - 'expected #{this} to not contain ' + util.inspect(str) - ); - - return this; - }; - - /** - * ### .keys(key1, [key2], [...]) - * - * Asserts that the target has exactly the given keys, or - * asserts the inclusion of some keys when using the - * `include` or `contain` modifiers. - * - * expect({ foo: 1, bar: 2 }).to.have.keys(['foo', 'bar']); - * expect({ foo: 1, bar: 2, baz: 3 }).to.contain.keys('foo', 'bar'); - * - * @name keys - * @alias key - * @param {String...|Array} keys - * @api public - */ - - Assertion.prototype.keys = function (keys) { - var obj = flag(this, 'object'), - str, - ok = true; - - keys = - keys instanceof Array ? keys : Array.prototype.slice.call(arguments); - - if (!keys.length) throw new Error('keys required'); - - var actual = Object.keys(obj), - len = keys.length; - - // Inclusion - ok = keys.every(function (key) { - return ~actual.indexOf(key); - }); - - // Strict - if (!flag(this, 'negate') && !flag(this, 'contains')) { - ok = ok && keys.length == actual.length; - } - - // Key string - if (len > 1) { - keys = keys.map(function (key) { - return util.inspect(key); - }); - var last = keys.pop(); - str = keys.join(', ') + ', and ' + last; - } else { - str = util.inspect(keys[0]); - } - - // Form - str = (len > 1 ? 'keys ' : 'key ') + str; - - // Have / include - str = (flag(this, 'contains') ? 'contain ' : 'have ') + str; - - // Assertion - this.assert( - ok, - 'expected #{this} to ' + str, - 'expected #{this} to not ' + str, - keys, - Object.keys(obj) - ); - - return this; - }; - - /** - * ### .throw(constructor) - * - * Asserts that the function target will throw a specific error, or specific type of error - * (as determined using `instanceof`), optionally with a RegExp or string inclusion test - * for the error's message. - * - * var err = new ReferenceError('This is a bad function.'); - * var fn = function () { throw err; } - * expect(fn).to.throw(ReferenceError); - * expect(fn).to.throw(Error); - * expect(fn).to.throw(/bad function/); - * expect(fn).to.not.throw('good function'); - * expect(fn).to.throw(ReferenceError, /bad function/); - * expect(fn).to.throw(err); - * expect(fn).to.not.throw(new RangeError('Out of range.')); - * - * Please note that when a throw expectation is negated, it will check each - * parameter independently, starting with error constructor type. The appropriate way - * to check for the existence of a type of error but for a message that does not match - * is to use `and`. - * - * expect(fn).to.throw(ReferenceError) - * .and.not.throw(/good function/); - * - * @name throw - * @alias throws - * @alias Throw - * @param {ErrorConstructor} constructor - * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types - * @api public - */ - - Assertion.prototype.Throw = function (constructor, msg) { - var obj = flag(this, 'object'); - new Assertion(obj).is.a('function'); - - var thrown = false, - desiredError = null, - name = null; - - if (arguments.length === 0) { - msg = null; - constructor = null; - } else if ( - constructor && - (constructor instanceof RegExp || 'string' === typeof constructor) - ) { - msg = constructor; - constructor = null; - } else if (constructor && constructor instanceof Error) { - desiredError = constructor; - constructor = null; - msg = null; - } else if (typeof constructor === 'function') { - name = new constructor().name; - } else { - constructor = null; - } - - try { - obj(); - } catch (err) { - // first, check desired error - if (desiredError) { - this.assert( - err === desiredError, - 'expected #{this} to throw ' + - util.inspect(desiredError) + - ' but ' + - util.inspect(err) + - ' was thrown', - 'expected #{this} to not throw ' + util.inspect(desiredError) - ); - return this; - } - // next, check constructor - if (constructor) { - this.assert( - err instanceof constructor, - 'expected #{this} to throw ' + - name + - ' but a ' + - err.name + - ' was thrown', - 'expected #{this} to not throw ' + name - ); - if (!msg) return this; - } - // next, check message - if (err.message && msg && msg instanceof RegExp) { - this.assert( - msg.exec(err.message), - 'expected #{this} to throw error matching ' + - msg + - ' but got ' + - util.inspect(err.message), - 'expected #{this} to throw error not matching ' + msg - ); - return this; - } else if (err.message && msg && 'string' === typeof msg) { - this.assert( - ~err.message.indexOf(msg), - 'expected #{this} to throw error including #{exp} but got #{act}', - 'expected #{this} to throw error not including #{act}', - msg, - err.message - ); - return this; - } else { - thrown = true; - } - } - - var expectedThrown = name - ? name - : desiredError - ? util.inspect(desiredError) - : 'an error'; - - this.assert( - thrown === true, - 'expected #{this} to throw ' + expectedThrown, - 'expected #{this} to not throw ' + expectedThrown - ); - - return this; - }; - - /** - * ### .respondTo(method) - * - * Asserts that the object or class target will respond to a method. - * - * Klass.prototype.bar = function(){}; - * expect(Klass).to.respondTo('bar'); - * expect(obj).to.respondTo('bar'); - * - * To check if a constructor will respond to a static function, - * set the `itself` flag. - * - * Klass.baz = function(){}; - * expect(Klass).itself.to.respondTo('baz'); - * - * @name respondTo - * @param {String} method - * @api public - */ - - Assertion.prototype.respondTo = function (method) { - var obj = flag(this, 'object'), - itself = flag(this, 'itself'), - context = - 'function' === typeof obj && !itself - ? obj.prototype[method] - : obj[method]; - - this.assert( - 'function' === typeof context, - 'expected #{this} to respond to ' + util.inspect(method), - 'expected #{this} to not respond to ' + util.inspect(method), - 'function', - typeof context - ); - - return this; - }; - - /** - * ### .itself - * - * Sets the `itself` flag, later used by the `respondTo` assertion. - * - * function Foo() {} - * Foo.bar = function() {} - * Foo.prototype.baz = function() {} - * - * expect(Foo).itself.to.respondTo('bar'); - * expect(Foo).itself.not.to.respondTo('baz'); - * - * @name itself - * @api public - */ - Object.defineProperty(Assertion.prototype, 'itself', { - get: function () { - flag(this, 'itself', true); - return this; - }, - configurable: true, - }); - - /** - * ### .satisfy(method) - * - * Asserts that the target passes a given truth test. - * - * expect(1).to.satisfy(function(num) { return num > 0; }); - * - * @name satisfy - * @param {Function} matcher - * @api public - */ - - Assertion.prototype.satisfy = function (matcher) { - var obj = flag(this, 'object'); - this.assert( - matcher(obj), - 'expected #{this} to satisfy ' + util.inspect(matcher), - 'expected #{this} to not satisfy' + util.inspect(matcher), - this.negate ? false : true, - matcher(obj) - ); - - return this; - }; - - /** - * ### .closeTo(expected, delta) - * - * Asserts that the target is equal `expected`, to within a +/- `delta` range. - * - * expect(1.5).to.be.closeTo(1, 0.5); - * - * @name closeTo - * @param {Number} expected - * @param {Number} delta - * @api public - */ - - Assertion.prototype.closeTo = function (expected, delta) { - var obj = flag(this, 'object'); - this.assert( - obj - delta === expected || obj + delta === expected, - 'expected #{this} to be close to ' + expected + ' +/- ' + delta, - 'expected #{this} not to be close to ' + expected + ' +/- ' + delta - ); - - return this; - }; - - /*! - * Aliases. - */ - - (function alias(name, as) { - Assertion.prototype[as] = Assertion.prototype[name]; - return alias; - })('equal', 'eq')('above', 'gt')('below', 'lt')('length', 'lengthOf')( - 'keys', - 'key' - )('ownProperty', 'haveOwnProperty')('above', 'greaterThan')( - 'below', - 'lessThan' - )('Throw', 'throws')('Throw', 'throw')('instanceOf', 'instanceof'); - }); // module: assertion.js - - require.register('browser/error.js', function (module, exports, require) { - /*! - * chai - * Copyright(c) 2011-2012 Jake Luer <[email protected]> - * MIT Licensed - */ - - module.exports = AssertionError; - - function AssertionError(options) { - options = options || {}; - this.message = options.message; - this.actual = options.actual; - this.expected = options.expected; - this.operator = options.operator; - - if (options.stackStartFunction && Error.captureStackTrace) { - var stackStartFunction = options.stackStartFunction; - Error.captureStackTrace(this, stackStartFunction); - } - } - - AssertionError.prototype = Object.create(Error.prototype); - AssertionError.prototype.name = 'AssertionError'; - AssertionError.prototype.constructor = AssertionError; - - AssertionError.prototype.toString = function () { - return this.message; - }; - }); // module: browser/error.js - - require.register('chai.js', function (module, exports, require) { - /*! - * chai - * Copyright(c) 2011-2012 Jake Luer <[email protected]> - * MIT Licensed - */ - - var used = [], - exports = (module.exports = {}); - - /*! - * Chai version - */ - - exports.version = '1.0.4'; - - /*! - * Primary `Assertion` prototype - */ - - exports.Assertion = require('./assertion'); - - /*! - * Assertion Error - */ - - exports.AssertionError = require('./browser/error'); - - /*! - * Utils for plugins (not exported) - */ - - var util = require('./utils'); - - /** - * # .use(function) - * - * Provides a way to extend the internals of Chai - * - * @param {Function} - * @returns {this} for chaining - * @api public - */ - - exports.use = function (fn) { - if (!~used.indexOf(fn)) { - fn(this, util); - used.push(fn); - } - - return this; - }; - - /*! - * Expect interface - */ - - var expect = require('./interface/expect'); - exports.use(expect); - - /*! - * Should interface - */ - - var should = require('./interface/should'); - exports.use(should); - - /*! - * Assert interface - */ - - var assert = require('./interface/assert'); - exports.use(assert); - }); // module: chai.js - - require.register('interface/assert.js', function (module, exports, require) { - /*! - * chai - * Copyright(c) 2011-2012 Jake Luer <[email protected]> - * MIT Licensed - */ - - module.exports = function (chai, util) { - /*! - * Chai dependencies. - */ - - var Assertion = chai.Assertion, - flag = util.flag; - - /*! - * Module export. - */ - - /** - * ### assert(expression, message) - * - * Write your own test expressions. - * - * assert('foo' !== 'bar', 'foo is not bar'); - * assert(Array.isArray([]), 'empty arrays are arrays'); - * - * @param {Mixed} expression to test for truthiness - * @param {String} message to display on error - * @name assert - * @api public - */ - - var assert = (chai.assert = function (express, errmsg) { - var test = new Assertion(null); - test.assert(express, errmsg, '[ negation message unavailable ]'); - }); - - /** - * ### .fail(actual, expected, [message], [operator]) - * - * Throw a failure. Node.js `assert` module-compatible. - * - * @name fail - * @param {Mixed} actual - * @param {Mixed} expected - * @param {String} message - * @param {String} operator - * @api public - */ - - assert.fail = function (actual, expected, message, operator) { - throw new chai.AssertionError({ - actual: actual, - expected: expected, - message: message, - operator: operator, - stackStartFunction: assert.fail, - }); - }; - - /** - * ### .ok(object, [message]) - * - * Asserts that `object` is truthy. - * - * assert.ok('everything', 'everything is ok'); - * assert.ok(false, 'this will fail'); - * - * @name ok - * @param {Mixed} object to test - * @param {String} message - * @api public - */ - - assert.ok = function (val, msg) { - new Assertion(val, msg).is.ok; - }; - - /** - * ### .equal(actual, expected, [message]) - * - * Asserts non-strict equality (`==`) of `actual` and `expected`. - * - * assert.equal(3, '3', '== coerces values to strings'); - * - * @name equal - * @param {Mixed} actual - * @param {Mixed} expected - * @param {String} message - * @api public - */ - - assert.equal = function (act, exp, msg) { - var test = new Assertion(act, msg); - - test.assert( - exp == flag(test, 'object'), - 'expected #{this} to equal #{exp}', - 'expected #{this} to not equal #{act}', - exp, - act - ); - }; - - /** - * ### .notEqual(actual, expected, [message]) - * - * Asserts non-strict inequality (`!=`) of `actual` and `expected`. - * - * assert.notEqual(3, 4, 'these numbers are not equal'); - * - * @name notEqual - * @param {Mixed} actual - * @param {Mixed} expected - * @param {String} message - * @api public - */ - - assert.notEqual = function (act, exp, msg) { - var test = new Assertion(act, msg); - - test.assert( - exp != flag(test, 'object'), - 'expected #{this} to not equal #{exp}', - 'expected #{this} to equal #{act}', - exp, - act - ); - }; - - /** - * ### .strictEqual(actual, expected, [message]) - * - * Asserts strict equality (`===`) of `actual` and `expected`. - * - * assert.strictEqual(true, true, 'these booleans are strictly equal'); - * - * @name strictEqual - * @param {Mixed} actual - * @param {Mixed} expected - * @param {String} message - * @api public - */ - - assert.strictEqual = function (act, exp, msg) { - new Assertion(act, msg).to.equal(exp); - }; - - /** - * ### .notStrictEqual(actual, expected, [message]) - * - * Asserts strict inequality (`!==`) of `actual` and `expected`. - * - * assert.notStrictEqual(3, '3', 'no coercion for strict equality'); - * - * @name notStrictEqual - * @param {Mixed} actual - * @param {Mixed} expected - * @param {String} message - * @api public - */ - - assert.notStrictEqual = function (act, exp, msg) { - new Assertion(act, msg).to.not.equal(exp); - }; - - /** - * ### .deepEqual(actual, expected, [message]) - * - * Asserts that `actual` is deeply equal to `expected`. - * - * assert.deepEqual({ tea: 'green' }, { tea: 'green' }); - * - * @name deepEqual - * @param {Mixed} actual - * @param {Mixed} expected - * @param {String} message - * @api public - */ - - assert.deepEqual = function (act, exp, msg) { - new Assertion(act, msg).to.eql(exp); - }; - - /** - * ### .notDeepEqual(actual, expected, [message]) - * - * Assert that `actual` is not deeply equal to `expected`. - * - * assert.notDeepEqual({ tea: 'green' }, { tea: 'jasmine' }); - * - * @name notDeepEqual - * @param {Mixed} actual - * @param {Mixed} expected - * @param {String} message - * @api public - */ - - assert.notDeepEqual = function (act, exp, msg) { - new Assertion(act, msg).to.not.eql(exp); - }; - - /** - * ### .isTrue(value, [message]) - * - * Asserts that `value` is true. - * - * var teaServed = true; - * assert.isTrue(teaServed, 'the tea has been served'); - * - * @name isTrue - * @param {Mixed} value - * @param {String} message - * @api public - */ - - assert.isTrue = function (val, msg) { - new Assertion(val, msg).is['true']; - }; - - /** - * ### .isFalse(value, [message]) - * - * Asserts that `value` is false. - * - * var teaServed = false; - * assert.isFalse(teaServed, 'no tea yet? hmm...'); - * - * @name isFalse - * @param {Mixed} value - * @param {String} message - * @api public - */ - - assert.isFalse = function (val, msg) { - new Assertion(val, msg).is['false']; - }; - - /** - * ### .isNull(value, [message]) - * - * Asserts that `value` is null. - * - * assert.isNull(err, 'there was no error'); - * - * @name isNull - * @param {Mixed} value - * @param {String} message - * @api public - */ - - assert.isNull = function (val, msg) { - new Assertion(val, msg).to.equal(null); - }; - - /** - * ### .isNotNull(value, [message]) - * - * Asserts that `value` is not null. - * - * var tea = 'tasty chai'; - * assert.isNotNull(tea, 'great, time for tea!'); - * - * @name isNotNull - * @param {Mixed} value - * @param {String} message - * @api public - */ - - assert.isNotNull = function (val, msg) { - new Assertion(val, msg).to.not.equal(null); - }; - - /** - * ### .isUndefined(value, [message]) - * - * Asserts that `value` is `undefined`. - * - * var tea; - * assert.isUndefined(tea, 'no tea defined'); - * - * @name isUndefined - * @param {Mixed} value - * @param {String} message - * @api public - */ - - assert.isUndefined = function (val, msg) { - new Assertion(val, msg).to.equal(undefined); - }; - - /** - * ### .isDefined(value, [message]) - * - * Asserts that `value` is not `undefined`. - * - * var tea = 'cup of chai'; - * assert.isDefined(tea, 'tea has been defined'); - * - * @name isUndefined - * @param {Mixed} value - * @param {String} message - * @api public - */ - - assert.isDefined = function (val, msg) { - new Assertion(val, msg).to.not.equal(undefined); - }; - - /** - * ### .isFunction(value, [message]) - * - * Asserts that `value` is a function. - * - * function serveTea() { return 'cup of tea'; }; - * assert.isFunction(serveTea, 'great, we can have tea now'); - * - * @name isFunction - * @param {Mixed} value - * @param {String} message - * @api public - */ - - assert.isFunction = function (val, msg) { - new Assertion(val, msg).to.be.a('function'); - }; - - /** - * ### .isNotFunction(value, [message]) - * - * Asserts that `value` is _not_ a function. - * - * var serveTea = [ 'heat', 'pour', 'sip' ]; - * assert.isNotFunction(serveTea, 'great, we have listed the steps'); - * - * @name isNotFunction - * @param {Mixed} value - * @param {String} message - * @api public - */ - - assert.isNotFunction = function (val, msg) { - new Assertion(val, msg).to.not.be.a('function'); - }; - - /** - * ### .isObject(value, [message]) - * - * Asserts that `value` is an object (as revealed by - * `Object.prototype.toString`). - * - * var selection = { name: 'Chai', serve: 'with spices' }; - * assert.isObject(selection, 'tea selection is an object'); - * - * @name isObject - * @param {Mixed} value - * @param {String} message - * @api public - */ - - assert.isObject = function (val, msg) { - new Assertion(val, msg).to.be.a('object'); - }; - - /** - * ### .isNotObject(value, [message]) - * - * Asserts that `value` is _not_ an object. - * - * var selection = 'chai' - * assert.isObject(selection, 'tea selection is not an object'); - * assert.isObject(null, 'null is not an object'); - * - * @name isNotObject - * @param {Mixed} value - * @param {String} message - * @api public - */ - - assert.isNotObject = function (val, msg) { - new Assertion(val, msg).to.not.be.a('object'); - }; - - /** - * ### .isArray(value, [message]) - * - * Asserts that `value` is an array. - * - * var menu = [ 'green', 'chai', 'oolong' ]; - * assert.isArray(menu, 'what kind of tea do we want?'); - * - * @name isArray - * @param {Mixed} value - * @param {String} message - * @api public - */ - - assert.isArray = function (val, msg) { - new Assertion(val, msg).to.be.an('array'); - }; - - /** - * ### .isNotArray(value, [message]) - * - * Asserts that `value` is _not_ an array. - * - * var menu = 'green|chai|oolong'; - * assert.isNotArray(menu, 'what kind of tea do we want?'); - * - * @name isNotArray - * @param {Mixed} value - * @param {String} message - * @api public - */ - - assert.isNotArray = function (val, msg) { - new Assertion(val, msg).to.not.be.an('array'); - }; - - /** - * ### .isString(value, [message]) - * - * Asserts that `value` is a string. - * - * var teaOrder = 'chai'; - * assert.isString(teaOrder, 'order placed'); - * - * @name isString - * @param {Mixed} value - * @param {String} message - * @api public - */ - - assert.isString = function (val, msg) { - new Assertion(val, msg).to.be.a('string'); - }; - - /** - * ### .isNotString(value, [message]) - * - * Asserts that `value` is _not_ a string. - * - * var teaOrder = 4; - * assert.isNotString(teaOrder, 'order placed'); - * - * @name isNotString - * @param {Mixed} value - * @param {String} message - * @api public - */ - - assert.isNotString = function (val, msg) { - new Assertion(val, msg).to.not.be.a('string'); - }; - - /** - * ### .isNumber(value, [message]) - * - * Asserts that `value` is a number. - * - * var cups = 2; - * assert.isNumber(cups, 'how many cups'); - * - * @name isNumber - * @param {Number} value - * @param {String} message - * @api public - */ - - assert.isNumber = function (val, msg) { - new Assertion(val, msg).to.be.a('number'); - }; - - /** - * ### .isNotNumber(value, [message]) - * - * Asserts that `value` is _not_ a number. - * - * var cups = '2 cups please'; - * assert.isNotNumber(cups, 'how many cups'); - * - * @name isNotNumber - * @param {Mixed} value - * @param {String} message - * @api public - */ - - assert.isNotNumber = function (val, msg) { - new Assertion(val, msg).to.not.be.a('number'); - }; - - /** - * ### .isBoolean(value, [message]) - * - * Asserts that `value` is a boolean. - * - * var teaReady = true - * , teaServed = false; - * - * assert.isBoolean(teaReady, 'is the tea ready'); - * assert.isBoolean(teaServed, 'has tea been served'); - * - * @name isBoolean - * @param {Mixed} value - * @param {String} message - * @api public - */ - - assert.isBoolean = function (val, msg) { - new Assertion(val, msg).to.be.a('boolean'); - }; - - /** - * ### .isNotBoolean(value, [message]) - * - * Asserts that `value` is _not_ a boolean. - * - * var teaReady = 'yep' - * , teaServed = 'nope'; - * - * assert.isNotBoolean(teaReady, 'is the tea ready'); - * assert.isNotBoolean(teaServed, 'has tea been served'); - * - * @name isNotBoolean - * @param {Mixed} value - * @param {String} message - * @api public - */ - - assert.isNotBoolean = function (val, msg) { - new Assertion(val, msg).to.not.be.a('boolean'); - }; - - /** - * ### .typeOf(value, name, [message]) - * - * Asserts that `value`'s type is `name`, as determined by - * `Object.prototype.toString`. - * - * assert.typeOf({ tea: 'chai' }, 'object', 'we have an object'); - * assert.typeOf(['chai', 'jasmine'], 'array', 'we have an array'); - * assert.typeOf('tea', 'string', 'we have a string'); - * assert.typeOf(/tea/, 'regexp', 'we have a regular expression'); - * assert.typeOf(null, 'null', 'we have a null'); - * assert.typeOf(undefined, 'undefined', 'we have an undefined'); - * - * @name typeOf - * @param {Mixed} value - * @param {String} name - * @param {String} message - * @api public - */ - - assert.typeOf = function (val, type, msg) { - new Assertion(val, msg).to.be.a(type); - }; - - /** - * ### .notTypeOf(value, name, [message]) - * - * Asserts that `value`'s type is _not_ `name`, as determined by - * `Object.prototype.toString`. - * - * assert.notTypeOf('tea', 'number', 'strings are not numbers'); - * - * @name notTypeOf - * @param {Mixed} value - * @param {String} typeof name - * @param {String} message - * @api public - */ - - assert.notTypeOf = function (val, type, msg) { - new Assertion(val, msg).to.not.be.a(type); - }; - - /** - * ### .instanceOf(object, constructor, [message]) - * - * Asserts that `value` is an instance of `constructor`. - * - * var Tea = function (name) { this.name = name; } - * , chai = new Tea('chai'); - * - * assert.instanceOf(chai, Tea, 'chai is an instance of tea'); - * - * @name instanceOf - * @param {Object} object - * @param {Constructor} constructor - * @param {String} message - * @api public - */ - - assert.instanceOf = function (val, type, msg) { - new Assertion(val, msg).to.be.instanceOf(type); - }; - - /** - * ### .notInstanceOf(object, constructor, [message]) - * - * Asserts `value` is not an instance of `constructor`. - * - * var Tea = function (name) { this.name = name; } - * , chai = new String('chai'); - * - * assert.notInstanceOf(chai, Tea, 'chai is not an instance of tea'); - * - * @name notInstanceOf - * @param {Object} object - * @param {Constructor} constructor - * @param {String} message - * @api public - */ - - assert.notInstanceOf = function (val, type, msg) { - new Assertion(val, msg).to.not.be.instanceOf(type); - }; - - /** - * ### .include(haystack, needle, [message]) - * - * Asserts that `haystack` includes `needle`. Works - * for strings and arrays. - * - * assert.include('foobar', 'bar', 'foobar contains string "bar"'); - * assert.include([ 1, 2, 3 ], 3, 'array contains value'); - * - * @name include - * @param {Array|String} haystack - * @param {Mixed} needle - * @param {String} message - * @api public - */ - - assert.include = function (exp, inc, msg) { - var obj = new Assertion(exp, msg); - - if (Array.isArray(exp)) { - obj.to.include(inc); - } else if ('string' === typeof exp) { - obj.to.contain.string(inc); - } - }; - - /** - * ### .match(value, regexp, [message]) - * - * Asserts that `value` matches the regular expression `regexp`. - * - * assert.match('foobar', /^foo/, 'regexp matches'); - * - * @name match - * @param {Mixed} value - * @param {RegExp} regexp - * @param {String} message - * @api public - */ - - assert.match = function (exp, re, msg) { - new Assertion(exp, msg).to.match(re); - }; - - /** - * ### .notMatch(value, regexp, [message]) - * - * Asserts that `value` does not match the regular expression `regexp`. - * - * assert.notMatch('foobar', /^foo/, 'regexp does not match'); - * - * @name notMatch - * @param {Mixed} value - * @param {RegExp} regexp - * @param {String} message - * @api public - */ - - assert.notMatch = function (exp, re, msg) { - new Assertion(exp, msg).to.not.match(re); - }; - - /** - * ### .property(object, property, [message]) - * - * Asserts that `object` has a property named by `property`. - * - * assert.property({ tea: { green: 'matcha' }}, 'tea'); - * - * @name property - * @param {Object} object - * @param {String} property - * @param {String} message - * @api public - */ - - assert.property = function (obj, prop, msg) { - new Assertion(obj, msg).to.have.property(prop); - }; - - /** - * ### .notProperty(object, property, [message]) - * - * Asserts that `object` does _not_ have a property named by `property`. - * - * assert.notProperty({ tea: { green: 'matcha' }}, 'coffee'); - * - * @name notProperty - * @param {Object} object - * @param {String} property - * @param {String} message - * @api public - */ - - assert.notProperty = function (obj, prop, msg) { - new Assertion(obj, msg).to.not.have.property(prop); - }; - - /** - * ### .deepProperty(object, property, [message]) - * - * Asserts that `object` has a property named by `property`, which can be a - * string using dot- and bracket-notation for deep reference. - * - * assert.deepProperty({ tea: { green: 'matcha' }}, 'tea.green'); - * - * @name deepProperty - * @param {Object} object - * @param {String} property - * @param {String} message - * @api public - */ - - assert.deepProperty = function (obj, prop, msg) { - new Assertion(obj, msg).to.have.deep.property(prop); - }; - - /** - * ### .notDeepProperty(object, property, [message]) - * - * Asserts that `object` does _not_ have a property named by `property`, which - * can be a string using dot- and bracket-notation for deep reference. - * - * assert.notDeepProperty({ tea: { green: 'matcha' }}, 'tea.oolong'); - * - * @name notDeepProperty - * @param {Object} object - * @param {String} property - * @param {String} message - * @api public - */ - - assert.notDeepProperty = function (obj, prop, msg) { - new Assertion(obj, msg).to.not.have.deep.property(prop); - }; - - /** - * ### .propertyVal(object, property, value, [message]) - * - * Asserts that `object` has a property named by `property` with value given - * by `value`. - * - * assert.propertyVal({ tea: 'is good' }, 'tea', 'is good'); - * - * @name propertyVal - * @param {Object} object - * @param {String} property - * @param {Mixed} value - * @param {String} message - * @api public - */ - - assert.propertyVal = function (obj, prop, val, msg) { - new Assertion(obj, msg).to.have.property(prop, val); - }; - - /** - * ### .propertyNotVal(object, property, value, [message]) - * - * Asserts that `object` has a property named by `property`, but with a value - * different from that given by `value`. - * - * assert.propertyNotVal({ tea: 'is good' }, 'tea', 'is bad'); - * - * @name propertyNotVal - * @param {Object} object - * @param {String} property - * @param {Mixed} value - * @param {String} message - * @api public - */ - - assert.propertyNotVal = function (obj, prop, val, msg) { - new Assertion(obj, msg).to.not.have.property(prop, val); - }; - - /** - * ### .deepPropertyVal(object, property, value, [message]) - * - * Asserts that `object` has a property named by `property` with value given - * by `value`. `property` can use dot- and bracket-notation for deep - * reference. - * - * assert.deepPropertyVal({ tea: { green: 'matcha' }}, 'tea.green', 'matcha'); - * - * @name deepPropertyVal - * @param {Object} object - * @param {String} property - * @param {Mixed} value - * @param {String} message - * @api public - */ - - assert.deepPropertyVal = function (obj, prop, val, msg) { - new Assertion(obj, msg).to.have.deep.property(prop, val); - }; - - /** - * ### .deepPropertyNotVal(object, property, value, [message]) - * - * Asserts that `object` has a property named by `property`, but with a value - * different from that given by `value`. `property` can use dot- and - * bracket-notation for deep reference. - * - * assert.deepPropertyNotVal({ tea: { green: 'matcha' }}, 'tea.green', 'konacha'); - * - * @name deepPropertyNotVal - * @param {Object} object - * @param {String} property - * @param {Mixed} value - * @param {String} message - * @api public - */ - - assert.deepPropertyNotVal = function (obj, prop, val, msg) { - new Assertion(obj, msg).to.not.have.deep.property(prop, val); - }; - - /** - * ### .lengthOf(object, length, [message]) - * - * Asserts that `object` has a `length` property with the expected value. - * - * assert.lengthOf([1,2,3], 3, 'array has length of 3'); - * assert.lengthOf('foobar', 5, 'string has length of 6'); - * - * @name lengthOf - * @param {Mixed} object - * @param {Number} length - * @param {String} message - * @api public - */ - - assert.lengthOf = function (exp, len, msg) { - new Assertion(exp, msg).to.have.length(len); - }; - - /** - * ### .throws(function, [constructor/regexp], [message]) - * - * Asserts that `function` will throw an error that is an instance of - * `constructor`, or alternately that it will throw an error with message - * matching `regexp`. - * - * assert.throw(fn, ReferenceError, 'function throws a reference error'); - * - * @name throws - * @alias throw - * @alias Throw - * @param {Function} function - * @param {ErrorConstructor} constructor - * @param {RegExp} regexp - * @param {String} message - * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types - * @api public - */ - - assert.Throw = function (fn, type, msg) { - if ('string' === typeof type) { - msg = type; - type = null; - } - - new Assertion(fn, msg).to.Throw(type); - }; - - /** - * ### .doesNotThrow(function, [constructor/regexp], [message]) - * - * Asserts that `function` will _not_ throw an error that is an instance of - * `constructor`, or alternately that it will not throw an error with message - * matching `regexp`. - * - * assert.doesNotThrow(fn, Error, 'function does not throw'); - * - * @name doesNotThrow - * @param {Function} function - * @param {ErrorConstructor} constructor - * @param {RegExp} regexp - * @param {String} message - * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types - * @api public - */ - - assert.doesNotThrow = function (fn, type, msg) { - if ('string' === typeof type) { - msg = type; - type = null; - } - - new Assertion(fn, msg).to.not.Throw(type); - }; - - /** - * ### .operator(val1, operator, val2, [message]) - * - * Compares two values using `operator`. - * - * assert.operator(1, '<', 2, 'everything is ok'); - * assert.operator(1, '>', 2, 'this will fail'); - * - * @name operator - * @param {Mixed} val1 - * @param {String} operator - * @param {Mixed} val2 - * @param {String} message - * @api public - */ - - assert.operator = function (val, operator, val2, msg) { - if ( - !~['==', '===', '>', '>=', '<', '<=', '!=', '!=='].indexOf(operator) - ) { - throw new Error('Invalid operator "' + operator + '"'); - } - var test = new Assertion(eval(val + operator + val2), msg); - test.assert( - true === flag(test, 'object'), - 'expected ' + - util.inspect(val) + - ' to be ' + - operator + - ' ' + - util.inspect(val2), - 'expected ' + - util.inspect(val) + - ' to not be ' + - operator + - ' ' + - util.inspect(val2) - ); - }; - - /*! - * Undocumented / untested - */ - - assert.ifError = function (val, msg) { - new Assertion(val, msg).to.not.be.ok; - }; - - /*! - * Aliases. - */ - - (function alias(name, as) { - assert[as] = assert[name]; - return alias; - })('Throw', 'throw')('Throw', 'throws'); - }; - }); // module: interface/assert.js - - require.register('interface/expect.js', function (module, exports, require) { - /*! - * chai - * Copyright(c) 2011-2012 Jake Luer <[email protected]> - * MIT Licensed - */ - - module.exports = function (chai, util) { - chai.expect = function (val, message) { - return new chai.Assertion(val, message); - }; - }; - }); // module: interface/expect.js - - require.register('interface/should.js', function (module, exports, require) { - /*! - * chai - * Copyright(c) 2011-2012 Jake Luer <[email protected]> - * MIT Licensed - */ - - module.exports = function (chai, util) { - var Assertion = chai.Assertion; - - function loadShould() { - // modify Object.prototype to have `should` - Object.defineProperty(Object.prototype, 'should', { - set: function () {}, - get: function () { - if (this instanceof String || this instanceof Number) { - return new Assertion(this.constructor(this)); - } else if (this instanceof Boolean) { - return new Assertion(this == true); - } - return new Assertion(this); - }, - configurable: true, - }); - - var should = {}; - - should.equal = function (val1, val2) { - new Assertion(val1).to.equal(val2); - }; - - should.Throw = function (fn, errt, errs) { - new Assertion(fn).to.Throw(errt, errs); - }; - - should.exist = function (val) { - new Assertion(val).to.exist; - }; - - // negation - should.not = {}; - - should.not.equal = function (val1, val2) { - new Assertion(val1).to.not.equal(val2); - }; - - should.not.Throw = function (fn, errt, errs) { - new Assertion(fn).to.not.Throw(errt, errs); - }; - - should.not.exist = function (val) { - new Assertion(val).to.not.exist; - }; - - should['throw'] = should['Throw']; - should.not['throw'] = should.not['Throw']; - - return should; - } - - chai.should = loadShould; - chai.Should = loadShould; - }; - }); // module: interface/should.js - - require.register( - 'utils/addChainableMethod.js', - function (module, exports, require) { - /*! - * Chai - addChainingMethod utility - * Copyright(c) 2012 Jake Luer <[email protected]> - * MIT Licensed - */ - - /*! - * Module dependencies - */ - - var transferFlags = require('./transferFlags'); - - /** - * ### addChainableMethod (ctx, name, method, chainingBehavior) - * - * Adds a method to an object, such that the method can also be chained. - * - * utils.addChainableMethod(chai.Assertion.prototype, 'foo', function (str) { - * var obj = utils.flag(this, 'object'); - * new chai.Assertion(obj).to.be.equal(str); - * }); - * - * Can also be accessed directly from `chai.Assertion`. - * - * chai.Assertion.addChainableMethod('foo', fn, chainingBehavior); - * - * The result can then be used as both a method assertion, executing both `method` and - * `chainingBehavior`, or as a language chain, which only executes `chainingBehavior`. - * - * expect(fooStr).to.be.foo('bar'); - * expect(fooStr).to.be.foo.equal('foo'); - * - * @param {Object} ctx object to which the method is added - * @param {String} name of method to add - * @param {Function} method function to be used for `name`, when called - * @param {Function} chainingBehavior function to be called every time the property is accessed - * @name addChainableMethod - * @api public - */ - - module.exports = function (ctx, name, method, chainingBehavior) { - if (typeof chainingBehavior !== 'function') - chainingBehavior = function () {}; - - Object.defineProperty(ctx, name, { - get: function () { - chainingBehavior.call(this); - - var assert = function () { - var result = method.apply(this, arguments); - return result === undefined ? this : result; - }; - - // Re-enumerate every time to better accomodate plugins. - var asserterNames = Object.getOwnPropertyNames(ctx); - asserterNames.forEach(function (asserterName) { - var pd = Object.getOwnPropertyDescriptor(ctx, asserterName), - functionProtoPD = Object.getOwnPropertyDescriptor( - Function.prototype, - asserterName - ); - // Avoid trying to overwrite things that we can't, like `length` and `arguments`. - if (functionProtoPD && !functionProtoPD.configurable) return; - if (asserterName === 'arguments') return; // @see chaijs/chai/issues/69 - Object.defineProperty(assert, asserterName, pd); - }); - - transferFlags(this, assert); - return assert; - }, - configurable: true, - }); - }; - } - ); // module: utils/addChainableMethod.js - - require.register('utils/addMethod.js', function (module, exports, require) { - /*! - * Chai - addMethod utility - * Copyright(c) 2012 Jake Luer <[email protected]> - * MIT Licensed - */ - - /** - * ### addMethod (ctx, name, method) - * - * Adds a method to the prototype of an object. - * - * utils.addMethod(chai.Assertion.prototype, 'foo', function (str) { - * var obj = utils.flag(this, 'object'); - * new chai.Assertion(obj).to.be.equal(str); - * }); - * - * Can also be accessed directly from `chai.Assertion`. - * - * chai.Assertion.addMethod('foo', fn); - * - * Then can be used as any other assertion. - * - * expect(fooStr).to.be.foo('bar'); - * - * @param {Object} ctx object to which the method is added - * @param {String} name of method to add - * @param {Function} method function to be used for name - * @name addMethod - * @api public - */ - - module.exports = function (ctx, name, method) { - ctx[name] = function () { - var result = method.apply(this, arguments); - return result === undefined ? this : result; - }; - }; - }); // module: utils/addMethod.js - - require.register('utils/addProperty.js', function (module, exports, require) { - /*! - * Chai - addProperty utility - * Copyright(c) 2012 Jake Luer <[email protected]> - * MIT Licensed - */ - - /** - * ### addProperty (ctx, name, getter) - * - * Adds a property to the prototype of an object. - * - * utils.addProperty(chai.Assertion.prototype, 'foo', function () { - * var obj = utils.flag(this, 'object'); - * new chai.Assertion(obj).to.be.instanceof(Foo); - * }); - * - * Can also be accessed directly from `chai.Assertion`. - * - * chai.Assertion.addProperty('foo', fn); - * - * Then can be used as any other assertion. - * - * expect(myFoo).to.be.foo; - * - * @param {Object} ctx object to which the property is added - * @param {String} name of property to add - * @param {Function} getter function to be used for name - * @name addProperty - * @api public - */ - - module.exports = function (ctx, name, getter) { - Object.defineProperty(ctx, name, { - get: function () { - var result = getter.call(this); - return result === undefined ? this : result; - }, - configurable: true, - }); - }; - }); // module: utils/addProperty.js - - require.register('utils/eql.js', function (module, exports, require) { - // This is directly from Node.js assert - // https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/assert.js - - module.exports = _deepEqual; - - // For browser implementation - if (!Buffer) { - var Buffer = { - isBuffer: function () { - return false; - }, - }; - } - - function _deepEqual(actual, expected) { - // 7.1. All identical values are equivalent, as determined by ===. - if (actual === expected) { - return true; - } else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) { - if (actual.length != expected.length) return false; - - for (var i = 0; i < actual.length; i++) { - if (actual[i] !== expected[i]) return false; - } - - return true; - - // 7.2. If the expected value is a Date object, the actual value is - // equivalent if it is also a Date object that refers to the same time. - } else if (actual instanceof Date && expected instanceof Date) { - return actual.getTime() === expected.getTime(); - - // 7.3. Other pairs that do not both pass typeof value == 'object', - // equivalence is determined by ==. - } else if (typeof actual != 'object' && typeof expected != 'object') { - return actual === expected; - - // 7.4. For all other Object pairs, including Array objects, equivalence is - // determined by having the same number of owned properties (as verified - // with Object.prototype.hasOwnProperty.call), the same set of keys - // (although not necessarily the same order), equivalent values for every - // corresponding key, and an identical 'prototype' property. Note: this - // accounts for both named and indexed properties on Arrays. - } else { - return objEquiv(actual, expected); - } - } - - function isUndefinedOrNull(value) { - return value === null || value === undefined; - } - - function isArguments(object) { - return Object.prototype.toString.call(object) == '[object Arguments]'; - } - - function objEquiv(a, b) { - if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) return false; - // an identical 'prototype' property. - if (a.prototype !== b.prototype) return false; - //~~~I've managed to break Object.keys through screwy arguments passing. - // Converting to array solves the problem. - if (isArguments(a)) { - if (!isArguments(b)) { - return false; - } - a = pSlice.call(a); - b = pSlice.call(b); - return _deepEqual(a, b); - } - try { - var ka = Object.keys(a), - kb = Object.keys(b), - key, - i; - } catch (e) { - //happens when one is a string literal and the other isn't - return false; - } - // having the same number of owned properties (keys incorporates - // hasOwnProperty) - if (ka.length != kb.length) return false; - //the same set of keys (although not necessarily the same order), - ka.sort(); - kb.sort(); - //~~~cheap key test - for (i = ka.length - 1; i >= 0; i--) { - if (ka[i] != kb[i]) return false; - } - //equivalent values for every corresponding key, and - //~~~possibly expensive deep test - for (i = ka.length - 1; i >= 0; i--) { - key = ka[i]; - if (!_deepEqual(a[key], b[key])) return false; - } - return true; - } - }); // module: utils/eql.js - - require.register('utils/flag.js', function (module, exports, require) { - /*! - * Chai - flag utility - * Copyright(c) 2012 Jake Luer <[email protected]> - * MIT Licensed - */ - - /** - * ### flag(object ,key, [value]) - * - * Get or set a flag value on an object. If a - * value is provided it will be set, else it will - * return the currently set value or `undefined` if - * the value is not set. - * - * utils.flag(this, 'foo', 'bar'); // setter - * utils.flag(this, 'foo'); // getter, returns `bar` - * - * @param {Object} object (constructed Assertion - * @param {String} key - * @param {Mixed} value (optional) - * @name flag - * @api private - */ - - module.exports = function (obj, key, value) { - var flags = obj.__flags || (obj.__flags = Object.create(null)); - if (arguments.length === 3) { - flags[key] = value; - } else { - return flags[key]; - } - }; - }); // module: utils/flag.js - - require.register('utils/getActual.js', function (module, exports, require) { - /*! - * Chai - getActual utility - * Copyright(c) 2012 Jake Luer <[email protected]> - * MIT Licensed - */ - - /** - * # getActual(object, [actual]) - * - * Returns the `actual` value for an Assertion - * - * @param {Object} object (constructed Assertion) - * @param {Arguments} chai.Assertion.prototype.assert arguments - */ - - module.exports = function (obj, args) { - var actual = args[4]; - return 'undefined' !== actual ? actual : obj.obj; - }; - }); // module: utils/getActual.js - - require.register('utils/getMessage.js', function (module, exports, require) { - /*! - * Chai - message composition utility - * Copyright(c) 2012 Jake Luer <[email protected]> - * MIT Licensed - */ - - /*! - * Module dependencies - */ - - var flag = require('./flag'), - getActual = require('./getActual'), - inspect = require('./inspect'); - - /** - * # getMessage(object, message, negateMessage) - * - * Construct the error message based on flags - * and template tags. Template tags will return - * a stringified inspection of the object referenced. - * - * Message template tags: - * - `#{this}` current asserted object - * - `#{act}` actual value - * - `#{exp}` expected value - * - * @param {Object} object (constructed Assertion) - * @param {Arguments} chai.Assertion.prototype.assert arguments - */ - - module.exports = function (obj, args) { - var negate = flag(obj, 'negate'), - val = flag(obj, 'object'), - expected = args[3], - actual = getActual(obj, args), - msg = negate ? args[2] : args[1], - flagMsg = flag(obj, 'message'); - - msg = msg || ''; - msg = msg - .replace(/#{this}/g, inspect(val)) - .replace(/#{act}/g, inspect(actual)) - .replace(/#{exp}/g, inspect(expected)); - - return flagMsg ? flagMsg + ': ' + msg : msg; - }; - }); // module: utils/getMessage.js - - require.register('utils/getName.js', function (module, exports, require) { - /*! - * Chai - getName utility - * Copyright(c) 2012 Jake Luer <[email protected]> - * MIT Licensed - */ - - /** - * # getName(func) - * - * Gets the name of a function, in a cross-browser way. - * - * @param {Function} a function (usually a constructor) - */ - - module.exports = function (func) { - if (func.name) return func.name; - - var match = /^\s?function ([^(]*)\(/.exec(func); - return match && match[1] ? match[1] : ''; - }; - }); // module: utils/getName.js - - require.register( - 'utils/getPathValue.js', - function (module, exports, require) { - /*! - * Chai - getPathValue utility - * Copyright(c) 2012 Jake Luer <[email protected]> - * @see https://github.com/logicalparadox/filtr - * MIT Licensed - */ - - /** - * ### .getPathValue(path, object) - * - * This allows the retrieval of values in an - * object given a string path. - * - * var obj = { - * prop1: { - * arr: ['a', 'b', 'c'] - * , str: 'Hello' - * } - * , prop2: { - * arr: [ { nested: 'Universe' } ] - * , str: 'Hello again!' - * } - * } - * - * The following would be the results. - * - * getPathValue('prop1.str', obj); // Hello - * getPathValue('prop1.att[2]', obj); // b - * getPathValue('prop2.arr[0].nested', obj); // Universe - * - * @param {String} path - * @param {Object} object - * @returns {Object} value or `undefined` - * @name getPathValue - * @api public - */ - - var getPathValue = (module.exports = function (path, obj) { - var parsed = parsePath(path); - return _getPathValue(parsed, obj); - }); - - /*! - * ## parsePath(path) - * - * Helper function used to parse string object - * paths. Use in conjunction with `_getPathValue`. - * - * var parsed = parsePath('myobject.property.subprop'); - * - * ### Paths: - * - * * Can be as near infinitely deep and nested - * * Arrays are also valid using the formal `myobject.document[3].property`. - * - * @param {String} path - * @returns {Object} parsed - * @api private - */ - - function parsePath(path) { - var parts = path.split('.').filter(Boolean); - return parts.map(function (value) { - var re = /([A-Za-z0-9]+)\[(\d+)\]$/, - mArr = re.exec(value), - val; - if (mArr) val = { p: mArr[1], i: parseFloat(mArr[2]) }; - return val || value; - }); - } - - /*! - * ## _getPathValue(parsed, obj) - * - * Helper companion function for `.parsePath` that returns - * the value located at the parsed address. - * - * var value = getPathValue(parsed, obj); - * - * @param {Object} parsed definition from `parsePath`. - * @param {Object} object to search against - * @returns {Object|Undefined} value - * @api private - */ - - function _getPathValue(parsed, obj) { - var tmp = obj, - res; - for (var i = 0, l = parsed.length; i < l; i++) { - var part = parsed[i]; - if (tmp) { - if ('object' === typeof part && tmp[part.p]) { - tmp = tmp[part.p][part.i]; - } else { - tmp = tmp[part]; - } - if (i == l - 1) res = tmp; - } else { - res = undefined; - } - } - return res; - } - } - ); // module: utils/getPathValue.js - - require.register('utils/index.js', function (module, exports, require) { - /*! - * chai - * Copyright(c) 2011 Jake Luer <[email protected]> - * MIT Licensed - */ - - /*! - * Main exports - */ - - var exports = (module.exports = {}); - - /*! - * test utility - */ - - exports.test = require('./test'); - - /*! - * message utility - */ - - exports.getMessage = require('./getMessage'); - - /*! - * actual utility - */ - - exports.getActual = require('./getActual'); - - /*! - * Inspect util - */ - - exports.inspect = require('./inspect'); - - /*! - * Flag utility - */ - - exports.flag = require('./flag'); - - /*! - * Flag transferring utility - */ - - exports.transferFlags = require('./transferFlags'); - - /*! - * Deep equal utility - */ - - exports.eql = require('./eql'); - - /*! - * Deep path value - */ - - exports.getPathValue = require('./getPathValue'); - - /*! - * Function name - */ - - exports.getName = require('./getName'); - - /*! - * add Property - */ - - exports.addProperty = require('./addProperty'); - - /*! - * add Method - */ - - exports.addMethod = require('./addMethod'); - - /*! - * overwrite Property - */ - - exports.overwriteProperty = require('./overwriteProperty'); - - /*! - * overwrite Method - */ - - exports.overwriteMethod = require('./overwriteMethod'); - - /*! - * Add a chainable method - */ - - exports.addChainableMethod = require('./addChainableMethod'); - }); // module: utils/index.js - - require.register('utils/inspect.js', function (module, exports, require) { - // This is (almost) directly from Node.js utils - // https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/util.js - - var getName = require('./getName'); - - module.exports = inspect; - - /** - * Echos the value of a value. Trys to print the value out - * in the best way possible given the different types. - * - * @param {Object} obj The object to print out. - * @param {Boolean} showHidden Flag that shows hidden (not enumerable) - * properties of objects. - * @param {Number} depth Depth in which to descend in object. Default is 2. - * @param {Boolean} colors Flag to turn on ANSI escape codes to color the - * output. Default is false (no coloring). - */ - function inspect(obj, showHidden, depth, colors) { - var ctx = { - showHidden: showHidden, - seen: [], - stylize: function (str) { - return str; - }, - }; - return formatValue(ctx, obj, typeof depth === 'undefined' ? 2 : depth); - } - - function formatValue(ctx, value, recurseTimes) { - // Provide a hook for user-specified inspect functions. - // Check that value is an object with an inspect function on it - if ( - value && - typeof value.inspect === 'function' && - // Filter out the util module, it's inspect function is special - value.inspect !== exports.inspect && - // Also filter out any prototype objects using the circular check. - !(value.constructor && value.constructor.prototype === value) - ) { - return value.inspect(recurseTimes); - } - - // Primitive types cannot have properties - var primitive = formatPrimitive(ctx, value); - if (primitive) { - return primitive; - } - - // Look up the keys of the object. - var visibleKeys = Object.keys(value); - var keys = ctx.showHidden - ? Object.getOwnPropertyNames(value) - : visibleKeys; - - // Some type of object without properties can be shortcutted. - // In IE, errors have a single `stack` property, or if they are vanilla `Error`, - // a `stack` plus `description` property; ignore those for consistency. - if ( - keys.length === 0 || - (isError(value) && - ((keys.length === 1 && keys[0] === 'stack') || - (keys.length === 2 && - keys[0] === 'description' && - keys[1] === 'stack'))) - ) { - if (typeof value === 'function') { - var name = getName(value); - var nameSuffix = name ? ': ' + name : ''; - return ctx.stylize('[Function' + nameSuffix + ']', 'special'); - } - if (isRegExp(value)) { - return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); - } - if (isDate(value)) { - return ctx.stylize(Date.prototype.toUTCString.call(value), 'date'); - } - if (isError(value)) { - return formatError(value); - } - } - - var base = '', - array = false, - braces = ['{', '}']; - - // Make Array say that they are Array - if (isArray(value)) { - array = true; - braces = ['[', ']']; - } - - // Make functions say that they are functions - if (typeof value === 'function') { - var n = value.name ? ': ' + value.name : ''; - base = ' [Function' + n + ']'; - } - - // Make RegExps say that they are RegExps - if (isRegExp(value)) { - base = ' ' + RegExp.prototype.toString.call(value); - } - - // Make dates with properties first say the date - if (isDate(value)) { - base = ' ' + Date.prototype.toUTCString.call(value); - } - - // Make error with message first say the error - if (isError(value)) { - return formatError(value); - } - - if (keys.length === 0 && (!array || value.length == 0)) { - return braces[0] + base + braces[1]; - } - - if (recurseTimes < 0) { - if (isRegExp(value)) { - return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); - } else { - return ctx.stylize('[Object]', 'special'); - } - } - - ctx.seen.push(value); - - var output; - if (array) { - output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); - } else { - output = keys.map(function (key) { - return formatProperty( - ctx, - value, - recurseTimes, - visibleKeys, - key, - array - ); - }); - } - - ctx.seen.pop(); - - return reduceToSingleString(output, base, braces); - } - - function formatPrimitive(ctx, value) { - switch (typeof value) { - case 'undefined': - return ctx.stylize('undefined', 'undefined'); - - case 'string': - var simple = - "'" + - JSON.stringify(value) - .replace(/^"|"$/g, '') - .replace(/'/g, "\\'") - .replace(/\\"/g, '"') + - "'"; - return ctx.stylize(simple, 'string'); - - case 'number': - return ctx.stylize('' + value, 'number'); - - case 'boolean': - return ctx.stylize('' + value, 'boolean'); - } - // For some reason typeof null is "object", so special case here. - if (value === null) { - return ctx.stylize('null', 'null'); - } - } - - function formatError(value) { - return '[' + Error.prototype.toString.call(value) + ']'; - } - - function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { - var output = []; - for (var i = 0, l = value.length; i < l; ++i) { - if (Object.prototype.hasOwnProperty.call(value, String(i))) { - output.push( - formatProperty( - ctx, - value, - recurseTimes, - visibleKeys, - String(i), - true - ) - ); - } else { - output.push(''); - } - } - keys.forEach(function (key) { - if (!key.match(/^\d+$/)) { - output.push( - formatProperty(ctx, value, recurseTimes, visibleKeys, key, true) - ); - } - }); - return output; - } - - function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { - var name, str; - if (value.__lookupGetter__) { - if (value.__lookupGetter__(key)) { - if (value.__lookupSetter__(key)) { - str = ctx.stylize('[Getter/Setter]', 'special'); - } else { - str = ctx.stylize('[Getter]', 'special'); - } - } else { - if (value.__lookupSetter__(key)) { - str = ctx.stylize('[Setter]', 'special'); - } - } - } - if (visibleKeys.indexOf(key) < 0) { - name = '[' + key + ']'; - } - if (!str) { - if (ctx.seen.indexOf(value[key]) < 0) { - if (recurseTimes === null) { - str = formatValue(ctx, value[key], null); - } else { - str = formatValue(ctx, value[key], recurseTimes - 1); - } - if (str.indexOf('\n') > -1) { - if (array) { - str = str - .split('\n') - .map(function (line) { - return ' ' + line; - }) - .join('\n') - .substr(2); - } else { - str = - '\n' + - str - .split('\n') - .map(function (line) { - return ' ' + line; - }) - .join('\n'); - } - } - } else { - str = ctx.stylize('[Circular]', 'special'); - } - } - if (typeof name === 'undefined') { - if (array && key.match(/^\d+$/)) { - return str; - } - name = JSON.stringify('' + key); - if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { - name = name.substr(1, name.length - 2); - name = ctx.stylize(name, 'name'); - } else { - name = name - .replace(/'/g, "\\'") - .replace(/\\"/g, '"') - .replace(/(^"|"$)/g, "'"); - name = ctx.stylize(name, 'string'); - } - } - - return name + ': ' + str; - } - - function reduceToSingleString(output, base, braces) { - var numLinesEst = 0; - var length = output.reduce(function (prev, cur) { - numLinesEst++; - if (cur.indexOf('\n') >= 0) numLinesEst++; - return prev + cur.length + 1; - }, 0); - - if (length > 60) { - return ( - braces[0] + - (base === '' ? '' : base + '\n ') + - ' ' + - output.join(',\n ') + - ' ' + - braces[1] - ); - } - - return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; - } - - function isArray(ar) { - return ( - Array.isArray(ar) || - (typeof ar === 'object' && objectToString(ar) === '[object Array]') - ); - } - - function isRegExp(re) { - return typeof re === 'object' && objectToString(re) === '[object RegExp]'; - } - - function isDate(d) { - return typeof d === 'object' && objectToString(d) === '[object Date]'; - } - - function isError(e) { - return typeof e === 'object' && objectToString(e) === '[object Error]'; - } - - function objectToString(o) { - return Object.prototype.toString.call(o); - } - }); // module: utils/inspect.js - - require.register( - 'utils/overwriteMethod.js', - function (module, exports, require) { - /*! - * Chai - overwriteMethod utility - * Copyright(c) 2012 Jake Luer <[email protected]> - * MIT Licensed - */ - - /** - * ### overwriteMethod (ctx, name, fn) - * - * Overwrites an already existing method and provides - * access to previous function. Must return function - * to be used for name. - * - * utils.overwriteMethod(chai.Assertion.prototype, 'equal', function (_super) { - * return function (str) { - * var obj = utils.flag(this, 'object'); - * if (obj instanceof Foo) { - * new chai.Assertion(obj.value).to.equal(str); - * } else { - * _super.apply(this, arguments); - * } - * } - * }); - * - * Can also be accessed directly from `chai.Assertion`. - * - * chai.Assertion.overwriteMethod('foo', fn); - * - * Then can be used as any other assertion. - * - * expect(myFoo).to.equal('bar'); - * - * @param {Object} ctx object whose method is to be overwritten - * @param {String} name of method to overwrite - * @param {Function} method function that returns a function to be used for name - * @name overwriteMethod - * @api public - */ - - module.exports = function (ctx, name, method) { - var _method = ctx[name], - _super = function () { - return this; - }; - - if (_method && 'function' === typeof _method) _super = _method; - - ctx[name] = function () { - var result = method(_super).apply(this, arguments); - return result === undefined ? this : result; - }; - }; - } - ); // module: utils/overwriteMethod.js - - require.register( - 'utils/overwriteProperty.js', - function (module, exports, require) { - /*! - * Chai - overwriteProperty utility - * Copyright(c) 2012 Jake Luer <[email protected]> - * MIT Licensed - */ - - /** - * ### overwriteProperty (ctx, name, fn) - * - * Overwrites an already existing property getter and provides - * access to previous value. Must return function to use as getter. - * - * utils.overwriteProperty(chai.Assertion.prototype, 'ok', function (_super) { - * return function () { - * var obj = utils.flag(this, 'object'); - * if (obj instanceof Foo) { - * new chai.Assertion(obj.name).to.equal('bar'); - * } else { - * _super.call(this); - * } - * } - * }); - * - * - * Can also be accessed directly from `chai.Assertion`. - * - * chai.Assertion.overwriteProperty('foo', fn); - * - * Then can be used as any other assertion. - * - * expect(myFoo).to.be.ok; - * - * @param {Object} ctx object whose property is to be overwritten - * @param {String} name of property to overwrite - * @param {Function} getter function that returns a getter function to be used for name - * @name overwriteProperty - * @api public - */ - - module.exports = function (ctx, name, getter) { - var _get = Object.getOwnPropertyDescriptor(ctx, name), - _super = function () {}; - - if (_get && 'function' === typeof _get.get) _super = _get.get; - - Object.defineProperty(ctx, name, { - get: function () { - var result = getter(_super).call(this); - return result === undefined ? this : result; - }, - configurable: true, - }); - }; - } - ); // module: utils/overwriteProperty.js - - require.register('utils/test.js', function (module, exports, require) { - /*! - * Chai - test utility - * Copyright(c) 2012 Jake Luer <[email protected]> - * MIT Licensed - */ - - /*! - * Module dependencies - */ - - var flag = require('./flag'); - - /** - * # test(object, expression) - * - * Test and object for expression. - * - * @param {Object} object (constructed Assertion) - * @param {Arguments} chai.Assertion.prototype.assert arguments - */ - - module.exports = function (obj, args) { - var negate = flag(obj, 'negate'), - expr = args[0]; - return negate ? !expr : expr; - }; - }); // module: utils/test.js - - require.register( - 'utils/transferFlags.js', - function (module, exports, require) { - /*! - * Chai - transferFlags utility - * Copyright(c) 2012 Jake Luer <[email protected]> - * MIT Licensed - */ - - /** - * ### transferFlags(assertion, object, includeAll = true) - * - * Transfer all the flags for `assertion` to `object`. If - * `includeAll` is set to `false`, then the base Chai - * assertion flags (namely `object`, `ssfi`, and `message`) - * will not be transferred. - * - * - * var newAssertion = new Assertion(); - * utils.transferFlags(assertion, newAssertion); - * - * var anotherAssertion = new Assertion(myObj); - * utils.transferFlags(assertion, anotherAssertion, false); - * - * @param {Assertion} assertion the assertion to transfer the flags from - * @param {Object} object the object to transfer the flags too; usually a new assertion - * @param {Boolean} includeAll - * @name getAllFlags - * @api private - */ - - module.exports = function (assertion, object, includeAll) { - var flags = - assertion.__flags || (assertion.__flags = Object.create(null)); - - if (!object.__flags) { - object.__flags = Object.create(null); - } - - includeAll = arguments.length === 3 ? includeAll : true; - - for (var flag in flags) { - if ( - includeAll || - (flag !== 'object' && flag !== 'ssfi' && flag != 'message') - ) { - object.__flags[flag] = flags[flag]; - } - } - }; - } - ); // module: utils/transferFlags.js - - return require('chai'); -}); diff --git a/test/support/function-helpers.js b/test/support/function-helpers.js deleted file mode 100644 index f8dfe68e..00000000 --- a/test/support/function-helpers.js +++ /dev/null @@ -1,59 +0,0 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var sinon = require('sinon'); - var faker = require('../../lib').faker; -} - -var functionHelpers = {}; - -module.exports = functionHelpers; - -var IGNORED_MODULES = [ - 'locales', - 'locale', - 'localeFallback', - 'definitions', - 'fake', - 'helpers', - 'mersenne', -]; -var IGNORED_METHODS = { - system: ['directoryPath', 'filePath'], // these are TODOs -}; - -function isTestableModule(mod) { - return IGNORED_MODULES.indexOf(mod) === -1; -} - -function isMethodOf(mod) { - return function (meth) { - return typeof faker[mod][meth] === 'function'; - }; -} - -function isTestableMethod(mod) { - return function (meth) { - return !(mod in IGNORED_METHODS && IGNORED_METHODS[mod].indexOf(meth) >= 0); - }; -} - -function both(pred1, pred2) { - return function (value) { - return pred1(value) && pred2(value); - }; -} - -// Basic smoke tests to make sure each method is at least implemented and returns a value. - -functionHelpers.modulesList = function modulesList() { - var modules = Object.keys(faker) - .filter(isTestableModule) - .reduce(function (result, mod) { - result[mod] = Object.keys(faker[mod]).filter( - both(isMethodOf(mod), isTestableMethod(mod)) - ); - return result; - }, {}); - - return modules; -}; diff --git a/test/support/luhnCheck.js b/test/support/luhnCheck.js deleted file mode 100644 index 9a5b8538..00000000 --- a/test/support/luhnCheck.js +++ /dev/null @@ -1,22 +0,0 @@ -module.exports = function (number) { - number = number.replace(/\D/g, ''); - var split = number.split(''); - split = split.map(function (num) { - return parseInt(num); - }); - var check = split.pop(); - split.reverse(); - split = split.map(function (num, index) { - if (index % 2 === 0) { - num *= 2; - if (num > 9) { - num -= 9; - } - } - return num; - }); - var sum = split.reduce(function (prev, curr) { - return prev + curr; - }); - return sum % 10 === check; -}; diff --git a/test/support/luhnCheck.ts b/test/support/luhnCheck.ts new file mode 100644 index 00000000..fb4e0bb0 --- /dev/null +++ b/test/support/luhnCheck.ts @@ -0,0 +1,18 @@ +export function luhnCheck(number: string): boolean { + number = number.replace(/\D/g, ''); + let split: string[] | number[] = number.split(''); + split = split.map((num) => parseInt(num)); + const check = split.pop(); + split.reverse(); + split = split.map((num, index) => { + if (index % 2 === 0) { + num *= 2; + if (num > 9) { + num -= 9; + } + } + return num; + }); + const sum = split.reduce((prev, curr) => prev + curr); + return sum % 10 === check; +} diff --git a/test/support/sinon-1.5.2.js b/test/support/sinon-1.5.2.js deleted file mode 100644 index 82939b65..00000000 --- a/test/support/sinon-1.5.2.js +++ /dev/null @@ -1,4524 +0,0 @@ -/** - * Sinon.JS 1.5.2, 2012/11/27 - * - * @author Christian Johansen ([email protected]) - * @author Contributors: https://github.com/cjohansen/Sinon.JS/blob/master/AUTHORS - * - * (The BSD License) - * - * Copyright (c) 2010-2012, Christian Johansen, [email protected] - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * * Neither the name of Christian Johansen nor the names of his contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -var sinon = function () { - 'use strict'; - - var buster = (function (setTimeout, B) { - var isNode = typeof require == 'function' && typeof module == 'object'; - var div = typeof document != 'undefined' && document.createElement('div'); - var F = function () {}; - - var buster = { - bind: function bind(obj, methOrProp) { - var method = - typeof methOrProp == 'string' ? obj[methOrProp] : methOrProp; - var args = Array.prototype.slice.call(arguments, 2); - return function () { - var allArgs = args.concat(Array.prototype.slice.call(arguments)); - return method.apply(obj, allArgs); - }; - }, - - partial: function partial(fn) { - var args = [].slice.call(arguments, 1); - return function () { - return fn.apply(this, args.concat([].slice.call(arguments))); - }; - }, - - create: function create(object) { - F.prototype = object; - return new F(); - }, - - extend: function extend(target) { - if (!target) { - return; - } - for (var i = 1, l = arguments.length, prop; i < l; ++i) { - for (prop in arguments[i]) { - target[prop] = arguments[i][prop]; - } - } - return target; - }, - - nextTick: function nextTick(callback) { - if (typeof process != 'undefined' && process.nextTick) { - return process.nextTick(callback); - } - setTimeout(callback, 0); - }, - - functionName: function functionName(func) { - if (!func) return ''; - if (func.displayName) return func.displayName; - if (func.name) return func.name; - var matches = func.toString().match(/function\s+([^\(]+)/m); - return (matches && matches[1]) || ''; - }, - - isNode: function isNode(obj) { - if (!div) return false; - try { - obj.appendChild(div); - obj.removeChild(div); - } catch (e) { - return false; - } - return true; - }, - - isElement: function isElement(obj) { - return obj && obj.nodeType === 1 && buster.isNode(obj); - }, - - isArray: function isArray(arr) { - return Object.prototype.toString.call(arr) == '[object Array]'; - }, - - flatten: function flatten(arr) { - var result = [], - arr = arr || []; - for (var i = 0, l = arr.length; i < l; ++i) { - result = result.concat( - buster.isArray(arr[i]) ? flatten(arr[i]) : arr[i] - ); - } - return result; - }, - - each: function each(arr, callback) { - for (var i = 0, l = arr.length; i < l; ++i) { - callback(arr[i]); - } - }, - - map: function map(arr, callback) { - var results = []; - for (var i = 0, l = arr.length; i < l; ++i) { - results.push(callback(arr[i])); - } - return results; - }, - - parallel: function parallel(fns, callback) { - function cb(err, res) { - if (typeof callback == 'function') { - callback(err, res); - callback = null; - } - } - if (fns.length == 0) { - return cb(null, []); - } - var remaining = fns.length, - results = []; - function makeDone(num) { - return function done(err, result) { - if (err) { - return cb(err); - } - results[num] = result; - if (--remaining == 0) { - cb(null, results); - } - }; - } - for (var i = 0, l = fns.length; i < l; ++i) { - fns[i](makeDone(i)); - } - }, - - series: function series(fns, callback) { - function cb(err, res) { - if (typeof callback == 'function') { - callback(err, res); - } - } - var remaining = fns.slice(); - var results = []; - function callNext() { - if (remaining.length == 0) return cb(null, results); - var promise = remaining.shift()(next); - if (promise && typeof promise.then == 'function') { - promise.then(buster.partial(next, null), next); - } - } - function next(err, result) { - if (err) return cb(err); - results.push(result); - callNext(); - } - callNext(); - }, - - countdown: function countdown(num, done) { - return function () { - if (--num == 0) done(); - }; - }, - }; - - if ( - typeof process === 'object' && - typeof require === 'function' && - typeof module === 'object' - ) { - var crypto = require('crypto'); - var path = require('path'); - - buster.tmpFile = function (fileName) { - var hashed = crypto.createHash('sha1'); - hashed.update(fileName); - var tmpfileName = hashed.digest('hex'); - - if (process.platform == 'win32') { - return path.join(process.env['TEMP'], tmpfileName); - } else { - return path.join('/tmp', tmpfileName); - } - }; - } - - if (Array.prototype.some) { - buster.some = function (arr, fn, thisp) { - return arr.some(fn, thisp); - }; - } else { - // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some - buster.some = function (arr, fun, thisp) { - if (arr == null) { - throw new TypeError(); - } - arr = Object(arr); - var len = arr.length >>> 0; - if (typeof fun !== 'function') { - throw new TypeError(); - } - - for (var i = 0; i < len; i++) { - if (arr.hasOwnProperty(i) && fun.call(thisp, arr[i], i, arr)) { - return true; - } - } - - return false; - }; - } - - if (Array.prototype.filter) { - buster.filter = function (arr, fn, thisp) { - return arr.filter(fn, thisp); - }; - } else { - // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/filter - buster.filter = function (fn, thisp) { - if (this == null) { - throw new TypeError(); - } - - var t = Object(this); - var len = t.length >>> 0; - if (typeof fn != 'function') { - throw new TypeError(); - } - - var res = []; - for (var i = 0; i < len; i++) { - if (i in t) { - var val = t[i]; // in case fun mutates this - if (fn.call(thisp, val, i, t)) { - res.push(val); - } - } - } - - return res; - }; - } - - if (isNode) { - module.exports = buster; - buster.eventEmitter = require('./buster-event-emitter'); - Object.defineProperty(buster, 'defineVersionGetter', { - get: function () { - return require('./define-version-getter'); - }, - }); - } - - return buster.extend(B || {}, buster); - })(setTimeout, buster); - if (typeof buster === 'undefined') { - var buster = {}; - } - - if (typeof module === 'object' && typeof require === 'function') { - buster = require('buster-core'); - } - - buster.format = buster.format || {}; - buster.format.excludeConstructors = ['Object', /^.$/]; - buster.format.quoteStrings = true; - - buster.format.ascii = (function () { - var hasOwn = Object.prototype.hasOwnProperty; - - var specialObjects = []; - if (typeof global != 'undefined') { - specialObjects.push({ obj: global, value: '[object global]' }); - } - if (typeof document != 'undefined') { - specialObjects.push({ obj: document, value: '[object HTMLDocument]' }); - } - if (typeof window != 'undefined') { - specialObjects.push({ obj: window, value: '[object Window]' }); - } - - function keys(object) { - var k = (Object.keys && Object.keys(object)) || []; - - if (k.length == 0) { - for (var prop in object) { - if (hasOwn.call(object, prop)) { - k.push(prop); - } - } - } - - return k.sort(); - } - - function isCircular(object, objects) { - if (typeof object != 'object') { - return false; - } - - for (var i = 0, l = objects.length; i < l; ++i) { - if (objects[i] === object) { - return true; - } - } - - return false; - } - - function ascii(object, processed, indent) { - if (typeof object == 'string') { - var quote = typeof this.quoteStrings != 'boolean' || this.quoteStrings; - return processed || quote ? '"' + object + '"' : object; - } - - if (typeof object == 'function' && !(object instanceof RegExp)) { - return ascii.func(object); - } - - processed = processed || []; - - if (isCircular(object, processed)) { - return '[Circular]'; - } - - if (Object.prototype.toString.call(object) == '[object Array]') { - return ascii.array.call(this, object, processed); - } - - if (!object) { - return '' + object; - } - - if (buster.isElement(object)) { - return ascii.element(object); - } - - if ( - typeof object.toString == 'function' && - object.toString !== Object.prototype.toString - ) { - return object.toString(); - } - - for (var i = 0, l = specialObjects.length; i < l; i++) { - if (object === specialObjects[i].obj) { - return specialObjects[i].value; - } - } - - return ascii.object.call(this, object, processed, indent); - } - - ascii.func = function (func) { - return 'function ' + buster.functionName(func) + '() {}'; - }; - - ascii.array = function (array, processed) { - processed = processed || []; - processed.push(array); - var pieces = []; - - for (var i = 0, l = array.length; i < l; ++i) { - pieces.push(ascii.call(this, array[i], processed)); - } - - return '[' + pieces.join(', ') + ']'; - }; - - ascii.object = function (object, processed, indent) { - processed = processed || []; - processed.push(object); - indent = indent || 0; - var pieces = [], - properties = keys(object), - prop, - str, - obj; - var is = ''; - var length = 3; - - for (var i = 0, l = indent; i < l; ++i) { - is += ' '; - } - - for (i = 0, l = properties.length; i < l; ++i) { - prop = properties[i]; - obj = object[prop]; - - if (isCircular(obj, processed)) { - str = '[Circular]'; - } else { - str = ascii.call(this, obj, processed, indent + 2); - } - - str = (/\s/.test(prop) ? '"' + prop + '"' : prop) + ': ' + str; - length += str.length; - pieces.push(str); - } - - var cons = ascii.constructorName.call(this, object); - var prefix = cons ? '[' + cons + '] ' : ''; - - return length + indent > 80 - ? prefix + '{\n ' + is + pieces.join(',\n ' + is) + '\n' + is + '}' - : prefix + '{ ' + pieces.join(', ') + ' }'; - }; - - ascii.element = function (element) { - var tagName = element.tagName.toLowerCase(); - var attrs = element.attributes, - attribute, - pairs = [], - attrName; - - for (var i = 0, l = attrs.length; i < l; ++i) { - attribute = attrs.item(i); - attrName = attribute.nodeName.toLowerCase().replace('html:', ''); - - if (attrName == 'contenteditable' && attribute.nodeValue == 'inherit') { - continue; - } - - if (!!attribute.nodeValue) { - pairs.push(attrName + '="' + attribute.nodeValue + '"'); - } - } - - var formatted = '<' + tagName + (pairs.length > 0 ? ' ' : ''); - var content = element.innerHTML; - - if (content.length > 20) { - content = content.substr(0, 20) + '[...]'; - } - - var res = - formatted + pairs.join(' ') + '>' + content + '</' + tagName + '>'; - - return res.replace(/ contentEditable="inherit"/, ''); - }; - - ascii.constructorName = function (object) { - var name = buster.functionName(object && object.constructor); - var excludes = - this.excludeConstructors || buster.format.excludeConstructors || []; - - for (var i = 0, l = excludes.length; i < l; ++i) { - if (typeof excludes[i] == 'string' && excludes[i] == name) { - return ''; - } else if (excludes[i].test && excludes[i].test(name)) { - return ''; - } - } - - return name; - }; - - return ascii; - })(); - - if (typeof module != 'undefined') { - module.exports = buster.format; - } - /*jslint eqeqeq: false, onevar: false, forin: true, nomen: false, regexp: false, plusplus: false*/ - /*global module, require, __dirname, document*/ - /** - * Sinon core utilities. For internal use only. - * - * @author Christian Johansen ([email protected]) - * @license BSD - * - * Copyright (c) 2010-2011 Christian Johansen - */ - - var sinon = (function (buster) { - var div = typeof document != 'undefined' && document.createElement('div'); - var hasOwn = Object.prototype.hasOwnProperty; - - function isDOMNode(obj) { - var success = false; - - try { - obj.appendChild(div); - success = div.parentNode == obj; - } catch (e) { - return false; - } finally { - try { - obj.removeChild(div); - } catch (e) { - // Remove failed, not much we can do about that - } - } - - return success; - } - - function isElement(obj) { - return div && obj && obj.nodeType === 1 && isDOMNode(obj); - } - - function isFunction(obj) { - return ( - typeof obj === 'function' || - !!(obj && obj.constructor && obj.call && obj.apply) - ); - } - - function mirrorProperties(target, source) { - for (var prop in source) { - if (!hasOwn.call(target, prop)) { - target[prop] = source[prop]; - } - } - } - - var sinon = { - wrapMethod: function wrapMethod(object, property, method) { - if (!object) { - throw new TypeError('Should wrap property of object'); - } - - if (typeof method != 'function') { - throw new TypeError('Method wrapper should be function'); - } - - var wrappedMethod = object[property]; - - if (!isFunction(wrappedMethod)) { - throw new TypeError( - 'Attempted to wrap ' + - typeof wrappedMethod + - ' property ' + - property + - ' as function' - ); - } - - if (wrappedMethod.restore && wrappedMethod.restore.sinon) { - throw new TypeError( - 'Attempted to wrap ' + property + ' which is already wrapped' - ); - } - - if (wrappedMethod.calledBefore) { - var verb = !!wrappedMethod.returns ? 'stubbed' : 'spied on'; - throw new TypeError( - 'Attempted to wrap ' + property + ' which is already ' + verb - ); - } - - // IE 8 does not support hasOwnProperty on the window object. - var owned = hasOwn.call(object, property); - object[property] = method; - method.displayName = property; - - method.restore = function () { - // For prototype properties try to reset by delete first. - // If this fails (ex: localStorage on mobile safari) then force a reset - // via direct assignment. - if (!owned) { - delete object[property]; - } - if (object[property] === method) { - object[property] = wrappedMethod; - } - }; - - method.restore.sinon = true; - mirrorProperties(method, wrappedMethod); - - return method; - }, - - extend: function extend(target) { - for (var i = 1, l = arguments.length; i < l; i += 1) { - for (var prop in arguments[i]) { - if (arguments[i].hasOwnProperty(prop)) { - target[prop] = arguments[i][prop]; - } - - // DONT ENUM bug, only care about toString - if ( - arguments[i].hasOwnProperty('toString') && - arguments[i].toString != target.toString - ) { - target.toString = arguments[i].toString; - } - } - } - - return target; - }, - - create: function create(proto) { - var F = function () {}; - F.prototype = proto; - return new F(); - }, - - deepEqual: function deepEqual(a, b) { - if (sinon.match && sinon.match.isMatcher(a)) { - return a.test(b); - } - if (typeof a != 'object' || typeof b != 'object') { - return a === b; - } - - if (isElement(a) || isElement(b)) { - return a === b; - } - - if (a === b) { - return true; - } - - if ((a === null && b !== null) || (a !== null && b === null)) { - return false; - } - - var aString = Object.prototype.toString.call(a); - if (aString != Object.prototype.toString.call(b)) { - return false; - } - - if (aString == '[object Array]') { - if (a.length !== b.length) { - return false; - } - - for (var i = 0, l = a.length; i < l; i += 1) { - if (!deepEqual(a[i], b[i])) { - return false; - } - } - - return true; - } - - var prop, - aLength = 0, - bLength = 0; - - for (prop in a) { - aLength += 1; - - if (!deepEqual(a[prop], b[prop])) { - return false; - } - } - - for (prop in b) { - bLength += 1; - } - - if (aLength != bLength) { - return false; - } - - return true; - }, - - functionName: function functionName(func) { - var name = func.displayName || func.name; - - // Use function decomposition as a last resort to get function - // name. Does not rely on function decomposition to work - if it - // doesn't debugging will be slightly less informative - // (i.e. toString will say 'spy' rather than 'myFunc'). - if (!name) { - var matches = func.toString().match(/function ([^\s\(]+)/); - name = matches && matches[1]; - } - - return name; - }, - - functionToString: function toString() { - if (this.getCall && this.callCount) { - var thisValue, - prop, - i = this.callCount; - - while (i--) { - thisValue = this.getCall(i).thisValue; - - for (prop in thisValue) { - if (thisValue[prop] === this) { - return prop; - } - } - } - } - - return this.displayName || 'sinon fake'; - }, - - getConfig: function (custom) { - var config = {}; - custom = custom || {}; - var defaults = sinon.defaultConfig; - - for (var prop in defaults) { - if (defaults.hasOwnProperty(prop)) { - config[prop] = custom.hasOwnProperty(prop) - ? custom[prop] - : defaults[prop]; - } - } - - return config; - }, - - format: function (val) { - return '' + val; - }, - - defaultConfig: { - injectIntoThis: true, - injectInto: null, - properties: ['spy', 'stub', 'mock', 'clock', 'server', 'requests'], - useFakeTimers: true, - useFakeServer: true, - }, - - timesInWords: function timesInWords(count) { - return ( - (count == 1 && 'once') || - (count == 2 && 'twice') || - (count == 3 && 'thrice') || - (count || 0) + ' times' - ); - }, - - calledInOrder: function (spies) { - for (var i = 1, l = spies.length; i < l; i++) { - if (!spies[i - 1].calledBefore(spies[i])) { - return false; - } - } - - return true; - }, - - orderByFirstCall: function (spies) { - return spies.sort(function (a, b) { - // uuid, won't ever be equal - var aCall = a.getCall(0); - var bCall = b.getCall(0); - var aId = (aCall && aCall.callId) || -1; - var bId = (bCall && bCall.callId) || -1; - - return aId < bId ? -1 : 1; - }); - }, - - log: function () {}, - - logError: function (label, err) { - var msg = label + ' threw exception: '; - sinon.log(msg + '[' + err.name + '] ' + err.message); - if (err.stack) { - sinon.log(err.stack); - } - - setTimeout(function () { - err.message = msg + err.message; - throw err; - }, 0); - }, - - typeOf: function (value) { - if (value === null) { - return 'null'; - } else if (value === undefined) { - return 'undefined'; - } - var string = Object.prototype.toString.call(value); - return string.substring(8, string.length - 1).toLowerCase(); - }, - }; - - var isNode = typeof module == 'object' && typeof require == 'function'; - - if (isNode) { - try { - buster = { format: require('buster-format') }; - } catch (e) {} - module.exports = sinon; - module.exports.spy = require('./sinon/spy'); - module.exports.stub = require('./sinon/stub'); - module.exports.mock = require('./sinon/mock'); - module.exports.collection = require('./sinon/collection'); - module.exports.assert = require('./sinon/assert'); - module.exports.sandbox = require('./sinon/sandbox'); - module.exports.test = require('./sinon/test'); - module.exports.testCase = require('./sinon/test_case'); - module.exports.assert = require('./sinon/assert'); - module.exports.match = require('./sinon/match'); - } - - if (buster) { - var formatter = sinon.create(buster.format); - formatter.quoteStrings = false; - sinon.format = function () { - return formatter.ascii.apply(formatter, arguments); - }; - } else if (isNode) { - try { - var util = require('util'); - sinon.format = function (value) { - return typeof value == 'object' && - value.toString === Object.prototype.toString - ? util.inspect(value) - : value; - }; - } catch (e) { - /* Node, but no util module - would be very old, but better safe than - sorry */ - } - } - - return sinon; - })(typeof buster == 'object' && buster); - - /* @depend ../sinon.js */ - /*jslint eqeqeq: false, onevar: false, plusplus: false*/ - /*global module, require, sinon*/ - /** - * Match functions - * - * @author Maximilian Antoni ([email protected]) - * @license BSD - * - * Copyright (c) 2012 Maximilian Antoni - */ - - (function (sinon) { - var commonJSModule = - typeof module == 'object' && typeof require == 'function'; - - if (!sinon && commonJSModule) { - sinon = require('../sinon'); - } - - if (!sinon) { - return; - } - - function assertType(value, type, name) { - var actual = sinon.typeOf(value); - if (actual !== type) { - throw new TypeError( - 'Expected type of ' + name + ' to be ' + type + ', but was ' + actual - ); - } - } - - var matcher = { - toString: function () { - return this.message; - }, - }; - - function isMatcher(object) { - return matcher.isPrototypeOf(object); - } - - function matchObject(expectation, actual) { - if (actual === null || actual === undefined) { - return false; - } - for (var key in expectation) { - if (expectation.hasOwnProperty(key)) { - var exp = expectation[key]; - var act = actual[key]; - if (match.isMatcher(exp)) { - if (!exp.test(act)) { - return false; - } - } else if (sinon.typeOf(exp) === 'object') { - if (!matchObject(exp, act)) { - return false; - } - } else if (!sinon.deepEqual(exp, act)) { - return false; - } - } - } - return true; - } - - matcher.or = function (m2) { - if (!isMatcher(m2)) { - throw new TypeError('Matcher expected'); - } - var m1 = this; - var or = sinon.create(matcher); - or.test = function (actual) { - return m1.test(actual) || m2.test(actual); - }; - or.message = m1.message + '.or(' + m2.message + ')'; - return or; - }; - - matcher.and = function (m2) { - if (!isMatcher(m2)) { - throw new TypeError('Matcher expected'); - } - var m1 = this; - var and = sinon.create(matcher); - and.test = function (actual) { - return m1.test(actual) && m2.test(actual); - }; - and.message = m1.message + '.and(' + m2.message + ')'; - return and; - }; - - var match = function (expectation, message) { - var m = sinon.create(matcher); - var type = sinon.typeOf(expectation); - switch (type) { - case 'object': - if (typeof expectation.test === 'function') { - m.test = function (actual) { - return expectation.test(actual) === true; - }; - m.message = 'match(' + sinon.functionName(expectation.test) + ')'; - return m; - } - var str = []; - for (var key in expectation) { - if (expectation.hasOwnProperty(key)) { - str.push(key + ': ' + expectation[key]); - } - } - m.test = function (actual) { - return matchObject(expectation, actual); - }; - m.message = 'match(' + str.join(', ') + ')'; - break; - case 'number': - m.test = function (actual) { - return expectation == actual; - }; - break; - case 'string': - m.test = function (actual) { - if (typeof actual !== 'string') { - return false; - } - return actual.indexOf(expectation) !== -1; - }; - m.message = 'match("' + expectation + '")'; - break; - case 'regexp': - m.test = function (actual) { - if (typeof actual !== 'string') { - return false; - } - return expectation.test(actual); - }; - break; - case 'function': - m.test = expectation; - if (message) { - m.message = message; - } else { - m.message = 'match(' + sinon.functionName(expectation) + ')'; - } - break; - default: - m.test = function (actual) { - return sinon.deepEqual(expectation, actual); - }; - } - if (!m.message) { - m.message = 'match(' + expectation + ')'; - } - return m; - }; - - match.isMatcher = isMatcher; - - match.any = match(function () { - return true; - }, 'any'); - - match.defined = match(function (actual) { - return actual !== null && actual !== undefined; - }, 'defined'); - - match.truthy = match(function (actual) { - return !!actual; - }, 'truthy'); - - match.falsy = match(function (actual) { - return !actual; - }, 'falsy'); - - match.same = function (expectation) { - return match(function (actual) { - return expectation === actual; - }, 'same(' + expectation + ')'); - }; - - match.typeOf = function (type) { - assertType(type, 'string', 'type'); - return match(function (actual) { - return sinon.typeOf(actual) === type; - }, 'typeOf("' + type + '")'); - }; - - match.instanceOf = function (type) { - assertType(type, 'function', 'type'); - return match(function (actual) { - return actual instanceof type; - }, 'instanceOf(' + sinon.functionName(type) + ')'); - }; - - function createPropertyMatcher(propertyTest, messagePrefix) { - return function (property, value) { - assertType(property, 'string', 'property'); - var onlyProperty = arguments.length === 1; - var message = messagePrefix + '("' + property + '"'; - if (!onlyProperty) { - message += ', ' + value; - } - message += ')'; - return match(function (actual) { - if ( - actual === undefined || - actual === null || - !propertyTest(actual, property) - ) { - return false; - } - return onlyProperty || sinon.deepEqual(value, actual[property]); - }, message); - }; - } - - match.has = createPropertyMatcher(function (actual, property) { - if (typeof actual === 'object') { - return property in actual; - } - return actual[property] !== undefined; - }, 'has'); - - match.hasOwn = createPropertyMatcher(function (actual, property) { - return actual.hasOwnProperty(property); - }, 'hasOwn'); - - match.bool = match.typeOf('boolean'); - match.number = match.typeOf('number'); - match.string = match.typeOf('string'); - match.object = match.typeOf('object'); - match.func = match.typeOf('function'); - match.array = match.typeOf('array'); - match.regexp = match.typeOf('regexp'); - match.date = match.typeOf('date'); - - if (commonJSModule) { - module.exports = match; - } else { - sinon.match = match; - } - })((typeof sinon == 'object' && sinon) || null); - - /** - * @depend ../sinon.js - * @depend match.js - */ - /*jslint eqeqeq: false, onevar: false, plusplus: false*/ - /*global module, require, sinon*/ - /** - * Spy functions - * - * @author Christian Johansen ([email protected]) - * @license BSD - * - * Copyright (c) 2010-2011 Christian Johansen - */ - - (function (sinon) { - var commonJSModule = - typeof module == 'object' && typeof require == 'function'; - var spyCall; - var callId = 0; - var push = [].push; - var slice = Array.prototype.slice; - - if (!sinon && commonJSModule) { - sinon = require('../sinon'); - } - - if (!sinon) { - return; - } - - function spy(object, property) { - if (!property && typeof object == 'function') { - return spy.create(object); - } - - if (!object && !property) { - return spy.create(function () {}); - } - - var method = object[property]; - return sinon.wrapMethod(object, property, spy.create(method)); - } - - sinon.extend( - spy, - (function () { - function delegateToCalls(api, method, matchAny, actual, notCalled) { - api[method] = function () { - if (!this.called) { - if (notCalled) { - return notCalled.apply(this, arguments); - } - return false; - } - - var currentCall; - var matches = 0; - - for (var i = 0, l = this.callCount; i < l; i += 1) { - currentCall = this.getCall(i); - - if (currentCall[actual || method].apply(currentCall, arguments)) { - matches += 1; - - if (matchAny) { - return true; - } - } - } - - return matches === this.callCount; - }; - } - - function matchingFake(fakes, args, strict) { - if (!fakes) { - return; - } - - var alen = args.length; - - for (var i = 0, l = fakes.length; i < l; i++) { - if (fakes[i].matches(args, strict)) { - return fakes[i]; - } - } - } - - function incrementCallCount() { - this.called = true; - this.callCount += 1; - this.notCalled = false; - this.calledOnce = this.callCount == 1; - this.calledTwice = this.callCount == 2; - this.calledThrice = this.callCount == 3; - } - - function createCallProperties() { - this.firstCall = this.getCall(0); - this.secondCall = this.getCall(1); - this.thirdCall = this.getCall(2); - this.lastCall = this.getCall(this.callCount - 1); - } - - var vars = 'a,b,c,d,e,f,g,h,i,j,k,l'; - function createProxy(func) { - // Retain the function length: - var p; - if (func.length) { - eval( - 'p = (function proxy(' + - vars.substring(0, func.length * 2 - 1) + - ') { return p.invoke(func, this, slice.call(arguments)); });' - ); - } else { - p = function proxy() { - return p.invoke(func, this, slice.call(arguments)); - }; - } - return p; - } - - var uuid = 0; - - // Public API - var spyApi = { - reset: function () { - this.called = false; - this.notCalled = true; - this.calledOnce = false; - this.calledTwice = false; - this.calledThrice = false; - this.callCount = 0; - this.firstCall = null; - this.secondCall = null; - this.thirdCall = null; - this.lastCall = null; - this.args = []; - this.returnValues = []; - this.thisValues = []; - this.exceptions = []; - this.callIds = []; - if (this.fakes) { - for (var i = 0; i < this.fakes.length; i++) { - this.fakes[i].reset(); - } - } - }, - - create: function create(func) { - var name; - - if (typeof func != 'function') { - func = function () {}; - } else { - name = sinon.functionName(func); - } - - var proxy = createProxy(func); - - sinon.extend(proxy, spy); - delete proxy.create; - sinon.extend(proxy, func); - - proxy.reset(); - proxy.prototype = func.prototype; - proxy.displayName = name || 'spy'; - proxy.toString = sinon.functionToString; - proxy._create = sinon.spy.create; - proxy.id = 'spy#' + uuid++; - - return proxy; - }, - - invoke: function invoke(func, thisValue, args) { - var matching = matchingFake(this.fakes, args); - var exception, returnValue; - - incrementCallCount.call(this); - push.call(this.thisValues, thisValue); - push.call(this.args, args); - push.call(this.callIds, callId++); - - try { - if (matching) { - returnValue = matching.invoke(func, thisValue, args); - } else { - returnValue = (this.func || func).apply(thisValue, args); - } - } catch (e) { - push.call(this.returnValues, undefined); - exception = e; - throw e; - } finally { - push.call(this.exceptions, exception); - } - - push.call(this.returnValues, returnValue); - - createCallProperties.call(this); - - return returnValue; - }, - - getCall: function getCall(i) { - if (i < 0 || i >= this.callCount) { - return null; - } - - return spyCall.create( - this, - this.thisValues[i], - this.args[i], - this.returnValues[i], - this.exceptions[i], - this.callIds[i] - ); - }, - - calledBefore: function calledBefore(spyFn) { - if (!this.called) { - return false; - } - - if (!spyFn.called) { - return true; - } - - return this.callIds[0] < spyFn.callIds[spyFn.callIds.length - 1]; - }, - - calledAfter: function calledAfter(spyFn) { - if (!this.called || !spyFn.called) { - return false; - } - - return ( - this.callIds[this.callCount - 1] > - spyFn.callIds[spyFn.callCount - 1] - ); - }, - - withArgs: function () { - var args = slice.call(arguments); - - if (this.fakes) { - var match = matchingFake(this.fakes, args, true); - - if (match) { - return match; - } - } else { - this.fakes = []; - } - - var original = this; - var fake = this._create(); - fake.matchingAguments = args; - push.call(this.fakes, fake); - - fake.withArgs = function () { - return original.withArgs.apply(original, arguments); - }; - - for (var i = 0; i < this.args.length; i++) { - if (fake.matches(this.args[i])) { - incrementCallCount.call(fake); - push.call(fake.thisValues, this.thisValues[i]); - push.call(fake.args, this.args[i]); - push.call(fake.returnValues, this.returnValues[i]); - push.call(fake.exceptions, this.exceptions[i]); - push.call(fake.callIds, this.callIds[i]); - } - } - createCallProperties.call(fake); - - return fake; - }, - - matches: function (args, strict) { - var margs = this.matchingAguments; - - if ( - margs.length <= args.length && - sinon.deepEqual(margs, args.slice(0, margs.length)) - ) { - return !strict || margs.length == args.length; - } - }, - - printf: function (format) { - var spy = this; - var args = slice.call(arguments, 1); - var formatter; - - return (format || '').replace(/%(.)/g, function (match, specifyer) { - formatter = spyApi.formatters[specifyer]; - - if (typeof formatter == 'function') { - return formatter.call(null, spy, args); - } else if (!isNaN(parseInt(specifyer), 10)) { - return sinon.format(args[specifyer - 1]); - } - - return '%' + specifyer; - }); - }, - }; - - delegateToCalls(spyApi, 'calledOn', true); - delegateToCalls(spyApi, 'alwaysCalledOn', false, 'calledOn'); - delegateToCalls(spyApi, 'calledWith', true); - delegateToCalls(spyApi, 'calledWithMatch', true); - delegateToCalls(spyApi, 'alwaysCalledWith', false, 'calledWith'); - delegateToCalls( - spyApi, - 'alwaysCalledWithMatch', - false, - 'calledWithMatch' - ); - delegateToCalls(spyApi, 'calledWithExactly', true); - delegateToCalls( - spyApi, - 'alwaysCalledWithExactly', - false, - 'calledWithExactly' - ); - delegateToCalls( - spyApi, - 'neverCalledWith', - false, - 'notCalledWith', - function () { - return true; - } - ); - delegateToCalls( - spyApi, - 'neverCalledWithMatch', - false, - 'notCalledWithMatch', - function () { - return true; - } - ); - delegateToCalls(spyApi, 'threw', true); - delegateToCalls(spyApi, 'alwaysThrew', false, 'threw'); - delegateToCalls(spyApi, 'returned', true); - delegateToCalls(spyApi, 'alwaysReturned', false, 'returned'); - delegateToCalls(spyApi, 'calledWithNew', true); - delegateToCalls(spyApi, 'alwaysCalledWithNew', false, 'calledWithNew'); - delegateToCalls(spyApi, 'callArg', false, 'callArgWith', function () { - throw new Error( - this.toString() + ' cannot call arg since it was not yet invoked.' - ); - }); - spyApi.callArgWith = spyApi.callArg; - delegateToCalls(spyApi, 'yield', false, 'yield', function () { - throw new Error( - this.toString() + ' cannot yield since it was not yet invoked.' - ); - }); - // "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode. - spyApi.invokeCallback = spyApi.yield; - delegateToCalls( - spyApi, - 'yieldTo', - false, - 'yieldTo', - function (property) { - throw new Error( - this.toString() + - " cannot yield to '" + - property + - "' since it was not yet invoked." - ); - } - ); - - spyApi.formatters = { - c: function (spy) { - return sinon.timesInWords(spy.callCount); - }, - - n: function (spy) { - return spy.toString(); - }, - - C: function (spy) { - var calls = []; - - for (var i = 0, l = spy.callCount; i < l; ++i) { - push.call(calls, ' ' + spy.getCall(i).toString()); - } - - return calls.length > 0 ? '\n' + calls.join('\n') : ''; - }, - - t: function (spy) { - var objects = []; - - for (var i = 0, l = spy.callCount; i < l; ++i) { - push.call(objects, sinon.format(spy.thisValues[i])); - } - - return objects.join(', '); - }, - - '*': function (spy, args) { - var formatted = []; - - for (var i = 0, l = args.length; i < l; ++i) { - push.call(formatted, sinon.format(args[i])); - } - - return formatted.join(', '); - }, - }; - - return spyApi; - })() - ); - - spyCall = (function () { - function throwYieldError(proxy, text, args) { - var msg = sinon.functionName(proxy) + text; - if (args.length) { - msg += ' Received [' + slice.call(args).join(', ') + ']'; - } - throw new Error(msg); - } - - var callApi = { - create: function create( - spy, - thisValue, - args, - returnValue, - exception, - id - ) { - var proxyCall = sinon.create(spyCall); - delete proxyCall.create; - proxyCall.proxy = spy; - proxyCall.thisValue = thisValue; - proxyCall.args = args; - proxyCall.returnValue = returnValue; - proxyCall.exception = exception; - proxyCall.callId = (typeof id == 'number' && id) || callId++; - - return proxyCall; - }, - - calledOn: function calledOn(thisValue) { - if (sinon.match && sinon.match.isMatcher(thisValue)) { - return thisValue.test(this.thisValue); - } - return this.thisValue === thisValue; - }, - - calledWith: function calledWith() { - for (var i = 0, l = arguments.length; i < l; i += 1) { - if (!sinon.deepEqual(arguments[i], this.args[i])) { - return false; - } - } - - return true; - }, - - calledWithMatch: function calledWithMatch() { - for (var i = 0, l = arguments.length; i < l; i += 1) { - var actual = this.args[i]; - var expectation = arguments[i]; - if (!sinon.match || !sinon.match(expectation).test(actual)) { - return false; - } - } - return true; - }, - - calledWithExactly: function calledWithExactly() { - return ( - arguments.length == this.args.length && - this.calledWith.apply(this, arguments) - ); - }, - - notCalledWith: function notCalledWith() { - return !this.calledWith.apply(this, arguments); - }, - - notCalledWithMatch: function notCalledWithMatch() { - return !this.calledWithMatch.apply(this, arguments); - }, - - returned: function returned(value) { - return sinon.deepEqual(value, this.returnValue); - }, - - threw: function threw(error) { - if (typeof error == 'undefined' || !this.exception) { - return !!this.exception; - } - - if (typeof error == 'string') { - return this.exception.name == error; - } - - return this.exception === error; - }, - - calledWithNew: function calledWithNew(thisValue) { - return this.thisValue instanceof this.proxy; - }, - - calledBefore: function (other) { - return this.callId < other.callId; - }, - - calledAfter: function (other) { - return this.callId > other.callId; - }, - - callArg: function (pos) { - this.args[pos](); - }, - - callArgWith: function (pos) { - var args = slice.call(arguments, 1); - this.args[pos].apply(null, args); - }, - - yield: function () { - var args = this.args; - for (var i = 0, l = args.length; i < l; ++i) { - if (typeof args[i] === 'function') { - args[i].apply(null, slice.call(arguments)); - return; - } - } - throwYieldError( - this.proxy, - ' cannot yield since no callback was passed.', - args - ); - }, - - yieldTo: function (prop) { - var args = this.args; - for (var i = 0, l = args.length; i < l; ++i) { - if (args[i] && typeof args[i][prop] === 'function') { - args[i][prop].apply(null, slice.call(arguments, 1)); - return; - } - } - throwYieldError( - this.proxy, - " cannot yield to '" + prop + "' since no callback was passed.", - args - ); - }, - - toString: function () { - var callStr = this.proxy.toString() + '('; - var args = []; - - for (var i = 0, l = this.args.length; i < l; ++i) { - push.call(args, sinon.format(this.args[i])); - } - - callStr = callStr + args.join(', ') + ')'; - - if (typeof this.returnValue != 'undefined') { - callStr += ' => ' + sinon.format(this.returnValue); - } - - if (this.exception) { - callStr += ' !' + this.exception.name; - - if (this.exception.message) { - callStr += '(' + this.exception.message + ')'; - } - } - - return callStr; - }, - }; - callApi.invokeCallback = callApi.yield; - return callApi; - })(); - - spy.spyCall = spyCall; - - // This steps outside the module sandbox and will be removed - sinon.spyCall = spyCall; - - if (commonJSModule) { - module.exports = spy; - } else { - sinon.spy = spy; - } - })((typeof sinon == 'object' && sinon) || null); - - /** - * @depend ../sinon.js - * @depend spy.js - */ - /*jslint eqeqeq: false, onevar: false*/ - /*global module, require, sinon*/ - /** - * Stub functions - * - * @author Christian Johansen ([email protected]) - * @license BSD - * - * Copyright (c) 2010-2011 Christian Johansen - */ - - (function (sinon) { - var commonJSModule = - typeof module == 'object' && typeof require == 'function'; - - if (!sinon && commonJSModule) { - sinon = require('../sinon'); - } - - if (!sinon) { - return; - } - - function stub(object, property, func) { - if (!!func && typeof func != 'function') { - throw new TypeError('Custom stub should be function'); - } - - var wrapper; - - if (func) { - wrapper = sinon.spy && sinon.spy.create ? sinon.spy.create(func) : func; - } else { - wrapper = stub.create(); - } - - if (!object && !property) { - return sinon.stub.create(); - } - - if (!property && !!object && typeof object == 'object') { - for (var prop in object) { - if (typeof object[prop] === 'function') { - stub(object, prop); - } - } - - return object; - } - - return sinon.wrapMethod(object, property, wrapper); - } - - function getChangingValue(stub, property) { - var index = stub.callCount - 1; - var prop = - index in stub[property] - ? stub[property][index] - : stub[property + 'Last']; - stub[property + 'Last'] = prop; - - return prop; - } - - function getCallback(stub, args) { - var callArgAt = getChangingValue(stub, 'callArgAts'); - - if (callArgAt < 0) { - var callArgProp = getChangingValue(stub, 'callArgProps'); - - for (var i = 0, l = args.length; i < l; ++i) { - if (!callArgProp && typeof args[i] == 'function') { - return args[i]; - } - - if ( - callArgProp && - args[i] && - typeof args[i][callArgProp] == 'function' - ) { - return args[i][callArgProp]; - } - } - - return null; - } - - return args[callArgAt]; - } - - var join = Array.prototype.join; - - function getCallbackError(stub, func, args) { - if (stub.callArgAtsLast < 0) { - var msg; - - if (stub.callArgPropsLast) { - msg = - sinon.functionName(stub) + - " expected to yield to '" + - stub.callArgPropsLast + - "', but no object with such a property was passed."; - } else { - msg = - sinon.functionName(stub) + - ' expected to yield, but no callback was passed.'; - } - - if (args.length > 0) { - msg += ' Received [' + join.call(args, ', ') + ']'; - } - - return msg; - } - - return ( - 'argument at index ' + - stub.callArgAtsLast + - ' is not a function: ' + - func - ); - } - - var nextTick = (function () { - if ( - typeof process === 'object' && - typeof process.nextTick === 'function' - ) { - return process.nextTick; - } else if (typeof msSetImmediate === 'function') { - return msSetImmediate.bind(window); - } else if (typeof setImmediate === 'function') { - return setImmediate; - } else { - return function (callback) { - setTimeout(callback, 0); - }; - } - })(); - - function callCallback(stub, args) { - if (stub.callArgAts.length > 0) { - var func = getCallback(stub, args); - - if (typeof func != 'function') { - throw new TypeError(getCallbackError(stub, func, args)); - } - - var index = stub.callCount - 1; - - var callbackArguments = getChangingValue(stub, 'callbackArguments'); - var callbackContext = getChangingValue(stub, 'callbackContexts'); - - if (stub.callbackAsync) { - nextTick(function () { - func.apply(callbackContext, callbackArguments); - }); - } else { - func.apply(callbackContext, callbackArguments); - } - } - } - - var uuid = 0; - - sinon.extend( - stub, - (function () { - var slice = Array.prototype.slice, - proto; - - function throwsException(error, message) { - if (typeof error == 'string') { - this.exception = new Error(message || ''); - this.exception.name = error; - } else if (!error) { - this.exception = new Error('Error'); - } else { - this.exception = error; - } - - return this; - } - - proto = { - create: function create() { - var functionStub = function () { - callCallback(functionStub, arguments); - - if (functionStub.exception) { - throw functionStub.exception; - } else if (typeof functionStub.returnArgAt == 'number') { - return arguments[functionStub.returnArgAt]; - } else if (functionStub.returnThis) { - return this; - } - return functionStub.returnValue; - }; - - functionStub.id = 'stub#' + uuid++; - var orig = functionStub; - functionStub = sinon.spy.create(functionStub); - functionStub.func = orig; - - functionStub.callArgAts = []; - functionStub.callbackArguments = []; - functionStub.callbackContexts = []; - functionStub.callArgProps = []; - - sinon.extend(functionStub, stub); - functionStub._create = sinon.stub.create; - functionStub.displayName = 'stub'; - functionStub.toString = sinon.functionToString; - - return functionStub; - }, - - returns: function returns(value) { - this.returnValue = value; - - return this; - }, - - returnsArg: function returnsArg(pos) { - if (typeof pos != 'number') { - throw new TypeError('argument index is not number'); - } - - this.returnArgAt = pos; - - return this; - }, - - returnsThis: function returnsThis() { - this.returnThis = true; - - return this; - }, - - throws: throwsException, - throwsException: throwsException, - - callsArg: function callsArg(pos) { - if (typeof pos != 'number') { - throw new TypeError('argument index is not number'); - } - - this.callArgAts.push(pos); - this.callbackArguments.push([]); - this.callbackContexts.push(undefined); - this.callArgProps.push(undefined); - - return this; - }, - - callsArgOn: function callsArgOn(pos, context) { - if (typeof pos != 'number') { - throw new TypeError('argument index is not number'); - } - if (typeof context != 'object') { - throw new TypeError('argument context is not an object'); - } - - this.callArgAts.push(pos); - this.callbackArguments.push([]); - this.callbackContexts.push(context); - this.callArgProps.push(undefined); - - return this; - }, - - callsArgWith: function callsArgWith(pos) { - if (typeof pos != 'number') { - throw new TypeError('argument index is not number'); - } - - this.callArgAts.push(pos); - this.callbackArguments.push(slice.call(arguments, 1)); - this.callbackContexts.push(undefined); - this.callArgProps.push(undefined); - - return this; - }, - - callsArgOnWith: function callsArgWith(pos, context) { - if (typeof pos != 'number') { - throw new TypeError('argument index is not number'); - } - if (typeof context != 'object') { - throw new TypeError('argument context is not an object'); - } - - this.callArgAts.push(pos); - this.callbackArguments.push(slice.call(arguments, 2)); - this.callbackContexts.push(context); - this.callArgProps.push(undefined); - - return this; - }, - - yields: function () { - this.callArgAts.push(-1); - this.callbackArguments.push(slice.call(arguments, 0)); - this.callbackContexts.push(undefined); - this.callArgProps.push(undefined); - - return this; - }, - - yieldsOn: function (context) { - if (typeof context != 'object') { - throw new TypeError('argument context is not an object'); - } - - this.callArgAts.push(-1); - this.callbackArguments.push(slice.call(arguments, 1)); - this.callbackContexts.push(context); - this.callArgProps.push(undefined); - - return this; - }, - - yieldsTo: function (prop) { - this.callArgAts.push(-1); - this.callbackArguments.push(slice.call(arguments, 1)); - this.callbackContexts.push(undefined); - this.callArgProps.push(prop); - - return this; - }, - - yieldsToOn: function (prop, context) { - if (typeof context != 'object') { - throw new TypeError('argument context is not an object'); - } - - this.callArgAts.push(-1); - this.callbackArguments.push(slice.call(arguments, 2)); - this.callbackContexts.push(context); - this.callArgProps.push(prop); - - return this; - }, - }; - - // create asynchronous versions of callsArg* and yields* methods - for (var method in proto) { - // need to avoid creating anotherasync versions of the newly added async methods - if ( - proto.hasOwnProperty(method) && - method.match(/^(callsArg|yields|thenYields$)/) && - !method.match(/Async/) - ) { - proto[method + 'Async'] = (function (syncFnName) { - return function () { - this.callbackAsync = true; - return this[syncFnName].apply(this, arguments); - }; - })(method); - } - } - - return proto; - })() - ); - - if (commonJSModule) { - module.exports = stub; - } else { - sinon.stub = stub; - } - })((typeof sinon == 'object' && sinon) || null); - - /** - * @depend ../sinon.js - * @depend stub.js - */ - /*jslint eqeqeq: false, onevar: false, nomen: false*/ - /*global module, require, sinon*/ - /** - * Mock functions. - * - * @author Christian Johansen ([email protected]) - * @license BSD - * - * Copyright (c) 2010-2011 Christian Johansen - */ - - (function (sinon) { - var commonJSModule = - typeof module == 'object' && typeof require == 'function'; - var push = [].push; - - if (!sinon && commonJSModule) { - sinon = require('../sinon'); - } - - if (!sinon) { - return; - } - - function mock(object) { - if (!object) { - return sinon.expectation.create('Anonymous mock'); - } - - return mock.create(object); - } - - sinon.mock = mock; - - sinon.extend( - mock, - (function () { - function each(collection, callback) { - if (!collection) { - return; - } - - for (var i = 0, l = collection.length; i < l; i += 1) { - callback(collection[i]); - } - } - - return { - create: function create(object) { - if (!object) { - throw new TypeError('object is null'); - } - - var mockObject = sinon.extend({}, mock); - mockObject.object = object; - delete mockObject.create; - - return mockObject; - }, - - expects: function expects(method) { - if (!method) { - throw new TypeError('method is falsy'); - } - - if (!this.expectations) { - this.expectations = {}; - this.proxies = []; - } - - if (!this.expectations[method]) { - this.expectations[method] = []; - var mockObject = this; - - sinon.wrapMethod(this.object, method, function () { - return mockObject.invokeMethod(method, this, arguments); - }); - - push.call(this.proxies, method); - } - - var expectation = sinon.expectation.create(method); - push.call(this.expectations[method], expectation); - - return expectation; - }, - - restore: function restore() { - var object = this.object; - - each(this.proxies, function (proxy) { - if (typeof object[proxy].restore == 'function') { - object[proxy].restore(); - } - }); - }, - - verify: function verify() { - var expectations = this.expectations || {}; - var messages = [], - met = []; - - each(this.proxies, function (proxy) { - each(expectations[proxy], function (expectation) { - if (!expectation.met()) { - push.call(messages, expectation.toString()); - } else { - push.call(met, expectation.toString()); - } - }); - }); - - this.restore(); - - if (messages.length > 0) { - sinon.expectation.fail(messages.concat(met).join('\n')); - } else { - sinon.expectation.pass(messages.concat(met).join('\n')); - } - - return true; - }, - - invokeMethod: function invokeMethod(method, thisValue, args) { - var expectations = this.expectations && this.expectations[method]; - var length = (expectations && expectations.length) || 0, - i; - - for (i = 0; i < length; i += 1) { - if ( - !expectations[i].met() && - expectations[i].allowsCall(thisValue, args) - ) { - return expectations[i].apply(thisValue, args); - } - } - - var messages = [], - available, - exhausted = 0; - - for (i = 0; i < length; i += 1) { - if (expectations[i].allowsCall(thisValue, args)) { - available = available || expectations[i]; - } else { - exhausted += 1; - } - push.call(messages, ' ' + expectations[i].toString()); - } - - if (exhausted === 0) { - return available.apply(thisValue, args); - } - - messages.unshift( - 'Unexpected call: ' + - sinon.spyCall.toString.call({ - proxy: method, - args: args, - }) - ); - - sinon.expectation.fail(messages.join('\n')); - }, - }; - })() - ); - - var times = sinon.timesInWords; - - sinon.expectation = (function () { - var slice = Array.prototype.slice; - var _invoke = sinon.spy.invoke; - - function callCountInWords(callCount) { - if (callCount == 0) { - return 'never called'; - } else { - return 'called ' + times(callCount); - } - } - - function expectedCallCountInWords(expectation) { - var min = expectation.minCalls; - var max = expectation.maxCalls; - - if (typeof min == 'number' && typeof max == 'number') { - var str = times(min); - - if (min != max) { - str = 'at least ' + str + ' and at most ' + times(max); - } - - return str; - } - - if (typeof min == 'number') { - return 'at least ' + times(min); - } - - return 'at most ' + times(max); - } - - function receivedMinCalls(expectation) { - var hasMinLimit = typeof expectation.minCalls == 'number'; - return !hasMinLimit || expectation.callCount >= expectation.minCalls; - } - - function receivedMaxCalls(expectation) { - if (typeof expectation.maxCalls != 'number') { - return false; - } - - return expectation.callCount == expectation.maxCalls; - } - - return { - minCalls: 1, - maxCalls: 1, - - create: function create(methodName) { - var expectation = sinon.extend( - sinon.stub.create(), - sinon.expectation - ); - delete expectation.create; - expectation.method = methodName; - - return expectation; - }, - - invoke: function invoke(func, thisValue, args) { - this.verifyCallAllowed(thisValue, args); - - return _invoke.apply(this, arguments); - }, - - atLeast: function atLeast(num) { - if (typeof num != 'number') { - throw new TypeError("'" + num + "' is not number"); - } - - if (!this.limitsSet) { - this.maxCalls = null; - this.limitsSet = true; - } - - this.minCalls = num; - - return this; - }, - - atMost: function atMost(num) { - if (typeof num != 'number') { - throw new TypeError("'" + num + "' is not number"); - } - - if (!this.limitsSet) { - this.minCalls = null; - this.limitsSet = true; - } - - this.maxCalls = num; - - return this; - }, - - never: function never() { - return this.exactly(0); - }, - - once: function once() { - return this.exactly(1); - }, - - twice: function twice() { - return this.exactly(2); - }, - - thrice: function thrice() { - return this.exactly(3); - }, - - exactly: function exactly(num) { - if (typeof num != 'number') { - throw new TypeError("'" + num + "' is not a number"); - } - - this.atLeast(num); - return this.atMost(num); - }, - - met: function met() { - return !this.failed && receivedMinCalls(this); - }, - - verifyCallAllowed: function verifyCallAllowed(thisValue, args) { - if (receivedMaxCalls(this)) { - this.failed = true; - sinon.expectation.fail( - this.method + ' already called ' + times(this.maxCalls) - ); - } - - if ('expectedThis' in this && this.expectedThis !== thisValue) { - sinon.expectation.fail( - this.method + - ' called with ' + - thisValue + - ' as thisValue, expected ' + - this.expectedThis - ); - } - - if (!('expectedArguments' in this)) { - return; - } - - if (!args) { - sinon.expectation.fail( - this.method + - ' received no arguments, expected ' + - sinon.format(this.expectedArguments) - ); - } - - if (args.length < this.expectedArguments.length) { - sinon.expectation.fail( - this.method + - ' received too few arguments (' + - sinon.format(args) + - '), expected ' + - sinon.format(this.expectedArguments) - ); - } - - if ( - this.expectsExactArgCount && - args.length != this.expectedArguments.length - ) { - sinon.expectation.fail( - this.method + - ' received too many arguments (' + - sinon.format(args) + - '), expected ' + - sinon.format(this.expectedArguments) - ); - } - - for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) { - if (!sinon.deepEqual(this.expectedArguments[i], args[i])) { - sinon.expectation.fail( - this.method + - ' received wrong arguments ' + - sinon.format(args) + - ', expected ' + - sinon.format(this.expectedArguments) - ); - } - } - }, - - allowsCall: function allowsCall(thisValue, args) { - if (this.met() && receivedMaxCalls(this)) { - return false; - } - - if ('expectedThis' in this && this.expectedThis !== thisValue) { - return false; - } - - if (!('expectedArguments' in this)) { - return true; - } - - args = args || []; - - if (args.length < this.expectedArguments.length) { - return false; - } - - if ( - this.expectsExactArgCount && - args.length != this.expectedArguments.length - ) { - return false; - } - - for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) { - if (!sinon.deepEqual(this.expectedArguments[i], args[i])) { - return false; - } - } - - return true; - }, - - withArgs: function withArgs() { - this.expectedArguments = slice.call(arguments); - return this; - }, - - withExactArgs: function withExactArgs() { - this.withArgs.apply(this, arguments); - this.expectsExactArgCount = true; - return this; - }, - - on: function on(thisValue) { - this.expectedThis = thisValue; - return this; - }, - - toString: function () { - var args = (this.expectedArguments || []).slice(); - - if (!this.expectsExactArgCount) { - push.call(args, '[...]'); - } - - var callStr = sinon.spyCall.toString.call({ - proxy: this.method, - args: args, - }); - - var message = - callStr.replace(', [...', '[, ...') + - ' ' + - expectedCallCountInWords(this); - - if (this.met()) { - return 'Expectation met: ' + message; - } - - return ( - 'Expected ' + - message + - ' (' + - callCountInWords(this.callCount) + - ')' - ); - }, - - verify: function verify() { - if (!this.met()) { - sinon.expectation.fail(this.toString()); - } else { - sinon.expectation.pass(this.toString()); - } - - return true; - }, - - pass: function (message) { - sinon.assert.pass(message); - }, - fail: function (message) { - var exception = new Error(message); - exception.name = 'ExpectationError'; - - throw exception; - }, - }; - })(); - - if (commonJSModule) { - module.exports = mock; - } else { - sinon.mock = mock; - } - })((typeof sinon == 'object' && sinon) || null); - - /** - * @depend ../sinon.js - * @depend stub.js - * @depend mock.js - */ - /*jslint eqeqeq: false, onevar: false, forin: true*/ - /*global module, require, sinon*/ - /** - * Collections of stubs, spies and mocks. - * - * @author Christian Johansen ([email protected]) - * @license BSD - * - * Copyright (c) 2010-2011 Christian Johansen - */ - - (function (sinon) { - var commonJSModule = - typeof module == 'object' && typeof require == 'function'; - var push = [].push; - var hasOwnProperty = Object.prototype.hasOwnProperty; - - if (!sinon && commonJSModule) { - sinon = require('../sinon'); - } - - if (!sinon) { - return; - } - - function getFakes(fakeCollection) { - if (!fakeCollection.fakes) { - fakeCollection.fakes = []; - } - - return fakeCollection.fakes; - } - - function each(fakeCollection, method) { - var fakes = getFakes(fakeCollection); - - for (var i = 0, l = fakes.length; i < l; i += 1) { - if (typeof fakes[i][method] == 'function') { - fakes[i][method](); - } - } - } - - function compact(fakeCollection) { - var fakes = getFakes(fakeCollection); - var i = 0; - while (i < fakes.length) { - fakes.splice(i, 1); - } - } - - var collection = { - verify: function resolve() { - each(this, 'verify'); - }, - - restore: function restore() { - each(this, 'restore'); - compact(this); - }, - - verifyAndRestore: function verifyAndRestore() { - var exception; - - try { - this.verify(); - } catch (e) { - exception = e; - } - - this.restore(); - - if (exception) { - throw exception; - } - }, - - add: function add(fake) { - push.call(getFakes(this), fake); - return fake; - }, - - spy: function spy() { - return this.add(sinon.spy.apply(sinon, arguments)); - }, - - stub: function stub(object, property, value) { - if (property) { - var original = object[property]; - - if (typeof original != 'function') { - if (!hasOwnProperty.call(object, property)) { - throw new TypeError( - 'Cannot stub non-existent own property ' + property - ); - } - - object[property] = value; - - return this.add({ - restore: function () { - object[property] = original; - }, - }); - } - } - if (!property && !!object && typeof object == 'object') { - var stubbedObj = sinon.stub.apply(sinon, arguments); - - for (var prop in stubbedObj) { - if (typeof stubbedObj[prop] === 'function') { - this.add(stubbedObj[prop]); - } - } - - return stubbedObj; - } - - return this.add(sinon.stub.apply(sinon, arguments)); - }, - - mock: function mock() { - return this.add(sinon.mock.apply(sinon, arguments)); - }, - - inject: function inject(obj) { - var col = this; - - obj.spy = function () { - return col.spy.apply(col, arguments); - }; - - obj.stub = function () { - return col.stub.apply(col, arguments); - }; - - obj.mock = function () { - return col.mock.apply(col, arguments); - }; - - return obj; - }, - }; - - if (commonJSModule) { - module.exports = collection; - } else { - sinon.collection = collection; - } - })((typeof sinon == 'object' && sinon) || null); - - /*jslint eqeqeq: false, plusplus: false, evil: true, onevar: false, browser: true, forin: false*/ - /*global module, require, window*/ - /** - * Fake timer API - * setTimeout - * setInterval - * clearTimeout - * clearInterval - * tick - * reset - * Date - * - * Inspired by jsUnitMockTimeOut from JsUnit - * - * @author Christian Johansen ([email protected]) - * @license BSD - * - * Copyright (c) 2010-2011 Christian Johansen - */ - - if (typeof sinon == 'undefined') { - var sinon = {}; - } - - (function (global) { - var id = 1; - - function addTimer(args, recurring) { - if (args.length === 0) { - throw new Error('Function requires at least 1 parameter'); - } - - var toId = id++; - var delay = args[1] || 0; - - if (!this.timeouts) { - this.timeouts = {}; - } - - this.timeouts[toId] = { - id: toId, - func: args[0], - callAt: this.now + delay, - invokeArgs: Array.prototype.slice.call(args, 2), - }; - - if (recurring === true) { - this.timeouts[toId].interval = delay; - } - - return toId; - } - - function parseTime(str) { - if (!str) { - return 0; - } - - var strings = str.split(':'); - var l = strings.length, - i = l; - var ms = 0, - parsed; - - if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) { - throw new Error("tick only understands numbers and 'h:m:s'"); - } - - while (i--) { - parsed = parseInt(strings[i], 10); - - if (parsed >= 60) { - throw new Error('Invalid time ' + str); - } - - ms += parsed * Math.pow(60, l - i - 1); - } - - return ms * 1000; - } - - function createObject(object) { - var newObject; - - if (Object.create) { - newObject = Object.create(object); - } else { - var F = function () {}; - F.prototype = object; - newObject = new F(); - } - - newObject.Date.clock = newObject; - return newObject; - } - - sinon.clock = { - now: 0, - - create: function create(now) { - var clock = createObject(this); - - if (typeof now == 'number') { - clock.now = now; - } - - if (!!now && typeof now == 'object') { - throw new TypeError('now should be milliseconds since UNIX epoch'); - } - - return clock; - }, - - setTimeout: function setTimeout(callback, timeout) { - return addTimer.call(this, arguments, false); - }, - - clearTimeout: function clearTimeout(timerId) { - if (!this.timeouts) { - this.timeouts = []; - } - - if (timerId in this.timeouts) { - delete this.timeouts[timerId]; - } - }, - - setInterval: function setInterval(callback, timeout) { - return addTimer.call(this, arguments, true); - }, - - clearInterval: function clearInterval(timerId) { - this.clearTimeout(timerId); - }, - - tick: function tick(ms) { - ms = typeof ms == 'number' ? ms : parseTime(ms); - var tickFrom = this.now, - tickTo = this.now + ms, - previous = this.now; - var timer = this.firstTimerInRange(tickFrom, tickTo); - - var firstException; - while (timer && tickFrom <= tickTo) { - if (this.timeouts[timer.id]) { - tickFrom = this.now = timer.callAt; - try { - this.callTimer(timer); - } catch (e) { - firstException = firstException || e; - } - } - - timer = this.firstTimerInRange(previous, tickTo); - previous = tickFrom; - } - - this.now = tickTo; - - if (firstException) { - throw firstException; - } - }, - - firstTimerInRange: function (from, to) { - var timer, smallest, originalTimer; - - for (var id in this.timeouts) { - if (this.timeouts.hasOwnProperty(id)) { - if ( - this.timeouts[id].callAt < from || - this.timeouts[id].callAt > to - ) { - continue; - } - - if (!smallest || this.timeouts[id].callAt < smallest) { - originalTimer = this.timeouts[id]; - smallest = this.timeouts[id].callAt; - - timer = { - func: this.timeouts[id].func, - callAt: this.timeouts[id].callAt, - interval: this.timeouts[id].interval, - id: this.timeouts[id].id, - invokeArgs: this.timeouts[id].invokeArgs, - }; - } - } - } - - return timer || null; - }, - - callTimer: function (timer) { - if (typeof timer.interval == 'number') { - this.timeouts[timer.id].callAt += timer.interval; - } else { - delete this.timeouts[timer.id]; - } - - try { - if (typeof timer.func == 'function') { - timer.func.apply(null, timer.invokeArgs); - } else { - eval(timer.func); - } - } catch (e) { - var exception = e; - } - - if (!this.timeouts[timer.id]) { - if (exception) { - throw exception; - } - return; - } - - if (exception) { - throw exception; - } - }, - - reset: function reset() { - this.timeouts = {}; - }, - - Date: (function () { - var NativeDate = Date; - - function ClockDate(year, month, date, hour, minute, second, ms) { - // Defensive and verbose to avoid potential harm in passing - // explicit undefined when user does not pass argument - switch (arguments.length) { - case 0: - return new NativeDate(ClockDate.clock.now); - case 1: - return new NativeDate(year); - case 2: - return new NativeDate(year, month); - case 3: - return new NativeDate(year, month, date); - case 4: - return new NativeDate(year, month, date, hour); - case 5: - return new NativeDate(year, month, date, hour, minute); - case 6: - return new NativeDate(year, month, date, hour, minute, second); - default: - return new NativeDate( - year, - month, - date, - hour, - minute, - second, - ms - ); - } - } - - return mirrorDateProperties(ClockDate, NativeDate); - })(), - }; - - function mirrorDateProperties(target, source) { - if (source.now) { - target.now = function now() { - return target.clock.now; - }; - } else { - delete target.now; - } - - if (source.toSource) { - target.toSource = function toSource() { - return source.toSource(); - }; - } else { - delete target.toSource; - } - - target.toString = function toString() { - return source.toString(); - }; - - target.prototype = source.prototype; - target.parse = source.parse; - target.UTC = source.UTC; - target.prototype.toUTCString = source.prototype.toUTCString; - return target; - } - - var methods = [ - 'Date', - 'setTimeout', - 'setInterval', - 'clearTimeout', - 'clearInterval', - ]; - - function restore() { - var method; - - for (var i = 0, l = this.methods.length; i < l; i++) { - method = this.methods[i]; - if (global[method].hadOwnProperty) { - global[method] = this['_' + method]; - } else { - delete global[method]; - } - } - - // Prevent multiple executions which will completely remove these props - this.methods = []; - } - - function stubGlobal(method, clock) { - clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call( - global, - method - ); - clock['_' + method] = global[method]; - - if (method == 'Date') { - var date = mirrorDateProperties(clock[method], global[method]); - global[method] = date; - } else { - global[method] = function () { - return clock[method].apply(clock, arguments); - }; - - for (var prop in clock[method]) { - if (clock[method].hasOwnProperty(prop)) { - global[method][prop] = clock[method][prop]; - } - } - } - - global[method].clock = clock; - } - - sinon.useFakeTimers = function useFakeTimers(now) { - var clock = sinon.clock.create(now); - clock.restore = restore; - clock.methods = Array.prototype.slice.call( - arguments, - typeof now == 'number' ? 1 : 0 - ); - - if (clock.methods.length === 0) { - clock.methods = methods; - } - - for (var i = 0, l = clock.methods.length; i < l; i++) { - stubGlobal(clock.methods[i], clock); - } - - return clock; - }; - })( - typeof global != 'undefined' && typeof global !== 'function' ? global : this - ); - - sinon.timers = { - setTimeout: setTimeout, - clearTimeout: clearTimeout, - setInterval: setInterval, - clearInterval: clearInterval, - Date: Date, - }; - - if (typeof module == 'object' && typeof require == 'function') { - module.exports = sinon; - } - - /*jslint eqeqeq: false, onevar: false*/ - /*global sinon, module, require, ActiveXObject, XMLHttpRequest, DOMParser*/ - /** - * Minimal Event interface implementation - * - * Original implementation by Sven Fuchs: https://gist.github.com/995028 - * Modifications and tests by Christian Johansen. - * - * @author Sven Fuchs ([email protected]) - * @author Christian Johansen ([email protected]) - * @license BSD - * - * Copyright (c) 2011 Sven Fuchs, Christian Johansen - */ - - if (typeof sinon == 'undefined') { - this.sinon = {}; - } - - (function () { - var push = [].push; - - sinon.Event = function Event(type, bubbles, cancelable) { - this.initEvent(type, bubbles, cancelable); - }; - - sinon.Event.prototype = { - initEvent: function (type, bubbles, cancelable) { - this.type = type; - this.bubbles = bubbles; - this.cancelable = cancelable; - }, - - stopPropagation: function () {}, - - preventDefault: function () { - this.defaultPrevented = true; - }, - }; - - sinon.EventTarget = { - addEventListener: function addEventListener(event, listener, useCapture) { - this.eventListeners = this.eventListeners || {}; - this.eventListeners[event] = this.eventListeners[event] || []; - push.call(this.eventListeners[event], listener); - }, - - removeEventListener: function removeEventListener( - event, - listener, - useCapture - ) { - var listeners = - (this.eventListeners && this.eventListeners[event]) || []; - - for (var i = 0, l = listeners.length; i < l; ++i) { - if (listeners[i] == listener) { - return listeners.splice(i, 1); - } - } - }, - - dispatchEvent: function dispatchEvent(event) { - var type = event.type; - var listeners = - (this.eventListeners && this.eventListeners[type]) || []; - - for (var i = 0; i < listeners.length; i++) { - if (typeof listeners[i] == 'function') { - listeners[i].call(this, event); - } else { - listeners[i].handleEvent(event); - } - } - - return !!event.defaultPrevented; - }, - }; - })(); - - /** - * @depend ../../sinon.js - * @depend event.js - */ - /*jslint eqeqeq: false, onevar: false*/ - /*global sinon, module, require, ActiveXObject, XMLHttpRequest, DOMParser*/ - /** - * Fake XMLHttpRequest object - * - * @author Christian Johansen ([email protected]) - * @license BSD - * - * Copyright (c) 2010-2011 Christian Johansen - */ - - if (typeof sinon == 'undefined') { - this.sinon = {}; - } - sinon.xhr = { XMLHttpRequest: this.XMLHttpRequest }; - - // wrapper for global - (function (global) { - var xhr = sinon.xhr; - xhr.GlobalXMLHttpRequest = global.XMLHttpRequest; - xhr.GlobalActiveXObject = global.ActiveXObject; - xhr.supportsActiveX = typeof xhr.GlobalActiveXObject != 'undefined'; - xhr.supportsXHR = typeof xhr.GlobalXMLHttpRequest != 'undefined'; - xhr.workingXHR = xhr.supportsXHR - ? xhr.GlobalXMLHttpRequest - : xhr.supportsActiveX - ? function () { - return new xhr.GlobalActiveXObject('MSXML2.XMLHTTP.3.0'); - } - : false; - - /*jsl:ignore*/ - var unsafeHeaders = { - 'Accept-Charset': true, - 'Accept-Encoding': true, - Connection: true, - 'Content-Length': true, - Cookie: true, - Cookie2: true, - 'Content-Transfer-Encoding': true, - Date: true, - Expect: true, - Host: true, - 'Keep-Alive': true, - Referer: true, - TE: true, - Trailer: true, - 'Transfer-Encoding': true, - Upgrade: true, - 'User-Agent': true, - Via: true, - }; - /*jsl:end*/ - - function FakeXMLHttpRequest() { - this.readyState = FakeXMLHttpRequest.UNSENT; - this.requestHeaders = {}; - this.requestBody = null; - this.status = 0; - this.statusText = ''; - - if (typeof FakeXMLHttpRequest.onCreate == 'function') { - FakeXMLHttpRequest.onCreate(this); - } - } - - function verifyState(xhr) { - if (xhr.readyState !== FakeXMLHttpRequest.OPENED) { - throw new Error('INVALID_STATE_ERR'); - } - - if (xhr.sendFlag) { - throw new Error('INVALID_STATE_ERR'); - } - } - - // filtering to enable a white-list version of Sinon FakeXhr, - // where whitelisted requests are passed through to real XHR - function each(collection, callback) { - if (!collection) return; - for (var i = 0, l = collection.length; i < l; i += 1) { - callback(collection[i]); - } - } - function some(collection, callback) { - for (var index = 0; index < collection.length; index++) { - if (callback(collection[index]) === true) return true; - } - return false; - } - // largest arity in XHR is 5 - XHR#open - var apply = function (obj, method, args) { - switch (args.length) { - case 0: - return obj[method](); - case 1: - return obj[method](args[0]); - case 2: - return obj[method](args[0], args[1]); - case 3: - return obj[method](args[0], args[1], args[2]); - case 4: - return obj[method](args[0], args[1], args[2], args[3]); - case 5: - return obj[method](args[0], args[1], args[2], args[3], args[4]); - } - }; - - FakeXMLHttpRequest.filters = []; - FakeXMLHttpRequest.addFilter = function (fn) { - this.filters.push(fn); - }; - var IE6Re = /MSIE 6/; - FakeXMLHttpRequest.defake = function (fakeXhr, xhrArgs) { - var xhr = new sinon.xhr.workingXHR(); - each( - [ - 'open', - 'setRequestHeader', - 'send', - 'abort', - 'getResponseHeader', - 'getAllResponseHeaders', - 'addEventListener', - 'overrideMimeType', - 'removeEventListener', - ], - function (method) { - fakeXhr[method] = function () { - return apply(xhr, method, arguments); - }; - } - ); - - var copyAttrs = function (args) { - each(args, function (attr) { - try { - fakeXhr[attr] = xhr[attr]; - } catch (e) { - if (!IE6Re.test(navigator.userAgent)) throw e; - } - }); - }; - - var stateChange = function () { - fakeXhr.readyState = xhr.readyState; - if (xhr.readyState >= FakeXMLHttpRequest.HEADERS_RECEIVED) { - copyAttrs(['status', 'statusText']); - } - if (xhr.readyState >= FakeXMLHttpRequest.LOADING) { - copyAttrs(['responseText']); - } - if (xhr.readyState === FakeXMLHttpRequest.DONE) { - copyAttrs(['responseXML']); - } - if (fakeXhr.onreadystatechange) - fakeXhr.onreadystatechange.call(fakeXhr); - }; - if (xhr.addEventListener) { - for (var event in fakeXhr.eventListeners) { - if (fakeXhr.eventListeners.hasOwnProperty(event)) { - each(fakeXhr.eventListeners[event], function (handler) { - xhr.addEventListener(event, handler); - }); - } - } - xhr.addEventListener('readystatechange', stateChange); - } else { - xhr.onreadystatechange = stateChange; - } - apply(xhr, 'open', xhrArgs); - }; - FakeXMLHttpRequest.useFilters = false; - - function verifyRequestSent(xhr) { - if (xhr.readyState == FakeXMLHttpRequest.DONE) { - throw new Error('Request done'); - } - } - - function verifyHeadersReceived(xhr) { - if (xhr.async && xhr.readyState != FakeXMLHttpRequest.HEADERS_RECEIVED) { - throw new Error('No headers received'); - } - } - - function verifyResponseBodyType(body) { - if (typeof body != 'string') { - var error = new Error( - 'Attempted to respond to fake XMLHttpRequest with ' + - body + - ', which is not a string.' - ); - error.name = 'InvalidBodyException'; - throw error; - } - } - - sinon.extend(FakeXMLHttpRequest.prototype, sinon.EventTarget, { - async: true, - - open: function open(method, url, async, username, password) { - this.method = method; - this.url = url; - this.async = typeof async == 'boolean' ? async : true; - this.username = username; - this.password = password; - this.responseText = null; - this.responseXML = null; - this.requestHeaders = {}; - this.sendFlag = false; - if (sinon.FakeXMLHttpRequest.useFilters === true) { - var xhrArgs = arguments; - var defake = some(FakeXMLHttpRequest.filters, function (filter) { - return filter.apply(this, xhrArgs); - }); - if (defake) { - return sinon.FakeXMLHttpRequest.defake(this, arguments); - } - } - this.readyStateChange(FakeXMLHttpRequest.OPENED); - }, - - readyStateChange: function readyStateChange(state) { - this.readyState = state; - - if (typeof this.onreadystatechange == 'function') { - try { - this.onreadystatechange(); - } catch (e) { - sinon.logError('Fake XHR onreadystatechange handler', e); - } - } - - this.dispatchEvent(new sinon.Event('readystatechange')); - }, - - setRequestHeader: function setRequestHeader(header, value) { - verifyState(this); - - if (unsafeHeaders[header] || /^(Sec-|Proxy-)/.test(header)) { - throw new Error('Refused to set unsafe header "' + header + '"'); - } - - if (this.requestHeaders[header]) { - this.requestHeaders[header] += ',' + value; - } else { - this.requestHeaders[header] = value; - } - }, - - // Helps testing - setResponseHeaders: function setResponseHeaders(headers) { - this.responseHeaders = {}; - - for (var header in headers) { - if (headers.hasOwnProperty(header)) { - this.responseHeaders[header] = headers[header]; - } - } - - if (this.async) { - this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED); - } - }, - - // Currently treats ALL data as a DOMString (i.e. no Document) - send: function send(data) { - verifyState(this); - - if (!/^(get|head)$/i.test(this.method)) { - if (this.requestHeaders['Content-Type']) { - var value = this.requestHeaders['Content-Type'].split(';'); - this.requestHeaders['Content-Type'] = value[0] + ';charset=utf-8'; - } else { - this.requestHeaders['Content-Type'] = 'text/plain;charset=utf-8'; - } - - this.requestBody = data; - } - - this.errorFlag = false; - this.sendFlag = this.async; - this.readyStateChange(FakeXMLHttpRequest.OPENED); - - if (typeof this.onSend == 'function') { - this.onSend(this); - } - }, - - abort: function abort() { - this.aborted = true; - this.responseText = null; - this.errorFlag = true; - this.requestHeaders = {}; - - if ( - this.readyState > sinon.FakeXMLHttpRequest.UNSENT && - this.sendFlag - ) { - this.readyStateChange(sinon.FakeXMLHttpRequest.DONE); - this.sendFlag = false; - } - - this.readyState = sinon.FakeXMLHttpRequest.UNSENT; - }, - - getResponseHeader: function getResponseHeader(header) { - if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) { - return null; - } - - if (/^Set-Cookie2?$/i.test(header)) { - return null; - } - - header = header.toLowerCase(); - - for (var h in this.responseHeaders) { - if (h.toLowerCase() == header) { - return this.responseHeaders[h]; - } - } - - return null; - }, - - getAllResponseHeaders: function getAllResponseHeaders() { - if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) { - return ''; - } - - var headers = ''; - - for (var header in this.responseHeaders) { - if ( - this.responseHeaders.hasOwnProperty(header) && - !/^Set-Cookie2?$/i.test(header) - ) { - headers += header + ': ' + this.responseHeaders[header] + '\r\n'; - } - } - - return headers; - }, - - setResponseBody: function setResponseBody(body) { - verifyRequestSent(this); - verifyHeadersReceived(this); - verifyResponseBodyType(body); - - var chunkSize = this.chunkSize || 10; - var index = 0; - this.responseText = ''; - - do { - if (this.async) { - this.readyStateChange(FakeXMLHttpRequest.LOADING); - } - - this.responseText += body.substring(index, index + chunkSize); - index += chunkSize; - } while (index < body.length); - - var type = this.getResponseHeader('Content-Type'); - - if ( - this.responseText && - (!type || /(text\/xml)|(application\/xml)|(\+xml)/.test(type)) - ) { - try { - this.responseXML = FakeXMLHttpRequest.parseXML(this.responseText); - } catch (e) { - // Unable to parse XML - no biggie - } - } - - if (this.async) { - this.readyStateChange(FakeXMLHttpRequest.DONE); - } else { - this.readyState = FakeXMLHttpRequest.DONE; - } - }, - - respond: function respond(status, headers, body) { - this.setResponseHeaders(headers || {}); - this.status = typeof status == 'number' ? status : 200; - this.statusText = FakeXMLHttpRequest.statusCodes[this.status]; - this.setResponseBody(body || ''); - }, - }); - - sinon.extend(FakeXMLHttpRequest, { - UNSENT: 0, - OPENED: 1, - HEADERS_RECEIVED: 2, - LOADING: 3, - DONE: 4, - }); - - // Borrowed from JSpec - FakeXMLHttpRequest.parseXML = function parseXML(text) { - var xmlDoc; - - if (typeof DOMParser != 'undefined') { - var parser = new DOMParser(); - xmlDoc = parser.parseFromString(text, 'text/xml'); - } else { - xmlDoc = new ActiveXObject('Microsoft.XMLDOM'); - xmlDoc.async = 'false'; - xmlDoc.loadXML(text); - } - - return xmlDoc; - }; - - FakeXMLHttpRequest.statusCodes = { - 100: 'Continue', - 101: 'Switching Protocols', - 200: 'OK', - 201: 'Created', - 202: 'Accepted', - 203: 'Non-Authoritative Information', - 204: 'No Content', - 205: 'Reset Content', - 206: 'Partial Content', - 300: 'Multiple Choice', - 301: 'Moved Permanently', - 302: 'Found', - 303: 'See Other', - 304: 'Not Modified', - 305: 'Use Proxy', - 307: 'Temporary Redirect', - 400: 'Bad Request', - 401: 'Unauthorized', - 402: 'Payment Required', - 403: 'Forbidden', - 404: 'Not Found', - 405: 'Method Not Allowed', - 406: 'Not Acceptable', - 407: 'Proxy Authentication Required', - 408: 'Request Timeout', - 409: 'Conflict', - 410: 'Gone', - 411: 'Length Required', - 412: 'Precondition Failed', - 413: 'Request Entity Too Large', - 414: 'Request-URI Too Long', - 415: 'Unsupported Media Type', - 416: 'Requested Range Not Satisfiable', - 417: 'Expectation Failed', - 422: 'Unprocessable Entity', - 500: 'Internal Server Error', - 501: 'Not Implemented', - 502: 'Bad Gateway', - 503: 'Service Unavailable', - 504: 'Gateway Timeout', - 505: 'HTTP Version Not Supported', - }; - - sinon.useFakeXMLHttpRequest = function () { - sinon.FakeXMLHttpRequest.restore = function restore(keepOnCreate) { - if (xhr.supportsXHR) { - global.XMLHttpRequest = xhr.GlobalXMLHttpRequest; - } - - if (xhr.supportsActiveX) { - global.ActiveXObject = xhr.GlobalActiveXObject; - } - - delete sinon.FakeXMLHttpRequest.restore; - - if (keepOnCreate !== true) { - delete sinon.FakeXMLHttpRequest.onCreate; - } - }; - if (xhr.supportsXHR) { - global.XMLHttpRequest = sinon.FakeXMLHttpRequest; - } - - if (xhr.supportsActiveX) { - global.ActiveXObject = function ActiveXObject(objId) { - if (objId == 'Microsoft.XMLHTTP' || /^Msxml2\.XMLHTTP/i.test(objId)) { - return new sinon.FakeXMLHttpRequest(); - } - - return new xhr.GlobalActiveXObject(objId); - }; - } - - return sinon.FakeXMLHttpRequest; - }; - - sinon.FakeXMLHttpRequest = FakeXMLHttpRequest; - })(this); - - if (typeof module == 'object' && typeof require == 'function') { - module.exports = sinon; - } - - /** - * @depend fake_xml_http_request.js - */ - /*jslint eqeqeq: false, onevar: false, regexp: false, plusplus: false*/ - /*global module, require, window*/ - /** - * The Sinon "server" mimics a web server that receives requests from - * sinon.FakeXMLHttpRequest and provides an API to respond to those requests, - * both synchronously and asynchronously. To respond synchronuously, canned - * answers have to be provided upfront. - * - * @author Christian Johansen ([email protected]) - * @license BSD - * - * Copyright (c) 2010-2011 Christian Johansen - */ - - if (typeof sinon == 'undefined') { - var sinon = {}; - } - - sinon.fakeServer = (function () { - var push = [].push; - function F() {} - - function create(proto) { - F.prototype = proto; - return new F(); - } - - function responseArray(handler) { - var response = handler; - - if (Object.prototype.toString.call(handler) != '[object Array]') { - response = [200, {}, handler]; - } - - if (typeof response[2] != 'string') { - throw new TypeError( - 'Fake server response body should be string, but was ' + - typeof response[2] - ); - } - - return response; - } - - var wloc = typeof window !== 'undefined' ? window.location : {}; - var rCurrLoc = new RegExp('^' + wloc.protocol + '//' + wloc.host); - - function matchOne(response, reqMethod, reqUrl) { - var rmeth = response.method; - var matchMethod = - !rmeth || rmeth.toLowerCase() == reqMethod.toLowerCase(); - var url = response.url; - var matchUrl = - !url || - url == reqUrl || - (typeof url.test == 'function' && url.test(reqUrl)); - - return matchMethod && matchUrl; - } - - function match(response, request) { - var requestMethod = this.getHTTPMethod(request); - var requestUrl = request.url; - - if (!/^https?:\/\//.test(requestUrl) || rCurrLoc.test(requestUrl)) { - requestUrl = requestUrl.replace(rCurrLoc, ''); - } - - if (matchOne(response, this.getHTTPMethod(request), requestUrl)) { - if (typeof response.response == 'function') { - var ru = response.url; - var args = [request].concat(!ru ? [] : requestUrl.match(ru).slice(1)); - return response.response.apply(response, args); - } - - return true; - } - - return false; - } - - return { - create: function () { - var server = create(this); - this.xhr = sinon.useFakeXMLHttpRequest(); - server.requests = []; - - this.xhr.onCreate = function (xhrObj) { - server.addRequest(xhrObj); - }; - - return server; - }, - - addRequest: function addRequest(xhrObj) { - var server = this; - push.call(this.requests, xhrObj); - - xhrObj.onSend = function () { - server.handleRequest(this); - }; - - if (this.autoRespond && !this.responding) { - setTimeout(function () { - server.responding = false; - server.respond(); - }, this.autoRespondAfter || 10); - - this.responding = true; - } - }, - - getHTTPMethod: function getHTTPMethod(request) { - if (this.fakeHTTPMethods && /post/i.test(request.method)) { - var matches = (request.requestBody || '').match(/_method=([^\b;]+)/); - return !!matches ? matches[1] : request.method; - } - - return request.method; - }, - - handleRequest: function handleRequest(xhr) { - if (xhr.async) { - if (!this.queue) { - this.queue = []; - } - - push.call(this.queue, xhr); - } else { - this.processRequest(xhr); - } - }, - - respondWith: function respondWith(method, url, body) { - if (arguments.length == 1 && typeof method != 'function') { - this.response = responseArray(method); - return; - } - - if (!this.responses) { - this.responses = []; - } - - if (arguments.length == 1) { - body = method; - url = method = null; - } - - if (arguments.length == 2) { - body = url; - url = method; - method = null; - } - - push.call(this.responses, { - method: method, - url: url, - response: typeof body == 'function' ? body : responseArray(body), - }); - }, - - respond: function respond() { - if (arguments.length > 0) this.respondWith.apply(this, arguments); - var queue = this.queue || []; - var request; - - while ((request = queue.shift())) { - this.processRequest(request); - } - }, - - processRequest: function processRequest(request) { - try { - if (request.aborted) { - return; - } - - var response = this.response || [404, {}, '']; - - if (this.responses) { - for (var i = 0, l = this.responses.length; i < l; i++) { - if (match.call(this, this.responses[i], request)) { - response = this.responses[i].response; - break; - } - } - } - - if (request.readyState != 4) { - request.respond(response[0], response[1], response[2]); - } - } catch (e) { - sinon.logError('Fake server request processing', e); - } - }, - - restore: function restore() { - return this.xhr.restore && this.xhr.restore.apply(this.xhr, arguments); - }, - }; - })(); - - if (typeof module == 'object' && typeof require == 'function') { - module.exports = sinon; - } - - /** - * @depend fake_server.js - * @depend fake_timers.js - */ - /*jslint browser: true, eqeqeq: false, onevar: false*/ - /*global sinon*/ - /** - * Add-on for sinon.fakeServer that automatically handles a fake timer along with - * the FakeXMLHttpRequest. The direct inspiration for this add-on is jQuery - * 1.3.x, which does not use xhr object's onreadystatehandler at all - instead, - * it polls the object for completion with setInterval. Dispite the direct - * motivation, there is nothing jQuery-specific in this file, so it can be used - * in any environment where the ajax implementation depends on setInterval or - * setTimeout. - * - * @author Christian Johansen ([email protected]) - * @license BSD - * - * Copyright (c) 2010-2011 Christian Johansen - */ - - (function () { - function Server() {} - Server.prototype = sinon.fakeServer; - - sinon.fakeServerWithClock = new Server(); - - sinon.fakeServerWithClock.addRequest = function addRequest(xhr) { - if (xhr.async) { - if (typeof setTimeout.clock == 'object') { - this.clock = setTimeout.clock; - } else { - this.clock = sinon.useFakeTimers(); - this.resetClock = true; - } - - if (!this.longestTimeout) { - var clockSetTimeout = this.clock.setTimeout; - var clockSetInterval = this.clock.setInterval; - var server = this; - - this.clock.setTimeout = function (fn, timeout) { - server.longestTimeout = Math.max( - timeout, - server.longestTimeout || 0 - ); - - return clockSetTimeout.apply(this, arguments); - }; - - this.clock.setInterval = function (fn, timeout) { - server.longestTimeout = Math.max( - timeout, - server.longestTimeout || 0 - ); - - return clockSetInterval.apply(this, arguments); - }; - } - } - - return sinon.fakeServer.addRequest.call(this, xhr); - }; - - sinon.fakeServerWithClock.respond = function respond() { - var returnVal = sinon.fakeServer.respond.apply(this, arguments); - - if (this.clock) { - this.clock.tick(this.longestTimeout || 0); - this.longestTimeout = 0; - - if (this.resetClock) { - this.clock.restore(); - this.resetClock = false; - } - } - - return returnVal; - }; - - sinon.fakeServerWithClock.restore = function restore() { - if (this.clock) { - this.clock.restore(); - } - - return sinon.fakeServer.restore.apply(this, arguments); - }; - })(); - - /** - * @depend ../sinon.js - * @depend collection.js - * @depend util/fake_timers.js - * @depend util/fake_server_with_clock.js - */ - /*jslint eqeqeq: false, onevar: false, plusplus: false*/ - /*global require, module*/ - /** - * Manages fake collections as well as fake utilities such as Sinon's - * timers and fake XHR implementation in one convenient object. - * - * @author Christian Johansen ([email protected]) - * @license BSD - * - * Copyright (c) 2010-2011 Christian Johansen - */ - - if (typeof module == 'object' && typeof require == 'function') { - var sinon = require('../sinon'); - sinon.extend(sinon, require('./util/fake_timers')); - } - - (function () { - var push = [].push; - - function exposeValue(sandbox, config, key, value) { - if (!value) { - return; - } - - if (config.injectInto) { - config.injectInto[key] = value; - } else { - push.call(sandbox.args, value); - } - } - - function prepareSandboxFromConfig(config) { - var sandbox = sinon.create(sinon.sandbox); - - if (config.useFakeServer) { - if (typeof config.useFakeServer == 'object') { - sandbox.serverPrototype = config.useFakeServer; - } - - sandbox.useFakeServer(); - } - - if (config.useFakeTimers) { - if (typeof config.useFakeTimers == 'object') { - sandbox.useFakeTimers.apply(sandbox, config.useFakeTimers); - } else { - sandbox.useFakeTimers(); - } - } - - return sandbox; - } - - sinon.sandbox = sinon.extend(sinon.create(sinon.collection), { - useFakeTimers: function useFakeTimers() { - this.clock = sinon.useFakeTimers.apply(sinon, arguments); - - return this.add(this.clock); - }, - - serverPrototype: sinon.fakeServer, - - useFakeServer: function useFakeServer() { - var proto = this.serverPrototype || sinon.fakeServer; - - if (!proto || !proto.create) { - return null; - } - - this.server = proto.create(); - return this.add(this.server); - }, - - inject: function (obj) { - sinon.collection.inject.call(this, obj); - - if (this.clock) { - obj.clock = this.clock; - } - - if (this.server) { - obj.server = this.server; - obj.requests = this.server.requests; - } - - return obj; - }, - - create: function (config) { - if (!config) { - return sinon.create(sinon.sandbox); - } - - var sandbox = prepareSandboxFromConfig(config); - sandbox.args = sandbox.args || []; - var prop, - value, - exposed = sandbox.inject({}); - - if (config.properties) { - for (var i = 0, l = config.properties.length; i < l; i++) { - prop = config.properties[i]; - value = exposed[prop] || (prop == 'sandbox' && sandbox); - exposeValue(sandbox, config, prop, value); - } - } else { - exposeValue(sandbox, config, 'sandbox', value); - } - - return sandbox; - }, - }); - - sinon.sandbox.useFakeXMLHttpRequest = sinon.sandbox.useFakeServer; - - if (typeof module == 'object' && typeof require == 'function') { - module.exports = sinon.sandbox; - } - })(); - - /** - * @depend ../sinon.js - * @depend stub.js - * @depend mock.js - * @depend sandbox.js - */ - /*jslint eqeqeq: false, onevar: false, forin: true, plusplus: false*/ - /*global module, require, sinon*/ - /** - * Test function, sandboxes fakes - * - * @author Christian Johansen ([email protected]) - * @license BSD - * - * Copyright (c) 2010-2011 Christian Johansen - */ - - (function (sinon) { - var commonJSModule = - typeof module == 'object' && typeof require == 'function'; - - if (!sinon && commonJSModule) { - sinon = require('../sinon'); - } - - if (!sinon) { - return; - } - - function test(callback) { - var type = typeof callback; - - if (type != 'function') { - throw new TypeError( - 'sinon.test needs to wrap a test function, got ' + type - ); - } - - return function () { - var config = sinon.getConfig(sinon.config); - config.injectInto = - (config.injectIntoThis && this) || config.injectInto; - var sandbox = sinon.sandbox.create(config); - var exception, result; - var args = Array.prototype.slice.call(arguments).concat(sandbox.args); - - try { - result = callback.apply(this, args); - } catch (e) { - exception = e; - } - - if (typeof exception !== 'undefined') { - sandbox.restore(); - throw exception; - } else { - sandbox.verifyAndRestore(); - } - - return result; - }; - } - - test.config = { - injectIntoThis: true, - injectInto: null, - properties: ['spy', 'stub', 'mock', 'clock', 'server', 'requests'], - useFakeTimers: true, - useFakeServer: true, - }; - - if (commonJSModule) { - module.exports = test; - } else { - sinon.test = test; - } - })((typeof sinon == 'object' && sinon) || null); - - /** - * @depend ../sinon.js - * @depend test.js - */ - /*jslint eqeqeq: false, onevar: false, eqeqeq: false*/ - /*global module, require, sinon*/ - /** - * Test case, sandboxes all test functions - * - * @author Christian Johansen ([email protected]) - * @license BSD - * - * Copyright (c) 2010-2011 Christian Johansen - */ - - (function (sinon) { - var commonJSModule = - typeof module == 'object' && typeof require == 'function'; - - if (!sinon && commonJSModule) { - sinon = require('../sinon'); - } - - if (!sinon || !Object.prototype.hasOwnProperty) { - return; - } - - function createTest(property, setUp, tearDown) { - return function () { - if (setUp) { - setUp.apply(this, arguments); - } - - var exception, result; - - try { - result = property.apply(this, arguments); - } catch (e) { - exception = e; - } - - if (tearDown) { - tearDown.apply(this, arguments); - } - - if (exception) { - throw exception; - } - - return result; - }; - } - - function testCase(tests, prefix) { - /*jsl:ignore*/ - if (!tests || typeof tests != 'object') { - throw new TypeError( - 'sinon.testCase needs an object with test functions' - ); - } - /*jsl:end*/ - - prefix = prefix || 'test'; - var rPrefix = new RegExp('^' + prefix); - var methods = {}, - testName, - property, - method; - var setUp = tests.setUp; - var tearDown = tests.tearDown; - - for (testName in tests) { - if (tests.hasOwnProperty(testName)) { - property = tests[testName]; - - if (/^(setUp|tearDown)$/.test(testName)) { - continue; - } - - if (typeof property == 'function' && rPrefix.test(testName)) { - method = property; - - if (setUp || tearDown) { - method = createTest(property, setUp, tearDown); - } - - methods[testName] = sinon.test(method); - } else { - methods[testName] = tests[testName]; - } - } - } - - return methods; - } - - if (commonJSModule) { - module.exports = testCase; - } else { - sinon.testCase = testCase; - } - })((typeof sinon == 'object' && sinon) || null); - - /** - * @depend ../sinon.js - * @depend stub.js - */ - /*jslint eqeqeq: false, onevar: false, nomen: false, plusplus: false*/ - /*global module, require, sinon*/ - /** - * Assertions matching the test spy retrieval interface. - * - * @author Christian Johansen ([email protected]) - * @license BSD - * - * Copyright (c) 2010-2011 Christian Johansen - */ - - (function (sinon, global) { - var commonJSModule = - typeof module == 'object' && typeof require == 'function'; - var slice = Array.prototype.slice; - var assert; - - if (!sinon && commonJSModule) { - sinon = require('../sinon'); - } - - if (!sinon) { - return; - } - - function verifyIsStub() { - var method; - - for (var i = 0, l = arguments.length; i < l; ++i) { - method = arguments[i]; - - if (!method) { - assert.fail('fake is not a spy'); - } - - if (typeof method != 'function') { - assert.fail(method + ' is not a function'); - } - - if (typeof method.getCall != 'function') { - assert.fail(method + ' is not stubbed'); - } - } - } - - function failAssertion(object, msg) { - object = object || global; - var failMethod = object.fail || assert.fail; - failMethod.call(object, msg); - } - - function mirrorPropAsAssertion(name, method, message) { - if (arguments.length == 2) { - message = method; - method = name; - } - - assert[name] = function (fake) { - verifyIsStub(fake); - - var args = slice.call(arguments, 1); - var failed = false; - - if (typeof method == 'function') { - failed = !method(fake); - } else { - failed = - typeof fake[method] == 'function' - ? !fake[method].apply(fake, args) - : !fake[method]; - } - - if (failed) { - failAssertion(this, fake.printf.apply(fake, [message].concat(args))); - } else { - assert.pass(name); - } - }; - } - - function exposedName(prefix, prop) { - return !prefix || /^fail/.test(prop) - ? prop - : prefix + prop.slice(0, 1).toUpperCase() + prop.slice(1); - } - - assert = { - failException: 'AssertError', - - fail: function fail(message) { - var error = new Error(message); - error.name = this.failException || assert.failException; - - throw error; - }, - - pass: function pass(assertion) {}, - - callOrder: function assertCallOrder() { - verifyIsStub.apply(null, arguments); - var expected = '', - actual = ''; - - if (!sinon.calledInOrder(arguments)) { - try { - expected = [].join.call(arguments, ', '); - actual = sinon.orderByFirstCall(slice.call(arguments)).join(', '); - } catch (e) { - // If this fails, we'll just fall back to the blank string - } - - failAssertion( - this, - 'expected ' + - expected + - ' to be ' + - 'called in order but were called as ' + - actual - ); - } else { - assert.pass('callOrder'); - } - }, - - callCount: function assertCallCount(method, count) { - verifyIsStub(method); - - if (method.callCount != count) { - var msg = - 'expected %n to be called ' + - sinon.timesInWords(count) + - ' but was called %c%C'; - failAssertion(this, method.printf(msg)); - } else { - assert.pass('callCount'); - } - }, - - expose: function expose(target, options) { - if (!target) { - throw new TypeError('target is null or undefined'); - } - - var o = options || {}; - var prefix = (typeof o.prefix == 'undefined' && 'assert') || o.prefix; - var includeFail = - typeof o.includeFail == 'undefined' || !!o.includeFail; - - for (var method in this) { - if (method != 'export' && (includeFail || !/^(fail)/.test(method))) { - target[exposedName(prefix, method)] = this[method]; - } - } - - return target; - }, - }; - - mirrorPropAsAssertion( - 'called', - 'expected %n to have been called at least once but was never called' - ); - mirrorPropAsAssertion( - 'notCalled', - function (spy) { - return !spy.called; - }, - 'expected %n to not have been called but was called %c%C' - ); - mirrorPropAsAssertion( - 'calledOnce', - 'expected %n to be called once but was called %c%C' - ); - mirrorPropAsAssertion( - 'calledTwice', - 'expected %n to be called twice but was called %c%C' - ); - mirrorPropAsAssertion( - 'calledThrice', - 'expected %n to be called thrice but was called %c%C' - ); - mirrorPropAsAssertion( - 'calledOn', - 'expected %n to be called with %1 as this but was called with %t' - ); - mirrorPropAsAssertion( - 'alwaysCalledOn', - 'expected %n to always be called with %1 as this but was called with %t' - ); - mirrorPropAsAssertion('calledWithNew', 'expected %n to be called with new'); - mirrorPropAsAssertion( - 'alwaysCalledWithNew', - 'expected %n to always be called with new' - ); - mirrorPropAsAssertion( - 'calledWith', - 'expected %n to be called with arguments %*%C' - ); - mirrorPropAsAssertion( - 'calledWithMatch', - 'expected %n to be called with match %*%C' - ); - mirrorPropAsAssertion( - 'alwaysCalledWith', - 'expected %n to always be called with arguments %*%C' - ); - mirrorPropAsAssertion( - 'alwaysCalledWithMatch', - 'expected %n to always be called with match %*%C' - ); - mirrorPropAsAssertion( - 'calledWithExactly', - 'expected %n to be called with exact arguments %*%C' - ); - mirrorPropAsAssertion( - 'alwaysCalledWithExactly', - 'expected %n to always be called with exact arguments %*%C' - ); - mirrorPropAsAssertion( - 'neverCalledWith', - 'expected %n to never be called with arguments %*%C' - ); - mirrorPropAsAssertion( - 'neverCalledWithMatch', - 'expected %n to never be called with match %*%C' - ); - mirrorPropAsAssertion('threw', '%n did not throw exception%C'); - mirrorPropAsAssertion('alwaysThrew', '%n did not always throw exception%C'); - - if (commonJSModule) { - module.exports = assert; - } else { - sinon.assert = assert; - } - })( - (typeof sinon == 'object' && sinon) || null, - typeof window != 'undefined' ? window : global - ); - - return sinon; -}.call((typeof window != 'undefined' && window) || {}); diff --git a/test/support/walk_dir.js b/test/support/walk_dir.js deleted file mode 100644 index f6a22dbb..00000000 --- a/test/support/walk_dir.js +++ /dev/null @@ -1,51 +0,0 @@ -var fs = require('fs'); - -var methods = { - walk: function (dir, validation_function, cb) { - if (arguments.length === 2) { - cb = validation_function; - validation_function = null; - } - - var results = []; - fs.readdir(dir, function (err, list) { - if (err) { - return cb(err); - } - - var pending = list.length; - - if (!pending) { - return cb(null, results); - } - - list.forEach(function (file) { - file = dir + '/' + file; - fs.stat(file, function (err, stat) { - if (stat && stat.isDirectory()) { - methods.walk(file, validation_function, function (err, res) { - results = results.concat(res); - if (!--pending) { - cb(null, results); - } - }); - } else { - if (typeof validation_function === 'function') { - if (validation_function(file)) { - results.push(file); - } - } else { - results.push(file); - } - - if (!--pending) { - cb(null, results); - } - } - }); - }); - }); - }, -}; - -module.exports = methods; diff --git a/test/system.spec.ts b/test/system.spec.ts new file mode 100644 index 00000000..5263a62f --- /dev/null +++ b/test/system.spec.ts @@ -0,0 +1,74 @@ +import { describe, expect, it, vi } from 'vitest'; +import { faker } from '../lib'; + +describe('system', () => { + describe('directoryPath()', () => { + it('returns unix fs directory full path', () => { + const spy_random_words = vi + .spyOn(faker.random, 'words') + .mockReturnValue('24/7'); + + const directoryPath = faker.system.directoryPath(); + + expect( + directoryPath.indexOf('/'), + 'generated directoryPath should start with /' + ).toBe(0); + + spy_random_words.mockRestore(); + }); + }); + + describe('filePath()', () => { + it('returns unix fs file full path', () => { + const spy_random_words = vi + .spyOn(faker.random, 'words') + .mockReturnValue('24/7'); + + const filePath = faker.system.filePath(); + + expect( + filePath.indexOf('/'), + 'generated filePath should start with /' + ).toBe(0); + + spy_random_words.mockRestore(); + }); + }); + + describe('fileName()', () => { + it('returns filenames without system path separators', () => { + const spy_random_words = vi + .spyOn(faker.random, 'words') + .mockReturnValue('24/7'); + + const fileName = faker.system.fileName(); + + expect( + fileName.indexOf('/'), + 'generated fileNames should not have path separators' + ).toBe(-1); + + spy_random_words.mockRestore(); + }); + }); + + describe('commonFileName()', () => { + it('returns filenames without system path separators', () => { + const spy_random_words = vi + .spyOn(faker.random, 'words') + .mockReturnValue('24/7'); + + const fileName = + // @ts-expect-error + faker.system.commonFileName(); + + expect( + fileName.indexOf('/'), + 'generated commonFileNames should not have path separators' + ).toBe(-1); + + spy_random_words.mockRestore(); + }); + }); +}); diff --git a/test/system.unit.js b/test/system.unit.js deleted file mode 100644 index ee279750..00000000 --- a/test/system.unit.js +++ /dev/null @@ -1,63 +0,0 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var sinon = require('sinon'); - var faker = require('../lib').faker; -} - -describe('system.js', function () { - describe('directoryPath()', function () { - it('returns unix fs directory full path', function () { - sinon.stub(faker.random, 'words').returns('24/7'); - var directoryPath = faker.system.directoryPath(); - assert.strictEqual( - directoryPath.indexOf('/'), - 0, - 'generated directoryPath should start with /' - ); - - faker.random.words.restore(); - }); - }); - - describe('filePath()', function () { - it('returns unix fs file full path', function () { - sinon.stub(faker.random, 'words').returns('24/7'); - var filePath = faker.system.filePath(); - assert.strictEqual( - filePath.indexOf('/'), - 0, - 'generated filePath should start with /' - ); - - faker.random.words.restore(); - }); - }); - - describe('fileName()', function () { - it('returns filenames without system path separators', function () { - sinon.stub(faker.random, 'words').returns('24/7'); - var fileName = faker.system.fileName(); - assert.strictEqual( - fileName.indexOf('/'), - -1, - 'generated fileNames should not have path separators' - ); - - faker.random.words.restore(); - }); - }); - - describe('commonFileName()', function () { - it('returns filenames without system path separators', function () { - sinon.stub(faker.random, 'words').returns('24/7'); - var fileName = faker.system.commonFileName(); - assert.strictEqual( - fileName.indexOf('/'), - -1, - 'generated commonFileNames should not have path separators' - ); - - faker.random.words.restore(); - }); - }); -}); diff --git a/test/time.spec.ts b/test/time.spec.ts new file mode 100644 index 00000000..4ef28952 --- /dev/null +++ b/test/time.spec.ts @@ -0,0 +1,23 @@ +import { describe, expect, it } from 'vitest'; +import { faker } from '../lib'; + +faker.seed(1234); + +describe('time', () => { + describe('recent()', () => { + it('returns the recent timestamp in Unix time format', () => { + const date = faker.time.recent(); + expect(typeof date).toBe('number'); + }); + + it('returns the recent timestamp in full time string format', () => { + const date = faker.time.recent('wide'); + expect(typeof date).toBe('string'); + }); + + it('returns the recent timestamp in abbreviated string format', () => { + const date = faker.time.recent('abbr'); + expect(typeof date).toBe('string'); + }); + }); +}); diff --git a/test/time.unit.js b/test/time.unit.js deleted file mode 100644 index 3c4a0650..00000000 --- a/test/time.unit.js +++ /dev/null @@ -1,29 +0,0 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var sinon = require('sinon'); - var faker = require('../lib').faker; -} - -faker.seed(1234); - -describe('time.js', function () { - describe('recent()', function () { - it('returns the recent timestamp in Unix time format', function () { - var date = faker.time.recent(); - assert.ok(typeof date === 'number'); - // assert.ok(date == new Date().getTime()); - }); - - it('returns the recent timestamp in full time string format', function () { - var date = faker.time.recent('wide'); - assert.ok(typeof date === 'string'); - // assert.ok(date == new Date().toTimeString()); - }); - - it('returns the recent timestamp in abbreviated string format', function () { - var date = faker.time.recent('abbr'); - assert.ok(typeof date === 'string'); - // assert.ok(date == new Date().toLocaleTimeString()); - }); - }); -}); diff --git a/test/unique.spec.ts b/test/unique.spec.ts new file mode 100644 index 00000000..26b80bff --- /dev/null +++ b/test/unique.spec.ts @@ -0,0 +1,61 @@ +import { describe, expect, it } from 'vitest'; +import { faker } from '../lib'; + +describe('unique', () => { + describe('unique()', () => { + it('is able to call a function with no arguments and return a result', () => { + const result = + // @ts-expect-error + faker.unique(faker.internet.email); + expect(typeof result).toBe('string'); + }); + + it('is able to call a function with arguments and return a result', () => { + const result = faker.unique(faker.internet.email, ['a', 'b', 'c']); // third argument is provider, or domain for email + expect(result).toMatch(/\@c/); + }); + + it('is able to call same function with arguments and return a result', () => { + const result = faker.unique(faker.internet.email, ['a', 'b', 'c']); // third argument is provider, or domain for email + expect(result).toMatch(/\@c/); + }); + + it('is able to exclude results as array', () => { + const result = faker.unique(faker.internet.protocol, [], { + exclude: ['https'], + }); + expect(result).toBe('http'); + }); + + it('is able to limit unique call by maxTime in ms', () => { + let result; + try { + result = faker.unique(faker.internet.protocol, [], { + maxTime: 1, + maxRetries: 9999, + exclude: ['https', 'http'], + }); + } catch (err) { + expect(err.message.substr(0, 16)).toBe('Exceeded maxTime'); + } + }); + + it('is able to limit unique call by maxRetries', () => { + let result; + try { + result = faker.unique(faker.internet.protocol, [], { + maxTime: 5000, + maxRetries: 5, + exclude: ['https', 'http'], + }); + } catch (err) { + expect(err.message.substr(0, 19)).toBe('Exceeded maxRetries'); + } + }); + + it('is able to call last function with arguments and return a result', () => { + const result = faker.unique(faker.internet.email, ['a', 'b', 'c']); // third argument is provider, or domain for email + expect(result).toMatch(/\@c/); + }); + }); +}); diff --git a/test/unique.unit.js b/test/unique.unit.js deleted file mode 100644 index d500243e..00000000 --- a/test/unique.unit.js +++ /dev/null @@ -1,62 +0,0 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var sinon = require('sinon'); - var faker = require('../lib').faker; -} - -describe('unique.js', function () { - describe('unique()', function () { - it('is able to call a function with no arguments and return a result', function () { - var result = faker.unique(faker.internet.email); - assert.strictEqual(typeof result, 'string'); - }); - - it('is able to call a function with arguments and return a result', function () { - var result = faker.unique(faker.internet.email, ['a', 'b', 'c']); // third argument is provider, or domain for email - assert.ok(result.match(/\@c/)); - }); - - it('is able to call same function with arguments and return a result', function () { - var result = faker.unique(faker.internet.email, ['a', 'b', 'c']); // third argument is provider, or domain for email - assert.ok(result.match(/\@c/)); - }); - - it('is able to exclude results as array', function () { - var result = faker.unique(faker.internet.protocol, [], { - exclude: ['https'], - }); - assert.strictEqual(result, 'http'); - }); - - it('is able to limit unique call by maxTime in ms', function () { - var result; - try { - result = faker.unique(faker.internet.protocol, [], { - maxTime: 1, - maxRetries: 9999, - exclude: ['https', 'http'], - }); - } catch (err) { - assert.strictEqual(err.message.substr(0, 16), 'Exceeded maxTime'); - } - }); - - it('is able to limit unique call by maxRetries', function () { - var result; - try { - result = faker.unique(faker.internet.protocol, [], { - maxTime: 5000, - maxRetries: 5, - exclude: ['https', 'http'], - }); - } catch (err) { - assert.strictEqual(err.message.substr(0, 19), 'Exceeded maxRetries'); - } - }); - - it('is able to call last function with arguments and return a result', function () { - var result = faker.unique(faker.internet.email, ['a', 'b', 'c']); // third argument is provider, or domain for email - assert.ok(result.match(/\@c/)); - }); - }); -}); diff --git a/test/vehicle.spec.ts b/test/vehicle.spec.ts new file mode 100644 index 00000000..57606d92 --- /dev/null +++ b/test/vehicle.spec.ts @@ -0,0 +1,98 @@ +import { expect } from 'vitest'; +import { describe, it, vi } from 'vitest'; +import { faker } from '../lib'; + +describe('vehicle', () => { + describe('vehicle()', () => { + it('returns a random vehicle', () => { + const spy_vehicle_vehicle = vi + .spyOn(faker.vehicle, 'vehicle') + .mockReturnValue('Ford Explorer'); + const vehicle = faker.vehicle.vehicle(); + + expect(vehicle).toBe('Ford Explorer'); + spy_vehicle_vehicle.mockRestore(); + }); + }); + + describe('manufacturer()', () => { + it('returns random manufacturer', () => { + const spy_vehicle_manufacturer = vi + .spyOn(faker.vehicle, 'manufacturer') + .mockReturnValue('Porsche'); + const manufacturer = faker.vehicle.manufacturer(); + + expect(manufacturer).toBe('Porsche'); + spy_vehicle_manufacturer.mockRestore(); + }); + }); + + describe('type()', () => { + it('returns random vehicle type', () => { + const spy_vehicle_type = vi + .spyOn(faker.vehicle, 'type') + .mockReturnValue('Minivan'); + const type = faker.vehicle.type(); + + expect(type).toBe('Minivan'); + spy_vehicle_type.mockRestore(); + }); + }); + + describe('fuel()', () => { + it('returns a fuel type', () => { + const spy_vehicle_fuel = vi + .spyOn(faker.vehicle, 'fuel') + .mockReturnValue('Hybrid'); + const fuel = faker.vehicle.fuel(); + + expect(fuel).toBe('Hybrid'); + spy_vehicle_fuel.mockRestore(); + }); + }); + + describe('vin()', () => { + it('returns valid vin number', () => { + const vin = faker.vehicle.vin(); + expect(vin).match( + /^([A-HJ-NPR-Z0-9]{10}[A-HJ-NPR-Z0-9]{1}[A-HJ-NPR-Z0-9]{1}\d{5})$/ + ); + }); + }); + + describe('color()', () => { + it('returns a random color', () => { + const spy_vehicle_color = vi + .spyOn(faker.vehicle, 'color') + .mockReturnValue('black'); + const color = faker.vehicle.color(); + + expect(color).toBe('black'); + spy_vehicle_color.mockRestore(); + }); + }); + + describe('vrm()', () => { + it('returns a random vrm', () => { + const spy_vehicle_vrm = vi + .spyOn(faker.vehicle, 'vrm') + .mockReturnValue('MF59EEW'); + const vrm = faker.vehicle.vrm(); + + expect(vrm).toBe('MF59EEW'); + spy_vehicle_vrm.mockRestore(); + }); + }); + + describe('bicycle()', () => { + it('returns a random type of bicycle', () => { + const spy_vehicle_bicycle = vi + .spyOn(faker.vehicle, 'bicycle') + .mockReturnValue('Adventure Road Bicycle'); + const bicycle = faker.vehicle.bicycle(); + + expect(bicycle).toBe('Adventure Road Bicycle'); + spy_vehicle_bicycle.mockRestore(); + }); + }); +}); diff --git a/test/vehicle.unit.js b/test/vehicle.unit.js deleted file mode 100644 index 8a065e68..00000000 --- a/test/vehicle.unit.js +++ /dev/null @@ -1,88 +0,0 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var sinon = require('sinon'); - var faker = require('../lib').faker; -} - -describe('vehicle.js', function () { - describe('vehicle()', function () { - it('returns a random vehicle', function () { - sinon.stub(faker.vehicle, 'vehicle').returns('Ford Explorer'); - var vehicle = faker.vehicle.vehicle(); - - assert.strictEqual(vehicle, 'Ford Explorer'); - faker.vehicle.vehicle.restore(); - }); - }); - - describe('manufacturer()', function () { - it('returns random manufacturer', function () { - sinon.stub(faker.vehicle, 'manufacturer').returns('Porsche'); - var manufacturer = faker.vehicle.manufacturer(); - - assert.strictEqual(manufacturer, 'Porsche'); - faker.vehicle.manufacturer.restore(); - }); - }); - - describe('type()', function () { - it('returns random vehicle type', function () { - sinon.stub(faker.vehicle, 'type').returns('Minivan'); - var type = faker.vehicle.type(); - - assert.strictEqual(type, 'Minivan'); - faker.vehicle.type.restore(); - }); - }); - - describe('fuel()', function () { - it('returns a fuel type', function () { - sinon.stub(faker.vehicle, 'fuel').returns('Hybrid'); - var fuel = faker.vehicle.fuel(); - - assert.strictEqual(fuel, 'Hybrid'); - faker.vehicle.fuel.restore(); - }); - }); - - describe('vin()', function () { - it('returns valid vin number', function () { - var vin = faker.vehicle.vin(); - assert.ok( - vin.match( - /^([A-HJ-NPR-Z0-9]{10}[A-HJ-NPR-Z0-9]{1}[A-HJ-NPR-Z0-9]{1}\d{5})$/ - ) - ); - }); - }); - - describe('color()', function () { - it('returns a random color', function () { - sinon.stub(faker.vehicle, 'color').returns('black'); - var color = faker.vehicle.color(); - - assert.strictEqual(color, 'black'); - faker.vehicle.color.restore(); - }); - }); - - describe('vrm()', function () { - it('returns a random vrm', function () { - sinon.stub(faker.vehicle, 'vrm').returns('MF59EEW'); - var vrm = faker.vehicle.vrm(); - - assert.equal(vrm, 'MF59EEW'); - faker.vehicle.vrm.restore(); - }); - }); - - describe('bicycle()', function () { - it('returns a random type of bicycle', function () { - sinon.stub(faker.vehicle, 'bicycle').returns('Adventure Road Bicycle'); - var bicycle = faker.vehicle.bicycle(); - - assert.equal(bicycle, 'Adventure Road Bicycle'); - faker.vehicle.bicycle.restore(); - }); - }); -}); diff --git a/test/word.spec.ts b/test/word.spec.ts new file mode 100644 index 00000000..3790861c --- /dev/null +++ b/test/word.spec.ts @@ -0,0 +1,35 @@ +import { describe, expect, it } from 'vitest'; +import { faker } from '../lib'; + +describe('word', () => { + const methods = [ + 'adjective', + 'adverb', + 'conjunction', + 'interjection', + 'noun', + 'preposition', + 'verb', + ]; + + // Perform the same three tests for each method. + methods.forEach((method) => { + describe(method + '()', () => { + it('returns random value from ' + method + ' array', () => { + const word = faker.word[method](); + expect(faker.definitions.word[method]).toContain(word); + }); + it('optional length parameter returns expected result', () => { + const wordLength = 5; + const word = faker.word[method](wordLength); + expect(faker.definitions.word[method]).toContain(word); + expect(word.length).toBe(wordLength); + }); + it('unresolvable optional length returns random ' + method, () => { + const wordLength = 1000; + const word = faker.word[method](wordLength); + expect(faker.definitions.word[method]).toContain(word); + }); + }); + }); +}); diff --git a/test/word.unit.js b/test/word.unit.js deleted file mode 100644 index 9dc4755c..00000000 --- a/test/word.unit.js +++ /dev/null @@ -1,36 +0,0 @@ -if (typeof module !== 'undefined') { - var assert = require('assert'); - var faker = require('../lib').faker; -} - -describe('word.js', function () { - var methods = [ - 'adjective', - 'adverb', - 'conjunction', - 'interjection', - 'noun', - 'preposition', - 'verb', - ]; - // Perform the same three tests for each method. - methods.forEach(function (method) { - describe(method + '()', function () { - it('returns random value from ' + method + ' array', function () { - var word = faker.word[method](); - assert.ok(faker.definitions.word[method].includes(word)); - }); - it('optional length parameter returns expected result', function () { - var wordLength = 5; - var word = faker.word[method](wordLength); - assert.ok(faker.definitions.word[method].includes(word)); - assert.ok(word.length == wordLength); - }); - it('unresolvable optional length returns random ' + method, function () { - var wordLength = 1000; - var word = faker.word[method](wordLength); - assert.ok(faker.definitions.word[method].includes(word)); - }); - }); - }); -}); |
