fix test script and video capture
This commit is contained in:
@@ -90,4 +90,4 @@
|
|||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"electron": "^29"
|
"electron": "^29"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM node:11-stretch
|
FROM node:19.8.1-bullseye-slim
|
||||||
|
|
||||||
RUN DEBIAN_FRONTEND="noninteractive" apt-get update \
|
RUN DEBIAN_FRONTEND="noninteractive" apt-get update \
|
||||||
&& apt-get install -y --no-install-recommends nano ffmpeg xvfb git-core tmux locales mosquitto x11vnc
|
&& apt-get install -y --no-install-recommends nano ffmpeg xvfb git-core tmux locales mosquitto x11vnc
|
||||||
|
|||||||
@@ -16,9 +16,11 @@
|
|||||||
"dev:app": "cd app && npm run dev",
|
"dev:app": "cd app && npm run dev",
|
||||||
"dev:electron": "tsc && electron . --development",
|
"dev:electron": "tsc && electron . --development",
|
||||||
"lint": "npm-run-all --parallel lint:prettier lint:tslint",
|
"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": "prettier --check \"**/*.ts{x,}\"",
|
||||||
"lint:prettier:fix": "prettier --write \"**/*.ts{x,}\"",
|
"lint:prettier:fix": "prettier --write \"**/*.ts{x,}\"",
|
||||||
"lint:tslint": "tslint -p ./",
|
"lint:tslint": "tslint -p ./",
|
||||||
|
"lint:tslint:fix": "tslint -p ./ --fix",
|
||||||
"lint:spellcheck": "cspell -e ./build -e \"node_modules\" \"**/*.ts{x,}\"",
|
"lint:spellcheck": "cspell -e ./build -e \"node_modules\" \"**/*.ts{x,}\"",
|
||||||
"build": "tsc && cd app && yarn run build && cd ..",
|
"build": "tsc && cd app && yarn run build && cd ..",
|
||||||
"prepare-release": "ts-node scripts/prepare-release.ts",
|
"prepare-release": "ts-node scripts/prepare-release.ts",
|
||||||
@@ -88,13 +90,13 @@
|
|||||||
"builder-util-runtime": "^9",
|
"builder-util-runtime": "^9",
|
||||||
"chai": "^4.2.0",
|
"chai": "^4.2.0",
|
||||||
"cspell": "^4.0.28",
|
"cspell": "^4.0.28",
|
||||||
"electron": "29.1.1",
|
"electron": "29.2.0",
|
||||||
"electron-builder": "^24.13.3",
|
"electron-builder": "^24.13.3",
|
||||||
"mocha": "^10.4.0",
|
"mocha": "^10.4.0",
|
||||||
"mustache": "4",
|
"mustache": "4",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"nyc": "15",
|
"nyc": "15",
|
||||||
"playwright": "^1.42.1",
|
"playwright": "^1.43.0",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"redux-thunk": "^2.3.0",
|
"redux-thunk": "^2.3.0",
|
||||||
"source-map-support": "^0.5.9",
|
"source-map-support": "^0.5.9",
|
||||||
@@ -122,4 +124,4 @@
|
|||||||
"uuid": "^8.3.2",
|
"uuid": "^8.3.2",
|
||||||
"yarn-run-all": "^3.1.1"
|
"yarn-run-all": "^3.1.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,25 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
function finish {
|
function finish {
|
||||||
echo "Exiting, cleaning up"
|
set +e
|
||||||
tmux send-keys -t record q || echo "No tmux was running"
|
echo "Exiting, cleaning up.."
|
||||||
#echo kill $PID_XVFB $PID_CHROMEDRIVER $PID_MOSQUITTO
|
|
||||||
#kill $PID_XVFB $PID_CHROMEDRIVER $PID_MOSQUITTO
|
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
|
trap finish EXIT
|
||||||
@@ -18,28 +33,25 @@ export PID_XVFB=$!
|
|||||||
sleep 2
|
sleep 2
|
||||||
|
|
||||||
# Debug with VNC
|
# 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=$!
|
export PID_VNC=$!
|
||||||
|
|
||||||
# Start mqtt broker
|
# Start mqtt broker
|
||||||
mosquitto &
|
mosquitto &
|
||||||
export PID_MOSQUITTO=$!
|
export PID_MOSQUITTO=$!
|
||||||
|
|
||||||
#DISPLAY=:$SCR ./node_modules/.bin/chromedriver --url-base=wd/hub --port=9515 &
|
|
||||||
#export PID_CHROMEDRIVER=$!
|
|
||||||
#sleep 2
|
|
||||||
|
|
||||||
# Delete old video
|
# 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
|
# 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
|
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
|
# Start tests
|
||||||
node dist/src/spec/demoVideo.js
|
DISPLAY=:$SCR node dist/src/spec/demoVideo.js
|
||||||
TEST_EXIT_CODE=$?
|
TEST_EXIT_CODE=$?
|
||||||
echo "Webriver exitet with $TEST_EXIT_CODE"
|
echo "Test script exited with $TEST_EXIT_CODE"
|
||||||
|
|
||||||
# Stop recording
|
# Stop recording
|
||||||
tmux send-keys -t record q
|
tmux send-keys -t record q
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import * as fs from 'fs'
|
|||||||
import * as os from 'os'
|
import * as os from 'os'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
|
|
||||||
import { ElectronApplication, Page, _electron as electron } from 'playwright'
|
import { ElectronApplication, _electron as electron } from 'playwright'
|
||||||
|
|
||||||
import mockMqtt, { stop as stopMqtt } from './mock-mqtt'
|
import mockMqtt, { stop as stopMqtt } from './mock-mqtt'
|
||||||
import { clearOldTopics } from './scenarios/clearOldTopics'
|
import { clearOldTopics } from './scenarios/clearOldTopics'
|
||||||
@@ -13,7 +13,7 @@ import { copyTopicToClipboard } from './scenarios/copyTopicToClipboard'
|
|||||||
import { copyValueToClipboard } from './scenarios/copyValueToClipboard'
|
import { copyValueToClipboard } from './scenarios/copyValueToClipboard'
|
||||||
import { disconnect } from './scenarios/disconnect'
|
import { disconnect } from './scenarios/disconnect'
|
||||||
import { publishTopic } from './scenarios/publishTopic'
|
import { publishTopic } from './scenarios/publishTopic'
|
||||||
import { SceneBuilder } from './SceneBuilder'
|
import { Scene, SceneBuilder } from './SceneBuilder'
|
||||||
import { showAdvancedConnectionSettings } from './scenarios/showAdvancedConnectionSettings'
|
import { showAdvancedConnectionSettings } from './scenarios/showAdvancedConnectionSettings'
|
||||||
import { showJsonPreview } from './scenarios/showJsonPreview'
|
import { showJsonPreview } from './scenarios/showJsonPreview'
|
||||||
import { showMenu } from './scenarios/showMenu'
|
import { showMenu } from './scenarios/showMenu'
|
||||||
@@ -21,6 +21,15 @@ import { showNumericPlot } from './scenarios/showNumericPlot'
|
|||||||
import { showOffDiffCapability } from './scenarios/showOffDiffCapability'
|
import { showOffDiffCapability } from './scenarios/showOffDiffCapability'
|
||||||
import { showZoomLevel } from './scenarios/showZoomLevel'
|
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) => {
|
process.on('unhandledRejection', (error: Error | any) => {
|
||||||
console.error('unhandledRejection', error.message, error.stack)
|
console.error('unhandledRejection', error.message, error.stack)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
@@ -36,16 +45,10 @@ async function doStuff() {
|
|||||||
|
|
||||||
// Launch Electron app.
|
// Launch Electron app.
|
||||||
const electronApp: ElectronApplication = await electron.launch({
|
const electronApp: ElectronApplication = await electron.launch({
|
||||||
args: [`${__dirname}/../../..`],
|
args: [`${__dirname}/../../..`, ...runningUiTestOnCi],
|
||||||
// recordVideo: {
|
|
||||||
// dir: path.join(__dirname, '..', 'playwright-videos'),
|
|
||||||
// size: {
|
|
||||||
// width: 1280,
|
|
||||||
// height: 720,
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
console.log('Playwright started')
|
||||||
// Get the first window that the app opens, wait if necessary.
|
// Get the first window that the app opens, wait if necessary.
|
||||||
const page = await electronApp.firstWindow({ timeout: 3000 })
|
const page = await electronApp.firstWindow({ timeout: 3000 })
|
||||||
// Print the title.
|
// Print the title.
|
||||||
@@ -138,14 +141,10 @@ async function doStuff() {
|
|||||||
await sleep(3000)
|
await sleep(3000)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Exit app.
|
|
||||||
await electronApp.close()
|
|
||||||
console.log('Electron exited')
|
|
||||||
|
|
||||||
stopMqtt()
|
stopMqtt()
|
||||||
console.log('Stopped mqtt')
|
console.log('Stopped mqtt')
|
||||||
|
|
||||||
fs.writeFileSync('scenes.json', JSON.stringify(scenes.scenes, undefined, ' '))
|
cleanUp(scenes, electronApp)
|
||||||
}
|
}
|
||||||
|
|
||||||
doStuff()
|
doStuff()
|
||||||
|
|||||||
@@ -1,131 +1,114 @@
|
|||||||
// import * as os from 'os'
|
import * as os from 'os'
|
||||||
// import mockMqtt, { stopUpdates as stopMqttUpdates } from './mock-mqtt'
|
import { ElectronApplication, _electron as electron } from 'playwright'
|
||||||
// import { ClassNameMapping, countInstancesOf, createFakeMousePointer, getHeapDump, setFast, sleep } from './util'
|
|
||||||
// import { clearSearch, searchTree } from './scenarios/searchTree'
|
|
||||||
// import { connectTo } from './scenarios/connect'
|
|
||||||
// import { reconnect } from './scenarios/reconnect'
|
|
||||||
|
|
||||||
// process.on('unhandledRejection', (error: Error | any) => {
|
import mockMqtt, { stopUpdates as stopMqttUpdates } from './mock-mqtt'
|
||||||
// console.error('unhandledRejection', error.message, error.stack)
|
import { ClassNameMapping, countInstancesOf, createFakeMousePointer, getHeapDump, setFast, sleep } from './util'
|
||||||
// process.exit(1)
|
import { clearSearch, searchTree } from './scenarios/searchTree'
|
||||||
// })
|
import { connectTo } from './scenarios/connect'
|
||||||
|
import { reconnect } from './scenarios/reconnect'
|
||||||
|
|
||||||
// const runningUiTestOnCi = os.platform() === 'darwin' ? [] : ['--runningUiTestOnCi']
|
process.on('unhandledRejection', (error: Error | any) => {
|
||||||
|
console.error('unhandledRejection', error.message, error.stack)
|
||||||
|
process.exit(1)
|
||||||
|
})
|
||||||
|
|
||||||
// const options = {
|
const runningUiTestOnCi = os.platform() === 'darwin' ? [] : ['--runningUiTestOnCi']
|
||||||
// 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() {
|
async function doStuff() {
|
||||||
// console.log('Waiting for MQTT Broker on port 1880 (no auth)')
|
console.log('Waiting for MQTT Broker on port 1880 (no auth)')
|
||||||
// await mockMqtt()
|
await mockMqtt()
|
||||||
// console.log('start webdriver')
|
|
||||||
|
|
||||||
// const browser = await webdriverio.remote(options)
|
console.log('Starting playwright/electron')
|
||||||
// setFast()
|
|
||||||
// await createFakeMousePointer(browser)
|
|
||||||
|
|
||||||
// // Wait for Username input to be visible
|
// Launch Electron app.
|
||||||
// await browser.$('//label[contains(text(), "Username")]/..//input')
|
const electronApp: ElectronApplication = await electron.launch({
|
||||||
// await connectTo('127.0.0.1', browser)
|
args: [`${__dirname}/../../..`, ...runningUiTestOnCi],
|
||||||
// stopMqttUpdates()
|
})
|
||||||
// await sleep(1000, true)
|
|
||||||
|
|
||||||
// const heapDump = await getHeapDump(browser)
|
console.log('Playwright started')
|
||||||
// const initialTreeOccurrences = await countInstancesOf(heapDump, ClassNameMapping.Tree)
|
// Get the first window that the app opens, wait if necessary.
|
||||||
// const initialNodeOccurrences = await countInstancesOf(heapDump, ClassNameMapping.TreeNode)
|
const browser = await electronApp.firstWindow({ timeout: 3000 })
|
||||||
// console.log(initialTreeOccurrences, initialNodeOccurrences)
|
// 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)
|
||||||
|
|
||||||
// await doX(3, async () => {
|
setFast()
|
||||||
// await reconnect(browser)
|
await createFakeMousePointer(browser)
|
||||||
// })
|
// Wait for Username input to be visible
|
||||||
|
await browser.locator('//label[contains(text(), "Username")]/..//input')
|
||||||
// await sleep(1000, true)
|
await connectTo('127.0.0.1', browser)
|
||||||
|
stopMqttUpdates()
|
||||||
// await doX(15, async () => {
|
await sleep(1000, true)
|
||||||
// await searchTree('temp', browser)
|
const heapDump = await getHeapDump(browser)
|
||||||
// await reconnect(browser)
|
const initialTreeOccurrences = await countInstancesOf(heapDump, ClassNameMapping.Tree)
|
||||||
// })
|
const initialNodeOccurrences = await countInstancesOf(heapDump, ClassNameMapping.TreeNode)
|
||||||
|
console.log(initialTreeOccurrences, initialNodeOccurrences)
|
||||||
// await searchTree('ab', browser)
|
await doX(3, async () => {
|
||||||
// await clearSearch(browser)
|
await reconnect(browser)
|
||||||
|
})
|
||||||
// await searchTree('temp', browser)
|
await sleep(1000, true)
|
||||||
// await clearSearch(browser)
|
await doX(15, async () => {
|
||||||
|
await searchTree('temp', browser)
|
||||||
// await sleep(1000, true)
|
await reconnect(browser)
|
||||||
|
})
|
||||||
// await waitForGarbageCollectorToDetermineLeak(browser, initialTreeOccurrences, initialNodeOccurrences)
|
await searchTree('ab', browser)
|
||||||
// }
|
await clearSearch(browser)
|
||||||
|
await searchTree('temp', browser)
|
||||||
// async function waitForGarbageCollectorToDetermineLeak(
|
await clearSearch(browser)
|
||||||
// browser: any,
|
await sleep(1000, true)
|
||||||
// initialTreeOccurrences: number,
|
await waitForGarbageCollectorToDetermineLeak(browser, initialTreeOccurrences, initialNodeOccurrences)
|
||||||
// initialNodeOccurrences: number
|
}
|
||||||
// ) {
|
async function waitForGarbageCollectorToDetermineLeak(
|
||||||
// let delta = -1
|
browser: any,
|
||||||
// let lastTreeOccurrences = -1
|
initialTreeOccurrences: number,
|
||||||
// let lastNodeOccurrences = -1
|
initialNodeOccurrences: number
|
||||||
// let leak = false
|
) {
|
||||||
// while (delta < 0) {
|
let delta = -1
|
||||||
// if (lastTreeOccurrences !== -1) {
|
let lastTreeOccurrences = -1
|
||||||
// await sleep(10000, true)
|
let lastNodeOccurrences = -1
|
||||||
// }
|
let leak = false
|
||||||
// const heapDump = await getHeapDump(browser)
|
while (delta < 0) {
|
||||||
// const currentTreeOccurrences = await countInstancesOf(heapDump, ClassNameMapping.Tree)
|
if (lastTreeOccurrences !== -1) {
|
||||||
// const currentNodeOccurrences = await countInstancesOf(heapDump, ClassNameMapping.TreeNode)
|
await sleep(10000, true)
|
||||||
|
}
|
||||||
// // Temporary "leaks" are expected due to React Fibers memoization
|
const heapDump = await getHeapDump(browser)
|
||||||
// if (
|
const currentTreeOccurrences = await countInstancesOf(heapDump, ClassNameMapping.Tree)
|
||||||
// Math.abs(initialTreeOccurrences - currentTreeOccurrences) > 1 ||
|
const currentNodeOccurrences = await countInstancesOf(heapDump, ClassNameMapping.TreeNode)
|
||||||
// Math.abs(currentNodeOccurrences - initialNodeOccurrences) > 8
|
// Temporary "leaks" are expected due to React Fibers memoization
|
||||||
// ) {
|
if (
|
||||||
// console.error(
|
Math.abs(initialTreeOccurrences - currentTreeOccurrences) > 1 ||
|
||||||
// 'Possible leak detected',
|
Math.abs(currentNodeOccurrences - initialNodeOccurrences) > 8
|
||||||
// initialTreeOccurrences,
|
) {
|
||||||
// currentTreeOccurrences,
|
console.error(
|
||||||
// initialNodeOccurrences,
|
'Possible leak detected',
|
||||||
// currentNodeOccurrences
|
initialTreeOccurrences,
|
||||||
// )
|
currentTreeOccurrences,
|
||||||
// leak = true
|
initialNodeOccurrences,
|
||||||
// } else {
|
currentNodeOccurrences
|
||||||
// leak = false
|
)
|
||||||
// }
|
leak = true
|
||||||
|
} else {
|
||||||
// const treeDelta = lastTreeOccurrences >= 0 ? currentTreeOccurrences - lastTreeOccurrences : -1
|
leak = false
|
||||||
// const nodeDelta = lastTreeOccurrences >= 0 ? currentNodeOccurrences - lastNodeOccurrences : -1
|
}
|
||||||
// delta = treeDelta + nodeDelta
|
const treeDelta = lastTreeOccurrences >= 0 ? currentTreeOccurrences - lastTreeOccurrences : -1
|
||||||
|
const nodeDelta = lastTreeOccurrences >= 0 ? currentNodeOccurrences - lastNodeOccurrences : -1
|
||||||
// lastTreeOccurrences = currentTreeOccurrences
|
delta = treeDelta + nodeDelta
|
||||||
// lastNodeOccurrences = currentNodeOccurrences
|
lastTreeOccurrences = currentTreeOccurrences
|
||||||
// }
|
lastNodeOccurrences = currentNodeOccurrences
|
||||||
|
}
|
||||||
// if (leak) {
|
if (leak) {
|
||||||
// console.error('leak')
|
console.error('leak')
|
||||||
// process.exit(100)
|
process.exit(100)
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
async function doX(x: number, action: () => Promise<any>) {
|
||||||
// async function doX(x: number, action: () => Promise<any>) {
|
for (let i = 0; i < x; i += 1) {
|
||||||
// for (let i = 0; i < x; i += 1) {
|
await action()
|
||||||
// await action()
|
await sleep(10, true)
|
||||||
// await sleep(10, true)
|
}
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
doStuff()
|
doStuff()
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Browser, Element } from 'webdriverio'
|
import { Page } from 'playwright'
|
||||||
import { clickOn } from '../util'
|
import { clickOn } from '../util'
|
||||||
|
|
||||||
export async function reconnect(browser: Browser<'async'>) {
|
export async function reconnect(browser: Page) {
|
||||||
const disconnectButton = await browser.$('//button/span[contains(text(),"Disconnect")]')
|
const disconnectButton = await browser.locator('//button/span[contains(text(),"Disconnect")]')
|
||||||
await clickOn(disconnectButton, browser)
|
await clickOn(disconnectButton)
|
||||||
const connectButton = await browser.$('//button/span[contains(text(),"Connect")]')
|
const connectButton = await browser.locator('//button/span[contains(text(),"Connect")]')
|
||||||
await clickOn(connectButton, browser)
|
await clickOn(connectButton)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ export async function setTextInInput(name: string, text: string, browser: Page)
|
|||||||
|
|
||||||
export async function moveToCenterOfElement(element: Locator) {
|
export async function moveToCenterOfElement(element: Locator) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const { x, y, width, height } = await element.boundingBox();
|
const { x, y, width, height } = await element.boundingBox()
|
||||||
|
|
||||||
const targetX = x + width / 2
|
const targetX = x + width / 2
|
||||||
const targetY = y + height / 2
|
const targetY = y + height / 2
|
||||||
@@ -71,8 +71,9 @@ export async function moveToCenterOfElement(element: Locator) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function runJavascript(js: string, browser: Page) {
|
export async function runJavascript(js: string, browser: Page) {
|
||||||
console.log(js)
|
// there is probably a safer way to do this.. do not use eval...
|
||||||
await browser.evaluate(_js => eval(_js), js)
|
// tslint:disable-next-line no-eval
|
||||||
|
return browser.evaluate(script => eval(script), js)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function clickOnHistory(browser: Page) {
|
export async function clickOnHistory(browser: Page) {
|
||||||
@@ -80,16 +81,22 @@ export async function clickOnHistory(browser: Page) {
|
|||||||
await clickOn(messageHistory)
|
await clickOn(messageHistory)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function clickOn(element: Locator, clicks = 1, delay = 0, button: 'left' | 'right' | 'middle' = 'left', force = false) {
|
export async function clickOn(
|
||||||
|
element: Locator,
|
||||||
|
clicks = 1,
|
||||||
|
delay = 0,
|
||||||
|
button: 'left' | 'right' | 'middle' = 'left',
|
||||||
|
force = false
|
||||||
|
) {
|
||||||
await moveToCenterOfElement(element)
|
await moveToCenterOfElement(element)
|
||||||
await element.hover()
|
await element.hover()
|
||||||
await element.click({ clickCount: clicks, delay, button, force })
|
await element.click({ delay, button, force, clickCount: clicks })
|
||||||
await sleep(50)
|
await sleep(50)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createFakeMousePointer(browser: Page) {
|
export async function createFakeMousePointer(browser: Page) {
|
||||||
const js = 'window.demo.enableMouse();'
|
const js = 'window.demo.enableMouse();'
|
||||||
|
// @ts-lint-ignore
|
||||||
await runJavascript(js, browser)
|
await runJavascript(js, browser)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
98
yarn.lock
98
yarn.lock
@@ -24,22 +24,22 @@
|
|||||||
picocolors "^1.0.0"
|
picocolors "^1.0.0"
|
||||||
|
|
||||||
"@babel/compat-data@^7.23.5":
|
"@babel/compat-data@^7.23.5":
|
||||||
version "7.24.1"
|
version "7.24.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.1.tgz#31c1f66435f2a9c329bb5716a6d6186c516c3742"
|
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.4.tgz#6f102372e9094f25d908ca0d34fc74c74606059a"
|
||||||
integrity sha512-Pc65opHDliVpRHuKfzI+gSA4zcgr65O4cl64fFJIWEEh8JoHIHh0Oez1Eo8Arz8zq/JhgKodQaxEwUPRtZylVA==
|
integrity sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==
|
||||||
|
|
||||||
"@babel/core@^7.7.5":
|
"@babel/core@^7.7.5":
|
||||||
version "7.24.3"
|
version "7.24.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.3.tgz#568864247ea10fbd4eff04dda1e05f9e2ea985c3"
|
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.4.tgz#1f758428e88e0d8c563874741bc4ffc4f71a4717"
|
||||||
integrity sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ==
|
integrity sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@ampproject/remapping" "^2.2.0"
|
"@ampproject/remapping" "^2.2.0"
|
||||||
"@babel/code-frame" "^7.24.2"
|
"@babel/code-frame" "^7.24.2"
|
||||||
"@babel/generator" "^7.24.1"
|
"@babel/generator" "^7.24.4"
|
||||||
"@babel/helper-compilation-targets" "^7.23.6"
|
"@babel/helper-compilation-targets" "^7.23.6"
|
||||||
"@babel/helper-module-transforms" "^7.23.3"
|
"@babel/helper-module-transforms" "^7.23.3"
|
||||||
"@babel/helpers" "^7.24.1"
|
"@babel/helpers" "^7.24.4"
|
||||||
"@babel/parser" "^7.24.1"
|
"@babel/parser" "^7.24.4"
|
||||||
"@babel/template" "^7.24.0"
|
"@babel/template" "^7.24.0"
|
||||||
"@babel/traverse" "^7.24.1"
|
"@babel/traverse" "^7.24.1"
|
||||||
"@babel/types" "^7.24.0"
|
"@babel/types" "^7.24.0"
|
||||||
@@ -49,10 +49,10 @@
|
|||||||
json5 "^2.2.3"
|
json5 "^2.2.3"
|
||||||
semver "^6.3.1"
|
semver "^6.3.1"
|
||||||
|
|
||||||
"@babel/generator@^7.24.1":
|
"@babel/generator@^7.24.1", "@babel/generator@^7.24.4":
|
||||||
version "7.24.1"
|
version "7.24.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.1.tgz#e67e06f68568a4ebf194d1c6014235344f0476d0"
|
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.4.tgz#1fc55532b88adf952025d5d2d1e71f946cb1c498"
|
||||||
integrity sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A==
|
integrity sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types" "^7.24.0"
|
"@babel/types" "^7.24.0"
|
||||||
"@jridgewell/gen-mapping" "^0.3.5"
|
"@jridgewell/gen-mapping" "^0.3.5"
|
||||||
@@ -137,10 +137,10 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307"
|
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307"
|
||||||
integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==
|
integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==
|
||||||
|
|
||||||
"@babel/helpers@^7.24.1":
|
"@babel/helpers@^7.24.4":
|
||||||
version "7.24.1"
|
version "7.24.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.1.tgz#183e44714b9eba36c3038e442516587b1e0a1a94"
|
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.4.tgz#dc00907fd0d95da74563c142ef4cd21f2cb856b6"
|
||||||
integrity sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg==
|
integrity sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/template" "^7.24.0"
|
"@babel/template" "^7.24.0"
|
||||||
"@babel/traverse" "^7.24.1"
|
"@babel/traverse" "^7.24.1"
|
||||||
@@ -156,15 +156,15 @@
|
|||||||
js-tokens "^4.0.0"
|
js-tokens "^4.0.0"
|
||||||
picocolors "^1.0.0"
|
picocolors "^1.0.0"
|
||||||
|
|
||||||
"@babel/parser@^7.24.0", "@babel/parser@^7.24.1":
|
"@babel/parser@^7.24.0", "@babel/parser@^7.24.1", "@babel/parser@^7.24.4":
|
||||||
version "7.24.1"
|
version "7.24.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.1.tgz#1e416d3627393fab1cb5b0f2f1796a100ae9133a"
|
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.4.tgz#234487a110d89ad5a3ed4a8a566c36b9453e8c88"
|
||||||
integrity sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==
|
integrity sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==
|
||||||
|
|
||||||
"@babel/runtime@^7.17.2":
|
"@babel/runtime@^7.17.2":
|
||||||
version "7.24.1"
|
version "7.24.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.1.tgz#431f9a794d173b53720e69a6464abc6f0e2a5c57"
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.4.tgz#de795accd698007a66ba44add6cc86542aff1edd"
|
||||||
integrity sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ==
|
integrity sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==
|
||||||
dependencies:
|
dependencies:
|
||||||
regenerator-runtime "^0.14.0"
|
regenerator-runtime "^0.14.0"
|
||||||
|
|
||||||
@@ -734,9 +734,9 @@
|
|||||||
integrity sha512-PLwiVvTBg59tGFL/8VpcGvqOu3L4OuveNvPi0EYbWchRdEVP++yRUXJPFl+CApKEq13017/4Nf7aQ5lTtHUNsA==
|
integrity sha512-PLwiVvTBg59tGFL/8VpcGvqOu3L4OuveNvPi0EYbWchRdEVP++yRUXJPFl+CApKEq13017/4Nf7aQ5lTtHUNsA==
|
||||||
|
|
||||||
"@types/node@*", "@types/node@>=13.7.0", "@types/node@^20.9.0":
|
"@types/node@*", "@types/node@>=13.7.0", "@types/node@^20.9.0":
|
||||||
version "20.12.2"
|
version "20.12.4"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.2.tgz#9facdd11102f38b21b4ebedd9d7999663343d72e"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.4.tgz#af5921bd75ccdf3a3d8b3fa75bf3d3359268cd11"
|
||||||
integrity sha512-zQ0NYO87hyN6Xrclcqp7f8ZbXNbRfoGWNcMvHTPQp9UUrwI0mI7XBz+cu7/W6/VClYo2g63B0cjull/srU7LgQ==
|
integrity sha512-E+Fa9z3wSQpzgYQdYmme5X3OTuejnnTx88A6p6vkkJosR3KBz+HpE3kqNm98VE6cfLFcISx7zW7MsJkH6KwbTw==
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types "~5.26.4"
|
undici-types "~5.26.4"
|
||||||
|
|
||||||
@@ -1230,9 +1230,9 @@ camelcase@^6.0.0:
|
|||||||
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
|
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
|
||||||
|
|
||||||
caniuse-lite@^1.0.30001587:
|
caniuse-lite@^1.0.30001587:
|
||||||
version "1.0.30001605"
|
version "1.0.30001606"
|
||||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001605.tgz#ca12d7330dd8bcb784557eb9aa64f0037870d9d6"
|
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001606.tgz#b4d5f67ab0746a3b8b5b6d1f06e39c51beb39a9e"
|
||||||
integrity sha512-nXwGlFWo34uliI9z3n6Qc0wZaf7zaZWA1CPZ169La5mV3I/gem7bst0vr5XQH5TJXZIMfDeZyOrZnSlVzKxxHQ==
|
integrity sha512-LPbwnW4vfpJId225pwjZJOgX1m9sGfbw/RKJvw/t0QhYOOaTXHvkjVGFGPpvwEzufrjvTlsULnVTxdy4/6cqkg==
|
||||||
|
|
||||||
chai@^4.2.0:
|
chai@^4.2.0:
|
||||||
version "4.4.1"
|
version "4.4.1"
|
||||||
@@ -1874,9 +1874,9 @@ electron-publish@24.13.1:
|
|||||||
mime "^2.5.2"
|
mime "^2.5.2"
|
||||||
|
|
||||||
electron-to-chromium@^1.4.668:
|
electron-to-chromium@^1.4.668:
|
||||||
version "1.4.724"
|
version "1.4.728"
|
||||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.724.tgz#e0a86fe4d3d0e05a4d7b032549d79608078f830d"
|
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.728.tgz#ac54d9d1b38752b920ec737a48c83dec2bf45ea1"
|
||||||
integrity sha512-RTRvkmRkGhNBPPpdrgtDKvmOEYTrPlXDfc0J/Nfq5s29tEahAwhiX4mmhNzj6febWMleulxVYPh7QwCSL/EldA==
|
integrity sha512-Ud1v7hJJYIqehlUJGqR6PF1Ek8l80zWwxA6nGxigBsGJ9f9M2fciHyrIiNMerSHSH3p+0/Ia7jIlnDkt41h5cw==
|
||||||
|
|
||||||
electron-updater@^4.6:
|
electron-updater@^4.6:
|
||||||
version "4.6.5"
|
version "4.6.5"
|
||||||
@@ -1892,10 +1892,10 @@ electron-updater@^4.6:
|
|||||||
lodash.isequal "^4.5.0"
|
lodash.isequal "^4.5.0"
|
||||||
semver "^7.3.5"
|
semver "^7.3.5"
|
||||||
|
|
||||||
electron@29.1.1:
|
electron@29.2.0:
|
||||||
version "29.1.1"
|
version "29.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/electron/-/electron-29.1.1.tgz#e9cb11311324e4b43a3e73667cd2b65a30e8fa34"
|
resolved "https://registry.yarnpkg.com/electron/-/electron-29.2.0.tgz#98e9d45dcebda124fb0bd1ff20fc509ec692101c"
|
||||||
integrity sha512-cXN15NgCi7MkzGo5/23ZQbii+0UfhmUiDjACunmzcUofYCjF42XhFbL7JZnwgI0qtBCCeJU8qZNZt9lU91gUFw==
|
integrity sha512-ALKrCN52RG4g9prx4DriXSPnY5WoiyRUCNp7zEVQuoiNOpHTNqMMpRidQAHzntV4hajF1LMWHVoBkwqIs1jHhg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@electron/get" "^2.0.0"
|
"@electron/get" "^2.0.0"
|
||||||
"@types/node" "^20.9.0"
|
"@types/node" "^20.9.0"
|
||||||
@@ -3664,17 +3664,17 @@ pkg-dir@^4.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
find-up "^4.0.0"
|
find-up "^4.0.0"
|
||||||
|
|
||||||
playwright-core@1.42.1:
|
playwright-core@1.43.0:
|
||||||
version "1.42.1"
|
version "1.43.0"
|
||||||
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.42.1.tgz#13c150b93c940a3280ab1d3fbc945bc855c9459e"
|
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.43.0.tgz#d8079acb653abebb0b63062e432479647a4e1271"
|
||||||
integrity sha512-mxz6zclokgrke9p1vtdy/COWBH+eOZgYUVVU34C73M+4j4HLlQJHtfcqiqqxpP0o8HhMkflvfbquLX5dg6wlfA==
|
integrity sha512-iWFjyBUH97+pUFiyTqSLd8cDMMOS0r2ZYz2qEsPjH8/bX++sbIJT35MSwKnp1r/OQBAqC5XO99xFbJ9XClhf4w==
|
||||||
|
|
||||||
playwright@^1.42.1:
|
playwright@^1.43.0:
|
||||||
version "1.42.1"
|
version "1.43.0"
|
||||||
resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.42.1.tgz#79c828b51fe3830211137550542426111dc8239f"
|
resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.43.0.tgz#2c2efd4ee2a25defd8c24c98ccb342bdd9d435f5"
|
||||||
integrity sha512-PgwB03s2DZBcNRoW+1w9E+VkLBxweib6KTXM0M3tkiT4jVxKSi6PmVJ591J+0u10LUrgxB7dLRbiJqO5s2QPMg==
|
integrity sha512-SiOKHbVjTSf6wHuGCbqrEyzlm6qvXcv7mENP+OZon1I07brfZLGdfWV0l/efAzVx7TF3Z45ov1gPEkku9q25YQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
playwright-core "1.42.1"
|
playwright-core "1.43.0"
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents "2.3.2"
|
fsevents "2.3.2"
|
||||||
|
|
||||||
@@ -4633,9 +4633,9 @@ typescript@^4.5.5:
|
|||||||
integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==
|
integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==
|
||||||
|
|
||||||
typescript@^5.3.3:
|
typescript@^5.3.3:
|
||||||
version "5.4.3"
|
version "5.4.4"
|
||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.3.tgz#5c6fedd4c87bee01cd7a528a30145521f8e0feff"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.4.tgz#eb2471e7b0a5f1377523700a21669dce30c2d952"
|
||||||
integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==
|
integrity sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==
|
||||||
|
|
||||||
unbox-primitive@^1.0.2:
|
unbox-primitive@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
|
|||||||
Reference in New Issue
Block a user