Repository: gradio-app/gradio

Issue:
move component files into cleaner folder structure
first part of #3360.


Discussion:

Resolving patch:
diff --git a/demo/clear_components/run.py b/demo/clear_components/run.py
--- a/demo/clear_components/run.py
+++ b/demo/clear_components/run.py
@@ -7,13 +7,12 @@
 
 import numpy as np
 import matplotlib.pyplot as plt
-import random
-import os
+
 
 
 def random_plot():
     start_year = 2020
-    x = np.arange(start_year, start_year + random.randint(0, 10))
+    x = np.arange(start_year, start_year + 5)
     year_count = x.shape[0]
     plt_format = "-"
     fig = plt.figure()
@@ -115,7 +114,7 @@ def random_model3d():
         )
     ),
     gr.Dataframe(
-        value=lambda: pd.DataFrame({"random_number_rows": range(random.randint(0, 10))})
+        value=lambda: pd.DataFrame({"random_number_rows": range(5)}, columns=["one", "two", "three"])
     ),
     gr.Timeseries(value=lambda: os.path.join(file_dir, "time.csv")),
     gr.ColorPicker(value=lambda: random.choice(["#000000", "#ff0000", "#0000FF"])),


Test patch:
diff --git a/js/app/src/components/Audio/Audio.test.ts b/js/app/src/components/Audio/Audio.test.ts
deleted file mode 100644
--- a/js/app/src/components/Audio/Audio.test.ts
+++ /dev/null
@@ -1,352 +0,0 @@
-import { test, describe, assert, afterEach, vi, beforeAll } from "vitest";
-import { spy, spyOn } from "tinyspy";
-import { cleanup, render, wait_for_event, wait } from "@gradio/tootils";
-import event from "@testing-library/user-event";
-import { setupi18n } from "../../i18n";
-import { tick } from "svelte";
-
-import Audio from "./Audio.svelte";
-import type { LoadingStatus } from "../StatusTracker/types";
-
-const loading_status = {
-	eta: 0,
-	queue_position: 1,
-	queue_size: 1,
-	status: "complete" as LoadingStatus["status"],
-	scroll_to_output: false,
-	visible: true,
-	fn_index: 0,
-	show_progress: "full" as LoadingStatus["show_progress"]
-};
-
-describe("Audio", () => {
-	beforeAll(() => {
-		window.HTMLMediaElement.prototype.play = vi.fn();
-		window.HTMLMediaElement.prototype.pause = vi.fn();
-	});
-	afterEach(() => cleanup());
-
-	test("renders provided value and label", async () => {
-		const { getByTestId, queryAllByText } = await render(Audio, {
-			show_label: true,
-			loading_status,
-			mode: "dynamic",
-			value: {
-				name: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav",
-				data: null,
-				is_file: true
-			},
-			label: "Audio Component",
-			root: "foo",
-			root_url: null,
-			streaming: false,
-			pending: false,
-			name: "bar",
-			source: "upload"
-		});
-
-		assert.isTrue(
-			getByTestId("Audio Component-audio").src.endsWith(
-				"foo/file=https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav"
-			)
-		);
-		assert(queryAllByText("Audio Component").length, 1);
-	});
-
-	test("hides label", async () => {
-		const { queryAllByText } = await render(Audio, {
-			show_label: false,
-			loading_status,
-			mode: "dynamic",
-			value: {
-				name: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav",
-				data: null,
-				is_file: true
-			},
-			label: "Audio Component",
-			root: "foo",
-			root_url: null,
-			streaming: false,
-			pending: false,
-			name: "bar",
-			source: "upload"
-		});
-
-		assert(queryAllByText("Audio Component").length, 0);
-	});
-
-	test("upload sets change event", async () => {
-		setupi18n();
-		const { container, component } = await render(Audio, {
-			show_label: false,
-			loading_status,
-			value: null,
-			mode: "dynamic",
-			label: "audio",
-			root: "foo",
-			root_url: null,
-			streaming: false,
-			name: "bar",
-			source: "upload"
-		});
-
-		const item = container.querySelectorAll("input")[0];
-		const file = new File(["hello"], "my-audio.wav", { type: "audio/wav" });
-		event.upload(item, file);
-		const mock = await wait_for_event(component, "change");
-		assert.equal(mock.callCount, 1);
-		assert.equal(
-			component.$capture_state().value.data,
-			"data:audio/wav;base64,aGVsbG8="
-		);
-		assert.equal(component.$capture_state().value.name, "my-audio.wav");
-	});
-
-	test("static audio sets value", async () => {
-		const { getByTestId } = await render(Audio, {
-			show_label: true,
-			loading_status,
-			mode: "static",
-			value: {
-				name: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav",
-				data: null,
-				is_file: true
-			},
-			label: "Audio Component",
-			root: "foo",
-			root_url: null,
-			streaming: false,
-			pending: false,
-			name: "bar",
-			source: "upload"
-		});
-
-		assert.isTrue(
-			getByTestId("Audio Component-audio").src.endsWith(
-				"foo/file=https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav"
-			)
-		);
-	});
-
-	test("stop recording sets data", async () => {
-		let data_event;
-		let stop_event;
-
-		const media_recorder_mock = vi.fn((s, x) => {
-			return {
-				start: vi.fn(() => {
-					data_event({ data: "hello" });
-					data_event({ data: "hello" });
-					data_event({ data: "hello" });
-					data_event({ data: "hello" });
-				}),
-				stop: vi.fn(async () => {
-					await stop_event();
-				}),
-				addEventListener: vi.fn((evt, cb) => {
-					if (evt === "dataavailable") {
-						data_event = cb;
-					}
-
-					if (evt === "stop") {
-						stop_event = cb;
-					}
-				})
-			};
-		});
-
-		const media_mock = {
-			mediaDevices: {
-				getUserMedia: vi.fn(() => Promise.resolve(true))
-			}
-		};
-
-		vi.stubGlobal("navigator", media_mock);
-		vi.stubGlobal("MediaRecorder", media_recorder_mock);
-
-		const { component, getByText } = await render(Audio, {
-			show_label: true,
-			loading_status,
-			mode: "dynamic",
-			value: null,
-			label: "Audio Component",
-			root: "foo",
-			root_url: null,
-			streaming: false,
-			pending: false,
-			source: "microphone",
-			name: "bar"
-		});
-
-		const startButton = getByText("Record from microphone");
-		await event.click(startButton);
-		const stopButton = getByText("Stop recording");
-		await event.click(stopButton);
-		const mock = await wait_for_event(component, "stop_recording");
-
-		assert.equal(
-			component.$capture_state().value.data,
-			"data:audio/wav;base64,aGVsbG9oZWxsb2hlbGxvaGVsbG8="
-		);
-		assert.equal(component.$capture_state().value.name, "audio.wav");
-		assert.equal(mock.callCount, 1);
-	});
-
-	test("when autoplay is true `media.play` should be called in static mode", async () => {
-		const { getByTestId } = await render(Audio, {
-			show_label: true,
-			loading_status,
-			mode: "static",
-			value: {
-				name: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav",
-				data: null,
-				is_file: true
-			},
-			label: "static",
-			root: "foo",
-			root_url: null,
-			streaming: false,
-			pending: false,
-			source: "microphone",
-			autoplay: true
-		});
-
-		const startButton = getByTestId<HTMLAudioElement>("static-audio");
-		const fn = spyOn(startButton, "play");
-		startButton.dispatchEvent(new Event("loadeddata"));
-
-		assert.equal(fn.callCount, 1);
-	});
-
-	test("when autoplay is true `media.play` should be called in dynamic mode", async () => {
-		const { getByTestId } = await render(Audio, {
-			show_label: true,
-			loading_status,
-			mode: "dynamic",
-			value: {
-				name: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav",
-				data: null,
-				is_file: true
-			},
-			label: "dynamic",
-			root: "foo",
-			root_url: null,
-			streaming: false,
-			pending: false,
-			source: "microphone",
-			autoplay: true
-		});
-
-		const startButton = getByTestId<HTMLAudioElement>("dynamic-audio");
-		const fn = spyOn(startButton, "play");
-		startButton.dispatchEvent(new Event("loadeddata"));
-
-		assert.equal(fn.callCount, 1);
-	});
-
-	test("when autoplay is true `media.play` should be called in static mode when the audio data is updated", async () => {
-		const { component, getByTestId } = await render(Audio, {
-			show_label: true,
-			loading_status,
-			mode: "static",
-			value: {
-				name: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav",
-				data: null,
-				is_file: true
-			},
-			label: "static",
-			root: "foo",
-			root_url: null,
-			streaming: false,
-			pending: false,
-			source: "microphone",
-			autoplay: true
-		});
-
-		const startButton = getByTestId<HTMLAudioElement>("static-audio");
-		const fn = spyOn(startButton, "play");
-
-		startButton.dispatchEvent(new Event("loadeddata"));
-
-		component.$set({
-			value: {
-				name: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav",
-				data: null,
-				is_file: true
-			}
-		});
-
-		startButton.dispatchEvent(new Event("loadeddata"));
-
-		assert.equal(fn.callCount, 2);
-	});
-
-	test("when autoplay is true `media.play` should be called in dynamic mode when the audio data is updated", async () => {
-		const { component, getByTestId } = await render(Audio, {
-			show_label: true,
-			loading_status,
-			mode: "dynamic",
-			value: {
-				name: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav",
-				data: null,
-				is_file: true
-			},
-			label: "dynamic",
-			root: "foo",
-			root_url: null,
-			streaming: false,
-			pending: false,
-			source: "microphone",
-			autoplay: true
-		});
-
-		const startButton = getByTestId<HTMLAudioElement>("dynamic-audio");
-		const fn = spyOn(startButton, "play");
-
-		startButton.dispatchEvent(new Event("loadeddata"));
-
-		component.$set({
-			value: {
-				name: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav",
-				data: null,
-				is_file: true
-			}
-		});
-
-		startButton.dispatchEvent(new Event("loadeddata"));
-
-		assert.equal(fn.callCount, 2);
-	});
-
-	test("audio change event trigger fires when value is changed and only fires once", async () => {
-		const { component } = await render(Audio, {
-			show_label: true,
-			loading_status,
-			mode: "static",
-			value: {
-				name: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav",
-				data: null,
-				is_file: true
-			},
-			label: "static",
-			root: "foo",
-			root_url: null,
-			streaming: false,
-			pending: false,
-			source: "microphone",
-			autoplay: true
-		});
-
-		const mock = spy();
-		component.$on("change", mock);
-
-		(component.value = [
-			{
-				name: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample2.wav",
-				data: null,
-				is_file: true
-			}
-		]),
-			assert.equal(mock.callCount, 1);
-	});
-});
diff --git a/js/app/src/components/Button/Button.test.ts b/js/app/src/components/Button/Button.test.ts
deleted file mode 100644
--- a/js/app/src/components/Button/Button.test.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import { test, describe, assert, afterEach } from "vitest";
-import { spy } from "tinyspy";
-import { cleanup, fireEvent, render } from "@gradio/tootils";
-
-import Button from "./Button.svelte";
-
-describe("Hello.svelte", () => {
-	afterEach(() => cleanup());
-
-	test.skip("renders label text", async () => {
-		const { container, component } = await render(Button, {
-			value: "Click Me"
-		});
-		assert.equal(container.innerText, "Click Me");
-	});
-
-	test.skip("triggers callback when clicked", async () => {
-		const { container, component } = await render(Button, {
-			value: "Click Me"
-		});
-		const mock = spy();
-		component.$on("click", mock);
-
-		fireEvent.click(container.querySelector("button")!);
-
-		assert.isTrue(mock.called);
-	});
-});
diff --git a/js/app/src/components/ColorPicker/ColorPicker.test.ts b/js/app/src/components/ColorPicker/ColorPicker.test.ts
deleted file mode 100644
--- a/js/app/src/components/ColorPicker/ColorPicker.test.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-import { test, describe, assert, afterEach } from "vitest";
-import { cleanup, render } from "@gradio/tootils";
-
-import ColorPicker from "./ColorPicker.svelte";
-import type { LoadingStatus } from "../StatusTracker/types";
-
-const loading_status = {
-	eta: 0,
-	queue_position: 1,
-	queue_size: 1,
-	status: "complete" as LoadingStatus["status"],
-	scroll_to_output: false,
-	visible: true,
-	fn_index: 0
-};
-
-describe("ColorPicker", () => {
-	afterEach(() => cleanup());
-
-	test("renders provided value", async () => {
-		const { getByDisplayValue } = await render(ColorPicker, {
-			loading_status,
-			show_label: true,
-			mode: "dynamic",
-			value: "#000000",
-			label: "ColorPicker"
-		});
-
-		const item: HTMLInputElement = getByDisplayValue("#000000");
-		assert.equal(item.value, "#000000");
-	});
-
-	test("changing the color should update the value", async () => {
-		const { component, getByDisplayValue } = await render(ColorPicker, {
-			loading_status,
-			show_label: true,
-			mode: "dynamic",
-			value: "#000000",
-			label: "ColorPicker"
-		});
-
-		const item: HTMLInputElement = getByDisplayValue("#000000");
-
-		assert.equal(item.value, "#000000");
-
-		await component.$set({
-			value: "#FFFFFF"
-		});
-
-		assert.equal(component.value, "#FFFFFF");
-	});
-});
diff --git a/js/app/src/components/File/File.test.ts b/js/app/src/components/File/File.test.ts
deleted file mode 100644
--- a/js/app/src/components/File/File.test.ts
+++ /dev/null
@@ -1,76 +0,0 @@
-import { test, describe, expect, afterEach, vi, assert } from "vitest";
-import { cleanup, render } from "@gradio/tootils";
-import { spy } from "tinyspy";
-
-import File from "./File.svelte";
-import type { LoadingStatus } from "../StatusTracker/types";
-import { upload_files } from "@gradio/client";
-
-const loading_status = {
-	eta: 0,
-	queue_position: 1,
-	queue_size: 1,
-	status: "complete" as LoadingStatus["status"],
-	scroll_to_output: false,
-	visible: true,
-	fn_index: 0
-};
-
-describe("File", () => {
-	afterEach(() => {
-		cleanup();
-		vi.restoreAllMocks();
-	});
-
-	test("gr.File uploads with blob", async () => {
-		vi.mock("@gradio/client", async () => {
-			return {
-				upload_files: vi.fn((f) => new Promise((res) => res({})))
-			};
-		});
-
-		const api = await import("@gradio/client");
-
-		await render(File, {
-			loading_status,
-			label: "file",
-			// @ts-ignore
-			value: { name: "freddy.json", data: "{'name': 'freddy'}", blob: vi.fn() },
-			show_label: true,
-			mode: "dynamic",
-			root: "http://localhost:7860",
-			file_count: "1",
-			root_url: null
-		});
-
-		expect(api.upload_files).toHaveBeenCalled();
-	});
-
-	test("gr.File does not upload without blob", async () => {
-		const mockUpload = vi.fn(upload_files);
-
-		const { component } = await render(File, {
-			loading_status,
-			label: "file",
-			value: { name: "freddy.json", data: "{'name': 'freddy'}" },
-			show_label: true,
-			mode: "dynamic",
-			root: "http://localhost:7860",
-			file_count: "1",
-			root_url: null
-		});
-
-		expect(mockUpload).not.toHaveBeenCalled();
-
-		const mock = spy();
-		component.$on("change", mock);
-
-		component.value = {
-			name: "freddy_2.json",
-			data: "{'name': 'freddy'}",
-			is_file: true
-		};
-
-		assert.equal(mock.callCount, 1);
-	});
-});
diff --git a/js/app/src/components/Gallery/Gallery.test.ts b/js/app/src/components/Gallery/Gallery.test.ts
deleted file mode 100644
--- a/js/app/src/components/Gallery/Gallery.test.ts
+++ /dev/null
@@ -1,104 +0,0 @@
-import { test, describe, assert, afterEach, vi } from "vitest";
-import { cleanup, render } from "@gradio/tootils";
-
-import Gallery from "./Gallery.svelte";
-import type { LoadingStatus } from "../StatusTracker/types";
-
-const loading_status: LoadingStatus = {
-	eta: 0,
-	queue_position: 1,
-	queue_size: 1,
-	status: "complete",
-	scroll_to_output: false,
-	visible: true,
-	fn_index: 0,
-	show_progress: "full"
-};
-
-describe("Gallery", () => {
-	afterEach(() => {
-		cleanup();
-		vi.restoreAllMocks();
-	});
-
-	test("preview shows detailed image by default", async () => {
-		window.Element.prototype.scrollTo = vi.fn(() => {});
-
-		const { getAllByTestId, getByTestId } = await render(Gallery, {
-			loading_status,
-			label: "gallery",
-			// @ts-ignore
-			value: [
-				[
-					{
-						name: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80",
-						data: null,
-						is_file: true
-					},
-					"label 0"
-				],
-				[
-					{
-						name: "https://images.unsplash.com/photo-1542909168-82c3e7fdca5c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8aHVtYW4lMjBmYWNlfGVufDB8fDB8fA%3D%3D&w=1000&q=80",
-						data: null,
-						is_file: true
-					},
-					"label 1"
-				]
-			],
-			show_label: true,
-			mode: "dynamic",
-			root: "http://localhost:7860",
-			root_url: null,
-			preview: true
-		});
-
-		const details = getAllByTestId("detailed-image");
-
-		assert.equal(details.length, 1);
-	});
-
-	test("detailed view does not show larger image", async () => {
-		const { queryAllByTestId, getByTestId } = await render(Gallery, {
-			loading_status,
-			label: "gallery",
-			// @ts-ignore
-			value: [
-				[
-					{
-						name: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80",
-						data: null,
-						is_file: true
-					},
-					"label 0"
-				],
-				[
-					{
-						name: "https://images.unsplash.com/photo-1542909168-82c3e7fdca5c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8aHVtYW4lMjBmYWNlfGVufDB8fDB8fA%3D%3D&w=1000&q=80",
-						data: null,
-						is_file: true
-					},
-					"label 1"
-				],
-				[
-					{
-						name: "https://images.unsplash.com/photo-1601412436009-d964bd02edbc?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=464&q=80",
-						data: null,
-						is_file: true
-					},
-					"label 2"
-				]
-			],
-			show_label: true,
-			mode: "dynamic",
-			root: "http://localhost:7860",
-			root_url: null,
-			preview: true,
-			allow_preview: false
-		});
-
-		const details = queryAllByTestId("detailed-image");
-
-		assert.equal(details.length, 0);
-	});
-});
diff --git a/js/app/test/chatinterface_streaming_echo.spec.ts b/js/app/test/chatinterface_streaming_echo.spec.ts
--- a/js/app/test/chatinterface_streaming_echo.spec.ts
+++ b/js/app/test/chatinterface_streaming_echo.spec.ts
@@ -9,47 +9,52 @@ test("chatinterface works with streaming functions and all buttons behave as exp
 	const clear_button = await page.locator("button").nth(4);
 	const textbox = await page.getByTestId("textbox").nth(0);
 
-	let last_iteration;
+	let iterations: Promise<any>[] = [];
 	page.on("websocket", (ws) => {
-		last_iteration = ws.waitForEvent("framereceived", {
-			predicate: (event) => {
-				return JSON.parse(event.payload as string).msg === "process_completed";
-			}
-		});
+		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 last_iteration;
+	await iterations[0];
 	await expect(textbox).toHaveValue("");
-	await expect.poll(async () => page.locator('.bot.message p').count()).toBe(1);
+	await expect.poll(async () => page.locator(".bot.message p").count()).toBe(1);
 	const bot_message_0 = await page.locator(".bot.message p").nth(0);
-	await expect(bot_message_0).toContainText("You typed: hello"); 
+	await expect(bot_message_0).toContainText("You typed: hello");
 
 	await textbox.fill("hi");
 	await submit_button.click();
-	await last_iteration;	
+	await iterations[1];
 	await expect(textbox).toHaveValue("");
-	await expect.poll(async () => page.locator('.bot.message p').count()).toBe(2);
+	await expect.poll(async () => page.locator(".bot.message p").count()).toBe(2);
 	const bot_message_1 = await page.locator(".bot.message p").nth(1);
-	await expect(bot_message_1).toContainText("You typed: hi"); 
+	await expect(bot_message_1).toContainText("You typed: hi");
 
 	await retry_button.click();
-	await last_iteration;
+	await iterations[2];
 	await expect(textbox).toHaveValue("");
-	await expect(bot_message_1).toContainText("You typed: hi"); 
+	await expect(bot_message_1).toContainText("You typed: hi");
 
 	await undo_button.click();
-	await expect.poll(async () => page.locator('.bot.message p').count()).toBe(1);
+	await iterations[3];
+	await expect.poll(async () => page.locator(".bot.message p").count()).toBe(1);
 	await expect(textbox).toHaveValue("hi");
 
 	await textbox.fill("salaam");
 	await submit_button.click();
-	await last_iteration;	
+	await iterations[4];
 	await expect(textbox).toHaveValue("");
-	await expect.poll(async () => page.locator('.bot.message p').count()).toBe(2);
-	await expect(bot_message_1).toContainText("You typed: salaam"); 
+	await expect.poll(async () => page.locator(".bot.message p").count()).toBe(2);
+	await expect(bot_message_1).toContainText("You typed: salaam");
 
 	await clear_button.click();
-	await expect.poll(async () => page.locator('.bot.message p').count()).toBe(0);
+	await expect.poll(async () => page.locator(".bot.message p").count()).toBe(0);
 });
diff --git a/js/app/test/components.test.ts b/js/app/test/components.test.ts
--- a/js/app/test/components.test.ts
+++ b/js/app/test/components.test.ts
@@ -10,30 +10,30 @@ import {
 import { render, cleanup } from "@gradio/tootils";
 import { setupi18n } from "../src/i18n";
 
-import AnnotatedImage from "../src/components/AnnotatedImage/AnnotatedImage.svelte";
-import Audio from "../src/components/Audio/Audio.svelte";
+import AnnotatedImage from "@gradio/annotatedimage";
+import Audio from "@gradio/audio";
 import Chatbot from "@gradio/chatbot";
-import Checkbox from "../src/components/Checkbox/Checkbox.svelte";
-import CheckboxGroup from "../src/components/CheckboxGroup/CheckboxGroup.svelte";
-import ColorPicker from "../src/components/ColorPicker/ColorPicker.svelte";
-import DataFrame from "../src/components/DataFrame/DataFrame.svelte";
-import Dropdown from "../src/components/Dropdown/Dropdown.svelte";
-import File from "../src/components/File/File.svelte";
-import Gallery from "../src/components/Gallery/Gallery.svelte";
-import HTML from "../src/components/HTML/HTML.svelte";
-import HighlightedText from "../src/components/HighlightedText/HighlightedText.svelte";
-import Json from "../src/components/Json/Json.svelte";
-import Label from "../src/components/Label/Label.svelte";
-import Markdown from "../src/components/Markdown/Markdown.svelte";
-import Model3D from "../src/components/Model3D/Model3D.svelte";
-import Number from "../src/components/Number/Number.svelte";
-import Radio from "../src/components/Radio/Radio.svelte";
-import Slider from "../src/components/Slider/Slider.svelte";
-import Textbox from "../src/components/Textbox/Textbox.svelte";
-import TimeSeries from "../src/components/TimeSeries/TimeSeries.svelte";
-import UploadButton from "../src/components/UploadButton/UploadButton.svelte";
-import Video from "../src/components/Video/Video.svelte";
-import { LoadingStatus } from "../src/components/StatusTracker/types";
+import Checkbox from "@gradio/checkbox";
+import CheckboxGroup from "@gradio/checkboxgroup";
+import ColorPicker from "@gradio/colorpicker";
+import DataFrame from "@gradio/dataframe";
+import Dropdown from "@gradio/dropdown";
+import File from "@gradio/file";
+import Gallery from "@gradio/gallery";
+import HTML from "@gradio/html";
+import HighlightedText from "@gradio/highlightedtext";
+import Json from "@gradio/json";
+import Label from "@gradio/label";
+import Markdown from "@gradio/markdown";
+import Model3D from "@gradio/model3d";
+import Number from "@gradio/number";
+import Radio from "@gradio/radio";
+import Slider from "@gradio/slider";
+import Textbox from "@gradio/textbox";
+import TimeSeries from "@gradio/timeseries";
+import UploadButton from "@gradio/uploadbutton";
+import Video from "@gradio/video";
+import { LoadingStatus } from "@gradio/statustracker/types";
 
 const loading_status: LoadingStatus = {
 	eta: 0,
diff --git a/js/app/test/tests.md b/js/app/test/tests.md
--- a/js/app/test/tests.md
+++ b/js/app/test/tests.md
@@ -5,134 +5,178 @@ Just a little reference docs to understand what is tested/ needs testing. Perhap
 ## Interface
 
 ## Flagging
+
 ## Blocks
+
 ## Block Layouts
+
 ## Themes
 
 ## Components
 
 ### Props/kwargs
 
-| Component       | `value`         |  `visible`       |  `elem_id`       |  `elem_classes`     |  `container`      |  `label`  |  `show_label`  |
-| --------------- | --------------- | ---------------- | ---------------- | ------------------- | ----------------- | --------- | ---------------|
-| AnnotatedImage  | `❌`            | `✅`              | `✅`             | `✅`                 | `❌`              | `✅`      | `❌`            |
-| Audio           | `❌`            | `✅`              | `✅`             | `✅`                 | `❌`              | `✅`      | `❌`            |
-| BarPlot         | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| Button          | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| Chatbot         | `❌`            | `✅`              | `✅`             | `✅`                 | `❌`              | `✅`      | `❌`            |
-| Checkbox        | `❌`            | `✅`              | `✅`             | `✅`                 | `❌`              | `✅`      | `❌`            |
-| CheckboxGroup   | `❌`            | `✅`              | `✅`             | `✅`                 | `❌`              | `✅`      | `❌`            |
-| ClearButton     | `❌`            | `✅`              | `✅`             | `✅`                 | `❌`              | `✅`      | `❌`            |
-| Code            | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| ColorPicker     | `❌`            | `✅`              | `✅`             | `✅`                 | `❌`              | `✅`      | `❌`            |
-| Dataframe       | `❌`            | `✅`              | `✅`             | `✅`                 | `❌`              | `✅`      | `❌`            |
-| Dropdown        | `❌`            | `✅`              | `✅`             | `✅`                 | `❌`              | `✅`      | `❌`            |
-| File            | `❌`            | `✅`              | `✅`             | `✅`                 | `❌`              | `✅`      | `❌`            |
-| Gallery         | `❌`            | `✅`              | `✅`             | `✅`                 | `❌`              | `✅`      | `❌`            |
-| HTML            | `❌`            | `✅`              | `✅`             | `✅`                 | `❌`              | `✅`      | `❌`            |
-| HighlightedText | `❌`            | `✅`              | `✅`             | `✅`                 | `❌`              | `✅`      | `❌`            |
-| Image           | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            | 
-| JSON            | `❌`            | `✅`              | `✅`             | `✅`                 | `❌`              | `✅`      | `❌`            |
-| Label           | `❌`            | `✅`              | `✅`             | `✅`                 | `❌`              | `✅`      | `❌`            |
-| Lineplot        | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| Markdown        | `❌`            | `✅`              | `✅`             | `✅`                 | `❌`              | `✅`      | `❌`            |
-| Model3D         | `❌`            | `✅`              | `✅`             | `✅`                 | `❌`              | `✅`      | `❌`            |
-| Number          | `❌`            | `✅`              | `✅`             | `✅`                 | `❌`              | `✅`      | `❌`            |
-| Plot            | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| Radio           | `❌`            | `✅`              | `✅`             | `✅`                 | `❌`              | `✅`      | `❌`            |
-| ScatterPlot     | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| Slider          | `❌`            | `✅`              | `✅`             | `✅`                 | `❌`              | `✅`      | `❌`            |
-| Textbox         | `❌`            | `✅`              | `✅`             | `✅`                 | `❌`              | `✅`      | `❌`            |
-| Timeseries      | `❌`            | `✅`              | `✅`             | `✅`                 | `❌`              | `✅`      | `❌`            |
-| UploadButton    | `❌`            | `✅`              | `✅`             | `✅`                 | `❌`              | `✅`      | `❌`            |
-| Video           | `❌`            | `✅`              | `✅`             | `✅`                 | `❌`              | `✅`      | `❌`            |
+| Component       | `value` | `visible` | `elem_id` | `elem_classes` | `container` | `label` | `show_label` |
+| --------------- | ------- | --------- | --------- | -------------- | ----------- | ------- | ------------ | --- |
+| AnnotatedImage  | `❌`    | `✅`      | `✅`      | `✅`           | `❌`        | `✅`    | `❌`         |
+| Audio           | `❌`    | `✅`      | `✅`      | `✅`           | `❌`        | `✅`    | `❌`         |
+| BarPlot         | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| Button          | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| Chatbot         | `❌`    | `✅`      | `✅`      | `✅`           | `❌`        | `✅`    | `❌`         |
+| Checkbox        | `❌`    | `✅`      | `✅`      | `✅`           | `❌`        | `✅`    | `❌`         |
+| CheckboxGroup   | `❌`    | `✅`      | `✅`      | `✅`           | `❌`        | `✅`    | `❌`         |
+| ClearButton     | `❌`    | `✅`      | `✅`      | `✅`           | `❌`        | `✅`    | `❌`         |
+| Code            | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| ColorPicker     | `❌`    | `✅`      | `✅`      | `✅`           | `❌`        | `✅`    | `❌`         |
+| Dataframe       | `❌`    | `✅`      | `✅`      | `✅`           | `❌`        | `✅`    | `❌`         |
+| Dropdown        | `❌`    | `✅`      | `✅`      | `✅`           | `❌`        | `✅`    | `❌`         |
+| File            | `❌`    | `✅`      | `✅`      | `✅`           | `❌`        | `✅`    | `❌`         |
+| Gallery         | `❌`    | `✅`      | `✅`      | `✅`           | `❌`        | `✅`    | `❌`         |
+| HTML            | `❌`    | `✅`      | `✅`      | `✅`           | `❌`        | `✅`    | `❌`         |
+| HighlightedText | `❌`    | `✅`      | `✅`      | `✅`           | `❌`        | `✅`    | `❌`         |
+| Image           | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |     |
+| JSON            | `❌`    | `✅`      | `✅`      | `✅`           | `❌`        | `✅`    | `❌`         |
+| Label           | `❌`    | `✅`      | `✅`      | `✅`           | `❌`        | `✅`    | `❌`         |
+| Lineplot        | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| Markdown        | `❌`    | `✅`      | `✅`      | `✅`           | `❌`        | `✅`    | `❌`         |
+| Model3D         | `❌`    | `✅`      | `✅`      | `✅`           | `❌`        | `✅`    | `❌`         |
+| Number          | `❌`    | `✅`      | `✅`      | `✅`           | `❌`        | `✅`    | `❌`         |
+| Plot            | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| Radio           | `❌`    | `✅`      | `✅`      | `✅`           | `❌`        | `✅`    | `❌`         |
+| ScatterPlot     | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| Slider          | `❌`    | `✅`      | `✅`      | `✅`           | `❌`        | `✅`    | `❌`         |
+| Textbox         | `❌`    | `✅`      | `✅`      | `✅`           | `❌`        | `✅`    | `❌`         |
+| Timeseries      | `❌`    | `✅`      | `✅`      | `✅`           | `❌`        | `✅`    | `❌`         |
+| UploadButton    | `❌`    | `✅`      | `✅`      | `✅`           | `❌`        | `✅`    | `❌`         |
+| Video           | `❌`    | `✅`      | `✅`      | `✅`           | `❌`        | `✅`    | `❌`         |
 
 ### Events
 
-| Component       | `value`         |  `visible`       |  `elem_id`       |  `elem_classes`     |  `container`      |  `label`  |  `show_label`  |
-| --------------- | --------------- | ---------------- | ---------------- | ------------------- | ----------------- | --------- | ---------------|
-| AnnotatedImage  | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| Audio           | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| BarPlot         | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| Button          | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| Chatbot         | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| Checkbox        | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| CheckboxGroup   | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| ClearButton     | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| Code            | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| ColorPicker     | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| Dataframe       | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| Dataset         | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| Dropdown        | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| File            | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| Gallery         | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| HTML            | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| HighlightedText | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| Image           | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            | 
-| Interpretation  | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| JSON            | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| Label           | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| Lineplot        | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| Markdown        | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| Model3D         | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| Number          | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| Plot            | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| Radio           | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| ScatterPlot     | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| Slider          | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| State           | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| Textbox         | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| Timeseries      | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| UploadButton    | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
-| Video           | `❌`            | `❌`              | `❌`             | `❌`                 | `❌`              | `❌`      | `❌`            |
+| Component       | `value` | `visible` | `elem_id` | `elem_classes` | `container` | `label` | `show_label` |
+| --------------- | ------- | --------- | --------- | -------------- | ----------- | ------- | ------------ | --- |
+| AnnotatedImage  | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| Audio           | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| BarPlot         | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| Button          | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| Chatbot         | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| Checkbox        | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| CheckboxGroup   | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| ClearButton     | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| Code            | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| ColorPicker     | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| Dataframe       | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| Dataset         | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| Dropdown        | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| File            | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| Gallery         | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| HTML            | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| HighlightedText | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| Image           | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |     |
+| Interpretation  | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| JSON            | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| Label           | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| Lineplot        | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| Markdown        | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| Model3D         | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| Number          | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| Plot            | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| Radio           | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| ScatterPlot     | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| Slider          | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| State           | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| Textbox         | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| Timeseries      | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| UploadButton    | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
+| Video           | `❌`    | `❌`      | `❌`      | `❌`           | `❌`        | `❌`    | `❌`         |
 
 ### `AnnotatedImage`
+
 ### `Audio`
+
 ### `BarPlot`
+
 ### `Button`
+
 ### `Chatbot`
+
 ### `Checkbox`
+
 ### `CheckboxGroup`
+
 ### `ClearButton`
+
 ### `Code`
+
 ### `ColorPicker`
+
 ### `Dataframe`
+
 ### `Dataset`
+
 ### `Dropdown`
+
 ### `File`
+
 ### `Gallery`
+
 ### `HTML`
+
 ### `HighlightedText`
+
 ### `Image`
+
 ### `Interpretation`
+
 ### `JSON`
+
 ### `Label`
+
 ### `Lineplot`
+
 ### `Markdown`
+
 ### `Model3D`
+
 ### `Number`
+
 ### `Plot`
+
 ### `Radio`
+
 ### `ScatterPlot`
+
 ### `Slider`
+
 ### `State`
+
 ### `Textbox`
+
 ### `Timeseries`
+
 ### `UploadButton`
+
 ### `Video`
 
 ## Helpers
 
 ### Error
+
 ### load
+
 ### Examples
+
 ### Progress
+
 ### update
+
 ### make_waveform
+
 ### EventData
 
-## Routes 
+## Routes
+
 ### `Request`
+
 ### `mount_gradio_app`
 
 ## Clients
diff --git a/js/chatbot/src/Chatbot.test.ts b/js/chatbot/Chatbot.test.ts
similarity index 97%
rename from js/chatbot/src/Chatbot.test.ts
rename to js/chatbot/Chatbot.test.ts
--- a/js/chatbot/src/Chatbot.test.ts
+++ b/js/chatbot/Chatbot.test.ts
@@ -1,7 +1,7 @@
 import { test, describe, assert, afterEach } from "vitest";
 import { cleanup, render } from "@gradio/tootils";
-import Chatbot from "./Index.svelte";
-import type { LoadingStatus } from "../../app/src/components/StatusTracker/types";
+import Chatbot from "./index.svelte";
+import type { LoadingStatus } from "@gradio/statustracker/types";
 import type { FileData } from "@gradio/upload";
 
 const loading_status: LoadingStatus = {
diff --git a/js/form/src/Range.test.ts b/js/form/src/Range.test.ts
deleted file mode 100644
--- a/js/form/src/Range.test.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { test, describe, afterEach, vi, expect } from "vitest";
-import { cleanup, render, fireEvent } from "@gradio/tootils";
-
-import Range from "./Range.svelte";
-
-describe("Range", () => {
-	afterEach(() => cleanup());
-
-	test("Release event called on blur and pointerUp", async () => {
-		const results = await render(Range, {
-			label: "range",
-			show_label: true,
-			value: 1,
-			minimum: 0,
-			maximum: 10
-		});
-
-		const numberInput = results.getAllByTestId("number-input")[0];
-		const mock = vi.fn();
-		results.component.$on("release", mock);
-
-		fireEvent.pointerUp(numberInput);
-
-		expect(mock).toHaveBeenCalledOnce();
-
-		fireEvent.blur(numberInput);
-		expect(mock).toHaveBeenCalledTimes(2);
-	});
-});
diff --git a/js/app/src/components/Group/Group.test.ts b/js/group/Group.test.ts
similarity index 93%
rename from js/app/src/components/Group/Group.test.ts
rename to js/group/Group.test.ts
--- a/js/app/src/components/Group/Group.test.ts
+++ b/js/group/Group.test.ts
@@ -1,7 +1,7 @@
 import { test, describe, assert, afterEach, vi } from "vitest";
 import { cleanup, render } from "@gradio/tootils";
 
-import Group from "./Group.svelte";
+import Group from "./static";
 
 describe("Group", () => {
 	afterEach(() => {
diff --git a/js/app/src/components/Image/Image.test.ts b/js/image/Image.test.ts
similarity index 89%
rename from js/app/src/components/Image/Image.test.ts
rename to js/image/Image.test.ts
--- a/js/app/src/components/Image/Image.test.ts
+++ b/js/image/Image.test.ts
@@ -9,10 +9,10 @@ import {
 } from "vitest";
 import { spy } from "tinyspy";
 import { cleanup, render } from "@gradio/tootils";
-import { setupi18n } from "../../i18n";
+import { setupi18n } from "../app/src/i18n";
 
-import Image from "./Image.svelte";
-import type { LoadingStatus } from "../StatusTracker/types";
+import Image from "./index.svelte";
+import type { LoadingStatus } from "@gradio/statustracker/types";
 
 const loading_status = {
 	eta: 0,
diff --git a/js/app/src/components/Radio/Radio.test.ts b/js/radio/Radio.test.ts
similarity index 94%
rename from js/app/src/components/Radio/Radio.test.ts
rename to js/radio/Radio.test.ts
--- a/js/app/src/components/Radio/Radio.test.ts
+++ b/js/radio/Radio.test.ts
@@ -3,8 +3,8 @@ import { test, describe, assert, afterEach } from "vitest";
 import { cleanup, render } from "@gradio/tootils";
 import event from "@testing-library/user-event";
 
-import Radio from "./Radio.svelte";
-import type { LoadingStatus } from "../StatusTracker/types";
+import Radio from "./index.svelte";
+import type { LoadingStatus } from "@gradio/statustracker/types";
 
 const loading_status = {
 	eta: 0,
diff --git a/js/app/src/components/Textbox/Textbox.test.ts b/js/textbox/Textbox.test.ts
similarity index 93%
rename from js/app/src/components/Textbox/Textbox.test.ts
rename to js/textbox/Textbox.test.ts
--- a/js/app/src/components/Textbox/Textbox.test.ts
+++ b/js/textbox/Textbox.test.ts
@@ -3,8 +3,8 @@ import { spy } from "tinyspy";
 import { cleanup, fireEvent, render, get_text, wait } from "@gradio/tootils";
 import event from "@testing-library/user-event";
 
-import Textbox from "./Textbox.svelte";
-import type { LoadingStatus } from "../StatusTracker/types";
+import Textbox from "./index.svelte";
+import type { LoadingStatus } from "@gradio/statustracker/types";
 
 const loading_status = {
 	eta: 0,
diff --git a/js/app/src/components/UploadButton/UploadButton.test.ts b/js/uploadbutton/UploadButton.test.ts
similarity index 92%
rename from js/app/src/components/UploadButton/UploadButton.test.ts
rename to js/uploadbutton/UploadButton.test.ts
--- a/js/app/src/components/UploadButton/UploadButton.test.ts
+++ b/js/uploadbutton/UploadButton.test.ts
@@ -2,9 +2,9 @@ import { test, describe, expect, vi, afterEach, assert } from "vitest";
 import { spy, spyOn } from "tinyspy";
 import { cleanup, render, wait_for_event } from "@gradio/tootils";
 import event from "@testing-library/user-event";
-import { setupi18n } from "../../i18n";
-import type { LoadingStatus } from "../StatusTracker/types";
-import UploadButton from "./UploadButton.svelte";
+import { setupi18n } from "../app/src/i18n";
+import type { LoadingStatus } from "@gradio/statustracker/types";
+import UploadButton from "./index.svelte";
 
 describe("UploadButton", () => {
 	afterEach(() => {
diff --git a/js/app/src/components/Video/Video.test.ts b/js/video/Video.test.ts
similarity index 97%
rename from js/app/src/components/Video/Video.test.ts
rename to js/video/Video.test.ts
--- a/js/app/src/components/Video/Video.test.ts
+++ b/js/video/Video.test.ts
@@ -10,10 +10,10 @@ import {
 } from "vitest";
 import { spy, spyOn } from "tinyspy";
 import { cleanup, render } from "@gradio/tootils";
-import { setupi18n } from "../../i18n";
+import { setupi18n } from "../app/src/i18n";
 
-import Video from "./Video.svelte";
-import type { LoadingStatus } from "../StatusTracker/types";
+import Video from "./index.svelte";
+import type { LoadingStatus } from "@gradio/statustracker/types";
 
 const loading_status = {
 	eta: 0,
diff --git a/test/README.md b/test/README.md
--- a/test/README.md
+++ b/test/README.md
@@ -2,7 +2,7 @@
 
 - All the tests should test Backend functionalities. Frontend functionalities and e2e tests are done in Frontend.
 - Make use of pytest fixtures whenever it is possible. With fixtures, objects with high initialize durations are reused within tests, ex. a client session.
-- All test_data resides within _gradio/test_data_ and all test_files resides within test/test_files.
+- All test*data resides within \_gradio/test_data* and all test_files resides within test/test_files.
 - When doing network operations do not forget to make use of async to make tests faster.
 - Have clear class and function naming within the tests.
 - Short descriptions within test functions are great.
diff --git a/test/test_files/README.md b/test/test_files/README.md
--- a/test/test_files/README.md
+++ b/test/test_files/README.md
@@ -1,5 +1,6 @@
 Files in this directory are used in:
-* tests for the gradio library
-* example inputs in the view API documentation
 
-Warning: please be careful when renaming / deleting files 
\ No newline at end of file
+- tests for the gradio library
+- example inputs in the view API documentation
+
+Warning: please be careful when renaming / deleting files