Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Offline UI - indicate slow connection and failed credentials #1679

Merged
merged 20 commits into from
Feb 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- `component`: Fix [#1626](https://github.com/Microsoft/BotFramework-WebChat/issues/1626). Fixed `Number.isNaN` is not available in IE11, by [@compulim](https://github.com/compulim) in PR [#1628](https://github.com/Microsoft/BotFramework-WebChat/pull/1628)
- `bundle`: Fix [#1652](https://github.com/Microsoft/BotFramework-WebChat/issues/1652). Pass `pollingInterval` to DirectLineJS constructor, by [@neetu-das](https://github.com/neetu-das) in PR [#1655](https://github.com/Microsoft/BotFramework-WebChat/pull/1655)
- `core`: Reworked logic on connect/disconnect for reliability on handling corner cases, by [@compulim](https://github.com/compulim) in PR [#1649](https://github.com/Microsoft/BotFramework-WebChat/pull/1649)
- `core`: Fix [#1521](https://github.com/Microsoft/BotFramework-WebChat/issues/1521). Add connectivity status component and update localization, by [@corinagum](https://github.com/corinagum) in PR [#1679](https://github.com/Microsoft/BotFramework-WebChat/pull/1679)

### Removed
- `botAvatarImage` and `userAvatarImage` props, as they are moved inside `styleOptions`, in PR [#1486](https://github.com/Microsoft/BotFramework-WebChat/pull/1486)
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.
71 changes: 71 additions & 0 deletions __tests__/offlineUI.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { imageSnapshotOptions, timeouts } from './constants.json';

// selenium-webdriver API doc:
// https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/index_exports_WebDriver.html

describe('offline UI', async () => {
test('should show "slow to connect" UI when connection is slow', async() => {
const { driver } = await setupWebDriver({
createDirectLine: options => {
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 !== 2 && observer.next(connectionStatus);
}
});

return () => subscription.unsubscribe();
})
};
},
setup: () => new Promise(resolve => {
const scriptElement = document.createElement('script');

scriptElement.onload = resolve;
scriptElement.setAttribute('src', 'https://unpkg.com/[email protected]/client/core.min.js');

document.head.appendChild(scriptElement);
})
});

await driver.sleep(15000);

const base64PNG = await driver.takeScreenshot();

expect(base64PNG).toMatchImageSnapshot(imageSnapshotOptions);
}, 60000);

test('should show "unable to connect" UI when credentials are incorrect', async() => {
const { driver } = await setupWebDriver({
createDirectLine: () => {
return window.WebChat.createDirectLine({ token: 'INVALID-TOKEN' });
},
setup: () => new Promise(resolve => {
const scriptElement = document.createElement('script');

scriptElement.onload = resolve;
scriptElement.setAttribute('src', 'https://unpkg.com/[email protected]/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);
}, 60000);
});
6 changes: 5 additions & 1 deletion __tests__/setup/pageObjects/hideCursor.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
export default async function hideCursor(driver) {
await driver.executeScript(() => document.querySelector(':focus').blur());
await driver.executeScript(() => {
const focusedElement = document.querySelector(':focus');

focusedElement && focusedElement.blur();
});
}
24 changes: 20 additions & 4 deletions __tests__/setup/setupTestFramework.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,26 @@ global.setupWebDriver = async (options = {}) => {
await driver.get(baseURL);
}

await driver.executeScript((coverage, props) => {
window.__coverage__ = coverage;
main({ props });
}, global.__coverage__, options.props);
await driver.executeAsyncScript(
(coverage, props, createDirectLineFnString, setupFnString, callback) => {
window.__coverage__ = coverage;

const setupPromise = setupFnString ? eval(`() => ${ setupFnString }`)()() : Promise.resolve();

setupPromise.then(() => {
main({
createDirectLine: createDirectLineFnString && eval(`() => ${ createDirectLineFnString }`)(),
props
});

callback();
});
},
global.__coverage__,
options.props,
options.createDirectLine && options.createDirectLine.toString(),
options.setup && options.setup.toString()
);

await driver.wait(webChatLoaded(), timeouts.navigation);

Expand Down
13 changes: 7 additions & 6 deletions __tests__/setup/web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@
<script>
window.WebChatTest = { actions: [] };

function main({ props } = {}) {
function main({
createDirectLine,
props
} = {}) {
const webChatScript = document.createElement('script');

webChatScript.setAttribute('src', '/webchat-instrumented.js');
Expand All @@ -72,12 +75,10 @@
return next(action);
});

createDirectLine || (createDirectLine = window.WebChat.createDirectLine);

window.WebChat.renderWebChat({
// directLine: window.WebChat.createDirectLine({
// domain: 'http://localhost:5000/v3/directline',
// webSocket: false
// })
directLine: window.WebChat.createDirectLine({ token }),
directLine: createDirectLine({ token }),
store,
...props
}, document.getElementById('webchat'));
Expand Down
2 changes: 1 addition & 1 deletion packages/component/src/Activity/SendStatus.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const { ActivityClientState: { SEND_FAILED, SENDING } } = Constants;
// TODO: [P4] Currently, this is the only place which use a templated string
// We could refactor this into a general component if there are more templated strings
function sendFailed(language, replace) {
const text = localize('Send failed, {retry}', language);
const text = localize(SEND_FAILED_KEY, language);
const retry = localize('retry', language);
const match = /\{retry\}/.exec(text);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';

export default ({ className, size = 1 }) =>
<svg
alt=""
className={ className }
height={ 16 * size }
viewBox="0 0 13.1 13.1"
width={ 16 * size }
>
<path fillRule="evenodd" d="M6.5,13C2.9,13,0,10.1,0,6.5S2.9,0,6.5,0S13,2.9,13,6.5S10.1,13,6.5,13z M6.1,3.5v4.3h0.9V3.5H6.1z M6.1,8.7
v0.9h0.9V8.7H6.1z"/>
</svg>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';

export default ({ className, size = 1 }) =>
<svg
alt=""
className={ className }
height={ 16 * size }
viewBox="0 0 13.1 13.1"
width={ 16 * size }
>
<path fillRule="evenodd" d="M13.1,13.1H0L6.6,0L13.1,13.1z M7,10.5H6.1v0.9H7V10.5z M7,9.7V5.2H6.1v4.4L7,9.7z"/>
</svg>
2 changes: 2 additions & 0 deletions packages/component/src/BasicSendBox.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { css } from 'glamor';
import classNames from 'classnames';
import React from 'react';

import ConnectivityStatus from './SendBox/ConnectivityStatus';
import connectToWebChat from './connectToWebChat';
import DictationInterims from './SendBox/DictationInterims';
import MicrophoneButton from './SendBox/MicrophoneButton';
Expand Down Expand Up @@ -43,6 +44,7 @@ const BasicSendBox = ({
) }
role="form"
>
<ConnectivityStatus />
<SuggestedActions />
<div className="main">
{ !styleSet.options.hideUploadButton &&
Expand Down
6 changes: 5 additions & 1 deletion packages/component/src/Localization/cs-CZ.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
export default {
// FAILED_CONNECTION_NOTIFICATION: '',
// Do not localize {Retry}; it is a placeholder for "Retry". English translation should be, "Send failed. Retry."
SEND_FAILED_KEY: 'nepodařilo se odeslat, {Retry}.',
// SLOW_CONNECTION_NOTIFICATION: '',
'Chat': 'Chat',
// 'Download file': '',
// 'Microphone off': '',
// 'Microphone on': '',
'Listening…': 'Poslouchám…',
'retry': 'opakovat',
'Send failed, {retry}': 'nepodařilo se odeslat, {retry}',
'Retry': '{retry}', // Please alter this value if 'Retry' at the beginning of a sentence is written differently than at the end of a sentence.
'Send': 'Odeslat',
'Sending': 'Odesílání',
'Speak': 'Použít hlas',
Expand Down
6 changes: 5 additions & 1 deletion packages/component/src/Localization/da-DK.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
export default {
// FAILED_CONNECTION_NOTIFICATION: '',
// Do not localize {Retry}; it is a placeholder for "Retry". English translation should be, "Send failed. Retry."
SEND_FAILED_KEY: 'ikke sendt, {Retry}.',
// SLOW_CONNECTION_NOTIFICATION: '',
'Chat': 'Chat',
// 'Download file': '',
// 'Microphone off': '',
// 'Microphone on': '',
'Listening…': 'Lytter…',
'retry': 'prøv igen',
'Send failed, {retry}': 'ikke sendt, {retry}',
'Retry': '{retry}', // Please alter this value if 'Retry' at the beginning of a sentence is written differently than at the end of a sentence.
'Sending': 'sender',
// 'Starting…': '',
'Tax': 'Skat',
Expand Down
6 changes: 5 additions & 1 deletion packages/component/src/Localization/de-DE.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
export default {
// FAILED_CONNECTION_NOTIFICATION: '',
// Do not localize {Retry}; it is a placeholder for "Retry". English translation should be, "Send failed. Retry."
SEND_FAILED_KEY: 'konnte nicht senden, {Retry}.',
// SLOW_CONNECTION_NOTIFICATION: '',
'Chat': 'Chat',
// 'Download file': '',
// 'Microphone off': '',
// 'Microphone on': '',
'Listening…': 'Hören…',
'retry': 'wiederholen',
'Send failed, {retry}': 'konnte nicht senden, {retry}',
'Retry': '{retry}', // Please alter this value if 'Retry' at the beginning of a sentence is written differently than at the end of a sentence.
'Send': 'Senden',
'Sending': 'sendet',
// 'Speak': '',
Expand Down
6 changes: 5 additions & 1 deletion packages/component/src/Localization/el-GR.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
export default {
// FAILED_CONNECTION_NOTIFICATION: '',
// Do not localize {Retry}; it is a placeholder for "Retry". English translation should be, "Send failed. Retry."
SEND_FAILED_KEY: 'αποτυχία, {Retry}.',
// SLOW_CONNECTION_NOTIFICATION: '',
'Chat': 'Συνομιλία',
// 'Download file': '',
// 'Microphone off': '',
// 'Microphone on': '',
'Listening…': 'Ακούγοντας…',
'retry': 'δοκιμή',
'Send failed, {retry}': 'αποτυχία, {retry}',
'Retry': '{retry}', // Please alter this value if 'Retry' at the beginning of a sentence is written differently than at the end of a sentence.
'Send': 'Αποστολή',
'Sending': 'αποστολή',
// 'Speak': '',
Expand Down
56 changes: 27 additions & 29 deletions packages/component/src/Localization/en-US.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,36 +39,34 @@ function xMinutesAgo(dateStr) {
}

export default {
FAILED_CONNECTION_NOTIFICATION: 'Unable to connect.',
// Do not localize {Retry}; it is a placeholder for "Retry". English translation should be, "Send failed. Retry."
SEND_FAILED_KEY: 'Send failed. {Retry}.',
SLOW_CONNECTION_NOTIFICATION: 'Taking longer than usual to connect.',
'Bot said something': botSaidSomething,
'User said something': userSaidSomething,
'X minutes ago': xMinutesAgo,
...[
// '[File of type '%1']",
// '[Unknown Card '%1']',
'Adaptive Card parse error',
'Adaptive Card render error',
'Chat',
'Download file',
'Microphone off',
'Microphone on',
'Left',
'Listening…',
'New messages',
'retry',
'Right',
// Do not localize {retry}, it is a placeholder for "retry"
'Send failed, {retry}',
'Send',
'Sending',
'Speak',
'Starting…',
'Tax',
'Total',
'Type your message',
'Upload file',
'VAT'
].reduce((result, text) => ({
...result,
[text]: text
}), {})
// '[File of type '%1']': '[File of type '%1']",
// '[Unknown Card '%1']': '[Unknown Card '%1']',
'Adaptive Card parse error' : 'Adaptive Card parse error',
'Adaptive Card render error': 'Adaptive Card render error',
'Chat': 'Chat',
'Download file': 'Download file',
'Microphone off': 'Microphone off',
'Microphone on': 'Microphone on',
'Left': 'Left',
'Listening…': 'Listening…',
'New messages': 'New messages',
'Right': 'Right',
'retry': 'retry',
'Retry': 'Retry',
'Send': 'Send',
'Sending': 'Sending',
'Speak': 'Speak',
'Starting…': 'Starting…',
'Tax': 'Tax',
'Total': 'Total',
'Type your message': 'Type your message',
'Upload file': 'Upload file',
'VAT': 'VAT'
}
8 changes: 6 additions & 2 deletions packages/component/src/Localization/es-ES.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
export default {
// FAILED_CONNECTION_NOTIFICATION: '',
// Do not localize {Retry}; it is a placeholder for "Retry". English translation should be, "Send failed. Retry."
SEND_FAILED_KEY: 'No enviado. {Retry}.',
// SLOW_CONNECTION_NOTIFICATION: '',
'Chat': 'Chat',
'Microphone off': 'Apagar micrófono',
'Microphone on': 'Encender micrófono',
'Download file': 'Descargar archivo',
'New messages': 'Nuevos mensajes',
'Listening…': 'Escuchando…',
'retry': 'reintentar',
'Send failed, {retry}': 'no enviado, {retry}',
'Retry': 'Reintentar', // Please alter this value if 'Retry' at the beginning of a sentence is written differently than at the end of a sentence.
'Send': 'Enviar',
'Sending': 'enviando',
'Sending': 'Enviando',
'Speak': 'Hablar',
'Starting…': 'Comenzando',
'Tax': 'Impuestos',
Expand Down
6 changes: 5 additions & 1 deletion packages/component/src/Localization/fi-FI.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
export default {
// FAILED_CONNECTION_NOTIFICATION: '',
// Do not localize {Retry}; it is a placeholder for "Retry". English translation should be, "Send failed. Retry."
SEND_FAILED_KEY: 'ei voitu lähettää, {Retry}.',
// SLOW_CONNECTION_NOTIFICATION: '',
'Chat': 'Chat',
// 'Download file': '',
// 'Microphone off': '',
// 'Microphone on': '',
'Listening…': 'Kuuntelee…',
'retry': 'yritä uudelleen',
'Send failed, {retry}': 'ei voitu lähettää, {retry}',
'Retry': '{retry}', // Please alter this value if 'Retry' at the beginning of a sentence is written differently than at the end of a sentence.
'Send': 'Lähetä',
'Sending': 'lähettää',
'Speak': 'Puhu',
Expand Down
6 changes: 5 additions & 1 deletion packages/component/src/Localization/fr-FR.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ function xMinutesAgo(dateStr) {
}

export default {
// FAILED_CONNECTION_NOTIFICATION: '',
// Do not localize {Retry}; it is a placeholder for "Retry". English translation should be, "Send failed. Retry."
SEND_FAILED_KEY: 'Échec d\'envoi, {Retry}.',
// SLOW_CONNECTION_NOTIFICATION: '',
'Chat': 'Discuter',
// 'Download file': '',
// 'Microphone off': '',
Expand All @@ -40,7 +44,7 @@ export default {
'New messages': 'Nouveaux messages',
'retry': 'Réessayer',
'Right': 'Droite',
'Send failed, {retry}': 'Échec d\'envoi, {retry}',
'Retry': '{retry}', // Please alter this value if 'Retry' at the beginning of a sentence is written differently than at the end of a sentence.
'Send': 'Envoyer',
'Sending': 'Envoi…',
'Speak': 'Parlez',
Expand Down
Loading