From e811ce765ce8d22df18609d9cbfa1be842952653 Mon Sep 17 00:00:00 2001 From: Oleg Korshul Date: Mon, 12 Jun 2023 22:31:18 +0300 Subject: [PATCH] Add tests for editors --- tests/puppeteer/config_chrome.json | 4 + tests/puppeteer/config_firefox.json | 4 + tests/puppeteer/install.py | 9 ++ tests/puppeteer/run.py | 64 +++++++++++ tests/puppeteer/tester.js | 171 ++++++++++++++++++++++++++++ tests/puppeteer/tests/bold.js | 27 +++++ 6 files changed, 279 insertions(+) create mode 100644 tests/puppeteer/config_chrome.json create mode 100644 tests/puppeteer/config_firefox.json create mode 100644 tests/puppeteer/install.py create mode 100644 tests/puppeteer/run.py create mode 100644 tests/puppeteer/tester.js create mode 100644 tests/puppeteer/tests/bold.js diff --git a/tests/puppeteer/config_chrome.json b/tests/puppeteer/config_chrome.json new file mode 100644 index 0000000..3064650 --- /dev/null +++ b/tests/puppeteer/config_chrome.json @@ -0,0 +1,4 @@ +{ + "browser" : "chrome", + "browserUrl" : "C:/Program Files/Google/Chrome/Application/chrome.exe" +} \ No newline at end of file diff --git a/tests/puppeteer/config_firefox.json b/tests/puppeteer/config_firefox.json new file mode 100644 index 0000000..1293bee --- /dev/null +++ b/tests/puppeteer/config_firefox.json @@ -0,0 +1,4 @@ +{ + "browser" : "firefox", + "browserUrl" : "C:/Program Files/Mozilla Firefox/firefox.exe" +} \ No newline at end of file diff --git a/tests/puppeteer/install.py b/tests/puppeteer/install.py new file mode 100644 index 0000000..cb73e86 --- /dev/null +++ b/tests/puppeteer/install.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python + +import sys +sys.path.append('../../scripts') +import base +import os + +os.environ["PUPPETEER_SKIP_CHROMIUM_DOWNLOAD"] = "true" +base.cmd("npm", ["i", "puppeteer"]) diff --git a/tests/puppeteer/run.py b/tests/puppeteer/run.py new file mode 100644 index 0000000..f13b5a4 --- /dev/null +++ b/tests/puppeteer/run.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python + +import sys +sys.path.append('../../scripts') +import base +import os +import glob +import json + +def get_tests_in_dir(directory): + files = [] + for file in glob.glob(directory + "/*.js"): + if base.is_file(file): + files.append(file) + elif is_dir(file): + files += get_tests_in_dir(file) + return files + +params = sys.argv[1:] +if (0 == len(params)): + print("use: run.py path_to_config [path_to_test]") + exit(0) + +config_path = params[0] +test_file = "./tests" + +if (1 < len(params)): + test_file = params[1] + +tests_array = [test_file] +if base.is_dir(test_file): + tests_array = get_tests_in_dir(test_file) + +config_content = "{}" +with open(config_path, "r") as config_path_loader: + config_content = config_path_loader.read() + +print(config_content) + +config = json.loads(config_content) +os.environ["PUPPETEER_SKIP_CHROMIUM_DOWNLOAD"] = "true" +if "browser" in config: + print("browser: " + config["browser"]) + os.environ["PUPPETEER_PRODUCT"] = config["browser"] + +if "browserUrl" in config: + print("browserUrl: " + config["browserUrl"]) + os.environ["PUPPETEER_EXECUTABLE_PATH"] = config["browserUrl"] + +if not base.is_dir("./work_directory"): + base.create_dir("./work_directory") + base.create_dir("./work_directory/cache") + base.create_dir("./work_directory/downloads") + +for test in tests_array: + print("run test: " + test) + run_file = test + ".runned.js" + base.copy_file("./tester.js", run_file) + test_content = base.readFile(test) + test_content = test_content.replace("await Tester.", "Tester.") + test_content = test_content.replace("Tester.", "await Tester.") + base.replaceInFile(run_file, "\"%%CODE%%\"", test_content) + base.cmd("node", [run_file]) + base.delete_file(run_file) diff --git a/tests/puppeteer/tester.js b/tests/puppeteer/tester.js new file mode 100644 index 0000000..997e58a --- /dev/null +++ b/tests/puppeteer/tester.js @@ -0,0 +1,171 @@ +const puppeteer = require('puppeteer') +const pathfs = require('path') +const fs = require('fs'); + +function TesterImpl() +{ + this.browser = null; + this.page = null; + this.width = 1500; + this.height = 800; + this.pixelRatio = 1; + + this.cacheDir = pathfs.resolve("./work_directory/cache"); + this.downloadsDir = pathfs.resolve("./work_directory/downloads"); + this.downloadCounter = 0; + + this.load = async function(url) + { + const head = { x: 100, y: 200 }; + this.browser = await puppeteer.launch({ + headless: false, + product: process.env["PUPPETEER_PRODUCT"], + args: [ + "--disable-infobars", + `--window-size=${this.width+head.x},${this.height+head.y}`, + "--disk-cache-dir=" + this.cacheDir + ], + defaultViewport : {width: this.width, height: this.height, deviceScaleFactor : this.pixelRatio } + }); + + this.page = await this.browser.newPage(); + await this.page.setViewport({ width: this.width, height: this.height }); + let waitObject = (process.env["PUPPETEER_PRODUCT"] === "firefox") ? { waitUntil: "networkidle0", timeout: 15000 } : {}; + await this.page.goto(url + "&autotest=enabled", waitObject); + console.log("[tester] pageLoaded"); + return this.page; + }; + + this.close = async function(nosleep) + { + if (true !== nosleep) + await this.waitAutosave(); + await this.browser.close(); + }; + + this.sleep = async function(ms) + { + return await new Promise(resolve => setTimeout(resolve, ms)); + }; + + this.waitEditor = async function() + { + // TODO: wait first onEndRecalculate + await this.sleep(5000); + console.log("[tester] editorReady"); + }; + + this.waitAutosave = async function() + { + await this.sleep(5000); + }; + + this.evaluateInMainFrame = async function(code) + { + return await this.page.evaluate(code); + }; + this.evaluateInEditorFrame = async function(code) + { + const frame = await this.page.frames().find(frame => frame.name() === 'frameEditor'); + if (!frame) + return; + return await frame.evaluate(code); + }; + + this.click = async function(id) + { + let res = await this.evaluateInEditorFrame("document.getElementById(\"" + id + "\").click(); \"[tester] clicked: " + id + "\""); + //console.log(res); + await this.sleep(200); + return res; + }; + + this.mouseClick = async function(x, y, options) + { + let res = await this.page.mouse.click(x, y, options); + await this.sleep(200); + return res; + }; + + this.eval = async function(code) + { + let res = await this.evaluateInEditorFrame(code); + await this.sleep(200); + return res; + }; + + this.keyDown = async function(key) + { + // https://pptr.dev/api/puppeteer.keyinput + let res = await this.page.keyboard.down(key); + await this.sleep(200); + return res; + }; + + this.keyUp = async function(key) + { + // https://pptr.dev/api/puppeteer.keyinput + let res = await this.page.keyboard.up(key); + await this.sleep(200); + return res; + }; + + this.keyClick = async function(key) + { + // https://pptr.dev/api/puppeteer.keyinput + let res = await this.page.keyboard.down(key); + res = await this.page.keyboard.up(key); + await this.sleep(200); + return res; + }; + + this.keyPress = async function(key) + { + // https://pptr.dev/api/puppeteer.keyinput + let res = await this.page.keyboard.press(key); + await this.sleep(200); + return res; + }; + + this.input = async function(text) + { + let res = await this.page.keyboard.type(text); + await this.sleep(200); + return res; + }; + + this.downloadFile = async function(format, path) + { + const tmpDir = pathfs.resolve(this.downloadsDir, "./tmp" + this.downloadCounter++); + fs.mkdirSync(tmpDir); + + // emulate download + const client = await this.page.target().createCDPSession(); + await client.send("Page.setDownloadBehavior", { + behavior: "allow", + downloadPath: tmpDir + }); + + await this.evaluateInEditorFrame("document.querySelectorAll('[data-layout-name=\"toolbar-file\"]')[0].click();"); + await this.sleep(200); + await this.evaluateInEditorFrame("document.getElementsByClassName(\"svg-format-" + format + "\")[0].click();"); + await this.sleep(200); + await this.evaluateInEditorFrame("document.getElementById(\"fm-btn-return\").click();"); + + await this.sleep(2000); + + const files = fs.readdirSync(tmpDir); + fs.copyFileSync(pathfs.resolve(tmpDir, "./" + files[0]), pathfs.resolve(path)); + fs.rmSync(tmpDir, { recursive: true, force: true }); + }; +} + +const Tester = new TesterImpl; + +try { + (async () => { + "%%CODE%%" + })(); +} catch (err) { + console.error(err); +} diff --git a/tests/puppeteer/tests/bold.js b/tests/puppeteer/tests/bold.js new file mode 100644 index 0000000..94b8c68 --- /dev/null +++ b/tests/puppeteer/tests/bold.js @@ -0,0 +1,27 @@ +Tester.load("path_to_file"); +Tester.waitEditor(); + +// down Enter +Tester.keyClick("Enter"); + +// type text +Tester.input("Hello World!"); + +Tester.keyPress("ArrowLeft"); +Tester.keyDown("Shift"); +for (let i = 0; i < 5; i++) + Tester.keyPress("ArrowLeft"); +Tester.keyUp("Shift"); + +// bold +Tester.click("id-toolbar-btn-bold"); +// italic +Tester.mouseClick(115, 105); + +// if needed +Tester.waitAutosave(); + +Tester.downloadFile("docx", "./work_directory/new.docx") +Tester.downloadFile("odt", "./work_directory/new.odt") + +Tester.close(true);