Lint tests, format JSON (#818)

This commit is contained in:
Jeremy Gallant
2025-08-31 16:04:34 -04:00
committed by GitHub
parent d7e492cdc9
commit 91426a89e5
35 changed files with 2052 additions and 1979 deletions
+3 -3
View File
@@ -1,10 +1,10 @@
{ {
"editor.formatOnSave": true, "editor.formatOnSave": true,
"editor.codeActionsOnSave": { "editor.codeActionsOnSave": {
"source.fixAll.biome": "explicit", "source.fixAll.biome": "explicit"
}, },
"search.exclude": { "search.exclude": {
"**/i18n/locales/*-*/**": true, "**/i18n/locales/*-*/**": true
}, },
"vitest.workspaceConfig": "vitest.config.ts", "vitest.workspaceConfig": "vitest.config.ts"
} }
+29 -2
View File
@@ -1,6 +1,14 @@
{ {
"files": { "files": {
"includes": ["**/*.ts", "**/*.tsx", "!**/*.test.ts", "!**/*.test.tsx", "!npm_modules/**", "!dist/**", "!npm/**"], "includes": [
"**/*.ts",
"**/*.tsx",
"!npm_modules/**",
"!dist/**",
"!npm/**",
"**/*.json",
"!**/locales/*-*/*.json"
],
"ignoreUnknown": false "ignoreUnknown": false
}, },
"formatter": { "formatter": {
@@ -38,7 +46,26 @@
}, },
"json": { "json": {
"formatter": { "formatter": {
"enabled": false "enabled": true
}
},
"overrides": [
{
"includes": [
"**/*.test.ts",
"**/*.test.tsx",
"**/__tests__/**/*.{ts,tsx}"
],
"linter": {
"rules": {
"suspicious": {
"noExplicitAny": "off"
},
"style": {
"noNonNullAssertion": "off"
} }
} }
} }
}
]
}
+3 -1
View File
@@ -13,7 +13,9 @@
"tsdown": { "tsdown": {
"entry": "mod.ts", "entry": "mod.ts",
"dts": true, "dts": true,
"format": ["esm"], "format": [
"esm"
],
"splitting": false, "splitting": false,
"clean": true "clean": true
}, },
+1 -6
View File
@@ -7,12 +7,7 @@
"outDir": "./dist", "outDir": "./dist",
"moduleResolution": "bundler", "moduleResolution": "bundler",
"emitDeclarationOnly": false, "emitDeclarationOnly": false,
"esModuleInterop": true, "esModuleInterop": true
}, },
"include": ["src"] "include": ["src"]
} }
+3 -1
View File
@@ -12,7 +12,9 @@
"tsdown": { "tsdown": {
"entry": "mod.ts", "entry": "mod.ts",
"dts": true, "dts": true,
"format": ["esm"], "format": [
"esm"
],
"splitting": false, "splitting": false,
"clean": true "clean": true
}, },
+6 -2
View File
@@ -2,7 +2,9 @@
"name": "@meshtastic/transport-http", "name": "@meshtastic/transport-http",
"version": "0.2.3-2", "version": "0.2.3-2",
"description": "A transport layer for Meshtastic applications using HTTP.", "description": "A transport layer for Meshtastic applications using HTTP.",
"exports": {".": "./mod.ts"}, "exports": {
".": "./mod.ts"
},
"type": "module", "type": "module",
"files": [ "files": [
"package.json", "package.json",
@@ -17,7 +19,9 @@
"tsdown": { "tsdown": {
"entry": "mod.ts", "entry": "mod.ts",
"dts": true, "dts": true,
"format": ["esm"], "format": [
"esm"
],
"splitting": false, "splitting": false,
"clean": true "clean": true
}, },
+1 -1
View File
@@ -7,7 +7,7 @@
"outDir": "./dist", "outDir": "./dist",
"moduleResolution": "bundler", "moduleResolution": "bundler",
"emitDeclarationOnly": false, "emitDeclarationOnly": false,
"esModuleInterop": true, "esModuleInterop": true
}, },
"include": ["src"] "include": ["src"]
} }
+3 -1
View File
@@ -13,7 +13,9 @@
"tsdown": { "tsdown": {
"entry": "mod.ts", "entry": "mod.ts",
"dts": true, "dts": true,
"format": ["esm"], "format": [
"esm"
],
"splitting": false, "splitting": false,
"clean": true "clean": true
}, },
+1 -6
View File
@@ -7,12 +7,7 @@
"outDir": "./dist", "outDir": "./dist",
"moduleResolution": "bundler", "moduleResolution": "bundler",
"emitDeclarationOnly": false, "emitDeclarationOnly": false,
"esModuleInterop": true, "esModuleInterop": true
}, },
"include": ["src"] "include": ["src"]
} }
+3 -1
View File
@@ -14,7 +14,9 @@
"tsdown": { "tsdown": {
"entry": "mod.ts", "entry": "mod.ts",
"dts": true, "dts": true,
"format": ["esm"], "format": [
"esm"
],
"splitting": false, "splitting": false,
"clean": true "clean": true
}, },
+1 -6
View File
@@ -7,12 +7,7 @@
"outDir": "./dist", "outDir": "./dist",
"moduleResolution": "bundler", "moduleResolution": "bundler",
"emitDeclarationOnly": false, "emitDeclarationOnly": false,
"esModuleInterop": true, "esModuleInterop": true
}, },
"include": ["src"] "include": ["src"]
} }
@@ -19,7 +19,9 @@
"tsdown": { "tsdown": {
"entry": "mod.ts", "entry": "mod.ts",
"dts": true, "dts": true,
"format": ["esm"], "format": [
"esm"
],
"splitting": false, "splitting": false,
"clean": true "clean": true
}, },
@@ -1,11 +1,13 @@
import { describe, vi, expect, beforeEach, afterEach } from "vitest"; import { describe, expect, vi } from "vitest";
import { runTransportContract } from "../../../tests/utils/transportContract"; import { runTransportContract } from "../../../tests/utils/transportContract";
import { TransportWebBluetooth } from "./transport"; import { TransportWebBluetooth } from "./transport";
class MiniEmitter { class MiniEmitter {
private listeners = new Map<string, Set<(e: Event) => void>>(); private listeners = new Map<string, Set<(e: Event) => void>>();
addEventListener(type: string, listener: (e: Event) => void) { addEventListener(type: string, listener: (e: Event) => void) {
if (!this.listeners.has(type)) this.listeners.set(type, new Set()); if (!this.listeners.has(type)) {
this.listeners.set(type, new Set());
}
this.listeners.get(type)!.add(listener); this.listeners.get(type)!.add(listener);
} }
removeEventListener(type: string, listener: (e: Event) => void) { removeEventListener(type: string, listener: (e: Event) => void) {
@@ -66,10 +68,16 @@ function stubWebBluetooth() {
// Primary service returns our three characteristics by UUID // Primary service returns our three characteristics by UUID
const primaryService: BluetoothRemoteGATTService = { const primaryService: BluetoothRemoteGATTService = {
async getCharacteristic(uuid: string) { async getCharacteristic(uuid: string) {
if (uuid === TransportWebBluetooth.ToRadioUuid) return toRadioCharacteristic; if (uuid === TransportWebBluetooth.ToRadioUuid) {
if (uuid === TransportWebBluetooth.FromRadioUuid) return fromRadioCharacteristic; return toRadioCharacteristic;
if (uuid === TransportWebBluetooth.FromNumUuid) return fromNumCharacteristic; }
throw new Error("Unknown characteristic: " + uuid); if (uuid === TransportWebBluetooth.FromRadioUuid) {
return fromRadioCharacteristic;
}
if (uuid === TransportWebBluetooth.FromNumUuid) {
return fromNumCharacteristic;
}
throw new Error(`Unknown characteristic: ${uuid}`);
}, },
} as unknown as BluetoothRemoteGATTService; } as unknown as BluetoothRemoteGATTService;
@@ -94,10 +102,20 @@ function stubWebBluetooth() {
return primaryService; return primaryService;
}, },
device: { device: {
addEventListener: (...args: Parameters<EventTarget["addEventListener"]>) => addEventListener: (
deviceEmitter.addEventListener(args[0] as string, args[1] as (e: Event) => void), ...args: Parameters<EventTarget["addEventListener"]>
removeEventListener: (...args: Parameters<EventTarget["removeEventListener"]>) => ) =>
deviceEmitter.removeEventListener(args[0] as string, args[1] as (e: Event) => void), deviceEmitter.addEventListener(
args[0] as string,
args[1] as (e: Event) => void,
),
removeEventListener: (
...args: Parameters<EventTarget["removeEventListener"]>
) =>
deviceEmitter.removeEventListener(
args[0] as string,
args[1] as (e: Event) => void,
),
} as unknown as BluetoothDevice, } as unknown as BluetoothDevice,
} as unknown as BluetoothRemoteGATTServer; } as unknown as BluetoothRemoteGATTServer;
@@ -114,7 +132,10 @@ function stubWebBluetooth() {
}, },
}; };
vi.stubGlobal("navigator", Object.assign({}, globalThis.navigator, fakeNavigator)); vi.stubGlobal(
"navigator",
Object.assign({}, globalThis.navigator, fakeNavigator),
);
// helper actions for tests/contract // helper actions for tests/contract
return { return {
@@ -142,24 +163,36 @@ describe("TransportWebBluetooth (contract)", () => {
name: "TransportWebBluetooth", name: "TransportWebBluetooth",
setup: () => {}, setup: () => {},
teardown: () => { teardown: () => {
(globalThis as unknown as { __ble?: ReturnType<typeof stubWebBluetooth> }).__ble?.cleanup(); (
(globalThis as unknown as { __ble?: ReturnType<typeof stubWebBluetooth> }).__ble = undefined; globalThis as unknown as { __ble?: ReturnType<typeof stubWebBluetooth> }
).__ble?.cleanup();
(
globalThis as unknown as { __ble?: ReturnType<typeof stubWebBluetooth> }
).__ble = undefined;
vi.restoreAllMocks(); vi.restoreAllMocks();
vi.unstubAllGlobals(); vi.unstubAllGlobals();
}, },
create: async () => { create: async () => {
(globalThis as unknown as { __ble: ReturnType<typeof stubWebBluetooth> }).__ble = stubWebBluetooth(); (
globalThis as unknown as { __ble: ReturnType<typeof stubWebBluetooth> }
).__ble = stubWebBluetooth();
return await TransportWebBluetooth.create(); return await TransportWebBluetooth.create();
}, },
pushIncoming: async (bytes) => { pushIncoming: async (bytes) => {
(globalThis as unknown as { __ble: ReturnType<typeof stubWebBluetooth> }).__ble.pushIncoming(bytes); (
globalThis as unknown as { __ble: ReturnType<typeof stubWebBluetooth> }
).__ble.pushIncoming(bytes);
await Promise.resolve(); await Promise.resolve();
}, },
assertLastWritten: (bytes) => { assertLastWritten: (bytes) => {
(globalThis as unknown as { __ble: ReturnType<typeof stubWebBluetooth> }).__ble.assertLastWritten(bytes); (
globalThis as unknown as { __ble: ReturnType<typeof stubWebBluetooth> }
).__ble.assertLastWritten(bytes);
}, },
triggerDisconnect: async () => { triggerDisconnect: async () => {
(globalThis as unknown as { __ble: ReturnType<typeof stubWebBluetooth> }).__ble.triggerGattDisconnect(); (
globalThis as unknown as { __ble: ReturnType<typeof stubWebBluetooth> }
).__ble.triggerGattDisconnect();
await Promise.resolve(); await Promise.resolve();
}, },
}); });
@@ -8,12 +8,7 @@
"moduleResolution": "bundler", "moduleResolution": "bundler",
"emitDeclarationOnly": false, "emitDeclarationOnly": false,
"esModuleInterop": true, "esModuleInterop": true,
"types": ["@types/web-bluetooth"], "types": ["@types/web-bluetooth"]
}, },
"include": ["src"] "include": ["src"]
} }
+3 -1
View File
@@ -19,7 +19,9 @@
"tsdown": { "tsdown": {
"entry": "mod.ts", "entry": "mod.ts",
"dts": true, "dts": true,
"format": ["esm"], "format": [
"esm"
],
"splitting": false, "splitting": false,
"clean": true "clean": true
}, },
@@ -1,7 +1,7 @@
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
import { TransportWebSerial } from "./transport";
import { Types, Utils } from "@meshtastic/core"; import { Types, Utils } from "@meshtastic/core";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { runTransportContract } from "../../../tests/utils/transportContract"; import { runTransportContract } from "../../../tests/utils/transportContract";
import { TransportWebSerial } from "./transport";
function stubCoreTransforms() { function stubCoreTransforms() {
const toDevice = new TransformStream<Uint8Array, Uint8Array>({ const toDevice = new TransformStream<Uint8Array, Uint8Array>({
@@ -45,14 +45,26 @@ function stubNavigatorSerial() {
const handlers = new Set<SerialDisconnectHandler>(); const handlers = new Set<SerialDisconnectHandler>();
const serialStub = { const serialStub = {
addEventListener: (type: string, handler: EventListenerOrEventListenerObject) => { addEventListener: (
if (type === "disconnect") handlers.add(handler as any as SerialDisconnectHandler); type: string,
handler: EventListenerOrEventListenerObject,
) => {
if (type === "disconnect") {
handlers.add(handler as any as SerialDisconnectHandler);
}
}, },
removeEventListener: (type: string, handler: EventListenerOrEventListenerObject) => { removeEventListener: (
if (type === "disconnect") handlers.delete(handler as any as SerialDisconnectHandler); type: string,
handler: EventListenerOrEventListenerObject,
) => {
if (type === "disconnect") {
handlers.delete(handler as any as SerialDisconnectHandler);
}
}, },
dispatchDisconnect(port: any) { dispatchDisconnect(port: any) {
for (const h of handlers) h({ port }); for (const h of handlers) {
h({ port });
}
}, },
requestPort: vi.fn(async () => new FakeSerialPort()), requestPort: vi.fn(async () => new FakeSerialPort()),
}; };
@@ -201,8 +213,12 @@ describe("TransportWebSerial (extras)", () => {
// drain statuses until connected // drain statuses until connected
for (let i = 0; i < 3; i++) { for (let i = 0; i < 3; i++) {
const { value } = await reader.read(); const { value } = await reader.read();
if (!value || value.type !== "status") break; if (!value || value.type !== "status") {
if (value.data.status === Types.DeviceStatusEnum.DeviceConnected) break; break;
}
if (value.data.status === Types.DeviceStatusEnum.DeviceConnected) {
break;
}
} }
// fire OS-level disconnect // fire OS-level disconnect
@@ -212,7 +228,10 @@ describe("TransportWebSerial (extras)", () => {
let saw = false; let saw = false;
for (let i = 0; i < 6; i++) { for (let i = 0; i < 6; i++) {
const { value } = await reader.read(); const { value } = await reader.read();
if (value?.type === "status" && value.data.reason === "serial-disconnected") { if (
value?.type === "status" &&
value.data.reason === "serial-disconnected"
) {
saw = true; saw = true;
break; break;
} }
+1 -6
View File
@@ -8,12 +8,7 @@
"moduleResolution": "bundler", "moduleResolution": "bundler",
"emitDeclarationOnly": false, "emitDeclarationOnly": false,
"esModuleInterop": true, "esModuleInterop": true,
"types": ["@types/w3c-web-serial"], "types": ["@types/w3c-web-serial"]
}, },
"include": ["src"] "include": ["src"]
} }
@@ -24,7 +24,9 @@ vi.mock("@core/services/featureFlags", () => {
return { return {
featureFlags: { featureFlags: {
get: vi.fn((key: string) => { get: vi.fn((key: string) => {
if (key === "persistNodeDB") return true; if (key === "persistNodeDB") {
return true;
}
return false; return false;
}), }),
}, },
@@ -64,7 +66,7 @@ describe("NodeDB store", () => {
expect(db.getNode(10)?.num).toBe(10); expect(db.getNode(10)?.num).toBe(10);
const all = db.getNodes(); const all = db.getNodes();
expect(all.map(n => n.num).sort()).toEqual([10, 11]); expect(all.map((n) => n.num).sort()).toEqual([10, 11]);
db.removeNode(10); db.removeNode(10);
expect(db.getNodesLength()).toBe(1); expect(db.getNodesLength()).toBe(1);
@@ -128,7 +130,6 @@ describe("NodeDB store", () => {
const { useNodeDBStore } = await freshStore(); const { useNodeDBStore } = await freshStore();
const st = useNodeDBStore.getState(); const st = useNodeDBStore.getState();
const oldDB = st.addNodeDB(10); const oldDB = st.addNodeDB(10);
oldDB.setNodeNum(999); oldDB.setNodeNum(999);
oldDB.addNode(makeNode(200)); oldDB.addNode(makeNode(200));
@@ -202,7 +203,9 @@ describe("NodeDB store", () => {
it("when exceeding cap, evicts earliest inserted, not the newly added", async () => { it("when exceeding cap, evicts earliest inserted, not the newly added", async () => {
const { useNodeDBStore } = await freshStore(); const { useNodeDBStore } = await freshStore();
const st = useNodeDBStore.getState(); const st = useNodeDBStore.getState();
for (let i = 1; i <= 10; i++) st.addNodeDB(i); for (let i = 1; i <= 10; i++) {
st.addNodeDB(i);
}
st.addNodeDB(11); st.addNodeDB(11);
expect(st.getNodeDB(1)).toBeUndefined(); expect(st.getNodeDB(1)).toBeUndefined();
expect(st.getNodeDB(11)).toBeDefined(); expect(st.getNodeDB(11)).toBeDefined();