From 282d18ca1a102222dc493d8fdccec5176ded70f4 Mon Sep 17 00:00:00 2001 From: Anthony Griffith Date: Wed, 11 Sep 2024 11:40:50 -0600 Subject: [PATCH 1/2] fix method return the function was returning the opposite of what was intended --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 80bf717..3587100 100644 --- a/src/index.ts +++ b/src/index.ts @@ -461,7 +461,7 @@ export class Validation implements FormValidation { if (!this.fieldsToValidate.includes(field)) throw new Error(`Field "${field.name}" is not being validated`); - return !!this.validateField(field, silently); + return !!!this.validateField(field, silently); } /** From 7015f93a3bc852542a43340bd49dad8006c394a7 Mon Sep 17 00:00:00 2001 From: Anthony Griffith Date: Wed, 11 Sep 2024 11:42:20 -0600 Subject: [PATCH 2/2] add tests to all methods --- tests/4-methods.spec.ts | 315 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 315 insertions(+) diff --git a/tests/4-methods.spec.ts b/tests/4-methods.spec.ts index d18dca9..2547c73 100644 --- a/tests/4-methods.spec.ts +++ b/tests/4-methods.spec.ts @@ -2,3 +2,318 @@ Public Methods Testing - Check if each of the public methods can be called and work as expected */ +// /* +// Basic configuration testing +// - Check if Validation can be initialized and correctly configured +// - No in-depth testing of Validation functionality +// */ + +import { test, expect } from '@playwright/test'; +import { Validation } from '../src/index' + +// Extend the window object to include the Validation class +declare global { + interface Window { + Validation: typeof Validation; + validationInstance: Validation; + } +} + +test.beforeEach(async ({ page }) => { + page.on('console', msg => console.log(msg.text())); // Capture console logs + + await page.goto('http://127.0.0.1:3000/tests'); + + await page.evaluate(() => { + window.validationInstance = new window.Validation('#testForm', { + submitCallback: () => { + }, + fields: { + name: { + rules: ['required'], + }, + email: { + rules: ['required', 'validEmail'], + }, + }, + }); + }); +}); + + +test.describe('Validation Methods', () => { + + // TESTS + + test.describe('#isValid', () => { + test('should return true when all fields are valid', async ({ page }) => { + const nameInput = await page.$('#name'); + const emailInput = await page.$('#email'); + const ageInput = await page.$('#age'); + + await nameInput?.fill('John Doe'); + await emailInput?.fill('jhon.doe@some.com'); + await ageInput?.fill('26'); + + const isValid = await page.evaluate(() => { + return window.validationInstance.isValid(); + }); + + expect(isValid).toBe(true); + }); + + test('should return false when there are validation errors', async ({ page }) => { + const nameInput = await page.$('#name'); + const emailInput = await page.$('#email'); + const ageInput = await page.$('#age'); + + await nameInput?.fill('John Doe'); + await emailInput?.fill('abc'); + await ageInput?.fill('24'); + + const isValid = await page.evaluate(() => { + return window.validationInstance.isValid(); + }); + + expect(isValid).toBe(false); + }); + }); + + test.describe('#validateForm', () => { + test('should validate the form and return true when valid', async ({ page }) => { + const nameInput = await page.$('#name'); + const emailInput = await page.$('#email'); + const ageInput = await page.$('#age'); + + await nameInput?.fill('John Doe'); + await emailInput?.fill('jhon.doe@some.com'); + await ageInput?.fill('26'); + + const isValid = await page.evaluate(() => { + return window.validationInstance.validateForm(); + }); + + expect(isValid).toBe(true); + }); + + test('should validate the form and return false when invalid', async ({ page }) => { + const nameInput = await page.$('#name'); + const emailInput = await page.$('#email'); + const ageInput = await page.$('#age'); + + await nameInput?.fill('John Doe'); + await emailInput?.fill('abc'); + await ageInput?.fill('24'); + + const isValid = await page.evaluate(() => { + return window.validationInstance.validateForm(); + }); + + expect(isValid).toBe(false); + }); + }); + + test.describe('#isFieldValid', () => { + test('should return true when a specific field is valid', async ({ page }) => { + const emailInput = await page.$('#email'); + + await emailInput?.fill('john.doe@gmail.com'); + + const isValid = await page.evaluate(() => { + return window.validationInstance.isFieldValid("email"); + }); + + expect(isValid).toBe(true); + }); + + test('should return false when a specific field is invalid', async ({ page }) => { + const emailInput = await page.$('#email'); + + await emailInput?.fill('invalid-email'); + + const isValid = await page.evaluate(() => { + return window.validationInstance.isFieldValid("email"); + }); + + expect(isValid).toBe(false); + }); + + test('should throw an error if the field is empty', async ({ page }) => { + // Test the isFieldValid method when the field is empty + try { + await page.evaluate(() => { + return window.validationInstance.isFieldValid(""); + }); + } catch (error) { + expect(error).toBeTruthy(); + } + }); + + test('should throw an error if the field does not exist', async ({ page }) => { + try { + await page.evaluate(() => { + return window.validationInstance.isFieldValid("nonExistentField"); + }); + } catch (error) { + expect(error).toBeTruthy(); + } + }); + }); +}); + +test.describe('Rule Management Methods', () => { + + + test.describe('#addMethod', async () => { + test('should successfully add a custom validation method', async ({ page }) => { + page.evaluate(() => { + window.validationInstance.addMethod('startsWithA', (_, value) => { + return value.startsWith('a'); + }, 'Email must start with the letter "a"'); + + window.validationInstance.addFieldRule('email', 'startsWithA'); + }); + + const emailInput = await page.$('#email'); + await emailInput?.fill("a@gmail.com"); + + const isValid = await page.evaluate(() => { + return window.validationInstance.isFieldValid("email"); + }); + + expect(isValid).toBe(true); + }); + + test('should modify a method if it already exists', async ({ page }) => { + page.evaluate(() => { + window.validationInstance.addMethod('validEmail', (_, value) => { + return value.startsWith('a'); + }, "Email must start with the letter 'a'"); + + window.validationInstance.addFieldRule('email', 'validEmail'); + }); + + const emailInput = await page.$('#email'); + await emailInput?.fill("a"); + + const isValid = await page.evaluate(() => { + return window.validationInstance.isFieldValid("email"); + }); + + expect(isValid).toBe(true); + + }); + }); + + test.describe('#setFieldRules', () => { + test('should set the rules for a field', async ({ page }) => { + page.evaluate(() => { + window.validationInstance.setFieldRules('age', ['numbersOnly', 'required']); + }); + + const nameInput = await page.$('#age'); + await nameInput?.fill('26'); + + const isValid = await page.evaluate(() => { + return window.validationInstance.isFieldValid("age"); + }); + + expect(isValid).toBe(true); + }); + }); + + test.describe('#addFieldRule', () => { + test('should add a rule to a field', async ({ page }) => { + page.evaluate(() => { + window.validationInstance.addFieldRule('age', 'numbersOnly'); + }); + + const nameInput = await page.$('#age'); + await nameInput?.fill('26'); + + const isValid = await page.evaluate(() => { + return window.validationInstance.isFieldValid("age"); + }); + + expect(isValid).toBe(true); + }); + }); + + test.describe('#removeFieldRule', () => { + test('should remove a rule from a field', async ({ page }) => { + page.evaluate(() => { + window.validationInstance.removeFieldRule('email', 'validEmail'); + }); + + const emailInput = await page.$('#email'); + await emailInput?.fill('invalid-email'); + + const isValid = await page.evaluate(() => { + return window.validationInstance.isFieldValid("email"); + }); + + expect(isValid).toBe(true); + }); + + test('should throw an error if the field does not exist', async ({ page }) => { + try { + await page.evaluate(() => { + window.validationInstance.removeFieldRule('nonExistentField', 'validEmail'); + }); + } catch (error) { + expect(error).toBeTruthy(); + } + }); + }); +}); + +test.describe('Form Configuration Methods', () => { + test.describe('#addFieldConfig', () => { + test('should add a field configuration', async ({ page }) => { + page.evaluate(() => { + window.validationInstance.addFieldConfig('age', { + rules: ['numbersOnly'], + messages: { + numbersOnly: 'Please enter numbers only', + }, + optional: false, + inputContainer: '#age', + errorPlacement: ()=>{}, + }); + }); + + const nameInput = await page.$('#age'); + await nameInput?.fill('26'); + + const isValid = await page.evaluate(() => { + return window.validationInstance.isFieldValid("age"); + }); + + expect(isValid).toBe(true); + }); + }); +}); + +test.describe('Form Utility Methods', () => { + test.describe('#cloneDeep', () => { + test('should clone a validation object', async ({ page }) => { + const clonedInstance = await page.evaluate(() => { + return window.validationInstance.cloneDeep({ + submitCallback: () => { + }, + fields: { + name: { + rules: ['required'], + }, + email: { + rules: ['required', 'validEmail'], + }, + }, + }); + }); + + expect(clonedInstance).toBeTruthy(); + }); + }); +}) +