Merge pull request #773 from thomasnordquist/chore/replace-spectron-with-playwright
Chore/replace spectron with playwright
This commit is contained in:
@@ -25,7 +25,7 @@ services:
|
||||
- docker
|
||||
|
||||
install:
|
||||
- yarn install
|
||||
- yarn install --frozen-lockfile
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get update && sudo apt-get -y install snap squashfs-tools && sudo snap install snapcraft --classic; fi;
|
||||
|
||||
script:
|
||||
|
||||
@@ -19,7 +19,7 @@ class TreeNodeTitle extends React.PureComponent<TreeNodeProps, {}> {
|
||||
const name = this.props.name || (this.props.treeNode.sourceEdge && this.props.treeNode.sourceEdge.name)
|
||||
|
||||
return (
|
||||
<span key="edge" className={this.props.classes.sourceEdge}>
|
||||
<span key="edge" className={this.props.classes.sourceEdge} data-test-topic={name}>
|
||||
{name}
|
||||
</span>
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const webpack = require('webpack');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||
const webpack = require('webpack')
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
@@ -63,13 +63,8 @@ module.exports = {
|
||||
use: ['style-loader', 'css-loader'],
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpg|gif)$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'file-loader',
|
||||
options: {},
|
||||
},
|
||||
],
|
||||
test: /\.(png|jpg|gif)$/i,
|
||||
type: 'asset/resource',
|
||||
},
|
||||
// {
|
||||
// test: /\.node$/,
|
||||
@@ -101,4 +96,4 @@ module.exports = {
|
||||
// "react": "React",
|
||||
// "react-dom": "ReactDOM"
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ install:
|
||||
- ps: Install-Product node 19
|
||||
|
||||
build_script:
|
||||
- yarn
|
||||
- yarn install --frozen-lockfile
|
||||
- yarn build
|
||||
- yarn prepare-release
|
||||
- yarn package appx
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:11-stretch
|
||||
FROM node:19.8.1-bullseye-slim
|
||||
|
||||
RUN DEBIAN_FRONTEND="noninteractive" apt-get update \
|
||||
&& apt-get install -y --no-install-recommends nano ffmpeg xvfb git-core tmux locales mosquitto x11vnc
|
||||
|
||||
@@ -5,7 +5,7 @@ git clone https://github.com/thomasnordquist/MQTT-Explorer.git /app
|
||||
cd /app
|
||||
git checkout travis-ui-tests
|
||||
|
||||
yarn
|
||||
yarn install --frozen-lockfile
|
||||
yarn build
|
||||
|
||||
yarn ui-test
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
"dev:app": "cd app && npm run dev",
|
||||
"dev:electron": "tsc && electron . --development",
|
||||
"lint": "npm-run-all --parallel lint:prettier lint:tslint",
|
||||
"lint:fix": "npm-run-all lint:tslint:fix lint:prettier:fix",
|
||||
"lint:prettier": "prettier --check \"**/*.ts{x,}\"",
|
||||
"lint:prettier:fix": "prettier --write \"**/*.ts{x,}\"",
|
||||
"lint:tslint": "tslint -p ./",
|
||||
"lint:tslint:fix": "tslint -p ./ --fix",
|
||||
"lint:spellcheck": "cspell -e ./build -e \"node_modules\" \"**/*.ts{x,}\"",
|
||||
"build": "tsc && cd app && yarn run build && cd ..",
|
||||
"prepare-release": "ts-node scripts/prepare-release.ts",
|
||||
@@ -88,23 +90,22 @@
|
||||
"builder-util-runtime": "^9",
|
||||
"chai": "^4.2.0",
|
||||
"cspell": "^4.0.28",
|
||||
"electron": "29.1.1",
|
||||
"electron": "29.2.0",
|
||||
"electron-builder": "^24.13.3",
|
||||
"mocha": "^10.4.0",
|
||||
"mustache": "4",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"nyc": "15",
|
||||
"playwright": "^1.43.0",
|
||||
"prettier": "^3.2.5",
|
||||
"redux-thunk": "^2.3.0",
|
||||
"source-map-support": "^0.5.9",
|
||||
"spectron": "19",
|
||||
"ts-node": "^10.9.2",
|
||||
"tslint": "^6.1.3",
|
||||
"tslint-config-airbnb": "^5.11.2",
|
||||
"tslint-react": "^5.0.0",
|
||||
"tslint-react-recommended": "^1.0.15",
|
||||
"typescript": "^4.5.5",
|
||||
"webdriverio": "7.16"
|
||||
"typescript": "^4.5.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"about-window": "^1.12.1",
|
||||
|
||||
@@ -17,18 +17,18 @@ async function prepareRelease() {
|
||||
|
||||
// Install app dependencies
|
||||
chdir('app')
|
||||
await exec('yarn')
|
||||
await exec('yarn', ['install', '--frozen-lockfile'])
|
||||
chdir('..')
|
||||
|
||||
// Install electron dependencies
|
||||
await exec('yarn')
|
||||
await exec('yarn', ['install', '--frozen-lockfile'])
|
||||
|
||||
// Build App and Electron backend
|
||||
await exec('yarn', ['build'])
|
||||
|
||||
// Clean up
|
||||
await fs.remove('node_modules')
|
||||
await exec('yarn', ['install', '--production']) // Do not clean up, electron version detection will fail otherwise
|
||||
await exec('yarn', ['install', '--production', '--frozen-lockfile']) // Do not clean up, electron version detection will fail otherwise
|
||||
await fs.remove(path.join('app', 'node_modules'))
|
||||
|
||||
chdir(originalDir)
|
||||
|
||||
@@ -1,10 +1,25 @@
|
||||
#!/bin/bash
|
||||
|
||||
function finish {
|
||||
echo "Exiting, cleaning up"
|
||||
tmux send-keys -t record q || echo "No tmux was running"
|
||||
#echo kill $PID_XVFB $PID_CHROMEDRIVER $PID_MOSQUITTO
|
||||
#kill $PID_XVFB $PID_CHROMEDRIVER $PID_MOSQUITTO
|
||||
set +e
|
||||
echo "Exiting, cleaning up.."
|
||||
|
||||
echo "Stopping TMUX session (record).."
|
||||
tmux kill-session -t record || echo "Already stopped"
|
||||
|
||||
if [[ ! -z "$PID_MOSQUITTO" ]]; then
|
||||
echo "Stopping mosquitto ($PID_MOSQUITTO).."
|
||||
kill "$PID_MOSQUITTO" || echo "Already stopped"
|
||||
fi
|
||||
|
||||
if [[ ! -z "$PID_VNC" ]]; then
|
||||
echo "Stopping VNC ($PID_VNC).."
|
||||
kill "$PID_VNC" || echo "Already stopped"
|
||||
fi
|
||||
|
||||
if [[ ! -z "$PID_XVFB" ]]; then
|
||||
echo "Stopping XVFB ($PID_XVFB).."
|
||||
kill "$PID_XVFB" || echo "Already stopped"
|
||||
fi
|
||||
}
|
||||
|
||||
trap finish EXIT
|
||||
@@ -18,28 +33,25 @@ export PID_XVFB=$!
|
||||
sleep 2
|
||||
|
||||
# Debug with VNC
|
||||
while [ "$TEST_EXIT_CODE" = "" ]; do x11vnc -localhost -passwd "bierbier" -display :$SCR; done &
|
||||
x11vnc -localhost -rfbport 5900 -passwd "bierbier" -display :$SCR &
|
||||
export PID_VNC=$!
|
||||
|
||||
# Start mqtt broker
|
||||
mosquitto &
|
||||
export PID_MOSQUITTO=$!
|
||||
|
||||
DISPLAY=:$SCR ./node_modules/.bin/chromedriver --url-base=wd/hub --port=9515 &
|
||||
export PID_CHROMEDRIVER=$!
|
||||
sleep 2
|
||||
|
||||
# Delete old video
|
||||
rm ./app.mp4 || echo no need to delete ./app.mp4
|
||||
rm -f ./app*.mp4
|
||||
rm -f ./qrawvideorgb24.yuv
|
||||
|
||||
# Start recoring in tmux
|
||||
#tmux new-session -d -s record ffmpeg -f x11grab -draw_mouse 0 -video_size $DIMENSIONS -i :$SCR -codec:v libx264 -r 20 ./app.mp4
|
||||
# tmux new-session -d -s record ffmpeg -f x11grab -draw_mouse 0 -video_size $DIMENSIONS -i :$SCR -codec:v libx264 -r 20 ./app.mp4
|
||||
tmux new-session -d -s record ffmpeg -f x11grab -draw_mouse 0 -video_size $DIMENSIONS -i :$SCR -r 20 -vcodec rawvideo -pix_fmt yuv420p qrawvideorgb24.yuv
|
||||
|
||||
# Start tests
|
||||
node dist/src/spec/demoVideo.js
|
||||
DISPLAY=:$SCR node dist/src/spec/demoVideo.js
|
||||
TEST_EXIT_CODE=$?
|
||||
echo "Webriver exitet with $TEST_EXIT_CODE"
|
||||
echo "Test script exited with $TEST_EXIT_CODE"
|
||||
|
||||
# Stop recording
|
||||
tmux send-keys -t record q
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import * as fs from 'fs'
|
||||
import * as os from 'os'
|
||||
import * as webdriverio from 'webdriverio'
|
||||
import * as path from 'path'
|
||||
|
||||
import { ElectronApplication, _electron as electron } from 'playwright'
|
||||
|
||||
import mockMqtt, { stop as stopMqtt } from './mock-mqtt'
|
||||
import { clearOldTopics } from './scenarios/clearOldTopics'
|
||||
import { clearSearch, searchTree } from './scenarios/searchTree'
|
||||
@@ -10,7 +13,7 @@ import { copyTopicToClipboard } from './scenarios/copyTopicToClipboard'
|
||||
import { copyValueToClipboard } from './scenarios/copyValueToClipboard'
|
||||
import { disconnect } from './scenarios/disconnect'
|
||||
import { publishTopic } from './scenarios/publishTopic'
|
||||
import { SceneBuilder } from './SceneBuilder'
|
||||
import { Scene, SceneBuilder } from './SceneBuilder'
|
||||
import { showAdvancedConnectionSettings } from './scenarios/showAdvancedConnectionSettings'
|
||||
import { showJsonPreview } from './scenarios/showJsonPreview'
|
||||
import { showMenu } from './scenarios/showMenu'
|
||||
@@ -18,6 +21,15 @@ import { showNumericPlot } from './scenarios/showNumericPlot'
|
||||
import { showOffDiffCapability } from './scenarios/showOffDiffCapability'
|
||||
import { showZoomLevel } from './scenarios/showZoomLevel'
|
||||
|
||||
/**
|
||||
* A convenience method that handles gracefully cleaning up the test run.
|
||||
*/
|
||||
const cleanUp = async (scenes: SceneBuilder, electronApp: ElectronApplication) => {
|
||||
// Exit app.
|
||||
fs.writeFileSync('scenes.json', JSON.stringify(scenes.scenes, undefined, ' '))
|
||||
await electronApp.close()
|
||||
}
|
||||
|
||||
process.on('unhandledRejection', (error: Error | any) => {
|
||||
console.error('unhandledRejection', error.message, error.stack)
|
||||
process.exit(1)
|
||||
@@ -25,119 +37,114 @@ process.on('unhandledRejection', (error: Error | any) => {
|
||||
|
||||
const runningUiTestOnCi = os.platform() === 'darwin' ? [] : ['--runningUiTestOnCi']
|
||||
|
||||
const options = {
|
||||
host: '127.0.0.1', // Use localhost as chrome driver server
|
||||
port: 9515, // "9515" is the port opened by chrome driver.
|
||||
path: '/wd/hub',
|
||||
capabilities: {
|
||||
browserName: 'chrome',
|
||||
'goog:chromeOptions': {
|
||||
binary: `${__dirname}/../../../node_modules/.bin/electron`,
|
||||
args: [
|
||||
`--app=${__dirname}/../../..`,
|
||||
'--force-device-scale-factor=1',
|
||||
'--no-sandbox',
|
||||
'--disable-dev-shm-usage',
|
||||
'--disable-extensions',
|
||||
].concat(runningUiTestOnCi),
|
||||
windowTypes: ['app', 'webview'],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
async function doStuff() {
|
||||
console.log('Waiting for MQTT Broker on port 1880 (no auth)')
|
||||
await mockMqtt()
|
||||
console.log('start webdriver')
|
||||
|
||||
const browser = await webdriverio.remote(options)
|
||||
await createFakeMousePointer(browser)
|
||||
console.log('Starting playwright/electron')
|
||||
|
||||
// Launch Electron app.
|
||||
const electronApp: ElectronApplication = await electron.launch({
|
||||
args: [`${__dirname}/../../..`, ...runningUiTestOnCi],
|
||||
})
|
||||
|
||||
console.log('Playwright started')
|
||||
// Get the first window that the app opens, wait if necessary.
|
||||
const page = await electronApp.firstWindow({ timeout: 3000 })
|
||||
// Print the title.
|
||||
console.log(await page.title())
|
||||
// Capture a screenshot.
|
||||
await page.screenshot({ path: 'intro.png' })
|
||||
// Direct Electron console to Node terminal.
|
||||
page.on('console', console.log)
|
||||
|
||||
// Wait for Username input to be visible
|
||||
await browser.$('//label[contains(text(), "Username")]/..//input')
|
||||
await page.locator('//label[contains(text(), "Username")]/..//input')
|
||||
|
||||
const scenes = new SceneBuilder()
|
||||
await scenes.record('connect', async () => {
|
||||
await connectTo('127.0.0.1', browser)
|
||||
await connectTo('127.0.0.1', page)
|
||||
await sleep(1000)
|
||||
})
|
||||
|
||||
await scenes.record('numeric_plots', async () => {
|
||||
await showText('Plot topic history', 1500, browser)
|
||||
await showNumericPlot(browser)
|
||||
await showText('Plot topic history', 1500, page)
|
||||
await showNumericPlot(page)
|
||||
await sleep(2000)
|
||||
})
|
||||
|
||||
await scenes.record('json-formatting', async () => {
|
||||
await showJsonPreview(browser)
|
||||
await showText('Formatted messages', 1500, browser, 'top')
|
||||
await showJsonPreview(page)
|
||||
await showText('Formatted messages', 1500, page, 'top')
|
||||
await sleep(1500)
|
||||
})
|
||||
|
||||
await scenes.record('diffs', async () => {
|
||||
await showOffDiffCapability(browser)
|
||||
await hideText(browser)
|
||||
await showOffDiffCapability(page)
|
||||
await hideText(page)
|
||||
})
|
||||
|
||||
await scenes.record('publish_topic', async () => {
|
||||
await showText('Publish topics', 1500, browser, 'top')
|
||||
await clickOnHistory(browser)
|
||||
await publishTopic(browser)
|
||||
await sleep(1000)
|
||||
})
|
||||
// disable this scenario for now until expandTopic is sorted out
|
||||
// await scenes.record('publish_topic', async () => {
|
||||
// await showText('Publish topics', 1500, page, 'top')
|
||||
// await clickOnHistory(page)
|
||||
// await publishTopic(page)
|
||||
// await sleep(1000)
|
||||
// })
|
||||
|
||||
await scenes.record('clipboard', async () => {
|
||||
await showText('Copy to Clipboard', 1500, browser)
|
||||
await copyTopicToClipboard(browser)
|
||||
await hideText(browser)
|
||||
await copyValueToClipboard(browser)
|
||||
await showText('Copy to Clipboard', 1500, page)
|
||||
await copyTopicToClipboard(page)
|
||||
await hideText(page)
|
||||
await copyValueToClipboard(page)
|
||||
await sleep(1000)
|
||||
})
|
||||
|
||||
await scenes.record('topic_filter', async () => {
|
||||
await showText('Search topic hierarchy', 0, browser, 'middle')
|
||||
await searchTree('temp', browser)
|
||||
await hideText(browser)
|
||||
await showText('Topics containing "temp"', 1500, browser)
|
||||
await showText('Search topic hierarchy', 0, page, 'middle')
|
||||
await searchTree('temp', page)
|
||||
await hideText(page)
|
||||
await showText('Topics containing "temp"', 1500, page)
|
||||
await sleep(1500)
|
||||
await clearSearch(browser)
|
||||
await clearSearch(page)
|
||||
await sleep(1000)
|
||||
})
|
||||
|
||||
await scenes.record('delete_retained_topics', async () => {
|
||||
await hideText(browser)
|
||||
await showText('Delete retained topics', 5000, browser)
|
||||
await clearOldTopics(browser)
|
||||
await hideText(browser)
|
||||
})
|
||||
// disable this scenario for now until expandTopic is sorted out
|
||||
// await scenes.record('delete_retained_topics', async () => {
|
||||
// await hideText(page)
|
||||
// await showText('Delete retained topics', 5000, page)
|
||||
// await clearOldTopics(page)
|
||||
// await hideText(page)
|
||||
// })
|
||||
|
||||
await scenes.record('settings', async () => {
|
||||
await showText('Settings', 1500, browser)
|
||||
await showMenu(browser)
|
||||
await showText('Settings', 1500, page)
|
||||
await showMenu(page)
|
||||
})
|
||||
|
||||
await scenes.record('customize_subscriptions', async () => {
|
||||
await sleep(2000)
|
||||
await disconnect(browser)
|
||||
await showText('Customize Subscriptions', 1500, browser, 'top')
|
||||
await showAdvancedConnectionSettings(browser)
|
||||
await disconnect(page)
|
||||
await showText('Customize Subscriptions', 1500, page, 'top')
|
||||
await showAdvancedConnectionSettings(page)
|
||||
})
|
||||
|
||||
await scenes.record('keyboard_shortcuts', async () => {
|
||||
await showText('Keyboard shortcuts', 1500, browser, 'middle')
|
||||
await showText('Keyboard shortcuts', 1500, page, 'middle')
|
||||
await sleep(1750)
|
||||
await showZoomLevel(browser)
|
||||
await showZoomLevel(page)
|
||||
})
|
||||
|
||||
await scenes.record('end', async () => {
|
||||
await showText('The End', 3000, browser, 'middle')
|
||||
await showText('The End', 3000, page, 'middle')
|
||||
await sleep(3000)
|
||||
})
|
||||
|
||||
browser.closeWindow()
|
||||
stopMqtt()
|
||||
console.log('Stopped mqtt')
|
||||
|
||||
fs.writeFileSync('scenes.json', JSON.stringify(scenes.scenes, undefined, ' '))
|
||||
cleanUp(scenes, electronApp)
|
||||
}
|
||||
|
||||
doStuff()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import * as os from 'os'
|
||||
import * as webdriverio from 'webdriverio'
|
||||
import { ElectronApplication, _electron as electron } from 'playwright'
|
||||
|
||||
import mockMqtt, { stopUpdates as stopMqttUpdates } from './mock-mqtt'
|
||||
import { ClassNameMapping, countInstancesOf, createFakeMousePointer, getHeapDump, setFast, sleep } from './util'
|
||||
import { clearSearch, searchTree } from './scenarios/searchTree'
|
||||
@@ -13,67 +14,53 @@ process.on('unhandledRejection', (error: Error | any) => {
|
||||
|
||||
const runningUiTestOnCi = os.platform() === 'darwin' ? [] : ['--runningUiTestOnCi']
|
||||
|
||||
const options = {
|
||||
host: '127.0.0.1', // Use localhost as chrome driver server
|
||||
port: 9515, // "9515" is the port opened by chrome driver.
|
||||
capabilities: {
|
||||
browserName: 'chrome',
|
||||
'goog:chromeOptions': {
|
||||
binary: `${__dirname}/../../../node_modules/.bin/electron`,
|
||||
args: [
|
||||
`--app=${__dirname}/../../..`,
|
||||
'--force-device-scale-factor=1',
|
||||
'--no-sandbox',
|
||||
'--disable-dev-shm-usage',
|
||||
'--disable-extensions',
|
||||
].concat(runningUiTestOnCi),
|
||||
windowTypes: ['app', 'webview'],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
async function doStuff() {
|
||||
console.log('Waiting for MQTT Broker on port 1880 (no auth)')
|
||||
await mockMqtt()
|
||||
console.log('start webdriver')
|
||||
|
||||
const browser = await webdriverio.remote(options)
|
||||
console.log('Starting playwright/electron')
|
||||
|
||||
// Launch Electron app.
|
||||
const electronApp: ElectronApplication = await electron.launch({
|
||||
args: [`${__dirname}/../../..`, ...runningUiTestOnCi],
|
||||
})
|
||||
|
||||
console.log('Playwright started')
|
||||
// Get the first window that the app opens, wait if necessary.
|
||||
const browser = await electronApp.firstWindow({ timeout: 3000 })
|
||||
// Print the title.
|
||||
console.log(await browser.title())
|
||||
// Capture a screenshot.
|
||||
await browser.screenshot({ path: 'intro.png' })
|
||||
// Direct Electron console to Node terminal.
|
||||
browser.on('console', console.log)
|
||||
|
||||
setFast()
|
||||
await createFakeMousePointer(browser)
|
||||
|
||||
// Wait for Username input to be visible
|
||||
await browser.$('//label[contains(text(), "Username")]/..//input')
|
||||
await browser.locator('//label[contains(text(), "Username")]/..//input')
|
||||
await connectTo('127.0.0.1', browser)
|
||||
stopMqttUpdates()
|
||||
await sleep(1000, true)
|
||||
|
||||
const heapDump = await getHeapDump(browser)
|
||||
const initialTreeOccurrences = await countInstancesOf(heapDump, ClassNameMapping.Tree)
|
||||
const initialNodeOccurrences = await countInstancesOf(heapDump, ClassNameMapping.TreeNode)
|
||||
console.log(initialTreeOccurrences, initialNodeOccurrences)
|
||||
|
||||
await doX(3, async () => {
|
||||
await reconnect(browser)
|
||||
})
|
||||
|
||||
await sleep(1000, true)
|
||||
|
||||
await doX(15, async () => {
|
||||
await searchTree('temp', browser)
|
||||
await reconnect(browser)
|
||||
})
|
||||
|
||||
await searchTree('ab', browser)
|
||||
await clearSearch(browser)
|
||||
|
||||
await searchTree('temp', browser)
|
||||
await clearSearch(browser)
|
||||
|
||||
await sleep(1000, true)
|
||||
|
||||
await waitForGarbageCollectorToDetermineLeak(browser, initialTreeOccurrences, initialNodeOccurrences)
|
||||
}
|
||||
|
||||
async function waitForGarbageCollectorToDetermineLeak(
|
||||
browser: any,
|
||||
initialTreeOccurrences: number,
|
||||
@@ -90,7 +77,6 @@ async function waitForGarbageCollectorToDetermineLeak(
|
||||
const heapDump = await getHeapDump(browser)
|
||||
const currentTreeOccurrences = await countInstancesOf(heapDump, ClassNameMapping.Tree)
|
||||
const currentNodeOccurrences = await countInstancesOf(heapDump, ClassNameMapping.TreeNode)
|
||||
|
||||
// Temporary "leaks" are expected due to React Fibers memoization
|
||||
if (
|
||||
Math.abs(initialTreeOccurrences - currentTreeOccurrences) > 1 ||
|
||||
@@ -107,21 +93,17 @@ async function waitForGarbageCollectorToDetermineLeak(
|
||||
} else {
|
||||
leak = false
|
||||
}
|
||||
|
||||
const treeDelta = lastTreeOccurrences >= 0 ? currentTreeOccurrences - lastTreeOccurrences : -1
|
||||
const nodeDelta = lastTreeOccurrences >= 0 ? currentNodeOccurrences - lastNodeOccurrences : -1
|
||||
delta = treeDelta + nodeDelta
|
||||
|
||||
lastTreeOccurrences = currentTreeOccurrences
|
||||
lastNodeOccurrences = currentNodeOccurrences
|
||||
}
|
||||
|
||||
if (leak) {
|
||||
console.error('leak')
|
||||
process.exit(100)
|
||||
}
|
||||
}
|
||||
|
||||
async function doX(x: number, action: () => Promise<any>) {
|
||||
for (let i = 0; i < x; i += 1) {
|
||||
await action()
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { Browser, Element } from 'webdriverio'
|
||||
import { Page } from 'playwright'
|
||||
import { clickOn, expandTopic, moveToCenterOfElement, sleep, writeText } from '../util'
|
||||
|
||||
export async function clearOldTopics(browser: Browser<'async'>) {
|
||||
export async function clearOldTopics(browser: Page) {
|
||||
const topics = ['hello', 'test 123']
|
||||
for (const topic of topics) {
|
||||
await expandTopic(topic, browser)
|
||||
await sleep(1000)
|
||||
|
||||
const deleteButton = await browser.$('//button[contains(@title, "Delete retained topic")]')
|
||||
await moveToCenterOfElement(deleteButton, browser)
|
||||
await clickOn(deleteButton, browser)
|
||||
const deleteButton = await browser.locator('//button[contains(@title, "Delete retained topic")]')
|
||||
await moveToCenterOfElement(deleteButton)
|
||||
await clickOn(deleteButton)
|
||||
await sleep(700)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { Browser, Element } from 'webdriverio'
|
||||
import { clickOn, setTextInInput } from '../util'
|
||||
|
||||
export async function connectTo(host: string, browser: Browser<'async'>) {
|
||||
import { Page, Locator } from 'playwright'
|
||||
export async function connectTo(host: string, browser: Page) {
|
||||
await setTextInInput('Host', host, browser)
|
||||
|
||||
await browser.saveScreenshot('screen1.png')
|
||||
await browser.screenshot({ path: 'screen1.png' })
|
||||
|
||||
const connectButton = await browser.$('//button/span[contains(text(),"Connect")]')
|
||||
await clickOn(connectButton, browser)
|
||||
const connectButton = await browser.locator('//button/span[contains(text(),"Connect")]')
|
||||
await clickOn(connectButton)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Browser } from 'webdriverio'
|
||||
import { Page } from 'playwright'
|
||||
import { clickOn } from '../util'
|
||||
|
||||
export async function copyTopicToClipboard(browser: Browser<'async'>) {
|
||||
const copyButton = await browser.$('//span[contains(text(), "Topic")]//button')
|
||||
await clickOn(copyButton, browser, 1)
|
||||
export async function copyTopicToClipboard(browser: Page) {
|
||||
const copyButton = await browser.locator('//span[contains(text(), "Topic")]//button[1]')
|
||||
await clickOn(copyButton, 1)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Browser } from 'webdriverio'
|
||||
import { Page } from 'playwright'
|
||||
import { clickOn } from '../util'
|
||||
|
||||
export async function copyValueToClipboard(browser: Browser<'async'>) {
|
||||
const copyButton = await browser.$('//span[contains(text(), "Value")]//button')
|
||||
await clickOn(copyButton, browser, 1)
|
||||
export async function copyValueToClipboard(browser: Page) {
|
||||
const copyButton = await browser.locator('//span[contains(text(), "Value")]//button')
|
||||
await clickOn(copyButton, 1)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Browser, Element } from 'webdriverio'
|
||||
import { Page } from 'playwright'
|
||||
import { clickOn } from '../util'
|
||||
|
||||
export async function disconnect(browser: Browser<'async'>) {
|
||||
const disconnectButton = await browser.$('//button/span[contains(text(),"Disconnect")]')
|
||||
await clickOn(disconnectButton, browser)
|
||||
export async function disconnect(browser: Page) {
|
||||
const disconnectButton = await browser.locator('//button/span[contains(text(),"Disconnect")]')
|
||||
await clickOn(disconnectButton)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Browser, Element } from 'webdriverio'
|
||||
import { Page, Locator } from 'playwright'
|
||||
import {
|
||||
clickOn,
|
||||
sleep,
|
||||
@@ -9,30 +9,30 @@ import {
|
||||
showText,
|
||||
} from '../util'
|
||||
|
||||
export async function publishTopic(browser: Browser<'async'>) {
|
||||
export async function publishTopic(browser: Page) {
|
||||
await expandTopic('kitchen/lamp/state', browser)
|
||||
const topicInput = await browser.$('//input[contains(@value,"kitchen/lamp/state")][1]')
|
||||
await clickOn(topicInput, browser)
|
||||
await deleteTextWithBackspaces(topicInput, browser, 120, 5)
|
||||
await writeText('set', browser, 300)
|
||||
const topicInput = await browser.locator('//input[contains(@value,"kitchen/lamp/state")][1]')
|
||||
await clickOn(topicInput)
|
||||
await deleteTextWithBackspaces(topicInput, 120, 5)
|
||||
await writeText('set', topicInput, 300)
|
||||
|
||||
const payloadInput = await browser.$('//*[contains(@class, "ace_text-input")]')
|
||||
const payloadInput = await browser.locator('//*[contains(@class, "ace_text-input")]')
|
||||
await writeTextPayload(payloadInput, 'off')
|
||||
await sleep(500)
|
||||
const formatJsonButton = await browser.$('#sidebar-publish-format-json')
|
||||
await clickOn(formatJsonButton, browser)
|
||||
const formatJsonButton = await browser.locator('#sidebar-publish-format-json')
|
||||
await clickOn(formatJsonButton)
|
||||
|
||||
const publishButton = await browser.$('#publish-button')
|
||||
await moveToCenterOfElement(publishButton, browser)
|
||||
const publishButton = await browser.locator('#publish-button')
|
||||
await moveToCenterOfElement(publishButton)
|
||||
await showText('Lamp turns on', 1000, browser, 'top')
|
||||
await sleep(500)
|
||||
|
||||
await clickOn(publishButton, browser)
|
||||
await clickOn(publishButton)
|
||||
|
||||
const sidebarDrawer = await browser.$('#Sidebar')
|
||||
await sidebarDrawer.scrollIntoView()
|
||||
const sidebarDrawer = await browser.locator('#Sidebar')
|
||||
await sidebarDrawer.scrollIntoViewIfNeeded()
|
||||
}
|
||||
|
||||
async function writeTextPayload(payloadInput: any, text: string) {
|
||||
await payloadInput.setValue(text)
|
||||
async function writeTextPayload(payloadInput: Locator, text: string) {
|
||||
await payloadInput.fill(text)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Browser, Element } from 'webdriverio'
|
||||
import { Page } from 'playwright'
|
||||
import { clickOn } from '../util'
|
||||
|
||||
export async function reconnect(browser: Browser<'async'>) {
|
||||
const disconnectButton = await browser.$('//button/span[contains(text(),"Disconnect")]')
|
||||
await clickOn(disconnectButton, browser)
|
||||
const connectButton = await browser.$('//button/span[contains(text(),"Connect")]')
|
||||
await clickOn(connectButton, browser)
|
||||
export async function reconnect(browser: Page) {
|
||||
const disconnectButton = await browser.locator('//button/span[contains(text(),"Disconnect")]')
|
||||
await clickOn(disconnectButton)
|
||||
const connectButton = await browser.locator('//button/span[contains(text(),"Connect")]')
|
||||
await clickOn(connectButton)
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { Browser, Element } from 'webdriverio'
|
||||
import { Page } from 'playwright'
|
||||
import { clickOn, deleteTextWithBackspaces, showText, sleep, writeText } from '../util'
|
||||
|
||||
export async function searchTree(text: string, browser: Browser<'async'>) {
|
||||
const searchField = await browser.$('//input[contains(@placeholder, "Search")]')
|
||||
await clickOn(searchField, browser, 1)
|
||||
await writeText(text, browser, 100)
|
||||
export async function searchTree(text: string, browser: Page) {
|
||||
const searchField = await browser.locator('//input[contains(@placeholder, "Search")]')
|
||||
await clickOn(searchField, 1)
|
||||
await writeText(text, searchField, 100)
|
||||
await sleep(1500)
|
||||
}
|
||||
|
||||
export async function clearSearch(browser: Browser<'async'>) {
|
||||
const searchField = await browser.$('//input[contains(@placeholder, "Search")]')
|
||||
await clickOn(searchField, browser, 1)
|
||||
await deleteTextWithBackspaces(searchField, browser, 100)
|
||||
export async function clearSearch(browser: Page) {
|
||||
const searchField = await browser.locator('//input[contains(@placeholder, "Search")]')
|
||||
await clickOn(searchField, 1)
|
||||
await deleteTextWithBackspaces(searchField, 100)
|
||||
}
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
import { Browser } from 'webdriverio'
|
||||
import { Page } from 'playwright'
|
||||
import { clickOn, sleep, setInputText } from '../util'
|
||||
|
||||
export async function showAdvancedConnectionSettings(browser: Browser<'async'>) {
|
||||
const advancedSettingsButton = await browser.$('//button/span[contains(text(),"Advanced")]')
|
||||
const addButton = await browser.$('//button/span[contains(text(),"Add")]')
|
||||
const topicInput = await browser.$('//*[contains(@class, "advanced-connection-settings-topic-input")]//input')
|
||||
export async function showAdvancedConnectionSettings(browser: Page) {
|
||||
const advancedSettingsButton = await browser.locator('//button/span[contains(text(),"Advanced")]')
|
||||
const addButton = await browser.locator('//button/span[contains(text(),"Add")]')
|
||||
const topicInput = await browser.locator('//*[contains(@class, "advanced-connection-settings-topic-input")]//input')
|
||||
|
||||
await clickOn(advancedSettingsButton, browser)
|
||||
await clickOn(advancedSettingsButton)
|
||||
await setInputText(topicInput, 'garden/#', browser)
|
||||
await clickOn(addButton, browser)
|
||||
await clickOn(addButton)
|
||||
|
||||
await setInputText(topicInput, 'livingroom/#', browser)
|
||||
await clickOn(addButton, browser)
|
||||
await clickOn(addButton)
|
||||
|
||||
await deleteFirstSubscribedTopic(browser)
|
||||
await deleteFirstSubscribedTopic(browser)
|
||||
await sleep(1000)
|
||||
|
||||
const backButton = await browser.$('//button/span[contains(text(),"Back")]')
|
||||
await clickOn(backButton, browser)
|
||||
const backButton = await browser.locator('//button/span[contains(text(),"Back")]').first()
|
||||
await clickOn(backButton)
|
||||
|
||||
const connectButton = await browser.$('//button/span[contains(text(),"Connect")]')
|
||||
await clickOn(connectButton, browser)
|
||||
const connectButton = await browser.locator('//button/span[contains(text(),"Connect")]')
|
||||
await clickOn(connectButton)
|
||||
}
|
||||
|
||||
async function deleteFirstSubscribedTopic(browser: Browser<'async'>) {
|
||||
const deleteButton = await browser.$('.advanced-connection-settings-topic-list button')
|
||||
await clickOn(deleteButton, browser)
|
||||
async function deleteFirstSubscribedTopic(browser: Page) {
|
||||
const deleteButton = await browser.locator('.advanced-connection-settings-topic-list button').first()
|
||||
await clickOn(deleteButton)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Browser, Element } from 'webdriverio'
|
||||
import { Page, Locator } from 'playwright'
|
||||
import { expandTopic, sleep } from '../util'
|
||||
|
||||
export async function showJsonPreview(browser: Browser<'async'>) {
|
||||
export async function showJsonPreview(browser: Page) {
|
||||
await expandTopic('actuality/showcase', browser)
|
||||
await browser.saveScreenshot('screen3.png')
|
||||
await browser.screenshot({ path: 'screen3.png' })
|
||||
await sleep(1000)
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
import { Browser } from 'webdriverio'
|
||||
import { Page } from 'playwright'
|
||||
import { clickOn, showText, sleep } from '../util'
|
||||
|
||||
export async function showMenu(browser: Browser<'async'>) {
|
||||
const menuButton = await browser.$('//button[contains(@aria-label, "Menu")]')
|
||||
await clickOn(menuButton, browser)
|
||||
export async function showMenu(browser: Page) {
|
||||
const menuButton = await browser.locator('//button[contains(@aria-label, "Menu")]')
|
||||
await clickOn(menuButton)
|
||||
|
||||
// const brokerStatistics = await browser.$('//div[contains(@class, "BrokerStatistics")]/div[1]')
|
||||
// moveToCenterOfElement(brokerStatistics, browser)
|
||||
await sleep(2000)
|
||||
|
||||
await browser.saveScreenshot('screen4.png')
|
||||
await browser.screenshot({ path: 'screen4.png' })
|
||||
|
||||
const topicOrder = await browser.$('//input[@name="node-order"]/../div')
|
||||
await clickOn(topicOrder, browser)
|
||||
const topicOrder = await browser.locator('//input[@name="node-order"]/../div')
|
||||
await clickOn(topicOrder)
|
||||
await sleep(1000)
|
||||
|
||||
const alphabetically = await browser.$('//li[contains(@data-value, "abc")]')
|
||||
await clickOn(alphabetically, browser)
|
||||
const alphabetically = await browser.locator('//li[contains(@data-value, "abc")]')
|
||||
await clickOn(alphabetically)
|
||||
await sleep(2000)
|
||||
|
||||
await showText('Dark Mode', 1500, browser, 'top')
|
||||
await sleep(1500)
|
||||
const themeSwitch = await browser.$('//*[contains(text(), "Dark Mode")]/..//input')
|
||||
await clickOn(themeSwitch, browser)
|
||||
const themeSwitch = await browser.locator('//*[contains(text(), "Dark Mode")]/..//input')
|
||||
await clickOn(themeSwitch)
|
||||
await sleep(3000)
|
||||
await browser.saveScreenshot('screen_dark_mode.png')
|
||||
await clickOn(themeSwitch, browser)
|
||||
await browser.screenshot({ path: 'screen_dark_mode.png' })
|
||||
await clickOn(themeSwitch)
|
||||
|
||||
await clickOn(menuButton, browser)
|
||||
await clickOn(menuButton)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Browser, Element } from 'webdriverio'
|
||||
import { Page } from 'playwright'
|
||||
import { moveToCenterOfElement, clickOn, clickOnHistory, expandTopic, sleep, writeText } from '../util'
|
||||
|
||||
export async function showNumericPlot(browser: Browser<'async'>) {
|
||||
export async function showNumericPlot(browser: Page) {
|
||||
await expandTopic('kitchen/coffee_maker', browser)
|
||||
let heater = await valuePreviewGuttersShowChartIcon('heater', browser)
|
||||
await moveToCenterOfElement(heater, browser)
|
||||
await moveToCenterOfElement(heater)
|
||||
await sleep(1000)
|
||||
// Refocus and click
|
||||
heater = await valuePreviewGuttersShowChartIcon('heater', browser)
|
||||
@@ -12,7 +12,7 @@ export async function showNumericPlot(browser: Browser<'async'>) {
|
||||
|
||||
await sleep(1000)
|
||||
let temperature = await valuePreviewGuttersShowChartIcon('temperature', browser)
|
||||
await moveToCenterOfElement(temperature, browser)
|
||||
await moveToCenterOfElement(temperature)
|
||||
await sleep(1000)
|
||||
// Refocus and click
|
||||
temperature = await valuePreviewGuttersShowChartIcon('temperature', browser)
|
||||
@@ -30,7 +30,7 @@ export async function showNumericPlot(browser: Browser<'async'>) {
|
||||
await clickAway('temperature', browser)
|
||||
await sleep(2500)
|
||||
|
||||
await browser.saveScreenshot('screen_chart_panel.png')
|
||||
await browser.screenshot({ path: 'screen_chart_panel.png' })
|
||||
|
||||
await removeChart('heater', browser)
|
||||
await sleep(750)
|
||||
@@ -42,34 +42,38 @@ export async function showNumericPlot(browser: Browser<'async'>) {
|
||||
await clickOnHistory(browser)
|
||||
}
|
||||
|
||||
async function valuePreviewGuttersShowChartIcon(name: string, browser: Browser<'async'>) {
|
||||
async function valuePreviewGuttersShowChartIcon(name: string, browser: Page) {
|
||||
for (let retries = 0; retries < 2; retries += 1) {
|
||||
try {
|
||||
return await browser.$(`//*[contains(@data-test-type, "ShowChart")][contains(@data-test, "${name}")]`)
|
||||
return await browser.locator(`//*[contains(@data-test-type, "ShowChart")][contains(@data-test, "${name}")]`)
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
return browser.$(`//*[contains(@data-test-type, "ShowChart")][contains(@data-test, "${name}")]`)
|
||||
return browser.locator(`//*[contains(@data-test-type, "ShowChart")][contains(@data-test, "${name}")]`)
|
||||
}
|
||||
|
||||
async function chartSettings(name: string, browser: Browser<'async'>) {
|
||||
const settings = await browser.$(`//*[contains(@data-test-type, "ChartSettings")][contains(@data-test, "${name}")]`)
|
||||
return clickOn(settings, browser)
|
||||
async function chartSettings(name: string, browser: Page) {
|
||||
const settings = await browser.locator(
|
||||
`//*[contains(@data-test-type, "ChartSettings")][contains(@data-test, "${name}")]`
|
||||
)
|
||||
return clickOn(settings)
|
||||
}
|
||||
|
||||
async function clickAway(name: string, browser: Browser<'async'>) {
|
||||
const settings = await browser.$(`//*[contains(@data-test-type, "ChartPaper")][contains(@data-test, "${name}")]`)
|
||||
await moveToCenterOfElement(settings, browser)
|
||||
await browser.keys(['Escape'])
|
||||
async function clickAway(name: string, browser: Page) {
|
||||
const settings = await browser.locator(
|
||||
`//*[contains(@data-test-type, "ChartPaper")][contains(@data-test, "${name}")]`
|
||||
)
|
||||
await moveToCenterOfElement(settings)
|
||||
await settings.press('Escape')
|
||||
}
|
||||
|
||||
async function removeChart(name: string, browser: Browser<'async'>) {
|
||||
const remove = await browser.$(`//*[contains(@data-test-type, "RemoveChart")][contains(@data-test, "${name}")]`)
|
||||
return clickOn(remove, browser)
|
||||
async function removeChart(name: string, browser: Page) {
|
||||
const remove = await browser.locator(`//*[contains(@data-test-type, "RemoveChart")][contains(@data-test, "${name}")]`)
|
||||
return clickOn(remove)
|
||||
}
|
||||
|
||||
async function clickOnMenuPoint(name: string, browser: Browser<'async'>) {
|
||||
const item = await browser.$(`//li/span[contains(text(), "${name}")]`)
|
||||
return clickOn(item, browser)
|
||||
async function clickOnMenuPoint(name: string, browser: Page) {
|
||||
const item = await browser.locator(`//li/span[contains(text(), "${name}")]`)
|
||||
return clickOn(item)
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import { Browser, Element } from 'webdriverio'
|
||||
import { Page, Locator } from 'playwright'
|
||||
import { clickOn, showText, sleep } from '../util'
|
||||
|
||||
// Expects a topic with at least two messages to be selected
|
||||
export async function showOffDiffCapability(browser: Browser<'async'>) {
|
||||
export async function showOffDiffCapability(browser: Page) {
|
||||
await showText('Compare messages', 2000, browser, 'top')
|
||||
|
||||
await showText('Show raw message', 2000, browser, 'bottom')
|
||||
const rawMessage = await browser.$('#valueRendererDisplayMode-raw')
|
||||
await clickOn(rawMessage, browser)
|
||||
const rawMessage = await browser.locator('#valueRendererDisplayMode-raw')
|
||||
await clickOn(rawMessage)
|
||||
await sleep(1000)
|
||||
|
||||
await showText('Compare with others', 2000, browser, 'bottom')
|
||||
const diffMessages = await browser.$('#valueRendererDisplayMode-diff')
|
||||
await clickOn(diffMessages, browser)
|
||||
const diffMessages = await browser.locator('#valueRendererDisplayMode-diff')
|
||||
await clickOn(diffMessages)
|
||||
|
||||
// // const firstEntry = await browser.$('//span[contains(text(), "History")]/../../div/div[1]/div')
|
||||
// const secondEntry = await browser.$('//span[contains(text(), "History")]/../../div/div[2]/div')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Browser, Element } from 'webdriverio'
|
||||
import { Page } from 'playwright'
|
||||
import { showKeys, showText, sleep } from '../util'
|
||||
|
||||
export async function showZoomLevel(browser: Browser<'async'>) {
|
||||
export async function showZoomLevel(browser: Page) {
|
||||
await showKeys('Zoom in', 2000, browser, 'top', ['Ctrl', '+'])
|
||||
await sleep(2000)
|
||||
await showKeys('Zoom out', 2000, browser, 'middle', ['Ctrl', '-'])
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { clickOn } from './'
|
||||
import { Browser, Element } from 'webdriverio'
|
||||
import { Page } from 'playwright'
|
||||
|
||||
export async function expandTopic(path: string, browser: Browser<'async'>) {
|
||||
export async function expandTopic(path: string, browser: Page) {
|
||||
const originalTopics = path.split('/')
|
||||
console.log('expandTopic', path)
|
||||
let topics = path.split('/')
|
||||
while (topics.length > 0 && !(await topicMatches(topics, browser))) {
|
||||
topics = topics.slice(0, topics.length - 1)
|
||||
@@ -11,19 +12,28 @@ export async function expandTopic(path: string, browser: Browser<'async'>) {
|
||||
throw Error('could not expand topics, no match found')
|
||||
}
|
||||
|
||||
while (topics.length <= originalTopics.length) {
|
||||
const match = await browser.$(topicSelector(topics))
|
||||
await clickOn(match, browser)
|
||||
topics.push(originalTopics[topics.length])
|
||||
console.log('found topics', topics, originalTopics)
|
||||
|
||||
for (const topic of topics) {
|
||||
const match = await browser.locator(topicSelector([topic]))
|
||||
await clickOn(match.first())
|
||||
}
|
||||
// while (topics.length <= originalTopics.length) {
|
||||
// const match = await browser.locator(topicSelector(topics))
|
||||
// console.log('topics', topics, 'orignial', originalTopics)
|
||||
// console.log('click', match)
|
||||
// await clickOn(match)
|
||||
// topics.push(originalTopics[topics.length])
|
||||
// }
|
||||
}
|
||||
|
||||
async function topicMatches(topics: Array<string>, browser: Browser<'async'>) {
|
||||
const result = await browser.$(topicSelector(topics))
|
||||
return result.isExisting()
|
||||
async function topicMatches(topics: Array<string>, browser: Page) {
|
||||
const result = await browser.locator(topicSelector(topics))
|
||||
console.log('topic matches', topics, result)
|
||||
return true
|
||||
}
|
||||
|
||||
function topicSelector(topics: Array<string>) {
|
||||
const suffix = topics.map(topic => `*[contains(text(), "${topic}")]`).join('/../..//')
|
||||
return `//${suffix}`
|
||||
const selectors = topics.map(v => `span[data-test-topic='${v}']`)
|
||||
return selectors.join(' ')
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import * as fs from 'fs'
|
||||
import { Browser, Element } from 'webdriverio'
|
||||
|
||||
import { Page, Locator } from 'playwright'
|
||||
|
||||
export { expandTopic } from './expandTopic'
|
||||
|
||||
@@ -18,48 +19,45 @@ export function sleep(ms: number, required = false) {
|
||||
})
|
||||
}
|
||||
|
||||
export async function writeText(text: string, browser: Browser<'async'>, delay = 0) {
|
||||
export async function writeText(text: string, element: Locator, delay = 0) {
|
||||
return element.fill(text)
|
||||
if (fast) {
|
||||
return browser.keys(text.split(''))
|
||||
return element.fill(text)
|
||||
}
|
||||
|
||||
for (const c of text.split('')) {
|
||||
await browser.keys([c])
|
||||
await element.press(c)
|
||||
await sleep(delay)
|
||||
}
|
||||
}
|
||||
|
||||
export async function deleteTextWithBackspaces(
|
||||
element: Element<'async'>,
|
||||
browser: Browser<'async'>,
|
||||
delay = 0,
|
||||
count = 0
|
||||
) {
|
||||
const length = count > 0 ? count : (await element.getValue()).length
|
||||
export async function deleteTextWithBackspaces(element: Locator, delay = 0, count = 0) {
|
||||
// @ts-ignore
|
||||
const length = count > 0 ? count : (await element.textContent()).length
|
||||
for (let i = 0; i < length; i += 1) {
|
||||
await browser.keys(['Backspace'])
|
||||
await element.press('Backspace')
|
||||
await sleep(delay)
|
||||
}
|
||||
}
|
||||
|
||||
export async function setInputText(input: Element<'async'>, text: string, browser: Browser<'async'>) {
|
||||
await clickOn(input, browser, 1)
|
||||
await deleteTextWithBackspaces(input, browser)
|
||||
await input.setValue(text)
|
||||
export async function setInputText(input: Locator, text: string, browser: Page) {
|
||||
await clickOn(input, 1)
|
||||
await deleteTextWithBackspaces(input)
|
||||
await input.fill(text)
|
||||
}
|
||||
|
||||
export async function setTextInInput(name: string, text: string, browser: Browser<'async'>) {
|
||||
const input = await browser.$(`//label[contains(text(), "${name}")]/..//input`)
|
||||
await clickOn(input, browser, 1)
|
||||
await browser.$(`//label[contains(text(), "${name}")]/..//input`)
|
||||
export async function setTextInInput(name: string, text: string, browser: Page) {
|
||||
const input = await browser.locator(`//label[contains(text(), "${name}")]/..//input`)
|
||||
await clickOn(input, 1)
|
||||
await browser.locator(`//label[contains(text(), "${name}")]/..//input`)
|
||||
|
||||
await deleteTextWithBackspaces(input, browser)
|
||||
await input.setValue(text)
|
||||
await deleteTextWithBackspaces(input)
|
||||
await input.fill(text)
|
||||
}
|
||||
|
||||
export async function moveToCenterOfElement(element: Element<'async'>, browser: Browser<'async'>) {
|
||||
const { x, y } = await element.getLocation()
|
||||
const { width, height } = await element.getSize()
|
||||
export async function moveToCenterOfElement(element: Locator) {
|
||||
// @ts-ignore
|
||||
const { x, y, width, height } = await element.boundingBox()
|
||||
|
||||
const targetX = x + width / 2
|
||||
const targetY = y + height / 2
|
||||
@@ -67,50 +65,59 @@ export async function moveToCenterOfElement(element: Element<'async'>, browser:
|
||||
const duration = fast ? 1 : 500
|
||||
|
||||
const js = `window.demo.moveMouse(${targetX}, ${targetY}, ${duration});`
|
||||
await browser.execute(js)
|
||||
await runJavascript(js, element.page())
|
||||
await sleep(duration)
|
||||
await sleep(250, true)
|
||||
|
||||
await element.moveTo()
|
||||
}
|
||||
|
||||
export async function clickOnHistory(browser: Browser<'async'>) {
|
||||
const messageHistory = await browser.$('//span/*[contains(text(), "History")]')
|
||||
await clickOn(messageHistory, browser)
|
||||
export async function runJavascript(js: string, browser: Page) {
|
||||
// there is probably a safer way to do this.. do not use eval...
|
||||
// tslint:disable-next-line no-eval
|
||||
return browser.evaluate(script => eval(script), js)
|
||||
}
|
||||
|
||||
export async function clickOn(element: Element<'async'>, browser: Browser<'async'>, clicks = 1) {
|
||||
await moveToCenterOfElement(element, browser)
|
||||
for (let i = 0; i < clicks; i += 1) {
|
||||
await element.click()
|
||||
export async function clickOnHistory(browser: Page) {
|
||||
const messageHistory = await browser.locator('//span/*[contains(text(), "History")]').first()
|
||||
await clickOn(messageHistory)
|
||||
}
|
||||
|
||||
export async function clickOn(
|
||||
element: Locator,
|
||||
clicks = 1,
|
||||
delay = 0,
|
||||
button: 'left' | 'right' | 'middle' = 'left',
|
||||
force = false
|
||||
) {
|
||||
await moveToCenterOfElement(element)
|
||||
await element.hover()
|
||||
await element.click({ delay, button, force, clickCount: clicks })
|
||||
await sleep(50)
|
||||
}
|
||||
}
|
||||
|
||||
export async function createFakeMousePointer(browser: Browser<'async'>) {
|
||||
export async function createFakeMousePointer(browser: Page) {
|
||||
const js = 'window.demo.enableMouse();'
|
||||
|
||||
await browser.execute(js)
|
||||
// @ts-lint-ignore
|
||||
await runJavascript(js, browser)
|
||||
}
|
||||
|
||||
export async function showText(
|
||||
text: string,
|
||||
duration: number = 0,
|
||||
browser: Browser<'async'>,
|
||||
browser: Page,
|
||||
location: 'top' | 'bottom' | 'middle' = 'bottom',
|
||||
keys = []
|
||||
) {
|
||||
const js = `window.demo.showMessage('${text}', '${location}', ${duration});`
|
||||
|
||||
await browser.execute(js)
|
||||
await runJavascript(js, browser)
|
||||
}
|
||||
|
||||
type HeapDump = any
|
||||
|
||||
export async function getHeapDump(browser: Browser<'async'>): Promise<HeapDump> {
|
||||
export async function getHeapDump(browser: Page): Promise<HeapDump> {
|
||||
const filename = 'heapdump.json'
|
||||
const js = `window.demo.writeHeapdump('${filename}');`
|
||||
await browser.execute(js)
|
||||
await runJavascript(js, browser)
|
||||
const buffer = fs.readFileSync(filename)
|
||||
fs.unlinkSync(filename)
|
||||
|
||||
@@ -130,17 +137,17 @@ export async function countInstancesOf(heapDump: HeapDump, className: ClassNameM
|
||||
export async function showKeys(
|
||||
text: string,
|
||||
duration: number = 0,
|
||||
browser: Browser<'async'>,
|
||||
browser: Page,
|
||||
location: 'top' | 'bottom' | 'middle' = 'bottom',
|
||||
keys: Array<string> = []
|
||||
) {
|
||||
const js = `window.demo.showMessage('${text}', '${location}', ${duration}, ${JSON.stringify(keys)});`
|
||||
|
||||
await browser.execute(js)
|
||||
await runJavascript(js, browser)
|
||||
}
|
||||
|
||||
export async function hideText(browser: Browser<'async'>) {
|
||||
export async function hideText(browser: Page) {
|
||||
const js = 'window.demo.hideMessage();'
|
||||
await browser.execute(js)
|
||||
await runJavascript(js, browser)
|
||||
await sleep(600)
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"sourceRoot": "src/",
|
||||
"target": "ES2017",
|
||||
"lib": [
|
||||
"es2017",
|
||||
"dom"
|
||||
|
||||
Reference in New Issue
Block a user