1
import { spawn } from "node:child_process";
2
import { join, basename } from "path";
3
import { fileURLToPath } from "url";
4
import { readdirSync, writeFileSync } from "fs";
9
const __dirname = fileURLToPath(new URL(".", import.meta.url));
10
const TEST_APP_PATH = join(__dirname, "./test.py");
11
const TEST_FILES_PATH = join(__dirname, "..", "js", "app", "test");
12
const ROOT = join(__dirname, "..");
14
const test_files = readdirSync(TEST_FILES_PATH)
17
f.endsWith("spec.ts") &&
18
!f.endsWith(".skip.spec.ts") &&
19
!f.endsWith(".component.spec.ts")
21
.map((f) => basename(f, ".spec.ts"));
23
export default async function global_setup() {
24
const verbose = process.env.GRADIO_TEST_VERBOSE;
26
const port = await find_free_port(7860, 8860);
27
process.env.GRADIO_E2E_TEST_PORT = port;
29
process.stdout.write(kl.yellow("\nCreating test gradio app.\n\n"));
31
const test_app = make_app(test_files, port);
32
process.stdout.write(kl.yellow("App created. Starting test server.\n\n"));
34
process.stdout.write(kl.bgBlue(" =========================== \n"));
35
process.stdout.write(kl.bgBlue(" === PYTHON STARTUP LOGS === \n"));
36
process.stdout.write(kl.bgBlue(" =========================== \n\n"));
38
writeFileSync(TEST_APP_PATH, test_app);
40
const app = await spawn_gradio_app(TEST_APP_PATH, port, verbose);
43
kl.green(`\n\nServer started. Running tests on port ${port}.\n`)
47
process.stdout.write(kl.green(`\nTests complete, cleaning up!\n`));
52
const INFO_RE = /^INFO:/;
54
function spawn_gradio_app(app, port, verbose) {
55
const PORT_RE = new RegExp(`:${port}`);
57
return new Promise((res, rej) => {
58
const _process = spawn(`python`, [app], {
64
GRADIO_SERVER_PORT: `7879`,
65
PYTHONUNBUFFERED: "true",
66
GRADIO_ANALYTICS_ENABLED: "False"
69
_process.stdout.setEncoding("utf8");
71
function std_out(data) {
72
const _data = data.toString();
73
const is_info = INFO_RE.test(_data);
76
process.stdout.write(kl.yellow(_data));
80
process.stdout.write(`${_data}\n`);
83
if (PORT_RE.test(_data)) {
84
process.stdout.write(kl.bgBlue("\n =========== END =========== "));
89
_process.stdout.off("data", std_out);
90
_process.stderr.off("data", std_out);
95
_process.stdout.on("data", std_out);
96
_process.stderr.on("data", std_out);
97
_process.on("exit", () => kill_process(_process));
98
_process.on("close", () => kill_process(_process));
99
_process.on("disconnect", () => kill_process(_process));
103
function kill_process(process) {
104
process.kill("SIGKILL");
107
function make_app(demos, port) {
108
return `import gradio as gr
110
from fastapi import FastAPI
112
${demos.map((d) => `from demo.${d}.run import demo as ${d}`).join("\n")}
116
.map((d) => `app = gr.mount_gradio_app(app, ${d}, path="/${d}")`)
119
config = uvicorn.Config(app, port=${port}, log_level="info")
120
server = uvicorn.Server(config=config)
124
export async function find_free_port(start_port, end_port) {
125
for (let port = start_port; port < end_port; port++) {
126
if (await is_free_port(port)) {
132
`Could not find free ports: there were not enough ports available.`
136
export function is_free_port(port) {
137
return new Promise((accept, reject) => {
138
const sock = net.createConnection(port, "127.0.0.1");
139
sock.once("connect", () => {
143
sock.once("error", (e) => {
145
if (e.code === "ECONNREFUSED") {