backend-service/internal/services/booking_integration_test.go

284 lines
6.9 KiB
Go
Raw Normal View History

package services
import (
"testing"
"time"
"attune-heart-therapy/internal/config"
"attune-heart-therapy/internal/models"
)
// MockBookingRepository for testing
type MockBookingRepository struct {
bookings map[uint]*models.Booking
nextID uint
}
func NewMockBookingRepository() *MockBookingRepository {
return &MockBookingRepository{
bookings: make(map[uint]*models.Booking),
nextID: 1,
}
}
func (m *MockBookingRepository) Create(booking *models.Booking) error {
booking.ID = m.nextID
m.nextID++
m.bookings[booking.ID] = booking
return nil
}
func (m *MockBookingRepository) GetByID(id uint) (*models.Booking, error) {
if booking, exists := m.bookings[id]; exists {
return booking, nil
}
return nil, nil
}
func (m *MockBookingRepository) GetByUserID(userID uint) ([]models.Booking, error) {
var result []models.Booking
for _, booking := range m.bookings {
if booking.UserID == userID {
result = append(result, *booking)
}
}
return result, nil
}
func (m *MockBookingRepository) Update(booking *models.Booking) error {
m.bookings[booking.ID] = booking
return nil
}
func (m *MockBookingRepository) Delete(id uint) error {
delete(m.bookings, id)
return nil
}
func (m *MockBookingRepository) GetUpcomingBookings() ([]models.Booking, error) {
var result []models.Booking
now := time.Now()
for _, booking := range m.bookings {
if booking.Status == models.BookingStatusScheduled && booking.ScheduledAt.After(now) {
result = append(result, *booking)
}
}
return result, nil
}
// MockScheduleRepository for testing
type MockScheduleRepository struct {
schedules map[uint]*models.Schedule
}
func NewMockScheduleRepository() *MockScheduleRepository {
return &MockScheduleRepository{
schedules: make(map[uint]*models.Schedule),
}
}
func (m *MockScheduleRepository) Create(schedule *models.Schedule) error {
m.schedules[schedule.ID] = schedule
return nil
}
func (m *MockScheduleRepository) GetAvailable(date time.Time) ([]models.Schedule, error) {
var result []models.Schedule
for _, schedule := range m.schedules {
if schedule.IsAvailable && schedule.BookedCount < schedule.MaxBookings {
result = append(result, *schedule)
}
}
return result, nil
}
func (m *MockScheduleRepository) Update(schedule *models.Schedule) error {
m.schedules[schedule.ID] = schedule
return nil
}
func (m *MockScheduleRepository) GetByID(id uint) (*models.Schedule, error) {
if schedule, exists := m.schedules[id]; exists {
return schedule, nil
}
return nil, nil
}
func (m *MockScheduleRepository) IncrementBookedCount(scheduleID uint) error {
if schedule, exists := m.schedules[scheduleID]; exists {
schedule.BookedCount++
}
return nil
}
func (m *MockScheduleRepository) DecrementBookedCount(scheduleID uint) error {
if schedule, exists := m.schedules[scheduleID]; exists {
schedule.BookedCount--
}
return nil
}
func (m *MockBookingRepository) GetByPaymentID(paymentID string) (*models.Booking, error) {
for _, booking := range m.bookings {
if booking.PaymentID == paymentID {
return booking, nil
}
}
return nil, nil
}
// MockUserRepository for testing
type MockUserRepository struct {
users map[uint]*models.User
}
func NewMockUserRepository() *MockUserRepository {
return &MockUserRepository{
users: make(map[uint]*models.User),
}
}
func (m *MockUserRepository) Create(user *models.User) error {
m.users[user.ID] = user
return nil
}
func (m *MockUserRepository) GetByID(id uint) (*models.User, error) {
if user, exists := m.users[id]; exists {
return user, nil
}
user := &models.User{
Email: "test@example.com",
FirstName: "Test",
}
user.ID = id
return user, nil
}
func (m *MockUserRepository) GetByEmail(email string) (*models.User, error) {
for _, user := range m.users {
if user.Email == email {
return user, nil
}
}
return nil, nil
}
func (m *MockUserRepository) Update(user *models.User) error {
m.users[user.ID] = user
return nil
}
func (m *MockUserRepository) GetActiveUsersCount() (int64, error) {
return int64(len(m.users)), nil
}
// MockNotificationService for testing
type MockNotificationService struct{}
func (m *MockNotificationService) SendWelcomeEmail(user *models.User) error {
return nil
}
func (m *MockNotificationService) SendPaymentNotification(user *models.User, booking *models.Booking, success bool) error {
return nil
}
func (m *MockNotificationService) SendMeetingInfo(user *models.User, booking *models.Booking) error {
return nil
}
func (m *MockNotificationService) SendReminder(user *models.User, booking *models.Booking) error {
return nil
}
func (m *MockNotificationService) ScheduleReminder(bookingID uint, reminderTime time.Time) error {
return nil
}
func (m *MockNotificationService) ProcessPendingNotifications() error {
return nil
}
func TestBookingService_CreateBookingWithJitsiIntegration(t *testing.T) {
// Setup mock repositories
bookingRepo := NewMockBookingRepository()
scheduleRepo := NewMockScheduleRepository()
userRepo := NewMockUserRepository()
// Setup Jitsi service
jitsiConfig := &config.JitsiConfig{
BaseURL: "https://meet.jit.si",
}
jitsiService := NewJitsiService(jitsiConfig)
// Setup mock services
var paymentService PaymentService
notificationService := &MockNotificationService{}
// Create booking service
bookingService := NewBookingService(bookingRepo, scheduleRepo, userRepo, jitsiService, paymentService, notificationService)
// Create a test schedule
schedule := &models.Schedule{
StartTime: time.Now().Add(24 * time.Hour),
EndTime: time.Now().Add(25 * time.Hour),
IsAvailable: true,
MaxBookings: 1,
BookedCount: 0,
}
schedule.ID = 1
scheduleRepo.schedules[1] = schedule
// Create booking request
req := BookingRequest{
ScheduleID: 1,
Amount: 100.0,
Notes: "Test booking with Jitsi integration",
}
// Create booking
booking, err := bookingService.CreateBooking(123, req)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if booking == nil {
t.Fatal("Expected booking to be created, got nil")
}
// Verify booking details
if booking.UserID != 123 {
t.Errorf("Expected user ID 123, got %d", booking.UserID)
}
if booking.Amount != 100.0 {
t.Errorf("Expected amount 100.0, got %f", booking.Amount)
}
// Verify Jitsi integration
if booking.JitsiRoomID == "" {
t.Error("Expected Jitsi room ID to be set")
}
if booking.JitsiRoomURL == "" {
t.Error("Expected Jitsi room URL to be set")
}
// Verify URL format
expectedPrefix := "https://meet.jit.si/"
if len(booking.JitsiRoomURL) <= len(expectedPrefix) {
t.Error("Expected room URL to contain room ID")
}
if booking.JitsiRoomURL[:len(expectedPrefix)] != expectedPrefix {
t.Errorf("Expected room URL to start with %s, got %s", expectedPrefix, booking.JitsiRoomURL)
}
// Verify schedule booking count was incremented
updatedSchedule, _ := scheduleRepo.GetByID(1)
if updatedSchedule.BookedCount != 1 {
t.Errorf("Expected booked count to be 1, got %d", updatedSchedule.BookedCount)
}
}