Skip to content

refactor(suite): separate app composition from initialization - #32195

Merged
peter-sanderson merged 5 commits into
developfrom
refactor-suite-app-initialization
Sep 8, 2026
Merged

refactor(suite): separate app composition from initialization#32195
peter-sanderson merged 5 commits into
developfrom
refactor-suite-app-initialization

Conversation

@peter-sanderson

@peter-sanderson peter-sanderson commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Description

Make the web and desktop composition roots synchronous and return an async init service, so service wiring is independent of application startup. Create the Redux store during composition and hydrate that same store after storage preloading and the desktop handshake, preserving preload behavior without running application middleware during hydration.

🤖 LLM Test Recommendations

Summary: The changed files are concentrated in app initialization, web/desktop composition roots, and Redux store creation/hydration. The biggest risks are app startup failures, broken persisted-state/migration behavior, and regressions in TrezorConnect or bridge initialization. A small, targeted smoke suite covering initial run, database migrations, browser entry gates, desktop bridge lifecycle, and representative TrezorConnect flows provides high confidence without running the full catalog.

Changed files (22)
  • packages/suite-desktop-ui/src/MainDesktop.tsx
  • packages/suite-desktop-ui/src/createDesktopInit.tsx
  • packages/suite-desktop-ui/src/createSuiteDesktopCompositionRoot.ts
  • packages/suite-desktop-ui/src/index.tsx
  • packages/suite-web/src/MainWeb.tsx
  • packages/suite-web/src/createSuiteWebCompositionRoot.ts
  • packages/suite-web/src/createWebInit.tsx
  • packages/suite-web/src/index.ts
  • packages/suite-web/src/static/vite-index.ts
  • packages/suite/index.ts
  • packages/suite/src/reducers/createHydrateReduxStore.ts
  • packages/suite/src/reducers/createReduxStore.ts
  • packages/suite/src/reducers/store.ts
  • packages/suite/src/support/createConnectLoggerFactory.ts
  • packages/suite/src/support/createGetBinFilesBaseUrl.ts
  • packages/suite/src/support/suite/preloadStore.ts
  • suite/test-utils/package.json
  • suite/test-utils/src/StoreProviderForTests.tsx
  • suite/test-utils/src/index.ts
  • suite/test-utils/src/initStoreForTests.ts
  • suite/test-utils/src/renderWithStore.tsx
  • suite/test-utils/tsconfig.json

Recommended tests (10)

🔴 High priority (10)
  • suite/e2e/tests/suite/initial-run.test.ts — Verifies onboarding/analytics consent state persists across reloads and that the app reaches a connected-device state after initial run. This directly exercises the web composition root, init flow, and Redux store hydration/preload logic.
  • suite/e2e/tests/suite/db-migration.test.ts — Tests IndexedDB migration of persisted user settings between Suite versions, which relies on the updated store creation, hydration, and preload-store code paths.
  • suite/e2e/tests/suite/db-locale-migration.test.ts — Validates that language preference survives a cross-version database migration and app reload, directly exercising persisted store hydration and initialization.
  • suite/e2e/tests/browser/firefox.test.ts — Confirms the web app loads and the unsupported-browser gate behaves correctly in Firefox, exercising the web entry point and composition root initialization.
  • suite/e2e/tests/browser/safari.test.ts — Confirms the unsupported-browser gate renders and can be bypassed in Safari, directly testing the web app shell and entry-point initialization.
  • suite/e2e/tests/browser/ios.test.ts — Verifies the iOS unsupported-platform page renders without a bypass option, exercising platform detection and the web composition root entry path.
  • suite/e2e/tests/bridge-tor/spawn-bridge.test.ts — Tests that the desktop app spawns and stops its bundled bridge process correctly across launch, reload, and quit, directly covering the desktop initialization and composition root.
  • suite/e2e/tests/bridge-tor/spawn-bridge-daemon.test.ts — Exercises the desktop daemon-mode startup path where the bridge is spawned separately from the UI, directly testing the desktop init and composition root changes.
  • suite/e2e/tests/trezor-connect/getAddress.test.ts — Validates TrezorConnect address export in suite-desktop core mode after onboarding, covering Connect initialization, permissions modal, and desktop app integration affected by the composition root and Connect logger setup.
  • suite/e2e/tests/trezor-connect/connectPopupWeb.test.ts — Covers the web-based TrezorConnect popup lifecycle and permission/address flows, exercising the web composition root, init, and Connect integration.

