Skip to content

Commit

Permalink
feat: add weekday and weekend rules
Browse files Browse the repository at this point in the history
  • Loading branch information
thetutlage committed Nov 21, 2023
1 parent c893f10 commit 223bb93
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ export const messages = {
'date.afterOrSameAs': 'The {{ field }} field must be a date after or same as {{ otherField }}',
'date.beforeField': 'The {{ field }} field must be a date before {{ otherField }}',
'date.beforeOrSameAs': 'The {{ field }} field must be a date before or same as {{ otherField }}',

'date.weekend': 'The {{ field }} field is not a weekend',
'date.weekday': 'The {{ field }} field is not a weekday',
}

/**
Expand Down
18 changes: 18 additions & 0 deletions src/schema/date/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {
beforeRule,
sameAsRule,
equalsRule,
weekendRule,
weekdayRule,
notSameAsRule,
afterFieldRule,
beforeFieldRule,
Expand Down Expand Up @@ -53,6 +55,8 @@ export class VineDate extends BaseLiteralType<Date, Date> {
afterOrSameAs: afterOrSameAsRule,
beforeField: beforeFieldRule,
beforeOrSameAs: beforeOrSameAsRule,
weekend: weekendRule,
weekday: weekdayRule,
};

/**
Expand Down Expand Up @@ -220,6 +224,20 @@ export class VineDate extends BaseLiteralType<Date, Date> {
return this.use(beforeOrSameAsRule({ otherField, ...options }))
}

/**
* The weekend rule ensures the date falls on a weekend
*/
weekend(): this {
return this.use(weekendRule())
}

/**
* The weekday rule ensures the date falls on a weekday
*/
weekday(): this {
return this.use(weekdayRule())
}

/**
* Clones the VineDate schema type. The applied options
* and validations are copied to the new instance
Expand Down
32 changes: 32 additions & 0 deletions src/schema/date/rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -547,3 +547,35 @@ export const beforeOrSameAsRule = createRule<
})
}
})

/**
* The weekend rule ensures the date falls on a weekend
*/
export const weekendRule = createRule((_, __, field) => {
if (!field.meta.$value) {
return
}

const dateTime = field.meta.$value as Dayjs
const day = dateTime.day()

if (day !== 0 && day !== 6) {
field.report(messages['date.weekend'], 'date.weekend', field)
}
})

/**
* The weekday rule ensures the date falls on a weekday
*/
export const weekdayRule = createRule((_, __, field) => {
if (!field.meta.$value) {
return
}

const dateTime = field.meta.$value as Dayjs
const day = dateTime.day()

if (day === 0 || day === 6) {
field.report(messages['date.weekday'], 'date.weekday', field)
}
})
93 changes: 93 additions & 0 deletions tests/unit/rules/date.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {
beforeRule,
sameAsRule,
equalsRule,
weekendRule,
weekdayRule,
notSameAsRule,
afterFieldRule,
beforeFieldRule,
Expand Down Expand Up @@ -1448,3 +1450,94 @@ test.group('Date | beforeOrSameAs', () => {
validated.assertSucceeded()
})
})

test.group('Date | weekend', () => {
test('skip validation when value is not a valid date', () => {
const date = dateRule({})
const weekend = weekendRule()
const validated = validator.execute([date, weekend], 'foo')

validated.assertErrorsCount(1)
validated.assertError('The dummy field must be a datetime value')
})

test('skip validation when value is not a valid date with bail mode disabled', () => {
const date = dateRule({})
const weekend = weekendRule()
const validated = validator.bail(false).execute([date, weekend], 'foo')

validated.assertErrorsCount(1)
validated.assertError('The dummy field must be a datetime value')
})

test('report error when date is not a weekend', () => {
const date = dateRule({ formats: ['YYYY-MM-DD'] })
const weekend = weekendRule()
const validated = validator.execute([date, weekend], '2023-11-21')

validated.assertErrorsCount(1)
validated.assertError('The dummy field is not a weekend')
})

test('pass when date falls on Saturday', () => {
const date = dateRule({ formats: ['YYYY-MM-DD'] })
const weekend = weekendRule()
const validated = validator.execute([date, weekend], '2023-11-18')

validated.assertSucceeded()
})

test('pass when date falls on Sunday', () => {
const date = dateRule({ formats: ['YYYY-MM-DD'] })
const weekend = weekendRule()
const validated = validator.execute([date, weekend], '2023-11-19')

validated.assertSucceeded()
})
})

