diff --git a/src/components/InspectorControls.tsx b/src/components/InspectorControls.tsx
index d9114572..461f1388 100644
--- a/src/components/InspectorControls.tsx
+++ b/src/components/InspectorControls.tsx
@@ -265,9 +265,6 @@ export function InspectorControls({
Mouse sensitivity
-
?",
+ );
+ }
+ return context;
}
export function useDebug() {
- return useContext(DebugContext);
+ const context = useContext(DebugContext);
+ if (!context) {
+ throw new Error(
+ "No DebugContext found. Did you remember to add a ?",
+ );
+ }
+ return context;
}
export function useControls() {
- return useContext(ControlsContext);
+ const context = useContext(ControlsContext);
+ if (!context) {
+ throw new Error(
+ "No ControlsContext found. Did you remember to add a ?",
+ );
+ }
+ return context;
}
export function SettingsProvider({ children }: { children: ReactNode }) {
diff --git a/src/torqueScript/runtime.spec.ts b/src/torqueScript/runtime.spec.ts
index 83adba33..4c11c698 100644
--- a/src/torqueScript/runtime.spec.ts
+++ b/src/torqueScript/runtime.spec.ts
@@ -3,6 +3,22 @@ import { createRuntime } from "./runtime";
import type { TorqueRuntimeOptions } from "./types";
import { parse, transpile } from "./index";
+// Mock pino logger so log.warn() calls are capturable in Node.js (pino's
+// browser write function only applies in browsers, not in vitest/Node).
+const mockLogger = vi.hoisted(() => ({
+ warn: vi.fn(),
+ info: vi.fn(),
+ error: vi.fn(),
+ debug: vi.fn(),
+ trace: vi.fn(),
+ fatal: vi.fn(),
+ child: vi.fn(),
+}));
+
+vi.mock("../logger", () => ({
+ createLogger: () => mockLogger,
+}));
+
function run(script: string, options?: TorqueRuntimeOptions) {
const { $, $f, $g, state } = createRuntime(options);
const { code } = transpile(script);
@@ -1658,19 +1674,17 @@ describe("TorqueScript Runtime", () => {
it("returns false when exec called without loadScript", async () => {
const runtime = createRuntime();
- // Warn about missing loader during load
- const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
+ // Warn about missing loader during load (via pino logger)
+ mockLogger.warn.mockClear();
const script = await runtime.loadFromSource(
'$Result = exec("scripts/test.cs");',
);
- expect(warnSpy).toHaveBeenCalled();
- warnSpy.mockRestore();
+ expect(mockLogger.warn).toHaveBeenCalled();
- // Execution should warn and set $Result to false
+ // Execution should warn and set $Result to false (via console.warn in builtins)
const warnSpy2 = vi.spyOn(console, "warn").mockImplementation(() => {});
script.execute();
expect(warnSpy2).toHaveBeenCalledWith(
- "[runtime]",
'exec("scripts/test.cs"): script not found',
);
warnSpy2.mockRestore();
@@ -1763,15 +1777,14 @@ describe("TorqueScript Runtime", () => {
const runtime = createRuntime({
loadScript: async () => null,
});
- const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
+ mockLogger.warn.mockClear();
await runtime.loadFromSource('exec("scripts/missing.cs");');
- expect(warnSpy).toHaveBeenCalledWith(
- "[runtime]",
- "Script not found: scripts/missing.cs",
+ expect(mockLogger.warn).toHaveBeenCalledWith(
+ "Script not found: %s",
+ "scripts/missing.cs",
);
- warnSpy.mockRestore();
});
});
@@ -2925,7 +2938,7 @@ describe("TorqueScript Runtime", () => {
}
it("skips scripts matching glob patterns", async () => {
- const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
+ mockLogger.warn.mockClear();
const runtime = createRuntime({
loadScript: createLoader({
@@ -2940,11 +2953,10 @@ describe("TorqueScript Runtime", () => {
expect(runtime.$g.get("Main")).toBe(1);
expect(runtime.$g.get("AI")).toBe(""); // Not loaded
- expect(warnSpy).toHaveBeenCalledWith(
- "[runtime]",
- "Ignoring script: scripts/ai/brain.cs",
+ expect(mockLogger.warn).toHaveBeenCalledWith(
+ "Ignoring script: %s",
+ "scripts/ai/brain.cs",
);
- warnSpy.mockRestore();
});
it("is case insensitive", async () => {
@@ -2990,7 +3002,7 @@ describe("TorqueScript Runtime", () => {
it("marks ignored scripts as failed (not retried)", async () => {
let loadCount = 0;
- const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
+ mockLogger.warn.mockClear();
const runtime = createRuntime({
loadScript: async (path) => {
@@ -3011,13 +3023,13 @@ describe("TorqueScript Runtime", () => {
// Should only warn once (second exec sees it's already in failedScripts)
expect(
- warnSpy.mock.calls.filter(
- (c) => c[1] === "Ignoring script: scripts/ignored.cs",
+ mockLogger.warn.mock.calls.filter(
+ (c) =>
+ c[0] === "Ignoring script: %s" && c[1] === "scripts/ignored.cs",
).length,
).toBe(1);
// Loader should only be called for main.cs, not for ignored.cs
expect(loadCount).toBe(1);
- warnSpy.mockRestore();
});
it("matches exact filenames with glob", async () => {