package services_test import ( "context" "encoding/json" "regexp" "testing" "time" "github.com/DATA-DOG/go-sqlmock" "github.com/rede5/gohorsejobs/backend/internal/dto" "github.com/rede5/gohorsejobs/backend/internal/services" "github.com/stretchr/testify/assert" ) func TestAdminService_Extra_Unit(t *testing.T) { db, mock, err := sqlmock.New() assert.NoError(t, err) defer db.Close() svc := services.NewAdminService(db) ctx := context.Background() // 1. UpdateTag mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, name, category, active, created_at, updated_at FROM job_tags`)). WithArgs(10). WillReturnRows(sqlmock.NewRows([]string{"id", "name", "category", "active", "created_at", "updated_at"}). AddRow(10, "Old Tag", "skill", true, time.Now(), time.Now())) mock.ExpectExec(regexp.QuoteMeta(`UPDATE job_tags SET`)). WithArgs("New Tag", false, sqlmock.AnyArg(), 10). WillReturnResult(sqlmock.NewResult(1, 1)) name := "New Tag" active := false tag, err := svc.UpdateTag(ctx, 10, &name, &active) assert.NoError(t, err) assert.Equal(t, "New Tag", tag.Name) assert.Equal(t, false, tag.Active) // 2. GetEmailTemplate vars := []string{"name"} varsJSON, _ := json.Marshal(vars) mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, slug, subject, body_html, variables`)). WithArgs("welcome"). WillReturnRows(sqlmock.NewRows([]string{"id", "slug", "subject", "body_html", "variables", "created_at", "updated_at"}). AddRow("tpl-1", "welcome", "Welcome", "

Hi

", varsJSON, time.Now(), time.Now())) tpl, err := svc.GetEmailTemplate(ctx, "welcome") assert.NoError(t, err) assert.Equal(t, "Welcome", tpl.Subject) // 3. UpdateEmailSettings mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, provider, smtp_host`)). WillReturnRows(sqlmock.NewRows([]string{"id", "provider", "smtp_host", "smtp_port", "smtp_user", "smtp_pass", "smtp_secure", "sender_name", "sender_email", "amqp_url", "is_active", "updated_at"}). AddRow("set-1", "smtp", "old.host", 587, "user", "pass", true, "Sender", "email", "amqp://", true, time.Now())) mock.ExpectExec(regexp.QuoteMeta(`UPDATE email_settings SET`)). WithArgs("smtp", "new.host", sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), "set-1"). WillReturnResult(sqlmock.NewResult(1, 1)) mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, provider, smtp_host`)). WillReturnRows(sqlmock.NewRows([]string{"id", "provider", "smtp_host", "smtp_port", "smtp_user", "smtp_pass", "smtp_secure", "sender_name", "sender_email", "amqp_url", "is_active", "updated_at"}). AddRow("set-1", "smtp", "new.host", 587, "user", "pass", true, "Sender", "email", "amqp://", true, time.Now())) host := "new.host" settingsReq := dto.UpdateEmailSettingsRequest{SMTPHost: &host} settings, err := svc.UpdateEmailSettings(ctx, settingsReq) assert.NoError(t, err) if assert.NotNil(t, settings.SMTPHost) { assert.Equal(t, "new.host", *settings.SMTPHost) } } func TestAdminService_DuplicateJob(t *testing.T) { db, mock, err := sqlmock.New() assert.NoError(t, err) defer db.Close() svc := services.NewAdminService(db) mock.ExpectQuery(regexp.QuoteMeta(`SELECT company_id, created_by, title`)). WithArgs("job-1"). WillReturnRows(sqlmock.NewRows([]string{"company_id", "created_by", "title", "description", "salary_min", "salary_max", "salary_type", "employment_type", "work_mode", "working_hours", "location", "region_id", "city_id", "requirements", "benefits", "visa_support", "language_level"}). AddRow("cmp-1", "user-1", "Job 1", "Desc", 100.0, 200.0, "USD", "full-time", "remote", "40", "Loc", 1, 1, []byte("{}"), []byte("{}"), true, "en")) mock.ExpectQuery(regexp.QuoteMeta(`INSERT INTO jobs`)). WithArgs("cmp-1", "user-1", "Job 1", "Desc", 100.0, 200.0, "USD", "full-time", "remote", "40", "Loc", 1, 1, []byte("{}"), []byte("{}"), true, "en", "draft", false, sqlmock.AnyArg(), sqlmock.AnyArg()). WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow("job-new")) job, err := svc.DuplicateJob(context.Background(), "job-1") assert.NoError(t, err) assert.Equal(t, "job-new", job.ID) assert.Equal(t, "draft", job.Status) } func TestAdminService_ListMethods(t *testing.T) { db, mock, err := sqlmock.New() assert.NoError(t, err) defer db.Close() svc := services.NewAdminService(db) // ListCompanies mock.ExpectQuery(regexp.QuoteMeta(`SELECT COUNT(*) FROM companies`)). WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1)) mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, name`)). WillReturnRows(sqlmock.NewRows([]string{"id", "name", "slug", "type", "document", "address", "region_id", "city_id", "phone", "email", "website", "logo_url", "description", "active", "verified", "created_at", "updated_at"}). AddRow("cmp-1", "Company", "slug", "tech", "doc", "addr", 1, 1, "123", "email", "web", "logo", "desc", true, true, time.Now(), time.Now())) verified := true companies, total, err := svc.ListCompanies(context.Background(), &verified, 1, 10) assert.NoError(t, err) assert.Equal(t, 1, total) assert.Len(t, companies, 1) // ListUsers (with company filter) mock.ExpectQuery(regexp.QuoteMeta(`SELECT COUNT(*) FROM users WHERE tenant_id = $1`)). WithArgs("cmp-1"). WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1)) mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, COALESCE(name, full_name, identifier, ''), email, role`)). WithArgs("cmp-1", 10, 0). WillReturnRows(sqlmock.NewRows([]string{"id", "name", "email", "role", "status", "created_at"}). AddRow("u-1", "User", "email", "admin", "active", time.Now())) companyID := "cmp-1" users, total, err := svc.ListUsers(context.Background(), 1, 10, &companyID) assert.NoError(t, err) assert.Equal(t, 1, total) assert.Len(t, users, 1) // ListTags mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, name, category, active`)). WithArgs("skill"). WillReturnRows(sqlmock.NewRows([]string{"id", "name", "category", "active", "created_at", "updated_at"}). AddRow(1, "Go", "skill", true, time.Now(), time.Now())) cat := "skill" tags, err := svc.ListTags(context.Background(), &cat) assert.NoError(t, err) assert.Len(t, tags, 1) // CreateTag mock.ExpectQuery(regexp.QuoteMeta(`INSERT INTO job_tags`)). WithArgs("Java", "skill", true, sqlmock.AnyArg(), sqlmock.AnyArg()). WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(2)) newTag, err := svc.CreateTag(context.Background(), "Java", "skill") assert.NoError(t, err) assert.Equal(t, "Java", newTag.Name) // UpdateCompany mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, name`)). WithArgs("cmp-1"). WillReturnRows(sqlmock.NewRows([]string{"id", "name", "slug", "type", "document", "address", "region_id", "city_id", "phone", "email", "website", "logo_url", "description", "active", "verified", "created_at", "updated_at"}). AddRow("cmp-1", "Old Name", "slug", "tech", "doc", "addr", 1, 1, "123", "email", "web", "logo", "desc", true, true, time.Now(), time.Now())) mock.ExpectExec(regexp.QuoteMeta(`UPDATE companies`)). WithArgs("New Name", "slug", "tech", "doc", "addr", 1, 1, "123", "email", "web", "logo", "new desc", true, true, sqlmock.AnyArg(), "cmp-1"). WillReturnResult(sqlmock.NewResult(1, 1)) newName := "New Name" newDesc := "new desc" cmpReq := dto.UpdateCompanyRequest{Name: &newName, Description: &newDesc} updatedCmp, err := svc.UpdateCompany(context.Background(), "cmp-1", cmpReq) assert.NoError(t, err) assert.Equal(t, "New Name", updatedCmp.Name) }