diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ddaeea4cc..d9578fa0a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Added + +- Resolves [#3205](https://github.com/microsoft/BotFramework-WebChat/issues/3205). Added Direct Line App Service Extension protocol, by [@compulim](https://github.com/compulim) in PR [#3206](https://github.com/microsoft/BotFramework-WebChat/pull/3206) + ### Fixed - Fixes [#1340](https://github.com/microsoft/BotFramework-WebChat/issues/1340). Card container should not be focusable if they do not have `tapAction`, by [@compulim](https://github.compulim) in PR [#3193](https://github.com/microsoft/BotFramework-WebChat/issues/3193) @@ -42,6 +46,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - [`p-defer-es5@1.1.0`](https://npmjs.com/package/p-defer-es5) - [`web-speech-cognitive-services@7.0.0`](https://npmjs.com/package/web-speech-cognitive-services) - Updated localization strings for Estonian (Estonia) (`et-EE`), by [@LiweiMa](https://github.com/LiweiMa) in PR [#3183](https://github.com/microsoft/BotFramework-WebChat/pull/3183) +- Bumped [`botframework-directlinejs@0.12.0`](https://npmjs.com/package/botframework-directlinejs), by [@compulim](https://github.com/compulim) in PR [#3206](https://github.com/microsoft/BotFramework-WebChat/pull/3206) + +### Samples + +- Resolves [#3205](https://github.com/microsoft/BotFramework-WebChat/issues/3205). Added [Direct Line App Service Extension chat adapter](https://microsoft.github.io/BotFramework-WebChat/01.getting-started/i.protocol-direct-line-app-service-extension) sample, by [@compulim](https://github.com/compulim) in PR [#3206](https://github.com/microsoft/BotFramework-WebChat/pull/3206) ## [4.9.0] - 2020-05-11 diff --git a/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-display-network-interruption-occurred-reconnecting-status-when-connection-is-interrupted-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-display-network-interruption-occurred-reconnecting-status-when-connection-is-interrupted-1-snap.png deleted file mode 100644 index 994e348e02..0000000000 Binary files a/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-display-network-interruption-occurred-reconnecting-status-when-connection-is-interrupted-1-snap.png and /dev/null differ diff --git a/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-display-send-failed-retry-when-activity-is-not-able-to-send-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-display-send-failed-retry-when-activity-is-not-able-to-send-1-snap.png deleted file mode 100644 index 1a3ad8a5b1..0000000000 Binary files a/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-display-send-failed-retry-when-activity-is-not-able-to-send-1-snap.png and /dev/null differ diff --git a/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-display-send-failed-retry-when-activity-is-sent-but-not-acknowledged-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-display-send-failed-retry-when-activity-is-sent-but-not-acknowledged-1-snap.png deleted file mode 100644 index 57ada3ab80..0000000000 Binary files a/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-display-send-failed-retry-when-activity-is-sent-but-not-acknowledged-1-snap.png and /dev/null differ diff --git a/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-display-the-connecting-connectivity-status-when-connecting-for-the-first-time-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-display-the-connecting-connectivity-status-when-connecting-for-the-first-time-1-snap.png deleted file mode 100644 index 23149752c6..0000000000 Binary files a/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-display-the-connecting-connectivity-status-when-connecting-for-the-first-time-1-snap.png and /dev/null differ diff --git a/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-show-render-error-connectivity-status-when-a-java-script-error-is-present-in-the-code-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-show-render-error-connectivity-status-when-a-java-script-error-is-present-in-the-code-1-snap.png deleted file mode 100644 index df0e6f87a2..0000000000 Binary files a/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-show-render-error-connectivity-status-when-a-java-script-error-is-present-in-the-code-1-snap.png and /dev/null differ diff --git a/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-show-taking-longer-than-usual-to-connect-ui-when-connection-is-slow-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-show-taking-longer-than-usual-to-connect-ui-when-connection-is-slow-1-snap.png deleted file mode 100644 index af4b745ed1..0000000000 Binary files a/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-show-taking-longer-than-usual-to-connect-ui-when-connection-is-slow-1-snap.png and /dev/null differ diff --git a/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-show-taking-longer-than-usual-to-connect-ui-when-connection-is-slow-2-snap.png b/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-show-taking-longer-than-usual-to-connect-ui-when-connection-is-slow-2-snap.png deleted file mode 100644 index ed8f2ce9d6..0000000000 Binary files a/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-show-taking-longer-than-usual-to-connect-ui-when-connection-is-slow-2-snap.png and /dev/null differ diff --git a/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-show-taking-longer-than-usual-to-connect-ui-when-connection-is-slow-3-snap.png b/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-show-taking-longer-than-usual-to-connect-ui-when-connection-is-slow-3-snap.png deleted file mode 100644 index 46764de275..0000000000 Binary files a/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-show-taking-longer-than-usual-to-connect-ui-when-connection-is-slow-3-snap.png and /dev/null differ diff --git a/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-show-taking-longer-than-usual-to-connect-ui-when-reconnection-is-slow-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-show-taking-longer-than-usual-to-connect-ui-when-reconnection-is-slow-1-snap.png deleted file mode 100644 index af4b745ed1..0000000000 Binary files a/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-show-taking-longer-than-usual-to-connect-ui-when-reconnection-is-slow-1-snap.png and /dev/null differ diff --git a/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-show-unable-to-connect-ui-when-credentials-are-incorrect-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-show-unable-to-connect-ui-when-credentials-are-incorrect-1-snap.png deleted file mode 100644 index baaaf24ac0..0000000000 Binary files a/__tests__/__image_snapshots__/chrome-docker/offline-ui-js-offline-ui-should-show-unable-to-connect-ui-when-credentials-are-incorrect-1-snap.png and /dev/null differ diff --git a/__tests__/__image_snapshots__/chrome-docker/timestamp-js-change-send-timeout-on-the-fly-2-snap.png b/__tests__/__image_snapshots__/chrome-docker/timestamp-js-change-send-timeout-on-the-fly-2-snap.png deleted file mode 100644 index 5dc4c4f0e8..0000000000 Binary files a/__tests__/__image_snapshots__/chrome-docker/timestamp-js-change-send-timeout-on-the-fly-2-snap.png and /dev/null differ diff --git a/__tests__/__image_snapshots__/chrome-docker/timestamp-js-send-timeout-for-attachment-should-be-different-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/timestamp-js-send-timeout-for-attachment-should-be-different-1-snap.png deleted file mode 100644 index 9e8805139f..0000000000 Binary files a/__tests__/__image_snapshots__/chrome-docker/timestamp-js-send-timeout-for-attachment-should-be-different-1-snap.png and /dev/null differ diff --git a/__tests__/__image_snapshots__/chrome-docker/timestamp-js-send-timeout-for-attachment-should-be-different-2-snap.png b/__tests__/__image_snapshots__/chrome-docker/timestamp-js-send-timeout-for-attachment-should-be-different-2-snap.png deleted file mode 100644 index 9e8805139f..0000000000 Binary files a/__tests__/__image_snapshots__/chrome-docker/timestamp-js-send-timeout-for-attachment-should-be-different-2-snap.png and /dev/null differ diff --git a/__tests__/__image_snapshots__/chrome-docker/timestamp-js-send-timeout-for-attachment-should-be-different-3-snap.png b/__tests__/__image_snapshots__/chrome-docker/timestamp-js-send-timeout-for-attachment-should-be-different-3-snap.png deleted file mode 100644 index a8213532b8..0000000000 Binary files a/__tests__/__image_snapshots__/chrome-docker/timestamp-js-send-timeout-for-attachment-should-be-different-3-snap.png and /dev/null differ diff --git a/__tests__/__image_snapshots__/chrome-docker/timestamp-js-send-timeout-for-attachment-should-be-different-4-snap.png b/__tests__/__image_snapshots__/chrome-docker/timestamp-js-send-timeout-for-attachment-should-be-different-4-snap.png deleted file mode 100644 index 9e8805139f..0000000000 Binary files a/__tests__/__image_snapshots__/chrome-docker/timestamp-js-send-timeout-for-attachment-should-be-different-4-snap.png and /dev/null differ diff --git a/__tests__/__image_snapshots__/html/chat-adapter-direct-line-app-service-extension-js-direct-line-app-service-service-chat-adapter-should-connect-to-the-mock-bot-1-snap.png b/__tests__/__image_snapshots__/html/chat-adapter-direct-line-app-service-extension-js-direct-line-app-service-service-chat-adapter-should-connect-to-the-mock-bot-1-snap.png new file mode 100644 index 0000000000..a93a8949f2 Binary files /dev/null and b/__tests__/__image_snapshots__/html/chat-adapter-direct-line-app-service-extension-js-direct-line-app-service-service-chat-adapter-should-connect-to-the-mock-bot-1-snap.png differ diff --git a/__tests__/__image_snapshots__/html/speech-recognition-simple-js-speech-recognition-using-authorization-token-with-direct-line-speech-protocol-should-recognize-hello-world-1-snap.png b/__tests__/__image_snapshots__/html/speech-recognition-simple-js-speech-recognition-using-authorization-token-with-direct-line-speech-protocol-should-recognize-hello-world-1-snap.png index 5cfa1ec52a..2606098a4d 100644 Binary files a/__tests__/__image_snapshots__/html/speech-recognition-simple-js-speech-recognition-using-authorization-token-with-direct-line-speech-protocol-should-recognize-hello-world-1-snap.png and b/__tests__/__image_snapshots__/html/speech-recognition-simple-js-speech-recognition-using-authorization-token-with-direct-line-speech-protocol-should-recognize-hello-world-1-snap.png differ diff --git a/__tests__/__image_snapshots__/html/timestamp-attachment-send-timeout-js-timestamp-send-timeout-for-attachment-should-be-different-1-snap.png b/__tests__/__image_snapshots__/html/timestamp-attachment-send-timeout-js-timestamp-send-timeout-for-attachment-should-be-different-1-snap.png new file mode 100644 index 0000000000..498592a934 Binary files /dev/null and b/__tests__/__image_snapshots__/html/timestamp-attachment-send-timeout-js-timestamp-send-timeout-for-attachment-should-be-different-1-snap.png differ diff --git a/__tests__/__image_snapshots__/html/timestamp-attachment-send-timeout-js-timestamp-send-timeout-for-attachment-should-be-different-2-snap.png b/__tests__/__image_snapshots__/html/timestamp-attachment-send-timeout-js-timestamp-send-timeout-for-attachment-should-be-different-2-snap.png new file mode 100644 index 0000000000..498592a934 Binary files /dev/null and b/__tests__/__image_snapshots__/html/timestamp-attachment-send-timeout-js-timestamp-send-timeout-for-attachment-should-be-different-2-snap.png differ diff --git a/__tests__/__image_snapshots__/html/timestamp-attachment-send-timeout-js-timestamp-send-timeout-for-attachment-should-be-different-3-snap.png b/__tests__/__image_snapshots__/html/timestamp-attachment-send-timeout-js-timestamp-send-timeout-for-attachment-should-be-different-3-snap.png new file mode 100644 index 0000000000..16ce2a8794 Binary files /dev/null and b/__tests__/__image_snapshots__/html/timestamp-attachment-send-timeout-js-timestamp-send-timeout-for-attachment-should-be-different-3-snap.png differ diff --git a/__tests__/__image_snapshots__/html/timestamp-attachment-send-timeout-js-timestamp-send-timeout-for-attachment-should-be-different-4-snap.png b/__tests__/__image_snapshots__/html/timestamp-attachment-send-timeout-js-timestamp-send-timeout-for-attachment-should-be-different-4-snap.png new file mode 100644 index 0000000000..498592a934 Binary files /dev/null and b/__tests__/__image_snapshots__/html/timestamp-attachment-send-timeout-js-timestamp-send-timeout-for-attachment-should-be-different-4-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/timestamp-js-change-send-timeout-on-the-fly-3-snap.png b/__tests__/__image_snapshots__/html/timestamp-change-send-timeout-js-timestamp-change-send-timeout-on-the-fly-1-snap.png similarity index 100% rename from __tests__/__image_snapshots__/chrome-docker/timestamp-js-change-send-timeout-on-the-fly-3-snap.png rename to __tests__/__image_snapshots__/html/timestamp-change-send-timeout-js-timestamp-change-send-timeout-on-the-fly-1-snap.png diff --git a/__tests__/__image_snapshots__/html/timestamp-change-send-timeout-js-timestamp-change-send-timeout-on-the-fly-2-snap.png b/__tests__/__image_snapshots__/html/timestamp-change-send-timeout-js-timestamp-change-send-timeout-on-the-fly-2-snap.png new file mode 100644 index 0000000000..983c60c251 Binary files /dev/null and b/__tests__/__image_snapshots__/html/timestamp-change-send-timeout-js-timestamp-change-send-timeout-on-the-fly-2-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/timestamp-js-change-send-timeout-on-the-fly-1-snap.png b/__tests__/__image_snapshots__/html/timestamp-change-send-timeout-js-timestamp-change-send-timeout-on-the-fly-3-snap.png similarity index 96% rename from __tests__/__image_snapshots__/chrome-docker/timestamp-js-change-send-timeout-on-the-fly-1-snap.png rename to __tests__/__image_snapshots__/html/timestamp-change-send-timeout-js-timestamp-change-send-timeout-on-the-fly-3-snap.png index 36d65dec70..5c74f84bf0 100644 Binary files a/__tests__/__image_snapshots__/chrome-docker/timestamp-js-change-send-timeout-on-the-fly-1-snap.png and b/__tests__/__image_snapshots__/html/timestamp-change-send-timeout-js-timestamp-change-send-timeout-on-the-fly-3-snap.png differ diff --git a/__tests__/html/__jest__/WebChatEnvironment.js b/__tests__/html/__jest__/WebChatEnvironment.js index 4f753831ae..729ad27f2a 100644 --- a/__tests__/html/__jest__/WebChatEnvironment.js +++ b/__tests__/html/__jest__/WebChatEnvironment.js @@ -22,7 +22,7 @@ class WebChatEnvironment extends NodeEnvironment { this.global.abortSignal = signal; - if (this.global.docker) { + if (!this.global.docker) { const { port } = await hostServe(signal, { ...serveJSON, public: '.' diff --git a/__tests__/html/__jest__/setupRunHTMLTest.js b/__tests__/html/__jest__/setupRunHTMLTest.js index 9f3c7aa7d8..2b009352cf 100644 --- a/__tests__/html/__jest__/setupRunHTMLTest.js +++ b/__tests__/html/__jest__/setupRunHTMLTest.js @@ -26,7 +26,7 @@ global.runHTMLTest = async ( .build() : builder .forBrowser('chrome') - .usingServer('http://localhost:9515/') + .usingServer('http://localhost:9515') .setChromeOptions(chromeOptions) .build(); @@ -81,12 +81,12 @@ global.runHTMLTest = async ( } finally { // Using JSON Wire Protocol to kill Web Driver. // This is more reliable because Selenium package queue commands. - const res = await fetch(`http://localhost:4444/wd/hub/session/${sessionId}`, { method: 'DELETE' }); + const res = await fetch(`${builder.getServerUrl()}/session/${sessionId}`, { method: 'DELETE' }); if (!res.ok) { const json = await res.json(); - throw new Error(`Failed to kill WebDriver session ${sessionId}.\n\n${json && json.value && json.value.message}`); + console.warn(`Failed to kill WebDriver session ${sessionId}.\n\n${json && json.value && json.value.message}`); } } }; diff --git a/__tests__/html/chatAdapter.directLineAppServiceExtension.html b/__tests__/html/chatAdapter.directLineAppServiceExtension.html new file mode 100644 index 0000000000..d6f3e229bd --- /dev/null +++ b/__tests__/html/chatAdapter.directLineAppServiceExtension.html @@ -0,0 +1,37 @@ + + + + + + + +
+ + + diff --git a/__tests__/html/chatAdapter.directLineAppServiceExtension.js b/__tests__/html/chatAdapter.directLineAppServiceExtension.js new file mode 100644 index 0000000000..233b92bc44 --- /dev/null +++ b/__tests__/html/chatAdapter.directLineAppServiceExtension.js @@ -0,0 +1,7 @@ +/** + * @jest-environment ./__tests__/html/__jest__/WebChatEnvironment.js + */ + +describe('Direct Line App Service Service chat adapter', () => { + test('should connect to the MockBot.', () => runHTMLTest('chatAdapter.directLineAppServiceExtension.html')); +}); diff --git a/__tests__/html/offlineUI.fatalError.js b/__tests__/html/offlineUI.fatalError.js index 110ba65ac3..0dbfc4115c 100644 --- a/__tests__/html/offlineUI.fatalError.js +++ b/__tests__/html/offlineUI.fatalError.js @@ -4,5 +4,5 @@ describe('offline UI', () => { test('should show "Render error" connectivity status when a JavaScript error is present in the code.', () => - runHTMLTest('offlineUI.fatalError.html', { ignoreConsoleError: true })); + runHTMLTest('offlineUI.fatalError.html', { ignoreConsoleError: true, ignorePageError: true })); }); diff --git a/__tests__/html/offlineUI.invalidCredentials.html b/__tests__/html/offlineUI.invalidCredentials.html index 351f4f99fb..82c744e6f5 100644 --- a/__tests__/html/offlineUI.invalidCredentials.html +++ b/__tests__/html/offlineUI.invalidCredentials.html @@ -7,12 +7,37 @@
diff --git a/__tests__/html/offlineUI.invalidCredentials.js b/__tests__/html/offlineUI.invalidCredentials.js index 11f7c126a3..c2f3f563a7 100644 --- a/__tests__/html/offlineUI.invalidCredentials.js +++ b/__tests__/html/offlineUI.invalidCredentials.js @@ -4,5 +4,5 @@ describe('offline UI', () => { test('should show "unable to connect" UI when credentials are incorrect', () => - runHTMLTest('offlineUI.invalidCredentials.html')); + runHTMLTest('offlineUI.invalidCredentials.html', { ignorePageError: true })); }); diff --git a/__tests__/html/offlineUI.sendFailed.noAck.html b/__tests__/html/offlineUI.sendFailed.noAck.html index 48e81e7fd3..0b49254600 100644 --- a/__tests__/html/offlineUI.sendFailed.noAck.html +++ b/__tests__/html/offlineUI.sendFailed.noAck.html @@ -9,53 +9,57 @@ + + + +
+ + + diff --git a/__tests__/html/timestamp.attachmentSendTimeout.js b/__tests__/html/timestamp.attachmentSendTimeout.js new file mode 100644 index 0000000000..59e2febefc --- /dev/null +++ b/__tests__/html/timestamp.attachmentSendTimeout.js @@ -0,0 +1,7 @@ +/** + * @jest-environment ./__tests__/html/__jest__/WebChatEnvironment.js + */ + +describe('timestamp', () => { + test('send timeout for attachment should be different', () => runHTMLTest('timestamp.attachmentSendTimeout.html')); +}); diff --git a/__tests__/html/timestamp.changeSendTimeout.html b/__tests__/html/timestamp.changeSendTimeout.html new file mode 100644 index 0000000000..c10b5a6ebf --- /dev/null +++ b/__tests__/html/timestamp.changeSendTimeout.html @@ -0,0 +1,114 @@ + + + + + + + +
+ + + diff --git a/__tests__/html/timestamp.changeSendTimeout.js b/__tests__/html/timestamp.changeSendTimeout.js new file mode 100644 index 0000000000..a169e1839c --- /dev/null +++ b/__tests__/html/timestamp.changeSendTimeout.js @@ -0,0 +1,7 @@ +/** + * @jest-environment ./__tests__/html/__jest__/WebChatEnvironment.js + */ + +describe('timestamp', () => { + test('change send timeout on-the-fly', () => runHTMLTest('timestamp.changeSendTimeout.html')); +}); diff --git a/__tests__/offlineUI.js b/__tests__/offlineUI.js deleted file mode 100644 index c56d55f4de..0000000000 --- a/__tests__/offlineUI.js +++ /dev/null @@ -1,410 +0,0 @@ -import { Condition } from 'selenium-webdriver'; - -import { imageSnapshotOptions, timeouts } from './constants.json'; -import actionDispatched from './setup/conditions/actionDispatched'; -import connectivityStatusShown from './setup/conditions/connectivityStatusShown'; -import minNumActivitiesShown from './setup/conditions/minNumActivitiesShown'; -import staticSpinner from './setup/assets/staticSpinner'; -import uiConnected from './setup/conditions/uiConnected'; - -// selenium-webdriver API doc: -// https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/index_exports_WebDriver.html - -jest.setTimeout(timeouts.test); - -const allOutgoingMessagesFailed = new Condition('All outgoing messages to fail sending', driver => { - return driver.executeScript(() => { - const { store } = window.WebChatTest; - const { activities } = store.getState(); - - return activities - .filter(({ from: { role }, type }) => role === 'user' && type === 'message') - .every(({ channelData: { state } }) => state === 'send failed'); - }); -}); - -describe('offline UI', () => { - test('should show "Taking longer than usual to connect" UI when connection is slow', async () => { - const initialProps = { styleOptions: { spinnerAnimationBackgroundImage: staticSpinner } }; - const { driver, pageObjects } = await setupWebDriver({ - createDirectLine: options => { - // This part of code is running in the JavaScript VM in Chromium. - // This variable must be declared within scope - const ONLINE = 2; - - const workingDirectLine = window.WebChat.createDirectLine(options); - - return { - activity$: workingDirectLine.activity$, - postActivity: workingDirectLine.postActivity.bind(workingDirectLine), - - connectionStatus$: new Observable(observer => { - const subscription = workingDirectLine.connectionStatus$.subscribe({ - complete: () => observer.complete(), - error: err => observer.error(err), - next: connectionStatus => { - connectionStatus !== ONLINE && observer.next(connectionStatus); - } - }); - - return () => subscription.unsubscribe(); - }) - }; - }, - pingBotOnLoad: false, - props: initialProps, - setup: () => - Promise.all([ - window.WebChatTest.loadScript('https://unpkg.com/core-js@2.6.3/client/core.min.js'), - window.WebChatTest.loadScript('https://unpkg.com/lolex@4.0.1/lolex.js') - ]).then(() => { - window.WebChatTest.clock = lolex.install(); - }) - }); - - await driver.executeScript(() => { - window.WebChatTest.clock.tick(15000); - }); - - await driver.wait(actionDispatched('DIRECT_LINE/CONNECT_STILL_PENDING'), timeouts.directLine); - await driver.wait(connectivityStatusShown(/taking longer than usual/iu), timeouts.ui); - - expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); - - await pageObjects.updateProps({ - ...initialProps, - styleOptions: { - ...initialProps.styleOptions, - slowConnectionAfter: 20000 - } - }); - - await driver.wait(connectivityStatusShown(/connecting/iu), timeouts.ui); - expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); - - await driver.executeScript(() => { - window.WebChatTest.clock.tick(5000); - }); - - await driver.wait(connectivityStatusShown(/taking longer than usual/iu), timeouts.ui); - expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); - }); - - test('should show "unable to connect" UI when credentials are incorrect', async () => { - const { driver } = await setupWebDriver({ - createDirectLine: () => { - return window.WebChat.createDirectLine({ token: 'INVALID-TOKEN' }); - }, - pingBotOnLoad: false, - setup: () => - new Promise(resolve => { - const scriptElement = document.createElement('script'); - - scriptElement.onload = resolve; - scriptElement.setAttribute('src', 'https://unpkg.com/core-js@2.6.3/client/core.min.js'); - - document.head.appendChild(scriptElement); - }) - }); - - await driver.wait(async driver => { - return await driver.executeScript( - () => !!~window.WebChatTest.actions.findIndex(({ type }) => type === 'DIRECT_LINE/CONNECT_REJECTED') - ); - }, timeouts.directLine); - - const base64PNG = await driver.takeScreenshot(); - - expect(base64PNG).toMatchImageSnapshot(imageSnapshotOptions); - }); - - test('should display "Send failed. Retry" when activity is not able to send', async () => { - const { driver, pageObjects } = await setupWebDriver({ - createDirectLine: options => { - const workingDirectLine = window.WebChat.createDirectLine(options); - - return { - activity$: workingDirectLine.activity$, - connectionStatus$: workingDirectLine.connectionStatus$, - postActivity: activity => { - if (activity.type === 'message') { - return new Observable(({ error }) => error(new Error('artificial error'))); - } else { - return workingDirectLine.postActivity(activity); - } - } - }; - }, - setup: () => - Promise.all([ - window.WebChatTest.loadScript('https://unpkg.com/core-js@2.6.3/client/core.min.js'), - window.WebChatTest.loadScript('https://unpkg.com/lolex@4.0.1/lolex.js') - ]).then(() => { - window.WebChatTest.clock = lolex.install(); - }) - }); - - await driver.executeScript(() => window.WebChatTest.clock.tick(400)); - await driver.wait(uiConnected(), timeouts.directLine); - - await pageObjects.sendMessageViaSendBox('42', { waitForSend: false }); - - await driver.executeScript(() => window.WebChatTest.clock.tick(20000)); - await driver.wait(allOutgoingMessagesFailed, timeouts.postActivity); - - const base64PNG = await driver.takeScreenshot(); - - expect(base64PNG).toMatchImageSnapshot(imageSnapshotOptions); - }); - - test('should display "Send failed. Retry" when activity is sent but not acknowledged', async () => { - const { driver, pageObjects } = await setupWebDriver({ - createDirectLine: options => { - const workingDirectLine = window.WebChat.createDirectLine(options); - const bannedClientActivityIDs = []; - - return { - activity$: new Observable(observer => { - const subscription = workingDirectLine.activity$.subscribe({ - complete: () => observer.complete(), - error: err => observer.error(err), - next: activity => { - const { channelData: { clientActivityID } = {} } = activity; - - !bannedClientActivityIDs.includes(clientActivityID) && observer.next(activity); - } - }); - - return () => subscription.unsubscribe(); - }), - connectionStatus$: workingDirectLine.connectionStatus$, - postActivity: activity => { - const { - channelData: { clientActivityID }, - type - } = activity; - - type === 'message' && bannedClientActivityIDs.push(clientActivityID); - - return workingDirectLine.postActivity(activity); - } - }; - }, - setup: () => - Promise.all([ - window.WebChatTest.loadScript('https://unpkg.com/core-js@2.6.3/client/core.min.js'), - window.WebChatTest.loadScript('https://unpkg.com/lolex@4.0.1/lolex.js') - ]).then(() => { - window.WebChatTest.clock = lolex.install(); - }) - }); - - await driver.executeScript(() => window.WebChatTest.clock.tick(400)); - await driver.wait(uiConnected(), timeouts.directLine); - - await pageObjects.sendMessageViaSendBox('42', { waitForSend: false }); - - await driver.executeScript(() => window.WebChatTest.clock.tick(20000)); - await driver.wait(allOutgoingMessagesFailed, timeouts.postActivity); - await driver.wait(minNumActivitiesShown(2), timeouts.postActivity); - - const base64PNG = await driver.takeScreenshot(); - - expect(base64PNG).toMatchImageSnapshot(imageSnapshotOptions); - }); - - test('should display the "Connecting..." connectivity status when connecting for the first time', async () => { - const WEB_CHAT_PROPS = { styleOptions: { spinnerAnimationBackgroundImage: staticSpinner } }; - - const { driver } = await setupWebDriver({ - createDirectLine: options => { - // This part of code is running in the JavaScript VM in Chromium. - // This Direct Line Connection Status variable must be declared within scope - const UNINITIALIZED = 0; - - const workingDirectLine = window.WebChat.createDirectLine(options); - - return { - activity$: workingDirectLine.activity$, - postActivity: workingDirectLine.postActivity.bind(workingDirectLine), - - connectionStatus$: new Observable(observer => { - const subscription = workingDirectLine.connectionStatus$.subscribe({ - complete: () => observer.complete(), - error: err => observer.error(err), - next: connectionStatus => { - connectionStatus === UNINITIALIZED && observer.next(connectionStatus); - } - }); - - return () => subscription.unsubscribe(); - }) - }; - }, - pingBotOnLoad: false, - props: WEB_CHAT_PROPS, - setup: () => - new Promise(resolve => { - const scriptElement = document.createElement('script'); - - scriptElement.onload = resolve; - scriptElement.setAttribute('src', 'https://unpkg.com/core-js@2.6.3/client/core.min.js'); - - document.head.appendChild(scriptElement); - }) - }); - - const base64PNG = await driver.takeScreenshot(); - - expect(base64PNG).toMatchImageSnapshot(imageSnapshotOptions); - }); - - test('should display "Network interruption occurred. Reconnecting…" status when connection is interrupted', async () => { - const WEB_CHAT_PROPS = { styleOptions: { spinnerAnimationBackgroundImage: staticSpinner } }; - - const { driver } = await setupWebDriver({ - createDirectLine: options => { - // This part of code is running in the JavaScript VM in Chromium. - // These Direct Line Connection Status variables must be declared within scope - const CONNECTING = 1; - const ONLINE = 2; - - const reconnectingDirectLine = window.WebChat.createDirectLine(options); - - return { - activity$: reconnectingDirectLine.activity$, - postActivity: reconnectingDirectLine.postActivity.bind(reconnectingDirectLine), - - connectionStatus$: new Observable(observer => { - const subscription = reconnectingDirectLine.connectionStatus$.subscribe({ - complete: () => observer.complete(), - error: err => observer.error(err), - next: connectionStatus => { - observer.next(connectionStatus); - connectionStatus === ONLINE && observer.next(CONNECTING); - } - }); - - return () => subscription.unsubscribe(); - }) - }; - }, - pingBotOnLoad: false, - props: WEB_CHAT_PROPS, - setup: () => - Promise.all([ - window.WebChatTest.loadScript('https://unpkg.com/core-js@2.6.3/client/core.min.js'), - window.WebChatTest.loadScript('https://unpkg.com/lolex@4.0.1/lolex.js') - ]).then(() => { - window.WebChatTest.clock = lolex.install(); - }) - }); - - await driver.wait(actionDispatched('DIRECT_LINE/CONNECT_PENDING'), timeouts.directLine); - await driver.wait(actionDispatched('DIRECT_LINE/CONNECT_FULFILLED'), timeouts.directLine); - await driver.wait(actionDispatched('DIRECT_LINE/CONNECT_PENDING'), timeouts.directLine); - - await driver.executeScript(() => { - window.WebChatTest.clock.tick(400); // "Connecting" will be gone after 400ms, turning into "Network interruption occured" - window.WebChatTest.clock.tick(200); - }); - - // TODO: [P4] Understand why we need to fire tick() using two cross-VM calls - // When we put everything in a single cross-VM call, the last tick has no effect - await driver.executeScript(() => { - window.WebChatTest.clock.tick(1); // Shortly after 15s, it will show "Network interruption occured." - }); - - const base64PNG = await driver.takeScreenshot(); - - expect(base64PNG).toMatchImageSnapshot(imageSnapshotOptions); - }); - - test('should show "Taking longer than usual to connect" UI when reconnection is slow', async () => { - const { driver } = await setupWebDriver({ - createDirectLine: options => { - // This part of code is running in the JavaScript VM in Chromium. - // These Direct Line Connection Status variables must be declared within scope - const CONNECTING = 1; - - const ONLINE = 2; - - const reconnectingDirectLine = window.WebChat.createDirectLine(options); - - return { - activity$: reconnectingDirectLine.activity$, - postActivity: reconnectingDirectLine.postActivity.bind(reconnectingDirectLine), - - connectionStatus$: new Observable(observer => { - const subscription = reconnectingDirectLine.connectionStatus$.subscribe({ - complete: () => observer.complete(), - error: err => observer.error(err), - next: connectionStatus => { - observer.next(connectionStatus); - connectionStatus === ONLINE && observer.next(CONNECTING); - } - }); - - return () => subscription.unsubscribe(); - }) - }; - }, - pingBotOnLoad: false, - setup: () => - Promise.all([ - window.WebChatTest.loadScript('https://unpkg.com/core-js@2.6.3/client/core.min.js'), - window.WebChatTest.loadScript('https://unpkg.com/lolex@4.0.1/lolex.js') - ]).then(() => { - window.WebChatTest.clock = lolex.install(); - }) - }); - - await driver.wait(actionDispatched('DIRECT_LINE/RECONNECT_PENDING'), timeouts.directLine); - - await driver.executeScript(() => { - window.WebChatTest.clock.tick(400); // "Connecting" will be gone after 400ms - window.WebChatTest.clock.tick(14600); // Go to t=15s - }); - - // TODO: [P4] Understand why we need to fire tick() using two cross-VM calls - // When we put everything in a single cross-VM call, the last tick has no effect - await driver.executeScript(() => { - window.WebChatTest.clock.tick(1); // Shortly after 15s, it will show "Taking longer than usual to connect" - }); - - const base64PNG = await driver.takeScreenshot(); - - expect(base64PNG).toMatchImageSnapshot(imageSnapshotOptions); - }); - - test('should show "Render error" connectivity status when a JavaScript error is present in the code.', async () => { - const { driver, pageObjects } = await setupWebDriver({ - storeMiddleware: ({ dispatch }) => next => action => { - if ( - action.type === 'DIRECT_LINE/INCOMING_ACTIVITY' && - action.payload.activity && - action.payload.activity.text === 'error' - ) { - dispatch({ - type: 'DIRECT_LINE/POST_ACTIVITY', - payload: {} - }); - } - - return next(action); - } - }); - - await driver.wait(uiConnected(), timeouts.directLine); - await pageObjects.sendMessageViaSendBox('error', { waitForSend: false }); - await driver.wait(minNumActivitiesShown(2), timeouts.directLine); - await driver.wait(actionDispatched('WEB_CHAT/SAGA_ERROR'), timeouts.directLine); - - // Wait until error status come up - await driver.wait(connectivityStatusShown(/render error/iu), timeouts.ui); - - const base64PNG = await driver.takeScreenshot(); - - expect(base64PNG).toMatchImageSnapshot(imageSnapshotOptions); - }); -}); diff --git a/__tests__/timestamp.js b/__tests__/timestamp.js index d224adfee3..b1f21d0515 100644 --- a/__tests__/timestamp.js +++ b/__tests__/timestamp.js @@ -52,11 +52,11 @@ test('timestamp should update time', async () => { await pageObjects.sendMessageViaSendBox('echo timestamp', { waitForSend: true }); + await driver.executeScript(() => window.WebChatTest.clock.tick(1)); + await driver.wait(minNumActivitiesShown(3), timeouts.directLine); - await driver.executeScript(() => { - window.WebChatTest.clock.tick(330000); // t = 5.5 minutes - }); + await driver.executeScript(() => window.WebChatTest.clock.tick(330000)); // t = 5.5 minutes expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); }); @@ -108,132 +108,3 @@ test('change timestamp grouping on-the-fly', async () => { // After setting group timestamp to false, it should not show any timestamps. expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); }); - -test('change send timeout on-the-fly', async () => { - const { driver, pageObjects } = await setupWebDriver({ - createDirectLine: options => { - const workingDirectLine = window.WebChat.createDirectLine(options); - - return { - activity$: workingDirectLine.activity$, - connectionStatus$: workingDirectLine.connectionStatus$, - postActivity: activity => - activity.type === 'message' ? new Observable(() => {}) : workingDirectLine.postActivity(activity) - }; - }, - props: { - styleOptions: { - sendTimeout: 5000 - } - }, - setup: () => - Promise.all([ - window.WebChatTest.loadScript('https://unpkg.com/core-js@2.6.3/client/core.min.js'), - window.WebChatTest.loadScript('https://unpkg.com/lolex@4.0.1/lolex.js') - ]).then(() => { - window.WebChatTest.clock = lolex.install(); - }) - }); - - // Advance 1 second for the connection status prompt to be gone. - await driver.executeScript(() => window.WebChatTest.clock.tick(1000)); - - await driver.wait(uiConnected(), timeouts.directLine); - await pageObjects.sendMessageViaSendBox('echo Hello, World!', { waitForSend: false }); - - await driver.executeScript(() => window.WebChatTest.clock.tick(5000)); - - await driver.wait( - new Condition('turn into "Send failed. Retry.', driver => - driver.executeScript( - () => - document.querySelector('.webchat__row.message + .webchat__row [aria-hidden]').innerText === - 'Send failed. Retry.' - ) - ), - timeouts.ui - ); - - // After 5 seconds, it should show timeout. - expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); - - await pageObjects.updateProps({ styleOptions: { sendTimeout: 10000 } }); - - await driver.wait( - new Condition('turn into "Sending"', driver => - driver.executeScript( - () => document.querySelector('.webchat__row.message + .webchat__row [aria-hidden]').innerText === 'Sending' - ) - ), - timeouts.ui - ); - - // After changing the send timeout to 10 seconds, it should show "sending". - expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); - - await driver.executeScript(() => window.WebChatTest.clock.tick(5000)); - - await driver.wait( - new Condition('turn into "Send failed. Retry.', driver => - driver.executeScript( - () => - document.querySelector('.webchat__row.message + .webchat__row [aria-hidden]').innerText === - 'Send failed. Retry.' - ) - ), - timeouts.ui - ); - - // After 10 seconds, it should show timeout again. - expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); -}); - -test('send timeout for attachment should be different', async () => { - const { driver, pageObjects } = await setupWebDriver({ - createDirectLine: options => { - const workingDirectLine = window.WebChat.createDirectLine(options); - - return { - activity$: workingDirectLine.activity$, - connectionStatus$: workingDirectLine.connectionStatus$, - postActivity: activity => - activity.type === 'message' ? new Observable(() => {}) : workingDirectLine.postActivity(activity) - }; - }, - props: { - styleOptions: { - sendTimeout: 20000 - } - }, - setup: () => - Promise.all([ - window.WebChatTest.loadScript('https://unpkg.com/core-js@2.6.3/client/core.min.js'), - window.WebChatTest.loadScript('https://unpkg.com/lolex@4.0.1/lolex.js') - ]).then(() => { - window.WebChatTest.clock = lolex.install(); - }) - }); - - // Advance 1 second for the connection status prompt to be gone. - await driver.executeScript(() => window.WebChatTest.clock.tick(1000)); - - await driver.wait(uiConnected(), timeouts.directLine); - await pageObjects.sendFile('empty.zip', { waitForSend: false }); - - expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); - - await driver.executeScript(() => window.WebChatTest.clock.tick(20000)); - - // After 20 seconds, it should still show "sending". - expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); - - await driver.executeScript(() => window.WebChatTest.clock.tick(100000)); - - // After 120 seconds, it should show time out. - expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); - - await pageObjects.updateProps({ styleOptions: { sendTimeoutForAttachments: 130000 } }); - - // After changing the timeout to 130 seconds, it should show "sending". - expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); -}); diff --git a/packages/bundle/package-lock.json b/packages/bundle/package-lock.json index aac1e8418b..17be49da92 100644 --- a/packages/bundle/package-lock.json +++ b/packages/bundle/package-lock.json @@ -2072,8 +2072,7 @@ "@types/node": { "version": "12.12.18", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.18.tgz", - "integrity": "sha512-DBkZuIMFuAfjJHiunyRc+aNvmXYNwV1IPMgGKGlwCp6zh6MKrVtmvjSWK/axWcD25KJffkXgkfvFra8ndenXAw==", - "dev": true + "integrity": "sha512-DBkZuIMFuAfjJHiunyRc+aNvmXYNwV1IPMgGKGlwCp6zh6MKrVtmvjSWK/axWcD25KJffkXgkfvFra8ndenXAw==" }, "@types/prop-types": { "version": "15.7.3", @@ -2091,6 +2090,14 @@ "csstype": "^2.2.0" } }, + "@types/ws": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.4.tgz", + "integrity": "sha512-PpPrX7SZW9re6+Ha8ojZG4Se8AZXgf0GK6zmfqEuCsY49LFDNXO3SByp44X3dFEqtB73lkCDAdUazhAjVPiNwg==", + "requires": { + "@types/node": "*" + } + }, "@typescript-eslint/eslint-plugin": { "version": "2.12.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.12.0.tgz", @@ -2835,12 +2842,36 @@ "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" }, "botframework-directlinejs": { - "version": "0.11.6", - "resolved": "https://registry.npmjs.org/botframework-directlinejs/-/botframework-directlinejs-0.11.6.tgz", - "integrity": "sha512-IpMTaaf1jGHVjstYX7IqRCr21adNvKAhAVVLFLmnlqF4WZVpzVy3X14ZgttBmCPJTNuu2MhugOTzh0YxpjtqVQ==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/botframework-directlinejs/-/botframework-directlinejs-0.12.0.tgz", + "integrity": "sha512-2E+eCZ7RmIUa9h8FU7S1Dr4XoCUOCeI9R95DBYxc1zbjcpRmGmAquKy/zWJSOVQS4HlQ8gBTI38QcmG2iIvyzQ==", + "requires": { + "@babel/runtime": "7.6.0", + "botframework-streaming": "4.9.2", + "core-js": "3.6.4", + "cross-fetch": "3.0.4", + "rxjs": "5.5.10", + "url-search-params-polyfill": "8.0.0" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.0.tgz", + "integrity": "sha512-89eSBLJsxNxOERC0Op4vd+0Bqm6wRMqMbFtV3i0/fbaWw/mJ8Q3eBvgX0G4SyrOOLCtbu98HspF8o09MRT+KzQ==", + "requires": { + "regenerator-runtime": "^0.13.2" + } + } + } + }, + "botframework-streaming": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/botframework-streaming/-/botframework-streaming-4.9.2.tgz", + "integrity": "sha512-Vl94e6SnKUp94R1akKpFAUK5kinaKLAAmSBrol/fV8xghtfsZNLMWyVLDYPmstWdemuH5Jccpahb3mgPuEqV8A==", "requires": { - "@babel/runtime": "^7.6.0", - "rxjs": "^5.0.3" + "@types/ws": "^6.0.3", + "uuid": "^3.3.2", + "ws": "^7.1.2" } }, "brace-expansion": { @@ -3429,6 +3460,15 @@ "sha.js": "^2.4.8" } }, + "cross-fetch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.4.tgz", + "integrity": "sha512-MSHgpjQqgbT/94D4CyADeNoYh52zMkCX4pcJvPP5WqPsLFMKjr2TCMg381ox5qI0ii2dPwaLx/00477knXqXVw==", + "requires": { + "node-fetch": "2.6.0", + "whatwg-fetch": "3.0.0" + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -6880,6 +6920,11 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, + "node-fetch": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", + "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" + }, "node-libs-browser": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", @@ -8139,9 +8184,9 @@ } }, "rxjs": { - "version": "5.5.12", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz", - "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==", + "version": "5.5.10", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.10.tgz", + "integrity": "sha512-SRjimIDUHJkon+2hFo7xnvNC4ZEHGzCRwh9P7nzX3zPkCGFEg/tuElrNR7L/rZMagnK2JeH2jQwPRpmyXyLB6A==", "requires": { "symbol-observable": "1.0.1" } @@ -9208,6 +9253,11 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + }, "v8-compile-cache": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz", diff --git a/packages/bundle/package.json b/packages/bundle/package.json index 4311b4e350..a87984aad9 100644 --- a/packages/bundle/package.json +++ b/packages/bundle/package.json @@ -31,7 +31,7 @@ "dependencies": { "@babel/runtime": "7.8.7", "adaptivecards": "1.2.6", - "botframework-directlinejs": "0.11.6", + "botframework-directlinejs": "0.12.0", "botframework-directlinespeech-sdk": "0.0.0-0", "botframework-webchat-component": "0.0.0-0", "botframework-webchat-core": "0.0.0-0", diff --git a/packages/bundle/src/createDirectLineAppServiceExtension.js b/packages/bundle/src/createDirectLineAppServiceExtension.js new file mode 100644 index 0000000000..e946c82aa5 --- /dev/null +++ b/packages/bundle/src/createDirectLineAppServiceExtension.js @@ -0,0 +1,10 @@ +import { DirectLineStreaming } from 'botframework-directlinejs'; + +export default async function createDirectLineAppServiceExtension({ botAgent, conversationId, domain, token }) { + return new DirectLineStreaming({ + botAgent, + conversationId, + domain, + token + }); +} diff --git a/packages/bundle/src/index-es5.ts b/packages/bundle/src/index-es5.ts index 7bd1bdbbc0..313d011e08 100644 --- a/packages/bundle/src/index-es5.ts +++ b/packages/bundle/src/index-es5.ts @@ -30,6 +30,7 @@ import 'whatwg-fetch'; import { version } from './index-minimal'; import addVersion from './addVersion'; import defaultCreateDirectLine from './createDirectLine'; +import defaultCreateDirectLineAppServiceExtension from './createDirectLineAppServiceExtension'; export * from './index'; @@ -38,12 +39,23 @@ export const createDirectLine = options => { console.warn( 'Web Chat: Developers are not currently allowed to set botAgent in the createDirectLine function. See https://github.com/microsoft/BotFramework-WebChat/issues/2119 for more details.' ); + return defaultCreateDirectLine({ ...options, botAgent: `WebChat/${version} (ES5)` }); }; +export const createDirectLineAppServiceExtension = options => { + options.botAgent && + console.warn( + 'Web Chat: Developers are not currently allowed to set botAgent in the createDirectLine function. See https://github.com/microsoft/BotFramework-WebChat/issues/2119 for more details.' + ); + + return defaultCreateDirectLineAppServiceExtension({ ...options, botAgent: `WebChat/${version} (ES5)` }); +}; + window['WebChat'] = { ...window['WebChat'], - createDirectLine + createDirectLine, + createDirectLineAppServiceExtension }; addVersion('full-es5'); diff --git a/packages/bundle/src/index-minimal.ts b/packages/bundle/src/index-minimal.ts index a427fbb2de..10620cf99f 100644 --- a/packages/bundle/src/index-minimal.ts +++ b/packages/bundle/src/index-minimal.ts @@ -15,6 +15,7 @@ import addVersion from './addVersion'; import coreRenderWebChat from './renderWebChat'; import createBrowserWebSpeechPonyfillFactory from './createBrowserWebSpeechPonyfillFactory'; import defaultCreateDirectLine from './createDirectLine'; +import defaultCreateDirectLineAppServiceExtension from './createDirectLineAppServiceExtension'; const renderWebChat = coreRenderWebChat.bind(null, ReactWebChat); @@ -23,9 +24,19 @@ export const createDirectLine = options => { console.warn( 'Web Chat: Developers are not currently allowed to set botAgent in the createDirectLine function. See https://github.com/microsoft/BotFramework-WebChat/issues/2119 for more details.' ); + return defaultCreateDirectLine({ ...options, botAgent: `WebChat/${version} (Minimal)` }); }; +export const createDirectLineAppServiceExtension = options => { + options.botAgent && + console.warn( + 'Web Chat: Developers are not currently allowed to set botAgent in the createDirectLine function. See https://github.com/microsoft/BotFramework-WebChat/issues/2119 for more details.' + ); + + return defaultCreateDirectLineAppServiceExtension({ ...options, botAgent: `WebChat/${version} (Minimal)` }); +}; + export default ReactWebChat; export { @@ -48,6 +59,7 @@ window['WebChat'] = { Constants, createBrowserWebSpeechPonyfillFactory, createDirectLine, + createDirectLineAppServiceExtension, createStore, createStyleSet, hooks, diff --git a/packages/bundle/src/index.ts b/packages/bundle/src/index.ts index a60cd4507d..8840d30fef 100644 --- a/packages/bundle/src/index.ts +++ b/packages/bundle/src/index.ts @@ -14,6 +14,7 @@ import createCognitiveServicesSpeechServicesPonyfillFactory from './createCognit import createDirectLineSpeechAdapters from './createDirectLineSpeechAdapters'; import createStyleSet from './createFullStyleSet'; import defaultCreateDirectLine from './createDirectLine'; +import defaultCreateDirectLineAppServiceExtension from './createDirectLineAppServiceExtension'; import FullComposer from './FullComposer'; import HeroCardContent from './adaptiveCards/Attachment/HeroCardContent'; import OAuthCardContent from './adaptiveCards/Attachment/OAuthCardContent'; @@ -33,9 +34,19 @@ export const createDirectLine = options => { console.warn( 'Web Chat: Developers are not currently allowed to set botAgent. See https://github.com/microsoft/BotFramework-WebChat/issues/2119 for more details.' ); + return defaultCreateDirectLine({ ...options, botAgent: `WebChat/${version} (Full)` }); }; +export const createDirectLineAppServiceExtension = options => { + options.botAgent && + console.warn( + 'Web Chat: Developers are not currently allowed to set botAgent. See https://github.com/microsoft/BotFramework-WebChat/issues/2119 for more details.' + ); + + return defaultCreateDirectLineAppServiceExtension({ ...options, botAgent: `WebChat/${version} (Full)` }); +}; + const patchedHooks = { ...hooks, useAdaptiveCardsHostConfig, @@ -75,6 +86,7 @@ window['WebChat'] = { createAdaptiveCardsAttachmentMiddleware, createCognitiveServicesSpeechServicesPonyfillFactory, createDirectLine, + createDirectLineAppServiceExtension, createDirectLineSpeechAdapters, createStyleSet, hooks: patchedHooks, diff --git a/packages/core/package-lock.json b/packages/core/package-lock.json index d2bfd4365a..4a02f2c42a 100644 --- a/packages/core/package-lock.json +++ b/packages/core/package-lock.json @@ -1745,6 +1745,15 @@ "integrity": "sha512-DBkZuIMFuAfjJHiunyRc+aNvmXYNwV1IPMgGKGlwCp6zh6MKrVtmvjSWK/axWcD25KJffkXgkfvFra8ndenXAw==", "dev": true }, + "@types/ws": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.4.tgz", + "integrity": "sha512-PpPrX7SZW9re6+Ha8ojZG4Se8AZXgf0GK6zmfqEuCsY49LFDNXO3SByp44X3dFEqtB73lkCDAdUazhAjVPiNwg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "acorn": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", @@ -2039,19 +2048,32 @@ } }, "botframework-directlinejs": { - "version": "0.11.6", - "resolved": "https://registry.npmjs.org/botframework-directlinejs/-/botframework-directlinejs-0.11.6.tgz", - "integrity": "sha512-IpMTaaf1jGHVjstYX7IqRCr21adNvKAhAVVLFLmnlqF4WZVpzVy3X14ZgttBmCPJTNuu2MhugOTzh0YxpjtqVQ==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/botframework-directlinejs/-/botframework-directlinejs-0.12.0.tgz", + "integrity": "sha512-2E+eCZ7RmIUa9h8FU7S1Dr4XoCUOCeI9R95DBYxc1zbjcpRmGmAquKy/zWJSOVQS4HlQ8gBTI38QcmG2iIvyzQ==", "dev": true, "requires": { - "@babel/runtime": "^7.6.0", - "rxjs": "^5.0.3" + "@babel/runtime": "7.6.0", + "botframework-streaming": "4.9.2", + "core-js": "3.6.4", + "cross-fetch": "3.0.4", + "rxjs": "5.5.10", + "url-search-params-polyfill": "8.0.0" }, "dependencies": { + "@babel/runtime": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.0.tgz", + "integrity": "sha512-89eSBLJsxNxOERC0Op4vd+0Bqm6wRMqMbFtV3i0/fbaWw/mJ8Q3eBvgX0G4SyrOOLCtbu98HspF8o09MRT+KzQ==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.2" + } + }, "rxjs": { - "version": "5.5.12", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz", - "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==", + "version": "5.5.10", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.10.tgz", + "integrity": "sha512-SRjimIDUHJkon+2hFo7xnvNC4ZEHGzCRwh9P7nzX3zPkCGFEg/tuElrNR7L/rZMagnK2JeH2jQwPRpmyXyLB6A==", "dev": true, "requires": { "symbol-observable": "1.0.1" @@ -2065,6 +2087,17 @@ } } }, + "botframework-streaming": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/botframework-streaming/-/botframework-streaming-4.9.2.tgz", + "integrity": "sha512-Vl94e6SnKUp94R1akKpFAUK5kinaKLAAmSBrol/fV8xghtfsZNLMWyVLDYPmstWdemuH5Jccpahb3mgPuEqV8A==", + "dev": true, + "requires": { + "@types/ws": "^6.0.3", + "uuid": "^3.3.2", + "ws": "^7.1.2" + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -2343,6 +2376,12 @@ "dev": true, "optional": true }, + "core-js": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.4.tgz", + "integrity": "sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==", + "dev": true + }, "core-js-compat": { "version": "3.6.5", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz", @@ -2366,6 +2405,16 @@ "dev": true, "optional": true }, + "cross-fetch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.4.tgz", + "integrity": "sha512-MSHgpjQqgbT/94D4CyADeNoYh52zMkCX4pcJvPP5WqPsLFMKjr2TCMg381ox5qI0ii2dPwaLx/00477knXqXVw==", + "dev": true, + "requires": { + "node-fetch": "2.6.0", + "whatwg-fetch": "3.0.0" + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -4380,6 +4429,12 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, + "node-fetch": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", + "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==", + "dev": true + }, "node-releases": { "version": "1.1.57", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.57.tgz", @@ -5799,6 +5854,12 @@ "dev": true, "optional": true }, + "url-search-params-polyfill": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/url-search-params-polyfill/-/url-search-params-polyfill-8.0.0.tgz", + "integrity": "sha512-X4BTaEq1UMz9bTbMKQ6r+CippkKBsFWHiP9wycQc7aHH2Ml/Iieuo44+GJDb77pfP71bONYA/nUd4iokYAxVRQ==", + "dev": true + }, "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", @@ -5813,6 +5874,12 @@ "dev": true, "optional": true }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, "v8-compile-cache": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", @@ -5829,6 +5896,12 @@ "spdx-expression-parse": "^3.0.0" } }, + "whatwg-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", + "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==", + "dev": true + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -5876,6 +5949,12 @@ "mkdirp": "^0.5.1" } }, + "ws": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.0.tgz", + "integrity": "sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w==", + "dev": true + }, "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", diff --git a/packages/core/package.json b/packages/core/package.json index b08f1063f7..a1ca6c8739 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -35,7 +35,7 @@ "@types/node": "^12.12.18", "babel-plugin-istanbul": "^6.0.0", "babel-plugin-transform-inline-environment-variables": "^0.4.3", - "botframework-directlinejs": "^0.11.6", + "botframework-directlinejs": "0.12.0", "concurrently": "^5.1.0", "eslint": "^6.8.0", "eslint-plugin-prettier": "^3.1.2", diff --git a/packages/playground/package-lock.json b/packages/playground/package-lock.json index b0e848487f..10d16d2e08 100644 --- a/packages/playground/package-lock.json +++ b/packages/playground/package-lock.json @@ -1335,6 +1335,11 @@ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.3.tgz", "integrity": "sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==" }, + "@types/node": { + "version": "14.0.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.11.tgz", + "integrity": "sha512-lCvvI24L21ZVeIiyIUHZ5Oflv1hhHQ5E1S25IRlKIXaRkVgmXpJMI3wUJkmym2bTbCe+WoIibQnMVAU3FguaOg==" + }, "@types/q": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.2.tgz", @@ -1345,6 +1350,14 @@ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==" }, + "@types/ws": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.4.tgz", + "integrity": "sha512-PpPrX7SZW9re6+Ha8ojZG4Se8AZXgf0GK6zmfqEuCsY49LFDNXO3SByp44X3dFEqtB73lkCDAdUazhAjVPiNwg==", + "requires": { + "@types/node": "*" + } + }, "@types/yargs": { "version": "13.0.3", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.3.tgz", @@ -2386,12 +2399,56 @@ "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" }, "botframework-directlinejs": { - "version": "0.11.6", - "resolved": "https://registry.npmjs.org/botframework-directlinejs/-/botframework-directlinejs-0.11.6.tgz", - "integrity": "sha512-IpMTaaf1jGHVjstYX7IqRCr21adNvKAhAVVLFLmnlqF4WZVpzVy3X14ZgttBmCPJTNuu2MhugOTzh0YxpjtqVQ==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/botframework-directlinejs/-/botframework-directlinejs-0.12.0.tgz", + "integrity": "sha512-2E+eCZ7RmIUa9h8FU7S1Dr4XoCUOCeI9R95DBYxc1zbjcpRmGmAquKy/zWJSOVQS4HlQ8gBTI38QcmG2iIvyzQ==", + "requires": { + "@babel/runtime": "7.6.0", + "botframework-streaming": "4.9.2", + "core-js": "3.6.4", + "cross-fetch": "3.0.4", + "rxjs": "5.5.10", + "url-search-params-polyfill": "8.0.0" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.0.tgz", + "integrity": "sha512-89eSBLJsxNxOERC0Op4vd+0Bqm6wRMqMbFtV3i0/fbaWw/mJ8Q3eBvgX0G4SyrOOLCtbu98HspF8o09MRT+KzQ==", + "requires": { + "regenerator-runtime": "^0.13.2" + } + }, + "core-js": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.4.tgz", + "integrity": "sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==" + }, + "rxjs": { + "version": "5.5.10", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.10.tgz", + "integrity": "sha512-SRjimIDUHJkon+2hFo7xnvNC4ZEHGzCRwh9P7nzX3zPkCGFEg/tuElrNR7L/rZMagnK2JeH2jQwPRpmyXyLB6A==", + "requires": { + "symbol-observable": "1.0.1" + } + } + } + }, + "botframework-streaming": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/botframework-streaming/-/botframework-streaming-4.9.2.tgz", + "integrity": "sha512-Vl94e6SnKUp94R1akKpFAUK5kinaKLAAmSBrol/fV8xghtfsZNLMWyVLDYPmstWdemuH5Jccpahb3mgPuEqV8A==", "requires": { - "@babel/runtime": "^7.6.0", - "rxjs": "^5.0.3" + "@types/ws": "^6.0.3", + "uuid": "^3.3.2", + "ws": "^7.1.2" + }, + "dependencies": { + "ws": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.0.tgz", + "integrity": "sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w==" + } } }, "bowser": { @@ -3138,6 +3195,22 @@ "sha.js": "^2.4.8" } }, + "cross-fetch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.4.tgz", + "integrity": "sha512-MSHgpjQqgbT/94D4CyADeNoYh52zMkCX4pcJvPP5WqPsLFMKjr2TCMg381ox5qI0ii2dPwaLx/00477knXqXVw==", + "requires": { + "node-fetch": "2.6.0", + "whatwg-fetch": "3.0.0" + }, + "dependencies": { + "node-fetch": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", + "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" + } + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -12712,6 +12785,11 @@ "requires-port": "^1.0.0" } }, + "url-search-params-polyfill": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/url-search-params-polyfill/-/url-search-params-polyfill-8.0.0.tgz", + "integrity": "sha512-X4BTaEq1UMz9bTbMKQ6r+CippkKBsFWHiP9wycQc7aHH2Ml/Iieuo44+GJDb77pfP71bONYA/nUd4iokYAxVRQ==" + }, "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", diff --git a/packages/playground/package.json b/packages/playground/package.json index 8ec85a0c68..0a9af121d8 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -10,7 +10,7 @@ ], "dependencies": { "adaptivecards": "1.2.5", - "botframework-directlinejs": "^0.11.6", + "botframework-directlinejs": "0.12.0", "botframework-webchat": "0.0.0-0", "classnames": "^2.2.6", "glamor": "^2.20.40", diff --git a/packages/testharness/src/pageObjects/index.js b/packages/testharness/src/pageObjects/index.js index e9b1452b96..8fa7e93969 100644 --- a/packages/testharness/src/pageObjects/index.js +++ b/packages/testharness/src/pageObjects/index.js @@ -13,6 +13,7 @@ import sendMessageViaSendBox from './sendMessageViaSendBox'; import typeInSendBox from './typeInSendBox'; import verifyDOMIntegrity from './verifyDOMIntegrity'; import wait from './wait'; +import waitWithTick from './waitWithTick'; export { clickMicrophoneButton, @@ -29,5 +30,6 @@ export { sendMessageViaSendBox, typeInSendBox, verifyDOMIntegrity, - wait + wait, + waitWithTick }; diff --git a/packages/testharness/src/pageObjects/waitWithTick.js b/packages/testharness/src/pageObjects/waitWithTick.js new file mode 100644 index 0000000000..6c169722a4 --- /dev/null +++ b/packages/testharness/src/pageObjects/waitWithTick.js @@ -0,0 +1,16 @@ +import wait from './wait'; + +export default async function waitWithTick(condition, clock, timeout = 2000) { + const fn = condition.fn.bind(condition); + let initial = 1; + + return wait({ + ...condition, + fn: () => { + initial || clock.tick(1); + initial = 0; + + return fn(); + } + }, timeout); +} diff --git a/packages/testharness/src/token/fetchDirectLineAppServiceExtensionToken.js b/packages/testharness/src/token/fetchDirectLineAppServiceExtensionToken.js new file mode 100644 index 0000000000..4c9e6c7e13 --- /dev/null +++ b/packages/testharness/src/token/fetchDirectLineAppServiceExtensionToken.js @@ -0,0 +1,11 @@ +export default async function(url = 'https://webchat-mockbot2.azurewebsites.net/api/token/directlinease') { + const res = await fetch(url, { method: 'POST' }); + + if (!res.ok) { + throw new Error('Failed to fetch Direct Line App Service Extension token.'); + } + + const { token } = await res.json(); + + return token; +} diff --git a/packages/testharness/src/token/index.js b/packages/testharness/src/token/index.js index 71464eaf94..2d36d4636d 100644 --- a/packages/testharness/src/token/index.js +++ b/packages/testharness/src/token/index.js @@ -1,5 +1,11 @@ +import fetchDirectLineAppServiceExtensionToken from './fetchDirectLineAppServiceExtensionToken'; import fetchDirectLineSpeechCredentials from './fetchDirectLineSpeechCredentials'; import fetchDirectLineToken from './fetchDirectLineToken'; import fetchSpeechServicesCredentials from './fetchSpeechServicesCredentials'; -export { fetchDirectLineSpeechCredentials, fetchDirectLineToken, fetchSpeechServicesCredentials }; +export { + fetchDirectLineAppServiceExtensionToken, + fetchDirectLineSpeechCredentials, + fetchDirectLineToken, + fetchSpeechServicesCredentials +}; diff --git a/samples/01.getting-started/i.protocol-direct-line-app-service-extension/README.md b/samples/01.getting-started/i.protocol-direct-line-app-service-extension/README.md new file mode 100644 index 0000000000..aa8fa79813 --- /dev/null +++ b/samples/01.getting-started/i.protocol-direct-line-app-service-extension/README.md @@ -0,0 +1,146 @@ +# Sample - Getting Started with Direct Line App Service Extension protocol + +## Description + +A simple web page with Web Chat connected to a bot via [Direct Line App Service Extension protocol](https://docs.microsoft.com/en-us/azure/bot-service/bot-service-channel-directline-extension?view=azure-bot-service-4.0). + +# Test out the hosted sample + +- [Try out MockBot](https://microsoft.github.io/BotFramework-WebChat/01.getting-started/i.protocol-direct-line-app-service-extension) + +# How to run + +- Fork this repository +- Navigate to `/Your-Local-WebChat/samples/01.getting-started/i.protocol-direct-line-app-service-extension` in command line +- Run `npx serve` +- Browse to [http://localhost:5000/](http://localhost:5000/) + +# Things to try out + +- Type `hello`: you should be able to type to the bot and receive a response in plain text + +# Code + +> Jump to [completed code](#completed-code) to see the end-result `index.html`. + +## Getting started + +### Goals of this bot + +This code features the Direct Line App Service Extension protocol (Direct Line ASE). Additional steps required to set up a bot to use Direct Line App Service Extension can be found in the [DL ASE documentation](https://docs.microsoft.com/en-us/azure/bot-service/bot-service-channel-directline-extension?view=azure-bot-service-4.0). + +The `index.html` page has the following main goals: + +- To import the Web Chat bundle CDN script +- [Obtain a Direct Line ASE-specific token](obtain-a-direct-line-ase-specific-token) + - The token should have an issuer and audience of https://directlineextension.botframework.com/ + - The token should be generated from the Direct Line ASE-specific API at https://yourbot/.bot/v3/directline/tokens/generate +- Render using the Direct Line ASE chat adapter + +This sample starts with the [full-bundle CDN sample](../a.full-bundle/README.md) as the base template. + +### Obtain a Direct Line ASE-specific token + +We are updating the endpoint of our token server to retrieve a Direct Line ASE-specific token. + +```diff + … +- const res = await fetch('https://webchat-mockbot.azurewebsites.net/directline/token', { method: 'POST' }); ++ const res = await fetch('https://webchat-mockbot2.azurewebsites.net/api/token/directlinease', { method: 'POST' }); + … +``` + +> The token is a JSON Web Token and the `iss` and `aud` fields are both https://directlineextension.botframework.com/. + +### Render using the Direct Line ASE chat adapter + +Create a Direct Line ASE chat adapter with the ASE-specific token and bot endpoint. Our MockBot is hosted on https://webchat-mockbot2.azurewebsites.net/, the bot endpoint is https://webchat-mockbot2.azurewebsites.net/.bot/v3/directline. + +```diff + … + window.WebChat.renderWebChat( + { +- directLine: window.WebChat.createDirectLine({ token }) ++ directLine: await window.WebChat.createDirectLineAppServiceExtension({ ++ domain: 'https://webchat-mockbot2.azurewebsites.net/.bot/v3/directline', ++ token ++ }) + }, + document.getElementById('webchat') + ); + … +``` + +## Completed code + +Here is the finished `index.html`: + + +```html + + + + Web Chat: Full-featured bundle with Direct Line Speech channel + + + + + +
+ + + +``` + + +# Further reading + +## Other CDN bundles + +Check out the hosted samples and source code for other CDN bundle options below. + +- [Full bundle bot](https://microsoft.github.io/BotFramework-WebChat/01.getting-started/a.full-bundle) | [(Full bundle source code)](https://github.com/microsoft/BotFramework-WebChat/tree/master/samples/01.getting-started/a.full-bundle) +- [Full bundle with polyfills for ES5 browsers bot](https://microsoft.github.io/BotFramework-WebChat/01.getting-started/c.es5-bundle) | [(Full bundle with polyfills for ES5 browsers source code)](https://github.com/microsoft/BotFramework-WebChat/tree/master/samples/01.getting-started/c.es5-bundle) +- [Direct Line App Service Extension](https://docs.microsoft.com/en-us/azure/bot-service/bot-service-channel-directline-extension?view=azure-bot-service-4.0) + +## Full list of Web Chat hosted samples + +View the list of [available Web Chat samples](https://github.com/microsoft/BotFramework-WebChat/tree/master/samples) diff --git a/samples/01.getting-started/i.protocol-direct-line-app-service-extension/index.html b/samples/01.getting-started/i.protocol-direct-line-app-service-extension/index.html new file mode 100644 index 0000000000..4e91410e71 --- /dev/null +++ b/samples/01.getting-started/i.protocol-direct-line-app-service-extension/index.html @@ -0,0 +1,61 @@ + + + + Web Chat: Full-featured bundle with Direct Line Speech channel + + + + + + + +
+ + + diff --git a/samples/README.md b/samples/README.md index d59e980283..d783cd7f90 100644 --- a/samples/README.md +++ b/samples/README.md @@ -19,6 +19,7 @@ Here you can find all hosted samples of [Web Chat](https://github.com/microsoft/ | [`01.getting-started/f.host-with-angular`](https://github.com/microsoft/BotFramework-WebChat/tree/master/samples/01.getting-started/f.host-with-angular) | Demonstrates how to create an Angular component that hosts the full-featured Web Chat. | [Host with Angular Demo](https://stackblitz.com/github/omarsourour/ng-webchat-example) | | [`01.getting-started/g.hybrid-react-npm`](https://github.com/microsoft/BotFramework-WebChat/tree/master/samples/01.getting-started/g.hybrid-react-npm) | Demonstrates how to use different versions of React on a hosting app via NPM packages | [Hybrid React Demo](https://microsoft.github.io/BotFramework-WebChat/01.getting-started/g.hybrid-react-npm) | | [`01.getting-started/h.minimal-markdown`](https://github.com/microsoft/BotFramework-WebChat/tree/master/samples/01.getting-started/h.minimal-markdown) | Demonstrates how to add the CDN for Markdown-It dependency on top of the minimal bundle. | [Minimal with Markdown Demo](https://microsoft.github.io/BotFramework-WebChat/01.getting-started/h.minimal-markdown) | +| [`01.getting-started/i.protocol-direct-line-app-service-extension`](https://github.com/microsoft/BotFramework-WebChat/tree/master/samples/01.getting-started/i.protocol-direct-line-app-service-extension) | Demonstrates how to use Direct Line App Service Extension chat adapter | [Direct Line App Service Extension Demo](https://microsoft.github.io/BotFramework-WebChat/01.getting-started/i.protocol-direct-line-app-service-extension) | | **Branding, styling, and customization** | | | | [`02.branding-styling-and-customization/a.branding-web-chat`](https://github.com/microsoft/BotFramework-WebChat/tree/master/samples/02.branding-styling-and-customization/a.branding-web-chat) | Introduces the ability to style Web Chat to match your brand. This method of custom styling will not break upon Web Chat updates. | [Branding Web Chat Demo](https://microsoft.github.io/BotFramework-WebChat/02.branding-styling-and-customization/a.branding-web-chat) | | [`02.branding-styling-and-customization/b.idiosyncratic-manual-styles`](https://github.com/microsoft/BotFramework-WebChat/tree/master/samples/02.branding-styling-and-customization/b.idiosyncratic-manual-styles) | Demonstrates how to make manual style changes, and is a more complicated and time-consuming way to customize styling of Web Chat. Manual styles may be broken upon Web Chat updates. | [Idiosyncratic Styling Demo](https://microsoft.github.io/BotFramework-WebChat/02.branding-styling-and-customization/b.idiosyncratic-manual-styles) |