mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Make starting of application modular and unit testable (#5324)
* Introduce injection token as competition for injectable setup to have better control of timing of different setups Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Switch to using competition to setup app paths Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Switch to using competition for setupping IPC channel listeners Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Stop running setups in unit tests without need Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Switch to running injection token based setups over legacy DI setups in unit tests Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Consolidate naming for running setups Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Switch to running injection token based setups over legacy DI setups in application roots Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Adapt to typing changes in injectable Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Update injectable Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce concept of runnable as a way to delegate runs to Open Closed Principle compliant runnables Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Deprecate vars in favor of injectables Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Consolidate loading of extensions to injectable instead of setup-code Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Flag injectable causing side effects Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Adapt injectable to auto register using a plugin instead of internal feature that no longer exists Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Simplify late registrations Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce tokens for runnables of specific application events for Open Closed Principle Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Consolidate setup events to more granular timeslots Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Reimplement setup for catalog syncing using runnables instead of non-OCP in index.ts Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Reimplement setup for application menu using runnables instead of non-OCP in index.ts Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Reimplement setup for electron application name using runnables instead of non-OCP in index.ts Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Reimplement setup for immer using runnables instead of non-OCP in index.ts Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Reimplement setup for MobX strictness using runnables instead of non-OCP in index.ts Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Reimplement setup for application proxy using runnables instead of non-OCP in index.ts Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Reimplement setup for system certifications using runnables instead of non-OCP in index.ts Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Reimplement setup for system shutdown using runnables instead of non-OCP in index.ts Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Reimplement setup for main window visibility using runnables instead of non-OCP in index.ts Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Reimplement setup for application quit using runnables instead of non-OCP in index.ts Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Reimplement setup for after application is ready using runnables instead of non-OCP in index.ts Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Reimplement setup for application tray using runnables instead of non-OCP in index.ts Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Reimplement setup for deep linking using runnables instead of non-OCP in index.ts Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Reimplement setup for root frame using runnables instead of non-OCP in index.ts Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Remove multiple usages of shared global state Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Remove recently reimplemented stuff from index.ts Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Extract implementation for intent over technical phenomena (here electron events) Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Consolidate naming of event timing window Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Move directories for timing windows among peers Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Consolidate event naming Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Introduce function to remove duplication from things that are startable and stoppable Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Consolidate implementation of something startable and stoppable Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Consolidate naming Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Consolidate more startables and stoppables Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Introduce abstractions for electron application events Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce more abstractions for electron Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Abstract even more Electron specifics to make them overridable in unit tests Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Override dependency for causing side effects Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Make running of many delegatees able to be hierarchical Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Bump async-fn Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Make startable-stoppable also restartable Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Extract "isIntegrationTesting" as dependency for having a side-effect Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Make temporal dependency apparent Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Consolidate all setupping related to single feature to same runnable Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Abstract command line arguments to make them overridable in tests Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Deprecate some globals Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce injectable for __static directory to eliminate side effect on import Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Extract responsibilities from electron Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Extract async initialization from sync-injectable Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Accumulate more global overrides Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Make lifecycle of injectable store work as expected Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Extract responsibilities to delegatees Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Rename delegate for accuracy Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Rename another delegate for accuracy Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Rename yet another delegate for accuracy Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Add new global overrides Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Consolidate variable naming Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Rename injectable for accuracy Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Make difference between soft and hard quit of application apparent Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Make quit triggered by auto update manifest as hard quit instead of just soft quit Soft quit is the stand-by quit where only the renderer quits. Hard quit is the full quit of also main. Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Introduce abstraction for publishing and subscribing between processes Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Revert "Introduce abstraction for publishing and subscribing between processes" This reverts commit 46f2d5a5f28bddcf5ffe124b1c590b19e7b9a15f. Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Adapt code and unit tests to recent changes in application setup and event handling Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Group overrides by category Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Abstract event of application activation from electron Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Abstract event of device shutdown from electron Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Consolidate runnables related to Electron Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Make startableStoppables have ID for better error logging Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Make navigating to Helm Charts not blow up Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Add general override for behavioural tests Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Update snapshot Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Adapt vars after merge Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Fix code style Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Fix error about multiple states for React Router being present at once Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Kludge around test setup which is difficult because of circular dependencies Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Fix setupping of sentry after rebase Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Ensure that LensProxy is setupped before starting the main window Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Remove redundant import Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Consolidate to use injectable instead of var for static file directory Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Deprecate another var with injectable Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Tweak timing of runnables Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Extract tray icon path as injectable Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Make splash screen not blow up by providing compile-time environment variables Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce a way to run many synchronous runnables Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Make runnables for before application is ready synchronous as this is technical limitation of Electron See: https://github.com/electron/electron/issues/21370 Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Kill dead code Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Fix application quit by calling Electron's event.preventDefault in a very specific way and preventing async Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Fix missing injectable postfix in file name Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Tweak timeslot of a runnable Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Make it possible to not stop something that was never started Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Make quit of hidden Lens not blow up Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Extract responsibilities of WindowManager as injectables Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Consolidate code for application window Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Simplify directory structures for runnables Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Flag injectable causing side-effect Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Extract helpers for testing promises to test-utils Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Make script for running unit tests support targeting Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Make startable stoppable support async starting Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce reactive way to get theme from operating system Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Update yarn.lock after rebase Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Fix code style Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Remove code-style changes that are not welcome Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Switch to using dependency over using explicit side-effect Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Simplify naming Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Kill dead code Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Add empty mocks comply to lint Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Remove global state Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Extract responsibility of setting dependencies to own injectable Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Flag injectable causing side effects Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Extract responsibility to injectable Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Tweak typing Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Tweak naming of runnables Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Revert code-style changes Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Tweak types Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Extract injectable with side-effect for exact overriding Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Tweak name of timeslot to make it more apparent that new content for application load can be added Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Tweak name of the splash window for loading to avoid confusion with similarly named phenomenon Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Tweak comment Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Rename injectable for brevity Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Consolidate LensProxy related stuff to directory Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Rename injectables for accuracy Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Remove usage of extension for injectable for being YAGNI Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Prevent restarting a startableStoppable when already being started Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Rename callback in ApplicationBuilder for accuracy Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Fix conflicts after rebase Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Fix merge conflicts Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Revert switch to react-router-dom by installing history as dependency Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Make test more strict Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Make runnable give friendly error about incorrect hierarchy for easier debugging Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Fix code-style Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Fix code style Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Switch to using dependency instead of legacy-di Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Fix timing of injects Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> Co-authored-by: Iku-turso <mikko.aspiala@gmail.com>
This commit is contained in:
1 parent
b57d48e39e
commit
54b92aa9b6
302 files changed
+6388
-2025
No files matched your search
@@ -0,0 +1,267 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import { createContainer, getInjectable, getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { Runnable } from "./run-many-for";
|
||||
import { runManyFor } from "./run-many-for";
|
||||
import { getPromiseStatus } from "../test-utils/get-promise-status";
|
||||
|
||||
describe("runManyFor", () => {
|
||||
describe("given no hierarchy, when running many", () => {
|
||||
let runMock: AsyncFnMock<(...args: unknown[]) => Promise<void>>;
|
||||
let actualPromise: Promise<void>;
|
||||
|
||||
beforeEach(() => {
|
||||
const rootDi = createContainer();
|
||||
|
||||
runMock = asyncFn();
|
||||
|
||||
const someInjectionTokenForRunnables = getInjectionToken<Runnable>({
|
||||
id: "some-injection-token",
|
||||
});
|
||||
|
||||
const someInjectable = getInjectable({
|
||||
id: "some-injectable",
|
||||
instantiate: () => ({ run: () => runMock("some-call") }),
|
||||
injectionToken: someInjectionTokenForRunnables,
|
||||
});
|
||||
|
||||
const someOtherInjectable = getInjectable({
|
||||
id: "some-other-injectable",
|
||||
instantiate: () => ({ run: () => runMock("some-other-call") }),
|
||||
injectionToken: someInjectionTokenForRunnables,
|
||||
});
|
||||
|
||||
rootDi.register(someInjectable, someOtherInjectable);
|
||||
|
||||
const runMany = runManyFor(rootDi)(someInjectionTokenForRunnables);
|
||||
|
||||
actualPromise = runMany() as Promise<void>;
|
||||
});
|
||||
|
||||
it("runs all runnables at the same time", () => {
|
||||
expect(runMock.mock.calls).toEqual([
|
||||
["some-call"],
|
||||
["some-other-call"],
|
||||
]);
|
||||
});
|
||||
|
||||
it("does not resolve yet", async () => {
|
||||
const promiseStatus = await getPromiseStatus(actualPromise);
|
||||
|
||||
expect(promiseStatus.fulfilled).toBe(false);
|
||||
});
|
||||
|
||||
it("when all runnables resolve, resolves", async () => {
|
||||
await Promise.all([runMock.resolve(), runMock.resolve()]);
|
||||
|
||||
expect(await actualPromise).toBe(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe("given hierarchy that is three levels deep, when running many", () => {
|
||||
let runMock: AsyncFnMock<(...args: unknown[]) => Promise<void>>;
|
||||
let actualPromise: Promise<void>;
|
||||
|
||||
beforeEach(() => {
|
||||
const di = createContainer();
|
||||
|
||||
runMock = asyncFn();
|
||||
|
||||
const someInjectionTokenForRunnables = getInjectionToken<Runnable>({
|
||||
id: "some-injection-token",
|
||||
});
|
||||
|
||||
const someInjectable1 = getInjectable({
|
||||
id: "some-injectable-1",
|
||||
|
||||
instantiate: (di) => ({
|
||||
run: () => runMock("third-level-run"),
|
||||
runAfter: di.inject(someInjectable2),
|
||||
}),
|
||||
|
||||
injectionToken: someInjectionTokenForRunnables,
|
||||
});
|
||||
|
||||
const someInjectable2 = getInjectable({
|
||||
id: "some-injectable-2",
|
||||
|
||||
instantiate: (di) => ({
|
||||
run: () => runMock("second-level-run"),
|
||||
runAfter: di.inject(someInjectable3),
|
||||
}),
|
||||
|
||||
injectionToken: someInjectionTokenForRunnables,
|
||||
});
|
||||
|
||||
const someInjectable3 = getInjectable({
|
||||
id: "some-injectable-3",
|
||||
instantiate: () => ({ run: () => runMock("first-level-run") }),
|
||||
injectionToken: someInjectionTokenForRunnables,
|
||||
});
|
||||
|
||||
di.register(someInjectable1, someInjectable2, someInjectable3);
|
||||
|
||||
const runMany = runManyFor(di)(someInjectionTokenForRunnables);
|
||||
|
||||
actualPromise = runMany() as Promise<void>;
|
||||
});
|
||||
|
||||
it("runs first level runnables", () => {
|
||||
expect(runMock.mock.calls).toEqual([["first-level-run"]]);
|
||||
});
|
||||
|
||||
it("does not resolve yet", async () => {
|
||||
const promiseStatus = await getPromiseStatus(actualPromise);
|
||||
|
||||
expect(promiseStatus.fulfilled).toBe(false);
|
||||
});
|
||||
|
||||
describe("when first level runnables resolve", () => {
|
||||
beforeEach(async () => {
|
||||
runMock.mockClear();
|
||||
|
||||
await runMock.resolveSpecific(["first-level-run"]);
|
||||
});
|
||||
|
||||
it("runs second level runnables", async () => {
|
||||
expect(runMock.mock.calls).toEqual([["second-level-run"]]);
|
||||
});
|
||||
|
||||
it("does not resolve yet", async () => {
|
||||
const promiseStatus = await getPromiseStatus(actualPromise);
|
||||
|
||||
expect(promiseStatus.fulfilled).toBe(false);
|
||||
});
|
||||
|
||||
describe("when second level runnables resolve", () => {
|
||||
beforeEach(async () => {
|
||||
runMock.mockClear();
|
||||
|
||||
await runMock.resolveSpecific(["second-level-run"]);
|
||||
});
|
||||
|
||||
it("runs final third level runnables", async () => {
|
||||
expect(runMock.mock.calls).toEqual([["third-level-run"]]);
|
||||
});
|
||||
|
||||
it("does not resolve yet", async () => {
|
||||
const promiseStatus = await getPromiseStatus(actualPromise);
|
||||
|
||||
expect(promiseStatus.fulfilled).toBe(false);
|
||||
});
|
||||
|
||||
describe("when final third level runnables resolve", () => {
|
||||
beforeEach(async () => {
|
||||
await runMock.resolveSpecific(["third-level-run"]);
|
||||
});
|
||||
|
||||
it("resolves", async () => {
|
||||
const promiseStatus = await getPromiseStatus(actualPromise);
|
||||
|
||||
expect(promiseStatus.fulfilled).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("given invalid hierarchy, when running runnables, throws", () => {
|
||||
const rootDi = createContainer();
|
||||
|
||||
const runMock = asyncFn<(...args: unknown[]) => void>();
|
||||
|
||||
const someInjectionToken = getInjectionToken<Runnable>({
|
||||
id: "some-injection-token",
|
||||
});
|
||||
|
||||
const someOtherInjectionToken = getInjectionToken<Runnable>({
|
||||
id: "some-other-injection-token",
|
||||
});
|
||||
|
||||
const someInjectable = getInjectable({
|
||||
id: "some-runnable-1",
|
||||
|
||||
instantiate: (di) => ({
|
||||
run: () => runMock("some-runnable-1"),
|
||||
runAfter: di.inject(someOtherInjectable),
|
||||
}),
|
||||
|
||||
injectionToken: someInjectionToken,
|
||||
});
|
||||
|
||||
const someOtherInjectable = getInjectable({
|
||||
id: "some-runnable-2",
|
||||
|
||||
instantiate: () => ({
|
||||
run: () => runMock("some-runnable-2"),
|
||||
}),
|
||||
|
||||
injectionToken: someOtherInjectionToken,
|
||||
});
|
||||
|
||||
rootDi.register(someInjectable, someOtherInjectable);
|
||||
|
||||
const runMany = runManyFor(rootDi)(
|
||||
someInjectionToken,
|
||||
);
|
||||
|
||||
return expect(() => runMany()).rejects.toThrow(
|
||||
"Tried to run runnable after other runnable which does not same injection token.",
|
||||
);
|
||||
});
|
||||
|
||||
describe("when running many with parameter", () => {
|
||||
let runMock: AsyncFnMock<(...args: unknown[]) => Promise<void>>;
|
||||
|
||||
beforeEach(() => {
|
||||
const rootDi = createContainer();
|
||||
|
||||
runMock = asyncFn();
|
||||
|
||||
const someInjectionTokenForRunnablesWithParameter = getInjectionToken<
|
||||
Runnable<string>
|
||||
>({
|
||||
id: "some-injection-token",
|
||||
});
|
||||
|
||||
const someInjectable = getInjectable({
|
||||
id: "some-runnable-1",
|
||||
|
||||
instantiate: () => ({
|
||||
run: (parameter) => runMock("run-of-some-runnable-1", parameter),
|
||||
}),
|
||||
|
||||
injectionToken: someInjectionTokenForRunnablesWithParameter,
|
||||
});
|
||||
|
||||
const someOtherInjectable = getInjectable({
|
||||
id: "some-runnable-2",
|
||||
|
||||
instantiate: () => ({
|
||||
run: (parameter) => runMock("run-of-some-runnable-2", parameter),
|
||||
}),
|
||||
|
||||
injectionToken: someInjectionTokenForRunnablesWithParameter,
|
||||
});
|
||||
|
||||
rootDi.register(someInjectable, someOtherInjectable);
|
||||
|
||||
const runMany = runManyFor(rootDi)(
|
||||
someInjectionTokenForRunnablesWithParameter,
|
||||
);
|
||||
|
||||
runMany("some-parameter");
|
||||
});
|
||||
|
||||
it("runs all runnables using the parameter", () => {
|
||||
expect(runMock.mock.calls).toEqual([
|
||||
["run-of-some-runnable-1", "some-parameter"],
|
||||
["run-of-some-runnable-2", "some-parameter"],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { pipeline } from "@ogre-tools/fp";
|
||||
import type {
|
||||
DiContainerForInjection,
|
||||
InjectionToken,
|
||||
} from "@ogre-tools/injectable";
|
||||
import { filter, forEach, map, tap } from "lodash/fp";
|
||||
import { throwWithIncorrectHierarchyFor } from "./throw-with-incorrect-hierarchy-for";
|
||||
|
||||
export interface Runnable<TParameter = void> {
|
||||
run: Run<TParameter>;
|
||||
runAfter?: this;
|
||||
}
|
||||
|
||||
type Run<Param> = (parameter: Param) => Promise<void> | void;
|
||||
|
||||
export type RunMany = <Param>(
|
||||
injectionToken: InjectionToken<Runnable<Param>, void>
|
||||
) => Run<Param>;
|
||||
|
||||
export function runManyFor(di: DiContainerForInjection): RunMany {
|
||||
return (injectionToken) => async (parameter) => {
|
||||
const allRunnables = di.injectMany(injectionToken);
|
||||
|
||||
const throwWithIncorrectHierarchy = throwWithIncorrectHierarchyFor(allRunnables);
|
||||
|
||||
const recursedRun = async (
|
||||
runAfterRunnable: Runnable<any> | undefined = undefined,
|
||||
) =>
|
||||
await pipeline(
|
||||
allRunnables,
|
||||
|
||||
tap(runnables => forEach(throwWithIncorrectHierarchy, runnables)),
|
||||
|
||||
filter((runnable) => runnable.runAfter === runAfterRunnable),
|
||||
|
||||
map(async (runnable) => {
|
||||
await runnable.run(parameter);
|
||||
|
||||
await recursedRun(runnable);
|
||||
}),
|
||||
|
||||
(promises) => Promise.all(promises),
|
||||
);
|
||||
|
||||
await recursedRun();
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { createContainer, getInjectable, getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { RunnableSync } from "./run-many-sync-for";
|
||||
import { runManySyncFor } from "./run-many-sync-for";
|
||||
|
||||
describe("runManySyncFor", () => {
|
||||
describe("given hierarchy, when running many", () => {
|
||||
let runMock: jest.Mock;
|
||||
|
||||
beforeEach(() => {
|
||||
const rootDi = createContainer();
|
||||
|
||||
runMock = jest.fn();
|
||||
|
||||
const someInjectionTokenForRunnables = getInjectionToken<RunnableSync>({
|
||||
id: "some-injection-token",
|
||||
});
|
||||
|
||||
const someInjectable = getInjectable({
|
||||
id: "some-injectable",
|
||||
instantiate: () => ({ run: () => runMock("some-call") }),
|
||||
injectionToken: someInjectionTokenForRunnables,
|
||||
});
|
||||
|
||||
const someOtherInjectable = getInjectable({
|
||||
id: "some-other-injectable",
|
||||
instantiate: () => ({ run: () => runMock("some-other-call") }),
|
||||
injectionToken: someInjectionTokenForRunnables,
|
||||
});
|
||||
|
||||
rootDi.register(someInjectable, someOtherInjectable);
|
||||
|
||||
const runMany = runManySyncFor(rootDi)(someInjectionTokenForRunnables);
|
||||
|
||||
runMany();
|
||||
});
|
||||
|
||||
it("runs all runnables at the same time", () => {
|
||||
expect(runMock.mock.calls).toEqual([
|
||||
["some-call"],
|
||||
["some-other-call"],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("given hierarchy that is three levels deep, when running many", () => {
|
||||
let runMock: jest.Mock<(arg: string) => void>;
|
||||
|
||||
beforeEach(() => {
|
||||
const di = createContainer();
|
||||
|
||||
runMock = jest.fn();
|
||||
|
||||
const someInjectionTokenForRunnables = getInjectionToken<RunnableSync>({
|
||||
id: "some-injection-token",
|
||||
});
|
||||
|
||||
const someInjectable1 = getInjectable({
|
||||
id: "some-injectable-1",
|
||||
|
||||
instantiate: (di) => ({
|
||||
run: () => runMock("third-level-run"),
|
||||
runAfter: di.inject(someInjectable2),
|
||||
}),
|
||||
|
||||
injectionToken: someInjectionTokenForRunnables,
|
||||
});
|
||||
|
||||
const someInjectable2 = getInjectable({
|
||||
id: "some-injectable-2",
|
||||
|
||||
instantiate: (di) => ({
|
||||
run: () => runMock("second-level-run"),
|
||||
runAfter: di.inject(someInjectable3),
|
||||
}),
|
||||
|
||||
injectionToken: someInjectionTokenForRunnables,
|
||||
});
|
||||
|
||||
const someInjectable3 = getInjectable({
|
||||
id: "some-injectable-3",
|
||||
instantiate: () => ({ run: () => runMock("first-level-run") }),
|
||||
injectionToken: someInjectionTokenForRunnables,
|
||||
});
|
||||
|
||||
di.register(someInjectable1, someInjectable2, someInjectable3);
|
||||
|
||||
const runMany = runManySyncFor(di)(someInjectionTokenForRunnables);
|
||||
|
||||
runMany();
|
||||
});
|
||||
|
||||
it("runs runnables in order", () => {
|
||||
expect(runMock.mock.calls).toEqual([["first-level-run"], ["second-level-run"], ["third-level-run"]]);
|
||||
});
|
||||
});
|
||||
|
||||
it("given invalid hierarchy, when running runnables, throws", () => {
|
||||
const rootDi = createContainer();
|
||||
|
||||
const runMock = jest.fn();
|
||||
|
||||
const someInjectionToken = getInjectionToken<RunnableSync>({
|
||||
id: "some-injection-token",
|
||||
});
|
||||
|
||||
const someOtherInjectionToken = getInjectionToken<RunnableSync>({
|
||||
id: "some-other-injection-token",
|
||||
});
|
||||
|
||||
const someInjectable = getInjectable({
|
||||
id: "some-runnable-1",
|
||||
|
||||
instantiate: (di) => ({
|
||||
run: () => runMock("some-runnable-1"),
|
||||
runAfter: di.inject(someOtherInjectable),
|
||||
}),
|
||||
|
||||
injectionToken: someInjectionToken,
|
||||
});
|
||||
|
||||
const someOtherInjectable = getInjectable({
|
||||
id: "some-runnable-2",
|
||||
|
||||
instantiate: () => ({
|
||||
run: () => runMock("some-runnable-2"),
|
||||
}),
|
||||
|
||||
injectionToken: someOtherInjectionToken,
|
||||
});
|
||||
|
||||
rootDi.register(someInjectable, someOtherInjectable);
|
||||
|
||||
const runMany = runManySyncFor(rootDi)(
|
||||
someInjectionToken,
|
||||
);
|
||||
|
||||
return expect(() => runMany()).rejects.toThrow(
|
||||
"Tried to run runnable after other runnable which does not same injection token.",
|
||||
);
|
||||
});
|
||||
|
||||
describe("when running many with parameter", () => {
|
||||
let runMock: jest.Mock<(arg: string, arg2: string) => void>;
|
||||
|
||||
beforeEach(() => {
|
||||
const rootDi = createContainer();
|
||||
|
||||
runMock = jest.fn();
|
||||
|
||||
const someInjectionTokenForRunnablesWithParameter = getInjectionToken<
|
||||
RunnableSync<string>
|
||||
>({
|
||||
id: "some-injection-token",
|
||||
});
|
||||
|
||||
const someInjectable = getInjectable({
|
||||
id: "some-runnable-1",
|
||||
|
||||
instantiate: () => ({
|
||||
run: (parameter) => runMock("run-of-some-runnable-1", parameter),
|
||||
}),
|
||||
|
||||
injectionToken: someInjectionTokenForRunnablesWithParameter,
|
||||
});
|
||||
|
||||
const someOtherInjectable = getInjectable({
|
||||
id: "some-runnable-2",
|
||||
|
||||
instantiate: () => ({
|
||||
run: (parameter) => runMock("run-of-some-runnable-2", parameter),
|
||||
}),
|
||||
|
||||
injectionToken: someInjectionTokenForRunnablesWithParameter,
|
||||
});
|
||||
|
||||
rootDi.register(someInjectable, someOtherInjectable);
|
||||
|
||||
const runMany = runManySyncFor(rootDi)(
|
||||
someInjectionTokenForRunnablesWithParameter,
|
||||
);
|
||||
|
||||
runMany("some-parameter");
|
||||
});
|
||||
|
||||
it("runs all runnables using the parameter", () => {
|
||||
expect(runMock.mock.calls).toEqual([
|
||||
["run-of-some-runnable-1", "some-parameter"],
|
||||
["run-of-some-runnable-2", "some-parameter"],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { pipeline } from "@ogre-tools/fp";
|
||||
import type {
|
||||
DiContainerForInjection,
|
||||
InjectionToken,
|
||||
} from "@ogre-tools/injectable";
|
||||
import { filter, forEach, map, tap } from "lodash/fp";
|
||||
import type { Runnable } from "./run-many-for";
|
||||
import { throwWithIncorrectHierarchyFor } from "./throw-with-incorrect-hierarchy-for";
|
||||
|
||||
export interface RunnableSync<TParameter = void> {
|
||||
run: RunSync<TParameter>;
|
||||
runAfter?: this;
|
||||
}
|
||||
|
||||
type RunSync<Param> = (parameter: Param) => void;
|
||||
|
||||
export type RunManySync = <Param>(
|
||||
injectionToken: InjectionToken<Runnable<Param>, void>
|
||||
) => RunSync<Param>;
|
||||
|
||||
export function runManySyncFor(di: DiContainerForInjection): RunManySync {
|
||||
return (injectionToken) => async (parameter) => {
|
||||
const allRunnables = di.injectMany(injectionToken);
|
||||
|
||||
const throwWithIncorrectHierarchy = throwWithIncorrectHierarchyFor(allRunnables);
|
||||
|
||||
const recursedRun = (
|
||||
runAfterRunnable: RunnableSync<any> | undefined = undefined,
|
||||
) =>
|
||||
pipeline(
|
||||
allRunnables,
|
||||
|
||||
tap(runnables => forEach(throwWithIncorrectHierarchy, runnables)),
|
||||
|
||||
filter((runnable) => runnable.runAfter === runAfterRunnable),
|
||||
|
||||
map((runnable) => {
|
||||
runnable.run(parameter);
|
||||
|
||||
recursedRun(runnable);
|
||||
}),
|
||||
);
|
||||
|
||||
recursedRun();
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { Runnable } from "./run-many-for";
|
||||
import type { RunnableSync } from "./run-many-sync-for";
|
||||
|
||||
export const throwWithIncorrectHierarchyFor =
|
||||
(allRunnables: Runnable<any>[] | RunnableSync<any>[]) =>
|
||||
(runnable: Runnable<any> | RunnableSync<any>) => {
|
||||
if (runnable.runAfter && !allRunnables.includes(runnable.runAfter)) {
|
||||
throw new Error(
|
||||
"Tried to run runnable after other runnable which does not same injection token.",
|
||||
);
|
||||
}
|
||||
};
|
||||
Reference in new issue
Block a user