Add ADB management and live car telemetry
This commit is contained in:
@@ -1,5 +1,14 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { collectAdbStatus, type AdbConfig, type AdbExecutor } from "../src/adb.js";
|
||||
import { existsSync } from "node:fs";
|
||||
import {
|
||||
collectAdbStatus,
|
||||
collectCarTelemetry,
|
||||
installAdbApk,
|
||||
launchAdbTarget,
|
||||
listInstalledAdbPackages,
|
||||
type AdbConfig,
|
||||
type AdbExecutor
|
||||
} from "../src/adb.js";
|
||||
|
||||
const enabledConfig: AdbConfig = {
|
||||
enabled: true,
|
||||
@@ -129,3 +138,63 @@ describe("read-only ADB collector", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("ADB dashboard operations", () => {
|
||||
it("lists installed packages and identifies system paths", async () => {
|
||||
const execute: AdbExecutor = async (_executable, arguments_) => {
|
||||
expect(arguments_).toEqual(["-s", "MG4-HEAD-UNIT", "shell", "pm", "list", "packages", "-f"]);
|
||||
return {
|
||||
stdout: "package:/data/app/com.example/base.apk=com.example\npackage:/system/app/Settings/Settings.apk=com.android.settings\n",
|
||||
stderr: ""
|
||||
};
|
||||
};
|
||||
await expect(listInstalledAdbPackages(enabledConfig, execute)).resolves.toEqual([
|
||||
{ packageName: "com.android.settings", apkPath: "/system/app/Settings/Settings.apk", system: true },
|
||||
{ packageName: "com.example", apkPath: "/data/app/com.example/base.apk", system: false }
|
||||
]);
|
||||
});
|
||||
|
||||
it("launches validated packages and components without a shell", async () => {
|
||||
const calls: string[][] = [];
|
||||
const execute: AdbExecutor = async (_executable, arguments_) => {
|
||||
calls.push([...arguments_]);
|
||||
return { stdout: "", stderr: "" };
|
||||
};
|
||||
await launchAdbTarget(enabledConfig, { type: "component", value: "com.android.settings/.Settings" }, execute);
|
||||
await launchAdbTarget(enabledConfig, { type: "package", value: "com.example.app" }, execute);
|
||||
expect(calls).toEqual([
|
||||
["-s", "MG4-HEAD-UNIT", "shell", "am", "start", "-n", "com.android.settings/.Settings"],
|
||||
["-s", "MG4-HEAD-UNIT", "shell", "monkey", "-p", "com.example.app", "-c", "android.intent.category.LAUNCHER", "1"]
|
||||
]);
|
||||
await expect(launchAdbTarget(enabledConfig, { type: "component", value: "com.example/.Main;reboot" }, execute)).rejects.toThrow("INVALID_ADB_COMPONENT");
|
||||
});
|
||||
|
||||
it("parses the verified MG4 live properties and marks SAIC-only data unavailable", async () => {
|
||||
const execute: AdbExecutor = async () => ({
|
||||
stdout: "[arcsoft.avm.mCurCarSpeed]: [17]\n[arcsoft.avm.mCurCarGear]: [4]\n[arcsoft.avm.mCurCarWheelAngle]: [-12.5]\n",
|
||||
stderr: ""
|
||||
});
|
||||
await expect(collectCarTelemetry(enabledConfig, execute)).resolves.toMatchObject({
|
||||
available: true,
|
||||
speedKph: { available: true, value: 17 },
|
||||
gear: { available: true, value: "4" },
|
||||
wheelAngleDegrees: { available: true, value: -12.5 },
|
||||
batteryPercent: { available: false },
|
||||
rangeKm: { available: false }
|
||||
});
|
||||
});
|
||||
|
||||
it("accepts only ZIP-formatted APK payloads and removes the temporary file", async () => {
|
||||
let temporaryPath = "";
|
||||
const execute: AdbExecutor = async (_executable, arguments_, options) => {
|
||||
temporaryPath = arguments_.at(-1) ?? "";
|
||||
expect(arguments_.slice(0, 4)).toEqual(["-s", "MG4-HEAD-UNIT", "install", "-r"]);
|
||||
expect(existsSync(temporaryPath)).toBe(true);
|
||||
expect(options.timeout).toBe(120_000);
|
||||
return { stdout: "Success\n", stderr: "" };
|
||||
};
|
||||
await installAdbApk(enabledConfig, Buffer.from([0x50, 0x4b, 0x03, 0x04, 0x00]), execute);
|
||||
expect(existsSync(temporaryPath)).toBe(false);
|
||||
await expect(installAdbApk(enabledConfig, Buffer.from("not an apk"), execute)).rejects.toThrow("INVALID_APK");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user