Skip to main content

Casos de prueba — Settings y Queue

Catálogo de los tests de los módulos settings y queue. Specs fuente (relativas a src/app/modules/):

  • settings/controllers/tenant-settings.controller.spec.ts
  • settings/repositories/tenant-settings.repository.spec.ts
  • settings/services/tenant-settings.service.spec.ts
  • settings/services/auto-resolution-precedence.service.spec.ts
  • settings/services/business-hours-evaluator.service.spec.ts
  • settings/settings-module-wiring.integration.spec.ts
  • queue/queue.module.spec.ts

Resumen: 7 specs y 36 tests (it): 30 de settings (controlador 3, repositorio 5, servicio 7, precedencia 7, horario 7, wiring 1) y 6 de queue. El spec del controlador define 2 it dentro de un describe.each de 6 rutas, por lo que en ejecución corren 12 casos parametrizados más 1 adicional.

settings/controllers/tenant-settings.controller.spec.ts​

Integración HTTP (supertest) con PermissionsGuard real y ResponseInterceptor global; AuthGuard se reemplaza por un FakeAuthGuard que inyecta tenantId y roleId.

TenantSettingsController — permission guard integration › $method $path (describe.each)​

Se ejecuta para cada ruta: GET /v1/settings/get-all (SETTINGS_READ), PATCH /v1/settings/general, PATCH /v1/settings/attention/schedule, PATCH /v1/settings/attention/auto-resolution, PATCH /v1/settings/attention/csat y PATCH /v1/settings/attention/scheduled-messages (todas SETTINGS_UPDATE).

TestEscenarioResultado esperadoMocks
returns 403 Forbidden when the resolved acronym set is missing the required permissionEl set de acrónimos resuelto está vacíoLa ruta responde 403TenantSettingsService, TranslateService, PermissionResolverService, FakeAuthGuard
returns 200 OK when the resolved acronym set includes the required permissionEl set incluye el acrónimo requerido por la rutaResponde 200 y el resolver se invoca con (tenantId, roleId)Los mismos

TenantSettingsController — permission guard integration › GET /v1/settings/get-all — response body through the real global interceptor​

TestEscenarioResultado esperadoMocks
returns the actual settings payload, not an empty paginated shellGET /get-all con SETTINGS_READ pasando por el ResponseInterceptor realdata.results tiene 1 elemento y sus general y autoResolution coinciden con los settings por defecto (el payload no se descarta)Los mismos

settings/repositories/tenant-settings.repository.spec.ts​

Integración con MongoDB real en memoria (mongodb-memory-server).

TenantSettingsRepository — integration (mongodb-memory-server) › findByTenantId​

TestEscenarioResultado esperadoMocks
returns null when no settings exist for the tenantTenant sin documentoDevuelve nullNinguno (MongoDB en memoria)
returns the document scoped to the tenantSe crea el documento con valores por defecto para el tenant ADevuelve el documento con el tenantId del tenant ANinguno

TenantSettingsRepository — integration (mongodb-memory-server) › create​

TestEscenarioResultado esperadoMocks
stores the document with defaults for the tenantcreate con los valores por defecto del dominioDocumento con tenantId, general.language = 'es' y autoResolution.resolveInMinutes = 5Ninguno

TenantSettingsRepository — integration (mongodb-memory-server) › updateSection​

TestEscenarioResultado esperadoMocks
replaces only the requested section, scoped to tenantupdateSection(A, 'general', { language: 'en', timezone: 'UTC' })Se actualiza general y las demás secciones (p. ej. autoResolution.resolveInMinutes = 5) quedan intactasNinguno
returns null when the tenant has no settings documentupdateSection sobre el tenant B sin documentoDevuelve nullNinguno

settings/services/tenant-settings.service.spec.ts​

TenantSettingsService › getOrCreate​

TestEscenarioResultado esperadoMocks
returns existing settings mapped to TenantSettingsDomain when foundfindByTenantId devuelve un documento con general en inglés/UTCNo llama create; devuelve una instancia de TenantSettingsDomain con general = { language: 'en', timezone: 'UTC' }TenantSettingsRepository
creates default settings when none exist for the tenantfindByTenantId devuelve nullLlama create(tenantId, defaults) con los valores por defecto (idioma es, zona America/Mexico_City, secciones deshabilitadas, resolveInMinutes 5, límites de mensajes programados 5 / 30 / 10 / 50) y devuelve un TenantSettingsDomainTenantSettingsRepository

TenantSettingsService › updateGeneral​

TestEscenarioResultado esperadoMocks
ensures settings exist then replaces the general sectionSettings existentes; nuevo general en/UTCupdateSection(tenantId, 'general', newGeneral) y el resultado refleja el nuevo generalTenantSettingsRepository

TenantSettingsService › updateBusinessHours​

TestEscenarioResultado esperadoMocks
replaces the full businessHours sectionNuevo horario con un día habilitado (lunes 08:00-17:00)updateSection(tenantId, 'businessHours', newSchedule) y el resultado refleja la secciónTenantSettingsRepository

TenantSettingsService › updateAutoResolution​

TestEscenarioResultado esperadoMocks
replaces the full autoResolution sectionNueva configuración de auto-resoluciónupdateSection(tenantId, 'autoResolution', ...) y el resultado refleja la secciónTenantSettingsRepository

