247 lines
8.1 KiB
TypeScript
247 lines
8.1 KiB
TypeScript
|
|
import {
|
||
|
|
loginSchema,
|
||
|
|
registerSchema,
|
||
|
|
refreshTokenSchema,
|
||
|
|
resetPasswordSchema,
|
||
|
|
changePasswordSchema,
|
||
|
|
resetRequestSchema,
|
||
|
|
} from '@/validators/auth.validator';
|
||
|
|
|
||
|
|
// ============================================================
|
||
|
|
// loginSchema
|
||
|
|
// ============================================================
|
||
|
|
|
||
|
|
describe('loginSchema', () => {
|
||
|
|
it('should pass with valid email and password', () => {
|
||
|
|
const { error } = loginSchema.validate({
|
||
|
|
email: 'user@example.com',
|
||
|
|
password: 'password123',
|
||
|
|
});
|
||
|
|
expect(error).toBeUndefined();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should fail with invalid email format', () => {
|
||
|
|
const { error } = loginSchema.validate({
|
||
|
|
email: 'not-an-email',
|
||
|
|
password: 'password123',
|
||
|
|
});
|
||
|
|
expect(error).toBeDefined();
|
||
|
|
expect(error?.details[0].message).toMatch(/valid email/i);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should fail without email', () => {
|
||
|
|
const { error } = loginSchema.validate({ password: 'password123' });
|
||
|
|
expect(error).toBeDefined();
|
||
|
|
expect(error?.details[0].message).toMatch(/Email is required/i);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should fail without password', () => {
|
||
|
|
const { error } = loginSchema.validate({ email: 'user@example.com' });
|
||
|
|
expect(error).toBeDefined();
|
||
|
|
expect(error?.details[0].message).toMatch(/Password is required/i);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should fail with password shorter than 6 characters', () => {
|
||
|
|
const { error } = loginSchema.validate({
|
||
|
|
email: 'user@example.com',
|
||
|
|
password: '12345',
|
||
|
|
});
|
||
|
|
expect(error).toBeDefined();
|
||
|
|
expect(error?.details[0].message).toMatch(/at least 6 characters/i);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
// ============================================================
|
||
|
|
// registerSchema
|
||
|
|
// ============================================================
|
||
|
|
|
||
|
|
describe('registerSchema', () => {
|
||
|
|
const validPayload = {
|
||
|
|
username: 'john_doe',
|
||
|
|
email: 'john@example.com',
|
||
|
|
password: 'securepass',
|
||
|
|
first_name: 'John',
|
||
|
|
last_name: 'Doe',
|
||
|
|
phone: '0812345678',
|
||
|
|
};
|
||
|
|
|
||
|
|
it('should pass with all required fields', () => {
|
||
|
|
const { error } = registerSchema.validate(validPayload);
|
||
|
|
expect(error).toBeUndefined();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should pass with optional prefix', () => {
|
||
|
|
const { error } = registerSchema.validate({
|
||
|
|
...validPayload,
|
||
|
|
prefix: { th: 'นาย', en: 'Mr.' },
|
||
|
|
});
|
||
|
|
expect(error).toBeUndefined();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should fail if username has invalid characters', () => {
|
||
|
|
const { error } = registerSchema.validate({
|
||
|
|
...validPayload,
|
||
|
|
username: 'john doe!',
|
||
|
|
});
|
||
|
|
expect(error).toBeDefined();
|
||
|
|
expect(error?.details[0].message).toMatch(/letters, numbers, and underscores/i);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should fail if username is too short (< 3 chars)', () => {
|
||
|
|
const { error } = registerSchema.validate({
|
||
|
|
...validPayload,
|
||
|
|
username: 'ab',
|
||
|
|
});
|
||
|
|
expect(error).toBeDefined();
|
||
|
|
expect(error?.details[0].message).toMatch(/at least 3 characters/i);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should fail if username is too long (> 50 chars)', () => {
|
||
|
|
const { error } = registerSchema.validate({
|
||
|
|
...validPayload,
|
||
|
|
username: 'a'.repeat(51),
|
||
|
|
});
|
||
|
|
expect(error).toBeDefined();
|
||
|
|
expect(error?.details[0].message).toMatch(/not exceed 50 characters/i);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should fail with invalid email', () => {
|
||
|
|
const { error } = registerSchema.validate({
|
||
|
|
...validPayload,
|
||
|
|
email: 'bad-email',
|
||
|
|
});
|
||
|
|
expect(error).toBeDefined();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should fail if phone is too short (< 10 chars)', () => {
|
||
|
|
const { error } = registerSchema.validate({
|
||
|
|
...validPayload,
|
||
|
|
phone: '081234',
|
||
|
|
});
|
||
|
|
expect(error).toBeDefined();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should fail without first_name', () => {
|
||
|
|
const { error } = registerSchema.validate({
|
||
|
|
...validPayload,
|
||
|
|
first_name: undefined,
|
||
|
|
});
|
||
|
|
expect(error).toBeDefined();
|
||
|
|
expect(error?.details[0].message).toMatch(/First name is required/i);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should fail without last_name', () => {
|
||
|
|
const { error } = registerSchema.validate({
|
||
|
|
...validPayload,
|
||
|
|
last_name: undefined,
|
||
|
|
});
|
||
|
|
expect(error).toBeDefined();
|
||
|
|
expect(error?.details[0].message).toMatch(/Last name is required/i);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
// ============================================================
|
||
|
|
// refreshTokenSchema
|
||
|
|
// ============================================================
|
||
|
|
|
||
|
|
describe('refreshTokenSchema', () => {
|
||
|
|
it('should pass with a valid refreshToken', () => {
|
||
|
|
const { error } = refreshTokenSchema.validate({
|
||
|
|
refreshToken: 'some-refresh-token-string',
|
||
|
|
});
|
||
|
|
expect(error).toBeUndefined();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should fail without refreshToken', () => {
|
||
|
|
const { error } = refreshTokenSchema.validate({});
|
||
|
|
expect(error).toBeDefined();
|
||
|
|
expect(error?.details[0].message).toMatch(/Refresh token is required/i);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
// ============================================================
|
||
|
|
// resetPasswordSchema
|
||
|
|
// ============================================================
|
||
|
|
|
||
|
|
describe('resetPasswordSchema', () => {
|
||
|
|
it('should pass with valid token and password', () => {
|
||
|
|
const { error } = resetPasswordSchema.validate({
|
||
|
|
token: 'reset-token-abc',
|
||
|
|
password: 'newpassword',
|
||
|
|
});
|
||
|
|
expect(error).toBeUndefined();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should fail without token', () => {
|
||
|
|
const { error } = resetPasswordSchema.validate({ password: 'newpassword' });
|
||
|
|
expect(error).toBeDefined();
|
||
|
|
expect(error?.details[0].message).toMatch(/Reset token is required/i);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should fail with password too short', () => {
|
||
|
|
const { error } = resetPasswordSchema.validate({
|
||
|
|
token: 'abc',
|
||
|
|
password: '12345',
|
||
|
|
});
|
||
|
|
expect(error).toBeDefined();
|
||
|
|
expect(error?.details[0].message).toMatch(/at least 6 characters/i);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should fail with password too long (> 100 chars)', () => {
|
||
|
|
const { error } = resetPasswordSchema.validate({
|
||
|
|
token: 'abc',
|
||
|
|
password: 'a'.repeat(101),
|
||
|
|
});
|
||
|
|
expect(error).toBeDefined();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
// ============================================================
|
||
|
|
// changePasswordSchema (auth)
|
||
|
|
// ============================================================
|
||
|
|
|
||
|
|
describe('changePasswordSchema (auth.validator)', () => {
|
||
|
|
it('should pass with valid old and new passwords', () => {
|
||
|
|
const { error } = changePasswordSchema.validate({
|
||
|
|
oldPassword: 'oldpass123',
|
||
|
|
newPassword: 'newpass456',
|
||
|
|
});
|
||
|
|
expect(error).toBeUndefined();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should fail without oldPassword', () => {
|
||
|
|
const { error } = changePasswordSchema.validate({ newPassword: 'newpass456' });
|
||
|
|
expect(error).toBeDefined();
|
||
|
|
expect(error?.details[0].message).toMatch(/Password is required/i);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should fail without newPassword', () => {
|
||
|
|
const { error } = changePasswordSchema.validate({ oldPassword: 'oldpass123' });
|
||
|
|
expect(error).toBeDefined();
|
||
|
|
expect(error?.details[0].message).toMatch(/Password is required/i);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
// ============================================================
|
||
|
|
// resetRequestSchema
|
||
|
|
// ============================================================
|
||
|
|
|
||
|
|
describe('resetRequestSchema', () => {
|
||
|
|
it('should pass with valid email', () => {
|
||
|
|
const { error } = resetRequestSchema.validate({ email: 'user@example.com' });
|
||
|
|
expect(error).toBeUndefined();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should fail without email', () => {
|
||
|
|
const { error } = resetRequestSchema.validate({});
|
||
|
|
expect(error).toBeDefined();
|
||
|
|
expect(error?.details[0].message).toMatch(/Email is required/i);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should fail with invalid email', () => {
|
||
|
|
const { error } = resetRequestSchema.validate({ email: 'not-email' });
|
||
|
|
expect(error).toBeDefined();
|
||
|
|
expect(error?.details[0].message).toMatch(/valid email/i);
|
||
|
|
});
|
||
|
|
});
|