Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix-tests #7345

Merged
merged 39 commits into from Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
9ff2a7d
fix-tests
pngwn Feb 7, 2024
c775c0c
[tmp] Comment-out
whitphx Feb 12, 2024
1220e3a
Fix the URL constructor calls in `resolve_wasm_src()`, `should_proxy_…
whitphx Feb 19, 2024
81de3d5
Remove a circular dependency between lite/index.ts and lite/custom-el…
whitphx Feb 19, 2024
94f2bb5
Fix js/app/test/image_component_events.spec.ts
whitphx Feb 20, 2024
98dccc5
Set the `testIgnore` in `.config/playwright.config.js`
whitphx Feb 20, 2024
d047a9e
Fix the Lite dev mode only to create an app and expose the controller…
whitphx Feb 20, 2024
528e763
add changeset
gradio-pr-bot Feb 20, 2024
540f266
Set the mocked ruff version as 0.2.2
whitphx Feb 20, 2024
742d1e1
Extend timeout
whitphx Feb 20, 2024
640ec99
Fix to use the built lite files instead of the dev server
whitphx Feb 21, 2024
7099144
add changeset
gradio-pr-bot Feb 21, 2024
3580d79
comment out failed tests
whitphx Feb 21, 2024
5c243e9
Merge branch 'main' into run-lite-tests
whitphx Feb 21, 2024
6588d3c
Revert "comment out failed tests"
whitphx Feb 21, 2024
3767cdc
Fix the Gellery component to work in Wasm
whitphx Feb 21, 2024
f95a954
Fix js/app/test/file_explorer_component_events.spec.ts to run on Wasm
whitphx Feb 21, 2024
b99ddf9
Ignore queue_full_e2e_test.spec.ts
whitphx Feb 21, 2024
f7ddd6d
Revert "[tmp] Comment-out"
whitphx Feb 21, 2024
4425a09
Revert "Extend timeout"
whitphx Feb 21, 2024
c6855c9
Remove a commented out line
whitphx Feb 21, 2024
921348d
Refactor file_explorer_component_events.spec.ts
whitphx Feb 21, 2024
de2dbe3
Revert "fix-tests", restoring the original test-functional.yml content
whitphx Feb 21, 2024
c7ac95b
Set CI step names
whitphx Feb 21, 2024
32154f3
[tmp] Revert "Revert "fix-tests", restoring the original test-functio…
whitphx Feb 21, 2024
204075e
Revert "[tmp] Revert "Revert "fix-tests", restoring the original test…
whitphx Feb 21, 2024
95b2ee6
[tmp] Revert "Revert "[tmp] Revert "Revert "fix-tests", restoring the…
whitphx Feb 23, 2024
89b67f2
Fix vite.config.js removing unnecessary code
whitphx Feb 23, 2024
1e8ba06
Revert "Set the `testIgnore` in `.config/playwright.config.js`"
whitphx Feb 23, 2024
46c2763
Add gallery_component_events.spec.ts
whitphx Feb 23, 2024
c2d480c
Revert js/app/test
whitphx Feb 23, 2024
e655d74
tweak
pngwn Feb 23, 2024
f11890a
tweak
pngwn Feb 23, 2024
25bc7f3
Merge branch 'main' into run-lite-tests
pngwn Feb 23, 2024
4e492b4
Merge branch 'main' into run-lite-tests
pngwn Feb 26, 2024
0aad3d5
Merge branch 'main' into run-lite-tests
pngwn Feb 27, 2024
ce5e9f1
Merge branch 'main' into run-lite-tests
pngwn Mar 4, 2024
296b548
revert workflow changes
pngwn Mar 4, 2024
cc76deb
add changeset
gradio-pr-bot Mar 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/tired-pants-relax.md
@@ -0,0 +1,9 @@
---
"@gradio/app": minor
"@gradio/lite": minor
"@gradio/tootils": minor
"@gradio/wasm": minor
"gradio": minor
---

feat:fix-tests
16 changes: 10 additions & 6 deletions .config/playwright.config.js
Expand Up @@ -29,14 +29,18 @@ normal.projects = undefined; // Explicitly unset this field due to https://githu

const lite = defineConfig(base, {
webServer: {
command: "pnpm --filter @gradio/app dev:lite",
url: "http://localhost:9876/lite.html",
command: "python -m http.server 8000 --directory ../js/lite",
url: "http://localhost:8000/",
reuseExistingServer: !process.env.CI
},
testMatch: [
"**/file_component_events.spec.ts",
"**/chatbot_multimodal.spec.ts",
"**/kitchen_sink.spec.ts"
testIgnore: [
"**/audio_component_events.spec.ts", // Uploading a file requires ffprobe on the server-side, which is not supported in lite.
"**/cancel_events.spec.ts", // This sample app uses `time.sleep` which is not supported on Pyodide.
"**/custom_css.spec.ts", // Media queries is not working somehow.
"**/clear_components.spec.ts", // `gr.Image()` with remote image is not supported in lite because it calls `httpx.stream` through `processing_utils.save_url_to_cache()`.
"**/load_space.spec.ts", // `gr.load()`, which calls `httpx.get` is not supported in lite.
"**/gradio_pdf_demo.spec.ts", // The PDF component is not working on Lite, https://github.com/gradio-app/gradio/issues/7476
"**/queue_full_e2e_test.spec.ts" // In Lite, there is only one event loop, so multiple requests are pushed to the queue sequentially, which is not the case in normal mode.
],
workers: 1
});
Expand Down
13 changes: 12 additions & 1 deletion .github/workflows/test-functional.yml
Expand Up @@ -73,7 +73,18 @@ jobs:
run: |
. venv/bin/activate
pnpm run test:ct
# - run: pnpm --filter @gradio/app test:browser:lite

- name: Build Lite
run: |
. venv/bin/activate
python -m pip install build
pnpm --filter @gradio/app build:lite

- name: Run Lite E2E tests
run: |
. venv/bin/activate
pnpm --filter @gradio/app test:browser:lite

- name: do check
if: always()
uses: "gradio-app/github/actions/commit-status@main"
Expand Down
12 changes: 8 additions & 4 deletions gradio/components/gallery.py
Expand Up @@ -12,7 +12,7 @@
from gradio_client.documentation import document
from gradio_client.utils import is_http_url_like

from gradio import processing_utils, utils
from gradio import processing_utils, utils, wasm_utils
from gradio.components.base import Component
from gradio.data_classes import FileData, GradioModel, GradioRootModel
from gradio.events import Events
Expand Down Expand Up @@ -201,9 +201,13 @@ def _save(img):
caption=caption,
)

with ThreadPoolExecutor() as executor:
for o in executor.map(_save, value):
output.append(o)
if wasm_utils.IS_WASM:
for img in value:
output.append(_save(img))
else:
with ThreadPoolExecutor() as executor:
for o in executor.map(_save, value):
output.append(o)
return GalleryData(root=output)

@staticmethod
Expand Down
8 changes: 6 additions & 2 deletions js/app/src/lite/custom-element/index.ts
@@ -1,4 +1,6 @@
import { create, type Options } from "..";
// NOTE: We should only import the types from ".." to avoid the circular dependency of implementations,
// which causes repeated executions of the ".." module in †he dev mode and can lead to multiple instances of the dev app.
import type { create as createLiteAppFunc, Options } from "..";

interface GradioComponentOptions {
info: Options["info"];
Expand Down Expand Up @@ -28,7 +30,9 @@ function parseRequirementsTxt(content: string): string[] {
.filter((r) => r !== "");
}

export function bootstrap_custom_element(): void {
export function bootstrap_custom_element(
create: typeof createLiteAppFunc
): void {
const CUSTOM_ELEMENT_NAME = "gradio-lite";

if (customElements.get(CUSTOM_ELEMENT_NAME)) {
Expand Down
4 changes: 0 additions & 4 deletions js/app/src/lite/dev/App.svelte
Expand Up @@ -79,12 +79,8 @@ def hi(name):
controlPageTitle: false,
appMode: true
});
// @ts-ignore
window.controller = controller; // For Playwright
});
onDestroy(() => {
// @ts-ignore
window.controller = undefined;
controller.unmount();
});

Expand Down
36 changes: 29 additions & 7 deletions js/app/src/lite/index.ts
Expand Up @@ -258,15 +258,37 @@ export function create(options: Options): GradioAppController {
// @ts-ignore
globalThis.createGradioApp = create;

bootstrap_custom_element();
bootstrap_custom_element(create);

declare let BUILD_MODE: string;
declare let GRADIO_E2E_TEST_LITE: string;
if (BUILD_MODE === "dev") {
(async function () {
const DevApp = (await import("./dev/App.svelte")).default;

const app = new DevApp({
target: document.getElementById("dev-app")!
if (GRADIO_E2E_TEST_LITE) {
// For the Playwright E2E tests, we create an app and expose the controller to the global scope.
const controller = create({
target: document.getElementById("gradio-app")!,
code: "import gradio as gr; demo = gr.Interface(lambda x: x, 'text', 'text'); demo.launch()",
requirements: [],
sharedWorkerMode: true,
info: true,
container: true,
isEmbed: false,
initialHeight: "300px",
eager: false,
themeMode: null,
autoScroll: false,
controlPageTitle: false,
appMode: true
});
})();
// @ts-ignore
window.controller = controller;
} else {
(async function () {
const DevApp = (await import("./dev/App.svelte")).default;

const app = new DevApp({
target: document.getElementById("dev-app")!
});
})();
}
}
20 changes: 12 additions & 8 deletions js/app/test/file_explorer_component_events.spec.ts
Expand Up @@ -100,14 +100,18 @@ test("File Explorer selects all children when top level directory is selected.",
.getByRole("checkbox")
.check();

const res = page.waitForEvent("response", {
predicate: async (response) => {
return (await response.text()).indexOf("process_completed") !== -1;
}
});
await page.getByRole("button", { name: "Run" }).click();

await res;
if (!process.env.GRADIO_E2E_TEST_LITE) {
const res = page.waitForEvent("response", {
predicate: async (response) => {
return (await response.text()).indexOf("process_completed") !== -1;
}
});
await page.getByRole("button", { name: "Run" }).click();
await res;
} else {
// Lite hooks the HTTP requests, so we can't observe the response in this case.
await page.getByRole("button", { name: "Run" }).click();
}

const directory_paths_displayed = async () => {
const value = await page.getByLabel("Selected Directory").inputValue();
Expand Down
13 changes: 8 additions & 5 deletions js/app/test/image_component_events.spec.ts
Expand Up @@ -66,11 +66,14 @@ test("Image copy from clipboard dispatches upload event.", async ({ page }) => {
});

await page.getByLabel("Paste from clipboard").click();
await Promise.all([
page.waitForResponse(
(resp) => resp.url().includes("/clipboard.png") && resp.status() === 200
)
]);
if (!process.env.GRADIO_E2E_TEST_LITE) {
// Lite hooks the HTTP request to the image, so we can't wait for it.
await Promise.all([
page.waitForResponse(
(resp) => resp.url().includes("/clipboard.png") && resp.status() === 200
)
]);
}
await expect(page.getByLabel("# Change Events").first()).toHaveValue("1");
await expect(page.getByLabel("# Upload Events")).toHaveValue("1");
});
Expand Down
1 change: 1 addition & 0 deletions js/app/vite.config.ts
Expand Up @@ -100,6 +100,7 @@ export default defineConfig(({ mode }) => {

define: {
BUILD_MODE: production ? JSON.stringify("prod") : JSON.stringify("dev"),
GRADIO_E2E_TEST_LITE: process.env.GRADIO_E2E_TEST_LITE,
BACKEND_URL: production
? JSON.stringify("")
: JSON.stringify("http://localhost:7860/"),
Expand Down
50 changes: 50 additions & 0 deletions js/lite/for_e2e.html
@@ -0,0 +1,50 @@
<!doctype html>
<!-- A demo HTML file to test the bundled JS and CSS files -->
<html style="margin: 0; padding: 0; height: 100%">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no, maximum-scale=1"
/>

<link rel="preconnect" href="https://fonts.googleapis.com" />
<link
rel="preconnect"
href="https://fonts.gstatic.com"
crossorigin="anonymous"
/>

<script type="module" crossorigin src="./dist/lite.js"></script>
<link rel="stylesheet" href="./dist/lite.css" />
</head>

<body style="margin: 0; padding: 0; height: 100%">
<div id="gradio-app"></div>

<script type="module">
// type="module" is necessary to use `createGradioApp()`, which is loaded with <script type="module" /> tag above.
// For the Playwright tests, set the controller to the global scope.
window.controller = createGradioApp({
target: document.getElementById("gradio-app"),
code: `
import gradio as gr

def greet(name):
return "Hello, " + name + "!"

gr.Interface(fn=greet, inputs="text", outputs="text").launch()
`,
info: true,
container: true,
isEmbed: false,
initialHeight: "300px",
eager: false,
themeMode: null,
autoScroll: false,
controlPageTitle: false,
appMode: true
});
</script>
</body>
</html>
2 changes: 1 addition & 1 deletion js/tootils/src/index.ts
Expand Up @@ -37,7 +37,7 @@ const test_normal = base.extend<{ setup: void }>({
]
});

const lite_url = "http://localhost:9876/lite.html";
const lite_url = "http://localhost:8000/for_e2e.html";
// LIte taks a long time to initialize, so we share the page across tests, sacrificing the test isolation.
let shared_page_for_lite: Page;
const test_lite = base.extend<{ setup: void }>({
Expand Down
2 changes: 1 addition & 1 deletion js/wasm/src/webworker/index.ts
Expand Up @@ -80,7 +80,7 @@ async function initializeEnvironment(
await micropip.install(["markdown-it-py[linkify]~=2.2.0"]); // On 3rd June 2023, markdown-it-py 3.0.0 has been released. The `gradio` package depends on its `>=2.0.0` version so its 3.x will be resolved. However, it conflicts with `mdit-py-plugins`'s dependency `markdown-it-py >=1.0.0,<3.0.0` and micropip currently can't resolve it. So we explicitly install the compatible version of the library here.
await micropip.install(["anyio==3.*"]); // `fastapi` depends on `anyio>=3.4.0,<5` so its 4.* can be installed, but it conflicts with the anyio version `httpx` depends on, `==3.*`. Seems like micropip can't resolve it for now, so we explicitly install the compatible version of the library here.
await micropip.add_mock_package("pydantic", "2.4.2"); // PydanticV2 is not supported on Pyodide yet. Mock it here for installing the `gradio` package to pass the version check. Then, install PydanticV1 below.
await micropip.add_mock_package("ruff", "0.1.7"); // `ruff` was added to the requirements of `gradio` for the custom components (https://github.com/gradio-app/gradio/pull/7030), but it's not working on PYodide yet. Also Lite doesn't need it, so mock it here for installing the `gradio` package to pass the version check.
await micropip.add_mock_package("ruff", "0.2.2"); // `ruff` was added to the requirements of `gradio` for the custom components (https://github.com/gradio-app/gradio/pull/7030), but it's not working on PYodide yet. Also Lite doesn't need it, so mock it here for installing the `gradio` package to pass the version check.
await micropip.install.callKwargs(gradioWheelUrls, {
keep_going: true
});
Expand Down
2 changes: 1 addition & 1 deletion js/wasm/svelte/DownloadLink.svelte
Expand Up @@ -33,7 +33,7 @@
throw new Error("Wasm worker proxy is not available.");
}

const url = new URL(href);
const url = new URL(href, window.location.href);
const path = url.pathname;

is_downloading = true;
Expand Down
4 changes: 2 additions & 2 deletions js/wasm/svelte/file-url.ts
Expand Up @@ -9,7 +9,7 @@ export function should_proxy_wasm_src(src: MediaSrc): boolean {
return false;
}

const url = new URL(src);
const url = new URL(src, window.location.href);
if (!is_self_host(url)) {
// `src` is not accessing a local server resource, so we don't need to proxy this request to the Wasm worker.
return false;
Expand All @@ -33,7 +33,7 @@ export async function resolve_wasm_src(src: MediaSrc): Promise<MediaSrc> {
return src;
}

const url = new URL(src);
const url = new URL(src, window.location.href);
const path = url.pathname;
return maybeWorkerProxy
.httpRequest({
Expand Down