feat: support Switch 2 controllers and expanded profiles
This commit is contained in:
parent
4e48b7a9e7
commit
a87917bf0b
51 changed files with 4371 additions and 365 deletions
|
|
@ -63,35 +63,26 @@ def test_editor_serves_assets_and_complete_schema(
|
|||
) -> None:
|
||||
with running_server(monkeypatch, FakeDevice()) as (base_url, _):
|
||||
with urllib.request.urlopen(f"{base_url}/", timeout=2) as response:
|
||||
page = response.read().decode("utf-8")
|
||||
response.read()
|
||||
assert response.headers["Content-Security-Policy"]
|
||||
with urllib.request.urlopen(f"{base_url}/app.js", timeout=2) as response:
|
||||
script_size = len(response.read())
|
||||
response.read()
|
||||
assert response.headers["Content-Type"].startswith("text/javascript")
|
||||
with urllib.request.urlopen(
|
||||
f"{base_url}/assets/controller-switch-pro.svg", timeout=2
|
||||
) as response:
|
||||
artwork_size = len(response.read())
|
||||
response.read()
|
||||
assert response.headers["Content-Type"] == "image/svg+xml"
|
||||
|
||||
status, schema = request_json(f"{base_url}/api/schema")
|
||||
|
||||
assert status == 200
|
||||
assert "Profile Studio" in page
|
||||
assert script_size > 1000
|
||||
assert artwork_size > 10000
|
||||
assert schema["buttons"] == list(config_manager.LOGICAL_BUTTONS)
|
||||
assert schema["controls"] == list(config_manager.LOGICAL_CONTROLS)
|
||||
assert schema["rumble_policies"] == list(config_manager.RUMBLE_POLICIES)
|
||||
assert schema["turbo_modes"] == list(config_manager.TURBO_MODES)
|
||||
assert schema["macro_overrides"] == list(config_manager.MACRO_OVERRIDE_NAMES)
|
||||
assert schema["profile_capacity"] == 8
|
||||
assert schema["control_labels"]["generic"]["south"] == "A"
|
||||
assert schema["control_labels"]["xbox"]["left_shoulder"] == "LB"
|
||||
assert schema["control_labels"]["switch"]["east"] == "A"
|
||||
assert schema["control_labels"]["switch"]["left_trigger"] == "ZL"
|
||||
assert schema["control_labels"]["playstation"]["south"] == "Cross"
|
||||
assert schema["control_labels"]["playstation"]["select"] == "Create"
|
||||
assert (
|
||||
config_manager.ControllerProfile.from_json(
|
||||
json.dumps(schema["default_profile"])
|
||||
|
|
@ -100,6 +91,75 @@ def test_editor_serves_assets_and_complete_schema(
|
|||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("product_id", [0x2069, 0x2067, 0x2066])
|
||||
def test_switch2_input_choices_are_never_output_targets(
|
||||
monkeypatch: pytest.MonkeyPatch, product_id: int,
|
||||
) -> None:
|
||||
device = FakeDevice()
|
||||
identity = replace(device.stable_identity, vendor_id=0x057E, product_id=product_id)
|
||||
device.profile_identities = [device.global_identity, identity]
|
||||
device.active_profiles[identity.to_bytes()] = 0
|
||||
with running_server(monkeypatch, device) as (base_url, _):
|
||||
status, listing = request_json(f"{base_url}/api/profiles")
|
||||
assert status == 200
|
||||
status, schema = request_json(f"{base_url}/api/schema")
|
||||
assert status == 200
|
||||
owner = listing["identities"][1]
|
||||
assert owner["controller"]["style"] == "switch"
|
||||
assert set(config_manager.EXTRA_BUTTONS) <= set(owner["modifier_controls"])
|
||||
assert set(schema["extra_buttons"]).isdisjoint(schema["output_controls"])
|
||||
assert schema["output_controls"] == list(config_manager.OUTPUT_CONTROLS)
|
||||
|
||||
|
||||
def test_editor_migrates_schema6_and_saves_extra_mappings_without_metadata_loss(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
device = FakeDevice()
|
||||
key = (device.stable_identity.to_bytes(), 1)
|
||||
profile = custom_profile()
|
||||
legacy_wire = bytearray(profile.to_bytes())
|
||||
legacy_wire[:2] = b"\x06\x00"
|
||||
legacy_wire[344:] = bytes(40)
|
||||
device.profiles[key] = bytes(legacy_wire)
|
||||
device.profile_aliases[key[0]] = "Living room"
|
||||
device.profile_names[key] = "Racing"
|
||||
device.playtest_extra_buttons = 0x7F
|
||||
with running_server(monkeypatch, device) as (base_url, token):
|
||||
status, migrated = request_json(f"{base_url}/api/profiles/1/2")
|
||||
assert status == 200
|
||||
assert config_manager.ControllerProfile.from_json_object(migrated["profile"]) == profile
|
||||
draft = migrated["profile"]
|
||||
draft["extra_button_map"] = dict(zip(config_manager.EXTRA_BUTTONS, config_manager.LOGICAL_BUTTONS[:7]))
|
||||
draft["shift"]["mode"] = "hold"
|
||||
draft["shift"]["modifier"] = "c"
|
||||
draft["shift"]["extra_button_map"]["right_sr"] = "dpad_right"
|
||||
draft["macros"][0]["trigger"] = ["gl", "right_sr"]
|
||||
draft["macros"][0]["cancel"] = "gr"
|
||||
draft["switching_chord"] = ["left_sl", "left_sr"]
|
||||
draft["motion_toggle_chord"] = ["right_sl", "c"]
|
||||
status, validated = request_json(
|
||||
f"{base_url}/api/profiles/validate", method="POST", value=draft, token=token,
|
||||
)
|
||||
assert status == 200
|
||||
expected_profile = config_manager.ControllerProfile.from_json_object(draft)
|
||||
assert config_manager.ControllerProfile.from_json_object(validated["profile"]) == expected_profile
|
||||
assert device.profiles[key] == bytes(legacy_wire)
|
||||
status, _ = request_json(
|
||||
f"{base_url}/api/profiles/1/2", method="PUT", value=draft, token=token,
|
||||
)
|
||||
assert status == 200
|
||||
status, stored = request_json(f"{base_url}/api/profiles/1/2")
|
||||
assert status == 200
|
||||
assert config_manager.ControllerProfile.from_json_object(stored["profile"]) == expected_profile
|
||||
assert stored["alias"] == "Living room"
|
||||
assert stored["name"] == "Racing"
|
||||
assert stored["active"] is True
|
||||
status, sample = request_json(f"{base_url}/api/profiles/1/2/playtest")
|
||||
assert status == 200
|
||||
assert sample["extra_buttons"] == list(config_manager.EXTRA_BUTTONS)
|
||||
assert sample["buttons"] == ["south", "dpad_up", "dpad_right"]
|
||||
|
||||
|
||||
def test_editor_identifies_connected_controller_artwork(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue