Add dashboard Bluetooth controls
This commit is contained in:
@@ -356,6 +356,18 @@ describe("authentication boundary", () => {
|
||||
const webHeaders = { ...mutationHeaders(csrfToken), cookie };
|
||||
|
||||
expect((await app.inject({ method: "GET", url: "/api/mobile/devices" })).statusCode).toBe(401);
|
||||
expect((await app.inject({ method: "GET", url: "/api/mobile/bluetooth" })).statusCode).toBe(401);
|
||||
const bluetooth = await app.inject({ method: "GET", url: "/api/mobile/bluetooth", headers: { cookie } });
|
||||
expect(bluetooth.statusCode).toBe(200);
|
||||
expect(bluetooth.json()).toMatchObject({ powered: expect.any(Boolean), discoverable: expect.any(Boolean) });
|
||||
const invalidBluetoothAction = await app.inject({
|
||||
method: "POST",
|
||||
url: "/api/mobile/bluetooth",
|
||||
headers: webHeaders,
|
||||
payload: { action: "arbitrary-command" }
|
||||
});
|
||||
expect(invalidBluetoothAction.statusCode).toBe(400);
|
||||
expect(invalidBluetoothAction.json()).toMatchObject({ error: { code: "INVALID_BLUETOOTH_ACTION" } });
|
||||
const pairing = await app.inject({ method: "POST", url: "/api/mobile/pairing", headers: webHeaders });
|
||||
expect(pairing.statusCode).toBe(200);
|
||||
const code = pairing.json<{ code: string }>().code;
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { bluetoothActionSchema, parseBluetoothctlStatus, parseBluetoothStatus } from "../src/bluetooth.js";
|
||||
|
||||
describe("Bluetooth controls", () => {
|
||||
it("accepts only fixed radio actions", () => {
|
||||
expect(bluetoothActionSchema.safeParse("on").success).toBe(true);
|
||||
expect(bluetoothActionSchema.safeParse("off").success).toBe(true);
|
||||
expect(bluetoothActionSchema.safeParse("discoverable").success).toBe(true);
|
||||
expect(bluetoothActionSchema.safeParse("scan --all").success).toBe(false);
|
||||
});
|
||||
|
||||
it("validates status returned by the privileged helper", () => {
|
||||
expect(parseBluetoothStatus(JSON.stringify({
|
||||
supported: true,
|
||||
powered: true,
|
||||
discoverable: false,
|
||||
pairable: true,
|
||||
message: "Bluetooth is on."
|
||||
}))).toMatchObject({ supported: true, powered: true, discoverable: false });
|
||||
|
||||
expect(() => parseBluetoothStatus('{"powered":"yes"}')).toThrow();
|
||||
});
|
||||
|
||||
it("reads the adapter state from BlueZ without privileged polling", () => {
|
||||
const status = parseBluetoothctlStatus(`Controller AA:BB:CC:DD:EE:FF Pi [default]\n\tPowered: yes\n\tDiscoverable: yes\n\tPairable: yes\n`);
|
||||
expect(status).toMatchObject({ supported: true, powered: true, discoverable: true, pairable: true });
|
||||
expect(parseBluetoothctlStatus("")).toMatchObject({ supported: false, powered: false });
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user