Skip to content

Commit 21d6ce7

Browse files
authored
fix(user-state): receive agent stateChange event (webex#350)
1 parent 31ebfb1 commit 21d6ce7

File tree

6 files changed

+102
-16
lines changed

6 files changed

+102
-16
lines changed

packages/contact-center/store/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"react": "18.3.1",
2323
"react-dom": "18.3.1",
2424
"typescript": "5.6.3",
25-
"webex": "3.6.0-wxcc.5"
25+
"webex": "3.7.0-wxcc.3"
2626
},
2727
"devDependencies": {
2828
"@babel/core": "7.25.2",
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const AGENT_STATE_CHANGE = 'agent:stateChange';

packages/contact-center/user-state/src/helper.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import {useState, useEffect} from "react";
2+
// TODO: Export & Import this AGENT_STATE_CHANGE constant from SDK
3+
import {AGENT_STATE_CHANGE} from './constants';
24

35
export const useUserState = ({idleCodes, agentId, cc}) => {
46

@@ -11,12 +13,28 @@ export const useUserState = ({idleCodes, agentId, cc}) => {
1113
useEffect(() => {
1214
// Reset the timer whenever the component mounts or the state changes
1315
setElapsedTime(0);
14-
const timer = setInterval(() => {
16+
let timer = setInterval(() => {
1517
setElapsedTime(prevTime => prevTime + 1);
1618
}, 1000);
1719

20+
const handleStateChange = (data) => {
21+
if (data && typeof data === 'object' && data.type === 'AgentStateChangeSuccess') {
22+
const DEFAULT_CODE = '0'; // Default code when no aux code is present
23+
setCurrentState({
24+
id: data.auxCodeId?.trim() !== '' ? data.auxCodeId : DEFAULT_CODE
25+
});
26+
setElapsedTime(0);
27+
}
28+
};
29+
30+
cc.on(AGENT_STATE_CHANGE, handleStateChange);
31+
1832
// Cleanup the timer on component unmount
19-
return () => clearInterval(timer);
33+
return () => {
34+
clearInterval(timer);
35+
timer = null;
36+
cc.off(AGENT_STATE_CHANGE, handleStateChange);
37+
}
2038
}, []);
2139

2240
const setAgentStatus = (selectedCode) => {

packages/contact-center/user-state/tests/helper.ts

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import { useUserState } from '../src/helper';
33

44
describe('useUserState Hook', () => {
55
const mockCC = {
6-
setAgentState: jest.fn()
6+
setAgentState: jest.fn(),
7+
on: jest.fn(),
8+
off: jest.fn(),
79
};
810

911
const idleCodes = [
@@ -16,6 +18,8 @@ describe('useUserState Hook', () => {
1618
beforeEach(() => {
1719
jest.useFakeTimers();
1820
mockCC.setAgentState.mockReset();
21+
mockCC.on.mockReset();
22+
mockCC.off.mockReset();
1923
});
2024

2125
afterEach(() => {
@@ -31,6 +35,9 @@ describe('useUserState Hook', () => {
3135
elapsedTime: 0,
3236
currentState: {}
3337
});
38+
39+
expect(mockCC.on).toHaveBeenCalledTimes(1);
40+
expect(mockCC.on).toHaveBeenCalledWith('agent:stateChange', expect.any(Function));
3441
});
3542

3643
it('should increment elapsedTime every second', () => {
@@ -93,4 +100,57 @@ describe('useUserState Hook', () => {
93100
});
94101
});
95102
});
103+
104+
it('should handle agent state change events correctly', async () => {
105+
const { result } = renderHook(() => useUserState({ idleCodes, agentId, cc: mockCC }));
106+
107+
// Get the handler function that was registered
108+
const handler = mockCC.on.mock.calls[0][1];
109+
110+
// Test with right event type
111+
act(() => {
112+
handler({ type: 'AgentStateChangeSuccess', auxCodeId: '123' });
113+
});
114+
115+
await waitFor(() => {
116+
expect(result.current.currentState).toEqual({ id: '123' });
117+
});
118+
119+
// Test with wrong event type
120+
act(() => {
121+
handler({ type: 'WrongType' });
122+
});
123+
124+
await waitFor(() => {
125+
expect(result.current.currentState).toEqual({ id: '123' });
126+
});
127+
128+
// Test again with right event type but different value
129+
act(() => {
130+
handler({ type: 'AgentStateChangeSuccess', auxCodeId: '1213' });
131+
});
132+
133+
await waitFor(() => {
134+
expect(result.current.currentState).toEqual({ id: '1213' });
135+
});
136+
137+
// Test with empty auxCodeId
138+
act(() => {
139+
handler({ type: 'AgentStateChangeSuccess', auxCodeId: '' });
140+
});
141+
142+
await waitFor(() => {
143+
expect(result.current.currentState).toEqual({ id: '0' });
144+
});
145+
});
146+
147+
it('should cleanup event listener on unmount', () => {
148+
const { unmount } = renderHook(() => useUserState({ idleCodes, agentId, cc: mockCC }));
149+
150+
unmount();
151+
152+
// Verify that off was called with the same event and handler
153+
expect(mockCC.off).toHaveBeenCalledTimes(1);
154+
expect(mockCC.off).toHaveBeenCalledWith('agent:stateChange', expect.any(Function));
155+
});
96156
});

packages/contact-center/user-state/tests/user-state/index.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ import '@testing-library/jest-dom';
66

77
// Mock the store import
88
jest.mock('@webex/cc-store', () => {return {
9-
cc: {},
9+
cc: {
10+
on: jest.fn(),
11+
off: jest.fn(),
12+
},
1013
idleCodes: [],
1114
agentId: 'testAgentId'
1215
}});
@@ -17,7 +20,11 @@ describe('UserState Component', () => {
1720

1821
render(<UserState/>);
1922

20-
expect(useUserStateSpy).toHaveBeenCalledWith({cc: {}, idleCodes: [], agentId: 'testAgentId'});
23+
expect(useUserStateSpy).toHaveBeenCalledTimes(1);
24+
expect(useUserStateSpy).toHaveBeenCalledWith({cc: {
25+
on: expect.any(Function),
26+
off: expect.any(Function)
27+
}, idleCodes: [], agentId: 'testAgentId'});
2128
const heading = screen.getByTestId('user-state-title');
2229
expect(heading).toHaveTextContent('Agent State');
2330
});

yarn.lock

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5435,7 +5435,7 @@ __metadata:
54355435
react-dom: "npm:18.3.1"
54365436
ts-loader: "npm:9.5.1"
54375437
typescript: "npm:5.6.3"
5438-
webex: "npm:3.6.0-wxcc.5"
5438+
webex: "npm:3.7.0-wxcc.3"
54395439
webpack: "npm:5.94.0"
54405440
webpack-cli: "npm:5.1.4"
54415441
webpack-merge: "npm:6.0.1"
@@ -6382,17 +6382,17 @@ __metadata:
63826382
languageName: node
63836383
linkType: hard
63846384

6385-
"@webex/plugin-cc@npm:3.5.0-wxcc.4":
6386-
version: 3.5.0-wxcc.4
6387-
resolution: "@webex/plugin-cc@npm:3.5.0-wxcc.4"
6385+
"@webex/plugin-cc@npm:3.5.0-wxcc.9":
6386+
version: 3.5.0-wxcc.9
6387+
resolution: "@webex/plugin-cc@npm:3.5.0-wxcc.9"
63886388
dependencies:
63896389
"@types/platform": "npm:1.3.4"
63906390
"@webex/calling": "npm:3.6.0-wxcc.1"
63916391
"@webex/internal-plugin-mercury": "npm:3.5.0-wxcc.1"
63926392
"@webex/webex-core": "npm:3.5.0-wxcc.1"
63936393
buffer: "npm:6.0.3"
63946394
jest-html-reporters: "npm:3.0.11"
6395-
checksum: 10c0/bc4f04c3c827cf0edb9b4d5fc435fa5e7dee77d8e2b42d31cc86d17cfd35df3601584309feb3f6515916989bbc2304530c69c257dd4c84b05495a272bf92efbb
6395+
checksum: 10c0/238585455185112cbe13460a4477a71346c1a33a1b083704eb45b3ed737a6001f8dd221c8914160adc42482bcbdfdbd53fed9ec5a81d83a354e6e9efd573f786
63966396
languageName: node
63976397
linkType: hard
63986398

@@ -25907,9 +25907,9 @@ __metadata:
2590725907
languageName: node
2590825908
linkType: hard
2590925909

25910-
"webex@npm:3.6.0-wxcc.5":
25911-
version: 3.6.0-wxcc.5
25912-
resolution: "webex@npm:3.6.0-wxcc.5"
25910+
"webex@npm:3.7.0-wxcc.3":
25911+
version: 3.7.0-wxcc.3
25912+
resolution: "webex@npm:3.7.0-wxcc.3"
2591325913
dependencies:
2591425914
"@babel/polyfill": "npm:^7.12.1"
2591525915
"@babel/runtime-corejs2": "npm:^7.14.8"
@@ -25923,7 +25923,7 @@ __metadata:
2592325923
"@webex/internal-plugin-voicea": "npm:3.5.0-wxcc.1"
2592425924
"@webex/plugin-attachment-actions": "npm:3.5.0-wxcc.1"
2592525925
"@webex/plugin-authorization": "npm:3.5.0-wxcc.1"
25926-
"@webex/plugin-cc": "npm:3.5.0-wxcc.4"
25926+
"@webex/plugin-cc": "npm:3.5.0-wxcc.9"
2592725927
"@webex/plugin-device-manager": "npm:3.5.0-wxcc.1"
2592825928
"@webex/plugin-logger": "npm:3.5.0-wxcc.1"
2592925929
"@webex/plugin-meetings": "npm:3.5.0-wxcc.1"
@@ -25937,7 +25937,7 @@ __metadata:
2593725937
"@webex/storage-adapter-local-storage": "npm:3.5.0-wxcc.1"
2593825938
"@webex/webex-core": "npm:3.5.0-wxcc.1"
2593925939
lodash: "npm:^4.17.21"
25940-
checksum: 10c0/2268058f35abae6cccdfb994dd04a041b8c646bad8dc75b2eb56f00ed2c39019be2b506f1fe4cbcbe0c9d308c0483e7f157e7280f840b2e6c5155f4c9f27afe3
25940+
checksum: 10c0/ee83226f0d884db685b86fadf514c2cddfcbf91f8329d691be4132828e29477a6551bfebfe82a510b24b223319d0eb6badb7322d10713fec1c302a879a253e9d
2594125941
languageName: node
2594225942
linkType: hard
2594325943

0 commit comments

Comments
 (0)