aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/tests/test_lazy_load_failure.py
blob: 00c2030fcb5f83ab449d0aeb0ef404df2ddfe242 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
"""
A view whose module cannot be fetched says so, instead of spinning for good.

Found live after a hub deploy: the hub serves the module graph under
`/a/<hash>/` for the current hash only, so a tab opened before the deploy asked
for Search, Videos, Music, Photos and the player under a prefix that now
answers 404. `lazy.js` swallowed the rejection and kept the placeholder, so
every one of them showed a spinner for ever, with an empty console, while
Files and Chat — loaded before the deploy — worked. A reload fixed it, and
nothing on screen said so.

Measured in a browser: a rejected dynamic import is the one thing no source
reading can produce.
"""
import json
import shutil
import subprocess
from pathlib import Path

import pytest

HARNESS = Path(__file__).parent / "harness" / "lazy_failure_probe.py"
STATIC = Path(__file__).resolve().parents[1] / "src" / "meshbay_hub" / "static"

pytestmark = pytest.mark.skipif(
    shutil.which("google-chrome") is None or not (STATIC / "lazy.js").exists(),
    reason="Chrome or the SPA sources are not available")


@pytest.fixture(scope="module")
def probe():
    run = subprocess.run(["python3", str(HARNESS)], capture_output=True, timeout=120)
    assert run.returncode == 0, run.stderr.decode()[-2000:]
    out = json.loads(run.stdout.decode())
    assert "error" not in out, out["error"]
    return out


@pytest.mark.parametrize("view", ["plain", "framed"])
def test_a_module_that_answers_404_is_not_a_spinner(probe, view):
    assert not probe[view]["spinner"], "still spinning over a module that will never come"
    assert probe[view]["notice"], "nothing on screen says the view failed to load"
    assert probe[view]["buttons"], "no way offered to reload"


def test_the_failure_reaches_the_console(probe):
    """An empty console is what made this cost a scare instead of a glance."""
    assert len(probe["errors"]) == 2
    assert all("could not load" in e for e in probe["errors"])


def test_an_overlay_fails_inside_its_overlay_and_can_be_closed(probe):
    assert probe["framed"]["overlay"], "the player's notice landed outside its overlay"
    assert len(probe["framed"]["buttons"]) == 2
    assert probe["closed"] == 1, "the Close button did not reach the caller's onClose"
    assert len(probe["plain"]["buttons"]) == 1, "no onClose, so no Close button"


def test_a_module_that_exists_still_renders(probe):
    assert probe["fine"]