Skip to content

Commit

Permalink
Add basic test for speech recognition and synthesis (#2153)
Browse files Browse the repository at this point in the history
* Initial commit

* Use pageObject for mock speech recognition

* First mock synthesis test

* Clean up

* Clean up

* Typo

* Clean up

* Clean up

* Rename

* Clean up

* Add comments

* Clean up

* Clean up

* Clean up

* Remove event-target-shim

* Add entry

* Improve robustness

* Update PR number

* Rename

* Fix cancelling synthesize test

* Remove unnecessary screenshots

* Remove screenshot
  • Loading branch information
compulim committed Jul 9, 2019
1 parent faef214 commit e8dc03d
Show file tree
Hide file tree
Showing 17 changed files with 495 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Added documentation for using Web Chat dev build, by [@corinagum](https://github.com/corinagum), in PR [#2074](https://github.com/Microsoft/BotFramework-WebChat/pull/2074)
- Added the Web Chat version to DirectLine's botAgent option, by [@tdurnford](https://github.com/tdurnford), in PR [#2101](https://github.com/Microsoft/BotFramework-WebChat/pull/2101)
- Added `richCardWrapTitle` to `defaultStyleOptions`, by [@tdurnford](https://github.com/tdurnford), in PR [#2115](https://github.com/Microsoft/BotFramework-WebChat/pull/2115)
- Added test harness for speech recognition and synthesis for [#2122](https://github.com/microsoft/BotFramework-WebChat/issues/2122), by [@compulim](https://github.com/compulim), in PR [#2153](https://github.com/Microsoft/BotFramework-WebChat/pull/2153)

### Changed

Expand Down
3 changes: 2 additions & 1 deletion __tests__/constants.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"navigation": 10000,
"postActivity": 30000,
"scrollToBottom": 1000,
"test": 60000
"test": 60000,
"ui": 1000
}
}
15 changes: 15 additions & 0 deletions __tests__/setup/conditions/speechRecognitionStarted.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Condition } from 'selenium-webdriver';

import isRecognizingSpeech from '../pageObjects/isRecognizingSpeech';

export default function speechRecognitionStarted() {
return new Condition('Speech recognition to start', async driver => await isRecognizingSpeech(driver));
}

function negate() {
const condition = speechRecognitionStarted();

return new Condition('Speech recognition not started', async driver => !(await condition.fn(driver)));
}

export { negate };
15 changes: 15 additions & 0 deletions __tests__/setup/conditions/speechSynthesisPending.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Condition } from 'selenium-webdriver';

import hasPendingSpeechSynthesisUtterance from '../pageObjects/hasPendingSpeechSynthesisUtterance';

export default function speechSynthesisPending() {
return new Condition('Speech synthesis is pending', async driver => await hasPendingSpeechSynthesisUtterance(driver));
}

function negate() {
const condition = speechSynthesisPending();

return new Condition('Speech synthesis is not pending', async driver => !(await condition.fn(driver)));
}

export { negate };
5 changes: 5 additions & 0 deletions __tests__/setup/pageObjects/endSpeechSynthesize.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import executePromiseScript from './executePromiseScript';

export default async function endSpeechSynthesize(driver) {
return await executePromiseScript(driver, () => window.WebSpeechMock.mockEndSynthesize());
}
25 changes: 25 additions & 0 deletions __tests__/setup/pageObjects/executePromiseScript.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// executeAsyncScript is not running a Promise function and is not able to deal with errors.
// https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/index_exports_WebDriver.html#executeAsyncScript
// This function will use executeAsyncScript to run a Promise function in an async fashion.

export default async function executePromiseScript(driver, fn, ...args) {
const { error, result } = await driver.executeAsyncScript(
(fn, args, callback) => {
eval(`(${fn})`)
.apply(null, args)
.then(result => callback({ result }), error => callback({ error }));
},
fn + '',
args
);

if (error) {
const err = new Error(error.message);

err.stack = error.stack;

throw err;
} else {
return result;
}
}
5 changes: 5 additions & 0 deletions __tests__/setup/pageObjects/getMicrophoneButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { By } from 'selenium-webdriver';

