* Upgrade Nighwatch * Add Microsoft header * Fix yarn.lock
This commit is contained in:
Родитель
dccf5896c9
Коммит
2bdedaae10
26
package.json
26
package.json
|
@ -2,15 +2,23 @@
|
|||
"private": true,
|
||||
"name": "botbuilder-js",
|
||||
"version": "4.13.0",
|
||||
"workspaces": [
|
||||
"libraries/*",
|
||||
"libraries/functional-tests/dialogToDialog/*",
|
||||
"libraries/testskills/*",
|
||||
"testing/*",
|
||||
"testing/browser-functional/browser-echo-bot",
|
||||
"tools",
|
||||
"transcripts"
|
||||
],
|
||||
"workspaces": {
|
||||
"packages": [
|
||||
"libraries/*",
|
||||
"libraries/functional-tests/dialogToDialog/*",
|
||||
"libraries/testskills/*",
|
||||
"testing/*",
|
||||
"testing/browser-functional/browser-echo-bot",
|
||||
"tools",
|
||||
"transcripts"
|
||||
],
|
||||
"nohoist": [
|
||||
"**/@types/selenium-webdriver"
|
||||
],
|
||||
"nohoistComments": {
|
||||
"**/@types/selenium-webdriver": "This package is excluded from the root @types folder as it requires ES2015+, whereas some BotBuilder libraries support ES5+."
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"browser-functional-test": "yarn workspace browser-functional-tests test",
|
||||
"build": "wsrun -e -m -t build",
|
||||
|
|
|
@ -36,13 +36,7 @@ steps:
|
|||
inputs:
|
||||
versionSpec: 20.x
|
||||
|
||||
- script: |
|
||||
mkdir "testing/browser-functional/drivers"
|
||||
cp "%CHROMEWEBDRIVER%/chromedriver.exe" "testing/browser-functional/drivers"
|
||||
cp "%GECKOWEBDRIVER%/geckodriver.exe" "testing/browser-functional/drivers"
|
||||
displayName: use browser drivers
|
||||
|
||||
- script: yarn --network-timeout 600000
|
||||
- script: yarn install --network-timeout 600000
|
||||
displayName: yarn install
|
||||
|
||||
- script: yarn build
|
||||
|
@ -78,11 +72,10 @@ steps:
|
|||
echo "# Deploy source code"
|
||||
call az webapp deployment source config-zip --resource-group "$(TestResourceGroup)" --name "$(TestWebApp)" --src "$(System.DefaultWorkingDirectory)/testing/browser-functional/browser-echo-bot/browser-echo-bot.zip"
|
||||
|
||||
- script: yarn browser-functional-test chrome
|
||||
displayName: run chrome tests
|
||||
|
||||
- script: yarn browser-functional-test firefox
|
||||
displayName: run firefox tests
|
||||
- script: yarn browser-functional-test
|
||||
env:
|
||||
TestURI: $(TESTURI)
|
||||
displayName: Run tests
|
||||
|
||||
- task: AzureCLI@1
|
||||
displayName: 'Delete Resource Group'
|
||||
|
@ -90,5 +83,4 @@ steps:
|
|||
azureSubscription: '$(AzureSubscription)'
|
||||
scriptLocation: inlineScript
|
||||
inlineScript: 'call az group delete -n $(TestResourceGroup) --yes'
|
||||
|
||||
condition: succeededOrFailed()
|
||||
|
|
|
@ -1,113 +0,0 @@
|
|||
const axios = require('axios');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const cp = require('child_process');
|
||||
|
||||
const driversDir = 'drivers';
|
||||
|
||||
const browsers = {
|
||||
CHROME: 'chrome',
|
||||
FIREFOX: 'firefox',
|
||||
};
|
||||
|
||||
const drivers = {
|
||||
[browsers.CHROME]: {
|
||||
name: 'chromedriver.exe',
|
||||
path: path.join(__dirname, driversDir, 'chromedriver.exe'),
|
||||
port: 9515,
|
||||
url: 'https://googlechromelabs.github.io/chrome-for-testing',
|
||||
browser: {
|
||||
name: browsers.CHROME,
|
||||
url: 'https://www.google.com/chrome',
|
||||
exists(driver) {
|
||||
return browserExists(driver.port, 'cannot find Chrome binary');
|
||||
},
|
||||
},
|
||||
},
|
||||
[browsers.FIREFOX]: {
|
||||
name: 'geckodriver.exe',
|
||||
path: path.join(__dirname, driversDir, 'geckodriver.exe'),
|
||||
port: 4444,
|
||||
url: 'https://github.com/mozilla/geckodriver/releases',
|
||||
browser: {
|
||||
name: browsers.FIREFOX,
|
||||
url: 'https://www.mozilla.org/firefox/new',
|
||||
exists(driver) {
|
||||
return browserExists(driver.port, 'unable to find binary');
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
async function requirements() {
|
||||
const driver = drivers[process.argv[process.argv.indexOf('-e') + 1]?.trim().toLowerCase()];
|
||||
|
||||
if (!driver) {
|
||||
return true;
|
||||
}
|
||||
|
||||
console.log('[Validating Requirements]');
|
||||
|
||||
const exists = fs.existsSync(driver.path);
|
||||
if (!exists) {
|
||||
console.error(
|
||||
` ❌ Driver : ${driver.name}
|
||||
- The current Nightwatch configuration (nightwatch.conf.js) requires the '${driver.name}' to be installed inside the '${driversDir}' folder.
|
||||
Visit '${driver.url}' website to download the '${driver.browser.name}' driver.
|
||||
Make sure to take into account OS 'platform', 'architecture', and 'version'.`
|
||||
);
|
||||
return false;
|
||||
}
|
||||
console.log(` ✅ Driver : ${driver.name}`);
|
||||
|
||||
if(process.env.TF_BUILD != undefined) {
|
||||
console.log(` ✅ Browser: ${driver.browser.name}`);
|
||||
return true;
|
||||
}
|
||||
|
||||
const exe = cp.spawn(driver.path, [`--port=${driver.port}`], {
|
||||
encoding: 'utf-8',
|
||||
shell: false,
|
||||
detached: true,
|
||||
windowsHide: true,
|
||||
});
|
||||
|
||||
const isDriverRunning = await new Promise((res) => exe.stdout.on('data', () => res(true)));
|
||||
const browserExists = isDriverRunning && (await driver.browser.exists(driver));
|
||||
process.kill(exe.pid, 'SIGKILL');
|
||||
if (browserExists) {
|
||||
console.log(` ✅ Browser: ${driver.browser.name}`);
|
||||
return true;
|
||||
}
|
||||
|
||||
console.error(
|
||||
` ❌ Browser: ${driver.browser.name}
|
||||
- The current Nightwatch configuration (nightwatch.conf.js) requires the '${driver.browser.name}' browser to be installed.
|
||||
Visit '${driver.browser.url}' website to download and install it.`
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
async function browserExists(port, assertion) {
|
||||
try {
|
||||
const { data } = await axios.post(`http://localhost:${port}/session`, { capabilities: {} });
|
||||
await axios.delete(`http://localhost:${port}/session/${data.value.sessionId}`);
|
||||
return true;
|
||||
} catch (error) {
|
||||
if (error?.response?.data?.value?.message?.includes(assertion)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
drivers,
|
||||
browsers,
|
||||
async before() {
|
||||
if (!(await requirements())) {
|
||||
process.exit(1);
|
||||
}
|
||||
},
|
||||
};
|
|
@ -1,58 +0,0 @@
|
|||
const { drivers, browsers } = require('./globals');
|
||||
const seleniumServer = require('selenium-server');
|
||||
|
||||
module.exports = {
|
||||
src_folders: ['tests'],
|
||||
page_objects_path: 'tests/tests_pages',
|
||||
globals_path: './globals.js',
|
||||
test_settings: {
|
||||
default: {
|
||||
request_timeout_options: {
|
||||
timeout: 100000,
|
||||
retry_attempts: 3,
|
||||
},
|
||||
},
|
||||
|
||||
selenium: {
|
||||
selenium: {
|
||||
start_process: true,
|
||||
check_process_delay: 10000,
|
||||
port: drivers[browsers.FIREFOX].port,
|
||||
server_path: seleniumServer.path,
|
||||
cli_args: {
|
||||
'webdriver.gecko.driver': drivers[browsers.FIREFOX].path,
|
||||
},
|
||||
},
|
||||
webdriver: {
|
||||
start_process: false,
|
||||
},
|
||||
},
|
||||
|
||||
[browsers.CHROME]: {
|
||||
silent: true,
|
||||
selenium: {
|
||||
start_process: false,
|
||||
},
|
||||
webdriver: {
|
||||
start_process: true,
|
||||
server_path: drivers[browsers.CHROME].path,
|
||||
port: drivers[browsers.CHROME].port,
|
||||
},
|
||||
desiredCapabilities: {
|
||||
browserName: browsers.CHROME,
|
||||
javascriptEnabled: true,
|
||||
acceptSslCerts: true,
|
||||
},
|
||||
},
|
||||
|
||||
[browsers.FIREFOX]: {
|
||||
extends: 'selenium',
|
||||
silent: true,
|
||||
desiredCapabilities: {
|
||||
browserName: browsers.FIREFOX,
|
||||
javascriptEnabled: true,
|
||||
acceptSslCerts: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
|
@ -1 +0,0 @@
|
|||
require('nightwatch/bin/runner.js');
|
|
@ -0,0 +1,149 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
// Refer to the online docs for more details:
|
||||
// https://nightwatchjs.org/gettingstarted/configuration/
|
||||
//
|
||||
|
||||
// _ _ _ _ _ _ _
|
||||
// | \ | |(_) | | | | | | | |
|
||||
// | \| | _ __ _ | |__ | |_ __ __ __ _ | |_ ___ | |__
|
||||
// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \
|
||||
// | |\ || || (_| || | | || |_ \ V V / | (_| || |_ | (__ | | | |
|
||||
// \_| \_/|_| \__, ||_| |_| \__| \_/\_/ \__,_| \__| \___||_| |_|
|
||||
// __/ |
|
||||
// |___/
|
||||
|
||||
const dotenv = require('dotenv');
|
||||
dotenv.config();
|
||||
|
||||
const { DEFAULT_BROWSER, browsers } = require('./utils');
|
||||
const { validate } = require('./requirements');
|
||||
|
||||
const config = {
|
||||
// An array of folders (excluding subfolders) where your tests are located;
|
||||
// if this is not specified, the test source must be passed as the second argument to the test runner.
|
||||
src_folders: ['nightwatch/tests'],
|
||||
|
||||
// See https://nightwatchjs.org/guide/concepts/page-object-model.html
|
||||
page_objects_path: ['nightwatch/pages'],
|
||||
|
||||
// See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html
|
||||
custom_commands_path: [],
|
||||
|
||||
// See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html
|
||||
custom_assertions_path: [],
|
||||
|
||||
// See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html
|
||||
plugins: [],
|
||||
|
||||
// See https://nightwatchjs.org/guide/concepts/test-globals.html
|
||||
// globals_path: './globals.js',
|
||||
globals: {
|
||||
asyncHookTimeout: 10 * 60 * 1000, // 10 minutes
|
||||
async before() {
|
||||
const valid = await validate();
|
||||
if (!valid) {
|
||||
process.exit(1);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
webdriver: {},
|
||||
|
||||
test_workers: {
|
||||
enabled: true,
|
||||
},
|
||||
|
||||
test_settings: {
|
||||
default: {
|
||||
disable_error_log: false,
|
||||
launch_url: process.env.TestURI,
|
||||
|
||||
screenshots: {
|
||||
enabled: false,
|
||||
path: 'screens',
|
||||
on_failure: true,
|
||||
},
|
||||
|
||||
desiredCapabilities: {
|
||||
browserName: DEFAULT_BROWSER,
|
||||
},
|
||||
|
||||
webdriver: {
|
||||
start_process: true,
|
||||
server_path: '',
|
||||
},
|
||||
},
|
||||
|
||||
[browsers.firefox.key]: {
|
||||
desiredCapabilities: {
|
||||
browserName: browsers.firefox.id,
|
||||
alwaysMatch: {
|
||||
acceptInsecureCerts: true,
|
||||
'moz:firefoxOptions': {
|
||||
args: [
|
||||
// '-headless',
|
||||
// '-verbose'
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
webdriver: {
|
||||
start_process: true,
|
||||
server_path: '',
|
||||
cli_args: [
|
||||
// very verbose geckodriver logs
|
||||
// '-vv'
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
[browsers.chrome.key]: {
|
||||
desiredCapabilities: {
|
||||
browserName: browsers.chrome.id,
|
||||
'goog:chromeOptions': {
|
||||
// More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/
|
||||
args: [
|
||||
//'--no-sandbox',
|
||||
//'--ignore-certificate-errors',
|
||||
//'--allow-insecure-localhost',
|
||||
//'--headless=new'
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
webdriver: {
|
||||
start_process: true,
|
||||
server_path: '',
|
||||
cli_args: [
|
||||
// --verbose
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
[browsers.edge.key]: {
|
||||
desiredCapabilities: {
|
||||
browserName: browsers.edge.id,
|
||||
'ms:edgeOptions': {
|
||||
// More info on EdgeDriver: https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options
|
||||
args: [
|
||||
//'--headless=new'
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
webdriver: {
|
||||
start_process: true,
|
||||
server_path: '',
|
||||
cli_args: [
|
||||
// --verbose
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = config;
|
|
@ -3,25 +3,23 @@
|
|||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const dotenv = require('dotenv');
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
dotenv.config({ path: ENV_FILE });
|
||||
|
||||
module.exports = {
|
||||
url: process.env.TestURI,
|
||||
name: 'EchoBot',
|
||||
url: function(){
|
||||
return this.api.launchUrl;
|
||||
},
|
||||
elements: {
|
||||
webchatContainer: {
|
||||
selector: 'div[id=webchat]>div'
|
||||
selector: 'div[id=webchat]>div',
|
||||
},
|
||||
webchatMessagesList: {
|
||||
selector: 'section.webchat__basic-transcript__transcript'
|
||||
selector: 'section.webchat__basic-transcript__transcript',
|
||||
},
|
||||
webchatMessageInput: {
|
||||
selector: 'input[data-id=webchat-sendbox-input]'
|
||||
selector: 'input[data-id=webchat-sendbox-input]',
|
||||
},
|
||||
webchatMessageInputSubmitButton: {
|
||||
selector: 'button.webchat__send-button'
|
||||
}
|
||||
}
|
||||
}
|
||||
selector: 'button.webchat__send-button',
|
||||
},
|
||||
},
|
||||
};
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
const { DEFAULT_BROWSER, getFlag, getBrowser, logs, isBrowserInstalled, isBotRunning } = require('./utils');
|
||||
|
||||
async function validate() {
|
||||
const inputs = getFlag(['-e', '--env']).split(',');
|
||||
|
||||
let isBotValidated = false;
|
||||
for (const input of inputs) {
|
||||
let /** @type {import('./types').IBrowser} */ browser, /** @type {Error} */ err;
|
||||
[browser, err] = getBrowser(input);
|
||||
if (err) {
|
||||
logs.browserNotFoundWarn(err);
|
||||
[browser] = getBrowser(DEFAULT_BROWSER);
|
||||
}
|
||||
|
||||
if(!isBotValidated){
|
||||
err = await isBotRunning(browser);
|
||||
isBotValidated = true;
|
||||
if (err) {
|
||||
logs.echoBotNotRunningError(err);
|
||||
return false;
|
||||
} else {
|
||||
logs.echoBotRunningLog();
|
||||
}
|
||||
}
|
||||
|
||||
err = await isBrowserInstalled(browser);
|
||||
if (err) {
|
||||
logs.browserNotFoundError(browser);
|
||||
return false;
|
||||
} else {
|
||||
logs.browserInstalledLog(browser);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
module.exports = { validate };
|
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
describe('Echo Bot: Message Handling', () => {
|
||||
const botPage = browser.page.echo();
|
||||
|
||||
before(() => botPage.navigate());
|
||||
after((browser) => browser.quit());
|
||||
|
||||
it('Echo bot webchat is loaded', () => {
|
||||
// Check Webchat container is initialized and is present in the page
|
||||
botPage.assert.elementPresent('@webchatContainer');
|
||||
});
|
||||
|
||||
it('Echo bot webchat sends messages', async () => {
|
||||
// Type 'Hello' in the webchat input box and send it to the bot
|
||||
botPage.setValue('@webchatMessageInput', 'Hello');
|
||||
botPage.click('@webchatMessageInputSubmitButton', (result) => {
|
||||
// Assertion to check the button was clickable and got triggered
|
||||
browser.assert.strictEqual(result.status, 0, 'Message input working');
|
||||
});
|
||||
botPage.pause(250);
|
||||
|
||||
await assertMessageIsPresentInPage(botPage, 'Hello', 'Webchat contains user message');
|
||||
});
|
||||
|
||||
it('Echo bot webchat echoes messages', async () => {
|
||||
await assertMessageIsPresentInPage(botPage, '1: You said “Hello”', 'Webchat contains bot reply');
|
||||
});
|
||||
});
|
||||
|
||||
async function assertMessageIsPresentInPage(pageInstance, textSearch, assertMessage) {
|
||||
let messagesListPromises = [];
|
||||
// Get messages list from webchat
|
||||
await pageInstance.api
|
||||
.elements('@webchatMessagesList', function (messagesWebElements) {
|
||||
for (let index = 0; index < messagesWebElements.value.length; index++) {
|
||||
const webElement = messagesWebElements.value[index];
|
||||
messagesListPromises.push(function (resolve) {
|
||||
// Workaround for different implementations of the WebDriver API
|
||||
// This will be fixed when all browsers makes use of Selenium Server v4 which is compliant with the W3C WebDriver standards
|
||||
var elementId = webElement.ELEMENT != undefined ? webElement.ELEMENT : webElement.values()[0];
|
||||
pageInstance.api.elementIdText(elementId, function (elementText) {
|
||||
resolve(elementText.value == textSearch);
|
||||
});
|
||||
});
|
||||
}
|
||||
})
|
||||
.then(function () {
|
||||
Promise.all(messagesListPromises).then(function (results) {
|
||||
let messageExists = results.some(function (value) {
|
||||
return value;
|
||||
});
|
||||
// Check if any of the existing messages was equal to the needle.
|
||||
pageInstance.assert.strictEqual(messageExists, true, assertMessage);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
export interface IBrowser {
|
||||
id: string;
|
||||
key: string;
|
||||
name: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
export interface IBrowserList {
|
||||
chrome: IBrowser;
|
||||
firefox: IBrowser;
|
||||
edge: IBrowser;
|
||||
}
|
||||
|
||||
export type BrowserKeys = keyof IBrowserList;
|
|
@ -0,0 +1,135 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
const { Builder, Browser } = require('selenium-webdriver');
|
||||
const echoPage = require('./pages/echo');
|
||||
|
||||
const DEFAULT_BROWSER = Browser.CHROME;
|
||||
|
||||
/**
|
||||
@typedef IBrowser
|
||||
@type {import('./types').IBrowser}
|
||||
*/
|
||||
|
||||
/**
|
||||
@typedef IBrowserList
|
||||
@type {import('./types').IBrowserList}
|
||||
*/
|
||||
|
||||
/**
|
||||
@typedef BrowserKeys
|
||||
@type {import('./types').BrowserKeys}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @type {IBrowserList}
|
||||
*/
|
||||
const browsers = {
|
||||
chrome: {
|
||||
key: 'chrome',
|
||||
id: Browser.CHROME,
|
||||
name: 'Chrome',
|
||||
url: 'https://www.google.com/chrome',
|
||||
},
|
||||
firefox: {
|
||||
key: 'firefox',
|
||||
id: Browser.FIREFOX,
|
||||
name: 'Firefox',
|
||||
url: 'https://www.mozilla.org/firefox/new',
|
||||
},
|
||||
edge: {
|
||||
key: 'edge',
|
||||
id: Browser.EDGE,
|
||||
name: 'Edge',
|
||||
url: 'https://www.microsoft.com/edge',
|
||||
},
|
||||
};
|
||||
|
||||
const logs = {
|
||||
browserInstalledLog(browser) {
|
||||
console.info(` ✅ Browser '${browser.name}' detected`);
|
||||
},
|
||||
browserNotFoundWarn(err) {
|
||||
console.warn(` ⚠️ ${err.message} - Using default browser: ${DEFAULT_BROWSER}`);
|
||||
},
|
||||
browserNotFoundError(browser) {
|
||||
console.error(
|
||||
` ❌ Browser '${browser.name}' binary not found - Please visit the following URL to download and install the required browser: ${browser.url()}`
|
||||
);
|
||||
},
|
||||
echoBotNotRunningError(err) {
|
||||
console.error(` ❌ ${err.message} - Please start the bot by executing 'yarn start:echo' and try again`);
|
||||
},
|
||||
echoBotRunningLog() {
|
||||
console.info(` ✅ The '${echoPage.name}' is running at '${process.env.TestURI}'`);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {IBrowser} browser
|
||||
* @returns {Promise<Error>}
|
||||
*/
|
||||
async function isBrowserInstalled(browser) {
|
||||
if (!browser) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let driver;
|
||||
try {
|
||||
driver = await new Builder().forBrowser(browser.id).build();
|
||||
} catch (e) {
|
||||
return e;
|
||||
} finally {
|
||||
await driver?.quit();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {IBrowser} browser
|
||||
* @returns {Promise<Error>}
|
||||
*/
|
||||
async function isBotRunning(browser) {
|
||||
let driver;
|
||||
try {
|
||||
driver = await new Builder().forBrowser(browser.id).build();
|
||||
await driver.navigate().to(process.env.TestURI);
|
||||
} catch (error) {
|
||||
return new Error(`The '${echoPage.name}' bot is not running at '${process.env.TestURI}'`);
|
||||
} finally {
|
||||
await driver?.quit();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {BrowserKeys} key
|
||||
* @returns {[IBrowser, Error]}
|
||||
*/
|
||||
function getBrowser(key) {
|
||||
const browser = key ?? '';
|
||||
const result = browsers[browser.trim().toLowerCase()];
|
||||
if (!result) {
|
||||
return ['', new Error(`Browser '${browser}' not found`)];
|
||||
}
|
||||
|
||||
return [result, null];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string[]} flags
|
||||
* @returns {string}
|
||||
*/
|
||||
function getFlag(flags) {
|
||||
return process.argv.find((_, i, arr) => flags.includes(arr[i - 1]?.trim()));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
DEFAULT_BROWSER,
|
||||
browsers,
|
||||
logs,
|
||||
isBrowserInstalled,
|
||||
isBotRunning,
|
||||
getBrowser,
|
||||
getFlag,
|
||||
};
|
|
@ -7,14 +7,14 @@
|
|||
"devDependencies": {
|
||||
"axios": "^1.7.7",
|
||||
"dotenv": "^16.4.5",
|
||||
"nightwatch": "^2.6.21",
|
||||
"selenium-server": "^3.141.59"
|
||||
"nightwatch": "^3.7.0"
|
||||
},
|
||||
"directories": {
|
||||
"test": "tests"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node nightwatch.js -e"
|
||||
"test": "nightwatch --parallel --fail-fast --env firefox,chrome,edge --config nightwatch/config.js",
|
||||
"start:echo": "cd browser-echo-bot && yarn start"
|
||||
},
|
||||
"author": "Microsoft Corp.",
|
||||
"license": "MIT"
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
var botPage;
|
||||
module.exports = {
|
||||
botPage: {},
|
||||
before: function(browser) {
|
||||
botPage = browser.page.echoBotPage();
|
||||
},
|
||||
after: function(browser) {
|
||||
// End current page session
|
||||
botPage.end();
|
||||
},
|
||||
'Echo bot webchat is loaded': function(browser) {
|
||||
// Navigate to the Echo Bot page
|
||||
// This step is performed made in the first test since navigation can't be done in the 'before' hook
|
||||
botPage.navigate();
|
||||
|
||||
// Check Webchat container is initialized and is present in the page
|
||||
botPage
|
||||
.assert.elementPresent('@webchatContainer');
|
||||
},
|
||||
'Echo bot webchat sends messages': async function(browser) {
|
||||
// Type 'Hello' in the webchat input box and send it to the bot
|
||||
botPage
|
||||
.setValue('@webchatMessageInput', 'Hello');
|
||||
botPage
|
||||
.click('@webchatMessageInputSubmitButton', function (result) {
|
||||
// Assertion to check the button was clickable and got triggered
|
||||
this.assert.strictEqual(result.status, 0, 'Message input working');
|
||||
});
|
||||
botPage
|
||||
.pause(250);
|
||||
|
||||
await assertMessageIsPresentInPage(botPage, 'Hello', 'Webchat contains user message');
|
||||
},
|
||||
'Echo bot webchat echoes messages': async function(browser) {
|
||||
await assertMessageIsPresentInPage(botPage, '1: You said “Hello”', 'Webchat contains bot reply');
|
||||
}
|
||||
};
|
||||
|
||||
async function assertMessageIsPresentInPage(pageInstance, textSearch, assertMessage) {
|
||||
let messagesListPromises = [];
|
||||
// Get messages list from webchat
|
||||
await pageInstance.api.elements('@webchatMessagesList', function(messagesWebElements) {
|
||||
for (let index = 0; (index < messagesWebElements.value.length); index++) {
|
||||
const webElement = messagesWebElements.value[index];
|
||||
messagesListPromises.push((function(resolve) {
|
||||
// Workaround for different implementations of the WebDriver API
|
||||
// This will be fixed when all browsers makes use of Selenium Server v4 which is compliant with the W3C WebDriver standards
|
||||
var elementId = webElement.ELEMENT != undefined ? webElement.ELEMENT : webElement.values()[0];
|
||||
pageInstance.api.elementIdText(elementId, function(elementText) {
|
||||
resolve(elementText.value == textSearch);
|
||||
});
|
||||
}));
|
||||
}
|
||||
}).then(function(){
|
||||
Promise.all(messagesListPromises)
|
||||
.then(function (results) {
|
||||
let messageExists = results.some(function (value) {
|
||||
return value;
|
||||
});
|
||||
// Check if any of the existing messages was equal to the needle.
|
||||
pageInstance.assert.strictEqual(messageExists, true, assertMessage);
|
||||
});
|
||||
});
|
||||
}
|
1053
yarn.lock
1053
yarn.lock
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Загрузка…
Ссылка в новой задаче