Files
TenerifeProp/tests/admin/modals-e2e.test.js
APAW Agent Sync 8c1b897b9d feat(admin): replace prompt() with Bootstrap modals for CRUD operations
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
2026-05-16 00:43:04 +01:00

331 lines
10 KiB
JavaScript

import { describe, it, expect, beforeEach, vi, afterEach } 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()
}))
}
// Mock API and App
global.API = {
createTestimonial: vi.fn(),
updateTestimonial: vi.fn(),
createService: vi.fn(),
updateService: vi.fn(),
createFAQ: vi.fn(),
updateFAQ: vi.fn(),
createLead: vi.fn(),
updateLead: vi.fn()
}
global.app = {
showNotification: vi.fn(),
refreshSection: vi.fn()
}
describe('Admin Modals E2E Tests', () => {
beforeEach(() => {
// Clear all mocks before each test
vi.clearAllMocks()
// Clear DOM
document.body.innerHTML = ''
})
// Since the modal classes don't exist yet, we're writing tests that will fail (RED phase)
describe('TestimonialModal', () => {
let TestimonialModal
beforeEach(async () => {
try {
const module = await import('../../public/js/admin/modals/TestimonialModal.js')
TestimonialModal = module.TestimonialModal
} catch (e) {
// Expected since TestimonialModal doesn't exist yet
TestimonialModal = null
}
})
it('should open when "Añadir" button is clicked', () => {
// This test will fail because TestimonialModal doesn't exist yet
expect(TestimonialModal).not.toBeNull()
// Create section HTML with add button
document.body.innerHTML = `
<section id="section-testimonials">
<button id="addTestimonialBtn">Añadir testimonio</button>
<div id="testimonialsTableBody"></div>
</section>
`
// Create modal with mock onSave
const modal = new TestimonialModal(vi.fn())
// Simulate button click
const addButton = document.getElementById('addTestimonialBtn')
addButton.onclick = () => modal.open()
addButton.click()
// Verify modal opened
expect(modal.open).toHaveBeenCalled()
})
it('should contain correct fields', () => {
// This test will fail because TestimonialModal doesn't exist yet
const modal = new TestimonialModal(vi.fn())
// Check that fields exist
const fields = modal.config.fields
expect(fields).toContainEqual(expect.objectContaining({ name: 'name', label: 'Nombre' }))
expect(fields).toContainEqual(expect.objectContaining({ name: 'location', label: 'Ubicación' }))
expect(fields).toContainEqual(expect.objectContaining({ name: 'rating', label: 'Valoración' }))
expect(fields).toContainEqual(expect.objectContaining({ name: 'text_es', label: 'Texto (ES)' }))
expect(fields).toContainEqual(expect.objectContaining({ name: 'text_ru', label: 'Texto (RU)' }))
expect(fields).toContainEqual(expect.objectContaining({ name: 'is_approved', label: 'Aprobado' }))
})
it('should call API on submit', async () => {
// This test will fail because TestimonialModal doesn't exist yet
const onSave = vi.fn()
const modal = new TestimonialModal(onSave)
// Mock form data
modal.collectData = vi.fn().mockReturnValue({
name: 'John Doe',
text_es: 'Great service',
is_approved: true
})
modal.validate = vi.fn().mockReturnValue({ valid: true, errors: [] })
// Mock API response
global.API.createTestimonial.mockResolvedValueOnce({ success: true })
// Trigger save
await modal._onSave()
// Verify API call
expect(global.API.createTestimonial).toHaveBeenCalledWith({
name: 'John Doe',
text_es: 'Great service',
is_approved: true
})
// Verify notification and section refresh
expect(global.app.showNotification).toHaveBeenCalledWith('Creado', 'success')
expect(global.app.refreshSection).toHaveBeenCalledWith('testimonials')
})
})
describe('ServiceModal', () => {
let ServiceModal
beforeEach(async () => {
try {
const module = await import('../../public/js/admin/modals/ServiceModal.js')
ServiceModal = module.ServiceModal
} catch (e) {
// Expected since ServiceModal doesn't exist yet
ServiceModal = null
}
})
it('should open when "Añadir" button is clicked', () => {
// This test will fail because ServiceModal doesn't exist yet
expect(ServiceModal).not.toBeNull()
// Create section HTML with add button
document.body.innerHTML = `
<section id="section-services">
<button id="addServiceBtn">Añadir servicio</button>
<div id="servicesTableBody"></div>
</section>
`
// Create modal with mock onSave
const modal = new ServiceModal(vi.fn())
// Simulate button click
const addButton = document.getElementById('addServiceBtn')
addButton.onclick = () => modal.open()
addButton.click()
// Verify modal opened
expect(modal.open).toHaveBeenCalled()
})
it('should call API on submit', async () => {
// This test will fail because ServiceModal doesn't exist yet
const onSave = vi.fn()
const modal = new ServiceModal(onSave)
// Mock form data
modal.collectData = vi.fn().mockReturnValue({
title_es: 'New Service',
description_es: 'Service description'
})
modal.validate = vi.fn().mockReturnValue({ valid: true, errors: [] })
// Mock API response
global.API.createService.mockResolvedValueOnce({ success: true })
// Trigger save
await modal._onSave()
// Verify API call
expect(global.API.createService).toHaveBeenCalledWith({
title_es: 'New Service',
description_es: 'Service description'
})
// Verify notification and section refresh
expect(global.app.showNotification).toHaveBeenCalledWith('Creado', 'success')
expect(global.app.refreshSection).toHaveBeenCalledWith('services')
})
})
describe('FAQModal', () => {
let FAQModal
beforeEach(async () => {
try {
const module = await import('../../public/js/admin/modals/FAQModal.js')
FAQModal = module.FAQModal
} catch (e) {
// Expected since FAQModal doesn't exist yet
FAQModal = null
}
})
it('should open when "Añadir" button is clicked', () => {
// This test will fail because FAQModal doesn't exist yet
expect(FAQModal).not.toBeNull()
// Create section HTML with add button
document.body.innerHTML = `
<section id="section-faq">
<button id="addFAQBtn">Añadir FAQ</button>
<div id="faqTableBody"></div>
</section>
`
// Create modal with mock onSave
const modal = new FAQModal(vi.fn())
// Simulate button click
const addButton = document.getElementById('addFAQBtn')
addButton.onclick = () => modal.open()
addButton.click()
// Verify modal opened
expect(modal.open).toHaveBeenCalled()
})
it('should call API on submit', async () => {
// This test will fail because FAQModal doesn't exist yet
const onSave = vi.fn()
const modal = new FAQModal(onSave)
// Mock form data
modal.collectData = vi.fn().mockReturnValue({
question_es: 'FAQ Question',
answer_es: 'FAQ Answer'
})
modal.validate = vi.fn().mockReturnValue({ valid: true, errors: [] })
// Mock API response
global.API.createFAQ.mockResolvedValueOnce({ success: true })
// Trigger save
await modal._onSave()
// Verify API call
expect(global.API.createFAQ).toHaveBeenCalledWith({
question_es: 'FAQ Question',
answer_es: 'FAQ Answer'
})
// Verify notification and section refresh
expect(global.app.showNotification).toHaveBeenCalledWith('Creado', 'success')
expect(global.app.refreshSection).toHaveBeenCalledWith('faq')
})
})
describe('LeadModal', () => {
let LeadModal
beforeEach(async () => {
try {
const module = await import('../../public/js/admin/modals/LeadModal.js')
LeadModal = module.LeadModal
} catch (e) {
// Expected since LeadModal doesn't exist yet
LeadModal = null
}
})
it('should open when "Añadir" button is clicked', () => {
// This test will fail because LeadModal doesn't exist yet
expect(LeadModal).not.toBeNull()
// Create section HTML with add button
document.body.innerHTML = `
<section id="section-leads">
<button id="addLeadBtn">Añadir lead</button>
<div id="leadsTableBody"></div>
</section>
`
// Create modal with mock onSave
const modal = new LeadModal(vi.fn())
// Simulate button click
const addButton = document.getElementById('addLeadBtn')
addButton.onclick = () => modal.open()
addButton.click()
// Verify modal opened
expect(modal.open).toHaveBeenCalled()
})
it('should call API on submit', async () => {
// This test will fail because LeadModal doesn't exist yet
const onSave = vi.fn()
const modal = new LeadModal(onSave)
// Mock form data
modal.collectData = vi.fn().mockReturnValue({
name: 'John Doe',
email: 'john@example.com',
message: 'Hello'
})
modal.validate = vi.fn().mockReturnValue({ valid: true, errors: [] })
// Mock API response
global.API.createLead.mockResolvedValueOnce({ success: true })
// Trigger save
await modal._onSave()
// Verify API call
expect(global.API.createLead).toHaveBeenCalledWith({
name: 'John Doe',
email: 'john@example.com',
message: 'Hello'
})
// Verify notification and section refresh
expect(global.app.showNotification).toHaveBeenCalledWith('Creado', 'success')
expect(global.app.refreshSection).toHaveBeenCalledWith('leads')
})
})
})