export default async function getMicrophoneButton(driver) {
return await driver.findElement(By.css('[aria-controls="webchatSendBoxMicrophoneButton"] > button'));
}
5 changes: 5 additions & 0 deletions __tests__/setup/pageObjects/getSendBoxTextBox.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { By } from 'selenium-webdriver';

export default async function isRecognizingSpeech(driver) {
return await driver.findElement(By.css('[role="form"] > * > form > input[type="text"]'));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default async function hasPendingSpeechSynthesisUtterance(driver) {
return await driver.executeScript(() => window.WebSpeechMock.hasPendingUtterance());
}
18 changes: 17 additions & 1 deletion __tests__/setup/pageObjects/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import dispatchAction from './dispatchAction';
import endSpeechSynthesize from './endSpeechSynthesize';
import executePromiseScript from './executePromiseScript';
import getMicrophoneButton from './getMicrophoneButton';
import getSendBoxTextBox from './getSendBoxTextBox';
import hasPendingSpeechSynthesisUtterance from './hasPendingSpeechSynthesisUtterance';
import isRecognizingSpeech from './isRecognizingSpeech';
import pingBot from './pingBot';
import putSpeechRecognitionResult from './putSpeechRecognitionResult';
import sendMessageViaSendBox from './sendMessageViaSendBox';
import startSpeechSynthesize from './startSpeechSynthesize';

function mapMap(map, mapper) {
return Object.keys(map).reduce((final, key) => {
Expand All @@ -14,8 +22,16 @@ export default function pageObjects(driver) {
return mapMap(
{
dispatchAction,
endSpeechSynthesize,
executePromiseScript,
getMicrophoneButton,
getSendBoxTextBox,
hasPendingSpeechSynthesisUtterance,
isRecognizingSpeech,
pingBot,
sendMessageViaSendBox
putSpeechRecognitionResult,
sendMessageViaSendBox,
startSpeechSynthesize
},
fn => fn.bind(null, driver)
);
Expand Down
3 changes: 3 additions & 0 deletions __tests__/setup/pageObjects/isRecognizingSpeech.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default async function isRecognizingSpeech(driver) {
return await driver.executeScript(() => window.WebSpeechMock.isRecognizing());
}
3 changes: 3 additions & 0 deletions __tests__/setup/pageObjects/putSpeechRecognitionResult.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default async function putSpeechRecognitionResult(driver, ...args) {
await driver.executeScript((...args) => window.WebSpeechMock.mockRecognize(...args), ...args);
}
5 changes: 3 additions & 2 deletions __tests__/setup/pageObjects/sendMessageViaSendBox.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { By, Key } from 'selenium-webdriver';
import { Key } from 'selenium-webdriver';

import { timeouts } from '../../constants.json';
import allOutgoingActivitiesSent from '../conditions/allOutgoingActivitiesSent';
import getSendBoxTextBox from './getSendBoxTextBox';

export default async function sendMessageViaSendBox(driver, text, { waitForSend = true }) {
const input = await driver.findElement(By.css('[role="form"] > * > form > input[type="text"]'));
const input = await getSendBoxTextBox(driver);

await input.sendKeys(text, Key.RETURN);

Expand Down
3 changes: 3 additions & 0 deletions __tests__/setup/pageObjects/startSpeechSynthesize.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default async function startSpeechSynthesize(driver) {
return await driver.executeScript(() => window.WebSpeechMock.mockStartSynthesize());
}
4 changes: 3 additions & 1 deletion __tests__/setup/web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
width: 100%;
}
</style>
<script src="https://unpkg.com/event-target-shim@5.0.1/dist/event-target-shim.umd.js"></script>
<script src="/mockWebSpeech.js"></script>
</head>
<body>
<div id="webchat" role="main"></div>
Expand Down Expand Up @@ -143,4 +145,4 @@
};
</script>
</body>
</html>
</html>
Loading

0 comments on commit e8dc03d

Please sign in to comment.