1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-22 17:33:23 +01:00

Initialize composable observable store after update (#20468)

* Initialize composable observable store after update

The composable observable store now updates state immediately when the
structure is updated. Previously each store would only be updated after
the first state change. This ensures that the composable observable
store state is always complete.

* SUpport falsy controller state

We now use the nullish coalescing operator when checkint store.state, so that we don't accidentally ignore falsy state.

Co-authored-by: Frederik Bolding <frederik.bolding@gmail.com>

* Add test for falsy controller state

* Update state snapshots

A change on `develop` required another state update.

---------

Co-authored-by: Frederik Bolding <frederik.bolding@gmail.com>
This commit is contained in:
Mark Stacey 2023-08-17 12:22:37 -02:30 committed by Dan J Miller
parent 1d13008121
commit 3e26da493f
3 changed files with 124 additions and 0 deletions

View File

@ -51,6 +51,7 @@ export default class ComposableObservableStore extends ObservableStore {
updateStructure(config) {
this.config = config;
this.removeAllListeners();
const initialState = {};
for (const key of Object.keys(config)) {
if (!config[key]) {
throw new Error(`Undefined '${key}'`);
@ -72,7 +73,10 @@ export default class ComposableObservableStore extends ObservableStore {
},
);
}
initialState[key] = store.state ?? store.getState?.();
}
this.updateState(initialState);
}
/**

View File

@ -120,6 +120,46 @@ describe('ComposableObservableStore', () => {
});
});
it('should initialize state with all three types of stores', () => {
const controllerMessenger = new ControllerMessenger();
const exampleStore = new ObservableStore();
const exampleController = new ExampleController({
messenger: controllerMessenger,
});
const oldExampleController = new OldExampleController();
exampleStore.putState('state');
exampleController.updateBar('state');
oldExampleController.updateBaz('state');
const store = new ComposableObservableStore({ controllerMessenger });
store.updateStructure({
Example: exampleController,
OldExample: oldExampleController,
Store: exampleStore,
});
expect(store.getState()).toStrictEqual({
Example: { bar: 'state' },
OldExample: { baz: 'state' },
Store: 'state',
});
});
it('should initialize falsy state', () => {
const controllerMessenger = new ControllerMessenger();
const exampleStore = new ObservableStore();
exampleStore.putState(false);
const store = new ComposableObservableStore({ controllerMessenger });
store.updateStructure({
Example: exampleStore,
});
expect(store.getState()).toStrictEqual({
Example: false,
});
});
it('should return flattened state', () => {
const controllerMessenger = new ControllerMessenger();
const fooStore = new ObservableStore({ foo: 'foo' });

View File

@ -1,5 +1,18 @@
{
"AccountTracker": { "accounts": "object" },
"AddressBookController": "object",
"AlertController": {
"alertEnabledness": { "unconnectedAccount": true, "web3ShimUsage": true },
"unconnectedAccountAlertShownOrigins": "object",
"web3ShimUsageOrigins": "object"
},
"AnnouncementController": "object",
"AppMetadataController": {
"currentAppVersion": "10.34.4",
"previousAppVersion": "",
"previousMigrationVersion": 0,
"currentMigrationVersion": 94
},
"AppStateController": {
"connectedStatusPopoverHasBeenShown": true,
"defaultHomeActiveTabName": null,
@ -24,6 +37,7 @@
},
"ApprovalController": "object",
"CachedBalancesController": "object",
"CronjobController": "object",
"CurrencyController": {
"conversionDate": "number",
"conversionRate": 1700,
@ -42,6 +56,22 @@
"unapprovedEncryptionPublicKeyMsgCount": 0
},
"EnsController": "object",
"GasFeeController": "object",
"IncomingTransactionsController": {
"incomingTransactions": "object",
"incomingTxLastFetchedBlockByChainId": {
"0x1": null,
"0xe708": null,
"0x5": null,
"0xaa36a7": null,
"0xe704": null
}
},
"KeyringController": {
"isUnlocked": false,
"keyringTypes": "object",
"keyrings": "object"
},
"MetaMetricsController": {
"participateInMetaMetrics": true,
"metaMetricsId": "fake-metrics-id",
@ -66,6 +96,51 @@
"networksMetadata": "object",
"networkConfigurations": "object"
},
"NftController": "object",
"NotificationController": "object",
"OnboardingController": {
"seedPhraseBackedUp": true,
"firstTimeFlowType": "import",
"completedOnboarding": true,
"onboardingTabs": "object"
},
"PermissionController": "object",
"PermissionLogController": "object",
"PreferencesController": {
"useBlockie": false,
"useNonceField": false,
"usePhishDetect": true,
"dismissSeedBackUpReminder": "boolean",
"disabledRpcMethodPreferences": "object",
"useMultiAccountBalanceChecker": "boolean",
"useTokenDetection": "boolean",
"useNftDetection": "boolean",
"use4ByteResolution": "boolean",
"useCurrencyRateCheck": "boolean",
"openSeaEnabled": "boolean",
"advancedGasFee": "object",
"featureFlags": { "showIncomingTransactions": true },
"knownMethodData": "object",
"currentLocale": "en",
"identities": "object",
"lostIdentities": "object",
"forgottenPassword": false,
"preferences": {
"hideZeroBalanceTokens": false,
"showFiatInTestnets": false,
"showTestNetworks": false,
"useNativeCurrencyAsPrimaryCurrency": true
},
"ipfsGateway": "dweb.link",
"useAddressBarEnsResolution": "boolean",
"infuraBlocked": "boolean",
"ledgerTransportType": "string",
"snapRegistryList": "object",
"transactionSecurityCheckEnabled": "boolean",
"theme": "string",
"isLineaMainnetReleased": "boolean",
"selectedAddress": "string"
},
"SignatureController": {
"unapprovedMsgs": "object",
"unapprovedPersonalMsgs": "object",
@ -74,7 +149,12 @@
"unapprovedPersonalMsgCount": 0,
"unapprovedTypedMessagesCount": 0
},
"SmartTransactionsController": "object",
"SnapController": "object",
"SnapsRegistry": "object",
"SubjectMetadataController": "object",
"SwapsController": "object",
"TokenListController": "object",
"TokenRatesController": "object",
"TokensController": "object",
"TxController": "object"