Skip to content

Commit

Permalink
fix: scope use-propagate to a single Web Chat instance (#5248)
Browse files Browse the repository at this point in the history
* Add test

* fix: scope use-propagate to a single webchat instance

* Changelog

---------

Co-authored-by: William Wong <[email protected]>
  • Loading branch information
OEvgeny and compulim authored Aug 5, 2024
1 parent af6b947 commit c312f7f
Show file tree
Hide file tree
Showing 14 changed files with 166 additions and 82 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Notes: web developers are advised to use [`~` (tilde range)](https://github.com/
- Added missing support for chat history scroll with keyboard when Fluent send box is focused, in PR [#5191](https://github.com/microsoft/BotFramework-WebChat/pull/5191), by [@OEvgeny](https://github.com/OEvgeny)
- Fixed DTMF command usage sent by telephone keypad, in PR [#5198](https://github.com/microsoft/BotFramework-WebChat/pull/5198), by [@OEvgeny](https://github.com/OEvgeny)
- Fixed decorator import in legacy CommonJS environments, in [#5231](https://github.com/microsoft/BotFramework-WebChat/pull/5231), by [@OEvgeny](https://github.com/OEvgeny)
- Scoped `use-propagate` to individual WebChat instances to prevent interference between multiple instances, in PR [#5248](https://github.com/microsoft/BotFramework-WebChat/pull/5248), by [@OEvgeny](https://github.com/OEvgeny)

### Changed

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
121 changes: 121 additions & 0 deletions __tests__/html/fluentTheme/focusBack.multiple.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<!doctype html>
<html lang="en-US">
<head>
<link href="/assets/index.css" rel="stylesheet" type="text/css" />
<script crossorigin="anonymous" src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script crossorigin="anonymous" src="https://unpkg.com/[email protected]/umd/react.production.min.js"></script>
<script crossorigin="anonymous" src="https://unpkg.com/[email protected]/umd/react-dom.production.min.js"></script>
<script crossorigin="anonymous" src="/test-harness.js"></script>
<script crossorigin="anonymous" src="/test-page-object.js"></script>
<script crossorigin="anonymous" src="/__dist__/webchat-es5.js"></script>
<script crossorigin="anonymous" src="/__dist__/botframework-webchat-fluent-theme.production.min.js"></script>
<style>
#webchat {
display: flex;
width: 720px;
}
#webchat > * {
flex-basis: 50%;
}
</style>
</head>
<body>
<main id="webchat">
<div id="webchat1"></div>
<div id="webchat2"></div>
</main>
<script type="text/babel">
run(
async function () {
const {
React,
ReactDOM: { render },
WebChat: { FluentThemeProvider, ReactWebChat }
} = window; // Imports in UMD fashion.

await host.windowSize(720, 640, document.getElementById('webchat'));

const createWebChat = (id) => {
const { directLine, store } = testHelpers.createDirectLineEmulator();

const App = () => (
<ReactWebChat directLine={directLine} store={store} styleOptions={{ hideTelephoneKeypadButton: false }} />
);

render(
<FluentThemeProvider>
<App />
</FluentThemeProvider>,
document.getElementById(id)
);

return { directLine, store };
};

const webChat1 = createWebChat('webchat1');
const webChat2 = createWebChat('webchat2');

await pageConditions.uiConnected();

// Test WebChat 1
await webChat1.directLine.emulateIncomingActivity(
'WebChat 1: Eiusmod anim adipisicing cupidatat adipisicing officia sint qui consequat veniam id aute.'
);

await pageConditions.numActivitiesShown(1);

document.querySelector(`#webchat1 [data-testid="${WebChat.testIds.sendBoxTextBox}"]`).focus();

// WHEN: SHIFT-TAB key is pressed on WebChat 1.
await host.sendShiftTab();

// THEN: Should focus on the chat history of WebChat 1.
await host.snapshot();

// WHEN: A key is pressed on WebChat 1.
await host.sendKeys('WebChat 1: The quick brown fox jumps over the lazy dog');

// THEN: Should focus on the SendBox of WebChat 1
await host.snapshot();

await (await webChat1.directLine.actPostActivity(() => host.sendKeys('\n'))).resolveAll();

// THEN: Should send the activity in WebChat 1.
await pageConditions.numActivitiesShown(2);
await pageConditions.allOutgoingActivitiesSent();
await host.snapshot();

// Test WebChat 2
await webChat2.directLine.emulateIncomingActivity(
'WebChat 2: Eiusmod anim adipisicing cupidatat adipisicing officia sint qui consequat veniam id aute.'
);

document.querySelector(`#webchat2 [data-testid="${WebChat.testIds.sendBoxTextBox}"]`).focus();

// WHEN: SHIFT-TAB key is pressed on WebChat 2.
await host.sendShiftTab();

// THEN: Should focus on the chat history of WebChat 2.
await host.snapshot();

// WHEN: A key is pressed on WebChat 2.
await host.sendKeys('WebChat 2: The quick brown fox jumps over the lazy dog');

// THEN: Should focus on the SendBox of WebChat 2
await host.snapshot();

await (await webChat2.directLine.actPostActivity(() => host.sendKeys('\n'))).resolveAll();

// THEN: Should send the activity in WebChat 2.
await pageConditions.allOutgoingActivitiesSent();
await host.snapshot();
},
// TODO: unskip and try ShadowDOM when we get support
{ skipCheckAccessibility: true }
);
// TODO: unskip and try ShadowDOM when we get support
// TODO: fix checkAccessibility throws even if skipped
window.checkAccessibility = async () => {}
</script>
</body>
</html>
5 changes: 5 additions & 0 deletions __tests__/html/fluentTheme/focusBack.multiple.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/** @jest-environment ./packages/test/harness/src/host/jest/WebDriverEnvironment.js */

describe('Fluent theme applied with multiple WebChat instances', () => {
test('places focus back', () => runHTML('fluentTheme/focusBack.multiple'));
});
78 changes: 11 additions & 67 deletions packages/component/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/component/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@
"react-scroll-to-bottom": "4.2.0",
"redux": "5.0.1",
"simple-update-in": "2.2.0",
"use-propagate": "0.1.0",
"use-propagate": "^0.2.0-main.fb24772",
"use-ref-from": "0.1.0",
"valibot": "0.30.0"
},
Expand Down
24 changes: 15 additions & 9 deletions packages/component/src/Composer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ import addTargetBlankToHyperlinksMarkdown from './Utils/addTargetBlankToHyperlin
import createCSSKey from './Utils/createCSSKey';
import downscaleImageToDataURL from './Utils/downscaleImageToDataURL';
import mapMap from './Utils/mapMap';
import { FocusSendBoxScope } from './hooks/sendBoxFocus';
import { ScrollRelativeTranscriptScope } from './hooks/transcriptScrollRelative';

const { useGetActivityByKey, useReferenceGrammarID, useStyleOptions } = hooks;

Expand All @@ -72,15 +74,19 @@ const ComposerCoreUI = memo(({ children }: ComposerCoreUIProps) => {

return (
<div className={classNames('webchat__css-custom-properties', cssCustomProperties)}>
<DecoratorComposer>
<ModalDialogComposer>
{/* When <SendBoxComposer> is finalized, it will be using an independent instance that lives inside <BasicSendBox>. */}
<SendBoxComposer>
{children}
<Dictation onError={dictationOnError} />
</SendBoxComposer>
</ModalDialogComposer>
</DecoratorComposer>
<FocusSendBoxScope>
<ScrollRelativeTranscriptScope>
<DecoratorComposer>
<ModalDialogComposer>
{/* When <SendBoxComposer> is finalized, it will be using an independent instance that lives inside <BasicSendBox>. */}
<SendBoxComposer>
{children}
<Dictation onError={dictationOnError} />
</SendBoxComposer>
</ModalDialogComposer>
</DecoratorComposer>
</ScrollRelativeTranscriptScope>
</FocusSendBoxScope>
</div>
);
});
Expand Down
8 changes: 6 additions & 2 deletions packages/component/src/hooks/sendBoxFocus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import { createPropagation } from 'use-propagate';

export type SendBoxFocusOptions = WaitUntilable<{ noKeyboard: boolean }>;

const { useListen: useRegisterFocusSendBox, usePropagate: useFocusSendBox } = createPropagation<SendBoxFocusOptions>();
const {
PropagationScope: FocusSendBoxScope,
useListen: useRegisterFocusSendBox,
usePropagate: useFocusSendBox
} = createPropagation<SendBoxFocusOptions>();

export { useRegisterFocusSendBox, useFocusSendBox };
export { FocusSendBoxScope, useRegisterFocusSendBox, useFocusSendBox };
9 changes: 6 additions & 3 deletions packages/component/src/hooks/transcriptScrollRelative.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import { createPropagation } from 'use-propagate';

export type TranscriptScrollRelativeOptions = { direction: 'down' | 'up'; displacement?: number };

const { useListen: useRegisterScrollRelativeTranscript, usePropagate: useScrollRelativeTranscript } =
createPropagation<TranscriptScrollRelativeOptions>();
const {
PropagationScope: ScrollRelativeTranscriptScope,
useListen: useRegisterScrollRelativeTranscript,
usePropagate: useScrollRelativeTranscript
} = createPropagation<TranscriptScrollRelativeOptions>();

export { useRegisterScrollRelativeTranscript, useScrollRelativeTranscript };
export { ScrollRelativeTranscriptScope, useRegisterScrollRelativeTranscript, useScrollRelativeTranscript };

0 comments on commit c312f7f

Please sign in to comment.