Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8009a46cc9 |
@@ -146,8 +146,8 @@ const sweptValues = (row) => [...row.hostile, ...(row.falsy || [])];
|
|||||||
// particular branch's gate has let it past. Each of its entries names the
|
// particular branch's gate has let it past. Each of its entries names the
|
||||||
// `views` it is driven onto and declares whether the boot lands on them
|
// `views` it is driven onto and declares whether the boot lands on them
|
||||||
// (`restored: true`) or falls back to Home (`restored: false`), so a value
|
// (`restored: true`) or falls back to Home (`restored: false`), so a value
|
||||||
// written for one renderer cannot stop reaching it unnoticed. A value that
|
// written for one renderer cannot stop reaching it unnoticed. A value driven
|
||||||
// lands on some views and not others is one entry per outcome.
|
// onto every restorable view is written with everyRestorableView() below.
|
||||||
//
|
//
|
||||||
// `falsy` is the other POLARITY of a swept field, driven for the same reason.
|
// `falsy` is the other POLARITY of a swept field, driven for the same reason.
|
||||||
// It is not a value src/ never writes — for three of these fields it is the
|
// It is not a value src/ never writes — for three of these fields it is the
|
||||||
@@ -158,6 +158,23 @@ const sweptValues = (row) => [...row.hostile, ...(row.falsy || [])];
|
|||||||
// falsy value stored under that field comes back TRUTHY from the floor, so no
|
// falsy value stored under that field comes back TRUTHY from the floor, so no
|
||||||
// `!state.x` branch is reachable from a stored record at all.
|
// `!state.x` branch is reachable from a stored record at all.
|
||||||
|
|
||||||
|
// The `hostileRestore` entries for a value driven onto every restorable view:
|
||||||
|
// it falls back to Home on the views listed in `fallsBackOn` and lands on every
|
||||||
|
// other one, so a view added to RESTORABLE_VIEWS is driven, and expected to
|
||||||
|
// land, without editing the row.
|
||||||
|
function everyRestorableView(value, fallsBackOn) {
|
||||||
|
return [
|
||||||
|
{ value, views: fallsBackOn, restored: false },
|
||||||
|
{
|
||||||
|
value,
|
||||||
|
views: [...RESTORABLE_VIEWS].filter(
|
||||||
|
(view) => !fallsBackOn.includes(view),
|
||||||
|
),
|
||||||
|
restored: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
const CONTRACT = [
|
const CONTRACT = [
|
||||||
{
|
{
|
||||||
field: "wallets",
|
field: "wallets",
|
||||||
@@ -312,32 +329,14 @@ const CONTRACT = [
|
|||||||
routes: true,
|
routes: true,
|
||||||
// Comes back from the floor as null, which hasValidAddress() reads as
|
// Comes back from the floor as null, which hasValidAddress() reads as
|
||||||
// nothing selected: the popup falls back to Home on the five views
|
// nothing selected: the popup falls back to Home on the five views
|
||||||
// that need an address, and lands on the other six.
|
// that need an address, and lands on every other one.
|
||||||
hostileRestore: [
|
hostileRestore: everyRestorableView("length", [
|
||||||
{
|
"address",
|
||||||
value: "length",
|
"address-token",
|
||||||
views: [
|
"receive",
|
||||||
"address",
|
"transaction",
|
||||||
"address-token",
|
"confirm-tx",
|
||||||
"receive",
|
]),
|
||||||
"transaction",
|
|
||||||
"confirm-tx",
|
|
||||||
],
|
|
||||||
restored: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: "length",
|
|
||||||
views: [
|
|
||||||
"main",
|
|
||||||
"settings",
|
|
||||||
"settings-addtoken",
|
|
||||||
"wait-tx",
|
|
||||||
"success-tx",
|
|
||||||
"error-tx",
|
|
||||||
],
|
|
||||||
restored: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: "selectedAddress",
|
field: "selectedAddress",
|
||||||
@@ -469,44 +468,25 @@ const CONTRACT = [
|
|||||||
},
|
},
|
||||||
// A record that passes EVERY branch's gate at once, driven onto
|
// A record that passes EVERY branch's gate at once, driven onto
|
||||||
// every restorable view: a branch a view does not read must stay
|
// every restorable view: a branch a view does not read must stay
|
||||||
// one it does not read. The six views with no viewData branch
|
// one it does not read. The five views with a viewData branch
|
||||||
// render it, and must survive the fields every branch left behind;
|
// refuse it; every other one renders it, and must survive the
|
||||||
// on the five that have one, the guard refuses it.
|
// fields every branch left behind.
|
||||||
{
|
...everyRestorableView(
|
||||||
value: {
|
{
|
||||||
hash: "0x1",
|
hash: "0x1",
|
||||||
message: "boom",
|
message: "boom",
|
||||||
tx: { hash: "0x1" },
|
tx: { hash: "0x1" },
|
||||||
pendingTx: { amount: "1" },
|
pendingTx: { amount: "1" },
|
||||||
pendingWait: { hash: "0x1" },
|
pendingWait: { hash: "0x1" },
|
||||||
},
|
},
|
||||||
views: [
|
[
|
||||||
"main",
|
|
||||||
"address",
|
|
||||||
"address-token",
|
|
||||||
"receive",
|
|
||||||
"settings",
|
|
||||||
"settings-addtoken",
|
|
||||||
],
|
|
||||||
restored: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: {
|
|
||||||
hash: "0x1",
|
|
||||||
message: "boom",
|
|
||||||
tx: { hash: "0x1" },
|
|
||||||
pendingTx: { amount: "1" },
|
|
||||||
pendingWait: { hash: "0x1" },
|
|
||||||
},
|
|
||||||
views: [
|
|
||||||
"confirm-tx",
|
"confirm-tx",
|
||||||
"transaction",
|
"transaction",
|
||||||
"wait-tx",
|
"wait-tx",
|
||||||
"success-tx",
|
"success-tx",
|
||||||
"error-tx",
|
"error-tx",
|
||||||
],
|
],
|
||||||
restored: false,
|
),
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -810,19 +790,16 @@ function restoringOnto(view, extra) {
|
|||||||
|
|
||||||
// A boot that RESTORED is healthy and landed on the view it stored, rather
|
// A boot that RESTORED is healthy and landed on the view it stored, rather
|
||||||
// than falling back to Home — which a healthy boot also does, and which would
|
// than falling back to Home — which a healthy boot also does, and which would
|
||||||
// let a sweep pass by never running the renderer it is aimed at. `blank` is
|
// let a sweep pass by never running the renderer it is aimed at.
|
||||||
// reported as bootHealth() reports it, so a boot expected to fall back is still
|
|
||||||
// held to putting something on screen.
|
|
||||||
async function restoredHealth(profile, view) {
|
async function restoredHealth(profile, view) {
|
||||||
const env = await bootPopup(profile);
|
const env = await bootPopup(profile);
|
||||||
return {
|
return {
|
||||||
errors: env.pageErrors,
|
errors: env.pageErrors,
|
||||||
blank: env.visibleViews().length === 0,
|
|
||||||
restored: env.visibleViews().includes(view),
|
restored: env.visibleViews().includes(view),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const RESTORED = { ...HEALTHY, restored: true };
|
const RESTORED = { errors: [], restored: true };
|
||||||
|
|
||||||
describe("the base profile the sweep corrupts", () => {
|
describe("the base profile the sweep corrupts", () => {
|
||||||
for (const view of RESTORABLE_VIEWS) {
|
for (const view of RESTORABLE_VIEWS) {
|
||||||
@@ -977,9 +954,10 @@ describe("every field the router does not read, corrupted at once, onto", () =>
|
|||||||
|
|
||||||
// The values that only mean something on the restore path: a viewData that
|
// The values that only mean something on the restore path: a viewData that
|
||||||
// PASSES a branch's gate and then hands its renderer something dereferenced,
|
// PASSES a branch's gate and then hands its renderer something dereferenced,
|
||||||
// and a selectedWallet the floor turns into nothing selected. Each boot is held
|
// and a selectedWallet the floor turns into nothing selected. Each boot must
|
||||||
// to health and to where its entry says it lands, on its view or back on Home,
|
// throw nothing and show exactly the view its entry says it lands on: its own,
|
||||||
// so a value written for one renderer cannot stop reaching it and still pass.
|
// or Home, so a value written for one renderer cannot stop reaching it and
|
||||||
|
// still pass.
|
||||||
describe("a restore-only hostile value onto", () => {
|
describe("a restore-only hostile value onto", () => {
|
||||||
for (const row of CONTRACT) {
|
for (const row of CONTRACT) {
|
||||||
for (const entry of row.hostileRestore || []) {
|
for (const entry of row.hostileRestore || []) {
|
||||||
@@ -987,14 +965,15 @@ describe("a restore-only hostile value onto", () => {
|
|||||||
test(`${view}: ${row.field} = ${JSON.stringify(
|
test(`${view}: ${row.field} = ${JSON.stringify(
|
||||||
entry.value,
|
entry.value,
|
||||||
)}`, async () => {
|
)}`, async () => {
|
||||||
await expect(
|
const env = await bootPopup(
|
||||||
restoredHealth(
|
restoringOnto(view, { [row.field]: entry.value }),
|
||||||
restoringOnto(view, { [row.field]: entry.value }),
|
);
|
||||||
view,
|
expect({
|
||||||
),
|
errors: env.pageErrors,
|
||||||
).resolves.toEqual({
|
visible: env.visibleViews(),
|
||||||
...HEALTHY,
|
}).toEqual({
|
||||||
restored: entry.restored,
|
errors: [],
|
||||||
|
visible: [entry.restored ? view : "main"],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user