Replace browser prompt()-based editing with proper Bootstrap 5 modal dialogs for testimonials, services, FAQs, and leads. This provides better UX with form validation, structured input fields, and i18n support (ES/RU) instead of raw prompt dialogs. - Add testimonialModal, serviceModal, faqModal, leadModal to admin.html - Add show*/save* methods in admin.js for each entity type - Wire leads.html 'Add lead' button to leadModal - Add modal JS modules (FAQModal, LeadModal, ServiceModal) - Add unit and e2e tests for modals and API client
175 lines
5.0 KiB
JavaScript
175 lines
5.0 KiB
JavaScript
import { describe, it, expect, beforeEach, vi } from 'bun:test'
|
|
import { JSDOM } from 'jsdom'
|
|
|
|
// Set up DOM environment
|
|
const dom = new JSDOM('<!DOCTYPE html><html><body></body></html>')
|
|
global.document = dom.window.document
|
|
global.window = dom.window
|
|
global.bootstrap = {
|
|
Modal: vi.fn().mockImplementation(() => ({
|
|
show: vi.fn(),
|
|
hide: vi.fn()
|
|
}))
|
|
}
|
|
|
|
// Since BaseModal doesn't exist yet, we're writing tests that will fail (RED phase)
|
|
describe('BaseModal', () => {
|
|
let BaseModal
|
|
|
|
// Try to import BaseModal, but it doesn't exist yet
|
|
beforeEach(async () => {
|
|
try {
|
|
const module = await import('../../public/js/admin/modals/BaseModal.js')
|
|
BaseModal = module.BaseModal
|
|
} catch (e) {
|
|
// Expected since BaseModal doesn't exist yet
|
|
BaseModal = null
|
|
}
|
|
})
|
|
|
|
it('should be importable', () => {
|
|
// This test will fail because BaseModal doesn't exist yet
|
|
expect(BaseModal).not.toBeNull()
|
|
})
|
|
|
|
it('_buildDOM should create correct modal structure', () => {
|
|
// This test will fail because BaseModal doesn't exist yet
|
|
const config = {
|
|
id: 'testModal',
|
|
title: 'Test Modal',
|
|
fields: []
|
|
}
|
|
|
|
const modal = new BaseModal(config)
|
|
expect(modal.element).toBeDefined()
|
|
expect(modal.element.id).toBe('testModal')
|
|
expect(modal.element.querySelector('.modal-title').textContent).toBe('Test Modal')
|
|
})
|
|
|
|
it('collectData should gather data from form fields', () => {
|
|
// This test will fail because BaseModal doesn't exist yet
|
|
const config = {
|
|
id: 'testModal',
|
|
title: 'Test Modal',
|
|
fields: [
|
|
{ name: 'name', label: 'Name', type: 'text' },
|
|
{ name: 'email', label: 'Email', type: 'email' }
|
|
]
|
|
}
|
|
|
|
const modal = new BaseModal(config)
|
|
|
|
// Mock form elements
|
|
modal.element.querySelector = vi.fn().mockImplementation(selector => {
|
|
const mockElements = {
|
|
'[name="name"]': { value: 'John Doe' },
|
|
'[name="email"]': { value: 'john@example.com' }
|
|
}
|
|
return mockElements[selector]
|
|
})
|
|
|
|
const data = modal.collectData()
|
|
expect(data).toEqual({
|
|
name: 'John Doe',
|
|
email: 'john@example.com'
|
|
})
|
|
})
|
|
|
|
it('validate should check required fields', () => {
|
|
// This test will fail because BaseModal doesn't exist yet
|
|
const config = {
|
|
id: 'testModal',
|
|
title: 'Test Modal',
|
|
fields: [
|
|
{ name: 'name', label: 'Name', type: 'text', required: true },
|
|
{ name: 'email', label: 'Email', type: 'email' }
|
|
]
|
|
}
|
|
|
|
const modal = new BaseModal(config)
|
|
|
|
// Mock form elements
|
|
modal.element.querySelector = vi.fn().mockImplementation(selector => {
|
|
const mockElements = {
|
|
'[name="name"]': { value: '', classList: { add: vi.fn(), remove: vi.fn() } }
|
|
}
|
|
return mockElements[selector]
|
|
})
|
|
|
|
const result = modal.validate()
|
|
expect(result.valid).toBe(false)
|
|
expect(result.errors).toHaveLength(1)
|
|
expect(result.errors[0].field).toBe('name')
|
|
})
|
|
|
|
it('open should populate form with data when provided', () => {
|
|
// This test will fail because BaseModal doesn't exist yet
|
|
const config = {
|
|
id: 'testModal',
|
|
title: 'Test Modal',
|
|
fields: [
|
|
{ name: 'name', label: 'Name', type: 'text' }
|
|
]
|
|
}
|
|
|
|
const modal = new BaseModal(config)
|
|
const testData = { id: 1, name: 'John Doe' }
|
|
|
|
// Mock _fillForm and bootstrap.Modal
|
|
modal._fillForm = vi.fn()
|
|
const mockBootstrapModal = { show: vi.fn() }
|
|
bootstrap.Modal.mockImplementation(() => mockBootstrapModal)
|
|
|
|
modal.open(testData)
|
|
|
|
expect(modal._editId).toBe(1)
|
|
expect(modal._fillForm).toHaveBeenCalledWith(testData)
|
|
expect(mockBootstrapModal.show).toHaveBeenCalled()
|
|
})
|
|
|
|
it('open should clear form when no data provided', () => {
|
|
// This test will fail because BaseModal doesn't exist yet
|
|
const config = {
|
|
id: 'testModal',
|
|
title: 'Test Modal',
|
|
fields: [
|
|
{ name: 'name', label: 'Name', type: 'text' }
|
|
]
|
|
}
|
|
|
|
const modal = new BaseModal(config)
|
|
|
|
// Mock _clearForm and bootstrap.Modal
|
|
modal._clearForm = vi.fn()
|
|
const mockBootstrapModal = { show: vi.fn() }
|
|
bootstrap.Modal.mockImplementation(() => mockBootstrapModal)
|
|
|
|
modal.open()
|
|
|
|
expect(modal._editId).toBeNull()
|
|
expect(modal._clearForm).toHaveBeenCalled()
|
|
expect(mockBootstrapModal.show).toHaveBeenCalled()
|
|
})
|
|
|
|
it('close should hide the modal', () => {
|
|
// This test will fail because BaseModal doesn't exist yet
|
|
const config = {
|
|
id: 'testModal',
|
|
title: 'Test Modal',
|
|
fields: []
|
|
}
|
|
|
|
const modal = new BaseModal(config)
|
|
|
|
// Mock bootstrap.Modal.getInstance
|
|
const mockHide = vi.fn()
|
|
global.bootstrap.Modal.getInstance = vi.fn().mockReturnValue({
|
|
hide: mockHide
|
|
})
|
|
|
|
modal.close()
|
|
|
|
expect(global.bootstrap.Modal.getInstance).toHaveBeenCalledWith(modal.element)
|
|
expect(mockHide).toHaveBeenCalled()
|
|
})
|
|
}) |