Add local ADB web remote for Android TV
Node/Express server shells out to adb (connect/pair/keyevent/text/app launch) and serves a mobile-first installable PWA remote: power, mute, input switch, volume/channel rockers, D-pad, media transport, text entry, and one-tap streaming app launch. Supports multiple saved TVs and the Android 11+ wireless-debugging pairing flow. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RSVyYcrjrbmrMKT85G4fyn
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import * as adb from "../src/adb.js";
|
||||
|
||||
test("normalizeTarget adds default port 5555", () => {
|
||||
assert.equal(adb.normalizeTarget("192.168.1.50"), "192.168.1.50:5555");
|
||||
});
|
||||
|
||||
test("normalizeTarget keeps an explicit port", () => {
|
||||
assert.equal(adb.normalizeTarget("192.168.1.50:5556"), "192.168.1.50:5556");
|
||||
});
|
||||
|
||||
test("normalizeTarget trims whitespace", () => {
|
||||
assert.equal(adb.normalizeTarget(" 192.168.1.50 "), "192.168.1.50:5555");
|
||||
});
|
||||
|
||||
test("normalizeTarget rejects shell-hostile input", () => {
|
||||
assert.throws(() => adb.normalizeTarget("1.2.3.4; rm -rf /"), /doesn't look like/);
|
||||
});
|
||||
|
||||
test("normalizeTarget rejects empty input", () => {
|
||||
assert.throws(() => adb.normalizeTarget(""), /doesn't look like/);
|
||||
});
|
||||
|
||||
test("connect() rejects cleanly against a closed local port instead of hanging", async () => {
|
||||
// Nothing listens on 5599 locally, so `adb connect` should fail fast with
|
||||
// a normal error rather than the process throwing an unhandled exception.
|
||||
await assert.rejects(adb.connect("127.0.0.1:5599"), (err) => {
|
||||
assert.equal(err.name, "AdbError");
|
||||
return true;
|
||||
});
|
||||
});
|
||||
|
||||
test("pair() rejects a non-6-digit code before touching adb", async () => {
|
||||
await assert.rejects(adb.pair("127.0.0.1:5599", "12"), /6 digits/);
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { mkdtemp, rm } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
|
||||
test("deviceStore add/list/update/remove roundtrip", async () => {
|
||||
const dir = await mkdtemp(join(tmpdir(), "tv-remote-test-"));
|
||||
process.env.DEVICES_FILE = join(dir, "devices.json");
|
||||
|
||||
// Import fresh so it picks up the env var above.
|
||||
const store = await import(`../src/deviceStore.js?t=${Date.now()}`);
|
||||
|
||||
assert.deepEqual(await store.listSavedDevices(), []);
|
||||
|
||||
const device = await store.addSavedDevice({ name: "Living Room", host: "192.168.1.50" });
|
||||
assert.equal(device.name, "Living Room");
|
||||
assert.ok(device.id);
|
||||
|
||||
let list = await store.listSavedDevices();
|
||||
assert.equal(list.length, 1);
|
||||
|
||||
const updated = await store.updateSavedDevice(device.id, { name: "Lounge" });
|
||||
assert.equal(updated.name, "Lounge");
|
||||
|
||||
const removed = await store.removeSavedDevice(device.id);
|
||||
assert.equal(removed, true);
|
||||
|
||||
list = await store.listSavedDevices();
|
||||
assert.equal(list.length, 0);
|
||||
|
||||
await rm(dir, { recursive: true, force: true });
|
||||
delete process.env.DEVICES_FILE;
|
||||
});
|
||||
Reference in New Issue
Block a user