Skip to content

Commit

Permalink
SSR e2e + fixes (#9590)
Browse files Browse the repository at this point in the history
* fix tests in ssr mode

* fix loading race condition

* fix some tests

* add ci

* cleanup

* format

* add changeset

* clean

* test name

* broke it, fix

* fix?

* clean

* lint

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
Co-authored-by: Abubakar Abid <abubakar@huggingface.co>
  • Loading branch information
3 people authored Oct 8, 2024
1 parent 24fe222 commit e853c41
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 167 deletions.
9 changes: 9 additions & 0 deletions .changeset/bright-garlics-melt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@gradio/core": minor
"@self/app": minor
"@self/spa": minor
"@self/tootils": minor
"gradio": minor
---

feat:SSR e2e + fixes
7 changes: 6 additions & 1 deletion .github/workflows/test-functional.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,14 @@ jobs:
filter: "functional"
token: ${{ secrets.GITHUB_TOKEN }}
test:
name: "functional-test-SSR=${{ matrix.SSR }}"
permissions:
contents: read
name: "functional-test"
runs-on: ubuntu-latest
needs: changes
strategy:
matrix:
ssr: [true, false]
if: needs.changes.outputs.should_run == 'true'
steps:
- uses: actions/checkout@v4
Expand All @@ -56,6 +59,8 @@ jobs:
python -m pip install -r demo/stream_video_out/requirements.txt
- run: pnpm exec playwright install chromium firefox
- name: run browser tests
env:
GRADIO_SSR_MODE: ${{ matrix.ssr }}
run: |
. venv/bin/activate
CI=1 pnpm test:browser
Expand Down
1 change: 1 addition & 0 deletions gradio/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ async def conditional_routing_middleware(
and not path.startswith("/gradio_api")
and path not in ["/config", "/login", "/favicon.ico"]
and not path.startswith("/theme")
and not path.startswith("/static")
):
if App.app_port is None:
App.app_port = request.url.port or int(
Expand Down
203 changes: 60 additions & 143 deletions js/app/src/routes/[...catchall]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -115,139 +115,18 @@
let active_theme_mode: ThemeMode;
let intersecting: ReturnType<typeof create_intersection_store> = {
register: () => {},
subscribe: writable({}).subscribe
subscribe: writable({}).subscribe,
};
$: if (config?.app_id) {
app_id = config.app_id;
}
let css_text_stylesheet: HTMLStyleElement | null = null;
async function mount_custom_css(css_string: string | null): Promise<void> {
// if (css_string) {
// css_text_stylesheet = prefix_css(
// css_string,
// version,
// css_text_stylesheet || undefined,
// );
// }
await mount_css(
config.root + config.api_prefix + "/theme.css?v=" + config.theme_hash,
document.head
);
// if (!config.stylesheets) return;
// await Promise.all(
// config.stylesheets.map((stylesheet) => {
// let absolute_link =
// stylesheet.startsWith("http:") || stylesheet.startsWith("https:");
// if (absolute_link) {
// return mount_css(stylesheet, document.head);
// }
// return fetch(config.root + "/" + stylesheet)
// .then((response) => response.text())
// .then((css_string) => {
// prefix_css(css_string, version);
// });
// }),
// );
}
async function add_custom_html_head(
head_string: string | null
): Promise<void> {
// if (head_string) {
// const parser = new DOMParser();
// const parsed_head_html = Array.from(
// parser.parseFromString(head_string, "text/html").head.children,
// );
// if (parsed_head_html) {
// for (let head_element of parsed_head_html) {
// let newElement = document.createElement(head_element.tagName);
// Array.from(head_element.attributes).forEach((attr) => {
// newElement.setAttribute(attr.name, attr.value);
// });
// newElement.textContent = head_element.textContent;
// if (
// newElement.tagName == "META" &&
// newElement.getAttribute("property")
// ) {
// const domMetaList = Array.from(
// document.head.getElementsByTagName("meta") ?? [],
// );
// const matched = domMetaList.find((el) => {
// return (
// el.getAttribute("property") ==
// newElement.getAttribute("property") &&
// !el.isEqualNode(newElement)
// );
// });
// if (matched) {
// document.head.replaceChild(newElement, matched);
// continue;
// }
// }
// document.head.appendChild(newElement);
// }
// }
// }
}
function handle_theme_mode(target: HTMLDivElement): "light" | "dark" {
const force_light = window.__gradio_mode__ === "website";
let new_theme_mode: ThemeMode;
if (force_light) {
new_theme_mode = "light";
} else {
const url = new URL(window.location.toString());
const url_color_mode: ThemeMode | null = url.searchParams.get(
"__theme"
) as ThemeMode | null;
new_theme_mode = theme_mode || url_color_mode || "system";
}
if (new_theme_mode === "dark" || new_theme_mode === "light") {
apply_theme(target, new_theme_mode);
} else {
new_theme_mode = sync_system_theme(target);
}
return new_theme_mode;
}
function sync_system_theme(target: HTMLDivElement): "light" | "dark" {
const theme = update_scheme();
window
?.matchMedia("(prefers-color-scheme: dark)")
?.addEventListener("change", update_scheme);
function update_scheme(): "light" | "dark" {
let _theme: "light" | "dark" = window?.matchMedia?.(
"(prefers-color-scheme: dark)"
).matches
? "dark"
: "light";
apply_theme(target, _theme);
return _theme;
}
return theme;
}
function apply_theme(target: HTMLDivElement, theme: "dark" | "light"): void {
const dark_class_element = is_embed ? target.parentElement! : document.body;
const bg_element = is_embed ? target : target.parentElement!;
bg_element.style.background = "var(--body-background-fill)";
if (theme === "dark") {
dark_class_element.classList.add("dark");
} else {
dark_class_element.classList.remove("dark");
}
}
let status: SpaceStatus = {
message: "",
load_status: "pending",
status: "sleeping",
detail: "SLEEPING"
detail: "SLEEPING",
};
let app: ClientType = data.app;
Expand All @@ -260,12 +139,11 @@
let gradio_dev_mode = "";
onMount(async () => {
// active_theme_mode = handle_theme_mode(wrapper);
active_theme_mode = handle_theme_mode(wrapper);
//@ts-ignore
config = data.config;
window.gradio_config = config;
const api_url = location.origin;
window.gradio_config = data.config;
config = data.config;
Expand All @@ -280,19 +158,17 @@
message: "",
load_status: "complete",
status: "running",
detail: "RUNNING"
detail: "RUNNING",
};
// await mount_custom_css(config.css);
// await add_custom_html_head(config.head);
css_ready = true;
window.__is_colab__ = config.is_colab;
dispatch("loaded");
if (config.dev_mode) {
setTimeout(() => {
const { host } = new URL(api_url);
const { host } = new URL(data.api_url);
let url = new URL(`http://${host}${app.api_prefix}/dev/reload`);
stream = new EventSource(url);
stream.addEventListener("error", async (e) => {
Expand All @@ -302,10 +178,10 @@
});
stream.addEventListener("reload", async (event) => {
app.close();
app = await Client.connect(api_url, {
app = await Client.connect(data.api_url, {
status_callback: handle_status,
with_null_state: true,
events: ["data", "log", "status", "render"]
events: ["data", "log", "status", "render"],
});
if (!app.config) {
Expand All @@ -314,14 +190,6 @@
config = app.config;
window.__gradio_space__ = config.space_id;
await mount_custom_css(config.css);
await add_custom_html_head(config.head);
css_ready = true;
window.__is_colab__ = config.is_colab;
dispatch("loaded");
// // config = app.config;
// window.__gradio_space__ = config.space_id;
// await mount_custom_css(config.css);
});
}, 200);
}
Expand All @@ -339,8 +207,8 @@
new CustomEvent("render", {
bubbles: true,
cancelable: false,
composed: true
})
composed: true,
}),
);
}
Expand All @@ -351,7 +219,7 @@
async function mount_space_header(
space_id: string | null | undefined,
is_embed: boolean
is_embed: boolean,
): Promise<void> {
if (space_id && !is_embed && window.self === window.top) {
if (spaceheader) {
Expand All @@ -366,12 +234,61 @@
onDestroy(() => {
spaceheader?.remove();
});
function handle_theme_mode(target: HTMLDivElement): "light" | "dark" {
let new_theme_mode: ThemeMode;
const url = new URL(window.location.toString());
const url_color_mode: ThemeMode | null = url.searchParams.get(
"__theme",
) as ThemeMode | null;
new_theme_mode = theme_mode || url_color_mode || "system";
if (new_theme_mode === "dark" || new_theme_mode === "light") {
apply_theme(target, new_theme_mode);
} else {
new_theme_mode = sync_system_theme(target);
}
return new_theme_mode;
}
function sync_system_theme(target: HTMLDivElement): "light" | "dark" {
const theme = update_scheme();
window
?.matchMedia("(prefers-color-scheme: dark)")
?.addEventListener("change", update_scheme);
function update_scheme(): "light" | "dark" {
let _theme: "light" | "dark" = window?.matchMedia?.(
"(prefers-color-scheme: dark)",
).matches
? "dark"
: "light";
apply_theme(target, _theme);
return _theme;
}
return theme;
}
function apply_theme(target: HTMLDivElement, theme: "dark" | "light"): void {
const dark_class_element = is_embed ? target.parentElement! : document.body;
const bg_element = is_embed ? target : target.parentElement!;
bg_element.style.background = "var(--body-background-fill)";
if (theme === "dark") {
dark_class_element.classList.add("dark");
} else {
dark_class_element.classList.remove("dark");
}
}
</script>

<svelte:head>
<link rel="stylesheet" href={"./theme.css?v=" + config?.theme_hash} />

<style></style>
{#if config.head}
{@html config.head}
{/if}
</svelte:head>

<Embed
Expand Down
19 changes: 11 additions & 8 deletions js/core/src/Blocks.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import type { ToastMessage } from "@gradio/statustracker";
import type { ShareData, ValueData } from "@gradio/utils";
import MountComponents from "./MountComponents.svelte";
import { prefix_css } from "./css";
import logo from "./images/logo.svg";
import api_logo from "./api_docs/img/api-logo.svg";
Expand Down Expand Up @@ -47,8 +48,8 @@
export let username: string | null;
export let api_prefix = "";
export let max_file_size: number | undefined = undefined;
export let initial_layout: LayoutNode | undefined = undefined;
export let initial_layout: ComponentMeta | undefined = undefined;
export let css: string | null | undefined = null;
let {
layout: _layout,
targets,
Expand All @@ -61,10 +62,7 @@
scheduled_updates,
create_layout,
rerender_layout
} = create_components();
// @ts-ignore
$_layout = initial_layout;
} = create_components(initial_layout);
$: components, layout, dependencies, root, app, fill_height, target, run();
Expand Down Expand Up @@ -207,8 +205,10 @@
if ($scheduled_updates) {
_unsub = scheduled_updates.subscribe((updating) => {
if (!updating) {
trigger_api_call(dep_index, trigger_id, event_data);
unsub();
tick().then(() => {
trigger_api_call(dep_index, trigger_id, event_data);
unsub();
});
}
});
} else {
Expand Down Expand Up @@ -715,6 +715,9 @@
{#if control_page_title}
<title>{title}</title>
{/if}
{#if css}
{@html `\<style\>${prefix_css(css, version)}</style>`}
{/if}
</svelte:head>

<div class="wrap" style:min-height={app_mode ? "100%" : "auto"}>
Expand Down
Loading

0 comments on commit e853c41

Please sign in to comment.