Skip to content

Commit

Permalink
Add reload mode e2e test
Browse files Browse the repository at this point in the history
  • Loading branch information
freddyaboulton committed Mar 13, 2024
1 parent b0df3d3 commit e2f3472
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 2 deletions.
3 changes: 2 additions & 1 deletion .config/playwright-setup.js
Expand Up @@ -16,7 +16,8 @@ const test_files = readdirSync(TEST_FILES_PATH)
(f) =>
f.endsWith("spec.ts") &&
!f.endsWith(".skip.spec.ts") &&
!f.endsWith(".component.spec.ts")
!f.endsWith(".component.spec.ts") &&
!f.endsWith(".reload.spec.ts")
)
.map((f) => basename(f, ".spec.ts"));

Expand Down
2 changes: 1 addition & 1 deletion .config/playwright.config.js
Expand Up @@ -23,7 +23,7 @@ const base = defineConfig({
});

const normal = defineConfig(base, {
globalSetup: "./playwright-setup.js"
globalSetup: process.env.CUSTOM_TEST ? undefined : "./playwright-setup.js"
});

normal.projects = undefined; // Explicitly unset this field due to https://github.com/microsoft/playwright/issues/28795
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/test-functional.yml
Expand Up @@ -74,6 +74,10 @@ jobs:
run: |
. venv/bin/activate
pnpm run test:ct
- name: run reload mode test
run: |
. venv/bin/activate
CUSTOM_TEST=1 pnpm --filter @gradio/app test:browser:reload
- name: Run Lite E2E tests
run: |
. venv/bin/activate
Expand Down
81 changes: 81 additions & 0 deletions js/app/test/hello_world.reload.spec.ts
@@ -0,0 +1,81 @@
import { test, expect } from "@playwright/test";
import { spawnSync } from "node:child_process";
import { launch_app_background, kill_process } from "./utils";
import { join } from "path";

test.beforeAll(() => {
const demo = `
import gradio as gr
def greet(name):
return "Hello " + name + "!"
demo = gr.Interface(fn=greet, inputs="text", outputs="text")
if __name__ == "__main__":
demo.launch()
`;
// write contents of demo to a local 'run.py' file
spawnSync(`echo '${demo}' > ${join(process.cwd(), "run.py")}`, {
shell: true,
stdio: "pipe",
env: {
...process.env,
PYTHONUNBUFFERED: "true"
}
});
});

test.afterAll(() => {
spawnSync(`rm ${join(process.cwd(), "run.py")}`, {
shell: true,
stdio: "pipe",
env: {
...process.env,
PYTHONUNBUFFERED: "true"
}
});
});

test("gradio dev mode correctly reloads the page", async ({ page }) => {
test.setTimeout(20 * 1000);

let _process;
try {
const port = 7880;
const { process: _process } = await launch_app_background(
`GRADIO_SERVER_PORT=${port} gradio ${join(process.cwd(), "run.py")}`,
process.cwd()
);
console.log("Connected to port", port);
const demo = `
import gradio as gr
def greet(name):
return "Hello " + name + "!"
dmeo = gr.Interface(fn=greet, inputs=gr.Textbox(label="x"), outputs=gr.Textbox(label="foo"))
if __name__ == "__main__":
demo.launch()
`;
// write contents of demo to a local 'run.py' file
spawnSync(`echo '${demo}' > ${join(process.cwd(), "run.py")}`, {
shell: true,
stdio: "pipe",
env: {
...process.env,
PYTHONUNBUFFERED: "true"
}
});

await page.goto(`http://localhost:${port}`);

await page.getByLabel("x").fill("Maria");
await page.getByRole("button", { name: "Submit" }).click();

await expect(page.getByLabel("foo")).toHaveValue("Hello Maria!");
} finally {
if (_process) kill_process(_process);
}
});
61 changes: 61 additions & 0 deletions js/app/test/utils.ts
@@ -0,0 +1,61 @@
import { spawn } from "node:child_process";

import type { ChildProcess } from "child_process";

export function kill_process(process: ChildProcess) {
process.kill("SIGKILL");
}

type LaunchAppBackgroundReturn = {
port: number;
process: ChildProcess;
};

export const launch_app_background = async (
command: string,
cwd?: string
): Promise<LaunchAppBackgroundReturn> => {
const _process = spawn(command, {
shell: true,
stdio: "pipe",
cwd: cwd || process.cwd(),
env: {
...process.env,
PYTHONUNBUFFERED: "true"
}
});

_process.stdout.setEncoding("utf8");
_process.stderr.setEncoding("utf8");

_process.on("exit", () => kill_process(_process));
_process.on("close", () => kill_process(_process));
_process.on("disconnect", () => kill_process(_process));

let port;

function std_out(data: any) {
const _data: string = data.toString();
console.log(_data);

const portRegExp = /:(\d+)/;
const match = portRegExp.exec(_data);

if (match && match[1] && _data.includes("Running on local URL:")) {
port = parseInt(match[1], 10);
}
}

function std_err(data: any) {
const _data: string = data.toString();
console.log(_data);
}

_process.stdout.on("data", std_out);
_process.stderr.on("data", std_err);

while (!port) {
await new Promise((r) => setTimeout(r, 1000));
}
return { port: port, process: _process };
};

0 comments on commit e2f3472

Please sign in to comment.