diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d72646fd8..85029e2fe1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,7 +49,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - `connectCarouselFilmStrip`: Fixed `botAvatarInitials` and `userAvatarInitials` functionality from [recent name change](https://github.com/Microsoft/BotFramework-WebChat/pull/1486), - `BasicTranscript`: Fixed user activity should not be recreated after receive ACK from Direct Line, - by [@corinagum](https://github.com/corinagum) in PR [#1528](https://github.com/Microsoft/BotFramework-WebChat/pull/1528) -- `component`: Fix [#1560](https://github.com/Microsoft/BotFramework-WebChat/issues/1560). Fixed carousel layout did not show date and alignment issues, by [@compulim](https://github.com/compulim) in PR [#1561](https://github.com/Microsoft/BotFramework-WebChat/pull/1561) +- `component`: Fix [#1560](https://github.com/Microsoft/BotFramework-WebChat/issues/1560), [#1625](https://github.com/Microsoft/BotFramework-WebChat/issues/1625) and [#1635](https://github.com/Microsoft/BotFramework-WebChat/issues/1635). Fixed carousel layout not showing date and alignment issues, by [@compulim](https://github.com/compulim) in PR [#1561](https://github.com/Microsoft/BotFramework-WebChat/pull/1561) and [#1641](https://github.com/Microsoft/BotFramework-WebChat/pull/1641) - `playground`: Fix [#1562](https://github.com/Microsoft/BotFramework-WebChat/issues/1562). Fixed timestamp grouping "Don't group" and added "Don't show timestamp", by [@compulim](https://github.com/compulim) in PR [#1563](https://github.com/Microsoft/BotFramework-WebChat/pull/1563) - `component`: Fix [#1576](https://github.com/Microsoft/BotFramework-WebChat/issues/1576). Rich card without `tap` should be rendered properly, by [@compulim](https://github.com/compulim) in PR [#1577](https://github.com/Microsoft/BotFramework-WebChat/pull/1577) - `core`: Some sagas missed handling successive actions, in PR [#1286](https://github.com/Microsoft/BotFramework-WebChat/pull/1286) diff --git a/__tests__/__image_snapshots__/chrome-docker/basic-js-setup-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/basic-js-setup-1-snap.png index b118aa0d39..4f7d2fb224 100644 Binary files a/__tests__/__image_snapshots__/chrome-docker/basic-js-setup-1-snap.png and b/__tests__/__image_snapshots__/chrome-docker/basic-js-setup-1-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-with-avatar-initials-1-attachment-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-with-avatar-initials-1-attachment-1-snap.png new file mode 100644 index 0000000000..79f76ee28d Binary files /dev/null and b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-with-avatar-initials-1-attachment-1-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-with-avatar-initials-1-attachment-with-wide-screen-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-with-avatar-initials-1-attachment-with-wide-screen-1-snap.png new file mode 100644 index 0000000000..36758e6036 Binary files /dev/null and b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-with-avatar-initials-1-attachment-with-wide-screen-1-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-with-avatar-initials-2-attachments-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-with-avatar-initials-2-attachments-1-snap.png new file mode 100644 index 0000000000..3cd9d4d515 Binary files /dev/null and b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-with-avatar-initials-2-attachments-1-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-with-avatar-initials-2-attachments-with-wide-screen-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-with-avatar-initials-2-attachments-with-wide-screen-1-snap.png new file mode 100644 index 0000000000..732cd519f6 Binary files /dev/null and b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-with-avatar-initials-2-attachments-with-wide-screen-1-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-with-avatar-initials-4-attachments-and-message-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-with-avatar-initials-4-attachments-and-message-1-snap.png new file mode 100644 index 0000000000..bbaa798f2e Binary files /dev/null and b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-with-avatar-initials-4-attachments-and-message-1-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-with-avatar-initials-4-attachments-and-message-2-snap.png b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-with-avatar-initials-4-attachments-and-message-2-snap.png new file mode 100644 index 0000000000..a3bf5234a2 Binary files /dev/null and b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-with-avatar-initials-4-attachments-and-message-2-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-with-avatar-initials-4-attachments-and-no-message-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-with-avatar-initials-4-attachments-and-no-message-1-snap.png new file mode 100644 index 0000000000..8434b1f82c Binary files /dev/null and b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-with-avatar-initials-4-attachments-and-no-message-1-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-with-avatar-initials-4-attachments-and-no-message-2-snap.png b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-with-avatar-initials-4-attachments-and-no-message-2-snap.png new file mode 100644 index 0000000000..eba8ea3f93 Binary files /dev/null and b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-with-avatar-initials-4-attachments-and-no-message-2-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-without-avatar-initials-1-attachment-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-without-avatar-initials-1-attachment-1-snap.png new file mode 100644 index 0000000000..33ce330996 Binary files /dev/null and b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-without-avatar-initials-1-attachment-1-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-without-avatar-initials-1-attachment-with-wide-screen-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-without-avatar-initials-1-attachment-with-wide-screen-1-snap.png new file mode 100644 index 0000000000..6dcce64744 Binary files /dev/null and b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-without-avatar-initials-1-attachment-with-wide-screen-1-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-without-avatar-initials-2-attachments-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-without-avatar-initials-2-attachments-1-snap.png new file mode 100644 index 0000000000..ae408450c3 Binary files /dev/null and b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-without-avatar-initials-2-attachments-1-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-without-avatar-initials-2-attachments-with-wide-screen-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-without-avatar-initials-2-attachments-with-wide-screen-1-snap.png new file mode 100644 index 0000000000..2905fe0dc3 Binary files /dev/null and b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-without-avatar-initials-2-attachments-with-wide-screen-1-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-without-avatar-initials-4-attachments-and-message-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-without-avatar-initials-4-attachments-and-message-1-snap.png new file mode 100644 index 0000000000..4f7d2fb224 Binary files /dev/null and b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-without-avatar-initials-4-attachments-and-message-1-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-without-avatar-initials-4-attachments-and-message-2-snap.png b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-without-avatar-initials-4-attachments-and-message-2-snap.png new file mode 100644 index 0000000000..9e04001082 Binary files /dev/null and b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-without-avatar-initials-4-attachments-and-message-2-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-without-avatar-initials-4-attachments-and-no-message-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-without-avatar-initials-4-attachments-and-no-message-1-snap.png new file mode 100644 index 0000000000..a6956b8cf9 Binary files /dev/null and b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-without-avatar-initials-4-attachments-and-no-message-1-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-without-avatar-initials-4-attachments-and-no-message-2-snap.png b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-without-avatar-initials-4-attachments-and-no-message-2-snap.png new file mode 100644 index 0000000000..5cdc3b2e03 Binary files /dev/null and b/__tests__/__image_snapshots__/chrome-docker/carousel-js-carousel-without-avatar-initials-4-attachments-and-no-message-2-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/stacked-js-stacked-with-avatar-initials-1-attachment-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/stacked-js-stacked-with-avatar-initials-1-attachment-1-snap.png new file mode 100644 index 0000000000..d04459131d Binary files /dev/null and b/__tests__/__image_snapshots__/chrome-docker/stacked-js-stacked-with-avatar-initials-1-attachment-1-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/stacked-js-stacked-with-avatar-initials-1-attachment-with-wide-screen-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/stacked-js-stacked-with-avatar-initials-1-attachment-with-wide-screen-1-snap.png new file mode 100644 index 0000000000..b5fd26d704 Binary files /dev/null and b/__tests__/__image_snapshots__/chrome-docker/stacked-js-stacked-with-avatar-initials-1-attachment-with-wide-screen-1-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/stacked-js-stacked-with-avatar-initials-4-attachments-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/stacked-js-stacked-with-avatar-initials-4-attachments-1-snap.png new file mode 100644 index 0000000000..6fb33879af Binary files /dev/null and b/__tests__/__image_snapshots__/chrome-docker/stacked-js-stacked-with-avatar-initials-4-attachments-1-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/stacked-js-stacked-without-avatar-initials-1-attachment-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/stacked-js-stacked-without-avatar-initials-1-attachment-1-snap.png new file mode 100644 index 0000000000..83641110f7 Binary files /dev/null and b/__tests__/__image_snapshots__/chrome-docker/stacked-js-stacked-without-avatar-initials-1-attachment-1-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/stacked-js-stacked-without-avatar-initials-1-attachment-with-wide-screen-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/stacked-js-stacked-without-avatar-initials-1-attachment-with-wide-screen-1-snap.png new file mode 100644 index 0000000000..54c4bd36d1 Binary files /dev/null and b/__tests__/__image_snapshots__/chrome-docker/stacked-js-stacked-without-avatar-initials-1-attachment-with-wide-screen-1-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/stacked-js-stacked-without-avatar-initials-4-attachments-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/stacked-js-stacked-without-avatar-initials-4-attachments-1-snap.png new file mode 100644 index 0000000000..013ad0543e Binary files /dev/null and b/__tests__/__image_snapshots__/chrome-docker/stacked-js-stacked-without-avatar-initials-4-attachments-1-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/suggested-actions-js-suggested-actions-command-should-show-correctly-formatted-buttons-when-suggested-actions-are-displayed-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/suggested-actions-js-suggested-actions-command-should-show-correctly-formatted-buttons-when-suggested-actions-are-displayed-1-snap.png index 196741d985..7dc8b066d5 100644 Binary files a/__tests__/__image_snapshots__/chrome-docker/suggested-actions-js-suggested-actions-command-should-show-correctly-formatted-buttons-when-suggested-actions-are-displayed-1-snap.png and b/__tests__/__image_snapshots__/chrome-docker/suggested-actions-js-suggested-actions-command-should-show-correctly-formatted-buttons-when-suggested-actions-are-displayed-1-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/suggested-actions-js-suggested-actions-command-should-show-response-from-bot-and-no-text-from-user-on-imback-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/suggested-actions-js-suggested-actions-command-should-show-response-from-bot-and-no-text-from-user-on-imback-1-snap.png index 0bbb8694b1..574c2e1b88 100644 Binary files a/__tests__/__image_snapshots__/chrome-docker/suggested-actions-js-suggested-actions-command-should-show-response-from-bot-and-no-text-from-user-on-imback-1-snap.png and b/__tests__/__image_snapshots__/chrome-docker/suggested-actions-js-suggested-actions-command-should-show-response-from-bot-and-no-text-from-user-on-imback-1-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/suggested-actions-js-suggested-actions-command-should-show-response-from-bot-and-no-text-from-user-on-messageback-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/suggested-actions-js-suggested-actions-command-should-show-response-from-bot-and-no-text-from-user-on-messageback-1-snap.png index 896b3e4425..641d0a72b0 100644 Binary files a/__tests__/__image_snapshots__/chrome-docker/suggested-actions-js-suggested-actions-command-should-show-response-from-bot-and-no-text-from-user-on-messageback-1-snap.png and b/__tests__/__image_snapshots__/chrome-docker/suggested-actions-js-suggested-actions-command-should-show-response-from-bot-and-no-text-from-user-on-messageback-1-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/suggested-actions-js-suggested-actions-command-should-show-response-from-bot-and-no-text-from-user-on-postback-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/suggested-actions-js-suggested-actions-command-should-show-response-from-bot-and-no-text-from-user-on-postback-1-snap.png index e92c381586..cf5dc1b0e4 100644 Binary files a/__tests__/__image_snapshots__/chrome-docker/suggested-actions-js-suggested-actions-command-should-show-response-from-bot-and-no-text-from-user-on-postback-1-snap.png and b/__tests__/__image_snapshots__/chrome-docker/suggested-actions-js-suggested-actions-command-should-show-response-from-bot-and-no-text-from-user-on-postback-1-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/suggested-actions-js-suggested-actions-command-should-show-response-from-bot-and-text-from-user-on-messageback-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/suggested-actions-js-suggested-actions-command-should-show-response-from-bot-and-text-from-user-on-messageback-1-snap.png index 896b3e4425..8dc0ede019 100644 Binary files a/__tests__/__image_snapshots__/chrome-docker/suggested-actions-js-suggested-actions-command-should-show-response-from-bot-and-text-from-user-on-messageback-1-snap.png and b/__tests__/__image_snapshots__/chrome-docker/suggested-actions-js-suggested-actions-command-should-show-response-from-bot-and-text-from-user-on-messageback-1-snap.png differ diff --git a/__tests__/__image_snapshots__/chrome-docker/suggested-actions-js-suggested-actions-command-should-show-response-from-bot-and-text-from-user-on-postback-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/suggested-actions-js-suggested-actions-command-should-show-response-from-bot-and-text-from-user-on-postback-1-snap.png index 0b711a4c29..81d2813349 100644 Binary files a/__tests__/__image_snapshots__/chrome-docker/suggested-actions-js-suggested-actions-command-should-show-response-from-bot-and-text-from-user-on-postback-1-snap.png and b/__tests__/__image_snapshots__/chrome-docker/suggested-actions-js-suggested-actions-command-should-show-response-from-bot-and-text-from-user-on-postback-1-snap.png differ diff --git a/__tests__/basic.js b/__tests__/basic.js index a47e2f43e5..26022cf493 100644 --- a/__tests__/basic.js +++ b/__tests__/basic.js @@ -1,6 +1,8 @@ import { By, Key } from 'selenium-webdriver'; -import { imageSnapshotOptions } from './constants.json'; +import { imageSnapshotOptions, timeouts } from './constants.json'; + +import allImagesLoaded from './setup/conditions/allImagesLoaded.js'; import directLineConnected from './setup/conditions/directLineConnected'; import minNumActivitiesReached from './setup/conditions/minNumActivitiesReached'; import webChatLoaded from './setup/conditions/webChatLoaded'; @@ -9,21 +11,19 @@ import webChatLoaded from './setup/conditions/webChatLoaded'; // https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/index_exports_WebDriver.html test('setup', async () => { - const { driver } = await setupWebDriver(); + const { driver, pageObjects } = await setupWebDriver(); - await driver.wait(webChatLoaded(), 2000); - await driver.wait(directLineConnected(), 2000); + await driver.wait(webChatLoaded(), timeouts.navigation); + await driver.wait(directLineConnected(), timeouts.directLine); - const input = await driver.findElement(By.tagName('input[type="text"]')); + const input = await driver.findElement(By.css('input[type="text"]')); await input.sendKeys('layout carousel', Key.RETURN); - await driver.wait(minNumActivitiesReached(2), 2000); - - // TODO: [P2] Remove this sleep which wait for the image to be loaded - await driver.sleep(1000); + await driver.wait(minNumActivitiesReached(3), timeouts.directLine); + await driver.wait(allImagesLoaded(), timeouts.fetch); // Hide cursor before taking screenshot - await driver.executeScript(() => document.querySelector(':focus').blur()); + await pageObjects.hideCursor(); const base64PNG = await driver.takeScreenshot(); diff --git a/__tests__/carousel.js b/__tests__/carousel.js new file mode 100644 index 0000000000..c3fe8ed58f --- /dev/null +++ b/__tests__/carousel.js @@ -0,0 +1,280 @@ +import { By, Key } from 'selenium-webdriver'; + +import { imageSnapshotOptions, timeouts } from './constants.json'; +import allImagesLoaded from './setup/conditions/allImagesLoaded'; +import directLineConnected from './setup/conditions/directLineConnected'; +import minNumActivitiesReached from './setup/conditions/minNumActivitiesReached'; +import webChatLoaded from './setup/conditions/webChatLoaded'; + +// selenium-webdriver API doc: +// https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/index_exports_WebDriver.html + +describe('carousel without avatar initials', () => { + test('4 attachments and no message', async () => { + const { driver, pageObjects } = await setupWebDriver(); + + await driver.wait(webChatLoaded(), timeouts.navigation); + await driver.wait(directLineConnected(), timeouts.directLine); + + const input = await driver.findElement(By.css('input[type="text"]')); + + await input.sendKeys('carousel', Key.RETURN); + await driver.wait(minNumActivitiesReached(3), timeouts.directLine); + await driver.wait(allImagesLoaded(), timeouts.fetch); + + // Hide cursor before taking screenshot + await pageObjects.hideCursor(); + + expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); + + const rightFlipper = await driver.findElement(By.css('button[aria-label="Right"]')); + + await rightFlipper.click(); + await rightFlipper.click(); + await rightFlipper.click(); + await rightFlipper.click(); + + // Wait for carousel animation to finish + await driver.sleep(1000); + + expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); + }, 60000); + + test('4 attachments and message', async () => { + const { driver, pageObjects } = await setupWebDriver(); + + await driver.wait(webChatLoaded(), timeouts.navigation); + await driver.wait(directLineConnected(), timeouts.directLine); + + const input = await driver.findElement(By.css('input[type="text"]')); + + await input.sendKeys('layout carousel', Key.RETURN); + await driver.wait(minNumActivitiesReached(3), timeouts.directLine); + await driver.wait(allImagesLoaded(), timeouts.fetch); + + // Hide cursor before taking screenshot + await pageObjects.hideCursor(); + + expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); + + const rightFlipper = await driver.findElement(By.css('button[aria-label="Right"]')); + + await rightFlipper.click(); + await rightFlipper.click(); + await rightFlipper.click(); + await rightFlipper.click(); + + // Wait for carousel animation to finish + await driver.sleep(1000); + + expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); + }, 60000); + + test('2 attachments', async () => { + const { driver, pageObjects } = await setupWebDriver(); + + await driver.wait(webChatLoaded(), timeouts.navigation); + await driver.wait(directLineConnected(), timeouts.directLine); + + const input = await driver.findElement(By.css('input[type="text"]')); + + await input.sendKeys('layout double', Key.RETURN); + await driver.wait(minNumActivitiesReached(3), timeouts.directLine); + await driver.wait(allImagesLoaded(), timeouts.fetch); + + // Hide cursor before taking screenshot + await pageObjects.hideCursor(); + + expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); + }, 60000); + + test('2 attachments with wide screen', async () => { + const { driver, pageObjects } = await setupWebDriver({ width: 640 }); + + await driver.wait(webChatLoaded(), timeouts.navigation); + await driver.wait(directLineConnected(), timeouts.directLine); + + const input = await driver.findElement(By.css('input[type="text"]')); + + await input.sendKeys('layout double', Key.RETURN); + await driver.wait(minNumActivitiesReached(3), timeouts.directLine); + await driver.wait(allImagesLoaded(), timeouts.fetch); + + // Hide cursor before taking screenshot + await pageObjects.hideCursor(); + + expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); + }, 60000); + + test('1 attachment', async () => { + const { driver, pageObjects } = await setupWebDriver(); + + await driver.wait(webChatLoaded(), timeouts.navigation); + await driver.wait(directLineConnected(), timeouts.directLine); + + const input = await driver.findElement(By.css('input[type="text"]')); + + await input.sendKeys('layout single carousel', Key.RETURN); + await driver.wait(minNumActivitiesReached(3), timeouts.directLine); + await driver.wait(allImagesLoaded(), timeouts.fetch); + + // Hide cursor before taking screenshot + await pageObjects.hideCursor(); + + expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); + }, 60000); + + test('1 attachment with wide screen', async () => { + const { driver, pageObjects } = await setupWebDriver({ width: 640 }); + + await driver.wait(webChatLoaded(), timeouts.navigation); + await driver.wait(directLineConnected(), timeouts.directLine); + + const input = await driver.findElement(By.css('input[type="text"]')); + + await input.sendKeys('layout single carousel', Key.RETURN); + await driver.wait(minNumActivitiesReached(3), timeouts.directLine); + await driver.wait(allImagesLoaded(), timeouts.fetch); + + // Hide cursor before taking screenshot + await pageObjects.hideCursor(); + + expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); + }, 60000); +}); + +describe('carousel with avatar initials', () => { + const WEB_CHAT_PROPS = { styleOptions: { botAvatarInitials: 'BF', userAvatarInitials: 'WC' } }; + + test('4 attachments and no message', async () => { + const { driver, pageObjects } = await setupWebDriver({ props: WEB_CHAT_PROPS }); + + await driver.wait(webChatLoaded(), timeouts.navigation); + await driver.wait(directLineConnected(), timeouts.directLine); + + const input = await driver.findElement(By.css('input[type="text"]')); + + await input.sendKeys('carousel', Key.RETURN); + await driver.wait(minNumActivitiesReached(3), timeouts.directLine); + await driver.wait(allImagesLoaded(), timeouts.fetch); + + // Hide cursor before taking screenshot + await pageObjects.hideCursor(); + + expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); + + const rightFlipper = await driver.findElement(By.css('button[aria-label="Right"]')); + + await rightFlipper.click(); + await rightFlipper.click(); + await rightFlipper.click(); + await rightFlipper.click(); + + // Wait for carousel animation to finish + await driver.sleep(1000); + + expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); + }, 60000); + + test('4 attachments and message', async () => { + const { driver, pageObjects } = await setupWebDriver({ props: WEB_CHAT_PROPS }); + + await driver.wait(webChatLoaded(), timeouts.navigation); + await driver.wait(directLineConnected(), timeouts.directLine); + + const input = await driver.findElement(By.css('input[type="text"]')); + + await input.sendKeys('layout carousel', Key.RETURN); + await driver.wait(minNumActivitiesReached(3), timeouts.directLine); + await driver.wait(allImagesLoaded(), timeouts.fetch); + + // Hide cursor before taking screenshot + await pageObjects.hideCursor(); + + expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); + + const rightFlipper = await driver.findElement(By.css('button[aria-label="Right"]')); + + await rightFlipper.click(); + await rightFlipper.click(); + await rightFlipper.click(); + await rightFlipper.click(); + + // Wait for carousel animation to finish + await driver.sleep(1000); + + expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); + }, 60000); + + test('2 attachments', async () => { + const { driver, pageObjects } = await setupWebDriver({ props: WEB_CHAT_PROPS }); + + await driver.wait(webChatLoaded(), timeouts.navigation); + await driver.wait(directLineConnected(), timeouts.directLine); + + const input = await driver.findElement(By.css('input[type="text"]')); + + await input.sendKeys('layout double', Key.RETURN); + await driver.wait(minNumActivitiesReached(3), timeouts.directLine); + await driver.wait(allImagesLoaded(), timeouts.fetch); + + // Hide cursor before taking screenshot + await pageObjects.hideCursor(); + + expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); + }, 60000); + + test('2 attachments with wide screen', async () => { + const { driver, pageObjects } = await setupWebDriver({ props: WEB_CHAT_PROPS, width: 640 }); + + await driver.wait(webChatLoaded(), timeouts.navigation); + await driver.wait(directLineConnected(), timeouts.directLine); + + const input = await driver.findElement(By.css('input[type="text"]')); + + await input.sendKeys('layout double', Key.RETURN); + await driver.wait(minNumActivitiesReached(3), timeouts.directLine); + await driver.wait(allImagesLoaded(), timeouts.fetch); + + // Hide cursor before taking screenshot + await pageObjects.hideCursor(); + + expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); + }, 60000); + + test('1 attachment', async () => { + const { driver, pageObjects } = await setupWebDriver({ props: WEB_CHAT_PROPS }); + + await driver.wait(webChatLoaded(), timeouts.navigation); + await driver.wait(directLineConnected(), timeouts.directLine); + + const input = await driver.findElement(By.css('input[type="text"]')); + + await input.sendKeys('layout single carousel', Key.RETURN); + await driver.wait(minNumActivitiesReached(3), timeouts.directLine); + await driver.wait(allImagesLoaded(), timeouts.fetch); + + // Hide cursor before taking screenshot + await pageObjects.hideCursor(); + + expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); + }, 60000); + + test('1 attachment with wide screen', async () => { + const { driver, pageObjects } = await setupWebDriver({ props: WEB_CHAT_PROPS, width: 640 }); + + await driver.wait(webChatLoaded(), timeouts.navigation); + await driver.wait(directLineConnected(), timeouts.directLine); + + const input = await driver.findElement(By.css('input[type="text"]')); + + await input.sendKeys('layout single carousel', Key.RETURN); + await driver.wait(minNumActivitiesReached(3), timeouts.directLine); + await driver.wait(allImagesLoaded(), timeouts.fetch); + + // Hide cursor before taking screenshot + await pageObjects.hideCursor(); + + expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); + }, 60000); +}); diff --git a/__tests__/constants.json b/__tests__/constants.json index 2ccfc10131..226f6a7b25 100644 --- a/__tests__/constants.json +++ b/__tests__/constants.json @@ -3,5 +3,10 @@ "customDiffConfig": { "threshold": 0.14 } + }, + "timeouts": { + "directLine": 2500, + "fetch": 2500, + "navigation": 5000 } } diff --git a/__tests__/setup/conditions/allImagesLoaded.js b/__tests__/setup/conditions/allImagesLoaded.js new file mode 100644 index 0000000000..5798bb04c6 --- /dev/null +++ b/__tests__/setup/conditions/allImagesLoaded.js @@ -0,0 +1,7 @@ +import { Condition } from 'selenium-webdriver'; + +export default function () { + return new Condition('Waiting for all images to be loaded', async driver => + await driver.executeScript(() => [].every.call(document.querySelectorAll('img'), ({ complete }) => complete)) + ); +} diff --git a/__tests__/setup/conditions/allOutgoingActivitiesSent.js b/__tests__/setup/conditions/allOutgoingActivitiesSent.js new file mode 100644 index 0000000000..1ca02321ee --- /dev/null +++ b/__tests__/setup/conditions/allOutgoingActivitiesSent.js @@ -0,0 +1,12 @@ +import { Condition } from 'selenium-webdriver'; + +export default function () { + return new Condition('Waiting for Direct Line to connect', async driver => { + return await driver.executeScript(() => { + const { store } = window.WebChatTest; + const { activities } = store.getState(); + + return activities.filter(({ from: { role } }) => role === 'user').every(({ channelData: { state } }) => state === 'sent'); + }); + }); +} diff --git a/__tests__/setup/conditions/suggestedActionsShowed.js b/__tests__/setup/conditions/suggestedActionsShowed.js new file mode 100644 index 0000000000..8205c64b92 --- /dev/null +++ b/__tests__/setup/conditions/suggestedActionsShowed.js @@ -0,0 +1,5 @@ +import { By, until } from 'selenium-webdriver'; + +export default function () { + return until.elementLocated(By.css('[role="form"] ul')); +} diff --git a/__tests__/setup/pageObjects/hideCursor.js b/__tests__/setup/pageObjects/hideCursor.js new file mode 100644 index 0000000000..13a87c48bf --- /dev/null +++ b/__tests__/setup/pageObjects/hideCursor.js @@ -0,0 +1,3 @@ +export default async function hideCursor(driver) { + await driver.executeScript(() => document.querySelector(':focus').blur()); +} diff --git a/__tests__/setup/pageObjects/index.js b/__tests__/setup/pageObjects/index.js new file mode 100644 index 0000000000..a2c1dbfbd6 --- /dev/null +++ b/__tests__/setup/pageObjects/index.js @@ -0,0 +1,7 @@ +import hideCursor from './hideCursor'; + +export default function (driver) { + return { + hideCursor: hideCursor.bind(null, driver) + }; +} diff --git a/__tests__/setup/setupTestEnvironment.js b/__tests__/setup/setupTestEnvironment.js index 30f9aead99..5fc80c2d76 100644 --- a/__tests__/setup/setupTestEnvironment.js +++ b/__tests__/setup/setupTestEnvironment.js @@ -1,13 +1,13 @@ import { Options } from 'selenium-webdriver/chrome'; -export default function (browserName, builder) { +export default function (browserName, builder, { height, width } = {}) { switch (browserName) { case 'chrome-local': return { baseURL: 'http://localhost:$PORT/index.html', builder: builder.forBrowser('chrome').setChromeOptions( (builder.getChromeOptions() || new Options()) - .windowSize({ height: 640, width: 360 }) + .windowSize({ height: height || 640, width: width || 360 }) ) }; @@ -18,7 +18,7 @@ export default function (browserName, builder) { builder: builder.forBrowser('chrome').usingServer('http://localhost:4444/wd/hub').setChromeOptions( (builder.getChromeOptions() || new Options()) .headless() - .windowSize({ height: 640, width: 360 }) + .windowSize({ height: height || 640, width: width || 360 }) ) }; } diff --git a/__tests__/setup/setupTestFramework.js b/__tests__/setup/setupTestFramework.js index d55a31d5e1..42a1aff43a 100644 --- a/__tests__/setup/setupTestFramework.js +++ b/__tests__/setup/setupTestFramework.js @@ -6,6 +6,7 @@ import { configureToMatchImageSnapshot } from 'jest-image-snapshot'; import getPort from 'get-port'; import handler from 'serve-handler'; +import createPageObjects from './pageObjects/index'; import setupTestEnvironment from './setupTestEnvironment'; const BROWSER_NAME = process.env.WEBCHAT_TEST_ENV || 'chrome-docker'; @@ -21,10 +22,10 @@ expect.extend({ let driverPromise; let serverPromise; -global.setupWebDriver = async ({ props } = {}) => { +global.setupWebDriver = async (options = {}) => { if (!driverPromise) { driverPromise = (async () => { - let { baseURL, builder } = await setupTestEnvironment(BROWSER_NAME, new Builder()); + let { baseURL, builder } = await setupTestEnvironment(BROWSER_NAME, new Builder(), options); const driver = builder.build(); // If the baseURL contains $PORT, it means it requires us to fill-in @@ -36,12 +37,12 @@ global.setupWebDriver = async ({ props } = {}) => { await driver.get(baseURL); } - await driver.executeScript((coverage, options) => { + await driver.executeScript((coverage, props) => { window.__coverage__ = coverage; - main(options); - }, global.__coverage__, { props }); + main({ props }); + }, global.__coverage__, options.props); - return { driver }; + return { driver, pageObjects: createPageObjects(driver) }; })(); } diff --git a/__tests__/setup/web/index.html b/__tests__/setup/web/index.html index f968a7fc82..97103165e0 100644 --- a/__tests__/setup/web/index.html +++ b/__tests__/setup/web/index.html @@ -66,7 +66,7 @@ const res = await fetch('https://webchat-mockbot.azurewebsites.net/directline/token', { method: 'POST' }); const { token } = await res.json(); - const store = window.WebChat.createStore({}, () => next => action => { + const store = window.WebChatTest.store = window.WebChat.createStore({}, () => next => action => { window.WebChatTest.actions.push(action); return next(action); diff --git a/__tests__/stacked.js b/__tests__/stacked.js new file mode 100644 index 0000000000..460d40a5d7 --- /dev/null +++ b/__tests__/stacked.js @@ -0,0 +1,125 @@ +import { By, Key } from 'selenium-webdriver'; + +import { imageSnapshotOptions, timeouts } from './constants.json'; + +import allImagesLoaded from './setup/conditions/allImagesLoaded'; +import directLineConnected from './setup/conditions/directLineConnected'; +import minNumActivitiesReached from './setup/conditions/minNumActivitiesReached'; +import webChatLoaded from './setup/conditions/webChatLoaded'; + +// selenium-webdriver API doc: +// https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/index_exports_WebDriver.html + +describe('stacked without avatar initials', () => { + test('4 attachments', async () => { + const { driver, pageObjects } = await setupWebDriver(); + + await driver.wait(webChatLoaded(), timeouts.navigation); + await driver.wait(directLineConnected(), timeouts.directLine); + + const input = await driver.findElement(By.css('input[type="text"]')); + + await input.sendKeys('layout stacked', Key.RETURN); + await driver.wait(minNumActivitiesReached(3), timeouts.directLine); + await driver.wait(allImagesLoaded(), timeouts.fetch); + + // Hide cursor before taking screenshot + await pageObjects.hideCursor(); + + expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); + }, 60000); + + test('1 attachment', async () => { + const { driver, pageObjects } = await setupWebDriver(); + + await driver.wait(webChatLoaded(), timeouts.navigation); + await driver.wait(directLineConnected(), timeouts.directLine); + + const input = await driver.findElement(By.css('input[type="text"]')); + + await input.sendKeys('layout single', Key.RETURN); + await driver.wait(minNumActivitiesReached(3), timeouts.directLine); + await driver.wait(allImagesLoaded(), timeouts.fetch); + + // Hide cursor before taking screenshot + await pageObjects.hideCursor(); + + expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); + }, 60000); + + test('1 attachment with wide screen', async () => { + const { driver, pageObjects } = await setupWebDriver({ width: 640 }); + + await driver.wait(webChatLoaded(), timeouts.navigation); + await driver.wait(directLineConnected(), timeouts.directLine); + + const input = await driver.findElement(By.css('input[type="text"]')); + + await input.sendKeys('layout single', Key.RETURN); + await driver.wait(minNumActivitiesReached(3), timeouts.directLine); + await driver.wait(allImagesLoaded(), timeouts.fetch); + + // Hide cursor before taking screenshot + await pageObjects.hideCursor(); + + expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); + }, 60000); +}); + +describe('stacked with avatar initials', () => { + const WEB_CHAT_PROPS = { styleOptions: { botAvatarInitials: 'BF', userAvatarInitials: 'WC' } }; + + test('4 attachments', async () => { + const { driver, pageObjects } = await setupWebDriver({ props: WEB_CHAT_PROPS }); + + await driver.wait(webChatLoaded(), timeouts.navigation); + await driver.wait(directLineConnected(), timeouts.directLine); + + const input = await driver.findElement(By.css('input[type="text"]')); + + await input.sendKeys('layout stacked', Key.RETURN); + await driver.wait(minNumActivitiesReached(3), timeouts.directLine); + await driver.wait(allImagesLoaded(), timeouts.fetch); + + // Hide cursor before taking screenshot + await pageObjects.hideCursor(); + + expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); + }, 60000); + + test('1 attachment', async () => { + const { driver, pageObjects } = await setupWebDriver({ props: WEB_CHAT_PROPS }); + + await driver.wait(webChatLoaded(), timeouts.navigation); + await driver.wait(directLineConnected(), timeouts.directLine); + + const input = await driver.findElement(By.css('input[type="text"]')); + + await input.sendKeys('layout single', Key.RETURN); + await driver.wait(minNumActivitiesReached(3), timeouts.directLine); + await driver.wait(allImagesLoaded(), timeouts.fetch); + + // Hide cursor before taking screenshot + await pageObjects.hideCursor(); + + expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); + }, 60000); + + test('1 attachment with wide screen', async () => { + const { driver, pageObjects } = await setupWebDriver({ props: WEB_CHAT_PROPS, width: 640 }); + + await driver.wait(webChatLoaded(), timeouts.navigation); + await driver.wait(directLineConnected(), timeouts.directLine); + + const input = await driver.findElement(By.css('input[type="text"]')); + + await input.sendKeys('layout single', Key.RETURN); + await driver.wait(minNumActivitiesReached(3), timeouts.directLine); + await driver.wait(allImagesLoaded(), timeouts.fetch); + + // Hide cursor before taking screenshot + await pageObjects.hideCursor(); + + expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); + }, 60000); +}); diff --git a/__tests__/suggestedActions.js b/__tests__/suggestedActions.js index e764868ba4..29146be98e 100644 --- a/__tests__/suggestedActions.js +++ b/__tests__/suggestedActions.js @@ -1,5 +1,11 @@ import { By, Key } from 'selenium-webdriver'; -import { imageSnapshotOptions } from './constants.json'; + +import { imageSnapshotOptions, timeouts } from './constants.json'; +import allOutgoingActivitiesSent from './setup/conditions/allOutgoingActivitiesSent'; +import directLineConnected from './setup/conditions/directLineConnected'; +import minNumActivitiesReached from './setup/conditions/minNumActivitiesReached'; +import suggestedActionsShowed from './setup/conditions/suggestedActionsShowed'; +import webChatLoaded from './setup/conditions/webChatLoaded'; function sleep(ms = 1000) { return new Promise(resolve => setTimeout(resolve, ms)); @@ -10,14 +16,17 @@ function sleep(ms = 1000) { describe('suggested-actions command', async () => { test('should show correctly formatted buttons when suggested actions are displayed', async() => { - const { driver } = await setupWebDriver(); + const { driver, pageObjects } = await setupWebDriver(); - await sleep(4000); + await driver.wait(webChatLoaded(), timeouts.navigation); + await driver.wait(directLineConnected(), timeouts.directLine); - const input = await driver.findElement(By.tagName('input[type="text"]')); + const input = await driver.findElement(By.css('input[type="text"]')); await input.sendKeys('suggested-actions', Key.RETURN); - await sleep(2000); + await driver.wait(suggestedActionsShowed(), timeouts.directLine); + await driver.wait(allOutgoingActivitiesSent(), timeouts.directLine); + await pageObjects.hideCursor(); const base64PNG = await driver.takeScreenshot(); @@ -25,21 +34,24 @@ describe('suggested-actions command', async () => { }, 60000); test('should show response from bot and no text from user on imback', async () => { - const { driver } = await setupWebDriver(); + const { driver, pageObjects } = await setupWebDriver(); - await sleep(4000); + await driver.wait(webChatLoaded(), timeouts.navigation); + await driver.wait(directLineConnected(), timeouts.directLine); - const input = await driver.findElement(By.tagName('input[type="text"]')); + const input = await driver.findElement(By.css('input[type="text"]')); await input.sendKeys('suggested-actions', Key.RETURN); - await sleep(2000); + await driver.wait(suggestedActionsShowed(), timeouts.directLine); - const buttons = await driver.findElements(By.tagName('button')); + const buttons = await driver.findElements(By.css('button')); const imBackButton = buttons[1]; await imBackButton.click(); - await sleep(2000); + await driver.wait(minNumActivitiesReached(4), timeouts.directLine); + await driver.wait(allOutgoingActivitiesSent(), timeouts.directLine); + await pageObjects.hideCursor(); const base64PNG = await driver.takeScreenshot(); @@ -47,21 +59,24 @@ describe('suggested-actions command', async () => { }, 60000); test('should show response from bot and no text from user on postback', async () => { - const { driver } = await setupWebDriver(); + const { driver, pageObjects } = await setupWebDriver(); - await sleep(4000); + await driver.wait(webChatLoaded(), timeouts.navigation); + await driver.wait(directLineConnected(), timeouts.directLine); - const input = await driver.findElement(By.tagName('input[type="text"]')); + const input = await driver.findElement(By.css('input[type="text"]')); await input.sendKeys('suggested-actions', Key.RETURN); - await sleep(2000); + await driver.wait(suggestedActionsShowed(), timeouts.directLine); - const buttons = await driver.findElements(By.tagName('button')); + const buttons = await driver.findElements(By.css('button')); const postBackStringButton = buttons[2]; await postBackStringButton.click(); - await sleep(2000); + await driver.wait(minNumActivitiesReached(3), timeouts.directLine); + await driver.wait(allOutgoingActivitiesSent(), timeouts.directLine); + await pageObjects.hideCursor(); const base64PNG = await driver.takeScreenshot(); @@ -69,44 +84,50 @@ describe('suggested-actions command', async () => { }, 60000); test('should show response from bot and text from user on postback', async () => { - const { driver } = await setupWebDriver(); + const { driver, pageObjects } = await setupWebDriver(); - await sleep(4000); + await driver.wait(webChatLoaded(), timeouts.navigation); + await driver.wait(directLineConnected(), timeouts.directLine); - const input = await driver.findElement(By.tagName('input[type="text"]')); + const input = await driver.findElement(By.css('input[type="text"]')); - await input.sendKeys('suggested-actions', Key.RETURN); - await sleep(2000); + await input.sendKeys('suggested-actions', Key.RETURN); + await driver.wait(suggestedActionsShowed(), timeouts.directLine); - const buttons = await driver.findElements(By.tagName('button')); + const buttons = await driver.findElements(By.css('button')); - const postBackStringButton = buttons[3]; + const postBackStringButton = buttons[3]; - await postBackStringButton.click(); - await sleep(2000); + await postBackStringButton.click(); + await driver.wait(minNumActivitiesReached(3), timeouts.directLine); + await driver.wait(allOutgoingActivitiesSent(), timeouts.directLine); + await pageObjects.hideCursor(); - const base64PNG = await driver.takeScreenshot(); + const base64PNG = await driver.takeScreenshot(); - expect(base64PNG).toMatchImageSnapshot(imageSnapshotOptions); + expect(base64PNG).toMatchImageSnapshot(imageSnapshotOptions); }, 60000); test('should show response from bot and no text from user on messageback', async () => { - const { driver } = await setupWebDriver(); + const { driver, pageObjects } = await setupWebDriver(); - await sleep(4000); + await driver.wait(webChatLoaded(), timeouts.navigation); + await driver.wait(directLineConnected(), timeouts.directLine); - const input = await driver.findElement(By.tagName('input[type="text"]')); + const input = await driver.findElement(By.css('input[type="text"]')); await input.sendKeys('suggested-actions', Key.RETURN); - await sleep(2000); + await driver.wait(suggestedActionsShowed(), timeouts.directLine); - const buttons = await driver.findElements(By.tagName('button')); + const buttons = await driver.findElements(By.css('button')); const postBackStringButton = buttons[4]; await postBackStringButton.click(); - await sleep(2000); + await driver.wait(minNumActivitiesReached(4), timeouts.directLine); + await driver.wait(allOutgoingActivitiesSent(), timeouts.directLine); + await pageObjects.hideCursor(); const base64PNG = await driver.takeScreenshot(); @@ -114,21 +135,24 @@ describe('suggested-actions command', async () => { }, 60000); test('should show response from bot and text from user on messageback', async () => { - const { driver } = await setupWebDriver(); + const { driver, pageObjects } = await setupWebDriver(); - await sleep(4000); + await driver.wait(webChatLoaded(), timeouts.navigation); + await driver.wait(directLineConnected(), timeouts.directLine); - const input = await driver.findElement(By.tagName('input[type="text"]')); + const input = await driver.findElement(By.css('input[type="text"]')); await input.sendKeys('suggested-actions', Key.RETURN); - await sleep(2000); + await driver.wait(suggestedActionsShowed(), timeouts.directLine); - const buttons = await driver.findElements(By.tagName('button')); + const buttons = await driver.findElements(By.css('button')); const postBackStringButton = buttons[4]; await postBackStringButton.click(); - await sleep(2000); + await driver.wait(minNumActivitiesReached(4), timeouts.directLine); + await driver.wait(allOutgoingActivitiesSent(), timeouts.directLine); + await pageObjects.hideCursor(); const base64PNG = await driver.takeScreenshot(); diff --git a/packages/component/src/Activity/CarouselFilmStrip.js b/packages/component/src/Activity/CarouselFilmStrip.js index ca4549eee2..d504b580ed 100644 --- a/packages/component/src/Activity/CarouselFilmStrip.js +++ b/packages/component/src/Activity/CarouselFilmStrip.js @@ -13,7 +13,6 @@ import SendStatus from './SendStatus'; import textFormatToContentType from '../Utils/textFormatToContentType'; import Timestamp from './Timestamp'; - const { ActivityClientState: { SENDING, SEND_FAILED } } = Constants; const ROOT_CSS = css({ diff --git a/packages/component/src/Styles/StyleSet/CarouselFilmStrip.js b/packages/component/src/Styles/StyleSet/CarouselFilmStrip.js index f3faaa44db..e0e2e8cad2 100644 --- a/packages/component/src/Styles/StyleSet/CarouselFilmStrip.js +++ b/packages/component/src/Styles/StyleSet/CarouselFilmStrip.js @@ -11,7 +11,7 @@ export default function ({ }, '& > .avatar': { - marginRight: paddingRegular + marginLeft: paddingRegular }, '& > .content': { @@ -20,9 +20,10 @@ export default function ({ }, '& > ul': { + marginLeft: paddingRegular, + marginRight: paddingRegular, + '&:not(:first-child)': { - marginLeft: paddingRegular, - marginRight: paddingRegular, marginTop: paddingRegular },