nigerian-mobile-validator
Version:
The most rigorous, up-to-date library for validating Nigerian mobile numbers. Fully NCC-compliant, and security-focused, with enterprise-grade features to prevent the business risks of validation failures in regulated industries.
398 lines (397 loc) • 22.3 kB
JavaScript
"use strict";
// src/__tests__/synthetic-data/test-data-generator-property-based.ts
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TestDataGeneratorPropertyBased = void 0;
const test_data_generator_base_1 = require("./test-data-generator-base");
const test_data_generator_valid_numbers_1 = require("./test-data-generator-valid-numbers");
const test_data_generator_random_numbers_1 = require("./test-data-generator-random-numbers");
const mobile_validation_status_1 = require("../../number-validation/mobile-validation-status");
const telco_1 = require("../../numbering-plan/telco");
const network_access_code_1 = require("../../numbering-plan/network-access-code");
const chance_1 = __importDefault(require("chance"));
const test_data_generator_invalid_numbers_1 = require("./test-data-generator-invalid-numbers");
// Initialize Chance with a seed for reproducibility if needed
const chance = new chance_1.default();
/**
* Generator for property-based testing data
*/
class TestDataGeneratorPropertyBased extends test_data_generator_base_1.TestDataGeneratorBase {
/**
* Generate a property-based test for a specific validation aspect
* @param aspect The validation aspect to test
* @param count Number of test cases to generate
*/
// eslint-disable-next-line sonarjs/cognitive-complexity
static generatePropertyBasedTest(aspect, count = 10) {
const testCases = [];
switch (aspect) {
case 'format':
// Generate numbers with different formats (local, international, with plus)
for (let i = 0; i < count; i++) {
const format = chance.pickone(['local', 'international', 'international-plus']);
const networkCode = this.randomNetworkCode();
let number;
if (format === 'local') {
number = `0${networkCode}${this.randomSubscriberNumber(networkCode)}`;
}
else if (format === 'international') {
number = `234${networkCode}${this.randomSubscriberNumber(networkCode)}`;
}
else {
number = `+234${networkCode}${this.randomSubscriberNumber(networkCode)}`;
}
testCases.push({
number,
description: `Valid number in ${format} format`,
expectedValid: true,
expectedStatus: mobile_validation_status_1.MobileValidationStatus.Success,
tags: ['valid', format]
});
}
break;
case 'length':
// Generate numbers with different lengths
for (let i = 0; i < count; i++) {
const networkCode = this.randomNetworkCode();
const correctLength = chance.bool();
let number;
if (correctLength) {
number = `0${networkCode}${this.randomSubscriberNumber(networkCode)}`;
testCases.push({
number,
description: 'Valid number with correct length',
expectedValid: true,
expectedStatus: mobile_validation_status_1.MobileValidationStatus.Success,
tags: ['valid', 'length']
});
}
else {
const tooLong = chance.bool();
number = test_data_generator_invalid_numbers_1.TestDataGeneratorInvalidNumbers.generateInvalidLengthNumber(networkCode, tooLong);
testCases.push({
number,
description: `Invalid number - ${tooLong ? 'too many' : 'too few'} digits`,
expectedValid: false,
expectedStatus: mobile_validation_status_1.MobileValidationStatus.IncorrectNumberOfDigits,
tags: ['invalid', 'length']
});
}
}
break;
case 'chars':
// Generate numbers with/without non-numeric characters
for (let i = 0; i < count; i++) {
const networkCode = this.randomNetworkCode();
const hasNonNumeric = chance.bool();
if (hasNonNumeric) {
const number = test_data_generator_invalid_numbers_1.TestDataGeneratorInvalidNumbers.generateNonNumericNumber(networkCode);
testCases.push({
number,
description: 'Invalid number - contains non-numeric characters',
expectedValid: false,
expectedStatus: mobile_validation_status_1.MobileValidationStatus.ContainsNonNumericChars,
tags: ['invalid', 'chars']
});
}
else {
const number = `0${networkCode}${this.randomSubscriberNumber(networkCode)}`;
testCases.push({
number,
description: 'Valid number - only contains digits',
expectedValid: true,
expectedStatus: mobile_validation_status_1.MobileValidationStatus.Success,
tags: ['valid', 'chars']
});
}
}
break;
case 'network':
// Generate numbers with valid/invalid network codes
for (let i = 0; i < count; i++) {
const validNetwork = chance.bool();
if (validNetwork) {
const networkCode = this.randomNetworkCode();
const number = `0${networkCode}${this.randomSubscriberNumber(networkCode)}`;
testCases.push({
number,
description: 'Valid number - correct network code',
expectedValid: true,
expectedStatus: mobile_validation_status_1.MobileValidationStatus.Success,
tags: ['valid', 'network']
});
}
else {
const number = test_data_generator_invalid_numbers_1.TestDataGeneratorInvalidNumbers.generateInvalidNetworkCodeNumber();
testCases.push({
number,
description: 'Invalid number - incorrect network code',
expectedValid: false,
expectedStatus: mobile_validation_status_1.MobileValidationStatus.IncorrectNetworkCode,
tags: ['invalid', 'network']
});
}
}
break;
case 'telco':
// Generate numbers for different telcos
for (const telco of this.allValidTelcos) {
const number = test_data_generator_valid_numbers_1.TestDataGeneratorValidNumbers.generateValidNumberForTelco(telco);
testCases.push({
number,
description: `Valid ${telco} number`,
expectedValid: true,
expectedTelco: telco,
expectedStatus: mobile_validation_status_1.MobileValidationStatus.Success,
tags: ['valid', 'telco', telco.toLowerCase()]
});
}
// Add special 702 cases
testCases.push({
number: test_data_generator_valid_numbers_1.TestDataGeneratorValidNumbers.generateValidNumberForTelco(telco_1.Telco.Smile),
description: 'Valid Smile number (702 range)',
expectedValid: true,
expectedTelco: telco_1.Telco.Smile,
expectedNetworkCode: network_access_code_1.NetworkAccessCode.n702,
expectedStatus: mobile_validation_status_1.MobileValidationStatus.Success,
tags: ['valid', 'telco', 'smile', '702']
});
testCases.push({
number: test_data_generator_valid_numbers_1.TestDataGeneratorValidNumbers.generateValidNumberForTelco(telco_1.Telco.Openskys),
description: 'Valid Openskys number (702 range)',
expectedValid: true,
expectedTelco: telco_1.Telco.Openskys,
expectedNetworkCode: network_access_code_1.NetworkAccessCode.n702,
expectedStatus: mobile_validation_status_1.MobileValidationStatus.Success,
tags: ['valid', 'telco', 'openskys', '702']
});
break;
case 'special':
// Special case numbers like shared VAS, reserved, withdrawn
testCases.push({
number: '07001234567',
description: 'Shared VAS network code',
expectedValid: false,
expectedStatus: mobile_validation_status_1.MobileValidationStatus.SharedVASNetworkCode,
tags: ['invalid', 'special', 'vas']
});
testCases.push({
number: '07091234567',
description: 'Withdrawn network code',
expectedValid: false,
expectedStatus: mobile_validation_status_1.MobileValidationStatus.WithdrawnNetworkCode,
tags: ['invalid', 'special', 'withdrawn']
});
testCases.push({
number: '09001234567',
description: 'Reserved network code',
expectedValid: false,
expectedStatus: mobile_validation_status_1.MobileValidationStatus.ReservedNetworkCode,
tags: ['invalid', 'special', 'reserved']
});
testCases.push({
number: test_data_generator_invalid_numbers_1.TestDataGeneratorInvalidNumbers.generateReturned702Number(),
description: 'Returned number in 702 range',
expectedValid: false,
expectedStatus: mobile_validation_status_1.MobileValidationStatus.ReturnedNetworkCode,
tags: ['invalid', 'special', 'returned', '702']
});
testCases.push({
number: test_data_generator_invalid_numbers_1.TestDataGeneratorInvalidNumbers.generateWithdrawn702Number(),
description: 'Withdrawn number in 702 range',
expectedValid: false,
expectedStatus: mobile_validation_status_1.MobileValidationStatus.WithdrawnNetworkCode,
tags: ['invalid', 'special', 'withdrawn', '702']
});
break;
}
return testCases;
}
/**
* Generate random numbers for property-based testing
* Each number has a certain probability of being valid or having different types of issues
*
* @param count Number of test cases to generate
* @returns Array of test cases with expected properties
*/
static generatePropertyBasedTestCases(count = 100) {
const testCases = [];
for (let i = 0; i < count; i++) {
const testType = chance.pickone([
'valid-local',
'valid-international',
'valid-international-plus',
'valid-with-spaces',
'valid-with-o',
'invalid-format',
'invalid-length',
'invalid-chars',
'invalid-network',
'special-case'
]);
let number;
let expectedValid;
let expectedTelco;
let expectedNetworkCode;
let expectedStatus;
let description;
let tags = [];
switch (testType) {
case 'valid-local':
const telco = chance.pickone(this.allValidTelcos);
number = test_data_generator_valid_numbers_1.TestDataGeneratorValidNumbers.generateValidNumberForTelco(telco);
expectedValid = true;
expectedTelco = telco;
// Handle special case for 702 range
if (number.startsWith('0702')) {
expectedNetworkCode = network_access_code_1.NetworkAccessCode.n702;
}
else {
const networkCode = parseInt(number.substring(1, 4));
expectedNetworkCode = networkCode;
}
expectedStatus = mobile_validation_status_1.MobileValidationStatus.Success;
description = `Valid ${telco} number in local format`;
tags = ['valid', 'local', telco.toLowerCase()];
break;
case 'valid-international':
const intTelco = chance.pickone(this.allValidTelcos);
const intNetworkCode = this.randomNetworkCodeForTelco(intTelco);
number = test_data_generator_valid_numbers_1.TestDataGeneratorValidNumbers.generateInternationalNumber(intNetworkCode);
expectedValid = true;
expectedTelco = intTelco;
expectedNetworkCode = intNetworkCode;
expectedStatus = mobile_validation_status_1.MobileValidationStatus.Success;
description = `Valid ${intTelco} number in international format`;
tags = ['valid', 'international', intTelco.toLowerCase()];
break;
case 'valid-international-plus':
const intPlusTelco = chance.pickone(this.allValidTelcos);
const intPlusNetworkCode = this.randomNetworkCodeForTelco(intPlusTelco);
number = test_data_generator_valid_numbers_1.TestDataGeneratorValidNumbers.generateInternationalPlusNumber(intPlusNetworkCode);
expectedValid = true;
expectedTelco = intPlusTelco;
expectedNetworkCode = intPlusNetworkCode;
expectedStatus = mobile_validation_status_1.MobileValidationStatus.Success;
description = `Valid ${intPlusTelco} number in international format with plus`;
tags = ['valid', 'international-plus', intPlusTelco.toLowerCase()];
break;
case 'valid-with-spaces':
const spacesTelco = chance.pickone(this.allValidTelcos);
const spacesNetworkCode = this.randomNetworkCodeForTelco(spacesTelco);
number = test_data_generator_valid_numbers_1.TestDataGeneratorValidNumbers.generateNumberWithSpaces(spacesNetworkCode);
expectedValid = true;
expectedTelco = spacesTelco;
expectedNetworkCode = spacesNetworkCode;
expectedStatus = mobile_validation_status_1.MobileValidationStatus.Success;
description = `Valid ${spacesTelco} number with spaces`;
tags = ['valid', 'spaces', spacesTelco.toLowerCase()];
break;
case 'valid-with-o':
const oTelco = chance.pickone(this.allValidTelcos);
const oNetworkCode = this.randomNetworkCodeForTelco(oTelco);
number = test_data_generator_valid_numbers_1.TestDataGeneratorValidNumbers.generateNumberWithO(oNetworkCode);
expectedValid = true;
expectedTelco = oTelco;
expectedNetworkCode = oNetworkCode;
expectedStatus = mobile_validation_status_1.MobileValidationStatus.Success;
description = `Valid ${oTelco} number with 'o' instead of '0'`;
tags = ['valid', 'o-instead-of-0', oTelco.toLowerCase()];
break;
case 'invalid-format':
const netCode = this.randomNetworkCode();
number = netCode + this.randomSubscriberNumber(netCode); // Missing leading 0
expectedValid = false;
expectedStatus = mobile_validation_status_1.MobileValidationStatus.NotNigerianNumber;
description = 'Invalid number - incorrect format';
tags = ['invalid', 'format'];
break;
case 'invalid-length':
const lengthNetworkCode = this.randomNetworkCode();
const tooLong = chance.bool();
number = test_data_generator_invalid_numbers_1.TestDataGeneratorInvalidNumbers.generateInvalidLengthNumber(lengthNetworkCode, tooLong);
expectedValid = false;
expectedStatus = mobile_validation_status_1.MobileValidationStatus.IncorrectNumberOfDigits;
description = `Invalid number - ${tooLong ? 'too many' : 'too few'} digits`;
tags = ['invalid', 'length'];
break;
case 'invalid-chars':
const charsNetworkCode = this.randomNetworkCode();
number = test_data_generator_invalid_numbers_1.TestDataGeneratorInvalidNumbers.generateNonNumericNumber(charsNetworkCode);
expectedValid = false;
expectedStatus = mobile_validation_status_1.MobileValidationStatus.ContainsNonNumericChars;
description = 'Invalid number - contains non-numeric characters';
tags = ['invalid', 'chars'];
break;
case 'invalid-network':
number = test_data_generator_invalid_numbers_1.TestDataGeneratorInvalidNumbers.generateInvalidNetworkCodeNumber();
expectedValid = false;
expectedStatus = mobile_validation_status_1.MobileValidationStatus.IncorrectNetworkCode;
description = 'Invalid number - incorrect network code';
tags = ['invalid', 'network'];
break;
case 'special-case':
const specialCase = chance.pickone([
'shared-vas',
'withdrawn',
'reserved',
'returned-702',
'withdrawn-702'
]);
switch (specialCase) {
case 'shared-vas':
number = '07001234567';
expectedStatus = mobile_validation_status_1.MobileValidationStatus.SharedVASNetworkCode;
description = 'Invalid number - Shared VAS network code';
break;
case 'withdrawn':
number = '07091234567';
expectedStatus = mobile_validation_status_1.MobileValidationStatus.WithdrawnNetworkCode;
description = 'Invalid number - Withdrawn network code';
break;
case 'reserved':
number = '09001234567';
expectedStatus = mobile_validation_status_1.MobileValidationStatus.ReservedNetworkCode;
description = 'Invalid number - Reserved network code';
break;
case 'returned-702':
number = test_data_generator_invalid_numbers_1.TestDataGeneratorInvalidNumbers.generateReturned702Number();
expectedStatus = mobile_validation_status_1.MobileValidationStatus.WithdrawnNetworkCode;
description = 'Invalid number - Returned 702 range';
break;
case 'withdrawn-702':
number = test_data_generator_invalid_numbers_1.TestDataGeneratorInvalidNumbers.generateWithdrawn702Number();
expectedStatus = mobile_validation_status_1.MobileValidationStatus.WithdrawnNetworkCode;
description = 'Invalid number - Withdrawn 702 range';
break;
default:
number = '09001234567';
expectedStatus = mobile_validation_status_1.MobileValidationStatus.ReservedNetworkCode;
description = 'Invalid number - fallback to Reserved network code';
}
expectedValid = false;
tags = ['invalid', 'special', specialCase];
break;
default:
// Generate a fully random number as fallback
number = test_data_generator_random_numbers_1.TestDataGeneratorRandomNumbers.generateRandomPhoneNumber();
expectedValid = false;
description = `Random test case ${i}`;
tags = ['random'];
}
testCases.push({
number,
description,
expectedValid,
expectedTelco,
expectedNetworkCode,
expectedStatus,
tags
});
}
return testCases;
}
}
exports.TestDataGeneratorPropertyBased = TestDataGeneratorPropertyBased;