fix: a saved SuccessTx in another shape reopens as itself, and long amounts wrap (closes #740)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s

The popup refused a saved SuccessTx whose decoded record was in a shape it
did not expect, and showed Home. SuccessTx already shows only the lines it
can read, so the popup no longer checks the record first.

A long amount or token symbol was cut off at the edge of the screen. The
Amount figure, each decoded amount and the token symbol now wrap. WaitTx and
ErrorTx share the line that shows the symbol, so they gain this too.

Model: opus-5-5
This commit is contained in:
2026-11-03 09:19:41 +00:00
parent 448afdb5ce
commit 5c89a62a9d
6 changed files with 74 additions and 37 deletions
+48 -14
View File
@@ -416,20 +416,6 @@ const CONTRACT = [
views: ["success-tx"],
restored: false,
},
{
value: { hash: "0x1", to: ADDRESS, decoded: { details: 7 } },
views: ["success-tx"],
restored: false,
},
{
value: {
hash: "0x1",
to: ADDRESS,
decoded: { details: [{ address: 42 }] },
},
views: ["success-tx"],
restored: false,
},
// error-tx passes on `data.message`, same dereference.
{
value: { message: "boom" },
@@ -1082,3 +1068,51 @@ describe("a restore-only hostile value onto", () => {
}
}
});
// A saved decoded record comes back from storage, in whatever shape it is in.
// SuccessTx reopens as itself and shows only the lines it can read.
describe("a popup reopened on a SuccessTx with a decoded record in another shape", () => {
function savedSuccess(decoded) {
return restoringOnto("success-tx", {
viewData: {
amount: "1.0000",
symbol: "ETH",
to: ADDRESS,
hash: "0x1",
chainId: "0x1",
decoded,
},
});
}
test.each([
7,
"text",
[1, 2],
{ details: 7 },
{ details: [null] },
{ details: [7] },
{ details: [{ address: 42 }] },
{ details: [{ label: "Steps", value: "text", address: 42 }] },
])("%j shows the amount and the recipient", async (decoded) => {
const page = await bootPopup(savedSuccess(decoded));
expect(page.pageErrors).toEqual([]);
expect(page.visibleViews()).toEqual(["success-tx"]);
expect(page.hidden("success-tx-decoded")).toBe(true);
expect(page.text("success-tx-summary")).toBe("1.0000 ETH");
expect(page.node("success-tx-to").innerHTML).toContain(ADDRESS);
});
test("a line it can read is shown", async () => {
const page = await bootPopup(
savedSuccess({
details: [null, { label: "Steps", value: "V3_SWAP_EXACT_IN" }],
}),
);
expect(page.pageErrors).toEqual([]);
expect(page.visibleViews()).toEqual(["success-tx"]);
expect(page.node("success-tx-decoded").innerHTML).toContain(
"V3_SWAP_EXACT_IN",
);
});
});
+1 -1
View File
@@ -459,7 +459,7 @@ describe("a swap that gives another spender an allowance", () => {
expect(html).toContain("Permit2 allowance");
expect(html).toContain("Unlimited");
expect(html).toContain("Allowance token");
expect(html).toContain('<div class="font-bold">USDC</div>');
expect(html).toContain('<div class="font-bold break-words">USDC</div>');
expect(html).toContain(`data-copy="${USDC}"`);
}
+19 -3
View File
@@ -636,7 +636,7 @@ describe("SuccessTx and ErrorTx for a Sepolia transaction with mainnet active",
test("SuccessTx's decoded action names the token from the tokens tracked on Sepolia", async () => {
function expectTokenNamed() {
expect(getElement("success-tx-decoded").innerHTML).toContain(
'<div class="font-bold">TDOL</div>',
'<div class="font-bold break-words">TDOL</div>',
);
}
state.networkTrackedTokens = {
@@ -810,7 +810,7 @@ describe("the Permit2 allowance lines of a swap on WaitTx and ErrorTx", () => {
expect(html.indexOf("Unlimited")).toBeLessThan(
html.indexOf("Allowance token"),
);
expect(html).toContain('<div class="font-bold">USDC</div>');
expect(html).toContain('<div class="font-bold break-words">USDC</div>');
expect(html).toContain(`data-copy="${USDC}"`);
expect(html).toContain(`href="https://etherscan.io/address/${USDC}"`);
expect(html).toMatch(/<div class="text-xs">.*class="am-address"/);
@@ -869,7 +869,7 @@ describe("the Permit2 allowance lines of a swap on WaitTx and ErrorTx", () => {
// An amount of about 47 digits or more is wider than the screen. Without the
// break-words class its last digits are cut off at the edge. That class keeps
// the words of a line such as `(decimals unknown)` whole.
describe("a long amount on WaitTx and ErrorTx", () => {
describe("a long amount on WaitTx, ErrorTx and SuccessTx", () => {
test("each amount under the Amount figure wraps", () => {
const decoded = {
details: [
@@ -896,6 +896,22 @@ describe("a long amount on WaitTx and ErrorTx", () => {
expect(html).toMatch(
/id="error-tx-summary"\s+class="font-bold break-words"/,
);
expect(html).toMatch(
/id="success-tx-summary"\s+class="font-bold break-words"/,
);
});
test("each amount of SuccessTx's decoded action wraps", () => {
state.viewData = {
hash: TX_HASH,
to: RECIPIENT,
chainId: TX_INFO.chainId,
decoded: { details: [{ label: "Amount", value: "1.0000 ETH" }] },
};
txStatus.renderSuccess();
expect(getElement("success-tx-decoded").innerHTML).toContain(
'<div class="font-bold break-words">1.0000 ETH<',
);
});
});