test.group('Date | weekday', () => {
test('skip validation when value is not a valid date', () => {
const date = dateRule({})
const weekday = weekdayRule()
const validated = validator.execute([date, weekday], 'foo')

validated.assertErrorsCount(1)
validated.assertError('The dummy field must be a datetime value')
})

test('skip validation when value is not a valid date with bail mode disabled', () => {
const date = dateRule({})
const weekday = weekdayRule()
const validated = validator.bail(false).execute([date, weekday], 'foo')

validated.assertErrorsCount(1)
validated.assertError('The dummy field must be a datetime value')
})

test('report error when date falls on Saturday', () => {
const date = dateRule({ formats: ['YYYY-MM-DD'] })
const weekday = weekdayRule()
const validated = validator.execute([date, weekday], '2023-11-18')

validated.assertErrorsCount(1)
validated.assertError('The dummy field is not a weekday')
})

test('report error when date falls on Sunday', () => {
const date = dateRule({ formats: ['YYYY-MM-DD'] })
const weekday = weekdayRule()
const validated = validator.execute([date, weekday], '2023-11-19')

validated.assertErrorsCount(1)
validated.assertError('The dummy field is not a weekday')
})

test('pass when date falls on a Weekday', () => {
const date = dateRule({ formats: ['YYYY-MM-DD'] })
const weekday = weekdayRule()
const validated = validator.execute([date, weekday], '2023-11-21')

validated.assertSucceeded()
})
})
68 changes: 68 additions & 0 deletions tests/unit/schema/date.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import {
beforeRule,
sameAsRule,
equalsRule,
weekendRule,
weekdayRule,
notSameAsRule,
afterFieldRule,
beforeFieldRule,
Expand Down Expand Up @@ -839,4 +841,70 @@ test.group('VineDate | applying rules', () => {
options: beforeOrSameAs.options,
})
})

test('apply weekend rule', ({ assert }) => {
const refs = refsBuilder()
const schema = vine.date().weekend()

assert.deepEqual(schema[PARSE]('*', refs, { toCamelCase: false }), {
type: 'literal',
fieldName: '*',
propertyName: '*',
bail: true,
allowNull: false,
isOptional: false,
parseFnId: undefined,
validations: [
{
implicit: false,
isAsync: false,
ruleFnId: 'ref://1',
},
{
implicit: false,
isAsync: false,
ruleFnId: 'ref://2',
},
],
})

const weekend = weekendRule()
assert.deepEqual(refs.toJSON()['ref://2'], {
validator: weekend.rule.validator,
options: weekend.options,
})
})

test('apply weekday rule', ({ assert }) => {
const refs = refsBuilder()
const schema = vine.date().weekday()

assert.deepEqual(schema[PARSE]('*', refs, { toCamelCase: false }), {
type: 'literal',
fieldName: '*',
propertyName: '*',
bail: true,
allowNull: false,
isOptional: false,
parseFnId: undefined,
validations: [
{
implicit: false,
isAsync: false,
ruleFnId: 'ref://1',
},
{
implicit: false,
isAsync: false,
ruleFnId: 'ref://2',
},
],
})

const weekday = weekdayRule()
assert.deepEqual(refs.toJSON()['ref://2'], {
validator: weekday.rule.validator,
options: weekday.options,
})
})
})

0 comments on commit 223bb93

Please sign in to comment.