fix: complete caller analytics reliability remediation
This commit is contained in:
@@ -6,7 +6,7 @@ function run(events: AnalyticsEvent[]) { return projectAnalytics(events.reduce<A
|
||||
describe('caller analytics business state', () => {
|
||||
it.each([180,183])('counts %i as connected even if final call fails', code => {
|
||||
const [r] = run([event('ATTEMPT'), event('PROGRESS', { code }), event('END', { code: 487, source: 'verified-dialog-final' })]);
|
||||
expect(analyticsRates(r)).toMatchObject({ totalCalls: 1, connectedCalls: 1, answeredCalls: 0, failedCalls: 0, notConnectedCalls: 0, connectionRate: 100, overallAnswerRate: 0, connectedAnswerRate: 0 });
|
||||
expect(analyticsRates(r)).toMatchObject({ totalCalls: 1, connectedCalls: 1, answeredCalls: 0, failedCalls: 0, notConnectedCalls: 0, connectionRate: 100, overallAnswerRate: 0, connectedAnswerRate: 0, durationUnknownCalls:0 });
|
||||
});
|
||||
it.each([100,181,182])('does not treat %i as connected', code => {
|
||||
const [r] = run([event('ATTEMPT'), event('PROGRESS', { code }), event('END', { code: 486, source: 'verified-dialog-final' })]);
|
||||
@@ -15,8 +15,8 @@ describe('caller analytics business state', () => {
|
||||
it('counts positive sub-second duration, not just 200', () => {
|
||||
const [zero] = run([event('ATTEMPT'), event('ACCEPTED', { code: 200 })]);
|
||||
expect(zero.answeredCalls).toBe(0);
|
||||
const [positive] = run([event('ATTEMPT'), event('ACCEPTED', { code: 200 }), event('END', { at: start + 1500, source: 'verified-dialog-final' })]);
|
||||
expect(positive).toMatchObject({ connectedCalls: 1, answeredCalls: 1, talkMs: 500 });
|
||||
const [positive] = run([event('ATTEMPT'), event('ACCEPTED', { code: 200 }), event('TALK_START', { at:start+1100, source:'dialog-acked' }), event('END', { at: start + 1500, source: 'verified-dialog-final' })]);
|
||||
expect(positive).toMatchObject({ connectedCalls: 1, answeredCalls: 1, talkMs: 400 });
|
||||
});
|
||||
it('preserves zero actual duration', () => {
|
||||
const [r] = run([event('ATTEMPT'), event('ACCEPTED', { code: 200 }), event('END', { talkMs: 0, source: 'verified-dialog-final' })]);
|
||||
@@ -44,7 +44,7 @@ describe('caller analytics business state', () => {
|
||||
expect(() => run([event('ATTEMPT'), event('PROGRESS', { customerId: 'other', code: 180 })])).toThrow('Conflicting');
|
||||
});
|
||||
it('calculates the three different business rates', () => {
|
||||
expect(analyticsRates({ totalCalls:100, connectedCalls:60, answeredCalls:30, failedCalls:25, pendingCalls:15, unknownCalls:0, activeCalls:15, talkMs:0 })).toMatchObject({ notConnectedCalls:40, connectionRate:60, overallAnswerRate:30, connectedAnswerRate:50 });
|
||||
expect(analyticsRates({ totalCalls:100, connectedCalls:60, answeredCalls:30, failedCalls:25, pendingCalls:15, unknownCalls:0, activeCalls:15, talkMs:0, durationUnknownCalls:0, provisionalAnsweredCalls:0 })).toMatchObject({ notConnectedCalls:40, connectionRate:60, overallAnswerRate:30, connectedAnswerRate:50 });
|
||||
});
|
||||
it('does not erase missing progress evidence with an end event', () => {
|
||||
expect(run([event('END',{code:487,source:'verified-dialog-final'})])[0]).toMatchObject({unknownCalls:1,failedCalls:0});
|
||||
@@ -59,4 +59,13 @@ describe('caller analytics business state', () => {
|
||||
expect(run([event('ATTEMPT'),event('ACCEPTED',{code:200}),...sequence,event('END',{at:start+5000,source:'verified-dialog-final'})])[0]).toMatchObject({connectedCalls:1,answeredCalls:0,talkMs:0});
|
||||
}
|
||||
});
|
||||
it('does not infer answer duration from 2xx without ACK evidence',()=>{
|
||||
const[r]=run([event('ATTEMPT'),event('ACCEPTED',{code:200}),event('END',{at:start+5000,source:'verified-dialog-final'})]);
|
||||
expect(analyticsRates(r)).toMatchObject({connectedCalls:1,answeredCalls:0,talkMs:0,durationUnknownCalls:1,overallAnswerRate:null,connectedAnswerRate:null});
|
||||
});
|
||||
it('keeps a version 2 original call pending until explicit close',()=>{
|
||||
const base={schemaVersion:2};
|
||||
expect(run([event('START',base),event('ATTEMPT',base),event('END',{...base,code:486,source:'verified-dialog-final'})])[0]).toMatchObject({activeCalls:1,pendingCalls:1,failedCalls:0});
|
||||
expect(run([event('START',base),event('ATTEMPT',base),event('END',{...base,code:486,source:'verified-dialog-final'}),event('CLOSE',{...base,source:'attempts-exhausted'})])[0]).toMatchObject({activeCalls:0,pendingCalls:0,failedCalls:1});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user