From c13678283fb757e2ec79671ad9154357458d026c Mon Sep 17 00:00:00 2001 From: Harminder Virk Date: Wed, 4 Dec 2024 17:45:47 +0530 Subject: [PATCH] test: fix failing tests --- providers/database_provider.ts | 4 +- src/bindings/vinejs.ts | 181 +++++++++++++++++---------------- src/types/vine.ts | 4 +- test/bindings/vinejs.spec.ts | 51 +++++++--- 4 files changed, 136 insertions(+), 104 deletions(-) diff --git a/providers/database_provider.ts b/providers/database_provider.ts index 76a8113e..cf003399 100644 --- a/providers/database_provider.ts +++ b/providers/database_provider.ts @@ -44,7 +44,7 @@ declare module '@vinejs/vine' { * Ensure the value is unique inside the database by table and column name. * Optionally, you can define a filter to narrow down the query. */ - unique(options: VineDbSearchOptions): this + unique(options: VineDbSearchOptions): this /** * Ensure the value is unique inside the database by self @@ -59,7 +59,7 @@ declare module '@vinejs/vine' { * Ensure the value exists inside the database by table and column name. * Optionally, you can define a filter to narrow down the query. */ - exists(options: VineDbSearchOptions): this + exists(options: VineDbSearchOptions): this /** * Ensure the value exists inside the database by self diff --git a/src/bindings/vinejs.ts b/src/bindings/vinejs.ts index 45c0c6dc..ebdc90fa 100644 --- a/src/bindings/vinejs.ts +++ b/src/bindings/vinejs.ts @@ -25,113 +25,122 @@ export const messages = { * VineJS. */ export function defineValidationRules(db: Database) { - const uniqueRule = vine.createRule( - async (value, callbackOrOptions, field) => { - if (!field.isValid) { - return - } + function uniqueRule() { + return vine.createRule | VineDbSearchOptions>( + async (value, callbackOrOptions, field) => { + if (!field.isValid) { + return + } - /** - * Rely on the callback to execute the query and return value - * a boolean. - * - * True means value is unique - * False means value is not unique - */ - if (typeof callbackOrOptions === 'function') { - const isUnique = await callbackOrOptions(db, value as string, field) - if (!isUnique) { - field.report(messages['database.unique'], 'database.unique', field) + /** + * Rely on the callback to execute the query and return value + * a boolean. + * + * True means value is unique + * False means value is not unique + */ + if (typeof callbackOrOptions === 'function') { + const isUnique = await callbackOrOptions(db, value as ValueType, field) + if (!isUnique) { + field.report(messages['database.unique'], 'database.unique', field) + } + return } - return - } - const { table, column, filter, connection, caseInsensitive } = callbackOrOptions - const query = db.connection(connection).from(table).select(column) + const { table, column, filter, connection, caseInsensitive } = callbackOrOptions + const query = db.connection(connection).from(table).select(column) - /** - * Apply where clause respecting the caseInsensitive flag. - */ - if (caseInsensitive) { - query.whereRaw(`lower(${column}) = ?`, [db.raw(`lower(?)`, [value])]) - } else { - query.where(column, value as string) - } + /** + * Apply where clause respecting the caseInsensitive flag. + */ + if (caseInsensitive) { + query.whereRaw(`lower(${column}) = ?`, [db.raw(`lower(?)`, [value])]) + } else { + query.where(column, value as string | number) + } - /** - * Apply user filter - */ - await filter?.(query, value as string, field) - - /** - * Fetch the first row from the database - */ - const row = await query.first() - if (row) { - field.report(messages['database.unique'], 'database.unique', field) - } - } - ) + /** + * Apply user filter + */ + await filter?.(query, value as ValueType, field) - const existsRule = vine.createRule( - async (value, callbackOrOptions, field) => { - if (!field.isValid) { - return + /** + * Fetch the first row from the database + */ + const row = await query.first() + if (row) { + field.report(messages['database.unique'], 'database.unique', field) + } } + ) + } + + function existsRule() { + return vine.createRule | VineDbSearchOptions>( + async (value, callbackOrOptions, field) => { + if (!field.isValid) { + return + } - /** - * Rely on the callback to execute the query and return value - * a boolean. - * - * True means value exists - * False means value does not exist - */ - if (typeof callbackOrOptions === 'function') { - const exists = await callbackOrOptions(db, value as string, field) - if (!exists) { - field.report(messages['database.exists'], 'database.exists', field) + /** + * Rely on the callback to execute the query and return value + * a boolean. + * + * True means value exists + * False means value does not exist + */ + if (typeof callbackOrOptions === 'function') { + const exists = await callbackOrOptions(db, value as ValueType, field) + if (!exists) { + field.report(messages['database.exists'], 'database.exists', field) + } + return } - return - } - const { table, column, filter, connection, caseInsensitive } = callbackOrOptions - const query = db.connection(connection).from(table).select(column) + const { table, column, filter, connection, caseInsensitive } = callbackOrOptions + const query = db.connection(connection).from(table).select(column) - /** - * Apply where clause respecting the caseInsensitive flag. - */ - if (caseInsensitive) { - query.whereRaw(`lower(${column}) = ?`, [db.raw(`lower(?)`, [value])]) - } else { - query.where(column, value as string) - } + /** + * Apply where clause respecting the caseInsensitive flag. + */ + if (caseInsensitive) { + query.whereRaw(`lower(${column}) = ?`, [db.raw(`lower(?)`, [value])]) + } else { + query.where(column, value as string | number) + } - /** - * Apply user filter - */ - await filter?.(query, value as string, field) - - /** - * Fetch the first row from the database - */ - const row = await query.first() - if (!row) { - field.report(messages['database.exists'], 'database.exists', field) + /** + * Apply user filter + */ + await filter?.(query, value as ValueType, field) + + /** + * Fetch the first row from the database + */ + const row = await query.first() + if (!row) { + field.report(messages['database.exists'], 'database.exists', field) + } } - } - ) + ) + } + + const uniqueRuleForString = uniqueRule() + const uniqueRuleForNumber = uniqueRule() + const existsRuleForString = existsRule() + const existsRuleForNumber = existsRule() VineString.macro('unique', function (this: VineString, callbackOrOptions) { - return this.use(uniqueRule(callbackOrOptions)) + return this.use(uniqueRuleForString(callbackOrOptions)) }) VineString.macro('exists', function (this: VineString, callbackOrOptions) { - return this.use(existsRule(callbackOrOptions)) + return this.use(existsRuleForString(callbackOrOptions)) }) VineNumber.macro('unique', function (this: VineNumber, callbackOrOptions) { - return this.use(uniqueRule(callbackOrOptions)) + return this.use(uniqueRuleForNumber(callbackOrOptions)) }) VineNumber.macro('exists', function (this: VineNumber, callbackOrOptions) { - return this.use(existsRule(callbackOrOptions)) + return this.use(existsRuleForNumber(callbackOrOptions)) }) } diff --git a/src/types/vine.ts b/src/types/vine.ts index 3edf6644..a51b54d7 100644 --- a/src/types/vine.ts +++ b/src/types/vine.ts @@ -14,7 +14,7 @@ import type { DatabaseQueryBuilderContract } from './querybuilder.js' /** * Options for the unique and the exists validations */ -export type VineDbSearchOptions = { +export type VineDbSearchOptions = { /** * Database table for the query */ @@ -49,7 +49,7 @@ export type VineDbSearchOptions = { */ filter?: ( db: DatabaseQueryBuilderContract, - value: string, + value: ValueType, field: FieldContext ) => void | Promise } diff --git a/test/bindings/vinejs.spec.ts b/test/bindings/vinejs.spec.ts index 4d81c0f7..592a35e1 100644 --- a/test/bindings/vinejs.spec.ts +++ b/test/bindings/vinejs.spec.ts @@ -14,6 +14,9 @@ import { defineValidationRules } from '../../src/bindings/vinejs.js' import { getConfig, setup, cleanup, logger, createEmitter } from '../../test-helpers/index.js' let db: Database +const dialectPerformsCaseSensitiveSearch = ['mysql', 'mysql_legacy', 'mssql'].includes( + process.env.DB! +) test.group('VineJS | unique', (group) => { group.setup(async () => { @@ -102,13 +105,23 @@ test.group('VineJS | unique', (group) => { email: 'foo@bar.com', }) } catch (error) { - assert.deepEqual(error.messages, [ - { - field: 'email', - message: 'The email has already been taken', - rule: 'database.unique', - }, - ]) + if (dialectPerformsCaseSensitiveSearch) { + assert.deepEqual(error.messages, [ + { + field: 'email', + message: 'The email has already been taken', + rule: 'database.unique', + }, + ]) + } else { + assert.deepEqual(error.messages, [ + { + field: 'email', + message: 'The email has already been taken', + rule: 'database.unique', + }, + ]) + } } }) @@ -338,13 +351,23 @@ test.group('VineJS | exists', (group) => { email: 'foo@bar.com', }) } catch (error) { - assert.deepEqual(error.messages, [ - { - field: 'username', - message: 'The selected username is invalid', - rule: 'database.exists', - }, - ]) + if (dialectPerformsCaseSensitiveSearch) { + assert.deepEqual(error.messages, [ + { + field: 'email', + message: 'The email has already been taken', + rule: 'database.unique', + }, + ]) + } else { + assert.deepEqual(error.messages, [ + { + field: 'username', + message: 'The selected username is invalid', + rule: 'database.exists', + }, + ]) + } } })