Files
ueblueprint/tests/fixtures/BlueprintFixture.js
barsdeveloper e405a7245d WIP
2024-12-11 23:23:23 +02:00

160 lines
4.9 KiB
JavaScript
Executable File

import http from "http"
import httpServer from "http-server"
export default class BlueprintFixture {
#port = 8181
/** @type {Locator<Blueprint>} */
#blueprintLocator
get blueprintLocator() {
return this.#blueprintLocator
}
/** @type {Locator<NodeElement>} */
#node
get node() {
return this.#node
}
/** @type {ReturnType<httpServer.createServer>} */
static server
/** @param {import("playwright/test").Page} page */
constructor(page) {
this.page = page
this.#blueprintLocator = page.locator("ueb-blueprint")
this.#node = this.#blueprintLocator.locator("ueb-node").first()
if (process.env.UEBLUEPRINT_TEST_SERVER_PORT) {
this.#port = Number(process.env.UEBLUEPRINT_TEST_SERVER_PORT)
}
}
/**
* @param {Locator<HTMLElement>} draggable
* @param {Coordinates} offset
*/
async move(draggable, offset) {
const { x: x1, y: y1 } = await draggable.boundingBox()
await draggable.dragTo(this.blueprintLocator, {
sourcePosition: {
x: 1,
y: 1,
},
targetPosition: {
x: x1 + offset[0] + 1,
y: y1 + offset[1] + 1,
}
})
const { x: x2, y: y2 } = await draggable.boundingBox()
return {
before: [x1, y1],
after: [x2, y2],
}
}
async checkServerReady(url) {
return new Promise((resolve, reject) => {
const request = http.get(url, res => {
if (res.statusCode === 200) {
resolve()
} else {
reject(new Error(`Server not ready, status code: ${res.statusCode}`))
}
})
request.on("error", error => reject(error))
request.end()
})
}
createServer() {
return new Promise((resolve, reject) => {
const webserver = httpServer.createServer({
root: "./",
cors: true,
logFn: (req, res, error) => error && console.error(`Http server: ${error}`)
})
webserver.server.addListener("error", error => {
if (error.code === "EADDRINUSE") {
console.log(`Port ${this.#port} is already in use, assuming server is already running`)
resolve(webserver)
} else {
resolve(null)
}
})
webserver.listen(this.#port, "127.0.0.1", async () => {
console.log(`Server started on http://127.0.0.1:${this.#port}`)
const url = `http://127.0.0.1:${this.#port}/empty.html`
try {
await this.checkServerReady(url)
BlueprintFixture.server = webserver
resolve(webserver)
} catch (error) {
console.error("Server failed readiness check:", error)
reject(error)
}
})
process.addListener("SIGTERM", () => {
console.log("SIGTERM signal received: closing HTTP server")
webserver.close()
})
})
}
async setup() {
const url = `http://127.0.0.1:${this.#port}/empty.html`
try {
await this.page.goto(url)
} catch (e) {
if (e.message.includes("ERR_CONNECTION_REFUSED")) {
await this.createServer()
await this.page.goto(url)
} else {
throw e
}
}
this.#blueprintLocator = this.page.locator("ueb-blueprint")
// To cause the blueprint to get the focus and start listining for input, see MouseClick::#mouseDownHandler
await this.#blueprintLocator.click({ position: { x: 100, y: 300 } })
}
async removeNodes() {
return await this.#blueprintLocator.evaluate(blueprint =>
blueprint.removeGraphElement(...blueprint.getNodes())
)
}
/** @param {String} text */
async paste(text) {
return await this.#blueprintLocator.evaluate(
(blueprint, text) => {
const event = new ClipboardEvent("paste", {
bubbles: true,
cancelable: true,
clipboardData: new DataTransfer(),
})
event.clipboardData.setData("text", text)
blueprint.dispatchEvent(event)
},
text
)
}
async cleanup() {
}
blur() {
return this.page.evaluate(() => /** @type {HTMLElement} */(document.activeElement).blur())
}
getSerializedNodes() {
return this.blueprintLocator.evaluate(blueprint => {
blueprint.selectAll()
return blueprint.getSerializedText()
})
}
}