Compare commits
1
Commits
next
..
c56179abff
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c56179abff |
@@ -581,9 +581,8 @@ Transitions:
|
|||||||
- "+": derives the next address in place.
|
- "+": derives the next address in place.
|
||||||
- `[info]`: AddressDetail.
|
- `[info]`: AddressDetail.
|
||||||
- `[x]`: DeleteAddress.
|
- `[x]`: DeleteAddress.
|
||||||
- "Send": Send, with its dropdown on ETH. Refused with a flash message when the
|
- "Send": Send. Refused with a flash message when the active address has a zero
|
||||||
active address has a zero ETH balance or belongs to a wallet carrying the
|
ETH balance or belongs to a wallet carrying the `walletDefects.js` notice.
|
||||||
`walletDefects.js` notice.
|
|
||||||
- "Receive": Receive.
|
- "Receive": Receive.
|
||||||
- Tap a transaction row: TransactionDetail.
|
- Tap a transaction row: TransactionDetail.
|
||||||
- "Add additional wallet...": AddWallet.
|
- "Add additional wallet...": AddWallet.
|
||||||
|
|||||||
@@ -360,11 +360,6 @@ function init(_ctx) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
$("btn-address-token-back").addEventListener("click", () => {
|
$("btn-address-token-back").addEventListener("click", () => {
|
||||||
// AddressDetail's show() clears the token, but Back onto a drawn
|
|
||||||
// screen only unhides it. "Send" below may have left the dropdown on
|
|
||||||
// the token as well.
|
|
||||||
state.selectedToken = null;
|
|
||||||
$("send-token").value = "ETH";
|
|
||||||
goBack();
|
goBack();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -510,15 +510,11 @@ function init(ctx) {
|
|||||||
showFlash("Cannot send \u2014 zero balance.");
|
showFlash("Cannot send \u2014 zero balance.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Send uses a selected token ahead of its dropdown, and AddressToken
|
|
||||||
// can leave one selected on the way here.
|
|
||||||
state.selectedToken = null;
|
|
||||||
$("send-to").value = "";
|
$("send-to").value = "";
|
||||||
$("send-amount").value = "";
|
$("send-amount").value = "";
|
||||||
$("send-token-dropdown").classList.remove("hidden");
|
$("send-token-dropdown").classList.remove("hidden");
|
||||||
$("send-token-static").classList.add("hidden");
|
$("send-token-static").classList.add("hidden");
|
||||||
renderSendTokenSelect(addr);
|
renderSendTokenSelect(addr);
|
||||||
$("send-token").value = "ETH";
|
|
||||||
updateSendBalance();
|
updateSendBalance();
|
||||||
resetSendValidation();
|
resetSendValidation();
|
||||||
pushCurrentView();
|
pushCurrentView();
|
||||||
@@ -530,9 +526,6 @@ function init(ctx) {
|
|||||||
showFlash("No active address selected.");
|
showFlash("No active address selected.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Receive warns about a selected token, and AddressToken can leave one
|
|
||||||
// selected on the way here.
|
|
||||||
state.selectedToken = null;
|
|
||||||
ctx.showReceive();
|
ctx.showReceive();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,165 +0,0 @@
|
|||||||
// "Back" from AddressToken leaves no token selected. AddressDetail's show()
|
|
||||||
// would clear it, but Back onto a drawn screen only unhides that screen, and
|
|
||||||
// Send and Receive both read the field
|
|
||||||
// (https://git.eeqj.de/sneak/AutistMask/issues/751). Driven through the real
|
|
||||||
// popup over a stored profile.
|
|
||||||
|
|
||||||
const {
|
|
||||||
bootPopup,
|
|
||||||
cleanupPopup,
|
|
||||||
unversionedValidProfile,
|
|
||||||
TOKEN_ADDRESS,
|
|
||||||
} = require("./support/popupBoot");
|
|
||||||
|
|
||||||
const RECIPIENT = "0x711e691962E5c054b78071C789A0C8CE657377aD";
|
|
||||||
const TOKEN = {
|
|
||||||
address: TOKEN_ADDRESS,
|
|
||||||
symbol: "TST",
|
|
||||||
decimals: 18,
|
|
||||||
name: "Test Token",
|
|
||||||
};
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
cleanupPopup();
|
|
||||||
});
|
|
||||||
|
|
||||||
// The popup reopened onto AddressDetail, at an address holding 1.5 ETH and
|
|
||||||
// 2.5 TST.
|
|
||||||
function bootOnAddress() {
|
|
||||||
const profile = unversionedValidProfile({
|
|
||||||
currentView: "address",
|
|
||||||
viewStack: ["main"],
|
|
||||||
selectedWallet: 0,
|
|
||||||
selectedAddress: 0,
|
|
||||||
trackedTokens: [TOKEN],
|
|
||||||
});
|
|
||||||
profile.wallets[0].addresses[0].tokenBalances = [
|
|
||||||
{ ...TOKEN, balance: "2.5" },
|
|
||||||
];
|
|
||||||
return bootPopup(profile);
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddressToken opened from AddressDetail, as tapping the token's row does.
|
|
||||||
async function openToken(page) {
|
|
||||||
const { state } = require("../src/shared/state");
|
|
||||||
state.selectedToken = TOKEN_ADDRESS;
|
|
||||||
require("../src/popup/views/helpers").pushCurrentView();
|
|
||||||
require("../src/popup/views/addressToken").show();
|
|
||||||
await page.settle();
|
|
||||||
expect(page.visibleViews()).toEqual(["address-token"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function backFromToken(page) {
|
|
||||||
await page.click("btn-address-token-back");
|
|
||||||
expect(page.visibleViews()).toEqual(["address"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ETH chosen in Send's dropdown, as the user does.
|
|
||||||
async function chooseEth(page) {
|
|
||||||
const dropdown = page.node("send-token");
|
|
||||||
dropdown.value = "ETH";
|
|
||||||
for (const fn of dropdown.listeners.change) await fn();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Review for 1 of the token Send has, to RECIPIENT.
|
|
||||||
async function review(page) {
|
|
||||||
page.node("send-to").value = RECIPIENT;
|
|
||||||
page.node("send-amount").value = "1";
|
|
||||||
await page.click("btn-send-review");
|
|
||||||
expect(page.visibleViews()).toEqual(["confirm-tx"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
describe("after Back from AddressToken", () => {
|
|
||||||
test("no token is selected, on the page or in the stored record", async () => {
|
|
||||||
const page = await bootOnAddress();
|
|
||||||
await openToken(page);
|
|
||||||
await backFromToken(page);
|
|
||||||
|
|
||||||
const { state } = require("../src/shared/state");
|
|
||||||
expect(state.selectedToken).toBeNull();
|
|
||||||
expect(page.storage.read("autistmask").selectedToken).toBeNull();
|
|
||||||
});
|
|
||||||
|
|
||||||
test("Send with ETH chosen shows the ETH balance", async () => {
|
|
||||||
const page = await bootOnAddress();
|
|
||||||
await openToken(page);
|
|
||||||
await backFromToken(page);
|
|
||||||
|
|
||||||
await page.click("btn-send");
|
|
||||||
await chooseEth(page);
|
|
||||||
|
|
||||||
expect(page.text("send-balance")).toBe("Current balance: 1.5000 ETH");
|
|
||||||
});
|
|
||||||
|
|
||||||
test("Send with ETH chosen reviews ETH", async () => {
|
|
||||||
const page = await bootOnAddress();
|
|
||||||
await openToken(page);
|
|
||||||
await backFromToken(page);
|
|
||||||
|
|
||||||
await page.click("btn-send");
|
|
||||||
await chooseEth(page);
|
|
||||||
await review(page);
|
|
||||||
|
|
||||||
expect(page.text("confirm-type")).toBe("Native ETH transfer");
|
|
||||||
});
|
|
||||||
|
|
||||||
test("Receive shows no token warning", async () => {
|
|
||||||
const page = await bootOnAddress();
|
|
||||||
await openToken(page);
|
|
||||||
await backFromToken(page);
|
|
||||||
|
|
||||||
await page.click("btn-receive");
|
|
||||||
|
|
||||||
expect(page.visibleViews()).toEqual(["receive"]);
|
|
||||||
expect(page.text("receive-erc20-warning")).toBe("");
|
|
||||||
});
|
|
||||||
|
|
||||||
// AddressToken's Send sets the dropdown to the token, and nothing else
|
|
||||||
// rebuilds it on the way back to AddressDetail.
|
|
||||||
test("Send opens on ETH after AddressToken's Send has been used", async () => {
|
|
||||||
const page = await bootOnAddress();
|
|
||||||
await openToken(page);
|
|
||||||
await page.click("btn-address-token-send");
|
|
||||||
await page.click("btn-send-back");
|
|
||||||
await backFromToken(page);
|
|
||||||
|
|
||||||
await page.click("btn-send");
|
|
||||||
|
|
||||||
expect(page.value("send-token")).toBe("ETH");
|
|
||||||
expect(page.text("send-balance")).toBe("Current balance: 1.5000 ETH");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Send opened from AddressToken sends that token", () => {
|
|
||||||
async function expectSendsToken(page) {
|
|
||||||
await page.click("btn-address-token-send");
|
|
||||||
expect(page.text("send-balance")).toBe("Current balance: 2.5000 TST");
|
|
||||||
await review(page);
|
|
||||||
expect(page.text("confirm-type")).toBe("ERC-20 token transfer (TST)");
|
|
||||||
}
|
|
||||||
|
|
||||||
test("the first time", async () => {
|
|
||||||
const page = await bootOnAddress();
|
|
||||||
await openToken(page);
|
|
||||||
|
|
||||||
await expectSendsToken(page);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("after Back from Send", async () => {
|
|
||||||
const page = await bootOnAddress();
|
|
||||||
await openToken(page);
|
|
||||||
await page.click("btn-address-token-send");
|
|
||||||
await page.click("btn-send-back");
|
|
||||||
|
|
||||||
await expectSendsToken(page);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("when the token is opened again after Back from AddressToken", async () => {
|
|
||||||
const page = await bootOnAddress();
|
|
||||||
await openToken(page);
|
|
||||||
await backFromToken(page);
|
|
||||||
await openToken(page);
|
|
||||||
|
|
||||||
await expectSendsToken(page);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,185 +0,0 @@
|
|||||||
// Home's "Send" and "Receive" open with no token selected. Three routes reach
|
|
||||||
// Home with a token still selected, Send reads that token ahead of its dropdown,
|
|
||||||
// and Receive warns about it
|
|
||||||
// (https://git.eeqj.de/sneak/AutistMask/issues/753). Driven through the real
|
|
||||||
// popup over a stored profile.
|
|
||||||
|
|
||||||
const {
|
|
||||||
bootPopup,
|
|
||||||
cleanupPopup,
|
|
||||||
unversionedValidProfile,
|
|
||||||
TOKEN_ADDRESS,
|
|
||||||
} = require("./support/popupBoot");
|
|
||||||
|
|
||||||
const RECIPIENT = "0x711e691962E5c054b78071C789A0C8CE657377aD";
|
|
||||||
const OTHER_WALLET_ADDRESS = "0xdAC17F958D2ee523a2206206994597C13D831ec7";
|
|
||||||
const PRIVATE_KEY = "0x" + "11".repeat(32);
|
|
||||||
const PASSWORD = "correct horse battery staple";
|
|
||||||
const TOKEN = {
|
|
||||||
address: TOKEN_ADDRESS,
|
|
||||||
symbol: "TST",
|
|
||||||
decimals: 18,
|
|
||||||
name: "Test Token",
|
|
||||||
};
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
cleanupPopup();
|
|
||||||
});
|
|
||||||
|
|
||||||
// AddressToken opened from AddressDetail, as tapping the token's row does.
|
|
||||||
async function openToken(page) {
|
|
||||||
const { state } = require("../src/shared/state");
|
|
||||||
state.selectedToken = TOKEN_ADDRESS;
|
|
||||||
require("../src/popup/views/helpers").pushCurrentView();
|
|
||||||
require("../src/popup/views/addressToken").show();
|
|
||||||
await page.settle();
|
|
||||||
expect(page.visibleViews()).toEqual(["address-token"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The popup open on AddressToken, at an address holding 1.5 ETH and 2.5 TST.
|
|
||||||
// A second wallet is there for the route that deletes one.
|
|
||||||
async function bootOnToken() {
|
|
||||||
const profile = unversionedValidProfile({
|
|
||||||
currentView: "address",
|
|
||||||
viewStack: ["main"],
|
|
||||||
selectedWallet: 0,
|
|
||||||
selectedAddress: 0,
|
|
||||||
trackedTokens: [TOKEN],
|
|
||||||
});
|
|
||||||
profile.wallets[0].addresses[0].tokenBalances = [
|
|
||||||
{ ...TOKEN, balance: "2.5" },
|
|
||||||
];
|
|
||||||
profile.wallets.push({
|
|
||||||
type: "hd",
|
|
||||||
name: "Wallet 2",
|
|
||||||
xpub: "xpub-wallet-2",
|
|
||||||
encryptedSecret: "encrypted-secret-2",
|
|
||||||
nextIndex: 1,
|
|
||||||
addresses: [
|
|
||||||
{
|
|
||||||
address: OTHER_WALLET_ADDRESS,
|
|
||||||
balance: "0",
|
|
||||||
tokenBalances: [],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
const page = await bootPopup(profile);
|
|
||||||
await openToken(page);
|
|
||||||
return page;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function reopenAfterTokenSend() {
|
|
||||||
const closed = await bootOnToken();
|
|
||||||
await closed.click("btn-address-token-send");
|
|
||||||
cleanupPopup();
|
|
||||||
return bootPopup(undefined, { storage: closed.storage });
|
|
||||||
}
|
|
||||||
|
|
||||||
async function addWalletFromTokenSettings() {
|
|
||||||
const page = await bootOnToken();
|
|
||||||
await page.click("btn-settings");
|
|
||||||
await page.click("btn-main-add-wallet");
|
|
||||||
await page.click("tab-privkey");
|
|
||||||
page.node("import-private-key").value = PRIVATE_KEY;
|
|
||||||
page.node("add-wallet-password").value = PASSWORD;
|
|
||||||
page.node("add-wallet-password-confirm").value = PASSWORD;
|
|
||||||
await page.click("btn-add-wallet-confirm");
|
|
||||||
return page;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deletes through the lost-password screen. It asks for the wallet's name, and
|
|
||||||
// the stored wallets here have no real password.
|
|
||||||
async function deleteWalletFromTokenSettings() {
|
|
||||||
const page = await bootOnToken();
|
|
||||||
await page.click("btn-settings");
|
|
||||||
// What the second wallet's [x] button in Settings does.
|
|
||||||
require("../src/popup/views/helpers").pushCurrentView();
|
|
||||||
require("../src/popup/views/deleteWallet").show(1);
|
|
||||||
await page.click("btn-delete-wallet-lost-password");
|
|
||||||
page.node("delete-wallet-lost-name-input").value = "Wallet 2";
|
|
||||||
await page.click("btn-delete-wallet-lost-confirm");
|
|
||||||
await page.click("btn-settings-back");
|
|
||||||
return page;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ROUTES = [
|
|
||||||
["reopening the popup after AddressToken's Send", reopenAfterTokenSend],
|
|
||||||
[
|
|
||||||
"the Settings gear on AddressToken, then adding a wallet",
|
|
||||||
addWalletFromTokenSettings,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"the Settings gear on AddressToken, then deleting another wallet, then Back",
|
|
||||||
deleteWalletFromTokenSettings,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
// A route that stopped reaching Home with the token selected would prove nothing
|
|
||||||
// in the tests below, so it fails here.
|
|
||||||
async function arriveOnHome(route) {
|
|
||||||
const page = await route();
|
|
||||||
const { state } = require("../src/shared/state");
|
|
||||||
expect(page.visibleViews()).toEqual(["main"]);
|
|
||||||
expect(state.selectedToken).toBe(TOKEN_ADDRESS);
|
|
||||||
return page;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ETH chosen in Send's dropdown, as the user does.
|
|
||||||
async function chooseEth(page) {
|
|
||||||
const dropdown = page.node("send-token");
|
|
||||||
dropdown.value = "ETH";
|
|
||||||
for (const fn of dropdown.listeners.change) await fn();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Review for 1 of the token Send has, to RECIPIENT.
|
|
||||||
async function review(page) {
|
|
||||||
page.node("send-to").value = RECIPIENT;
|
|
||||||
page.node("send-amount").value = "1";
|
|
||||||
await page.click("btn-send-review");
|
|
||||||
expect(page.visibleViews()).toEqual(["confirm-tx"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
describe.each(ROUTES)("after %s", (_name, route) => {
|
|
||||||
test("choosing ETH on Home's Send reviews ETH", async () => {
|
|
||||||
const page = await arriveOnHome(route);
|
|
||||||
|
|
||||||
await page.click("btn-main-send");
|
|
||||||
await chooseEth(page);
|
|
||||||
await review(page);
|
|
||||||
|
|
||||||
expect(page.text("confirm-type")).toBe("Native ETH transfer");
|
|
||||||
expect(page.storage.read("autistmask").selectedToken).toBeNull();
|
|
||||||
});
|
|
||||||
|
|
||||||
test("Home's Send starts on ETH", async () => {
|
|
||||||
const page = await arriveOnHome(route);
|
|
||||||
|
|
||||||
await page.click("btn-main-send");
|
|
||||||
|
|
||||||
expect(page.text("send-balance")).toBe("Current balance: 1.5000 ETH");
|
|
||||||
expect(page.value("send-token")).toBe("ETH");
|
|
||||||
});
|
|
||||||
|
|
||||||
test("Home's Receive shows no token warning", async () => {
|
|
||||||
const page = await arriveOnHome(route);
|
|
||||||
|
|
||||||
await page.click("btn-main-receive");
|
|
||||||
|
|
||||||
expect(page.visibleViews()).toEqual(["receive"]);
|
|
||||||
expect(page.text("receive-erc20-warning")).toBe("");
|
|
||||||
expect(page.storage.read("autistmask").selectedToken).toBeNull();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("AddressToken's Send still sends the token after Home's Send has opened", async () => {
|
|
||||||
const page = await arriveOnHome(deleteWalletFromTokenSettings);
|
|
||||||
await page.click("btn-main-send");
|
|
||||||
await page.click("btn-send-back");
|
|
||||||
await openToken(page);
|
|
||||||
|
|
||||||
await page.click("btn-address-token-send");
|
|
||||||
|
|
||||||
expect(page.text("send-balance")).toBe("Current balance: 2.5000 TST");
|
|
||||||
await review(page);
|
|
||||||
expect(page.text("confirm-type")).toBe("ERC-20 token transfer (TST)");
|
|
||||||
});
|
|
||||||
Reference in New Issue
Block a user