Skip to content

Commit 2c88b1d

Browse files
Copilotsawka
andauthored
Add WebViewEnv and wire web preview to the mock WaveEnv contract (#3064)
The webview preview existed, but the webview feature was still reading key dependencies from global helpers instead of a narrowed `WaveEnv`, which left the preview without a proper mock environment contract. This change introduces a dedicated `WebViewEnv` and routes the webview model/view through it so preview/test mocks can supply the same dependencies explicitly. - **WaveEnv narrowing for webview** - Added `frontend/app/view/webview/webviewenv.ts` - Declares the exact webview dependencies used by the feature: - `electron`: `openExternal`, `getWebviewPreload`, `clearWebviewStorage`, `getConfigDir`, `setWebviewFocus` - `rpc`: `FetchSuggestionsCommand`, `SetMetaCommand`, `SetConfigCommand` - `wos`, `createBlock` - `getSettingsKeyAtom("web:defaulturl" | "web:defaultsearch")` - `getBlockMetaKeyAtom("web:hidenav" | "web:useragenttype" | "web:zoom" | "web:partition")` - **WebView model/view now consume env-provided dependencies** - `WebViewModel` now stores and uses `waveEnv` instead of reaching into global singletons for WOS, settings, block meta, RPC, and Electron APIs. - The React view now reads `web:defaultsearch`, `web:zoom`, and `web:partition` from `useWaveEnv<WebViewEnv>()`. - Webview event paths that create blocks / manage focus / use Electron preload are now driven by the env contract. - **Preview/mock behavior aligned with production semantics** - Updated the web preview mock search template to use `{query}`, matching the webview search-template substitution logic. - Fixed mock `SetConfigCommand` behavior so settings updates remain observable through `getSettingsKeyAtom`, which is required for env-driven preview behavior. - Clearing block homepage now removes `pinnedurl` via `null`, matching the mock RPC meta-deletion semantics. - **Focused coverage** - Extended the existing webview test to verify that homepage resolution and config updates flow through the supplied mock env rather than global helpers. ```ts export type WebViewEnv = WaveEnvSubset<{ electron: { openExternal: WaveEnv["electron"]["openExternal"]; getWebviewPreload: WaveEnv["electron"]["getWebviewPreload"]; clearWebviewStorage: WaveEnv["electron"]["clearWebviewStorage"]; getConfigDir: WaveEnv["electron"]["getConfigDir"]; setWebviewFocus: WaveEnv["electron"]["setWebviewFocus"]; }; rpc: { FetchSuggestionsCommand: WaveEnv["rpc"]["FetchSuggestionsCommand"]; SetMetaCommand: WaveEnv["rpc"]["SetMetaCommand"]; SetConfigCommand: WaveEnv["rpc"]["SetConfigCommand"]; }; wos: WaveEnv["wos"]; createBlock: WaveEnv["createBlock"]; getSettingsKeyAtom: SettingsKeyAtomFnType<"web:defaulturl" | "web:defaultsearch">; getBlockMetaKeyAtom: BlockMetaKeyAtomFnType< "web:hidenav" | "web:useragenttype" | "web:zoom" | "web:partition" >; }>; ``` - **Screenshot** - <screenshot>https://github.com/user-attachments/assets/8921737f-490d-4719-8131-15f07c15a74c</screenshot> <!-- START COPILOT CODING AGENT TIPS --> --- 📍 Connect Copilot coding agent with [Jira](https://gh.io/cca-jira-docs), [Azure Boards](https://gh.io/cca-azure-boards-docs) or [Linear](https://gh.io/cca-linear-docs) to delegate work to Copilot in one click without leaving your project management tool. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: sawka <2722291+sawka@users.noreply.github.com> Co-authored-by: sawka <mike@commandline.dev>
1 parent b0d77a8 commit 2c88b1d

File tree

5 files changed

+120
-53
lines changed

5 files changed

+120
-53
lines changed

frontend/app/view/webview/webview.test.tsx

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
// Copyright 2026, Command Line Inc.
22
// SPDX-License-Identifier: Apache-2.0
33

4+
import { globalStore } from "@/app/store/jotaiStore";
5+
import { makeMockWaveEnv } from "@/preview/mock/mockwaveenv";
46
import { renderToStaticMarkup } from "react-dom/server";
57
import { describe, expect, it } from "vitest";
6-
import { getWebPreviewDisplayUrl, WebViewPreviewFallback } from "./webview";
8+
import { atom } from "jotai";
9+
import { getWebPreviewDisplayUrl, WebViewModel, WebViewPreviewFallback } from "./webview";
710

811
describe("webview preview fallback", () => {
912
it("shows the requested URL", () => {
@@ -17,4 +20,40 @@ describe("webview preview fallback", () => {
1720
expect(getWebPreviewDisplayUrl("")).toBe("about:blank");
1821
expect(getWebPreviewDisplayUrl(null)).toBe("about:blank");
1922
});
23+
24+
it("uses the supplied env for homepage atoms and config updates", async () => {
25+
const blockId = "webview-env-block";
26+
const env = makeMockWaveEnv({
27+
settings: {
28+
"web:defaulturl": "https://default.example",
29+
},
30+
mockWaveObjs: {
31+
[`block:${blockId}`]: {
32+
otype: "block",
33+
oid: blockId,
34+
version: 1,
35+
meta: {
36+
pinnedurl: "https://block.example",
37+
},
38+
} as Block,
39+
},
40+
});
41+
const model = new WebViewModel({
42+
blockId,
43+
nodeModel: {
44+
isFocused: atom(true),
45+
focusNode: () => {},
46+
} as any,
47+
tabModel: {} as any,
48+
waveEnv: env,
49+
});
50+
51+
expect(globalStore.get(model.homepageUrl)).toBe("https://block.example");
52+
53+
await model.setHomepageUrl("https://global.example", "global");
54+
55+
expect(globalStore.get(model.homepageUrl)).toBe("https://global.example");
56+
expect(globalStore.get(env.getSettingsKeyAtom("web:defaulturl"))).toBe("https://global.example");
57+
expect(globalStore.get(env.wos.getWaveObjectAtom<Block>(`block:${blockId}`))?.meta?.pinnedurl).toBeUndefined();
58+
});
2059
});

frontend/app/view/webview/webview.tsx

Lines changed: 51 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,26 @@
33

44
import { BlockNodeModel } from "@/app/block/blocktypes";
55
import { Search, useSearch } from "@/app/element/search";
6-
import { createBlock, getApi, getBlockMetaKeyAtom, getSettingsKeyAtom, openLink } from "@/app/store/global";
76
import { getSimpleControlShiftAtom } from "@/app/store/keymodel";
8-
import { ObjectService } from "@/app/store/services";
97
import type { TabModel } from "@/app/store/tab-model";
10-
import { RpcApi } from "@/app/store/wshclientapi";
8+
import { makeORef } from "@/app/store/wos";
119
import { TabRpcClient } from "@/app/store/wshrpcutil";
1210
import {
1311
BlockHeaderSuggestionControl,
1412
SuggestionControlNoData,
1513
SuggestionControlNoResults,
1614
} from "@/app/suggestion/suggestion";
1715
import { MockBoundary } from "@/app/waveenv/mockboundary";
18-
import { WOS, globalStore } from "@/store/global";
16+
import { useWaveEnv } from "@/app/waveenv/waveenv";
17+
import { globalStore, openLink } from "@/store/global";
1918
import { adaptFromReactOrNativeKeyEvent, checkKeyPressed } from "@/util/keyutil";
2019
import { fireAndForget, useAtomValueSafe } from "@/util/util";
2120
import clsx from "clsx";
2221
import { WebviewTag } from "electron";
2322
import { Atom, PrimitiveAtom, atom, useAtomValue, useSetAtom } from "jotai";
2423
import { Fragment, createRef, memo, useCallback, useEffect, useRef, useState } from "react";
2524
import "./webview.scss";
25+
import type { WebViewEnv } from "./webviewenv";
2626

2727
// User agent strings for mobile emulation
2828
const USER_AGENT_IPHONE =
@@ -32,9 +32,9 @@ const USER_AGENT_ANDROID =
3232

3333
let webviewPreloadUrl = null;
3434

35-
function getWebviewPreloadUrl() {
35+
function getWebviewPreloadUrl(env: WebViewEnv) {
3636
if (webviewPreloadUrl == null) {
37-
webviewPreloadUrl = getApi().getWebviewPreload();
37+
webviewPreloadUrl = env.electron.getWebviewPreload();
3838
console.log("webviewPreloadUrl", webviewPreloadUrl);
3939
}
4040
if (webviewPreloadUrl == null) {
@@ -72,16 +72,18 @@ export class WebViewModel implements ViewModel {
7272
typeaheadOpen: PrimitiveAtom<boolean>;
7373
partitionOverride: PrimitiveAtom<string> | null;
7474
userAgentType: Atom<string>;
75+
env: WebViewEnv;
7576

76-
constructor({ blockId, nodeModel, tabModel }: ViewModelInitType) {
77+
constructor({ blockId, nodeModel, tabModel, waveEnv }: ViewModelInitType) {
7778
this.nodeModel = nodeModel;
7879
this.tabModel = tabModel;
7980
this.viewType = "web";
8081
this.blockId = blockId;
82+
this.env = waveEnv;
8183
this.noPadding = atom(true);
82-
this.blockAtom = WOS.getWaveObjectAtom<Block>(`block:${blockId}`);
84+
this.blockAtom = this.env.wos.getWaveObjectAtom<Block>(`block:${blockId}`);
8385
this.url = atom();
84-
const defaultUrlAtom = getSettingsKeyAtom("web:defaulturl");
86+
const defaultUrlAtom = this.env.getSettingsKeyAtom("web:defaulturl");
8587
this.homepageUrl = atom((get) => {
8688
const defaultUrl = get(defaultUrlAtom);
8789
const pinnedUrl = get(this.blockAtom)?.meta?.pinnedurl;
@@ -97,10 +99,10 @@ export class WebViewModel implements ViewModel {
9799
this.urlInputRef = createRef<HTMLInputElement>();
98100
this.webviewRef = createRef<WebviewTag>();
99101
this.domReady = atom(false);
100-
this.hideNav = getBlockMetaKeyAtom(blockId, "web:hidenav");
102+
this.hideNav = this.env.getBlockMetaKeyAtom(blockId, "web:hidenav");
101103
this.typeaheadOpen = atom(false);
102104
this.partitionOverride = null;
103-
this.userAgentType = getBlockMetaKeyAtom(blockId, "web:useragenttype");
105+
this.userAgentType = this.env.getBlockMetaKeyAtom(blockId, "web:useragenttype");
104106

105107
this.mediaPlaying = atom(false);
106108
this.mediaMuted = atom(false);
@@ -199,7 +201,7 @@ export class WebViewModel implements ViewModel {
199201
console.log("open external", url);
200202
if (url != null && url != "") {
201203
const externalUrl = this.modifyExternalUrl?.(url) ?? url;
202-
return getApi().openExternal(externalUrl);
204+
return this.env.electron.openExternal(externalUrl);
203205
}
204206
},
205207
});
@@ -280,7 +282,7 @@ export class WebViewModel implements ViewModel {
280282
query: string,
281283
reqContext: SuggestionRequestContext
282284
): Promise<FetchSuggestionsResponse> {
283-
const result = await RpcApi.FetchSuggestionsCommand(TabRpcClient, {
285+
const result = await this.env.rpc.FetchSuggestionsCommand(TabRpcClient, {
284286
suggestiontype: "bookmark",
285287
query,
286288
widgetid: reqContext.widgetid,
@@ -369,7 +371,12 @@ export class WebViewModel implements ViewModel {
369371
* @param url The URL that has been navigated to.
370372
*/
371373
handleNavigate(url: string) {
372-
fireAndForget(() => ObjectService.UpdateObjectMeta(WOS.makeORef("block", this.blockId), { url }));
374+
fireAndForget(() =>
375+
this.env.rpc.SetMetaCommand(TabRpcClient, {
376+
oref: makeORef("block", this.blockId),
377+
meta: { url },
378+
})
379+
);
373380
globalStore.set(this.url, url);
374381
if (this.searchAtoms) {
375382
globalStore.set(this.searchAtoms.isOpen, false);
@@ -415,7 +422,7 @@ export class WebViewModel implements ViewModel {
415422
* @param newUrl The new URL to load in the webview.
416423
*/
417424
loadUrl(newUrl: string, reason: string) {
418-
const defaultSearchAtom = getSettingsKeyAtom("web:defaultsearch");
425+
const defaultSearchAtom = this.env.getSettingsKeyAtom("web:defaultsearch");
419426
const searchTemplate = globalStore.get(defaultSearchAtom);
420427
const nextUrl = this.ensureUrlScheme(newUrl, searchTemplate);
421428
console.log("webview loadUrl", reason, nextUrl, "cur=", this.webviewRef.current.getURL());
@@ -437,7 +444,7 @@ export class WebViewModel implements ViewModel {
437444
* @returns Promise that resolves when the URL is loaded.
438445
*/
439446
loadUrlPromise(newUrl: string, reason: string): Promise<void> {
440-
const defaultSearchAtom = getSettingsKeyAtom("web:defaultsearch");
447+
const defaultSearchAtom = this.env.getSettingsKeyAtom("web:defaultsearch");
441448
const searchTemplate = globalStore.get(defaultSearchAtom);
442449
const nextUrl = this.ensureUrlScheme(newUrl, searchTemplate);
443450
console.log("webview loadUrlPromise", reason, nextUrl, "cur=", this.webviewRef.current?.getURL());
@@ -477,17 +484,17 @@ export class WebViewModel implements ViewModel {
477484
if (url != null && url != "") {
478485
switch (scope) {
479486
case "block":
480-
await RpcApi.SetMetaCommand(TabRpcClient, {
481-
oref: WOS.makeORef("block", this.blockId),
487+
await this.env.rpc.SetMetaCommand(TabRpcClient, {
488+
oref: makeORef("block", this.blockId),
482489
meta: { pinnedurl: url },
483490
});
484491
break;
485492
case "global":
486-
await RpcApi.SetMetaCommand(TabRpcClient, {
487-
oref: WOS.makeORef("block", this.blockId),
488-
meta: { pinnedurl: "" },
493+
await this.env.rpc.SetMetaCommand(TabRpcClient, {
494+
oref: makeORef("block", this.blockId),
495+
meta: { pinnedurl: null },
489496
});
490-
await RpcApi.SetConfigCommand(TabRpcClient, { "web:defaulturl": url });
497+
await this.env.rpc.SetConfigCommand(TabRpcClient, { "web:defaulturl": url });
491498
break;
492499
}
493500
}
@@ -537,7 +544,7 @@ export class WebViewModel implements ViewModel {
537544
try {
538545
const webContentsId = this.webviewRef.current?.getWebContentsId();
539546
if (webContentsId) {
540-
await getApi().clearWebviewStorage(webContentsId);
547+
await this.env.electron.clearWebviewStorage(webContentsId);
541548
}
542549
} catch (e) {
543550
console.error("Failed to clear cookies and storage", e);
@@ -583,8 +590,8 @@ export class WebViewModel implements ViewModel {
583590
return;
584591
}
585592
this.webviewRef.current?.setZoomFactor(factor || 1);
586-
RpcApi.SetMetaCommand(TabRpcClient, {
587-
oref: WOS.makeORef("block", this.blockId),
593+
this.env.rpc.SetMetaCommand(TabRpcClient, {
594+
oref: makeORef("block", this.blockId),
588595
meta: { "web:zoom": factor }, // allow null so we can remove the zoom factor here
589596
});
590597
}
@@ -632,8 +639,8 @@ export class WebViewModel implements ViewModel {
632639
type: "checkbox",
633640
click: () => {
634641
fireAndForget(() => {
635-
return RpcApi.SetMetaCommand(TabRpcClient, {
636-
oref: WOS.makeORef("block", this.blockId),
642+
return this.env.rpc.SetMetaCommand(TabRpcClient, {
643+
oref: makeORef("block", this.blockId),
637644
meta: { "web:useragenttype": null },
638645
});
639646
});
@@ -645,8 +652,8 @@ export class WebViewModel implements ViewModel {
645652
type: "checkbox",
646653
click: () => {
647654
fireAndForget(() => {
648-
return RpcApi.SetMetaCommand(TabRpcClient, {
649-
oref: WOS.makeORef("block", this.blockId),
655+
return this.env.rpc.SetMetaCommand(TabRpcClient, {
656+
oref: makeORef("block", this.blockId),
650657
meta: { "web:useragenttype": "mobile:iphone" },
651658
});
652659
});
@@ -658,8 +665,8 @@ export class WebViewModel implements ViewModel {
658665
type: "checkbox",
659666
click: () => {
660667
fireAndForget(() => {
661-
return RpcApi.SetMetaCommand(TabRpcClient, {
662-
oref: WOS.makeORef("block", this.blockId),
668+
return this.env.rpc.SetMetaCommand(TabRpcClient, {
669+
oref: makeORef("block", this.blockId),
663670
meta: { "web:useragenttype": "mobile:android" },
664671
});
665672
});
@@ -696,8 +703,8 @@ export class WebViewModel implements ViewModel {
696703
label: isNavHidden ? "Un-Hide Navigation" : "Hide Navigation",
697704
click: () =>
698705
fireAndForget(() => {
699-
return RpcApi.SetMetaCommand(TabRpcClient, {
700-
oref: WOS.makeORef("block", this.blockId),
706+
return this.env.rpc.SetMetaCommand(TabRpcClient, {
707+
oref: makeORef("block", this.blockId),
701708
meta: { "web:hidenav": !isNavHidden },
702709
});
703710
}),
@@ -735,16 +742,17 @@ export class WebViewModel implements ViewModel {
735742

736743
const BookmarkTypeahead = memo(
737744
({ model, blockRef }: { model: WebViewModel; blockRef: React.RefObject<HTMLDivElement> }) => {
745+
const env = useWaveEnv<WebViewEnv>();
738746
const openBookmarksJson = () => {
739747
fireAndForget(async () => {
740-
const path = `${getApi().getConfigDir()}/presets/bookmarks.json`;
748+
const path = `${env.electron.getConfigDir()}/presets/bookmarks.json`;
741749
const blockDef: BlockDef = {
742750
meta: {
743751
view: "preview",
744752
file: path,
745753
},
746754
};
747-
await createBlock(blockDef, false, true);
755+
await env.createBlock(blockDef, false, true);
748756
model.setTypeaheadOpen(false);
749757
});
750758
};
@@ -824,18 +832,19 @@ function WebViewPreviewFallback({ url }: { url?: string | null }) {
824832
}
825833

826834
const WebView = memo(({ model, onFailLoad, blockRef, initialSrc }: WebViewProps) => {
835+
const env = useWaveEnv<WebViewEnv>();
827836
const blockData = useAtomValue(model.blockAtom);
828837
const defaultUrl = useAtomValue(model.homepageUrl);
829-
const defaultSearchAtom = getSettingsKeyAtom("web:defaultsearch");
838+
const defaultSearchAtom = env.getSettingsKeyAtom("web:defaultsearch");
830839
const defaultSearch = useAtomValue(defaultSearchAtom);
831840
let metaUrl = blockData?.meta?.url || defaultUrl || "";
832841
if (metaUrl) {
833842
metaUrl = model.ensureUrlScheme(metaUrl, defaultSearch);
834843
}
835844
const metaUrlRef = useRef(metaUrl);
836-
const zoomFactor = useAtomValue(getBlockMetaKeyAtom(model.blockId, "web:zoom")) || 1;
845+
const zoomFactor = useAtomValue(env.getBlockMetaKeyAtom(model.blockId, "web:zoom")) || 1;
837846
const partitionOverride = useAtomValueSafe(model.partitionOverride);
838-
const metaPartition = useAtomValue(getBlockMetaKeyAtom(model.blockId, "web:partition"));
847+
const metaPartition = useAtomValue(env.getBlockMetaKeyAtom(model.blockId, "web:partition"));
839848
const webPartition = partitionOverride || metaPartition || undefined;
840849
const userAgentType = useAtomValue(model.userAgentType) || "default";
841850

@@ -1027,11 +1036,11 @@ const WebView = memo(({ model, onFailLoad, blockRef, initialSrc }: WebViewProps)
10271036
}
10281037
};
10291038
const webviewFocus = () => {
1030-
getApi().setWebviewFocus(webview.getWebContentsId());
1039+
env.electron.setWebviewFocus(webview.getWebContentsId());
10311040
model.nodeModel.focusNode();
10321041
};
10331042
const webviewBlur = () => {
1034-
getApi().setWebviewFocus(null);
1043+
env.electron.setWebviewFocus(null);
10351044
};
10361045
const handleDomReady = () => {
10371046
globalStore.set(model.domReady, true);
@@ -1086,7 +1095,7 @@ const WebView = memo(({ model, onFailLoad, blockRef, initialSrc }: WebViewProps)
10861095
src={metaUrlInitial}
10871096
data-blockid={model.blockId}
10881097
data-webcontentsid={webContentsId} // needed for emain
1089-
preload={getWebviewPreloadUrl()}
1098+
preload={getWebviewPreloadUrl(env)}
10901099
// @ts-expect-error This is a discrepancy between the React typing and the Chromium impl for webviewTag. Chrome webviewTag expects a string, while React expects a boolean.
10911100
allowpopups="true"
10921101
partition={webPartition}
@@ -1104,4 +1113,4 @@ const WebView = memo(({ model, onFailLoad, blockRef, initialSrc }: WebViewProps)
11041113
);
11051114
});
11061115

1107-
export { getWebPreviewDisplayUrl, WebView, WebViewPreviewFallback };
1116+
export { WebView, WebViewPreviewFallback, getWebPreviewDisplayUrl };
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2026, Command Line Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import type { BlockMetaKeyAtomFnType, SettingsKeyAtomFnType, WaveEnv, WaveEnvSubset } from "@/app/waveenv/waveenv";
5+
6+
export type WebViewEnv = WaveEnvSubset<{
7+
electron: {
8+
openExternal: WaveEnv["electron"]["openExternal"];
9+
getWebviewPreload: WaveEnv["electron"]["getWebviewPreload"];
10+
clearWebviewStorage: WaveEnv["electron"]["clearWebviewStorage"];
11+
getConfigDir: WaveEnv["electron"]["getConfigDir"];
12+
setWebviewFocus: WaveEnv["electron"]["setWebviewFocus"];
13+
};
14+
rpc: {
15+
FetchSuggestionsCommand: WaveEnv["rpc"]["FetchSuggestionsCommand"];
16+
SetMetaCommand: WaveEnv["rpc"]["SetMetaCommand"];
17+
SetConfigCommand: WaveEnv["rpc"]["SetConfigCommand"];
18+
};
19+
wos: WaveEnv["wos"];
20+
createBlock: WaveEnv["createBlock"];
21+
getSettingsKeyAtom: SettingsKeyAtomFnType<"web:defaulturl" | "web:defaultsearch">;
22+
getBlockMetaKeyAtom: BlockMetaKeyAtomFnType<
23+
"web:hidenav" | "web:useragenttype" | "web:zoom" | "web:partition"
24+
>;
25+
}>;

frontend/preview/mock/mockwaveenv.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -99,17 +99,11 @@ export function mergeMockEnv(base: MockEnv, overrides: MockEnv): MockEnv {
9999
};
100100
}
101101

102-
function makeMockSettingsKeyAtom(
103-
settingsAtom: Atom<SettingsType>,
104-
overrides?: Partial<SettingsType>
105-
): WaveEnv["getSettingsKeyAtom"] {
102+
function makeMockSettingsKeyAtom(settingsAtom: Atom<SettingsType>): WaveEnv["getSettingsKeyAtom"] {
106103
const keyAtomCache = new Map<keyof SettingsType, Atom<any>>();
107104
return <T extends keyof SettingsType>(key: T) => {
108105
if (!keyAtomCache.has(key)) {
109-
keyAtomCache.set(
110-
key,
111-
atom((get) => (overrides?.[key] !== undefined ? overrides[key] : get(settingsAtom)?.[key]))
112-
);
106+
keyAtomCache.set(key, atom((get) => get(settingsAtom)?.[key]));
113107
}
114108
return keyAtomCache.get(key) as Atom<SettingsType[T]>;
115109
};
@@ -345,7 +339,7 @@ export function makeMockWaveEnv(mockEnv?: MockEnv): MockWaveEnv {
345339
},
346340
rpc: makeMockRpc(overrides.rpc, mockWosFns),
347341
atoms,
348-
getSettingsKeyAtom: makeMockSettingsKeyAtom(atoms.settingsAtom, overrides.settings),
342+
getSettingsKeyAtom: makeMockSettingsKeyAtom(atoms.settingsAtom),
349343
platform,
350344
isDev: () => overrides.isDev ?? true,
351345
isWindows: () => platform === PlatformWindows,

0 commit comments

Comments
 (0)