@omega.js/desktop 0.52.0 → 0.53.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -12
- package/dist/assets/css/core/_initialize.scss +1 -1
- package/dist/assets/js/core/app-shell.js +14 -15
- package/dist/assets/themes/_template/_theme.js +6 -6
- package/dist/assets/themes/base/_includes/global/sections/account.html +4 -4
- package/dist/assets/themes/base/_includes/global/sections/app-sidebar.html +5 -5
- package/dist/assets/themes/base/_layouts/frontend/pages/account/index.html +3 -3
- package/dist/assets/themes/base/_layouts/frontend/pages/alternatives/index.html +1 -1
- package/dist/assets/themes/base/_layouts/frontend/pages/blog/tags/tag.html +1 -1
- package/dist/assets/themes/base/_layouts/frontend/pages/payment/confirmation.html +1 -1
- package/dist/assets/themes/base/_sections/marketing/newsletter-cta/section.js +2 -3
- package/dist/assets/themes/base/_sections/verts/unit/section.html +1 -1
- package/dist/assets/themes/base/_sections/verts/unit/section.js +3 -4
- package/dist/assets/themes/base/_theme.js +4 -3
- package/dist/assets/themes/bootstrap/_theme.js +2 -2
- package/dist/assets/themes/bootstrap/overrides/_links.scss +1 -1
- package/dist/assets/themes/classy/_theme.js +8 -6
- package/dist/assets/themes/classy/css/marketing/_sections.scss +1 -2
- package/dist/assets/themes/classy/js/hero-demo-form.js +3 -2
- package/dist/assets/themes/neobrutalism/_theme.js +5 -5
- package/dist/assets/themes/neobrutalism/js/pages/test/libraries/layers/index.js +1 -1
- package/dist/assets/themes/newsflash/_theme.js +6 -6
- package/dist/assets/themes/newsflash/js/pages/test/libraries/layers/index.js +1 -1
- package/dist/build.js +87 -111
- package/dist/cli.js +1 -1
- package/dist/commands/build.js +2 -2
- package/dist/commands/cdp/capture.js +2 -2
- package/dist/commands/cdp/quit.js +2 -2
- package/dist/commands/cdp/relaunch.js +2 -2
- package/dist/commands/cdp/theme.js +1 -1
- package/dist/commands/clean.js +2 -2
- package/dist/commands/deploy.js +4 -4
- package/dist/commands/finalize-release.js +4 -4
- package/dist/commands/install.js +3 -3
- package/dist/commands/launch.js +2 -2
- package/dist/commands/lib/deploy-precheck.js +3 -3
- package/dist/commands/lib/ensure-target.js +6 -6
- package/dist/commands/package.js +2 -2
- package/dist/commands/publish.js +2 -2
- package/dist/commands/release.js +3 -3
- package/dist/commands/runner.js +11 -11
- package/dist/commands/sign-windows.js +5 -5
- package/dist/commands/test.js +4 -4
- package/dist/commands/update.js +2 -2
- package/dist/commands/validate-certs.js +4 -4
- package/dist/commands/version.js +3 -3
- package/dist/defaults/AGENTS.md +17 -8
- package/dist/defaults/config/omega.json5 +7 -7
- package/dist/defaults/hooks/build/post.js +1 -1
- package/dist/defaults/hooks/build/pre.js +1 -1
- package/dist/defaults/hooks/deploy/pre.js +1 -1
- package/dist/defaults/hooks/release/post.js +1 -1
- package/dist/defaults/hooks/release/pre.js +1 -1
- package/dist/defaults/src/assets/js/components/about/index.js +3 -5
- package/dist/defaults/src/assets/js/components/main/index.js +3 -5
- package/dist/defaults/src/assets/js/components/settings/index.js +3 -5
- package/dist/defaults/src/integrations/context-menu/index.js +2 -2
- package/dist/defaults/src/integrations/menu/index.js +3 -3
- package/dist/defaults/src/integrations/tray/index.js +3 -3
- package/dist/defaults/src/main.js +3 -5
- package/dist/defaults/src/preload.js +3 -5
- package/dist/defaults/test/README.md +2 -2
- package/dist/gulp/main.js +9 -10
- package/dist/gulp/tasks/audit.js +7 -7
- package/dist/gulp/tasks/build-config.js +8 -8
- package/dist/gulp/tasks/bundle.js +16 -16
- package/dist/gulp/tasks/defaults.js +3 -3
- package/dist/gulp/tasks/distribute.js +2 -2
- package/dist/gulp/tasks/html.js +9 -9
- package/dist/gulp/tasks/package-quick.js +3 -3
- package/dist/gulp/tasks/package.js +3 -3
- package/dist/gulp/tasks/release.js +3 -3
- package/dist/gulp/tasks/sass.js +6 -6
- package/dist/gulp/tasks/serve.js +4 -4
- package/dist/hooks/notarize-artifacts.js +1 -1
- package/dist/hooks/notarize.js +1 -1
- package/dist/index.js +5 -8
- package/dist/lib/_environment-mixin.js +50 -0
- package/dist/lib/_lifecycle-mixin.js +45 -0
- package/dist/lib/analytics.js +33 -35
- package/dist/lib/app-state.js +14 -14
- package/dist/lib/auth-flow.js +18 -18
- package/dist/lib/auth-persistence.js +12 -12
- package/dist/lib/auth.js +421 -0
- package/dist/lib/auto-updater.js +49 -49
- package/dist/lib/context-menu.js +13 -13
- package/dist/lib/context.js +19 -19
- package/dist/lib/deep-link.js +34 -34
- package/dist/lib/fontawesome.js +5 -5
- package/dist/lib/ipc.js +4 -4
- package/dist/lib/menu.js +25 -25
- package/dist/lib/protocol.js +5 -5
- package/dist/lib/remote-config.js +22 -22
- package/dist/lib/remote-scripts.js +21 -21
- package/dist/lib/restart-manager/index.js +28 -28
- package/dist/lib/sign-helpers/exec-with-limit.js +1 -1
- package/dist/lib/sign-helpers/sign-events.js +1 -1
- package/dist/lib/startup.js +18 -13
- package/dist/lib/storage.js +10 -10
- package/dist/lib/templating.js +16 -16
- package/dist/lib/theme.js +10 -10
- package/dist/lib/tray.js +27 -27
- package/dist/lib/usage.js +11 -11
- package/dist/lib/window-manager.js +26 -26
- package/dist/main.js +398 -483
- package/dist/preload.js +236 -176
- package/dist/renderer.js +417 -391
- package/dist/test/fixtures/consumer-app/config/omega.json5 +1 -1
- package/dist/test/fixtures/consumer-app/src/assets/js/components/main/index.js +8 -11
- package/dist/test/fixtures/consumer-app/src/main.js +5 -7
- package/dist/test/fixtures/consumer-app/src/preload.js +2 -2
- package/dist/test/harness/boot-entry.js +22 -20
- package/dist/test/harness/main-entry.js +31 -30
- package/dist/test/harness/renderer-entry.js +5 -5
- package/dist/test/harness/renderer-preload.js +137 -141
- package/dist/test/index.js +10 -10
- package/dist/test/runner.js +2 -2
- package/dist/test/runners/boot.js +7 -6
- package/dist/test/runners/electron.js +3 -2
- package/dist/test/runners/render-event.js +2 -2
- package/dist/test/suites/boot/consumer-app-boots.test.js +57 -26
- package/dist/test/suites/boot/restart-manager.test.js +2 -2
- package/dist/test/suites/boot/storage-bundled.test.js +5 -5
- package/dist/test/suites/boot/theme.test.js +13 -13
- package/dist/test/suites/build/audit.test.js +1 -1
- package/dist/test/suites/build/auth-persistence-resolve.test.js +6 -6
- package/dist/test/suites/build/boot-fixture.test.js +2 -2
- package/dist/test/suites/build/boot-runner-timeout.test.js +6 -5
- package/dist/test/suites/build/brand-scss.test.js +1 -1
- package/dist/test/suites/build/build-json-bake.test.js +1 -1
- package/dist/test/suites/build/cli.test.js +2 -2
- package/dist/test/suites/build/config-schema.test.js +5 -5
- package/dist/test/suites/build/defaults-scaffold.test.js +2 -2
- package/dist/test/suites/build/deploy-hook.test.js +3 -3
- package/dist/test/suites/build/ensure-target.test.js +2 -2
- package/dist/test/suites/build/env-delivery.test.js +2 -2
- package/dist/test/suites/build/esm-only-dependency.test.js +2 -2
- package/dist/test/suites/build/exports.test.js +9 -8
- package/dist/test/suites/build/get-config.test.js +4 -4
- package/dist/test/suites/build/manifest-deps.test.js +1 -1
- package/dist/test/suites/build/merge-line-files.test.js +1 -1
- package/dist/test/suites/build/omega-shell.test.js +34 -2
- package/dist/test/suites/build/omega.test.js +350 -0
- package/dist/test/suites/build/renderer-auth-bridge.test.js +211 -78
- package/dist/test/suites/build/runner.test.js +2 -2
- package/dist/test/suites/build/sentry.test.js +2 -2
- package/dist/test/suites/build/sign-windows-e2e.test.js +2 -2
- package/dist/test/suites/build/templating.test.js +3 -3
- package/dist/test/suites/build/test-stealth.test.js +7 -9
- package/dist/test/suites/build/url-helpers.test.js +55 -56
- package/dist/test/suites/build/validate-config.test.js +2 -2
- package/dist/test/suites/build/wave5-pins.test.js +2 -2
- package/dist/test/suites/main/analytics.test.js +59 -59
- package/dist/test/suites/main/app-state.test.js +66 -66
- package/dist/test/suites/main/auth-flow.test.js +41 -41
- package/dist/test/suites/main/auth-persistence.test.js +54 -43
- package/dist/test/suites/main/{client-bridge.integration.test.js → auth.integration.test.js} +10 -9
- package/dist/test/suites/main/auth.test.js +336 -0
- package/dist/test/suites/main/auto-updater.test.js +134 -134
- package/dist/test/suites/main/boot-sequence.test.js +37 -49
- package/dist/test/suites/main/context-menu.test.js +51 -50
- package/dist/test/suites/main/context.test.js +25 -25
- package/dist/test/suites/main/deep-link.test.js +74 -74
- package/dist/test/suites/main/fontawesome.test.js +27 -27
- package/dist/test/suites/main/ipc.test.js +35 -35
- package/dist/test/suites/main/menu.test.js +101 -100
- package/dist/test/suites/main/protocol.test.js +19 -19
- package/dist/test/suites/main/remote-config.test.js +63 -63
- package/dist/test/suites/main/remote-scripts.test.js +103 -103
- package/dist/test/suites/main/request.test.js +71 -0
- package/dist/test/suites/main/restart-manager.test.js +33 -33
- package/dist/test/suites/main/startup-paths-and-ua.test.js +4 -4
- package/dist/test/suites/main/startup.test.js +26 -26
- package/dist/test/suites/main/stealth-window.test.js +1 -1
- package/dist/test/suites/main/storage.test.js +25 -25
- package/dist/test/suites/main/theme.test.js +34 -34
- package/dist/test/suites/main/tray.test.js +79 -79
- package/dist/test/suites/main/url-helpers.test.js +133 -133
- package/dist/test/suites/main/usage.test.js +25 -25
- package/dist/test/suites/main/window-bounds.test.js +27 -27
- package/dist/test/suites/main/window-manager.test.js +44 -44
- package/dist/test/suites/renderer/analytics-bridge.test.js +5 -5
- package/dist/test/suites/renderer/cross-context-helpers.test.js +37 -31
- package/dist/test/suites/renderer/round-trip.test.js +3 -3
- package/dist/test/suites/renderer/tooltips.test.js +15 -15
- package/dist/test/suites/renderer/{window-em-surface.test.js → window-desktop-surface.test.js} +27 -7
- package/dist/test/utils/extended-mode-warning.js +1 -1
- package/dist/utils/boot-harness.js +56 -0
- package/dist/utils/mode-helpers.js +2 -15
- package/dist/utils/ship-keys.js +3 -3
- package/dist/utils/signing-status.js +51 -0
- package/dist/utils/test-events.js +7 -0
- package/dist/utils/test-stealth.js +6 -6
- package/dist/utils/url-helpers.js +52 -42
- package/dist/utils/user-agent.js +44 -0
- package/dist/vendor/account/engine.js +3 -3
- package/dist/vendor/account/index.js +14 -45
- package/dist/vendor/account/resolve-account.js +44 -0
- package/dist/vendor/account/schema.js +1 -1
- package/dist/vendor/account/user.js +99 -0
- package/dist/vendor/config/client-config.js +1 -1
- package/dist/vendor/config/environment.js +11 -30
- package/dist/vendor/config/index.js +8 -11
- package/dist/vendor/config/load.js +1 -2
- package/dist/vendor/config/platforms.js +1 -1
- package/dist/vendor/config/retired-keys.js +2 -2
- package/dist/vendor/config/schema.js +5 -8
- package/dist/vendor/config/site-global.js +2 -3
- package/dist/vendor/config/validate.js +1 -2
- package/dist/vendor/config/winback.js +1 -1
- package/dist/vendor/devkit/actions-secrets.js +1 -1
- package/dist/vendor/devkit/attach-log-file.js +1 -1
- package/dist/vendor/devkit/build-json.js +1 -1
- package/dist/vendor/devkit/cli-router.js +3 -4
- package/dist/vendor/devkit/defaults-engine.js +9 -11
- package/dist/vendor/devkit/local.js +2 -0
- package/dist/vendor/devkit/merge-line-files.js +2 -3
- package/dist/vendor/devkit/test/runner-core.js +6 -6
- package/dist/vendor/monitoring/env.js +2 -2
- package/dist/vendor/monitoring/index.js +1 -1
- package/dist/vendor/monitoring/main.js +1 -1
- package/dist/vendor/monitoring/preload.js +1 -1
- package/dist/vendor/monitoring/renderer.js +1 -1
- package/docs/analytics.md +8 -8
- package/docs/app-state.md +19 -19
- package/docs/audit.md +4 -4
- package/docs/{client-bridge.md → auth.md} +88 -73
- package/docs/auto-updater.md +8 -8
- package/docs/boot-sequence.md +11 -6
- package/docs/build-system.md +1 -1
- package/docs/cdp-debugging.md +1 -1
- package/docs/common-mistakes.md +7 -7
- package/docs/config-schema.md +1 -1
- package/docs/context-menu.md +13 -13
- package/docs/context.md +11 -11
- package/docs/css.md +3 -9
- package/docs/deep-link.md +25 -25
- package/docs/environment-detection.md +16 -16
- package/docs/fontawesome.md +7 -5
- package/docs/hooks.md +8 -8
- package/docs/index.md +38 -27
- package/docs/ipc.md +10 -10
- package/docs/lib-modules.md +9 -9
- package/docs/logging.md +12 -14
- package/docs/menu.md +18 -18
- package/docs/remote-config.md +9 -9
- package/docs/remote-scripts.md +12 -12
- package/docs/restart-manager.md +8 -8
- package/docs/sentry.md +4 -4
- package/docs/shared/analytics.md +1 -1
- package/docs/shared/breaking-changes.md +79 -13
- package/docs/shared/config.md +17 -21
- package/docs/shared/logging.md +1 -1
- package/docs/shared/monitoring.md +5 -5
- package/docs/shared/testing.md +2 -2
- package/docs/shared/theming.md +1 -1
- package/docs/shared/translation.md +19 -10
- package/docs/startup.md +16 -16
- package/docs/storage.md +11 -11
- package/docs/templating.md +3 -3
- package/docs/test-boot-layer.md +12 -12
- package/docs/test-framework.md +17 -17
- package/docs/themes.md +7 -7
- package/docs/tooltips.md +2 -2
- package/docs/tray.md +31 -31
- package/docs/usage.md +7 -7
- package/docs/verts.md +1 -1
- package/docs/windows.md +22 -22
- package/package.json +3 -4
- package/dist/lib/client-bridge.js +0 -374
- package/dist/lib/logger.js +0 -4
- package/dist/test/suites/build/manager.test.js +0 -213
- package/dist/test/suites/main/client-bridge.test.js +0 -262
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Main-process tests for lib/app-state.js — storage-backed launch flags + crash sentinel.
|
|
2
2
|
//
|
|
3
|
-
// The harness already booted
|
|
3
|
+
// The harness already booted omega once, which incremented launchCount and seeded
|
|
4
4
|
// state. We test by calling appState.reset() then re-initializing with crafted
|
|
5
5
|
// storage state to simulate first-launch / repeat-launch / crash-recovery / upgrade.
|
|
6
6
|
|
|
@@ -14,60 +14,60 @@ module.exports = defineCases({
|
|
|
14
14
|
description: 'app-state (main)',
|
|
15
15
|
cleanup: async (ctx) => {
|
|
16
16
|
// Restore a sane state for any later suites that look at appState.
|
|
17
|
-
ctx.
|
|
17
|
+
ctx.omega.appState.reset();
|
|
18
18
|
// Mark _initialized=false so we can re-init cleanly.
|
|
19
|
-
ctx.
|
|
20
|
-
await ctx.
|
|
19
|
+
ctx.omega.appState._initialized = false;
|
|
20
|
+
await ctx.omega.appState.initialize(ctx.omega);
|
|
21
21
|
},
|
|
22
22
|
tests: [
|
|
23
23
|
{
|
|
24
24
|
name: 'initialize ran during boot',
|
|
25
25
|
run: (ctx) => {
|
|
26
|
-
ctx.expect(ctx.
|
|
26
|
+
ctx.expect(ctx.omega.appState._initialized).toBe(true);
|
|
27
27
|
},
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
30
|
name: 'first launch: flags + counters seeded correctly',
|
|
31
31
|
run: async (ctx) => {
|
|
32
|
-
ctx.
|
|
33
|
-
ctx.
|
|
34
|
-
await ctx.
|
|
35
|
-
|
|
36
|
-
ctx.expect(ctx.
|
|
37
|
-
ctx.expect(ctx.
|
|
38
|
-
ctx.expect(ctx.
|
|
39
|
-
ctx.expect(ctx.
|
|
40
|
-
ctx.expect(ctx.
|
|
32
|
+
ctx.omega.appState.reset();
|
|
33
|
+
ctx.omega.appState._initialized = false;
|
|
34
|
+
await ctx.omega.appState.initialize(ctx.omega);
|
|
35
|
+
|
|
36
|
+
ctx.expect(ctx.omega.appState.isFirstLaunch()).toBe(true);
|
|
37
|
+
ctx.expect(ctx.omega.appState.getLaunchCount()).toBe(1);
|
|
38
|
+
ctx.expect(ctx.omega.appState.getInstalledAt()).toBeInstanceOf(Date);
|
|
39
|
+
ctx.expect(ctx.omega.appState.getLastLaunchAt()).toBeNull();
|
|
40
|
+
ctx.expect(ctx.omega.appState.recoveredFromCrash()).toBe(false);
|
|
41
41
|
},
|
|
42
42
|
},
|
|
43
43
|
{
|
|
44
44
|
name: 'second launch: not first, count incremented, lastLaunchAt populated',
|
|
45
45
|
run: async (ctx) => {
|
|
46
|
-
ctx.
|
|
47
|
-
ctx.
|
|
48
|
-
await ctx.
|
|
46
|
+
ctx.omega.appState.reset();
|
|
47
|
+
ctx.omega.appState._initialized = false;
|
|
48
|
+
await ctx.omega.appState.initialize(ctx.omega);
|
|
49
49
|
|
|
50
50
|
// Simulate a graceful quit from the first launch.
|
|
51
|
-
const after1 = ctx.
|
|
51
|
+
const after1 = ctx.omega.storage.get(STORAGE_KEY);
|
|
52
52
|
after1.sentinel = false;
|
|
53
53
|
after1.lastQuitAt = Date.now();
|
|
54
|
-
ctx.
|
|
54
|
+
ctx.omega.storage.set(STORAGE_KEY, after1);
|
|
55
55
|
|
|
56
56
|
// Boot again.
|
|
57
|
-
ctx.
|
|
58
|
-
await ctx.
|
|
57
|
+
ctx.omega.appState._initialized = false;
|
|
58
|
+
await ctx.omega.appState.initialize(ctx.omega);
|
|
59
59
|
|
|
60
|
-
ctx.expect(ctx.
|
|
61
|
-
ctx.expect(ctx.
|
|
62
|
-
ctx.expect(ctx.
|
|
63
|
-
ctx.expect(ctx.
|
|
60
|
+
ctx.expect(ctx.omega.appState.isFirstLaunch()).toBe(false);
|
|
61
|
+
ctx.expect(ctx.omega.appState.getLaunchCount()).toBe(2);
|
|
62
|
+
ctx.expect(ctx.omega.appState.getLastLaunchAt()).toBeInstanceOf(Date);
|
|
63
|
+
ctx.expect(ctx.omega.appState.recoveredFromCrash()).toBe(false);
|
|
64
64
|
},
|
|
65
65
|
},
|
|
66
66
|
{
|
|
67
67
|
name: 'crash detection: previous launch left sentinel and no quit timestamp',
|
|
68
68
|
run: async (ctx) => {
|
|
69
69
|
// Seed storage with a "we were running and never gracefully quit" state.
|
|
70
|
-
ctx.
|
|
70
|
+
ctx.omega.storage.set(STORAGE_KEY, {
|
|
71
71
|
installedAt: Date.now() - 10000,
|
|
72
72
|
launchCount: 3,
|
|
73
73
|
lastLaunchAt: Date.now() - 1000,
|
|
@@ -76,17 +76,17 @@ module.exports = defineCases({
|
|
|
76
76
|
version: '1.0.0',
|
|
77
77
|
});
|
|
78
78
|
|
|
79
|
-
ctx.
|
|
80
|
-
await ctx.
|
|
79
|
+
ctx.omega.appState._initialized = false;
|
|
80
|
+
await ctx.omega.appState.initialize(ctx.omega);
|
|
81
81
|
|
|
82
|
-
ctx.expect(ctx.
|
|
83
|
-
ctx.expect(ctx.
|
|
82
|
+
ctx.expect(ctx.omega.appState.recoveredFromCrash()).toBe(true);
|
|
83
|
+
ctx.expect(ctx.omega.appState.getLaunchCount()).toBe(4);
|
|
84
84
|
},
|
|
85
85
|
},
|
|
86
86
|
{
|
|
87
87
|
name: 'graceful quit: sentinel cleared on next boot, no crash flag',
|
|
88
88
|
run: async (ctx) => {
|
|
89
|
-
ctx.
|
|
89
|
+
ctx.omega.storage.set(STORAGE_KEY, {
|
|
90
90
|
installedAt: Date.now() - 10000,
|
|
91
91
|
launchCount: 5,
|
|
92
92
|
lastLaunchAt: Date.now() - 1000,
|
|
@@ -95,17 +95,17 @@ module.exports = defineCases({
|
|
|
95
95
|
version: '1.0.0',
|
|
96
96
|
});
|
|
97
97
|
|
|
98
|
-
ctx.
|
|
99
|
-
await ctx.
|
|
98
|
+
ctx.omega.appState._initialized = false;
|
|
99
|
+
await ctx.omega.appState.initialize(ctx.omega);
|
|
100
100
|
|
|
101
|
-
ctx.expect(ctx.
|
|
102
|
-
ctx.expect(ctx.
|
|
101
|
+
ctx.expect(ctx.omega.appState.recoveredFromCrash()).toBe(false);
|
|
102
|
+
ctx.expect(ctx.omega.appState.getLaunchCount()).toBe(6);
|
|
103
103
|
},
|
|
104
104
|
},
|
|
105
105
|
{
|
|
106
106
|
name: 'version upgrade: previousVersion populated when version changes',
|
|
107
107
|
run: async (ctx) => {
|
|
108
|
-
ctx.
|
|
108
|
+
ctx.omega.storage.set(STORAGE_KEY, {
|
|
109
109
|
installedAt: Date.now() - 10000,
|
|
110
110
|
launchCount: 10,
|
|
111
111
|
lastLaunchAt: Date.now() - 1000,
|
|
@@ -114,19 +114,19 @@ module.exports = defineCases({
|
|
|
114
114
|
version: '0.9.0', // previous version
|
|
115
115
|
});
|
|
116
116
|
|
|
117
|
-
// Force the
|
|
118
|
-
const origConfig = ctx.
|
|
119
|
-
ctx.
|
|
117
|
+
// Force the omega instance's reported version to differ.
|
|
118
|
+
const origConfig = ctx.omega.config.app;
|
|
119
|
+
ctx.omega.config.app = { ...origConfig, version: '1.0.0' };
|
|
120
120
|
|
|
121
121
|
try {
|
|
122
|
-
ctx.
|
|
123
|
-
await ctx.
|
|
122
|
+
ctx.omega.appState._initialized = false;
|
|
123
|
+
await ctx.omega.appState.initialize(ctx.omega);
|
|
124
124
|
|
|
125
|
-
ctx.expect(ctx.
|
|
126
|
-
ctx.expect(ctx.
|
|
127
|
-
ctx.expect(ctx.
|
|
125
|
+
ctx.expect(ctx.omega.appState.getVersion()).toBe('1.0.0');
|
|
126
|
+
ctx.expect(ctx.omega.appState.getPreviousVersion()).toBe('0.9.0');
|
|
127
|
+
ctx.expect(ctx.omega.appState.wasUpgraded()).toBe(true);
|
|
128
128
|
} finally {
|
|
129
|
-
ctx.
|
|
129
|
+
ctx.omega.config.app = origConfig;
|
|
130
130
|
}
|
|
131
131
|
},
|
|
132
132
|
},
|
|
@@ -134,7 +134,7 @@ module.exports = defineCases({
|
|
|
134
134
|
name: 'no version change: wasUpgraded false, previousVersion preserved',
|
|
135
135
|
run: async (ctx) => {
|
|
136
136
|
// Seed with a previousVersion that should NOT be overwritten when version doesn't change.
|
|
137
|
-
ctx.
|
|
137
|
+
ctx.omega.storage.set(STORAGE_KEY, {
|
|
138
138
|
installedAt: Date.now() - 10000,
|
|
139
139
|
launchCount: 20,
|
|
140
140
|
lastLaunchAt: Date.now() - 1000,
|
|
@@ -144,53 +144,53 @@ module.exports = defineCases({
|
|
|
144
144
|
previousVersion: '0.9.0',
|
|
145
145
|
});
|
|
146
146
|
|
|
147
|
-
const origConfig = ctx.
|
|
148
|
-
ctx.
|
|
147
|
+
const origConfig = ctx.omega.config.app;
|
|
148
|
+
ctx.omega.config.app = { ...origConfig, version: '1.0.0' };
|
|
149
149
|
|
|
150
150
|
try {
|
|
151
|
-
ctx.
|
|
152
|
-
await ctx.
|
|
151
|
+
ctx.omega.appState._initialized = false;
|
|
152
|
+
await ctx.omega.appState.initialize(ctx.omega);
|
|
153
153
|
|
|
154
|
-
ctx.expect(ctx.
|
|
154
|
+
ctx.expect(ctx.omega.appState.wasUpgraded()).toBe(false);
|
|
155
155
|
// Should preserve the historical previousVersion rather than nuking it.
|
|
156
|
-
ctx.expect(ctx.
|
|
156
|
+
ctx.expect(ctx.omega.appState.getPreviousVersion()).toBe('0.9.0');
|
|
157
157
|
} finally {
|
|
158
|
-
ctx.
|
|
158
|
+
ctx.omega.config.app = origConfig;
|
|
159
159
|
}
|
|
160
160
|
},
|
|
161
161
|
},
|
|
162
162
|
{
|
|
163
163
|
name: 'launchedFromDeepLink: defaults false, set/cleared via setter',
|
|
164
164
|
run: (ctx) => {
|
|
165
|
-
ctx.expect(ctx.
|
|
166
|
-
ctx.
|
|
167
|
-
ctx.expect(ctx.
|
|
168
|
-
ctx.
|
|
169
|
-
ctx.expect(ctx.
|
|
165
|
+
ctx.expect(ctx.omega.appState.launchedFromDeepLink()).toBe(false);
|
|
166
|
+
ctx.omega.appState.setLaunchedFromDeepLink(true);
|
|
167
|
+
ctx.expect(ctx.omega.appState.launchedFromDeepLink()).toBe(true);
|
|
168
|
+
ctx.omega.appState.setLaunchedFromDeepLink(false);
|
|
169
|
+
ctx.expect(ctx.omega.appState.launchedFromDeepLink()).toBe(false);
|
|
170
170
|
},
|
|
171
171
|
},
|
|
172
172
|
{
|
|
173
173
|
name: 'launchedAtLogin returns a boolean',
|
|
174
174
|
run: (ctx) => {
|
|
175
|
-
ctx.expect(typeof ctx.
|
|
175
|
+
ctx.expect(typeof ctx.omega.appState.launchedAtLogin()).toBe('boolean');
|
|
176
176
|
},
|
|
177
177
|
},
|
|
178
178
|
{
|
|
179
179
|
name: 'getLastQuitAt reads live storage (returns null when sentinel is active)',
|
|
180
180
|
run: async (ctx) => {
|
|
181
|
-
ctx.
|
|
182
|
-
ctx.
|
|
183
|
-
await ctx.
|
|
181
|
+
ctx.omega.appState.reset();
|
|
182
|
+
ctx.omega.appState._initialized = false;
|
|
183
|
+
await ctx.omega.appState.initialize(ctx.omega);
|
|
184
184
|
// After init, sentinel=true and lastQuitAt=null.
|
|
185
|
-
ctx.expect(ctx.
|
|
185
|
+
ctx.expect(ctx.omega.appState.getLastQuitAt()).toBeNull();
|
|
186
186
|
},
|
|
187
187
|
},
|
|
188
188
|
{
|
|
189
189
|
name: 'reset() wipes persisted state',
|
|
190
190
|
run: (ctx) => {
|
|
191
|
-
ctx.expect(ctx.
|
|
192
|
-
ctx.
|
|
193
|
-
ctx.expect(ctx.
|
|
191
|
+
ctx.expect(ctx.omega.storage.has(STORAGE_KEY)).toBe(true);
|
|
192
|
+
ctx.omega.appState.reset();
|
|
193
|
+
ctx.expect(ctx.omega.storage.has(STORAGE_KEY)).toBe(false);
|
|
194
194
|
},
|
|
195
195
|
},
|
|
196
196
|
],
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Main-process tests for lib/auth-flow.js — the openAuthFlow() sign-in round trip.
|
|
2
2
|
// The dev loopback listener is REAL (http server on 127.0.0.1, real GETs simulate the
|
|
3
3
|
// browser's redirect back); only the pieces that would leave the machine are stubbed
|
|
4
|
-
// (shell.openExternal,
|
|
4
|
+
// (shell.openExternal, auth.handleToken, windows.get's show/focus surface).
|
|
5
5
|
|
|
6
6
|
const http = require('http');
|
|
7
7
|
const defineCases = require('../../../vendor/devkit/test/define-cases.js');
|
|
@@ -25,7 +25,7 @@ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
|
25
25
|
// getWebsiteUrl(), which since
|
|
26
26
|
// [#834](https://github.com/Omega-JS-Stack/omega/issues/834) answers from the
|
|
27
27
|
// resolved dev map the bundle task bakes (whose floor is @omega.js/config's
|
|
28
|
-
// classic numbers) and throws when an artifact carries none. The harness
|
|
28
|
+
// classic numbers) and throws when an artifact carries none. The harness instance
|
|
29
29
|
// loads src/defaults' config, which has no build behind it, so a real dev
|
|
30
30
|
// artifact's block is stated here.
|
|
31
31
|
function stubExternals(ctx) {
|
|
@@ -35,23 +35,23 @@ function stubExternals(ctx) {
|
|
|
35
35
|
const tokens = [];
|
|
36
36
|
const shown = [];
|
|
37
37
|
const origOpen = electron.shell.openExternal;
|
|
38
|
-
const origHandle = ctx.
|
|
39
|
-
const origShow = ctx.
|
|
40
|
-
const origDev = ctx.
|
|
38
|
+
const origHandle = ctx.omega.auth.handleToken;
|
|
39
|
+
const origShow = ctx.omega.windows.show;
|
|
40
|
+
const origDev = ctx.omega.config.dev;
|
|
41
41
|
electron.shell.openExternal = async (url) => { opened.push(url); };
|
|
42
|
-
ctx.
|
|
43
|
-
ctx.
|
|
44
|
-
ctx.
|
|
42
|
+
ctx.omega.auth.handleToken = (t) => { tokens.push(t); };
|
|
43
|
+
ctx.omega.windows.show = (name) => { shown.push(name); };
|
|
44
|
+
ctx.omega.config.dev = { ports: { ...CLASSIC_PORTS } };
|
|
45
45
|
return {
|
|
46
46
|
opened,
|
|
47
47
|
tokens,
|
|
48
48
|
shown,
|
|
49
49
|
restore() {
|
|
50
50
|
electron.shell.openExternal = origOpen;
|
|
51
|
-
ctx.
|
|
52
|
-
ctx.
|
|
53
|
-
if (origDev !== undefined) ctx.
|
|
54
|
-
ctx.
|
|
51
|
+
ctx.omega.auth.handleToken = origHandle;
|
|
52
|
+
ctx.omega.windows.show = origShow;
|
|
53
|
+
if (origDev !== undefined) ctx.omega.config.dev = origDev; else delete ctx.omega.config.dev;
|
|
54
|
+
ctx.omega.authFlow.cancel();
|
|
55
55
|
},
|
|
56
56
|
};
|
|
57
57
|
}
|
|
@@ -64,7 +64,7 @@ module.exports = defineCases({
|
|
|
64
64
|
{
|
|
65
65
|
name: 'initialize ran during boot',
|
|
66
66
|
run: (ctx) => {
|
|
67
|
-
ctx.expect(ctx.
|
|
67
|
+
ctx.expect(ctx.omega.authFlow._initialized).toBe(true);
|
|
68
68
|
},
|
|
69
69
|
},
|
|
70
70
|
{
|
|
@@ -72,7 +72,7 @@ module.exports = defineCases({
|
|
|
72
72
|
run: async (ctx) => {
|
|
73
73
|
const stubs = stubExternals(ctx);
|
|
74
74
|
try {
|
|
75
|
-
const { url, port } = await ctx.
|
|
75
|
+
const { url, port } = await ctx.omega.openAuthFlow();
|
|
76
76
|
ctx.expect(typeof port).toBe('number');
|
|
77
77
|
ctx.expect(stubs.opened[0]).toBe(url);
|
|
78
78
|
|
|
@@ -85,19 +85,19 @@ module.exports = defineCases({
|
|
|
85
85
|
ctx.expect(returnUrl.hostname).toBe('127.0.0.1');
|
|
86
86
|
ctx.expect(Number(returnUrl.port)).toBe(port);
|
|
87
87
|
ctx.expect(returnUrl.pathname).toBe('/auth/token');
|
|
88
|
-
ctx.expect(returnUrl.searchParams.get('state')).toBe(ctx.
|
|
88
|
+
ctx.expect(returnUrl.searchParams.get('state')).toBe(ctx.omega.authFlow._pending.nonce);
|
|
89
89
|
} finally {
|
|
90
90
|
stubs.restore();
|
|
91
91
|
}
|
|
92
92
|
},
|
|
93
93
|
},
|
|
94
94
|
{
|
|
95
|
-
name: 'valid browser return: 200 page, token →
|
|
95
|
+
name: 'valid browser return: 200 page, token → handleToken, listener torn down, app surfaced',
|
|
96
96
|
run: async (ctx) => {
|
|
97
97
|
const stubs = stubExternals(ctx);
|
|
98
98
|
try {
|
|
99
|
-
const { port } = await ctx.
|
|
100
|
-
const nonce = ctx.
|
|
99
|
+
const { port } = await ctx.omega.openAuthFlow();
|
|
100
|
+
const nonce = ctx.omega.authFlow._pending.nonce;
|
|
101
101
|
|
|
102
102
|
const res = await get(`http://127.0.0.1:${port}/auth/token?authToken=TOK-1&state=${nonce}`);
|
|
103
103
|
ctx.expect(res.status).toBe(200);
|
|
@@ -106,7 +106,7 @@ module.exports = defineCases({
|
|
|
106
106
|
ctx.expect(stubs.shown).toEqual(['main']);
|
|
107
107
|
|
|
108
108
|
// One-shot: the listener is gone.
|
|
109
|
-
ctx.expect(ctx.
|
|
109
|
+
ctx.expect(ctx.omega.authFlow._pending).toBeNull();
|
|
110
110
|
let refused = false;
|
|
111
111
|
await get(`http://127.0.0.1:${port}/auth/token?authToken=x&state=${nonce}`).catch(() => { refused = true; });
|
|
112
112
|
ctx.expect(refused).toBe(true);
|
|
@@ -116,12 +116,12 @@ module.exports = defineCases({
|
|
|
116
116
|
},
|
|
117
117
|
},
|
|
118
118
|
{
|
|
119
|
-
name: 'bad state or missing token: 400, no
|
|
119
|
+
name: 'bad state or missing token: 400, no handleToken, listener SURVIVES for the real return',
|
|
120
120
|
run: async (ctx) => {
|
|
121
121
|
const stubs = stubExternals(ctx);
|
|
122
122
|
try {
|
|
123
|
-
const { port } = await ctx.
|
|
124
|
-
const nonce = ctx.
|
|
123
|
+
const { port } = await ctx.omega.openAuthFlow();
|
|
124
|
+
const nonce = ctx.omega.authFlow._pending.nonce;
|
|
125
125
|
|
|
126
126
|
const bad1 = await get(`http://127.0.0.1:${port}/auth/token?authToken=EVIL&state=wrong`);
|
|
127
127
|
ctx.expect(bad1.status).toBe(400);
|
|
@@ -145,8 +145,8 @@ module.exports = defineCases({
|
|
|
145
145
|
run: async (ctx) => {
|
|
146
146
|
const stubs = stubExternals(ctx);
|
|
147
147
|
try {
|
|
148
|
-
const first = await ctx.
|
|
149
|
-
const second = await ctx.
|
|
148
|
+
const first = await ctx.omega.openAuthFlow();
|
|
149
|
+
const second = await ctx.omega.openAuthFlow();
|
|
150
150
|
|
|
151
151
|
// The first port no longer answers (unless the OS re-issued the same port to the
|
|
152
152
|
// second listener, in which case the nonce changed anyway).
|
|
@@ -155,7 +155,7 @@ module.exports = defineCases({
|
|
|
155
155
|
await get(`http://127.0.0.1:${first.port}/auth/token`).catch(() => { refused = true; });
|
|
156
156
|
ctx.expect(refused).toBe(true);
|
|
157
157
|
}
|
|
158
|
-
ctx.expect(ctx.
|
|
158
|
+
ctx.expect(ctx.omega.authFlow._pending.port).toBe(second.port);
|
|
159
159
|
} finally {
|
|
160
160
|
stubs.restore();
|
|
161
161
|
}
|
|
@@ -166,12 +166,12 @@ module.exports = defineCases({
|
|
|
166
166
|
run: async (ctx) => {
|
|
167
167
|
const stubs = stubExternals(ctx);
|
|
168
168
|
try {
|
|
169
|
-
const { port } = await ctx.
|
|
170
|
-
ctx.expect(ctx.
|
|
169
|
+
const { port } = await ctx.omega.openAuthFlow({ timeoutMs: 50 });
|
|
170
|
+
ctx.expect(ctx.omega.authFlow._pending.port).toBe(port);
|
|
171
171
|
await sleep(150);
|
|
172
|
-
ctx.expect(ctx.
|
|
173
|
-
ctx.
|
|
174
|
-
ctx.
|
|
172
|
+
ctx.expect(ctx.omega.authFlow._pending).toBeNull();
|
|
173
|
+
ctx.omega.authFlow.cancel();
|
|
174
|
+
ctx.omega.authFlow.cancel();
|
|
175
175
|
} finally {
|
|
176
176
|
stubs.restore();
|
|
177
177
|
}
|
|
@@ -181,25 +181,25 @@ module.exports = defineCases({
|
|
|
181
181
|
name: 'production open(): plain external open of getAuthUrl(), no listener',
|
|
182
182
|
run: async (ctx) => {
|
|
183
183
|
const stubs = stubExternals(ctx);
|
|
184
|
-
const
|
|
185
|
-
const origIsProd =
|
|
186
|
-
|
|
187
|
-
const origUrl =
|
|
188
|
-
|
|
189
|
-
|
|
184
|
+
const omega = ctx.omega;
|
|
185
|
+
const origIsProd = omega.isProduction;
|
|
186
|
+
omega.config.brand = omega.config.brand || {};
|
|
187
|
+
const origUrl = omega.config.brand.url;
|
|
188
|
+
omega.isProduction = () => true;
|
|
189
|
+
omega.config.brand.url = 'https://example.com';
|
|
190
190
|
try {
|
|
191
|
-
const { url, port } = await
|
|
191
|
+
const { url, port } = await omega.openAuthFlow();
|
|
192
192
|
ctx.expect(port).toBeUndefined();
|
|
193
|
-
ctx.expect(ctx.
|
|
193
|
+
ctx.expect(ctx.omega.authFlow._pending).toBeNull();
|
|
194
194
|
ctx.expect(stubs.opened[0]).toBe(url);
|
|
195
195
|
// Prod URL must ride the custom scheme, not a loopback return.
|
|
196
196
|
const signin = new URL(url);
|
|
197
197
|
const tokenUrl = new URL(signin.searchParams.get('authReturnUrl'));
|
|
198
198
|
const finalHop = tokenUrl.searchParams.get('authReturnUrl');
|
|
199
|
-
ctx.expect(finalHop).toBe(`${
|
|
199
|
+
ctx.expect(finalHop).toBe(`${omega.config.brand.id}://auth/token`);
|
|
200
200
|
} finally {
|
|
201
|
-
|
|
202
|
-
if (origUrl !== undefined)
|
|
201
|
+
omega.isProduction = origIsProd;
|
|
202
|
+
if (origUrl !== undefined) omega.config.brand.url = origUrl; else delete omega.config.brand.url;
|
|
203
203
|
stubs.restore();
|
|
204
204
|
}
|
|
205
205
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
// Main-process tests for lib/auth-persistence.js (pluggable session vault) and
|
|
2
|
-
//
|
|
1
|
+
// Main-process tests for lib/auth-persistence.js (pluggable session vault) and
|
|
2
|
+
// lib/auth.js's desktop:auth:account-resolved intake (renderer → main account).
|
|
3
3
|
// The safeStorage strategy runs REAL (OS keychain + real file under userData) when
|
|
4
4
|
// encryption is available in the test environment; adapter logic is covered against
|
|
5
5
|
// a real in-memory strategy either way.
|
|
@@ -27,27 +27,27 @@ module.exports = defineCases({
|
|
|
27
27
|
{
|
|
28
28
|
name: 'resolve(): a test run is none, whatever the config says',
|
|
29
29
|
run: async (ctx) => {
|
|
30
|
-
const
|
|
31
|
-
ctx.expect(
|
|
32
|
-
|
|
33
|
-
const orig =
|
|
30
|
+
const omega = ctx.omega;
|
|
31
|
+
ctx.expect(omega.isTesting()).toBe(true);
|
|
32
|
+
omega.config.omega = omega.config.omega || {};
|
|
33
|
+
const orig = omega.config.omega.authPersistence;
|
|
34
34
|
try {
|
|
35
35
|
// Unset, and explicitly asking for the vault, both land on none: the harness
|
|
36
36
|
// never signs a real user in, so it never asks the OS keychain
|
|
37
37
|
// ([#907](https://github.com/Omega-JS-Stack/omega/issues/907)).
|
|
38
|
-
delete
|
|
39
|
-
ctx.expect(await authPersistence.resolve(
|
|
38
|
+
delete omega.config.omega.authPersistence;
|
|
39
|
+
ctx.expect(await authPersistence.resolve(omega)).toBeNull();
|
|
40
40
|
ctx.expect(authPersistence.getActive()).toBeNull();
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
ctx.expect(await authPersistence.resolve(
|
|
42
|
+
omega.config.omega.authPersistence = 'safeStorage';
|
|
43
|
+
ctx.expect(await authPersistence.resolve(omega)).toBeNull();
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
ctx.expect(await authPersistence.resolve(
|
|
45
|
+
omega.config.omega.authPersistence = 'none';
|
|
46
|
+
ctx.expect(await authPersistence.resolve(omega)).toBeNull();
|
|
47
47
|
} finally {
|
|
48
|
-
if (orig !== undefined)
|
|
49
|
-
else delete
|
|
50
|
-
await authPersistence.resolve(
|
|
48
|
+
if (orig !== undefined) omega.config.omega.authPersistence = orig;
|
|
49
|
+
else delete omega.config.omega.authPersistence;
|
|
50
|
+
await authPersistence.resolve(omega); // restore the active strategy for later suites
|
|
51
51
|
}
|
|
52
52
|
},
|
|
53
53
|
},
|
|
@@ -58,7 +58,7 @@ module.exports = defineCases({
|
|
|
58
58
|
|
|
59
59
|
authPersistence.register('desktop-test-custom', fakeStrategy());
|
|
60
60
|
try {
|
|
61
|
-
// Selection by config is proven at the build layer, on a production
|
|
61
|
+
// Selection by config is proven at the build layer, on a production omega instance:
|
|
62
62
|
// under test mode resolve() answers none before it reads a thing.
|
|
63
63
|
ctx.expect(authPersistence._strategies['desktop-test-custom'].name).toBe('desktop-test-custom');
|
|
64
64
|
ctx.expect(await authPersistence._strategies['desktop-test-custom'].available()).toBe(true);
|
|
@@ -116,47 +116,58 @@ module.exports = defineCases({
|
|
|
116
116
|
},
|
|
117
117
|
},
|
|
118
118
|
{
|
|
119
|
-
name: '
|
|
119
|
+
name: 'auth account-resolved intake: uid-guarded, lands a User, broadcasts { document } once per change, dropped on sign-out',
|
|
120
120
|
run: async (ctx) => {
|
|
121
|
-
const
|
|
122
|
-
const
|
|
123
|
-
const origAuth =
|
|
124
|
-
const origBroadcast =
|
|
121
|
+
const omega = ctx.omega;
|
|
122
|
+
const auth = omega.auth;
|
|
123
|
+
const origAuth = auth._firebaseAuth;
|
|
124
|
+
const origBroadcast = omega.ipc.broadcast;
|
|
125
125
|
const broadcasts = [];
|
|
126
|
-
|
|
126
|
+
omega.ipc.broadcast = (ch, payload) => { if (ch === 'desktop:auth:plan-changed') broadcasts.push(payload); };
|
|
127
|
+
|
|
128
|
+
// What a signed-in renderer pushes: its User's stored document (resolved,
|
|
129
|
+
// metadata stamped) and its identity
|
|
130
|
+
const { User } = require('../../../vendor/account/index.js');
|
|
131
|
+
const IDENTITY = { uid: 'u1', email: 'x@y.z', displayName: 'X', photoURL: null, emailVerified: true };
|
|
132
|
+
const DOCUMENT = new User({ subscription: { product: { id: 'premium' }, status: 'active' }, roles: { betaTester: true } }, IDENTITY).toJSON();
|
|
133
|
+
|
|
127
134
|
try {
|
|
128
|
-
// Main signed out → any push is rejected.
|
|
129
|
-
|
|
130
|
-
let res = await
|
|
135
|
+
// Main signed out → any push is rejected, `user` stays signed out.
|
|
136
|
+
auth._firebaseAuth = { currentUser: null };
|
|
137
|
+
let res = await omega.ipc.invoke('desktop:auth:account-resolved', { uid: 'u1', document: DOCUMENT, identity: IDENTITY });
|
|
131
138
|
ctx.expect(res.accepted).toBe(false);
|
|
132
|
-
ctx.expect(
|
|
139
|
+
ctx.expect(auth.user.authenticated).toBe(false);
|
|
140
|
+
ctx.expect(auth.user.plan).toBe('basic');
|
|
133
141
|
|
|
134
|
-
// Matching uid →
|
|
135
|
-
|
|
136
|
-
res = await
|
|
142
|
+
// Matching uid → main builds its User from the WHOLE document + broadcasts it.
|
|
143
|
+
auth._firebaseAuth = { currentUser: { uid: 'u1', email: 'x@y.z' } };
|
|
144
|
+
res = await omega.ipc.invoke('desktop:auth:account-resolved', { uid: 'u1', document: DOCUMENT, identity: IDENTITY });
|
|
137
145
|
ctx.expect(res.accepted).toBe(true);
|
|
138
|
-
ctx.expect(
|
|
139
|
-
ctx.expect(
|
|
146
|
+
ctx.expect(auth.user.uid).toBe('u1');
|
|
147
|
+
ctx.expect(auth.user.plan).toBe('premium');
|
|
148
|
+
ctx.expect(auth.user.roles.betaTester).toBe(true);
|
|
149
|
+
ctx.expect(auth.user.profile.displayName).toBe('X');
|
|
140
150
|
ctx.expect(broadcasts.length).toBe(1);
|
|
151
|
+
ctx.expect(broadcasts[0]).toEqual({ document: auth.user.toJSON() });
|
|
141
152
|
|
|
142
153
|
// Identical push → accepted but NO second broadcast.
|
|
143
|
-
await
|
|
154
|
+
await omega.ipc.invoke('desktop:auth:account-resolved', { uid: 'u1', document: DOCUMENT, identity: IDENTITY });
|
|
144
155
|
ctx.expect(broadcasts.length).toBe(1);
|
|
145
156
|
|
|
146
|
-
// Mismatched uid (stale renderer) → dropped,
|
|
147
|
-
res = await
|
|
157
|
+
// Mismatched uid (stale renderer) → dropped, account intact.
|
|
158
|
+
res = await omega.ipc.invoke('desktop:auth:account-resolved', { uid: 'other', document: { subscription: { product: { id: 'max' }, status: 'active' } } });
|
|
148
159
|
ctx.expect(res.accepted).toBe(false);
|
|
149
|
-
ctx.expect(
|
|
160
|
+
ctx.expect(auth.user.plan).toBe('premium');
|
|
150
161
|
|
|
151
|
-
// Sign-out
|
|
152
|
-
|
|
153
|
-
ctx.expect(
|
|
154
|
-
ctx.expect(
|
|
162
|
+
// Sign-out drops the account.
|
|
163
|
+
auth._handleAuthStateChange(null);
|
|
164
|
+
ctx.expect(auth.user.authenticated).toBe(false);
|
|
165
|
+
ctx.expect(auth.user.plan).toBe('basic');
|
|
155
166
|
} finally {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
167
|
+
// A case that failed midway still leaves main signed out for the suites after it
|
|
168
|
+
if (auth.user.authenticated) auth._handleAuthStateChange(null);
|
|
169
|
+
auth._firebaseAuth = origAuth;
|
|
170
|
+
omega.ipc.broadcast = origBroadcast;
|
|
160
171
|
}
|
|
161
172
|
},
|
|
162
173
|
},
|
package/dist/test/suites/main/{client-bridge.integration.test.js → auth.integration.test.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Integration tests for
|
|
1
|
+
// Integration tests for lib/auth.js (`omega.auth`): actually hits Firebase.
|
|
2
2
|
//
|
|
3
3
|
// The SIGN-IN proof lives in #904: web, desktop and extension each sign in as a
|
|
4
4
|
// persona the backend emulator seeds, so this suite no longer mints a custom
|
|
@@ -25,32 +25,33 @@ const skipReason = checkSkipReason();
|
|
|
25
25
|
module.exports = defineCases({
|
|
26
26
|
type: 'suite',
|
|
27
27
|
layer: 'main',
|
|
28
|
-
description: '
|
|
28
|
+
description: 'auth (main, integration)',
|
|
29
29
|
skip: skipReason || false,
|
|
30
30
|
cleanup: async (ctx) => {
|
|
31
31
|
try {
|
|
32
|
-
await ctx.
|
|
32
|
+
await ctx.omega.auth.signOut();
|
|
33
33
|
} catch (e) { /* ignore */ }
|
|
34
34
|
},
|
|
35
35
|
tests: [
|
|
36
36
|
{
|
|
37
37
|
name: 'firebase loaded (cloud.config present in test config)',
|
|
38
38
|
run: (ctx) => {
|
|
39
|
-
if (!ctx.
|
|
39
|
+
if (!ctx.omega.auth._firebaseAuth) {
|
|
40
40
|
ctx.skip('cloud.config not set in default config — set one in src/defaults/config/omega.json5 to run');
|
|
41
41
|
}
|
|
42
|
-
ctx.expect(ctx.
|
|
42
|
+
ctx.expect(ctx.omega.auth._firebaseAuth).toBeTruthy();
|
|
43
43
|
},
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
|
-
name: 'sign-out
|
|
46
|
+
name: 'sign-out ends the session, drops the account, and broadcasts',
|
|
47
47
|
run: async (ctx) => {
|
|
48
|
-
if (!ctx.
|
|
48
|
+
if (!ctx.omega.auth._firebaseAuth?.currentUser) {
|
|
49
49
|
ctx.skip('not signed in (previous test may have skipped)');
|
|
50
50
|
}
|
|
51
|
-
const r = await ctx.
|
|
51
|
+
const r = await ctx.omega.auth.signOut();
|
|
52
52
|
ctx.expect(r.success).toBe(true);
|
|
53
|
-
ctx.expect(ctx.
|
|
53
|
+
ctx.expect(ctx.omega.auth._firebaseAuth.currentUser).toBeNull();
|
|
54
|
+
ctx.expect(ctx.omega.auth.user.authenticated).toBe(false);
|
|
54
55
|
},
|
|
55
56
|
},
|
|
56
57
|
],
|