⚠️ Changes with no test coverage (7)

  • packages/suite/src/support/createGetBinFilesBaseUrl.ts
  • suite/test-utils/package.json
  • suite/test-utils/src/StoreProviderForTests.tsx
  • suite/test-utils/src/index.ts
  • suite/test-utils/src/initStoreForTests.ts
  • suite/test-utils/src/renderWithStore.tsx
  • suite/test-utils/tsconfig.json

Updated: 2026-09-08T10:56:08.980Z

🌐 Preview deployments

🌐 Suite Web preview: https://dev.suite.sldev.cz/suite-web/refactor-suite-app-initialization/web/

🔍 Currents Test Results

🔍 Suite desktop test results: View in Currents

🔍 Suite web test results: View in Currents

🔒 Quarantined E2E Tests

Trezor Suite (web) — 4 test(s)
Test Type
Staking - Cardano > Stake Cardano 🤖 auto
Suite Sync - Update and Remove Labels > Update and remove labels syncs correctly to relay 🤖 auto
Trading - Swap > Swap SOL USDT token to ETH 🤖 auto
Trading - Swap coin to token > Swap Solana to USDC 🤖 auto

Updated: 2026-09-08T13:19:20.274Z • 4 test(s) total

Trezor Suite (desktop) — 5 test(s)
Test Type
Trading - Sell BTC > Sell Bitcoin for best offer 🤖 auto
Staking - Cardano > Stake Cardano 🤖 auto
Suite Sync - Update and Remove Labels > Update and remove labels syncs correctly to relay 🤖 auto
Quarantine test: "Suite Sync - Quota Manager top-up,Exceeded wallet limit is topped up from the device pool" 🙋 manual
Trading - Swap > Swap SOL USDT token to ETH 🤖 auto

Updated: 2026-09-08T13:18:34.930Z • 5 test(s) total

@peter-sanderson peter-sanderson added the no-project This label is used to specify that PR doesn't need to be added to a project label Sep 7, 2026
Comment thread packages/suite-web/src/createSuiteWebCompositionRoot.ts Outdated
Comment thread packages/suite-desktop-ui/src/createDesktopInit.tsx Outdated
Comment thread packages/suite-desktop-ui/src/createSuiteDesktopCompositionRoot.ts Outdated
Comment thread packages/suite-web/src/createWebInit.tsx Outdated
Comment thread skills/redux/SKILL.md Outdated
Comment thread skills/redux/SKILL.md Outdated
Comment thread packages/suite/src/reducers/createReduxStore.ts
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown

⚡️ Performance report (alpha)

Note

Alpha release: The limits are still being calibrated, and each measurement is
usually a single run on a shared CI runner, so expect noise between runs. Treat a
number as a hint to look closer, not as a verdict.

desktop / group 2

🟢 Within limits.

Each metric reads measured/limit (% of limit).

Scenario TBT Long tasks Longest task React commits Interaction
multi-account-discovery [T3W1] 1298/7000 ms
(19 %)
44/100
(44 %)
295/800 ms
(37 %)
230/400
(57 %)
7265 ms

desktop / group 5

🟢 Within limits.

Each metric reads measured/limit (% of limit).

Scenario TBT Long tasks Longest task React commits Interaction
account-switch [T3W1] 165/700 ms
(24 %)
1/5
(20 %)
215/700 ms
(31 %)
36/80
(45 %)
567 ms
wallet-discovery [T3W1] 390/2000 ms
(20 %)
16/45
(36 %)
230/400 ms
(57 %)
193/410
(47 %)
6071 ms

