mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage-server
synced 2026-04-11 18:08:16 +00:00
48 tests across 5 new spec files, all passing in <1s: - ozonetel-agent.service.spec: agent auth (login/logout/retry), manual dial, set disposition, change state, token caching (10 tests) - missed-call-webhook.spec: webhook payload parsing, IST→UTC conversion, duration parsing, CallerID handling, JSON-wrapped body (9 tests) - missed-queue.spec: abandon call polling, PENDING_CALLBACK status, UCID dedup, phone normalization, istToUtc utility (8 tests) - caller-resolution.spec: phone→lead+patient resolution (4 paths: both exist, lead only, patient only, neither), caching, phone normalization, link-if-unlinked (9 tests) - team.spec: 5-step member creation flow, SIP seat linking, validation, temp password Redis cache, email normalization, workspace context caching (8 tests) Fixtures: ozonetel-payloads.ts with accurate Ozonetel API shapes from official docs — webhook payloads, CDR records, abandon calls, disposition responses, auth responses. QA coverage: TC-MC-01/02/03, TC-IB-05/06/07, backs TC-IB/OB-01→06 via the Ozonetel service layer. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
226 lines
6.6 KiB
TypeScript
226 lines
6.6 KiB
TypeScript
/**
|
|
* Ozonetel API fixtures — accurate to the official docs (2026-04-10).
|
|
*
|
|
* These represent the EXACT shapes Ozonetel sends/returns. Used by
|
|
* unit tests to mock Ozonetel API responses and replay webhook payloads
|
|
* without a live Ozonetel account.
|
|
*
|
|
* Source: https://docs.ozonetel.com/reference
|
|
*/
|
|
|
|
// ─── Webhook "URL to Push" payloads ──────────────────────────────
|
|
// Ozonetel POSTs these to our /webhooks/ozonetel/missed-call endpoint.
|
|
// Field names match the CDR detail record (PascalCase).
|
|
|
|
export const WEBHOOK_INBOUND_ANSWERED = {
|
|
CallerID: '9949879837',
|
|
Status: 'Answered',
|
|
Type: 'InBound',
|
|
StartTime: '2026-04-09 14:30:00',
|
|
EndTime: '2026-04-09 14:34:00',
|
|
CallDuration: '00:04:00',
|
|
AgentName: 'global',
|
|
AudioFile: 'https://s3.ap-southeast-1.amazonaws.com/recordings.kookoo.in/global_healthx/20260409_143000.mp3',
|
|
monitorUCID: '31712345678901234',
|
|
Disposition: 'General Enquiry',
|
|
HangupBy: 'CustomerHangup',
|
|
DID: '918041763400',
|
|
CampaignName: 'Inbound_918041763400',
|
|
};
|
|
|
|
export const WEBHOOK_INBOUND_MISSED = {
|
|
CallerID: '6309248884',
|
|
Status: 'NotAnswered',
|
|
Type: 'InBound',
|
|
StartTime: '2026-04-09 15:00:00',
|
|
EndTime: '2026-04-09 15:00:30',
|
|
CallDuration: '00:00:00',
|
|
AgentName: '',
|
|
AudioFile: '',
|
|
monitorUCID: '31712345678905678',
|
|
Disposition: '',
|
|
HangupBy: 'CustomerHangup',
|
|
DID: '918041763400',
|
|
CampaignName: 'Inbound_918041763400',
|
|
};
|
|
|
|
export const WEBHOOK_OUTBOUND_ANSWERED = {
|
|
CallerID: '',
|
|
Status: 'Answered',
|
|
Type: 'OutBound',
|
|
StartTime: '2026-04-09 16:00:00',
|
|
EndTime: '2026-04-09 16:03:00',
|
|
CallDuration: '00:03:00',
|
|
AgentName: 'global',
|
|
AudioFile: 'https://s3.ap-southeast-1.amazonaws.com/recordings.kookoo.in/global_healthx/20260409_160000.mp3',
|
|
monitorUCID: '31712345678909999',
|
|
Disposition: 'Appointment Booked',
|
|
HangupBy: 'AgentHangup',
|
|
DID: '918041763400',
|
|
CampaignName: 'Inbound_918041763400',
|
|
};
|
|
|
|
export const WEBHOOK_OUTBOUND_NO_ANSWER = {
|
|
CallerID: '',
|
|
Status: 'NotAnswered',
|
|
Type: 'OutBound',
|
|
StartTime: '2026-04-09 16:10:00',
|
|
EndTime: '2026-04-09 16:10:45',
|
|
CallDuration: '00:00:00',
|
|
AgentName: 'global',
|
|
AudioFile: '',
|
|
monitorUCID: '31712345678908888',
|
|
Disposition: '',
|
|
HangupBy: 'Timeout',
|
|
DID: '918041763400',
|
|
CampaignName: 'Inbound_918041763400',
|
|
};
|
|
|
|
// ─── Agent Authentication ────────────────────────────────────────
|
|
// POST /CAServices/AgentAuthenticationV2/index.php
|
|
|
|
export const AGENT_AUTH_LOGIN_SUCCESS = {
|
|
status: 'success',
|
|
message: 'Agent global logged in successfully',
|
|
};
|
|
|
|
export const AGENT_AUTH_LOGIN_ALREADY = {
|
|
status: 'error',
|
|
message: 'Agent has already logged in',
|
|
};
|
|
|
|
export const AGENT_AUTH_LOGOUT_SUCCESS = {
|
|
status: 'success',
|
|
message: 'Agent global logged out successfully',
|
|
};
|
|
|
|
export const AGENT_AUTH_INVALID = {
|
|
status: 'error',
|
|
message: 'Invalid Authentication',
|
|
};
|
|
|
|
// ─── Set Disposition ─────────────────────────────────────────────
|
|
// POST /ca_apis/DispositionAPIV2 (action=Set)
|
|
|
|
export const DISPOSITION_SET_DURING_CALL = {
|
|
status: 'Success',
|
|
message: 'Disposition Queued Successfully',
|
|
};
|
|
|
|
export const DISPOSITION_SET_AFTER_CALL = {
|
|
details: 'Disposition saved successfully',
|
|
status: 'Success',
|
|
};
|
|
|
|
export const DISPOSITION_SET_UPDATE = {
|
|
status: 'Success',
|
|
message: 'Disposition Updated Successfully',
|
|
};
|
|
|
|
export const DISPOSITION_INVALID_UCID = {
|
|
status: 'Fail',
|
|
message: 'Invalid ucid',
|
|
};
|
|
|
|
export const DISPOSITION_INVALID_AGENT = {
|
|
status: 'Fail',
|
|
message: 'Invalid Agent ID',
|
|
};
|
|
|
|
// ─── CDR Detail Record ──────────────────────────────────────────
|
|
// GET /ca_reports/fetchCDRDetails
|
|
|
|
export const CDR_DETAIL_RECORD = {
|
|
AgentDialStatus: 'answered',
|
|
AgentID: 'global',
|
|
AgentName: 'global',
|
|
CallAudio: 'https://s3.ap-southeast-1.amazonaws.com/recordings.kookoo.in/global_healthx/20260409_143000.mp3',
|
|
CallDate: '2026-04-09',
|
|
CallID: 31733467784618213,
|
|
CallerConfAudioFile: '',
|
|
CallerID: '9949879837',
|
|
CampaignName: 'Inbound_918041763400',
|
|
Comments: '',
|
|
ConferenceDuration: '00:00:00',
|
|
CustomerDialStatus: 'answered',
|
|
CustomerRingTime: '00:00:05',
|
|
DID: '918041763400',
|
|
DialOutName: '',
|
|
DialStatus: 'answered',
|
|
DialedNumber: '523590',
|
|
Disposition: 'General Enquiry',
|
|
Duration: '00:04:00',
|
|
DynamicDID: '',
|
|
E164: '+919949879837',
|
|
EndTime: '14:34:00',
|
|
Event: 'AgentDial',
|
|
HandlingTime: '00:04:05',
|
|
HangupBy: 'CustomerHangup',
|
|
HoldDuration: '00:00:00',
|
|
Location: 'Bangalore',
|
|
PickupTime: '14:30:05',
|
|
Rating: 0,
|
|
RatingComments: '',
|
|
Skill: 'General',
|
|
StartTime: '14:30:00',
|
|
Status: 'Answered',
|
|
TalkTime: '00:04:00',
|
|
TimeToAnswer: '00:00:05',
|
|
TransferType: '',
|
|
TransferredTo: '',
|
|
Type: 'InBound',
|
|
UCID: 31712345678901234,
|
|
UUI: '',
|
|
WrapUpEndTime: '14:34:10',
|
|
WrapUpStartTime: '14:34:00',
|
|
WrapupDuration: '00:00:10',
|
|
};
|
|
|
|
export const CDR_RESPONSE_SUCCESS = {
|
|
status: 'success',
|
|
message: 'success',
|
|
details: [CDR_DETAIL_RECORD],
|
|
};
|
|
|
|
export const CDR_RESPONSE_EMPTY = {
|
|
status: 'success',
|
|
message: 'success',
|
|
details: [],
|
|
};
|
|
|
|
// ─── Abandon / Missed Calls ─────────────────────────────────────
|
|
// GET /ca_apis/abandonCalls
|
|
|
|
export const ABANDON_CALL_RECORD = {
|
|
monitorUCID: 31712345678905678,
|
|
type: 'InBound',
|
|
status: 'NotAnswered',
|
|
campaign: 'Inbound_918041763400',
|
|
callerID: '6309248884',
|
|
did: '918041763400',
|
|
skillID: '',
|
|
skill: '',
|
|
agentID: 'global',
|
|
agent: 'global',
|
|
hangupBy: 'CustomerHangup',
|
|
callTime: '2026-04-09 15:00:33',
|
|
};
|
|
|
|
export const ABANDON_RESPONSE_SUCCESS = {
|
|
status: 'success',
|
|
message: [ABANDON_CALL_RECORD],
|
|
};
|
|
|
|
export const ABANDON_RESPONSE_EMPTY = {
|
|
status: 'success',
|
|
message: [],
|
|
};
|
|
|
|
// ─── Get Disposition List ────────────────────────────────────────
|
|
// POST /ca_apis/DispositionAPIV2 (action=get)
|
|
|
|
export const DISPOSITION_LIST_SUCCESS = {
|
|
status: 'Success',
|
|
details: 'General Enquiry, Appointment Booked, Follow Up, Not Interested, Wrong Number, ',
|
|
};
|