Skip to content

Commit ecc9400

Browse files
netzenbotclaude
authored andcommitted
Fix flaky BraveWalletSignMessageBrowserTest.SIWE test (#34285)
* Fix flaky BraveWalletSignMessageBrowserTest.SIWE test The SIWE test sends two sign messages per iteration: one with matching origin and one with a different origin ("www.a.com"). The second message is rejected immediately by the provider, overwriting the global signMessageResult variable with an error. After NotifySignMessageRequestProcessed approves the first message, the test immediately checked signMessageResult, but the mojo approval response may not have been delivered to the renderer yet, so signMessageResult still contained the rejection error. Fix by replacing the immediate getSignMessageResult() check with a Promise-based wait that polls until signMessageResult is a string starting with "0x" (the signature). This is safe because both the rejection and approval go through the same mojo interface, so the rejection always arrives before the approval. Resolves brave/brave-browser#53167 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Address review: fix same race condition in other sign message tests Apply the same async polling pattern to UserApprovedRequest and UserRejectedRequest tests, which had the same race condition of calling getSignMessageResult() immediately after NotifySignMessageRequestProcessed() without waiting for the mojo response to arrive at the renderer. --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent fb3dc2f commit ecc9400

File tree

1 file changed

+46
-3
lines changed

1 file changed

+46
-3
lines changed

browser/brave_wallet/brave_wallet_sign_message_browsertest.cc

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,27 @@ namespace brave_wallet {
3737

3838
namespace {
3939

40+
// Waits for signMessageResult to be set to a string value. After
41+
// NotifySignMessageRequestProcessed() the result is delivered asynchronously
42+
// to the renderer via mojo, so we must poll rather than reading it immediately.
43+
constexpr char kWaitForSignMessageResult[] = R"(
44+
new Promise((resolve, reject) => {
45+
const deadline = Date.now() + 10000;
46+
const check = () => {
47+
if (typeof signMessageResult === 'string') {
48+
const result = signMessageResult;
49+
signMessageResult = undefined;
50+
resolve(result);
51+
} else if (Date.now() >= deadline) {
52+
reject(new Error('Timeout: signMessageResult=' +
53+
signMessageResult));
54+
} else {
55+
setTimeout(check, 10);
56+
}
57+
};
58+
check();
59+
}))";
60+
4061
bool WaitForWalletBubble(content::WebContents* web_contents) {
4162
auto* tab_helper =
4263
brave_wallet::BraveWalletTabHelper::FromWebContents(web_contents);
@@ -168,7 +189,7 @@ IN_PROC_BROWSER_TEST_F(BraveWalletSignMessageBrowserTest, UserApprovedRequest) {
168189
EXPECT_TRUE(WaitForWalletBubble(web_contents()));
169190
brave_wallet_service()->NotifySignMessageRequestProcessed(
170191
true, request_index++, nullptr, std::nullopt);
171-
EXPECT_EQ(EvalJs(web_contents(), "getSignMessageResult()").ExtractString(),
192+
EXPECT_EQ(EvalJs(web_contents(), kWaitForSignMessageResult).ExtractString(),
172193
"0x670651c072cac2a3f93cb862a17378f6849c66b4516e5d5a30210868a2840e"
173194
"2a6a345a"
174195
"4f84615c591c1a47260e798babe8f2f0cce03a09dac09df79c55d8e4401b");
@@ -196,7 +217,7 @@ IN_PROC_BROWSER_TEST_F(BraveWalletSignMessageBrowserTest, UserRejectedRequest) {
196217
EXPECT_TRUE(WaitForWalletBubble(web_contents()));
197218
brave_wallet_service()->NotifySignMessageRequestProcessed(
198219
false, request_index++, nullptr, std::nullopt);
199-
EXPECT_EQ(EvalJs(web_contents(), "getSignMessageResult()").ExtractString(),
220+
EXPECT_EQ(EvalJs(web_contents(), kWaitForSignMessageResult).ExtractString(),
200221
l10n_util::GetStringUTF8(IDS_WALLET_USER_REJECTED_REQUEST));
201222
}
202223
}
@@ -334,8 +355,30 @@ IN_PROC_BROWSER_TEST_F(BraveWalletSignMessageBrowserTest, SIWE) {
334355
EXPECT_TRUE(WaitForWalletBubble(web_contents()));
335356
brave_wallet_service()->NotifySignMessageRequestProcessed(
336357
true, request_index++, nullptr, std::nullopt);
358+
// The second sign message (wrong origin) is rejected immediately,
359+
// overwriting signMessageResult with an error before the approved
360+
// first message's signature arrives via mojo. Wait for the signature
361+
// (starts with "0x") to be delivered to the renderer.
362+
static constexpr char kWaitForSignResult[] = R"(
363+
new Promise((resolve, reject) => {
364+
const deadline = Date.now() + 10000;
365+
const check = () => {
366+
if (typeof signMessageResult === 'string' &&
367+
signMessageResult.startsWith('0x')) {
368+
const result = signMessageResult;
369+
signMessageResult = undefined;
370+
resolve(result);
371+
} else if (Date.now() >= deadline) {
372+
reject(new Error('Timeout: signMessageResult=' +
373+
signMessageResult));
374+
} else {
375+
setTimeout(check, 10);
376+
}
377+
};
378+
check();
379+
}))";
337380
// port is dynamic
338-
EXPECT_TRUE(EvalJs(web_contents(), "getSignMessageResult()")
381+
EXPECT_TRUE(EvalJs(web_contents(), kWaitForSignResult)
339382
.ExtractString()
340383
.starts_with("0x"));
341384
}

0 commit comments

Comments
 (0)