From 613d0d7178723f7ee4d504194ea629a65e474c6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Dalfors?= Date: Sat, 6 Apr 2024 21:20:40 +0200 Subject: [PATCH] fix test script and video capture --- app/package.json | 2 +- docker/Dockerfile | 2 +- package.json | 8 +- scripts/uiTests.sh | 42 +++--- src/spec/demoVideo.ts | 29 ++--- src/spec/leakTest.ts | 221 +++++++++++++++----------------- src/spec/scenarios/reconnect.ts | 12 +- src/spec/util/index.ts | 19 ++- yarn.lock | 98 +++++++------- 9 files changed, 218 insertions(+), 215 deletions(-) diff --git a/app/package.json b/app/package.json index a9b0794..142e4d3 100644 --- a/app/package.json +++ b/app/package.json @@ -90,4 +90,4 @@ "peerDependencies": { "electron": "^29" } -} +} \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile index 0842f87..a4a916e 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -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 diff --git a/package.json b/package.json index 1f6322c..aeabc2a 100644 --- a/package.json +++ b/package.json @@ -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,13 +90,13 @@ "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.42.1", + "playwright": "^1.43.0", "prettier": "^3.2.5", "redux-thunk": "^2.3.0", "source-map-support": "^0.5.9", @@ -122,4 +124,4 @@ "uuid": "^8.3.2", "yarn-run-all": "^3.1.1" } -} +} \ No newline at end of file diff --git a/scripts/uiTests.sh b/scripts/uiTests.sh index 64b3fcb..eb3fd76 100755 --- a/scripts/uiTests.sh +++ b/scripts/uiTests.sh @@ -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 -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 -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 diff --git a/src/spec/demoVideo.ts b/src/spec/demoVideo.ts index 08827dc..ef76c98 100644 --- a/src/spec/demoVideo.ts +++ b/src/spec/demoVideo.ts @@ -2,7 +2,7 @@ import * as fs from 'fs' import * as os from 'os' 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 { clearOldTopics } from './scenarios/clearOldTopics' @@ -13,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' @@ -21,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) @@ -36,16 +45,10 @@ async function doStuff() { // Launch Electron app. const electronApp: ElectronApplication = await electron.launch({ - args: [`${__dirname}/../../..`], - // recordVideo: { - // dir: path.join(__dirname, '..', 'playwright-videos'), - // size: { - // width: 1280, - // height: 720, - // }, - // }, + 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. @@ -138,14 +141,10 @@ async function doStuff() { await sleep(3000) }) - // Exit app. - await electronApp.close() - console.log('Electron exited') - stopMqtt() console.log('Stopped mqtt') - fs.writeFileSync('scenes.json', JSON.stringify(scenes.scenes, undefined, ' ')) + cleanUp(scenes, electronApp) } doStuff() diff --git a/src/spec/leakTest.ts b/src/spec/leakTest.ts index 058f5b6..b44bbcb 100644 --- a/src/spec/leakTest.ts +++ b/src/spec/leakTest.ts @@ -1,131 +1,114 @@ -// import * as os from 'os' -// import mockMqtt, { stopUpdates as stopMqttUpdates } from './mock-mqtt' -// 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' +import * as os from 'os' +import { ElectronApplication, _electron as electron } from 'playwright' -// process.on('unhandledRejection', (error: Error | any) => { -// console.error('unhandledRejection', error.message, error.stack) -// process.exit(1) -// }) +import mockMqtt, { stopUpdates as stopMqttUpdates } from './mock-mqtt' +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' -// const runningUiTestOnCi = os.platform() === 'darwin' ? [] : ['--runningUiTestOnCi'] +process.on('unhandledRejection', (error: Error | any) => { + console.error('unhandledRejection', error.message, error.stack) + process.exit(1) +}) -// 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'], -// }, -// }, -// } +const runningUiTestOnCi = os.platform() === 'darwin' ? [] : ['--runningUiTestOnCi'] async function doStuff() { -// console.log('Waiting for MQTT Broker on port 1880 (no auth)') -// await mockMqtt() -// console.log('start webdriver') + console.log('Waiting for MQTT Broker on port 1880 (no auth)') + await mockMqtt() -// const browser = await webdriverio.remote(options) -// setFast() -// await createFakeMousePointer(browser) + console.log('Starting playwright/electron') -// // Wait for Username input to be visible -// await browser.$('//label[contains(text(), "Username")]/..//input') -// await connectTo('127.0.0.1', browser) -// stopMqttUpdates() -// await sleep(1000, true) + // Launch Electron app. + const electronApp: ElectronApplication = await electron.launch({ + args: [`${__dirname}/../../..`, ...runningUiTestOnCi], + }) -// const heapDump = await getHeapDump(browser) -// const initialTreeOccurrences = await countInstancesOf(heapDump, ClassNameMapping.Tree) -// const initialNodeOccurrences = await countInstancesOf(heapDump, ClassNameMapping.TreeNode) -// console.log(initialTreeOccurrences, initialNodeOccurrences) + 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) -// 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, -// initialNodeOccurrences: number -// ) { -// let delta = -1 -// let lastTreeOccurrences = -1 -// let lastNodeOccurrences = -1 -// let leak = false -// while (delta < 0) { -// if (lastTreeOccurrences !== -1) { -// await sleep(10000, true) -// } -// 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 || -// Math.abs(currentNodeOccurrences - initialNodeOccurrences) > 8 -// ) { -// console.error( -// 'Possible leak detected', -// initialTreeOccurrences, -// currentTreeOccurrences, -// initialNodeOccurrences, -// currentNodeOccurrences -// ) -// leak = true -// } 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) { -// for (let i = 0; i < x; i += 1) { -// await action() -// await sleep(10, true) -// } + setFast() + await createFakeMousePointer(browser) + // Wait for Username input to be visible + 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, + initialNodeOccurrences: number +) { + let delta = -1 + let lastTreeOccurrences = -1 + let lastNodeOccurrences = -1 + let leak = false + while (delta < 0) { + if (lastTreeOccurrences !== -1) { + await sleep(10000, true) + } + 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 || + Math.abs(currentNodeOccurrences - initialNodeOccurrences) > 8 + ) { + console.error( + 'Possible leak detected', + initialTreeOccurrences, + currentTreeOccurrences, + initialNodeOccurrences, + currentNodeOccurrences + ) + leak = true + } 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) { + for (let i = 0; i < x; i += 1) { + await action() + await sleep(10, true) + } } doStuff() diff --git a/src/spec/scenarios/reconnect.ts b/src/spec/scenarios/reconnect.ts index 3a43948..3b2678f 100644 --- a/src/spec/scenarios/reconnect.ts +++ b/src/spec/scenarios/reconnect.ts @@ -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) } diff --git a/src/spec/util/index.ts b/src/spec/util/index.ts index afae82b..7e6805c 100644 --- a/src/spec/util/index.ts +++ b/src/spec/util/index.ts @@ -57,7 +57,7 @@ export async function setTextInInput(name: string, text: string, browser: Page) export async function moveToCenterOfElement(element: Locator) { // @ts-ignore - const { x, y, width, height } = await element.boundingBox(); + const { x, y, width, height } = await element.boundingBox() const targetX = x + width / 2 const targetY = y + height / 2 @@ -71,8 +71,9 @@ export async function moveToCenterOfElement(element: Locator) { } export async function runJavascript(js: string, browser: Page) { - console.log(js) - await browser.evaluate(_js => eval(_js), js) + // 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 clickOnHistory(browser: Page) { @@ -80,16 +81,22 @@ export async function clickOnHistory(browser: Page) { 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 element.hover() - await element.click({ clickCount: clicks, delay, button, force }) + await element.click({ delay, button, force, clickCount: clicks }) await sleep(50) } export async function createFakeMousePointer(browser: Page) { const js = 'window.demo.enableMouse();' - + // @ts-lint-ignore await runJavascript(js, browser) } diff --git a/yarn.lock b/yarn.lock index 94aa1f9..c1356d2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -24,22 +24,22 @@ picocolors "^1.0.0" "@babel/compat-data@^7.23.5": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.1.tgz#31c1f66435f2a9c329bb5716a6d6186c516c3742" - integrity sha512-Pc65opHDliVpRHuKfzI+gSA4zcgr65O4cl64fFJIWEEh8JoHIHh0Oez1Eo8Arz8zq/JhgKodQaxEwUPRtZylVA== + version "7.24.4" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.4.tgz#6f102372e9094f25d908ca0d34fc74c74606059a" + integrity sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ== "@babel/core@^7.7.5": - version "7.24.3" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.3.tgz#568864247ea10fbd4eff04dda1e05f9e2ea985c3" - integrity sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ== + version "7.24.4" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.4.tgz#1f758428e88e0d8c563874741bc4ffc4f71a4717" + integrity sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg== dependencies: "@ampproject/remapping" "^2.2.0" "@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-module-transforms" "^7.23.3" - "@babel/helpers" "^7.24.1" - "@babel/parser" "^7.24.1" + "@babel/helpers" "^7.24.4" + "@babel/parser" "^7.24.4" "@babel/template" "^7.24.0" "@babel/traverse" "^7.24.1" "@babel/types" "^7.24.0" @@ -49,10 +49,10 @@ json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.1.tgz#e67e06f68568a4ebf194d1c6014235344f0476d0" - integrity sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A== +"@babel/generator@^7.24.1", "@babel/generator@^7.24.4": + version "7.24.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.4.tgz#1fc55532b88adf952025d5d2d1e71f946cb1c498" + integrity sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw== dependencies: "@babel/types" "^7.24.0" "@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" integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== -"@babel/helpers@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.1.tgz#183e44714b9eba36c3038e442516587b1e0a1a94" - integrity sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg== +"@babel/helpers@^7.24.4": + version "7.24.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.4.tgz#dc00907fd0d95da74563c142ef4cd21f2cb856b6" + integrity sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw== dependencies: "@babel/template" "^7.24.0" "@babel/traverse" "^7.24.1" @@ -156,15 +156,15 @@ js-tokens "^4.0.0" picocolors "^1.0.0" -"@babel/parser@^7.24.0", "@babel/parser@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.1.tgz#1e416d3627393fab1cb5b0f2f1796a100ae9133a" - integrity sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg== +"@babel/parser@^7.24.0", "@babel/parser@^7.24.1", "@babel/parser@^7.24.4": + version "7.24.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.4.tgz#234487a110d89ad5a3ed4a8a566c36b9453e8c88" + integrity sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg== "@babel/runtime@^7.17.2": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.1.tgz#431f9a794d173b53720e69a6464abc6f0e2a5c57" - integrity sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ== + version "7.24.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.4.tgz#de795accd698007a66ba44add6cc86542aff1edd" + integrity sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA== dependencies: regenerator-runtime "^0.14.0" @@ -734,9 +734,9 @@ integrity sha512-PLwiVvTBg59tGFL/8VpcGvqOu3L4OuveNvPi0EYbWchRdEVP++yRUXJPFl+CApKEq13017/4Nf7aQ5lTtHUNsA== "@types/node@*", "@types/node@>=13.7.0", "@types/node@^20.9.0": - version "20.12.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.2.tgz#9facdd11102f38b21b4ebedd9d7999663343d72e" - integrity sha512-zQ0NYO87hyN6Xrclcqp7f8ZbXNbRfoGWNcMvHTPQp9UUrwI0mI7XBz+cu7/W6/VClYo2g63B0cjull/srU7LgQ== + version "20.12.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.4.tgz#af5921bd75ccdf3a3d8b3fa75bf3d3359268cd11" + integrity sha512-E+Fa9z3wSQpzgYQdYmme5X3OTuejnnTx88A6p6vkkJosR3KBz+HpE3kqNm98VE6cfLFcISx7zW7MsJkH6KwbTw== dependencies: undici-types "~5.26.4" @@ -1230,9 +1230,9 @@ camelcase@^6.0.0: integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30001587: - version "1.0.30001605" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001605.tgz#ca12d7330dd8bcb784557eb9aa64f0037870d9d6" - integrity sha512-nXwGlFWo34uliI9z3n6Qc0wZaf7zaZWA1CPZ169La5mV3I/gem7bst0vr5XQH5TJXZIMfDeZyOrZnSlVzKxxHQ== + version "1.0.30001606" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001606.tgz#b4d5f67ab0746a3b8b5b6d1f06e39c51beb39a9e" + integrity sha512-LPbwnW4vfpJId225pwjZJOgX1m9sGfbw/RKJvw/t0QhYOOaTXHvkjVGFGPpvwEzufrjvTlsULnVTxdy4/6cqkg== chai@^4.2.0: version "4.4.1" @@ -1874,9 +1874,9 @@ electron-publish@24.13.1: mime "^2.5.2" electron-to-chromium@^1.4.668: - version "1.4.724" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.724.tgz#e0a86fe4d3d0e05a4d7b032549d79608078f830d" - integrity sha512-RTRvkmRkGhNBPPpdrgtDKvmOEYTrPlXDfc0J/Nfq5s29tEahAwhiX4mmhNzj6febWMleulxVYPh7QwCSL/EldA== + version "1.4.728" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.728.tgz#ac54d9d1b38752b920ec737a48c83dec2bf45ea1" + integrity sha512-Ud1v7hJJYIqehlUJGqR6PF1Ek8l80zWwxA6nGxigBsGJ9f9M2fciHyrIiNMerSHSH3p+0/Ia7jIlnDkt41h5cw== electron-updater@^4.6: version "4.6.5" @@ -1892,10 +1892,10 @@ electron-updater@^4.6: lodash.isequal "^4.5.0" semver "^7.3.5" -electron@29.1.1: - version "29.1.1" - resolved "https://registry.yarnpkg.com/electron/-/electron-29.1.1.tgz#e9cb11311324e4b43a3e73667cd2b65a30e8fa34" - integrity sha512-cXN15NgCi7MkzGo5/23ZQbii+0UfhmUiDjACunmzcUofYCjF42XhFbL7JZnwgI0qtBCCeJU8qZNZt9lU91gUFw== +electron@29.2.0: + version "29.2.0" + resolved "https://registry.yarnpkg.com/electron/-/electron-29.2.0.tgz#98e9d45dcebda124fb0bd1ff20fc509ec692101c" + integrity sha512-ALKrCN52RG4g9prx4DriXSPnY5WoiyRUCNp7zEVQuoiNOpHTNqMMpRidQAHzntV4hajF1LMWHVoBkwqIs1jHhg== dependencies: "@electron/get" "^2.0.0" "@types/node" "^20.9.0" @@ -3664,17 +3664,17 @@ pkg-dir@^4.1.0: dependencies: find-up "^4.0.0" -playwright-core@1.42.1: - version "1.42.1" - resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.42.1.tgz#13c150b93c940a3280ab1d3fbc945bc855c9459e" - integrity sha512-mxz6zclokgrke9p1vtdy/COWBH+eOZgYUVVU34C73M+4j4HLlQJHtfcqiqqxpP0o8HhMkflvfbquLX5dg6wlfA== +playwright-core@1.43.0: + version "1.43.0" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.43.0.tgz#d8079acb653abebb0b63062e432479647a4e1271" + integrity sha512-iWFjyBUH97+pUFiyTqSLd8cDMMOS0r2ZYz2qEsPjH8/bX++sbIJT35MSwKnp1r/OQBAqC5XO99xFbJ9XClhf4w== -playwright@^1.42.1: - version "1.42.1" - resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.42.1.tgz#79c828b51fe3830211137550542426111dc8239f" - integrity sha512-PgwB03s2DZBcNRoW+1w9E+VkLBxweib6KTXM0M3tkiT4jVxKSi6PmVJ591J+0u10LUrgxB7dLRbiJqO5s2QPMg== +playwright@^1.43.0: + version "1.43.0" + resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.43.0.tgz#2c2efd4ee2a25defd8c24c98ccb342bdd9d435f5" + integrity sha512-SiOKHbVjTSf6wHuGCbqrEyzlm6qvXcv7mENP+OZon1I07brfZLGdfWV0l/efAzVx7TF3Z45ov1gPEkku9q25YQ== dependencies: - playwright-core "1.42.1" + playwright-core "1.43.0" optionalDependencies: fsevents "2.3.2" @@ -4633,9 +4633,9 @@ typescript@^4.5.5: integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== typescript@^5.3.3: - version "5.4.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.3.tgz#5c6fedd4c87bee01cd7a528a30145521f8e0feff" - integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg== + version "5.4.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.4.tgz#eb2471e7b0a5f1377523700a21669dce30c2d952" + integrity sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw== unbox-primitive@^1.0.2: version "1.0.2"