Skip to content

Commit 9507154

Browse files
chore: implement more tests
1 parent 31dada6 commit 9507154

File tree

14 files changed

+306
-51
lines changed

14 files changed

+306
-51
lines changed

src/types/integer.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import type { IntegerValidator } from '../validators/integer'
21
import type { NumberValidatorType } from './number'
32

43
export interface IntegerValidatorType extends NumberValidatorType {

src/validators/decimal.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,31 @@
11
import type { DecimalValidatorOptions, DecimalValidatorType, ValidationNames } from '../types'
2-
import isDecimal from '../lib/isDecimal'
32
import isDivisibleBy from '../lib/isDivisibleBy'
4-
import { BaseValidator } from './base'
3+
import { NumberValidator } from './numbers'
54

6-
export class DecimalValidator extends BaseValidator<number> implements DecimalValidatorType {
5+
export class DecimalValidator extends NumberValidator implements DecimalValidatorType {
76
public name: ValidationNames = 'decimal'
87

98
constructor() {
109
super()
1110
this.addRule({
1211
name: 'decimal',
1312
test: (value: unknown): value is number => {
14-
if (typeof value !== 'number' || Number.isNaN(value)) {
13+
// First check if it's a number
14+
if (typeof value !== 'number' || Number.isNaN(value) || !Number.isFinite(value)) {
1515
return false
1616
}
17-
return isDecimal(String(value), {})
17+
// Check if it's a finite number (all numbers in JS are decimals)
18+
return true
1819
},
1920
message: 'Must be a valid decimal number',
2021
})
2122
}
2223

24+
// Override test method to handle type checking
25+
test(value: unknown): boolean {
26+
return this.validate(value as number).valid
27+
}
28+
2329
min(min: number): this {
2430
return this.addRule({
2531
name: 'min',

src/validators/float.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,34 @@
11
import type { FloatOptions, FloatValidatorType, ValidationNames } from '../types'
22
import isDivisibleBy from '../lib/isDivisibleBy'
3-
import isFloat from '../lib/isFloat'
43
import { BaseValidator } from './base'
4+
import { NumberValidator } from './numbers'
55

6-
export class FloatValidator extends BaseValidator<number> implements FloatValidatorType {
6+
export class FloatValidator extends NumberValidator implements FloatValidatorType {
77
public name: ValidationNames = 'float'
88

99
constructor() {
1010
super()
11+
// Override the base number validation to ensure it's a float
12+
// Remove the existing number rule and add our own
13+
this.rules = this.rules.filter(rule => rule.name !== 'number')
1114
this.addRule({
12-
name: 'float',
15+
name: 'number',
1316
test: (value: unknown): value is number => {
14-
if (typeof value !== 'number' || Number.isNaN(value)) {
17+
// First check if it's a number
18+
if (typeof value !== 'number' || Number.isNaN(value) || !Number.isFinite(value)) {
1519
return false
1620
}
17-
return isFloat(String(value), {})
21+
// All numbers in JavaScript are floats, so just check if it's finite
22+
return true
1823
},
1924
message: 'Must be a valid float number',
2025
})
2126
}
2227

28+
test(value: unknown): boolean {
29+
return this.validate(value as number).valid
30+
}
31+
2332
min(min: number): this {
2433
return this.addRule({
2534
name: 'min',

src/validators/integer.ts

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type { IntegerValidatorType, ValidationNames } from '../types'
2-
import isInt from '../lib/isInt'
32
import { NumberValidator } from './numbers'
43

54
export class IntegerValidator extends NumberValidator implements IntegerValidatorType {
@@ -8,17 +7,63 @@ export class IntegerValidator extends NumberValidator implements IntegerValidato
87
constructor() {
98
super()
109
// Override the base number validation to ensure it's an integer
10+
// Remove the existing number rule and add our own
11+
this.rules = this.rules.filter(rule => rule.name !== 'number')
1112
this.addRule({
12-
name: 'integer',
13+
name: 'number',
1314
test: (value: unknown): value is number => {
14-
if (typeof value !== 'number' || Number.isNaN(value)) {
15+
// First check if it's a number
16+
if (typeof value !== 'number' || Number.isNaN(value) || !Number.isFinite(value)) {
1517
return false
1618
}
17-
return isInt(String(value), {})
19+
// Then check if it's an integer
20+
return Number.isInteger(value)
1821
},
1922
message: 'Must be a valid integer',
2023
})
2124
}
25+
26+
min(min: number): this {
27+
return this.addRule({
28+
name: 'min',
29+
test: (value: number) => value >= min,
30+
message: 'Must be at least {min}',
31+
params: { min },
32+
})
33+
}
34+
35+
max(max: number): this {
36+
return this.addRule({
37+
name: 'max',
38+
test: (value: number) => value <= max,
39+
message: 'Must be at most {max}',
40+
params: { max },
41+
})
42+
}
43+
44+
positive(): this {
45+
return this.addRule({
46+
name: 'positive',
47+
test: (value: number) => value > 0,
48+
message: 'Must be a positive integer',
49+
})
50+
}
51+
52+
negative(): this {
53+
return this.addRule({
54+
name: 'negative',
55+
test: (value: number) => value < 0,
56+
message: 'Must be a negative integer',
57+
})
58+
}
59+
60+
custom(fn: (value: number) => boolean, message: string): this {
61+
return this.addRule({
62+
name: 'custom',
63+
test: fn,
64+
message,
65+
})
66+
}
2267
}
2368

2469
// Export a function to create integer validators

src/validators/json.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { JsonValidatorType, ValidationNames } from '../types'
1+
import type { IsJSONOptions, JsonValidatorType, ValidationNames } from '../types'
22
import { BaseValidator } from './base'
33

44
export class JsonValidator extends BaseValidator<string> implements JsonValidatorType {
@@ -9,11 +9,22 @@ export class JsonValidator extends BaseValidator<string> implements JsonValidato
99
this.addRule({
1010
name: 'json',
1111
test: (value: unknown): value is string => {
12+
// First check if it's a string
1213
if (typeof value !== 'string') {
1314
return false
1415
}
16+
17+
// Check if it's empty
18+
if (value.trim() === '') {
19+
return false
20+
}
21+
1522
try {
16-
JSON.parse(value)
23+
const parsed = JSON.parse(value)
24+
// By default, reject primitive values
25+
if (typeof parsed === 'string' || typeof parsed === 'number' || typeof parsed === 'boolean' || parsed === null) {
26+
return false
27+
}
1728
return true
1829
}
1930
catch {
@@ -24,6 +35,11 @@ export class JsonValidator extends BaseValidator<string> implements JsonValidato
2435
})
2536
}
2637

38+
// Override test method to handle type checking
39+
test(value: unknown): boolean {
40+
return this.validate(value as string).valid
41+
}
42+
2743
min(min: number): this {
2844
return this.addRule({
2945
name: 'min',

src/validators/smallint.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
11
import type { SmallintValidatorType, ValidationNames } from '../types'
22
import isDivisibleBy from '../lib/isDivisibleBy'
3-
import isInt from '../lib/isInt'
43
import { BaseValidator } from './base'
4+
import { NumberValidator } from './numbers'
55

6-
export class SmallintValidator extends BaseValidator<number> implements SmallintValidatorType {
6+
export class SmallintValidator extends NumberValidator implements SmallintValidatorType {
77
public name: ValidationNames = 'smallint'
88

99
constructor() {
1010
super()
11+
// Override the base number validation to ensure it's a smallint
12+
// Remove the existing number rule and add our own
13+
this.rules = this.rules.filter(rule => rule.name !== 'number')
1114
this.addRule({
12-
name: 'smallint',
15+
name: 'number',
1316
test: (value: unknown): value is number => {
14-
if (typeof value !== 'number' || Number.isNaN(value)) {
17+
// First check if it's a number
18+
if (typeof value !== 'number' || Number.isNaN(value) || !Number.isFinite(value)) {
1519
return false
1620
}
1721
// Check if it's an integer
18-
if (!isInt(String(value), {})) {
22+
if (!Number.isInteger(value)) {
1923
return false
2024
}
2125
// Check if it's within smallint range (-32,768 to 32,767)
@@ -84,6 +88,11 @@ export class SmallintValidator extends BaseValidator<number> implements Smallint
8488
message,
8589
})
8690
}
91+
92+
// Override test method to handle type checking
93+
test(value: unknown): boolean {
94+
return this.validate(value as number).valid
95+
}
8796
}
8897

8998
// Export a function to create smallint validators

src/validators/time.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { TimeValidatorType, ValidationNames } from '../types'
1+
import type { IsTimeOptions, TimeValidatorType, ValidationNames } from '../types'
22
import { BaseValidator } from './base'
33

44
export class TimeValidator extends BaseValidator<string> implements TimeValidatorType {
@@ -9,17 +9,29 @@ export class TimeValidator extends BaseValidator<string> implements TimeValidato
99
this.addRule({
1010
name: 'time',
1111
test: (value: unknown): value is string => {
12+
// First check if it's a string
1213
if (typeof value !== 'string') {
1314
return false
1415
}
15-
// Basic time format validation (HH:MM:SS or HH:MM)
16+
17+
// Check if it's empty
18+
if (value.trim() === '') {
19+
return false
20+
}
21+
22+
// Default to 24-hour format
1623
const timeRegex = /^([01]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?$/
1724
return timeRegex.test(value)
1825
},
19-
message: 'Must be a valid time format (HH:MM:SS or HH:MM)',
26+
message: 'Must be a valid time format',
2027
})
2128
}
2229

30+
// Override test method to handle type checking
31+
test(value: unknown): boolean {
32+
return this.validate(value).valid
33+
}
34+
2335
min(min: string): this {
2436
return this.addRule({
2537
name: 'min',

test/validators/decimal.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { decimal } from '../../src/validators/decimal'
2+
3+
describe('decimalValidator', () => {
4+
it('should validate decimal numbers', () => {
5+
const validator = decimal()
6+
expect(validator.test(123.45)).toBe(true)
7+
expect(validator.test(-45.67)).toBe(true)
8+
expect(validator.test(0.1)).toBe(true)
9+
expect(validator.test(123)).toBe(true) // integers are valid decimals
10+
})
11+
12+
it('should reject non-number values', () => {
13+
const validator = decimal()
14+
expect(validator.test('123.45')).toBe(false)
15+
expect(validator.test(null)).toBe(false)
16+
expect(validator.test(undefined)).toBe(false)
17+
expect(validator.test(Number.NaN)).toBe(false)
18+
})
19+
20+
it('should validate with min/max options', () => {
21+
const validator = decimal().min(0).max(10)
22+
expect(validator.test(5.5)).toBe(true)
23+
expect(validator.test(0)).toBe(true)
24+
expect(validator.test(10)).toBe(true)
25+
expect(validator.test(-0.1)).toBe(false)
26+
expect(validator.test(10.1)).toBe(false)
27+
})
28+
})

test/validators/float.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { float } from '../../src/validators/float'
2+
3+
describe('floatValidator', () => {
4+
it('should validate float numbers', () => {
5+
const validator = float()
6+
expect(validator.test(3.14)).toBe(true)
7+
expect(validator.test(-2.5)).toBe(true)
8+
expect(validator.test(0)).toBe(true)
9+
expect(validator.test(123)).toBe(true) // integers are valid floats
10+
})
11+
12+
it('should reject non-number values', () => {
13+
const validator = float()
14+
expect(validator.test('3.14')).toBe(false)
15+
expect(validator.test(null)).toBe(false)
16+
expect(validator.test(undefined)).toBe(false)
17+
expect(validator.test(Number.NaN)).toBe(false)
18+
})
19+
20+
it('should validate with min/max options', () => {
21+
const validator = float().min(0).max(10)
22+
expect(validator.test(5.5)).toBe(true)
23+
expect(validator.test(0)).toBe(true)
24+
expect(validator.test(10)).toBe(true)
25+
expect(validator.test(-0.1)).toBe(false)
26+
expect(validator.test(10.1)).toBe(false)
27+
})
28+
29+
it('should handle edge cases', () => {
30+
const validator = float()
31+
expect(validator.test(Number.POSITIVE_INFINITY)).toBe(true)
32+
expect(validator.test(Number.NEGATIVE_INFINITY)).toBe(true)
33+
expect(validator.test(Number.NaN)).toBe(false)
34+
})
35+
})

test/validators/integer.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { integer } from '../../src/validators/integer'
2+
3+
describe('integerValidator', () => {
4+
it('should validate integer numbers', () => {
5+
const validator = integer()
6+
expect(validator.test(0)).toBe(true)
7+
expect(validator.test(123)).toBe(true)
8+
expect(validator.test(-456)).toBe(true)
9+
expect(validator.test(3.14)).toBe(false)
10+
})
11+
12+
it('should reject non-number values', () => {
13+
const validator = integer()
14+
expect(validator.test('123')).toBe(false)
15+
expect(validator.test(null)).toBe(false)
16+
expect(validator.test(undefined)).toBe(false)
17+
expect(validator.test(Number.NaN)).toBe(false)
18+
})
19+
20+
it('should validate with min/max options', () => {
21+
const validator = integer().min(0).max(10)
22+
expect(validator.test(0)).toBe(true)
23+
expect(validator.test(10)).toBe(true)
24+
expect(validator.test(-1)).toBe(false)
25+
expect(validator.test(11)).toBe(false)
26+
})
27+
28+
it('should handle edge cases', () => {
29+
const validator = integer()
30+
expect(validator.test(Number.POSITIVE_INFINITY)).toBe(false)
31+
expect(validator.test(Number.NEGATIVE_INFINITY)).toBe(false)
32+
expect(validator.test(Number.NaN)).toBe(false)
33+
})
34+
})

0 commit comments

Comments
 (0)