All checks were successful
check / check (push) Successful in 30s
Deleting a wallet left three defects in the same path: - `hasWallet` stayed true after the last wallet was deleted, so the next popup open rendered Home with "No wallets yet" instead of Welcome. It now tracks whether any wallet remains. - The selection was reset to wallet 0 / address 0 unconditionally. `selectedWallet` now follows the splice (decremented when a wallet before it is removed), and only falls back to the first remaining wallet's first address when the selection itself was deleted; `activeAddress` only moves when it belonged to the deleted wallet. - No `AUTISTMASK_ACTIVE_CHANGED` was sent, so connected sites kept reporting a deleted address. The delete path now broadcasts it after the state is persisted, whenever the active address actually changed, and the background re-emits `accountsChanged` from there. The transition moved into `src/shared/walletDelete.js` so it can be tested without a DOM. Site-permission cleanup is unchanged and still covers every address of an HD wallet.
130 lines
4.1 KiB
JavaScript
130 lines
4.1 KiB
JavaScript
const {
|
|
removeWalletFromState,
|
|
broadcastActiveChanged,
|
|
} = require("../src/shared/walletDelete");
|
|
|
|
// Fixed addresses — never used for anything but these tests.
|
|
const A0 = "0x66133E8ea0f5D1d612D2502a968757D1048c214a";
|
|
const A1 = "0xdAC17F958D2ee523a2206206994597C13D831ec7";
|
|
const B0 = "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599";
|
|
const C0 = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
|
|
|
|
function wallet(name, addresses) {
|
|
return {
|
|
name,
|
|
addresses: addresses.map((address) => ({ address })),
|
|
};
|
|
}
|
|
|
|
// A three-wallet state; wallet A is an HD wallet with two addresses.
|
|
function makeState(overrides = {}) {
|
|
return {
|
|
hasWallet: true,
|
|
wallets: [wallet("A", [A0, A1]), wallet("B", [B0]), wallet("C", [C0])],
|
|
selectedWallet: 0,
|
|
selectedAddress: 0,
|
|
activeAddress: A0,
|
|
allowedSites: {
|
|
[A0]: ["a.example"],
|
|
[A1]: ["b.example"],
|
|
[B0]: ["c.example"],
|
|
},
|
|
deniedSites: { [A1]: ["d.example"], [C0]: ["e.example"] },
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
describe("removeWalletFromState", () => {
|
|
test("deleting the last wallet clears hasWallet", () => {
|
|
const state = makeState({
|
|
wallets: [wallet("A", [A0])],
|
|
allowedSites: { [A0]: ["a.example"] },
|
|
deniedSites: {},
|
|
});
|
|
|
|
const { activeAddressChanged } = removeWalletFromState(state, 0);
|
|
|
|
expect(state.hasWallet).toBe(false);
|
|
expect(state.wallets).toEqual([]);
|
|
expect(state.selectedWallet).toBeNull();
|
|
expect(state.selectedAddress).toBeNull();
|
|
expect(state.activeAddress).toBeNull();
|
|
expect(activeAddressChanged).toBe(true);
|
|
});
|
|
|
|
test("deleting a non-selected wallet leaves the selection intact", () => {
|
|
const state = makeState({
|
|
selectedWallet: 2,
|
|
selectedAddress: 0,
|
|
activeAddress: C0,
|
|
});
|
|
|
|
const { activeAddressChanged } = removeWalletFromState(state, 1);
|
|
|
|
// Wallet C moved from index 2 to index 1 by the splice.
|
|
expect(state.wallets.map((w) => w.name)).toEqual(["A", "C"]);
|
|
expect(state.selectedWallet).toBe(1);
|
|
expect(state.selectedAddress).toBe(0);
|
|
expect(state.activeAddress).toBe(C0);
|
|
expect(activeAddressChanged).toBe(false);
|
|
expect(state.hasWallet).toBe(true);
|
|
});
|
|
|
|
test("deleting a wallet after the selection does not shift it", () => {
|
|
const state = makeState({
|
|
selectedWallet: 1,
|
|
selectedAddress: 0,
|
|
activeAddress: B0,
|
|
});
|
|
|
|
const { activeAddressChanged } = removeWalletFromState(state, 2);
|
|
|
|
expect(state.selectedWallet).toBe(1);
|
|
expect(state.activeAddress).toBe(B0);
|
|
expect(activeAddressChanged).toBe(false);
|
|
});
|
|
|
|
test("deleting the active wallet falls back to the first remaining address", () => {
|
|
const state = makeState({
|
|
selectedWallet: 0,
|
|
selectedAddress: 1,
|
|
activeAddress: A1,
|
|
});
|
|
|
|
const { activeAddressChanged } = removeWalletFromState(state, 0);
|
|
|
|
expect(state.wallets.map((w) => w.name)).toEqual(["B", "C"]);
|
|
expect(state.selectedWallet).toBe(0);
|
|
expect(state.selectedAddress).toBe(0);
|
|
expect(state.activeAddress).toBe(B0);
|
|
expect(activeAddressChanged).toBe(true);
|
|
expect(state.hasWallet).toBe(true);
|
|
});
|
|
|
|
test("site permissions are dropped for every address of the wallet", () => {
|
|
const state = makeState();
|
|
|
|
removeWalletFromState(state, 0);
|
|
|
|
expect(state.allowedSites).toEqual({ [B0]: ["c.example"] });
|
|
expect(state.deniedSites).toEqual({ [C0]: ["e.example"] });
|
|
});
|
|
});
|
|
|
|
describe("broadcastActiveChanged", () => {
|
|
afterEach(() => {
|
|
delete global.chrome;
|
|
});
|
|
|
|
test("sends AUTISTMASK_ACTIVE_CHANGED to the background", () => {
|
|
const sendMessage = jest.fn();
|
|
global.chrome = { runtime: { sendMessage } };
|
|
|
|
broadcastActiveChanged();
|
|
|
|
expect(sendMessage).toHaveBeenCalledWith({
|
|
type: "AUTISTMASK_ACTIVE_CHANGED",
|
|
});
|
|
});
|
|
});
|