TenantSettingsService › updateCsat​

TestEscenarioResultado esperadoMocks
replaces the full csat sectionNueva configuración CSAT con mensajes por calificaciónupdateSection(tenantId, 'csat', ...) y el resultado refleja la secciónTenantSettingsRepository

TenantSettingsService › updateScheduledMessages​

TestEscenarioResultado esperadoMocks
replaces the full scheduledMessages sectionNueva configuración de mensajes programados (notas no permitidas, límites reducidos, políticas send)updateSection(tenantId, 'scheduledMessages', ...) y el resultado refleja la secciónTenantSettingsRepository

settings/services/auto-resolution-precedence.service.spec.ts​

Servicio puro, sin mocks.

AutoResolutionPrecedenceService​

TestEscenarioResultado esperadoMocks
uses the tenant config when there is no departmentresolve(null, tenantConfig)Devuelve la configuración del tenant (enabled, resolveInMinutes, notifyInMinutes, notificationMessage, sendFarewellMessage)Ninguno
uses the tenant config when the department does not overrideDepartamento con overrideGlobalResolution: falsePrevalece la configuración del tenant (10 min, mensaje y despedida del tenant)Ninguno
uses the department config when overrideGlobalResolution is trueDepartamento con overrideGlobalResolution: truePrevalece la configuración del departamento (2 min, su mensaje, sin despedida)Ninguno
reports disabled when the effective source has enabled=falseTenant con enabled: false y sin departamentoenabled es falseNinguno
respects department precedence even when the department disables auto-resolution and the tenant enables itDepartamento con override y enabled: false, tenant habilitadoenabled es falseNinguno
takes sendFarewellMessage from the department when it overrides, from the tenant otherwiseDepartamento con override, departamento sin override y sin departamentofalse con override; true en los otros dos casos (valor del tenant)Ninguno
does not expose a farewell text: the copy lives only on the connectionresolve(null, config)El resultado no tiene la propiedad farewellMessageNinguno

settings/services/business-hours-evaluator.service.spec.ts​

Servicio puro con zonas horarias IANA (Luxon), sin mocks.

BusinessHoursEvaluatorService​

TestEscenarioResultado esperadoMocks
returns isWithinHours=true when current local time falls inside an enabled day rangeMiércoles 09:00 local (America/Mexico_City) con rango 09:00-18:00 habilitadoisWithinHours es trueNinguno
returns isWithinHours=false when the current day is not enabledMismo instante pero el día está deshabilitadofalseNinguno
returns isWithinHours=false when the current local time is before the configured range07:00 local, rango 09:00-18:00falseNinguno
returns isWithinHours=false at/after the range end (end boundary is exclusive)Exactamente 18:00 localfalse (el fin es exclusivo)Ninguno
returns isWithinHours=false when there is no configured entry for the current weekdaySolo hay entrada para lunes y la fecha es miércolesfalseNinguno
evaluates using the tenant IANA timezone via Luxon, correctly across a DST boundaryAmerica/New_York, mismo 13:00 UTC en julio (DST) y en enero (sin DST)true en julio (09:00 local) y false en enero (08:00 local)Ninguno
does NOT support cross-midnight ranges (startTime > endTime never matches) — documented model limitationRango 22:00-02:00 evaluado a las 17:00 localfalse; documenta que no hay soporte para rangos que cruzan medianocheNinguno

settings/settings-module-wiring.integration.spec.ts​

Regresión de la dependencia circular UserModule / SettingsModule: compila el grafo real de DI sin sobrescribir providers.

UserModule y SettingsModule wiring — integration (real DI graph)​

TestEscenarioResultado esperadoMocks
compiles the real module graph without any provider overridesSe importan ConfigModule, MongooseModule (Mongo en memoria), CoreAuthModule, CorePermissionsModule, StorageModule, MediaModule, UserModule y SettingsModule y se llama .compile()El módulo compila sin errores de DI y se cierra correctamenteNinguno (MongoDB en memoria; sin overrides)

queue/queue.module.spec.ts​

createRedisConnectionOptions (W13 — resilient Redis connection)​

ConfigService simulado con redis.host, redis.port, redis.password y redis.db.

TestEscenarioResultado esperadoMocks
sets maxRetriesPerRequest to null so a BullMQ Worker can attach without throwingOpciones con config por defectomaxRetriesPerRequest es nullConfigService.get
never gives up reconnecting (retryStrategy always returns a finite delay, never false/undefined)retryStrategy con intentos 1, 5, 50 y 1000Siempre devuelve un número mayor que 0ConfigService.get
caps the reconnect backoff instead of growing unbounded (no log-spam-then-thundering-herd)retryStrategy(100000)Devuelve REDIS_RECONNECT.MAX_DELAY_MSConfigService.get
keeps commands queued while disconnected instead of rejecting immediatelyOpciones por defectoenableOfflineQueue es trueConfigService.get
still forwards host/port/password/db from configConfig con password secret y db 2Las opciones reflejan host redis, puerto 6379, password y dbConfigService.get
never sets commandTimeout on the shared connection (CRITICAL-B — would race the Worker idle poll)Opciones por defectocommandTimeout es undefined (guarda de regresión)ConfigService.get