"""Build the whole Gradio graph with the models stubbed out. Catches component, parameter and event-wiring mistakes without a GPU, which is most of what breaks a Space on first deploy. The model path itself is not covered here. uv run --no-project --python 3.12 --with pytest --with "gradio==5.50.0" --with spaces \ --with pillow --with numpy --with imageio --with imageio-ffmpeg \ pytest space/test_app_smoke.py -q """ import os import sys import types import numpy as np import pytest from PIL import Image @pytest.fixture(scope="module") def app(): """Import app.py with `zoom` replaced by a stub that skips the GPU work.""" import geometry stub = types.ModuleType("zoom") stub.REPO = "dipta007/OracleZoom" stub.Models = type("Models", (), {"__init__": lambda self, weights=None: None}) def fake_zoom(models, image, levels=4, upscale=4, center=(0.5, 0.5)): cur = geometry.resize_and_center_crop(image) yield 0, 1, "", cur, cur for i in range(levels): blurry = geometry.zoom_window(cur, upscale, center).resize(cur.size, Image.BICUBIC) yield i + 1, upscale ** (i + 1), f"tag {i}", blurry, blurry cur = blurry stub.zoom = fake_zoom sys.modules["zoom"] = stub import app as module return module @pytest.fixture def photo(): rng = np.random.default_rng(0) return Image.fromarray(rng.integers(0, 255, (700, 900, 3), dtype=np.uint8)) def test_the_interface_builds(app): assert app.demo.blocks and app.demo.fns def test_preview_returns_a_canvas_and_tolerates_no_image(app, photo): assert app.preview(photo, 4, 0.3, 0.7).size == (512, 512) assert app.preview(None, 4, 0.5, 0.5) is None def test_declared_duration_grows_with_depth(app, photo): got = [app.estimate_duration(photo, n, 0.5, 0.5) for n in (1, 2, 3, 4)] assert got == sorted(got) and all(isinstance(v, int) for v in got) def test_the_shipped_example_assets_exist(app): for path in [app.EXAMPLE_CLIP, *app.EXAMPLE_COMPARE, *(p for p, _ in app.EXAMPLE_LEVELS)]: assert os.path.getsize(path) > 1000, path assert [label for _, label in app.EXAMPLE_LEVELS] == ["input", "4x", "16x", "64x", "256x"] def test_every_sample_named_for_the_examples_is_present(app): for name in app.SAMPLES: assert os.path.exists(f"samples/{name}.png") def test_run_streams_one_update_per_level_then_the_clip(app, photo): yields = list(app.run(photo, 3, 0.5, 0.5)) assert len(yields) == 5 # entry level, 3 zoom steps, then the clip assert all(len(y) == 5 for y in yields) assert yields[0][1] is None # first yield clears any stale clip status, clip, gallery, compare, prompts = yields[-1] assert [label for _, label in gallery] == ["input", "4x", "16x", "64x"] assert compare is not None and len(compare) == 2 assert prompts.count("tag") == 3 try: assert os.path.getsize(clip) > 10_000 finally: os.remove(clip) def test_run_rejects_an_empty_upload(app): import gradio as gr with pytest.raises(gr.Error): next(app.run(None, 4, 0.5, 0.5))