desktop / group 3

🟢 Within limits.

Each metric reads measured/limit (% of limit).

Scenario TBT Long tasks Longest task React commits Interaction
account-switch [T3W1] 150/700 ms
(21 %)
1/5
(20 %)
200/700 ms
(29 %)
29/80
(36 %)
500 ms
wallet-discovery [T3W1] 182/2000 ms
(9 %)
10/45
(22 %)
130/400 ms
(33 %)
212/410
(52 %)
5327 ms

desktop / group 1

🟢 Within limits.

Each metric reads measured/limit (% of limit).

Scenario TBT Long tasks Longest task React commits Interaction
account-switch [T3T1] 315/700 ms
(45 %)
1/5
(20 %)
365/700 ms
(52 %)
35/80
(44 %)
671 ms
wallet-discovery [T3T1] 818/2000 ms
(41 %)
23/45
(51 %)
227/400 ms
(57 %)
155/410
(38 %)
5329 ms

desktop / group 4

🟢 Within limits.

Each metric reads measured/limit (% of limit).

Scenario TBT Long tasks Longest task React commits Interaction
account-switch [T3W1] 244/700 ms
(35 %)
2/5
(40 %)
290/700 ms
(41 %)
35/80
(44 %)
742 ms
multi-account-discovery [T3W1] 1293/7000 ms
(18 %)
47/100
(47 %)
245/800 ms
(31 %)
227/400
(57 %)
6900 ms
wallet-discovery [T3W1] 608/2000 ms
(30 %)
20/45
(44 %)
188/400 ms
(47 %)
154/410
(38 %)
5231 ms

desktop / group 6

🟢 Within limits.

Each metric reads measured/limit (% of limit).

Scenario TBT Long tasks Longest task React commits Interaction
multi-account-discovery [T3W1] 1154/7000 ms
(16 %)
46/100
(46 %)
252/800 ms
(32 %)
229/400
(57 %)
6168 ms

desktop / group 7

🟢 Within limits.

Each metric reads measured/limit (% of limit).

Scenario TBT Long tasks Longest task React commits Interaction
account-switch [T3W1] 210/700 ms
(30 %)
1/5
(20 %)
260/700 ms
(37 %)
31/80
(39 %)
727 ms
wallet-discovery [T3W1] 691/2000 ms
(35 %)
21/45
(47 %)
164/400 ms
(41 %)
191/410
(47 %)
6482 ms

Comment thread skills/redux/SKILL.md
Comment thread packages/suite-web/src/createSuiteWebCompositionRoot.ts
@peter-sanderson
peter-sanderson force-pushed the refactor-suite-app-initialization branch 2 times, most recently from 8118cd1 to 0d055a5 Compare September 7, 2026 20:22
Comment thread skills/redux/SKILL.md Outdated
@peter-sanderson
peter-sanderson force-pushed the refactor-suite-app-initialization branch from 0d055a5 to 2df9532 Compare September 7, 2026 20:29
@peter-sanderson
peter-sanderson marked this pull request as ready for review September 7, 2026 21:01
export * from '@testing-library/user-event';

// Re-export store types from @trezor/suite
export type { PreloadedState } from '@trezor/suite';

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be completely unused. 😱

// When we run this first time `shouldRunTor` will tell if Tor should run according to previous settings,
// when it runs because of renderer (e.g. Ctrl+R) it will always be false.
if (shouldRunTor) {
await new Promise(resolve => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

like, wat? It runs root.render() twice? Here and line:84?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup, masterpiece :D

@Vere-Grey Vere-Grey left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good from test POV

Comment thread packages/suite/src/components/suite/Preloader/DatabaseCorruptedModal.tsx Outdated
@peter-sanderson
peter-sanderson merged commit 189dbb2 into develop Sep 8, 2026
39 of 40 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no-project This label is used to specify that PR doesn't need to be added to a project

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants