Skip to content

Commit db37a3e

Browse files
committed
fix: missing test update and w3a context
1 parent c7d3f81 commit db37a3e

5 files changed

Lines changed: 83 additions & 55 deletions

File tree

packages/modal/test/modalManager.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ describe("Web3Auth (modal)", () => {
133133
it("connect resolves on CONSENT_ACCEPTED when consent is required", async () => {
134134
const sdk = createSdk({
135135
uiConfig: {
136-
consentRequired: true,
136+
consentConfig: { required: true },
137137
privacyPolicy: "https://example.com/privacy",
138138
tncLink: "https://example.com/terms",
139139
} as never,

packages/no-modal/src/noModal.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,7 @@ export class Web3AuthNoModal extends SafeEventEmitter<Web3AuthNoModalEvents> imp
409409
this.removeListener(CONNECTOR_EVENTS.CONNECTED, onConnected);
410410
this.removeListener(CONNECTOR_EVENTS.ERRORED, onErrored);
411411
this.removeListener(CONNECTOR_EVENTS.AUTHORIZED, onAuthorized);
412+
this.removeListener(CONNECTOR_EVENTS.CONSENT_ACCEPTED, onConsentAccepted);
412413
};
413414

414415
const checkCompletion = async () => {
@@ -449,6 +450,10 @@ export class Web3AuthNoModal extends SafeEventEmitter<Web3AuthNoModalEvents> imp
449450
await checkCompletion();
450451
};
451452

453+
const onConsentAccepted = async () => {
454+
await completeConnection();
455+
};
456+
452457
const onErrored = async (err: Web3AuthError) => {
453458
// track connection failed event
454459
this.analytics.track(ANALYTICS_EVENTS.CONNECTION_FAILED, {
@@ -464,6 +469,9 @@ export class Web3AuthNoModal extends SafeEventEmitter<Web3AuthNoModalEvents> imp
464469
if (finalLoginParams.getAuthTokenInfo) {
465470
this.once(CONNECTOR_EVENTS.AUTHORIZED, onAuthorized);
466471
}
472+
if (this.consentRequired) {
473+
this.once(CONNECTOR_EVENTS.CONSENT_ACCEPTED, onConsentAccepted);
474+
}
467475
this.once(CONNECTOR_EVENTS.ERRORED, onErrored);
468476
connector.connect(finalLoginParams);
469477
this.setCurrentChain(initialChain.chainId);

packages/no-modal/src/react/context/useWeb3AuthInnerContextValue.ts

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,29 @@ type UseWeb3AuthInnerContextValueOptions<TWeb3Auth extends IWeb3Auth, TWeb3AuthO
3939
initEffectDependency?: unknown;
4040
};
4141

42+
type InitialWeb3AuthState = {
43+
chainId: string | null;
44+
chainNamespace: ChainNamespaceType | null;
45+
connection: Connection | null;
46+
isAuthorized: boolean;
47+
isConnected: boolean;
48+
status: CONNECTOR_STATUS_TYPE | null;
49+
};
50+
51+
function getInitialState(web3Auth: IWeb3Auth): InitialWeb3AuthState {
52+
const isConnected = web3Auth.status === CONNECTOR_STATUS.CONNECTED;
53+
const isAuthorized = web3Auth.status === CONNECTOR_STATUS.AUTHORIZED;
54+
55+
return {
56+
chainId: isConnected ? web3Auth.currentChainId : null,
57+
chainNamespace: isConnected ? (web3Auth.currentChain?.chainNamespace ?? null) : null,
58+
connection: isConnected ? web3Auth.connection : null,
59+
isAuthorized,
60+
isConnected,
61+
status: web3Auth.status,
62+
};
63+
}
64+
4265
export function useWeb3AuthInnerContextValue<TWeb3Auth extends IWeb3Auth, TWeb3AuthOptions>({
4366
Web3AuthConstructor,
4467
web3AuthOptions,
@@ -47,20 +70,20 @@ export function useWeb3AuthInnerContextValue<TWeb3Auth extends IWeb3Auth, TWeb3A
4770
cleanupOnUnmount = false,
4871
initEffectDependency,
4972
}: UseWeb3AuthInnerContextValueOptions<TWeb3Auth, TWeb3AuthOptions>): IWeb3AuthInnerContextValue<TWeb3Auth> {
50-
const [chainId, setChainId] = useState<string | null>(null);
51-
const [chainNamespace, setChainNamespace] = useState<ChainNamespaceType | null>(null);
73+
const web3Auth = useMemo(() => {
74+
return new Web3AuthConstructor(web3AuthOptions, initialState);
75+
}, [Web3AuthConstructor, web3AuthOptions, initialState]);
76+
const initialWeb3AuthState = getInitialState(web3Auth);
77+
const [chainId, setChainId] = useState<string | null>(() => initialWeb3AuthState.chainId);
78+
const [chainNamespace, setChainNamespace] = useState<ChainNamespaceType | null>(() => initialWeb3AuthState.chainNamespace);
5279
const [isInitializing, setIsInitializing] = useState<boolean>(false);
5380
const [initError, setInitError] = useState<Error | null>(null);
54-
const [connection, setConnection] = useState<Connection | null>(null);
81+
const [connection, setConnection] = useState<Connection | null>(() => initialWeb3AuthState.connection);
5582
const [isInitialized, setIsInitialized] = useState<boolean>(false);
5683
const [isMFAEnabled, setIsMFAEnabled] = useState<boolean>(false);
57-
const web3Auth = useMemo(() => {
58-
setConnection(null);
59-
return new Web3AuthConstructor(web3AuthOptions, initialState);
60-
}, [Web3AuthConstructor, web3AuthOptions, initialState]);
61-
const [isConnected, setIsConnected] = useState<boolean>(false);
62-
const [status, setStatus] = useState<CONNECTOR_STATUS_TYPE | null>(null);
63-
const [isAuthorized, setIsAuthorized] = useState<boolean>(false);
84+
const [isConnected, setIsConnected] = useState<boolean>(initialWeb3AuthState.isConnected);
85+
const [status, setStatus] = useState<CONNECTOR_STATUS_TYPE | null>(initialWeb3AuthState.status);
86+
const [isAuthorized, setIsAuthorized] = useState<boolean>(initialWeb3AuthState.isAuthorized);
6487

6588
const getPlugin = useCallback(
6689
((name: string) => {
@@ -70,6 +93,19 @@ export function useWeb3AuthInnerContextValue<TWeb3Auth extends IWeb3Auth, TWeb3A
7093
[web3Auth]
7194
);
7295

96+
// Reset derived hook state when a new SDK instance is created.
97+
useEffect(() => {
98+
const nextState = getInitialState(web3Auth);
99+
100+
setConnection(nextState.connection);
101+
setIsMFAEnabled(false);
102+
setIsConnected(nextState.isConnected);
103+
setIsAuthorized(nextState.isAuthorized);
104+
setStatus(nextState.status);
105+
setChainId(nextState.chainId);
106+
setChainNamespace(nextState.chainNamespace);
107+
}, [web3Auth]);
108+
73109
useEffect(() => {
74110
const controller = new AbortController();
75111

packages/no-modal/test/noModal.test.ts

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { beforeAll, describe, expect, it, vi } from "vitest";
1+
import { describe, expect, it, vi } from "vitest";
22

33
import {
44
CHAIN_NAMESPACES,
@@ -41,15 +41,13 @@ class TestWeb3AuthNoModal extends Web3AuthNoModal {
4141
public exposeSubscribeToConnectorEvents(connector: MockConnector) {
4242
this.subscribeToConnectorEvents(connector as unknown as IConnector<unknown>);
4343
}
44+
45+
public exposeCompleteConsentAcceptance() {
46+
return this.completeConsentAcceptance();
47+
}
4448
}
4549

4650
describe("Web3AuthNoModal", () => {
47-
beforeAll(() => {
48-
vi.stubGlobal("window", {
49-
location: { origin: "http://localhost:3000" },
50-
});
51-
});
52-
5351
it("throws when clientId is missing", () => {
5452
expect(
5553
() =>
@@ -273,20 +271,21 @@ describe("Web3AuthNoModal", () => {
273271
await expect(sdk.getUserInfo()).rejects.toThrow(WalletLoginError);
274272
});
275273

276-
it("auto-skips consent UI when consent:<userId> is true", async () => {
274+
it("auto-skips consent UI when prior consent is true", async () => {
277275
const storage = createMockStorage();
278-
await storage.set(WEB3AUTH_STATE_STORAGE_KEY, JSON.stringify({ consentDecisions: { "0xabc123": true } }));
276+
await storage.set(WEB3AUTH_STATE_STORAGE_KEY, JSON.stringify({ hasUserConsent: true }));
279277
const sdk = createSdk({
280278
initialAuthenticationMode: CONNECTOR_INITIAL_AUTHENTICATION_MODE.CONNECT_AND_SIGN,
281279
storage: { sessionId: storage },
282280
});
281+
await Promise.resolve();
283282
sdk.exposeSetConsentRequired(true);
284283
const consentRequiredListener = vi.fn();
285284
sdk.on(CONNECTOR_EVENTS.CONSENT_REQUIRING, consentRequiredListener);
286285

287286
const ethereumProvider = { request: vi.fn().mockResolvedValue(["0xAbC123"]) };
288-
const consentAcceptedListener = vi.fn();
289-
sdk.on(CONNECTOR_EVENTS.CONSENT_ACCEPTED, consentAcceptedListener);
287+
const authorizedListener = vi.fn();
288+
sdk.on(CONNECTOR_EVENTS.AUTHORIZED, authorizedListener);
290289
const connector = new MockConnector({ name: WALLET_CONNECTORS.METAMASK } as never);
291290
(sdk as unknown as { connectors: MockConnector[] }).connectors = [connector];
292291
sdk.exposeSubscribeToConnectorEvents(connector);
@@ -309,20 +308,21 @@ describe("Web3AuthNoModal", () => {
309308
authTokenInfo: { idToken: "id-token" },
310309
});
311310
await vi.waitFor(() => {
312-
expect(consentAcceptedListener).toHaveBeenCalledTimes(1);
311+
expect(authorizedListener).toHaveBeenCalledTimes(1);
313312
});
314313

315314
expect(sdk.status).toBe(CONNECTOR_STATUS.AUTHORIZED);
316315
expect(consentRequiredListener).not.toHaveBeenCalled();
317316
});
318317

319-
it("shows consent UI when stored decision is false", async () => {
318+
it("shows consent UI when prior consent is false", async () => {
320319
const storage = createMockStorage();
321-
await storage.set(WEB3AUTH_STATE_STORAGE_KEY, JSON.stringify({ consentDecisions: { "0xbeef": false } }));
320+
await storage.set(WEB3AUTH_STATE_STORAGE_KEY, JSON.stringify({ hasUserConsent: false }));
322321
const sdk = createSdk({
323322
initialAuthenticationMode: CONNECTOR_INITIAL_AUTHENTICATION_MODE.CONNECT_ONLY,
324323
storage: { sessionId: storage },
325324
});
325+
await Promise.resolve();
326326
sdk.exposeSetConsentRequired(true);
327327
const consentRequiredListener = vi.fn();
328328
sdk.on(CONNECTOR_EVENTS.CONSENT_REQUIRING, consentRequiredListener);
@@ -349,11 +349,11 @@ describe("Web3AuthNoModal", () => {
349349
await vi.waitFor(() => {
350350
expect(consentRequiredListener).toHaveBeenCalledTimes(1);
351351
});
352-
await sdk.acceptConsent();
352+
await sdk.exposeCompleteConsentAcceptance();
353353
await expect(connectionPromise).resolves.not.toBeNull();
354354
});
355355

356-
it("persists consent:<userId> when user accepts consent UI", async () => {
356+
it("persists user consent when user accepts consent UI", async () => {
357357
const storage = createMockStorage();
358358
const sdk = createSdk({
359359
initialAuthenticationMode: CONNECTOR_INITIAL_AUTHENTICATION_MODE.CONNECT_ONLY,
@@ -385,12 +385,12 @@ describe("Web3AuthNoModal", () => {
385385
await vi.waitFor(() => {
386386
expect(consentRequiredListener).toHaveBeenCalledTimes(1);
387387
});
388-
await sdk.acceptConsent();
388+
await sdk.exposeCompleteConsentAcceptance();
389389
await connectionPromise;
390390

391391
const stateJson = await storage.get(WEB3AUTH_STATE_STORAGE_KEY);
392392
const state = JSON.parse(stateJson!);
393-
expect(state.consentDecisions["0xfeed"]).toBe(true);
393+
expect(state.hasUserConsent).toBe(true);
394394
});
395395

396396
it("setConnectors deduplicates and emits updates only for new connectors", () => {

packages/no-modal/test/reactContext.test.ts

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { SafeEventEmitter } from "@web3auth/auth";
2-
import { act, createElement } from "react";
2+
import { act, createElement, useMemo } from "react";
33
import { createRoot, type Root } from "react-dom/client";
44
import { afterEach, describe, expect, it } from "vitest";
55

@@ -41,6 +41,8 @@ let latestInstance: TestWeb3Auth | null = null;
4141
class TestWeb3Auth extends SafeEventEmitter<Web3AuthNoModalEvents> implements IWeb3Auth {
4242
public status: CONNECTOR_STATUS_TYPE;
4343

44+
public loginMode = LOGIN_MODE.MODAL;
45+
4446
public currentChainId: string | null = null;
4547

4648
public currentChain: CustomChainConfig | undefined = undefined;
@@ -68,16 +70,16 @@ class TestWeb3Auth extends SafeEventEmitter<Web3AuthNoModalEvents> implements IW
6870
type TestComponentProps = {
6971
renders: RenderSnapshot[];
7072
onValue?: (value: LiveSnapshot) => void;
71-
seedStateFromStatus: boolean;
7273
status: CONNECTOR_STATUS_TYPE;
7374
};
7475

75-
function TestComponent({ renders, onValue, seedStateFromStatus, status }: TestComponentProps): null {
76+
function TestComponent({ renders, onValue, status }: TestComponentProps): null {
77+
const web3AuthOptions = useMemo(() => ({ status }), [status]);
78+
7679
// @ts-expect-error - For testing purposes
7780
const value = useWeb3AuthInnerContextValue<TestWeb3Auth, TestWeb3AuthOptions>({
7881
Web3AuthConstructor: TestWeb3Auth,
79-
web3AuthOptions: { status },
80-
seedStateFromStatus,
82+
web3AuthOptions,
8183
});
8284

8385
const snapshot: LiveSnapshot = {
@@ -99,7 +101,7 @@ function TestComponent({ renders, onValue, seedStateFromStatus, status }: TestCo
99101
return null;
100102
}
101103

102-
async function renderHook(options: TestWeb3AuthOptions & { seedStateFromStatus: boolean }) {
104+
async function renderHook(options: TestWeb3AuthOptions) {
103105
const renders: RenderSnapshot[] = [];
104106
const latestValue: { current: LiveSnapshot | null } = { current: null };
105107
const container = document.createElement("div");
@@ -113,7 +115,6 @@ async function renderHook(options: TestWeb3AuthOptions & { seedStateFromStatus:
113115
onValue: (value: LiveSnapshot) => {
114116
latestValue.current = value;
115117
},
116-
seedStateFromStatus: options.seedStateFromStatus,
117118
status: options.status,
118119
})
119120
);
@@ -139,9 +140,8 @@ describe("useWeb3AuthInnerContextValue", () => {
139140
latestInstance = null;
140141
});
141142

142-
it("seeds a connected first render from sdk status when enabled", async () => {
143+
it("seeds a connected first render from sdk status", async () => {
143144
const rendered = await renderHook({
144-
seedStateFromStatus: true,
145145
status: CONNECTOR_STATUS.CONNECTED,
146146
});
147147
({ root, container } = rendered);
@@ -153,9 +153,8 @@ describe("useWeb3AuthInnerContextValue", () => {
153153
});
154154
});
155155

156-
it("seeds an authorized first render from sdk status when enabled", async () => {
156+
it("seeds an authorized first render from sdk status", async () => {
157157
const rendered = await renderHook({
158-
seedStateFromStatus: true,
159158
status: CONNECTOR_STATUS.AUTHORIZED,
160159
});
161160
({ root, container } = rendered);
@@ -167,23 +166,8 @@ describe("useWeb3AuthInnerContextValue", () => {
167166
});
168167
});
169168

170-
it("keeps the first render disconnected when seeding is disabled", async () => {
171-
const rendered = await renderHook({
172-
seedStateFromStatus: false,
173-
status: CONNECTOR_STATUS.CONNECTED,
174-
});
175-
({ root, container } = rendered);
176-
177-
expect(rendered.renders[0]).toEqual({
178-
isConnected: false,
179-
isAuthorized: false,
180-
status: null,
181-
});
182-
});
183-
184169
it("waits for consent acceptance before marking the hook connected", async () => {
185170
const rendered = await renderHook({
186-
seedStateFromStatus: false,
187171
status: CONNECTOR_STATUS.CONNECTING,
188172
});
189173
({ root, container } = rendered);

0 commit comments

Comments
 (0)