diff --git a/__tests__/__image_snapshots__/chrome-docker/scroll-to-bottom-js-should-stick-to-bottom-if-submitting-an-adaptive-card-while-suggested-actions-is-open-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/scroll-to-bottom-js-should-stick-to-bottom-if-submitting-an-adaptive-card-while-suggested-actions-is-open-1-snap.png new file mode 100644 index 0000000000..4de237db33 Binary files /dev/null and b/__tests__/__image_snapshots__/chrome-docker/scroll-to-bottom-js-should-stick-to-bottom-if-submitting-an-adaptive-card-while-suggested-actions-is-open-1-snap.png differ diff --git a/__tests__/constants.json b/__tests__/constants.json index 20ac00b078..f976bfedad 100644 --- a/__tests__/constants.json +++ b/__tests__/constants.json @@ -9,6 +9,7 @@ "fetch": 2500, "navigation": 10000, "postActivity": 30000, + "scrollToBottom": 1000, "test": 60000 } } diff --git a/__tests__/scrollToBottom.js b/__tests__/scrollToBottom.js new file mode 100644 index 0000000000..436185be9e --- /dev/null +++ b/__tests__/scrollToBottom.js @@ -0,0 +1,36 @@ +import { By } from 'selenium-webdriver'; + +import { imageSnapshotOptions, timeouts } from './constants.json'; + +import minNumActivitiesShown from './setup/conditions/minNumActivitiesShown'; +import scrollToBottomCompleted from './setup/conditions/scrollToBottomCompleted'; +import suggestedActionsShowed from './setup/conditions/suggestedActionsShowed'; +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); + +test('should stick to bottom if submitting an Adaptive Card while suggested actions is open', async () => { + const { driver, pageObjects } = await setupWebDriver(); + + await driver.wait(uiConnected(), timeouts.directLine); + + await pageObjects.sendMessageViaSendBox('card inputs', { waitForSend: true }); + await driver.wait(minNumActivitiesShown(2), timeouts.directLine); + + await pageObjects.sendMessageViaSendBox('suggested-actions', { waitForSend: true }); + await driver.wait(suggestedActionsShowed(), timeouts.directLine); + await driver.wait(scrollToBottomCompleted(), timeouts.scrollToBottom); + + const submitButton = await driver.findElement(By.css('button.ac-pushButton:nth-of-type(2)')); + + await submitButton.click(); + await driver.wait(minNumActivitiesShown(5), timeouts.directLine); + await driver.wait(scrollToBottomCompleted(), timeouts.scrollToBottom); + + const base64PNG = await driver.takeScreenshot(); + + expect(base64PNG).toMatchImageSnapshot(imageSnapshotOptions); +}); diff --git a/__tests__/setup/conditions/scrollToBottomCompleted.js b/__tests__/setup/conditions/scrollToBottomCompleted.js new file mode 100644 index 0000000000..2fee80e1ea --- /dev/null +++ b/__tests__/setup/conditions/scrollToBottomCompleted.js @@ -0,0 +1,28 @@ +import { Condition } from 'selenium-webdriver'; + +import { timeouts } from '../../constants.json'; + +export default function scrollToBottomCompleted() { + return new Condition('for UI to scroll to bottom', async driver => { + const done = await driver.executeAsyncScript((timeoutInMS, callback) => { + const scrollable = document.querySelector('[role="log"] > *'); + + // If we do not receive any "scroll" event at all, probably we are at the bottom. + const defaultTimeout = setTimeout(() => callback(true), timeoutInMS); + let timeout; + const handleScroll = () => { + clearTimeout(defaultTimeout); + clearTimeout(timeout); + + timeout = setTimeout(() => { + scrollable.removeEventListener('scroll', handleScroll); + callback(true); + }, 200); + }; + + scrollable.addEventListener('scroll', handleScroll); + }, timeouts.scrollToBottom); + + return done; + }); +} diff --git a/__tests__/setup/pageObjects/sendMessageViaSendBox.js b/__tests__/setup/pageObjects/sendMessageViaSendBox.js index ec6da9d340..b3a363f482 100644 --- a/__tests__/setup/pageObjects/sendMessageViaSendBox.js +++ b/__tests__/setup/pageObjects/sendMessageViaSendBox.js @@ -4,7 +4,7 @@ import { timeouts } from '../../constants.json'; import allOutgoingActivitiesSent from '../conditions/allOutgoingActivitiesSent'; export default async function sendMessageViaSendBox(driver, text, { waitForSend = true }) { - const input = await driver.findElement(By.css('input[type="text"]')); + const input = await driver.findElement(By.css('[role="form"] > * > form > input[type="text"]')); await input.sendKeys(text, Key.RETURN);