Skip to content

Commit

Permalink
add more configuration options
Browse files Browse the repository at this point in the history
  • Loading branch information
veigaribo committed Oct 7, 2020
1 parent 1b6dba5 commit 401b284
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 8 deletions.
5 changes: 5 additions & 0 deletions src/__mocks__/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const config = {
generateRandom: Math.random,
skipValidations: false,
testSampleSize: 15,
}
28 changes: 24 additions & 4 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,37 @@
const testSampleSizeKey = Symbol('Test sample size')
const testSampleSize = Symbol('Test sample size')
const skipValidations = Symbol('Skip validations')
const generateRandom = Symbol('Generate random')

export const config = {
[testSampleSizeKey]: 15,
[generateRandom]: Math.random,
[skipValidations]: false,
[testSampleSize]: 15,

get generateRandom() {
return this[generateRandom]
},

set generateRandom(value: () => number) {
this[generateRandom] = value
},

get skipValidations() {
return this[skipValidations]
},

set skipValidations(value: boolean) {
this[skipValidations] = !!value
},

get testSampleSize() {
return this[testSampleSizeKey]
return this[testSampleSize]
},

set testSampleSize(value: number) {
if (value < 0) {
throw new Error(`Test sample size cannot be negative (got ${value}).`)
}

this[testSampleSizeKey] = Math.trunc(value)
this[testSampleSize] = Math.trunc(value)
},
}
16 changes: 12 additions & 4 deletions src/validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,28 @@ type InstanceValidator = Validator<InstanceConstructor>
const specialCases = [0, 1]

const getRandomSampleSize = (): number => {
if (config.testSampleSize < specialCases.length) {
const { testSampleSize } = config

if (testSampleSize < specialCases.length) {
throw new Error(
`Test sample size cannot be ${config.testSampleSize}, there are ${specialCases.length} special cases that must be tested. that is the minimum acceptable value.`,
`Test sample size cannot be ${testSampleSize}, there are ${specialCases.length} special cases that must be tested. that is the minimum acceptable value.`,
)
}

return config.testSampleSize - specialCases.length
return testSampleSize - specialCases.length
}

// An Obey of T validates using instances of T
export class Obeys<T extends InstanceConstructor> implements InstanceValidator {
constructor(public readonly param: Predicate<InstanceType<T>>) {}

check(instance: T): ValidationResult {
const { skipValidations, generateRandom } = config

if (skipValidations) {
return new Right(true)
}

const predicate = this.param

const paramsForInstance = instance.generateData.length
Expand Down Expand Up @@ -60,7 +68,7 @@ export class Obeys<T extends InstanceConstructor> implements InstanceValidator {
const params = arrayWithLength(paramsForPredicate).map(() => {
return instance.generateData(
// impure
...arrayWithLength(paramsForInstance).map(Math.random),
...arrayWithLength(paramsForInstance).map(generateRandom),
)
})

Expand Down
12 changes: 12 additions & 0 deletions test/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,15 @@ test('Will truncate valid testSampleSizes', () => {

expect(config.testSampleSize).toBe(Math.trunc(value))
})

test('Will cast skipValidations to boolean', () => {
// @ts-ignore
config.skipValidations = {}

expect(config.skipValidations).toBe(true)

// @ts-ignore
config.skipValidations = ''

expect(config.skipValidations).toBe(false)
})
50 changes: 50 additions & 0 deletions test/validators.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
jest.mock('../src/config')

import { config } from '../src/config'
import { Instance } from '../src/instances'
import { Left, Right } from '../src/utils'
Expand Down Expand Up @@ -25,6 +27,16 @@ class SumInstance extends EqInstance {
}
}

const defaultGenerateRandom = config.generateRandom
const defaultSkipValidations = config.skipValidations
const defaultTestSampleSize = config.testSampleSize

beforeEach(() => {
config.generateRandom = defaultGenerateRandom
config.skipValidations = defaultSkipValidations
config.testSampleSize = defaultTestSampleSize
})

test('Obey returns true if the predicate holds', () => {
const validator = obey((a: SumInstance, b: SumInstance) => {
return a.sum(b).equals(b.sum(a))
Expand Down Expand Up @@ -96,6 +108,44 @@ test('Will run as many tests as it is set in the config', () => {
expect(predicate).toBeCalledTimes(qty2)
})

test('Will not run any validation if the config says to do so', () => {
config.skipValidations = true

const predicate = jest.fn((a: SumInstance, b: SumInstance) => {
return a.sum(b).equals(b.sum(a))
})

const validator = obey(predicate)

expect(validator.check(SumInstance)).toBeInstanceOf(Right)
expect(predicate).not.toBeCalled()
})

test('Will use the given generateRandom callable', () => {
const random = -(2 ** 0.5)
config.generateRandom = () => random

const randomInstance = new SumInstance(random)
// special cases
const zero = new SumInstance(0)
const one = new SumInstance(1)

let anythingOtherThanExpected = false

const validator = obey((a: SumInstance, b: SumInstance) => {
if (
![a, b].every((x) => [zero, one, randomInstance].some(x.equals.bind(x)))
) {
anythingOtherThanExpected = true
}

return a.sum(b).equals(b.sum(a))
})

expect(validator.check(SumInstance)).toBeInstanceOf(Right)
expect(anythingOtherThanExpected).toBe(false)
})

const implement = (key: string) => {
return obey((a) => key in a)
}
Expand Down

0 comments on commit 401b284

Please sign in to comment.