Skip to content

Commit 19d25b7

Browse files
authored
Move class components to React Hooks (#2322)
* Move to functional components * Add changelog update * eslint fix * Update CHANGELOG.md * JSONDebugView fix * Relative time to functional component * Fix non exported CroppedImage * Fix clock skew tests * Update Contributing documentation * Add new root scripts * Refactor playground to React Hooks * Refactor * Fix CHANGELOG entry * Refactor package.json * Convert ConnectivityStatus to hooks * Fix debounce time * Wait for all images to ready * Remove console * Improve test reliability * Move to functional components * Add changelog update * eslint fix * Update CHANGELOG.md * JSONDebugView fix * Relative time to functional component * Fix non exported CroppedImage * Fix clock skew tests * Update Contributing documentation * Add new root scripts * Refactor playground to React Hooks * Refactor * Fix CHANGELOG entry * Refactor package.json * Convert ConnectivityStatus to hooks * Fix debounce time * Wait for all images to ready * Remove console * Improve test reliability * Update PR number * Apply suggestions from code review Co-Authored-By: William Wong <[email protected]> * PR fixes
1 parent eb6aa67 commit 19d25b7

38 files changed

Lines changed: 1103 additions & 1163 deletions

.github/CONTRIBUTING.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ There are 3 types of build tasks in the build process.
3737
We built a playground app for testing Web Chat so we can test certain Web Chat specific features.
3838

3939
```sh
40-
cd packages/playground
41-
npm start
40+
npm run start:playground
4241
```
4342

4443
Then browse to http://localhost:3000/, and click on one of the connection options on the upper right corner.

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
6565
- `samples/*`: Move to production version of Web Chat, and bump to [`[email protected]`](https://www.npmjs.com/package/react) and [`[email protected]`](https://www.npmjs.com/package/react-dom)
6666
- Moved the typing indicator to the send box and removed the typing indicator logic from the sagas, by [@tdurnford](https://github.com/tdurnford), in PR [#2321](https://github.com/microsoft/BotFramework-WebChat/pull/2321)
6767
- `component`: Move `Composer` to React hooks and functional components, by [@compulim](https://github.com), in PR [#2308](https://github.com/compulim/BotFramework-WebChat/pull/2308)
68+
- `component`: Fix [#1818](https://github.com/microsoft/BotFramework-WebChat/issues/1818) Move to functional components by [@corinagum](https://github.com/corinagum), in PR [#2322](https://github.com/microsoft/BotFramework-WebChat/pull/2322)
6869

6970
### Fixed
7071

__tests__/README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
Automated testing in Web Chat is using multiple open-source technologies.
44

5-
- [Travis CI](https://travis-ci.org/) for automatic testing
5+
- [Azure DevOps](https://azure.microsoft.com/en-us/services/devops/) for automatic testing
66
- Test against [MockBot](https://github.com/compulim/BotFramework-MockBot)
77
- Try it out with this [live demo](https://microsoft.github.io/BotFramework-WebChat/01.a.getting-started-full-bundle)
8-
- Visual regression test (a.k.a. compare screenshots)
8+
- Visual regression tests (a.k.a. compare screenshots)
99
- Generated on [Chrome on Docker](https://github.com/SeleniumHQ/docker-selenium)
1010
- Compared using [`pixelmatch`](https://npmjs.com/package/pixelmatch) via [`jest-image-snapshot`](https://npmjs.com/package/jest-image-snapshot)
1111
- Run under [`Jest`](https://jestjs.io/)
@@ -16,7 +16,8 @@ Automated testing in Web Chat is using multiple open-source technologies.
1616

1717
- Install Docker
1818
- On Windows, set environment variable `COMPOSE_CONVERT_WINDOWS_PATHS=1`
19-
- `docker-compose up --build`
19+
- `npm run start:docker`
20+
- In a separate terminal, run:
2021
- `npm test`
2122

2223
### Running tests under local box
44.5 KB
Loading

__tests__/clockSkew.js

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { By, Condition, Key } from 'selenium-webdriver';
1+
import { By } from 'selenium-webdriver';
22

33
import { imageSnapshotOptions, timeouts } from './constants.json';
4+
import allImagesLoaded from './setup/conditions/allImagesLoaded';
45
import allOutgoingActivitiesSent from './setup/conditions/allOutgoingActivitiesSent';
56
import minNumActivitiesShown from './setup/conditions/minNumActivitiesShown';
67
import uiConnected from './setup/conditions/uiConnected';
@@ -11,8 +12,10 @@ import uiConnected from './setup/conditions/uiConnected';
1112
jest.setTimeout(timeouts.test);
1213

1314
describe('Clock skew', () => {
14-
test('should not have any effects', async () => {
15-
const { driver, pageObjects } = await setupWebDriver({
15+
let driver, pageObjects;
16+
17+
beforeEach(async () => {
18+
const result = await setupWebDriver({
1619
createDirectLine: options => {
1720
const workingDirectLine = window.WebChat.createDirectLine(options);
1821
const activityBroker = window.createProduceConsumeBroker();
@@ -67,6 +70,11 @@ describe('Clock skew', () => {
6770
}
6871
});
6972

73+
driver = result.driver;
74+
pageObjects = result.pageObjects;
75+
});
76+
77+
test('should not have any effects', async () => {
7078
await driver.wait(uiConnected(), timeouts.directLine);
7179
await pageObjects.sendMessageViaSendBox('card bingsports', { waitForSend: false });
7280

@@ -75,16 +83,17 @@ describe('Clock skew', () => {
7583
await driver.wait(minNumActivitiesShown(2), timeouts.directLine);
7684
await driver.wait(allOutgoingActivitiesSent(), timeouts.directLine);
7785

78-
// Specifically set a large clock skew to make sure the 2nd user-originated activity has a positive clock skew.
86+
// Specifically set a large clock skew to make sure the 2nd user-originated activity has a positive clock skew (appears on bottom).
7987
// A large positive clock skew is used to test if it is below the 2nd bot-originated activity or not.
88+
// Recently, we found the clock in the Docker image has a clockskew of 1.1 hours. So putting a huge number like 10 days should make it work.
8089
await pageObjects.dispatchAction({
81-
payload: { value: 120000 },
90+
payload: { value: 864000000 },
8291
type: 'WEB_CHAT/SET_CLOCK_SKEW_ADJUSTMENT'
8392
});
8493

8594
// Make sure the clock skew is set correctly.
8695
// If it is not set, the result could be false-positive.
87-
await expect(pageObjects.getStore()).resolves.toHaveProperty('clockSkewAdjustment', 120000);
96+
await expect(pageObjects.getStore()).resolves.toHaveProperty('clockSkewAdjustment', 864000000);
8897

8998
await pageObjects.sendMessageViaSendBox('echo This outgoing activity should be the last in the list.', {
9099
waitForSend: false
@@ -103,4 +112,46 @@ describe('Clock skew', () => {
103112

104113
expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions);
105114
});
115+
116+
test('faking clock skew should affect activity order', async () => {
117+
await driver.wait(uiConnected(), timeouts.directLine);
118+
await pageObjects.sendMessageViaSendBox('card bingsports', { waitForSend: false });
119+
120+
await driver.executeScript(() => window.WebChatTest.releaseActivity(2));
121+
122+
await driver.wait(minNumActivitiesShown(2), timeouts.directLine);
123+
await driver.wait(allOutgoingActivitiesSent(), timeouts.directLine);
124+
125+
// Specifically set a large clock skew to make sure the 2nd user-originated activity has a negative clock skew (appears on top).
126+
await pageObjects.dispatchAction({
127+
payload: { value: -864000000 },
128+
type: 'WEB_CHAT/SET_CLOCK_SKEW_ADJUSTMENT'
129+
});
130+
131+
// Make sure the clock skew is set correctly.
132+
// If it is not set, the result could be false-positive.
133+
await expect(pageObjects.getStore()).resolves.toHaveProperty('clockSkewAdjustment', -864000000);
134+
135+
await pageObjects.sendMessageViaSendBox(
136+
'echo This outgoing activity should be the first in the list before echo back, and last after the echo back.',
137+
{
138+
waitForSend: false
139+
}
140+
);
141+
142+
await driver.wait(minNumActivitiesShown(3), timeouts.directLine);
143+
144+
const firstActivity = await driver.findElement(By.css('[role="list"] > li:first-child p'));
145+
146+
await expect(firstActivity.getText()).resolves.toBe(
147+
'echo This outgoing activity should be the first in the list before echo back, and last after the echo back.'
148+
);
149+
150+
await driver.executeScript(() => window.WebChatTest.releaseActivity(3));
151+
await driver.wait(minNumActivitiesShown(5), timeouts.directLine);
152+
await driver.wait(allOutgoingActivitiesSent(), timeouts.directLine);
153+
await driver.wait(allImagesLoaded(), timeouts.fetch);
154+
155+
expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions);
156+
});
106157
});

__tests__/disabledUI.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { imageSnapshotOptions, timeouts } from './constants.json';
2+
import uiConnected from './setup/conditions/uiConnected.js';
23

34
// selenium-webdriver API doc:
45
// https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/index_exports_WebDriver.html
@@ -12,6 +13,8 @@ describe('tests the UI of disabled Web Chat', () => {
1213

1314
const { driver } = await setupWebDriver({ props: { styleOptions, disabled } });
1415

16+
await driver.wait(uiConnected(), timeouts.directLine);
17+
1518
const base64PNG = await driver.takeScreenshot();
1619

1720
expect(base64PNG).toMatchImageSnapshot(imageSnapshotOptions);

__tests__/offlineUI.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,9 @@ describe('offline UI', () => {
384384
await driver.wait(minNumActivitiesShown(2), timeouts.directLine);
385385
await driver.wait(actionDispatched('WEB_CHAT/SAGA_ERROR'), timeouts.directLine);
386386

387+
// Wait until error status come up
388+
await driver.wait(async () => /render error/iu.test(await pageObjects.getNotificationText()), timeouts.ui);
389+
387390
const base64PNG = await driver.takeScreenshot();
388391

389392
expect(base64PNG).toMatchImageSnapshot(imageSnapshotOptions);

__tests__/setup/conditions/allImagesLoaded.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Condition } from 'selenium-webdriver';
22

33
export default function allImagesLoaded() {
44
return new Condition(
5-
'Waiting for all images to be loaded',
5+
'all images to be loaded',
66
async driver =>
77
await driver.executeScript(() => [].every.call(document.querySelectorAll('img'), ({ complete }) => complete))
88
);
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { By } from 'selenium-webdriver';
2+
3+
export default async function getNotificationText(driver) {
4+
const notificationTextAriaLabel = driver.findElement(By.css('[role="status"] > [aria-label]'));
5+
6+
if (notificationTextAriaLabel) {
7+
return await notificationTextAriaLabel.getAttribute('innerText');
8+
}
9+
}

__tests__/setup/pageObjects/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import dispatchAction from './dispatchAction';
55
import endSpeechSynthesize from './endSpeechSynthesize';
66
import errorSpeechSynthesize from './errorSpeechSynthesize';
77
import executePromiseScript from './executePromiseScript';
8+
import getNotificationText from './getNotificationText';
89
import getNumActivitiesShown from './getNumActivitiesShown';
910
import getSendBoxText from './getSendBoxText';
1011
import getStore from './getStore';
@@ -35,6 +36,7 @@ export default function pageObjects(driver) {
3536
endSpeechSynthesize,
3637
errorSpeechSynthesize,
3738
executePromiseScript,
39+
getNotificationText,
3840
getNumActivitiesShown,
3941
getSendBoxText,
4042
getStore,

0 commit comments

Comments
 (0)