Skip to content

Commit

Permalink
Fix flaky CI tests (again 😓 ) (#6780)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
3 people authored Dec 14, 2023
1 parent a807ede commit 51e241a
Show file tree
Hide file tree
Showing 15 changed files with 195 additions and 287 deletions.
5 changes: 5 additions & 0 deletions .changeset/social-dancers-yawn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"gradio": patch
---

fix:Fix flaky CI tests (again 😓 )
11 changes: 8 additions & 3 deletions .config/playwright.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export default {
import { defineConfig } from "@playwright/test";

export default defineConfig({
use: {
screenshot: "only-on-failure",
trace: "retain-on-failure",
Expand All @@ -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 changes: 1 addition & 1 deletion .github/workflows/ui.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
4 changes: 2 additions & 2 deletions gradio/cli/commands/components/_create_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@


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 = """
Expand Down
3 changes: 1 addition & 2 deletions gradio/cli/commands/components/build.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import shutil
import subprocess
import sys
from pathlib import Path

import semantic_version
Expand Down Expand Up @@ -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:
Expand Down
8 changes: 3 additions & 5 deletions gradio/cli/commands/components/publish.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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)
Expand Down
51 changes: 18 additions & 33 deletions js/app/test/audio_component_events.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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");
Expand All @@ -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");
});
Expand All @@ -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 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);
};

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();

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 expect(async () => event_triggered("# Output Play Events")).toPass();
await expect(async () => event_triggered("# Output Pause Events")).toPass();
await expect(async () => event_triggered("# Output Stop Events")).toPass();
});
25 changes: 2 additions & 23 deletions js/app/test/chatinterface_streaming_echo.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
60 changes: 26 additions & 34 deletions js/app/test/image_component_events.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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");
});
Expand All @@ -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");
});
24 changes: 12 additions & 12 deletions js/app/test/model3d_component_events.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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");
});
Loading

0 comments on commit 51e241a

Please sign in to comment.