mirror of
https://github.com/gradio-app/gradio.git
synced 2025-04-12 12:40:29 +08:00
Fix flaky CI tests (again 😓 ) (#6780)
* network idle
* Use **/upload
* Test flakes
* Fix pythont tests
* add changeset
* Use right wait
* upload
* trigger ci
* swap order
* networkidle❓
* lint'
* df
* 2 workers
* networkidle
* Fix cli test
* pause
* 3.8 fix
* 3.8
* no promise.all
* trigger ci
* Add code
* mark xfail
* trigger ci
* timeout
* Empty
* Flake
* test
* Flakes
* change test
* awaits
* cleanup
* fixes
---------
Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
Co-authored-by: Abubakar Abid <abubakar@huggingface.co>
This commit is contained in:
parent
a807ede818
commit
51e241addd
5
.changeset/social-dancers-yawn.md
Normal file
5
.changeset/social-dancers-yawn.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"gradio": patch
|
||||
---
|
||||
|
||||
fix:Fix flaky CI tests (again 😓 )
|
@ -1,4 +1,6 @@
|
||||
export default {
|
||||
import { defineConfig } from "@playwright/test";
|
||||
|
||||
export default defineConfig({
|
||||
use: {
|
||||
screenshot: "only-on-failure",
|
||||
trace: "retain-on-failure",
|
||||
@ -8,7 +10,10 @@ export default {
|
||||
args: ["--disable-web-security"]
|
||||
}
|
||||
},
|
||||
expect: { timeout: 60000 },
|
||||
timeout: 90000,
|
||||
testMatch: /.*.spec.ts/,
|
||||
testDir: "..",
|
||||
globalSetup: "./playwright-setup.js"
|
||||
};
|
||||
globalSetup: "./playwright-setup.js",
|
||||
workers: process.env.CI ? 1 : undefined
|
||||
});
|
||||
|
2
.github/workflows/ui.yml
vendored
2
.github/workflows/ui.yml
vendored
@ -71,7 +71,7 @@ jobs:
|
||||
- name: run browser tests
|
||||
run: |
|
||||
. venv/bin/activate
|
||||
pnpm test:browser
|
||||
CI=1 pnpm test:browser
|
||||
- name: upload screenshots
|
||||
uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
|
@ -13,8 +13,8 @@ import gradio
|
||||
|
||||
|
||||
def _in_test_dir():
|
||||
"""Check if the current working directory ends with gradio/js/gradio-preview/test."""
|
||||
return Path.cwd().parts[-4:] == ("gradio", "js", "gradio-preview", "test")
|
||||
"""Check if the current working directory ends with gradio/js/preview/test."""
|
||||
return Path.cwd().parts[-4:] == ("gradio", "js", "preview", "test")
|
||||
|
||||
|
||||
default_demo_code = """
|
||||
|
@ -1,6 +1,5 @@
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import semantic_version
|
||||
@ -83,7 +82,7 @@ def _build(
|
||||
else:
|
||||
live.update(":white_check_mark: Build succeeded!")
|
||||
|
||||
cmds = [sys.executable, "-m", "build", str(name)]
|
||||
cmds = [shutil.which("python"), "-m", "build", str(name)]
|
||||
live.update(f":construction_worker: Building... [grey37]({' '.join(cmds)})[/]")
|
||||
pipe = subprocess.run(cmds, capture_output=True, text=True)
|
||||
if pipe.returncode != 0:
|
||||
|
@ -1,11 +1,9 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import random
|
||||
import re
|
||||
import shutil
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
from typing import List, Optional
|
||||
|
||||
import semantic_version
|
||||
from huggingface_hub import HfApi
|
||||
@ -65,13 +63,13 @@ def _ignore(s, names):
|
||||
return ignored
|
||||
|
||||
|
||||
def _get_version_from_file(dist_file: Path) -> str | None:
|
||||
def _get_version_from_file(dist_file: Path) -> Optional[str]:
|
||||
match = re.search(r"-(\d+\.\d+\.\d+[a-zA-Z]*\d*)-", dist_file.name)
|
||||
if match:
|
||||
return match.group(1)
|
||||
|
||||
|
||||
def _get_max_version(distribution_files: list[Path]) -> str | None:
|
||||
def _get_max_version(distribution_files: List[Path]) -> Optional[str]:
|
||||
versions = []
|
||||
for p in distribution_files:
|
||||
version = _get_version_from_file(p)
|
||||
|
@ -7,10 +7,7 @@ test("Audio click-to-upload uploads audio successfuly. File downloading works an
|
||||
.getByRole("button", { name: "Drop Audio Here - or - Click to Upload" })
|
||||
.click();
|
||||
const uploader = await page.locator("input[type=file]");
|
||||
await Promise.all([
|
||||
uploader.setInputFiles(["../../test/test_files/audio_sample.wav"]),
|
||||
page.waitForResponse("**/upload?*")
|
||||
]);
|
||||
await uploader.setInputFiles(["../../test/test_files/audio_sample.wav"]);
|
||||
|
||||
await expect(page.getByLabel("# Input Change Events")).toHaveValue("1");
|
||||
await expect(page.getByLabel("# Input Upload Events")).toHaveValue("1");
|
||||
@ -21,10 +18,7 @@ test("Audio click-to-upload uploads audio successfuly. File downloading works an
|
||||
.getByRole("button", { name: "Drop Audio Here - or - Click to Upload" })
|
||||
.click();
|
||||
|
||||
await Promise.all([
|
||||
uploader.setInputFiles(["../../test/test_files/audio_sample.wav"]),
|
||||
page.waitForResponse("**/upload?*")
|
||||
]);
|
||||
await uploader.setInputFiles(["../../test/test_files/audio_sample.wav"]);
|
||||
|
||||
await expect(page.getByLabel("# Input Change Events")).toHaveValue("3");
|
||||
await expect(page.getByLabel("# Input Upload Events")).toHaveValue("2");
|
||||
@ -38,16 +32,13 @@ test("Audio click-to-upload uploads audio successfuly. File downloading works an
|
||||
test("Audio drag-and-drop uploads a file to the server correctly.", async ({
|
||||
page
|
||||
}) => {
|
||||
await Promise.all([
|
||||
drag_and_drop_file(
|
||||
page,
|
||||
"input[type=file]",
|
||||
"../../test/test_files/audio_sample.wav",
|
||||
"audio_sample.wav",
|
||||
"audio/wav"
|
||||
),
|
||||
page.waitForResponse("**/upload?*")
|
||||
]);
|
||||
await drag_and_drop_file(
|
||||
page,
|
||||
"input[type=file]",
|
||||
"../../test/test_files/audio_sample.wav",
|
||||
"audio_sample.wav",
|
||||
"audio/wav"
|
||||
);
|
||||
await expect(page.getByLabel("# Input Change Events")).toHaveValue("1");
|
||||
await expect(page.getByLabel("# Input Upload Events")).toHaveValue("1");
|
||||
});
|
||||
@ -67,30 +58,24 @@ test("Audio drag-and-drop displays a warning when the file is of the wrong mime
|
||||
|
||||
test("Play, Pause, and stop events work correctly.", async ({ page }) => {
|
||||
const uploader = await page.locator("input[type=file]");
|
||||
await Promise.all([
|
||||
uploader.setInputFiles(["../../demo/audio_debugger/cantina.wav"]),
|
||||
page.waitForResponse("**/upload?*")
|
||||
]);
|
||||
|
||||
await page
|
||||
.getByTestId("waveform-Output Audio")
|
||||
.getByLabel("Play", { exact: true })
|
||||
.click();
|
||||
await page.getByTestId("waveform-Output Audio").getByLabel("Pause").click();
|
||||
await page
|
||||
.getByTestId("waveform-Output Audio")
|
||||
.getByLabel("Play", { exact: true })
|
||||
.click();
|
||||
|
||||
await uploader.setInputFiles(["../../demo/audio_debugger/cantina.wav"]);
|
||||
const event_triggered = async (label: string) => {
|
||||
const value = await page.getByLabel(label).inputValue();
|
||||
expect(Number(value)).toBeGreaterThan(0);
|
||||
};
|
||||
|
||||
// toPass will retry the function until it passes or times out
|
||||
// need this because the stop event is only triggered when the video is done playing
|
||||
// hard to time otherwise
|
||||
await page
|
||||
.getByTestId("waveform-Output Audio")
|
||||
.getByLabel("Play", { exact: true })
|
||||
.click();
|
||||
await expect(async () => event_triggered("# Output Play Events")).toPass();
|
||||
|
||||
await page.getByTestId("waveform-Output Audio").getByLabel("Pause").click();
|
||||
await expect(async () => event_triggered("# Output Pause Events")).toPass();
|
||||
|
||||
await page
|
||||
.getByTestId("waveform-Output Audio")
|
||||
.getByLabel("Play", { exact: true })
|
||||
.click();
|
||||
await expect(async () => event_triggered("# Output Stop Events")).toPass();
|
||||
});
|
||||
|
@ -9,51 +9,30 @@ test("chatinterface works with streaming functions and all buttons behave as exp
|
||||
const clear_button = await page.getByRole("button", { name: "🗑️ Clear" });
|
||||
const textbox = await page.getByPlaceholder("Type a message...");
|
||||
|
||||
let iterations: Promise<any>[] = [];
|
||||
page.on("websocket", (ws) => {
|
||||
iterations.push(
|
||||
ws.waitForEvent("framereceived", {
|
||||
predicate: (event) => {
|
||||
return (
|
||||
JSON.parse(event.payload as string).msg === "process_completed"
|
||||
);
|
||||
}
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
await textbox.fill("hello");
|
||||
await submit_button.click();
|
||||
await iterations[0];
|
||||
await expect(textbox).toHaveValue("");
|
||||
await expect.poll(async () => page.locator(".chatbot p").count()).toBe(1);
|
||||
const bot_message_0 = await page.locator(".bot.message").nth(0);
|
||||
await expect(bot_message_0).toContainText("You typed: hello");
|
||||
|
||||
await textbox.fill("hi");
|
||||
await submit_button.click();
|
||||
await iterations[1];
|
||||
await expect(textbox).toHaveValue("");
|
||||
await expect.poll(async () => page.locator(".message.bot").count()).toBe(2);
|
||||
const bot_message_1 = await page.locator(".bot").nth(1);
|
||||
await expect(bot_message_1).toContainText("You typed: hi");
|
||||
|
||||
await retry_button.click();
|
||||
await iterations[2];
|
||||
await expect(textbox).toHaveValue("");
|
||||
await expect(bot_message_1).toContainText("You typed: hi");
|
||||
await expect(page.locator(".bot").nth(1)).toContainText("You typed: hi");
|
||||
|
||||
await undo_button.click();
|
||||
await iterations[3];
|
||||
await expect.poll(async () => page.locator(".message.bot").count()).toBe(1);
|
||||
await expect(textbox).toHaveValue("hi");
|
||||
|
||||
await textbox.fill("salaam");
|
||||
await submit_button.click();
|
||||
await iterations[4];
|
||||
await expect(textbox).toHaveValue("");
|
||||
await expect.poll(async () => page.locator(".bot.message").count()).toBe(2);
|
||||
await expect(bot_message_1).toContainText("You typed: salaam");
|
||||
await expect(page.locator(".bot").nth(1)).toContainText("You typed: salaam");
|
||||
|
||||
await clear_button.click();
|
||||
await expect.poll(async () => page.locator(".bot.message").count()).toBe(0);
|
||||
|
@ -6,37 +6,34 @@ test("Image click-to-upload uploads image successfuly. Clear button dispatches e
|
||||
}) => {
|
||||
await page.getByRole("button", { name: "Drop Image Here" }).click();
|
||||
const uploader = await page.locator("input[type=file]");
|
||||
await Promise.all([
|
||||
uploader.setInputFiles(["./test/files/cheetah1.jpg"]),
|
||||
page.waitForResponse("**/upload?*?*")
|
||||
]);
|
||||
const change_counter = await page.getByLabel("# Change Events", {
|
||||
exact: true
|
||||
});
|
||||
const clear_counter = await page.getByLabel("# Clear Events");
|
||||
const upload_counter = await page.getByLabel("# Upload Events");
|
||||
const change_output_counter = await page.getByLabel("# Change Events Output");
|
||||
|
||||
await expect(page.getByLabel("# Change Events").first()).toHaveValue("1");
|
||||
await expect(await page.getByLabel("# Upload Events")).toHaveValue("1");
|
||||
await expect(await page.getByLabel("# Change Events Output")).toHaveValue(
|
||||
"1"
|
||||
);
|
||||
await uploader.setInputFiles("./test/files/cheetah1.jpg");
|
||||
|
||||
await expect(change_counter).toHaveValue("1");
|
||||
await expect(upload_counter).toHaveValue("1");
|
||||
await expect(change_output_counter).toHaveValue("1");
|
||||
|
||||
const downloadPromise = page.waitForEvent("download");
|
||||
await page.getByLabel("Download").click();
|
||||
const download = await downloadPromise;
|
||||
// Automatically convert to png in the backend since PIL is very picky
|
||||
// PIL converts from .jpg to .jpeg
|
||||
await expect(download.suggestedFilename()).toBe("cheetah1.jpeg");
|
||||
|
||||
await page.getByLabel("Remove Image").click();
|
||||
await expect(page.getByLabel("# Clear Events")).toHaveValue("1");
|
||||
await expect(page.getByLabel("# Change Events").first()).toHaveValue("2");
|
||||
await expect(clear_counter).toHaveValue("1");
|
||||
await expect(change_counter).toHaveValue("2");
|
||||
await expect(upload_counter).toHaveValue("1");
|
||||
|
||||
await Promise.all([
|
||||
uploader.setInputFiles(["./test/files/gradio-logo.svg"]),
|
||||
page.waitForResponse("**/upload?*?*")
|
||||
]);
|
||||
|
||||
await expect(page.getByLabel("# Change Events").first()).toHaveValue("3");
|
||||
await expect(await page.getByLabel("# Upload Events")).toHaveValue("2");
|
||||
await expect(await page.getByLabel("# Change Events Output")).toHaveValue(
|
||||
"2"
|
||||
);
|
||||
await uploader.setInputFiles("./test/files/gradio-logo.svg");
|
||||
await expect(change_counter).toHaveValue("3");
|
||||
await expect(upload_counter).toHaveValue("2");
|
||||
await expect(change_output_counter).toHaveValue("2");
|
||||
|
||||
const SVGdownloadPromise = page.waitForEvent("download");
|
||||
await page.getByLabel("Download").click();
|
||||
@ -45,16 +42,13 @@ test("Image click-to-upload uploads image successfuly. Clear button dispatches e
|
||||
});
|
||||
|
||||
test("Image drag-to-upload uploads image successfuly.", async ({ page }) => {
|
||||
await Promise.all([
|
||||
drag_and_drop_file(
|
||||
page,
|
||||
"input[type=file]",
|
||||
"./test/files/cheetah1.jpg",
|
||||
"cheetag1.jpg",
|
||||
"image/*"
|
||||
),
|
||||
page.waitForResponse("**/upload?*")
|
||||
]);
|
||||
await drag_and_drop_file(
|
||||
page,
|
||||
"input[type=file]",
|
||||
"./test/files/cheetah1.jpg",
|
||||
"cheetag1.jpg",
|
||||
"image/*"
|
||||
);
|
||||
await expect(page.getByLabel("# Change Events").first()).toHaveValue("1");
|
||||
await expect(page.getByLabel("# Upload Events")).toHaveValue("1");
|
||||
});
|
||||
@ -71,9 +65,7 @@ test("Image copy from clipboard dispatches upload event.", async ({ page }) => {
|
||||
navigator.clipboard.write([new ClipboardItem({ [blob.type]: blob })]);
|
||||
});
|
||||
|
||||
await page.pause();
|
||||
await page.getByLabel("clipboard-image-toolbar-btn").click();
|
||||
await page.pause();
|
||||
await expect(page.getByLabel("# Change Events").first()).toHaveValue("1");
|
||||
await expect(page.getByLabel("# Upload Events")).toHaveValue("1");
|
||||
});
|
||||
|
@ -7,18 +7,19 @@ test("Model3D click-to-upload uploads file successfuly. Upload and clear events
|
||||
.getByRole("button", { name: "Drop File Here - or - Click to Upload" })
|
||||
.click();
|
||||
const uploader = await page.locator("input[type=file]");
|
||||
await Promise.all([
|
||||
uploader.setInputFiles(["./test/files/face.obj"]),
|
||||
page.waitForResponse("**/upload?*?*")
|
||||
]);
|
||||
const change_counter = await page.getByLabel("# Change Events");
|
||||
const upload_counter = await page.getByLabel("# Upload Events");
|
||||
const clear_counter = await page.getByLabel("# Clear Events");
|
||||
|
||||
await expect(page.getByLabel("# Change Events")).toHaveValue("1");
|
||||
await expect(page.getByLabel("# Upload Events")).toHaveValue("1");
|
||||
await uploader.setInputFiles("./test/files/face.obj");
|
||||
|
||||
await expect(change_counter).toHaveValue("1");
|
||||
await expect(upload_counter).toHaveValue("1");
|
||||
|
||||
await page.getByLabel("Clear").nth(0).click();
|
||||
await expect(page.getByLabel("# Change Events")).toHaveValue("2");
|
||||
await expect(page.getByLabel("# Clear Events")).toHaveValue("1");
|
||||
await expect(page.getByLabel("Clear Value")).toHaveValue("");
|
||||
await expect(change_counter).toHaveValue("2");
|
||||
await expect(clear_counter).toHaveValue("1");
|
||||
await expect(await page.getByLabel("Clear Value")).toHaveValue("");
|
||||
|
||||
const downloadPromise = page.waitForEvent("download");
|
||||
await page.getByLabel("Download").click();
|
||||
@ -35,7 +36,6 @@ test("Model3D drag-and-drop uploads a file to the server correctly.", async ({
|
||||
"./test/files/face.obj",
|
||||
"face.obj"
|
||||
);
|
||||
await page.waitForResponse("**/upload?*");
|
||||
await expect(page.getByLabel("# Change Events")).toHaveValue("1");
|
||||
await expect(page.getByLabel("# Upload Events")).toHaveValue("1");
|
||||
await expect(await page.getByLabel("# Change Events")).toHaveValue("1");
|
||||
await expect(await page.getByLabel("# Upload Events")).toHaveValue("1");
|
||||
});
|
||||
|
@ -5,10 +5,7 @@ test("UploadButton properly dispatches load event and click event for the single
|
||||
}) => {
|
||||
await page.getByRole("button", { name: "Upload Single File" }).click();
|
||||
const uploader = await page.getByTestId("Upload Single File-upload-button");
|
||||
await Promise.all([
|
||||
uploader.setInputFiles(["./test/files/face.obj"]),
|
||||
page.waitForResponse("**/upload?*?*")
|
||||
]);
|
||||
await uploader.setInputFiles(["./test/files/cheetah1.jpg"]);
|
||||
|
||||
await expect(page.getByLabel("# Load Upload Single File")).toHaveValue("1");
|
||||
await expect(
|
||||
@ -18,7 +15,7 @@ test("UploadButton properly dispatches load event and click event for the single
|
||||
const downloadPromise = page.waitForEvent("download");
|
||||
await page.getByRole("link").nth(0).click();
|
||||
const download = await downloadPromise;
|
||||
await expect(download.suggestedFilename()).toBe("face.obj");
|
||||
await expect(download.suggestedFilename()).toBe("cheetah1.jpg");
|
||||
});
|
||||
|
||||
test("UploadButton properly dispatches load event and click event for the multiple file case.", async ({
|
||||
@ -28,12 +25,9 @@ test("UploadButton properly dispatches load event and click event for the multip
|
||||
const uploader = await page.getByTestId(
|
||||
"Upload Multiple Files-upload-button"
|
||||
);
|
||||
await Promise.all([
|
||||
uploader.setInputFiles([
|
||||
"./test/files/face.obj",
|
||||
"./test/files/cheetah1.jpg"
|
||||
]),
|
||||
page.waitForResponse("**/upload?*?*")
|
||||
await uploader.setInputFiles([
|
||||
"./test/files/face.obj",
|
||||
"./test/files/cheetah1.jpg"
|
||||
]);
|
||||
|
||||
await expect(page.getByLabel("# Load Upload Multiple Files")).toHaveValue(
|
||||
|
@ -7,44 +7,44 @@ test("Video click-to-upload uploads video successfuly. Clear, play, and pause bu
|
||||
.getByRole("button", { name: "Drop Video Here - or - Click to Upload" })
|
||||
.click();
|
||||
const uploader = await page.locator("input[type=file]");
|
||||
await Promise.all([
|
||||
uploader.setInputFiles(["./test/files/file_test.ogg"]),
|
||||
page.waitForResponse("**/upload?*?*")
|
||||
]);
|
||||
await uploader.setInputFiles(["./test/files/file_test.ogg"]);
|
||||
|
||||
await expect(page.getByLabel("# Change Events")).toHaveValue("1");
|
||||
await expect(page.getByLabel("# Upload Events")).toHaveValue("1");
|
||||
|
||||
await page.getByLabel("play-pause-replay-button").nth(0).click();
|
||||
await page.getByLabel("play-pause-replay-button").nth(0).click();
|
||||
await expect(page.getByLabel("# Play Events")).toHaveValue("1");
|
||||
await expect(page.getByLabel("# Pause Events")).toHaveValue("1");
|
||||
|
||||
await page.getByLabel("Clear").click();
|
||||
await expect(page.getByLabel("# Change Events")).toHaveValue("2");
|
||||
await page
|
||||
.getByRole("button", { name: "Drop Video Here - or - Click to Upload" })
|
||||
.click();
|
||||
|
||||
await Promise.all([
|
||||
uploader.setInputFiles(["./test/files/file_test.ogg"]),
|
||||
page.waitForResponse("**/upload?*")
|
||||
]);
|
||||
await uploader.setInputFiles(["./test/files/file_test.ogg"]);
|
||||
|
||||
await expect(page.getByLabel("# Change Events")).toHaveValue("3");
|
||||
await expect(page.getByLabel("# Upload Events")).toHaveValue("2");
|
||||
|
||||
await page.getByLabel("play-pause-replay-button").first().click();
|
||||
await page.getByLabel("play-pause-replay-button").first().click();
|
||||
await expect(page.getByLabel("# Play Events")).toHaveValue("2");
|
||||
await expect(page.getByLabel("# Pause Events")).toHaveValue("2");
|
||||
|
||||
const downloadPromise = page.waitForEvent("download");
|
||||
await page.getByLabel("Download").click();
|
||||
const download = await downloadPromise;
|
||||
await expect(download.suggestedFilename()).toBe("file_test.ogg");
|
||||
});
|
||||
|
||||
test("Video play, pause events work correctly.", async ({ page }) => {
|
||||
await page
|
||||
.getByRole("button", { name: "Drop Video Here - or - Click to Upload" })
|
||||
.click();
|
||||
const uploader = await page.locator("input[type=file]");
|
||||
await uploader.setInputFiles(["./test/files/file_test.ogg"]);
|
||||
|
||||
// Wait change event to trigger
|
||||
await expect(page.getByLabel("# Change Events")).toHaveValue("1");
|
||||
|
||||
await page.getByLabel("play-pause-replay-button").first().click();
|
||||
await expect(page.getByLabel("# Play Events")).toHaveValue("1");
|
||||
await page.getByLabel("play-pause-replay-button").first().click();
|
||||
await expect(page.getByLabel("# Pause Events")).toHaveValue("1");
|
||||
});
|
||||
|
||||
test("Video drag-and-drop uploads a file to the server correctly.", async ({
|
||||
page
|
||||
}) => {
|
||||
@ -55,7 +55,6 @@ test("Video drag-and-drop uploads a file to the server correctly.", async ({
|
||||
"file_test.ogg",
|
||||
"video/*"
|
||||
);
|
||||
await page.waitForResponse("**/upload?*");
|
||||
await expect(page.getByLabel("# Change Events")).toHaveValue("1");
|
||||
await expect(page.getByLabel("# Upload Events")).toHaveValue("1");
|
||||
});
|
||||
|
162
pnpm-lock.yaml
generated
162
pnpm-lock.yaml
generated
@ -1,4 +1,4 @@
|
||||
lockfileVersion: '6.0'
|
||||
lockfileVersion: '6.1'
|
||||
|
||||
settings:
|
||||
autoInstallPeers: true
|
||||
@ -262,16 +262,16 @@ importers:
|
||||
version: 2.0.0(@sveltejs/kit@1.26.0)
|
||||
'@sveltejs/kit':
|
||||
specifier: ^1.5.0
|
||||
version: 1.26.0(svelte@4.2.3)(vite@4.5.0)
|
||||
version: 1.26.0(svelte@4.2.2)(vite@4.5.0)
|
||||
prettier:
|
||||
specifier: ^3.0.0
|
||||
version: 3.0.0
|
||||
prettier-plugin-svelte:
|
||||
specifier: ^3.0.0
|
||||
version: 3.0.0(prettier@3.0.0)(svelte@4.2.3)
|
||||
version: 3.0.0(prettier@3.0.0)(svelte@4.2.2)
|
||||
svelte-check:
|
||||
specifier: ^3.0.1
|
||||
version: 3.4.4(@babel/core@7.23.3)(less@4.2.0)(postcss@8.4.27)(svelte@4.2.3)
|
||||
version: 3.4.4(@babel/core@7.23.3)(less@4.2.0)(postcss@8.4.27)(svelte@4.2.2)
|
||||
typescript:
|
||||
specifier: ^5.0.0
|
||||
version: 5.0.2
|
||||
@ -292,7 +292,7 @@ importers:
|
||||
version: 3.0.0
|
||||
mdsvex:
|
||||
specifier: ^0.11.0
|
||||
version: 0.11.0(svelte@4.2.3)
|
||||
version: 0.11.0(svelte@4.2.2)
|
||||
postcss:
|
||||
specifier: '>=8.3.3 <9.0.0'
|
||||
version: 8.4.27
|
||||
@ -305,7 +305,7 @@ importers:
|
||||
version: 2.0.2(@sveltejs/kit@1.27.6)
|
||||
'@sveltejs/kit':
|
||||
specifier: ^1.27.6
|
||||
version: 1.27.6(svelte@4.2.3)(vite@4.5.0)
|
||||
version: 1.27.6(svelte@4.2.2)(vite@4.5.0)
|
||||
'@tailwindcss/forms':
|
||||
specifier: ^0.5.0
|
||||
version: 0.5.0(tailwindcss@3.1.6)
|
||||
@ -6731,7 +6731,7 @@ packages:
|
||||
peerDependencies:
|
||||
'@sveltejs/kit': ^1.0.0
|
||||
dependencies:
|
||||
'@sveltejs/kit': 1.26.0(svelte@4.2.3)(vite@4.5.0)
|
||||
'@sveltejs/kit': 1.26.0(svelte@4.2.2)(vite@4.5.0)
|
||||
import-meta-resolve: 2.2.2
|
||||
dev: true
|
||||
|
||||
@ -6740,7 +6740,7 @@ packages:
|
||||
peerDependencies:
|
||||
'@sveltejs/kit': ^1.0.0
|
||||
dependencies:
|
||||
'@sveltejs/kit': 1.27.6(svelte@4.2.3)(vite@4.5.0)
|
||||
'@sveltejs/kit': 1.27.6(svelte@4.2.2)(vite@4.5.0)
|
||||
import-meta-resolve: 2.2.2
|
||||
dev: true
|
||||
|
||||
@ -6749,7 +6749,7 @@ packages:
|
||||
peerDependencies:
|
||||
'@sveltejs/kit': ^1.5.0
|
||||
dependencies:
|
||||
'@sveltejs/kit': 1.27.6(svelte@4.2.3)(vite@4.5.0)
|
||||
'@sveltejs/kit': 1.27.6(svelte@4.2.2)(vite@4.5.0)
|
||||
dev: true
|
||||
|
||||
/@sveltejs/adapter-vercel@3.0.3(@sveltejs/kit@1.27.6):
|
||||
@ -6757,7 +6757,7 @@ packages:
|
||||
peerDependencies:
|
||||
'@sveltejs/kit': ^1.5.0
|
||||
dependencies:
|
||||
'@sveltejs/kit': 1.27.6(svelte@4.2.3)(vite@4.5.0)
|
||||
'@sveltejs/kit': 1.27.6(svelte@4.2.2)(vite@4.5.0)
|
||||
'@vercel/nft': 0.23.1
|
||||
esbuild: 0.18.20
|
||||
transitivePeerDependencies:
|
||||
@ -6765,7 +6765,7 @@ packages:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/@sveltejs/kit@1.26.0(svelte@4.2.3)(vite@4.5.0):
|
||||
/@sveltejs/kit@1.26.0(svelte@4.2.2)(vite@4.5.0):
|
||||
resolution: {integrity: sha512-CV/AlTziC05yrz7UjVqEd0pH6+2dnrbmcnHGr2d3jXtmOgzNnlDkXtX8g3BfJ6nntsPD+0jtS2PzhvRHblRz4A==}
|
||||
engines: {node: ^16.14 || >=18}
|
||||
hasBin: true
|
||||
@ -6774,7 +6774,7 @@ packages:
|
||||
svelte: ^3.54.0 || ^4.0.0-next.0
|
||||
vite: ^4.0.0
|
||||
dependencies:
|
||||
'@sveltejs/vite-plugin-svelte': 2.5.2(svelte@4.2.3)(vite@4.5.0)
|
||||
'@sveltejs/vite-plugin-svelte': 2.5.2(svelte@4.2.2)(vite@4.5.0)
|
||||
'@types/cookie': 0.5.4
|
||||
cookie: 0.5.0
|
||||
devalue: 4.3.2
|
||||
@ -6785,7 +6785,7 @@ packages:
|
||||
sade: 1.8.1
|
||||
set-cookie-parser: 2.6.0
|
||||
sirv: 2.0.3
|
||||
svelte: 4.2.3
|
||||
svelte: 4.2.2
|
||||
tiny-glob: 0.2.9
|
||||
undici: 5.26.5
|
||||
vite: 4.5.0(@types/node@20.3.2)(less@4.2.0)(lightningcss@1.21.7)(sass@1.66.1)(stylus@0.62.0)(sugarss@4.0.1)
|
||||
@ -6793,7 +6793,7 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@sveltejs/kit@1.27.6(svelte@4.2.3)(vite@4.5.0):
|
||||
/@sveltejs/kit@1.27.6(svelte@4.2.2)(vite@4.5.0):
|
||||
resolution: {integrity: sha512-GsjTkMbKzXdbeRg0tk8S7HNShQ4879ftRr0ZHaZfjbig1xQwG57Bvcm9U9/mpLJtCapLbLWUnygKrgcLISLC8A==}
|
||||
engines: {node: ^16.14 || >=18}
|
||||
hasBin: true
|
||||
@ -6802,7 +6802,7 @@ packages:
|
||||
svelte: ^3.54.0 || ^4.0.0-next.0 || ^5.0.0-next.0
|
||||
vite: ^4.0.0
|
||||
dependencies:
|
||||
'@sveltejs/vite-plugin-svelte': 2.5.2(svelte@4.2.3)(vite@4.5.0)
|
||||
'@sveltejs/vite-plugin-svelte': 2.5.2(svelte@4.2.2)(vite@4.5.0)
|
||||
'@types/cookie': 0.5.4
|
||||
cookie: 0.5.0
|
||||
devalue: 4.3.2
|
||||
@ -6813,7 +6813,7 @@ packages:
|
||||
sade: 1.8.1
|
||||
set-cookie-parser: 2.6.0
|
||||
sirv: 2.0.3
|
||||
svelte: 4.2.3
|
||||
svelte: 4.2.2
|
||||
tiny-glob: 0.2.9
|
||||
undici: 5.26.5
|
||||
vite: 4.5.0(@types/node@20.3.2)(less@4.2.0)(lightningcss@1.21.7)(sass@1.66.1)(stylus@0.62.0)(sugarss@4.0.1)
|
||||
@ -6835,6 +6835,21 @@ packages:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
/@sveltejs/vite-plugin-svelte-inspector@1.0.4(@sveltejs/vite-plugin-svelte@2.5.2)(svelte@4.2.2)(vite@4.5.0):
|
||||
resolution: {integrity: sha512-zjiuZ3yydBtwpF3bj0kQNV0YXe+iKE545QGZVTaylW3eAzFr+pJ/cwK8lZEaRp4JtaJXhD5DyWAV4AxLh6DgaQ==}
|
||||
engines: {node: ^14.18.0 || >= 16}
|
||||
peerDependencies:
|
||||
'@sveltejs/vite-plugin-svelte': ^2.2.0
|
||||
svelte: ^3.54.0 || ^4.0.0
|
||||
vite: ^4.0.0
|
||||
dependencies:
|
||||
'@sveltejs/vite-plugin-svelte': 2.5.2(svelte@4.2.2)(vite@4.5.0)
|
||||
debug: 4.3.4
|
||||
svelte: 4.2.2
|
||||
vite: 4.5.0(@types/node@20.3.2)(less@4.2.0)(lightningcss@1.21.7)(sass@1.66.1)(stylus@0.62.0)(sugarss@4.0.1)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
/@sveltejs/vite-plugin-svelte-inspector@1.0.4(@sveltejs/vite-plugin-svelte@2.5.2)(svelte@4.2.3)(vite@4.5.0):
|
||||
resolution: {integrity: sha512-zjiuZ3yydBtwpF3bj0kQNV0YXe+iKE545QGZVTaylW3eAzFr+pJ/cwK8lZEaRp4JtaJXhD5DyWAV4AxLh6DgaQ==}
|
||||
engines: {node: ^14.18.0 || >= 16}
|
||||
@ -6849,6 +6864,7 @@ packages:
|
||||
vite: 4.5.0(@types/node@20.3.2)(less@4.2.0)(lightningcss@1.21.7)(sass@1.66.1)(stylus@0.62.0)(sugarss@4.0.1)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/@sveltejs/vite-plugin-svelte@2.5.2(svelte@4.2.2)(vite@4.3.9):
|
||||
resolution: {integrity: sha512-Dfy0Rbl+IctOVfJvWGxrX/3m6vxPLH8o0x+8FA5QEyMUQMo4kGOVIojjryU7YomBAexOTAuYf1RT7809yDziaA==}
|
||||
@ -6869,6 +6885,25 @@ packages:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
/@sveltejs/vite-plugin-svelte@2.5.2(svelte@4.2.2)(vite@4.5.0):
|
||||
resolution: {integrity: sha512-Dfy0Rbl+IctOVfJvWGxrX/3m6vxPLH8o0x+8FA5QEyMUQMo4kGOVIojjryU7YomBAexOTAuYf1RT7809yDziaA==}
|
||||
engines: {node: ^14.18.0 || >= 16}
|
||||
peerDependencies:
|
||||
svelte: ^3.54.0 || ^4.0.0 || ^5.0.0-next.0
|
||||
vite: ^4.0.0
|
||||
dependencies:
|
||||
'@sveltejs/vite-plugin-svelte-inspector': 1.0.4(@sveltejs/vite-plugin-svelte@2.5.2)(svelte@4.2.2)(vite@4.5.0)
|
||||
debug: 4.3.4
|
||||
deepmerge: 4.3.1
|
||||
kleur: 4.1.5
|
||||
magic-string: 0.30.5
|
||||
svelte: 4.2.2
|
||||
svelte-hmr: 0.15.3(svelte@4.2.2)
|
||||
vite: 4.5.0(@types/node@20.3.2)(less@4.2.0)(lightningcss@1.21.7)(sass@1.66.1)(stylus@0.62.0)(sugarss@4.0.1)
|
||||
vitefu: 0.2.5(vite@4.5.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
/@sveltejs/vite-plugin-svelte@2.5.2(svelte@4.2.3)(vite@4.5.0):
|
||||
resolution: {integrity: sha512-Dfy0Rbl+IctOVfJvWGxrX/3m6vxPLH8o0x+8FA5QEyMUQMo4kGOVIojjryU7YomBAexOTAuYf1RT7809yDziaA==}
|
||||
engines: {node: ^14.18.0 || >= 16}
|
||||
@ -6887,6 +6922,7 @@ packages:
|
||||
vitefu: 0.2.5(vite@4.5.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/@tailwindcss/forms@0.5.0(tailwindcss@3.1.6):
|
||||
resolution: {integrity: sha512-KzWugryEBFkmoaYcBE18rs6gthWCFHHO7cAZm2/hv3hwD67AzwP7udSCa22E7R1+CEJL/FfhYsJWrc0b1aeSzw==}
|
||||
@ -12105,7 +12141,7 @@ packages:
|
||||
/mdn-data@2.0.30:
|
||||
resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==}
|
||||
|
||||
/mdsvex@0.11.0(svelte@4.2.3):
|
||||
/mdsvex@0.11.0(svelte@4.2.2):
|
||||
resolution: {integrity: sha512-gJF1s0N2nCmdxcKn8HDn0LKrN8poStqAicp6bBcsKFd/zkUBGLP5e7vnxu+g0pjBbDFOscUyI1mtHz+YK2TCDw==}
|
||||
peerDependencies:
|
||||
svelte: '>=3 <5'
|
||||
@ -12113,7 +12149,7 @@ packages:
|
||||
'@types/unist': 2.0.10
|
||||
prism-svelte: 0.4.7
|
||||
prismjs: 1.29.0
|
||||
svelte: 4.2.3
|
||||
svelte: 4.2.2
|
||||
vfile-message: 2.0.4
|
||||
dev: false
|
||||
|
||||
@ -13239,17 +13275,6 @@ packages:
|
||||
dependencies:
|
||||
prettier: 3.0.0
|
||||
svelte: 4.2.2
|
||||
dev: false
|
||||
|
||||
/prettier-plugin-svelte@3.0.0(prettier@3.0.0)(svelte@4.2.3):
|
||||
resolution: {integrity: sha512-l3RQcPty2UBCoRh3yb9c5XCAmxkrc4BptAnbd5acO1gmSJtChOWkiEjnOvh7hvmtT4V80S8gXCOKAq8RNeIzSw==}
|
||||
peerDependencies:
|
||||
prettier: ^3.0.0
|
||||
svelte: ^3.2.0 || ^4.0.0-next.0
|
||||
dependencies:
|
||||
prettier: 3.0.0
|
||||
svelte: 4.2.3
|
||||
dev: true
|
||||
|
||||
/prettier@2.8.8:
|
||||
resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==}
|
||||
@ -14603,34 +14628,6 @@ packages:
|
||||
- sass
|
||||
- stylus
|
||||
- sugarss
|
||||
dev: false
|
||||
|
||||
/svelte-check@3.4.4(@babel/core@7.23.3)(less@4.2.0)(postcss@8.4.27)(svelte@4.2.3):
|
||||
resolution: {integrity: sha512-Uys9+R65cj8TmP8f5UpS7B2xKpNLYNxEWJsA5ZoKcWq/uwvABFF7xS6iPQGLoa7hxz0DS6xU60YFpmq06E4JxA==}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
svelte: ^3.55.0 || ^4.0.0-next.0 || ^4.0.0
|
||||
dependencies:
|
||||
'@jridgewell/trace-mapping': 0.3.20
|
||||
chokidar: 3.5.3
|
||||
fast-glob: 3.3.2
|
||||
import-fresh: 3.3.0
|
||||
picocolors: 1.0.0
|
||||
sade: 1.8.1
|
||||
svelte: 4.2.3
|
||||
svelte-preprocess: 5.0.4(@babel/core@7.23.3)(less@4.2.0)(postcss@8.4.27)(svelte@4.2.3)(typescript@5.2.2)
|
||||
typescript: 5.2.2
|
||||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
- coffeescript
|
||||
- less
|
||||
- postcss
|
||||
- postcss-load-config
|
||||
- pug
|
||||
- sass
|
||||
- stylus
|
||||
- sugarss
|
||||
dev: true
|
||||
|
||||
/svelte-eslint-parser@0.32.2(svelte@4.2.2):
|
||||
resolution: {integrity: sha512-Ok9D3A4b23iLQsONrjqtXtYDu5ZZ/826Blaw2LeFZVTg1pwofKDG4mz3/GYTax8fQ0plRGHI6j+d9VQYy5Lo/A==}
|
||||
@ -14795,57 +14792,6 @@ packages:
|
||||
strip-indent: 3.0.0
|
||||
svelte: 4.2.2
|
||||
typescript: 5.2.2
|
||||
dev: false
|
||||
|
||||
/svelte-preprocess@5.0.4(@babel/core@7.23.3)(less@4.2.0)(postcss@8.4.27)(svelte@4.2.3)(typescript@5.2.2):
|
||||
resolution: {integrity: sha512-ABia2QegosxOGsVlsSBJvoWeXy1wUKSfF7SWJdTjLAbx/Y3SrVevvvbFNQqrSJw89+lNSsM58SipmZJ5SRi5iw==}
|
||||
engines: {node: '>= 14.10.0'}
|
||||
requiresBuild: true
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.10.2
|
||||
coffeescript: ^2.5.1
|
||||
less: ^3.11.3 || ^4.0.0
|
||||
postcss: ^7 || ^8
|
||||
postcss-load-config: ^2.1.0 || ^3.0.0 || ^4.0.0
|
||||
pug: ^3.0.0
|
||||
sass: ^1.26.8
|
||||
stylus: ^0.55.0
|
||||
sugarss: ^2.0.0 || ^3.0.0 || ^4.0.0
|
||||
svelte: ^3.23.0 || ^4.0.0-next.0 || ^4.0.0
|
||||
typescript: '>=3.9.5 || ^4.0.0 || ^5.0.0'
|
||||
peerDependenciesMeta:
|
||||
'@babel/core':
|
||||
optional: true
|
||||
coffeescript:
|
||||
optional: true
|
||||
less:
|
||||
optional: true
|
||||
postcss:
|
||||
optional: true
|
||||
postcss-load-config:
|
||||
optional: true
|
||||
pug:
|
||||
optional: true
|
||||
sass:
|
||||
optional: true
|
||||
stylus:
|
||||
optional: true
|
||||
sugarss:
|
||||
optional: true
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/core': 7.23.3
|
||||
'@types/pug': 2.0.9
|
||||
detect-indent: 6.1.0
|
||||
less: 4.2.0
|
||||
magic-string: 0.27.0
|
||||
postcss: 8.4.27
|
||||
sorcery: 0.11.0
|
||||
strip-indent: 3.0.0
|
||||
svelte: 4.2.3
|
||||
typescript: 5.2.2
|
||||
dev: true
|
||||
|
||||
/svelte-range-slider-pips@2.0.1:
|
||||
resolution: {integrity: sha512-sCHvcTgi0ZYE4c/mwSsdALRsfuqEmpwTsSUdL+PUrumZ8u2gv1GKwZ3GohcAcTB6gfmqRBkyn6ujRXrOIga1gw==}
|
||||
|
@ -141,6 +141,7 @@ pytest==7.1.2
|
||||
# -r requirements.in
|
||||
# pytest-asyncio
|
||||
# pytest-cov
|
||||
pytest-virtualenv==1.7.0
|
||||
pytest-asyncio==0.19.0
|
||||
# via -r requirements.in
|
||||
pytest-cov==3.0.0
|
||||
|
@ -1,12 +1,11 @@
|
||||
import shutil
|
||||
import textwrap
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from gradio.cli.commands.components._create_utils import OVERRIDES
|
||||
from gradio.cli.commands.components.build import _build
|
||||
from gradio.cli.commands.components.create import _create
|
||||
from gradio.cli.commands.components.install_component import _install
|
||||
from gradio.cli.commands.components.publish import _get_version_from_file
|
||||
from gradio.cli.commands.components.show import _show
|
||||
|
||||
@ -107,38 +106,44 @@ def test_show(capsys):
|
||||
|
||||
|
||||
@pytest.mark.xfail
|
||||
@pytest.mark.parametrize("template", ["Audio", "Video", "Image", "Textbox"])
|
||||
def test_build(template, tmp_path):
|
||||
_create(
|
||||
"TestTextbox",
|
||||
template=template,
|
||||
directory=tmp_path,
|
||||
overwrite=True,
|
||||
install=True,
|
||||
configure_metadata=False,
|
||||
)
|
||||
_build(tmp_path, build_frontend=True)
|
||||
template_dir: Path = (
|
||||
tmp_path.resolve() / "backend" / "gradio_testtextbox" / "templates"
|
||||
)
|
||||
assert template_dir.exists() and template_dir.is_dir()
|
||||
assert list(template_dir.glob("**/index.js"))
|
||||
assert (tmp_path / "dist").exists() and list((tmp_path / "dist").glob("*.whl"))
|
||||
@pytest.mark.parametrize("template", ["Image"])
|
||||
def test_build(template, virtualenv):
|
||||
# Copy pnpm-lock.yaml to not cause unintended changes tracked by git
|
||||
pnpm_lock = Path(__file__).parent / ".." / "pnpm-lock.yaml"
|
||||
pnpm_copy = Path(__file__).parent / ".." / "pnpm-lock-copy.yaml"
|
||||
shutil.copy(str(pnpm_lock), str(pnpm_copy))
|
||||
|
||||
# Using the js/preview/test directory will use the workspace code
|
||||
dir_ = (
|
||||
Path(__file__).parent / ".." / "js" / "preview" / "test" / "testtextbox"
|
||||
).resolve()
|
||||
shutil.rmtree(str(dir_), ignore_errors=True)
|
||||
|
||||
def test_install(tmp_path):
|
||||
_create(
|
||||
"TestTextbox",
|
||||
template="Textbox",
|
||||
directory=tmp_path,
|
||||
overwrite=True,
|
||||
install=False,
|
||||
configure_metadata=False,
|
||||
)
|
||||
try:
|
||||
# Local installs of gradio and gradio-client
|
||||
gradio_dir = Path(__file__).parent / ".."
|
||||
client = Path(__file__).parent / ".." / "client" / "python"
|
||||
virtualenv.run("pip install build")
|
||||
virtualenv.run(f"pip install -e {str(gradio_dir)}")
|
||||
virtualenv.run(f"pip install -e {str(client)}")
|
||||
|
||||
assert not (tmp_path / "frontend" / "node_modules").exists()
|
||||
_install(tmp_path)
|
||||
assert (tmp_path / "frontend" / "node_modules").exists()
|
||||
virtualenv.run(
|
||||
f"{shutil.which('gradio')} cc create TestTextbox --template {template} --no-configure-metadata --directory {str(dir_)}",
|
||||
)
|
||||
assert (dir_ / "frontend" / "node_modules").exists()
|
||||
|
||||
# need to reinstall local client because installing the custom component
|
||||
# will pull latest stable version from pypi
|
||||
virtualenv.run(f"pip install -e {str(client)}")
|
||||
virtualenv.run(f"{shutil.which('gradio')} cc build {str(dir_)}")
|
||||
|
||||
template_dir: Path = dir_ / "backend" / "gradio_testtextbox" / "templates"
|
||||
assert template_dir.exists() and template_dir.is_dir()
|
||||
assert list(template_dir.glob("**/index.js"))
|
||||
assert (dir_ / "dist").exists() and list((dir_ / "dist").glob("*.whl"))
|
||||
finally:
|
||||
shutil.move(str(pnpm_copy), str(pnpm_lock))
|
||||
shutil.rmtree(str(dir_), ignore_errors=True)
|
||||
|
||||
|
||||
def test_fallback_template_app(tmp_path):
|
||||
|
Loading…
x
Reference in New Issue
Block a user