Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
187 changes: 108 additions & 79 deletions packages/contact-center/store/ai-docs/store-spec.md

Large diffs are not rendered by default.

26 changes: 18 additions & 8 deletions packages/contact-center/store/src/storeEventsWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -414,10 +414,15 @@ class StoreWrapper implements IStoreWrapper {
this.store.cc.on(event, callback);
};

setTaskCallback = (event: TASK_EVENTS, callback, taskId: string) => {
if (!callback) return;
const task = this.store.taskList[taskId];
if (!task) return;
setTaskCallback = (event: TASK_EVENTS, callback, task: ITask) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve task-id callback callers

Existing @webex/cc-store consumers can still call setTaskCallback(event, cb, interactionId) because this singleton is a published/default package surface, and this change now treats that string as an ITask: the guard passes, the log prints an undefined id, and the call then fails at task.on(...) instead of registering the listener. Since this PR is described as non-breaking and only updates the in-repo callers, keep accepting the old string-id form (or add a separate new API) so already-published widgets/hosts do not crash after upgrading; the same compatibility issue applies to removeTaskCallback.

Useful? React with 👍 / 👎.

if (!callback || !task) return;
this.store.logger?.info(
`CC-Widgets: setTaskCallback(): registering task event '${event}' for ${task.data?.interactionId}`,
{
module: 'storeEventsWrapper.ts',
method: 'setTaskCallback',
}
);
task.on(event, callback);
};

Expand Down Expand Up @@ -445,10 +450,15 @@ class StoreWrapper implements IStoreWrapper {
this.store.cc.off(event);
};

removeTaskCallback = (event: TASK_EVENTS, callback, taskId: string) => {
if (!callback) return;
const task = this.store.taskList[taskId];
if (!task) return;
removeTaskCallback = (event: TASK_EVENTS, callback, task: ITask) => {
if (!callback || !task) return;
this.store.logger?.info(
`CC-Widgets: removeTaskCallback(): removing task event '${event}' for ${task.data?.interactionId}`,
{
module: 'storeEventsWrapper.ts',
method: 'removeTaskCallback',
}
);
task.off(event, callback);
};

Expand Down
31 changes: 17 additions & 14 deletions packages/contact-center/store/tests/storeEventsWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -474,46 +474,49 @@ describe('storeEventsWrapper', () => {
it('should set task callback', () => {
const mockCb = jest.fn();
expect(storeWrapper.setTaskCallback).toBeInstanceOf(Function);
storeWrapper['store'].taskList = {
mockTaskId: mockTask,
};

storeWrapper.setTaskCallback(TASK_EVENTS.TASK_ASSIGNED, mockCb, 'mockTaskId');
storeWrapper.setTaskCallback(TASK_EVENTS.TASK_ASSIGNED, mockCb, mockTask);
expect(mockTask.on).toHaveBeenCalledWith(TASK_EVENTS.TASK_ASSIGNED, mockCb);
});

it('should return if callback is not present or task is not found', () => {
it('should return if callback is not present or task is not provided', () => {
const mockCb = jest.fn();
expect(storeWrapper.setTaskCallback).toBeInstanceOf(Function);

storeWrapper.setTaskCallback(TASK_EVENTS.TASK_ASSIGNED, undefined, 'mockTaskId');
storeWrapper.setTaskCallback(TASK_EVENTS.TASK_ASSIGNED, undefined, mockTask);
expect(mockTask.on).not.toHaveBeenCalledWith(TASK_EVENTS.TASK_ASSIGNED, mockCb);

storeWrapper.setTaskCallback(TASK_EVENTS.TASK_ASSIGNED, mockCb, 'mockTaskI2');
storeWrapper.setTaskCallback(TASK_EVENTS.TASK_ASSIGNED, mockCb, null);
expect(mockTask.on).not.toHaveBeenCalledWith(TASK_EVENTS.TASK_ASSIGNED, mockCb);
});

it('should remove task callback', () => {
const mockCb = jest.fn();
storeWrapper['store'].taskList = {
mockTaskId: mockTask,
};
expect(storeWrapper.removeTaskCallback).toBeInstanceOf(Function);

storeWrapper.removeTaskCallback(TASK_EVENTS.TASK_WRAPPEDUP, mockCb, 'mockTaskId');
storeWrapper.removeTaskCallback(TASK_EVENTS.TASK_WRAPPEDUP, mockCb, mockTask);
expect(mockTask.off).toHaveBeenCalledWith(TASK_EVENTS.TASK_WRAPPEDUP, mockCb);
});

it('should return and not remove callback if callback is not present or task is not found', () => {
it('should return and not remove callback if callback is not present or task is not provided', () => {
const mockCb = jest.fn();
expect(storeWrapper.removeTaskCallback).toBeInstanceOf(Function);

storeWrapper.removeTaskCallback(TASK_EVENTS.TASK_ASSIGNED, undefined, 'mockTaskId');
storeWrapper.removeTaskCallback(TASK_EVENTS.TASK_ASSIGNED, undefined, mockTask);
expect(mockTask.on).not.toHaveBeenCalledWith(TASK_EVENTS.TASK_ASSIGNED, mockCb);

storeWrapper.removeTaskCallback(TASK_EVENTS.TASK_ASSIGNED, mockCb, 'mockTaskI2');
storeWrapper.removeTaskCallback(TASK_EVENTS.TASK_ASSIGNED, mockCb, null);
expect(mockTask.on).not.toHaveBeenCalledWith(TASK_EVENTS.TASK_ASSIGNED, mockCb);
});

it('should remove task callback even when task is absent from store.taskList', () => {
const mockCb = jest.fn();
// Clear taskList so the task is not found by ID lookup
storeWrapper['store'].taskList = {};

storeWrapper.removeTaskCallback(TASK_EVENTS.TASK_ASSIGNED, mockCb, mockTask);
expect(mockTask.off).toHaveBeenCalledWith(TASK_EVENTS.TASK_ASSIGNED, mockCb);
});
});
});

Expand Down
Loading