Skip to content

Commit e71af65

Browse files
authored
fix(cc-digital-channels): get-theme-value-from-store (#625)
1 parent ddcd28d commit e71af65

7 files changed

Lines changed: 101 additions & 27 deletions

File tree

packages/contact-center/cc-digital-channels/src/digital-channels/DigitalChannelsComponent.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const DigitalChannelsComponent: React.FunctionComponent<DigitalChannelsComponent
2020
return `${conversationId}-${jwtToken.slice(-8)}-${dataCenter}`;
2121
}, [conversationId, jwtToken, dataCenter]);
2222

23-
const isDarkTheme = currentTheme === 'DARK';
23+
const isDarkTheme = currentTheme?.toUpperCase() === 'DARK';
2424

2525
return (
2626
<div>

packages/contact-center/cc-digital-channels/src/digital-channels/digital-channels.types.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,6 @@ export interface DigitalChannelsDataHookProps {
2222
};
2323
}
2424

25-
export interface DigitalChannelsProps {
26-
currentTheme?: string;
27-
}
28-
2925
export interface DigitalChannelsComponentProps {
3026
conversationId: string;
3127
jwtToken: string;

packages/contact-center/cc-digital-channels/src/digital-channels/index.tsx

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,17 @@ import {ErrorBoundary} from 'react-error-boundary';
55
import store from '@webex/cc-store';
66
import {useDigitalChannelsInit, useDigitalChannelsData} from '../helper';
77
import {DigitalChannelsComponent} from './DigitalChannelsComponent';
8-
import {DigitalChannelsProps} from './digital-channels.types';
98

10-
const DigitalChannelsInternal: React.FunctionComponent<DigitalChannelsProps> = observer(({currentTheme}) => {
11-
const {logger, currentTask, isDigitalChannelsInitialized, setDigitalChannelsInitialized, getAccessToken, dataCenter} =
12-
store;
9+
const DigitalChannelsInternal: React.FunctionComponent = observer(() => {
10+
const {
11+
logger,
12+
currentTask,
13+
isDigitalChannelsInitialized,
14+
setDigitalChannelsInitialized,
15+
getAccessToken,
16+
dataCenter,
17+
currentTheme,
18+
} = store;
1319

1420
// Fetch JWT token and conversation ID
1521
const {jwtToken, conversationId, hasError} = useDigitalChannelsData({
@@ -45,15 +51,15 @@ const DigitalChannelsInternal: React.FunctionComponent<DigitalChannelsProps> = o
4551
);
4652
});
4753

48-
const DigitalChannels: React.FunctionComponent<DigitalChannelsProps> = (props) => {
54+
const DigitalChannels: React.FunctionComponent = () => {
4955
return (
5056
<ErrorBoundary
5157
fallbackRender={() => <></>}
5258
onError={(error: Error) => {
5359
if (store.onErrorCallback) store.onErrorCallback('DigitalChannels', error);
5460
}}
5561
>
56-
<DigitalChannelsInternal {...props} />
62+
<DigitalChannelsInternal />
5763
</ErrorBoundary>
5864
);
5965
};

packages/contact-center/cc-digital-channels/tests/digital-channels/DigitalChannelsComponent.test.tsx

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,58 @@ describe('DigitalChannelsComponent', () => {
9292
expect(engageWidget).toHaveAttribute('data-conversation-id', 'test-conv-123');
9393
expect(engageWidget).toHaveAttribute('data-visual-rebrand', 'true');
9494
});
95+
96+
it('should render dark theme when currentTheme is lowercase "dark"', () => {
97+
const {container, getByTestId} = render(
98+
<DigitalChannelsComponent
99+
conversationId="conversation-id"
100+
jwtToken="jwt-token"
101+
dataCenter="produs1"
102+
currentTheme="dark"
103+
/>
104+
);
105+
106+
const mdTheme = container.querySelector('md-theme#app-theme');
107+
expect(mdTheme).toBeInTheDocument();
108+
expect(mdTheme).toHaveAttribute('darktheme');
109+
110+
const engageWidget = getByTestId('engage-widget');
111+
expect(engageWidget).toHaveAttribute('data-theme', 'dark');
112+
});
113+
114+
it('should render dark theme when currentTheme is mixed-case "Dark"', () => {
115+
const {container, getByTestId} = render(
116+
<DigitalChannelsComponent
117+
conversationId="conversation-id"
118+
jwtToken="jwt-token"
119+
dataCenter="produs1"
120+
currentTheme="Dark"
121+
/>
122+
);
123+
124+
const mdTheme = container.querySelector('md-theme#app-theme');
125+
expect(mdTheme).toBeInTheDocument();
126+
expect(mdTheme).toHaveAttribute('darktheme');
127+
128+
const engageWidget = getByTestId('engage-widget');
129+
expect(engageWidget).toHaveAttribute('data-theme', 'dark');
130+
});
131+
132+
it('should render light theme when currentTheme is lowercase "light"', () => {
133+
const {container, getByTestId} = render(
134+
<DigitalChannelsComponent
135+
conversationId="conversation-id"
136+
jwtToken="jwt-token"
137+
dataCenter="produs1"
138+
currentTheme="light"
139+
/>
140+
);
141+
142+
const mdTheme = container.querySelector('md-theme#app-theme');
143+
expect(mdTheme).toBeInTheDocument();
144+
expect(mdTheme).toHaveAttribute('lighttheme');
145+
146+
const engageWidget = getByTestId('engage-widget');
147+
expect(engageWidget).toHaveAttribute('data-theme', 'light');
148+
});
95149
});

packages/contact-center/cc-digital-channels/tests/digital-channels/index.tsx

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ jest.mock('@webex/cc-store', () => {
7070
currentTask = mockCurrentTaskWithConversationId;
7171
isDigitalChannelsInitialized = false;
7272
dataCenter = mockDataCenter;
73+
currentTheme = 'LIGHT';
7374
onErrorCallback = jest.fn();
7475

7576
constructor() {
@@ -85,6 +86,12 @@ jest.mock('@webex/cc-store', () => {
8586
});
8687
});
8788

89+
setCurrentTheme = jest.fn((theme: string) => {
90+
runInAction(() => {
91+
this.currentTheme = theme;
92+
});
93+
});
94+
8895
getAccessToken = jest.fn().mockResolvedValue(mockJwtToken);
8996
}
9097

@@ -94,7 +101,6 @@ jest.mock('@webex/cc-store', () => {
94101
import {DigitalChannels} from '../../src/digital-channels';
95102
import {mockTask as mockTaskFixture} from '@webex/test-fixtures';
96103

97-
const mockProps = {};
98104
let mockShouldThrow = false;
99105

100106
jest.mock('../../src/digital-channels/DigitalChannelsComponent', () => {
@@ -117,7 +123,7 @@ describe('DigitalChannels Component - Integration Tests with Real Components', (
117123
});
118124

119125
it('should successfully load and initialize real Engage component without errors', async () => {
120-
const screen = render(<DigitalChannels {...mockProps} />);
126+
const screen = render(<DigitalChannels />);
121127

122128
// Wait for the widget to be loaded in the DOM
123129
await waitFor(
@@ -155,8 +161,16 @@ describe('DigitalChannels Component - Integration Tests with Real Components', (
155161
expect(engageWidget).toHaveAttribute('data-visual-rebrand', 'true');
156162
});
157163

158-
it('should render with dark theme when currentTheme is DARK', async () => {
159-
const screen = render(<DigitalChannels currentTheme="DARK" />);
164+
it('should render with dark theme when currentTheme is DARK in store', async () => {
165+
// eslint-disable-next-line @typescript-eslint/no-require-imports
166+
const storeModule = require('@webex/cc-store');
167+
168+
// Set dark theme in store before rendering
169+
runInAction(() => {
170+
storeModule.default.currentTheme = 'DARK';
171+
});
172+
173+
const screen = render(<DigitalChannels />);
160174

161175
// Wait for the widget to be loaded in the DOM
162176
await waitFor(
@@ -179,6 +193,14 @@ describe('DigitalChannels Component - Integration Tests with Real Components', (
179193
const engageWidget = screen.getByTestId('engage-widget');
180194
expect(engageWidget).toBeInTheDocument();
181195
expect(engageWidget).toHaveAttribute('data-theme', 'dark');
196+
197+
// Unmount the component before resetting theme to avoid act() warning
198+
screen.unmount();
199+
200+
// Reset theme to default for other tests
201+
runInAction(() => {
202+
storeModule.default.currentTheme = 'LIGHT';
203+
});
182204
});
183205

184206
it('should have proper store integration', async () => {
@@ -194,7 +216,7 @@ describe('DigitalChannels Component - Integration Tests with Real Components', (
194216
expect(storeModule.default.onErrorCallback).toBeDefined();
195217

196218
// Component should be able to access store without issues
197-
const screen = render(<DigitalChannels {...mockProps} />);
219+
const screen = render(<DigitalChannels />);
198220

199221
// Wait for the widget to appear in the DOM, proving store integration works
200222
await waitFor(
@@ -231,7 +253,7 @@ describe('DigitalChannels Component - Integration Tests with Real Components', (
231253
});
232254
});
233255

234-
const screen = render(<DigitalChannels {...mockProps} />);
256+
const screen = render(<DigitalChannels />);
235257

236258
// Verify nothing is rendered when currentTask is null
237259
expect(screen.container.querySelector('md-theme')).toBeNull();
@@ -295,7 +317,7 @@ describe('DigitalChannels Component - Integration Tests with Real Components', (
295317
});
296318

297319
it('should not render', async () => {
298-
const screen = render(<DigitalChannels {...mockProps} />);
320+
const screen = render(<DigitalChannels />);
299321

300322
// Wait for any async updates to complete
301323
await waitFor(() => {
@@ -333,7 +355,7 @@ describe('DigitalChannels Component - Integration Tests with Real Components', (
333355
});
334356

335357
it('should not render', async () => {
336-
const screen = render(<DigitalChannels {...mockProps} />);
358+
const screen = render(<DigitalChannels />);
337359

338360
// Wait for any async updates to complete
339361
await waitFor(() => {
@@ -369,7 +391,7 @@ describe('DigitalChannels ErrorBoundary', () => {
369391

370392
mockShouldThrow = true;
371393

372-
const screen = render(<DigitalChannels {...mockProps} />);
394+
const screen = render(<DigitalChannels />);
373395

374396
await waitFor(() => {
375397
expect(onErrorCallback).toHaveBeenCalledWith('DigitalChannels', expect.any(Error));
@@ -392,7 +414,7 @@ describe('DigitalChannels ErrorBoundary', () => {
392414
mockShouldThrow = true;
393415

394416
// Render should not throw when onErrorCallback is undefined
395-
const screen = render(<DigitalChannels {...mockProps} />);
417+
const screen = render(<DigitalChannels />);
396418

397419
// Wait for error boundary to catch and handle the error
398420
await waitFor(() => {

packages/contact-center/cc-widgets/src/wc.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,7 @@ const WebCallControlCAD = r2wc(CallControlCAD, {
5454

5555
const WebOutdialCall = r2wc(OutdialCall, {});
5656

57-
const WebDigitalChannels = r2wc(DigitalChannels, {
58-
props: {
59-
currentTheme: 'string',
60-
},
61-
});
57+
const WebDigitalChannels = r2wc(DigitalChannels, {});
6258

6359
// Whenever there is a new component, add the name of the component
6460
// and the web-component to the components object

widgets-samples/cc/samples-cc-react-app/src/EngageWidget.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ const EngageWidget: React.FC<EngageWidgetProps> = ({currentTheme, isSdkReady}) =
7777
</div>
7878
<div className={`${CSS_CLASSES.CONTENT_AREA} ${themeClass}`}>
7979
{isSupportedTask && isSdkReady ? (
80-
<DigitalChannels currentTheme={currentTheme} />
80+
<DigitalChannels />
8181
) : (
8282
<div className={CSS_CLASSES.CONTENT_PLACEHOLDER}>
8383
{!isSdkReady ? MESSAGES.INITIALIZING : MESSAGES.NO_ACTIVE_TASKS}

0 commit comments

Comments
 (0)