Skip to content

Commit e48e3be

Browse files
committed
allow feedback form to be submitted without text
1 parent ebe5fac commit e48e3be

File tree

4 files changed

+114
-6
lines changed

4 files changed

+114
-6
lines changed
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<!doctype html>
2+
<html lang="en-US">
3+
<head>
4+
<link href="/assets/index.css" rel="stylesheet" type="text/css" />
5+
<script crossorigin="anonymous" src="https://unpkg.com/@babel/standalone@7.8.7/babel.min.js"></script>
6+
<script crossorigin="anonymous" src="https://unpkg.com/react@16.8.6/umd/react.production.min.js"></script>
7+
<script crossorigin="anonymous" src="https://unpkg.com/react-dom@16.8.6/umd/react-dom.production.min.js"></script>
8+
<script crossorigin="anonymous" src="/test-harness.js"></script>
9+
<script crossorigin="anonymous" src="/test-page-object.js"></script>
10+
<script crossorigin="anonymous" src="/__dist__/webchat-es5.js"></script>
11+
<script crossorigin="anonymous" src="/__dist__/botframework-webchat-fluent-theme.production.min.js"></script>
12+
</head>
13+
14+
<body>
15+
<main id="webchat"></main>
16+
<script type="text/babel">
17+
run(async function () {
18+
const {
19+
React,
20+
ReactDOM: { render },
21+
WebChat: { FluentThemeProvider, ReactWebChat }
22+
} = window; // Imports in UMD fashion.
23+
24+
const { directLine, store } = testHelpers.createDirectLineEmulator();
25+
26+
const App = () => <ReactWebChat directLine={directLine} store={store} />;
27+
28+
render(
29+
<FluentThemeProvider>
30+
<App />
31+
</FluentThemeProvider>,
32+
document.getElementById('webchat')
33+
);
34+
35+
await pageConditions.uiConnected();
36+
37+
await directLine.emulateIncomingActivity({
38+
type: 'message',
39+
id: 'a-00000',
40+
timestamp: 0,
41+
text: 'This is a test message to show feedback buttons',
42+
from: {
43+
role: 'bot'
44+
},
45+
locale: 'en-US',
46+
entities: [],
47+
channelData: {
48+
feedbackLoop: {
49+
type: 'default',
50+
disclaimer: 'This is a test disclaimer message'
51+
}
52+
}
53+
});
54+
55+
await pageConditions.numActivitiesShown(1);
56+
57+
pageElements.byTestId('send box text area').focus();
58+
await host.sendShiftTab(2);
59+
60+
await host.sendKeys('ENTER');
61+
await host.sendKeys('SPACE');
62+
63+
await pageConditions.became(
64+
'feedback form is open',
65+
() => document.activeElement === pageElements.byTestId('feedback sendbox'),
66+
1000
67+
);
68+
await host.snapshot('local');
69+
70+
const { activity } = await directLine.actPostActivity(async () => {
71+
await host.sendTab(1);
72+
await host.sendKeys('ENTER');
73+
});
74+
75+
expect(activity).toEqual(
76+
expect.objectContaining({
77+
type: 'invoke',
78+
name: 'message/submitAction',
79+
value: {
80+
actionName: 'feedback',
81+
actionValue: {
82+
reaction: 'like',
83+
feedback: {
84+
feedbackText: ''
85+
}
86+
}
87+
}
88+
})
89+
);
90+
91+
await expect(pageElements.byTestId('feedback sendbox')).toBeFalsy();
92+
93+
// Feedback button state should persist
94+
await host.snapshot('local');
95+
});
96+
</script>
97+
</body>
98+
</html>
26.8 KB
Loading
13.3 KB
Loading

packages/component/src/ActivityFeedback/providers/ActivityFeedbackComposer.tsx

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,13 @@ function ActivityFeedbackComposer(props: ActivityFeedbackComposerProps) {
4444

4545
const [{ clearTimeout, setTimeout }] = usePonyfill();
4646
const [feedbackText, setFeedbackText, feedbackTextRef] = useStateWithRef<string | undefined>();
47+
48+
const isFeedbackLoopEnabled = useMemo(() => hasFeedbackLoop(activityFromProps), [activityFromProps]);
49+
4750
const activity: WebChatActivity = useMemo(
4851
() =>
4952
// Force enable feedback loop until service fixed their issue.
50-
hasFeedbackLoop(activityFromProps)
53+
isFeedbackLoopEnabled
5154
? Object.freeze({
5255
...activityFromProps,
5356
entities: [
@@ -83,7 +86,7 @@ function ActivityFeedbackComposer(props: ActivityFeedbackComposerProps) {
8386
]
8487
})
8588
: activityFromProps,
86-
[activityFromProps]
89+
[activityFromProps, isFeedbackLoopEnabled]
8790
);
8891

8992
const activityRef = useRefFrom(activity);
@@ -219,16 +222,15 @@ function ActivityFeedbackComposer(props: ActivityFeedbackComposerProps) {
219222
const { current: feedbackText } = feedbackTextRef;
220223
const isLegacyAction = action['@type'] === 'VoteAction';
221224

222-
// TODO: We should update this to use W3C Hydra.1
223-
if (typeof feedbackText !== 'undefined') {
225+
if (isFeedbackLoopEnabled) {
224226
postActivity({
225227
name: 'message/submitAction',
226228
replyToId: activityRef.current.id,
227229
type: 'invoke',
228230
value: {
229231
actionName: 'feedback',
230232
actionValue: {
231-
feedback: { feedbackText },
233+
feedback: { feedbackText: feedbackText || '' },
232234
reaction: action['@type'] === 'LikeAction' ? 'like' : 'dislike'
233235
}
234236
}
@@ -241,7 +243,15 @@ function ActivityFeedbackComposer(props: ActivityFeedbackComposerProps) {
241243
} as any);
242244
}
243245
},
244-
[actionsRef, actionStateRef, activityRef, feedbackTextRef, postActivity, setActionStateWithRefresh]
246+
[
247+
actionsRef,
248+
actionStateRef,
249+
activityRef,
250+
feedbackTextRef,
251+
isFeedbackLoopEnabled,
252+
postActivity,
253+
setActionStateWithRefresh
254+
]
245255
);
246256

247257
const selectedAction = useMemo<OrgSchemaAction | undefined>(

0 commit comments

Comments
 (0)