@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
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
// Main-process tests for lib/auth.js (`omega.auth`): unit-level coverage that doesn't hit Firebase.
|
|
2
|
+
//
|
|
3
|
+
// Real Firebase integration tests live in auth.integration.test.js
|
|
4
|
+
// (gated on extended mode); the sign-in proof itself is #904's, through a
|
|
5
|
+
// persona the backend emulator seeds.
|
|
6
|
+
|
|
7
|
+
const { User } = require('../../../vendor/account/index.js');
|
|
8
|
+
const defineCases = require('../../../vendor/devkit/test/define-cases.js');
|
|
9
|
+
|
|
10
|
+
module.exports = defineCases({
|
|
11
|
+
type: 'suite',
|
|
12
|
+
layer: 'main',
|
|
13
|
+
description: 'auth (main, unit)',
|
|
14
|
+
cleanup: async (ctx) => {
|
|
15
|
+
await ctx.omega.auth._resetForTests();
|
|
16
|
+
},
|
|
17
|
+
tests: [
|
|
18
|
+
{
|
|
19
|
+
name: 'initialize ran during boot',
|
|
20
|
+
run: (ctx) => {
|
|
21
|
+
ctx.expect(ctx.omega.auth._initialized).toBe(true);
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: 'IPC handlers are registered',
|
|
26
|
+
run: (ctx) => {
|
|
27
|
+
ctx.expect(ctx.omega.ipc.hasHandler('desktop:auth:sync-request')).toBe(true);
|
|
28
|
+
ctx.expect(ctx.omega.ipc.hasHandler('desktop:auth:sign-out')).toBe(true);
|
|
29
|
+
ctx.expect(ctx.omega.ipc.hasHandler('desktop:auth:get-user')).toBe(true);
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
// The public surface is exactly the account, its listener, and the three
|
|
34
|
+
// session calls; the snapshot/plan/roles getters and onAuthChange retired
|
|
35
|
+
// into `user` and `listen`.
|
|
36
|
+
name: 'the public surface: user, listen, signOut, getIdToken, handleToken',
|
|
37
|
+
run: (ctx) => {
|
|
38
|
+
const auth = ctx.omega.auth;
|
|
39
|
+
for (const name of ['listen', 'signOut', 'getIdToken', 'handleToken']) {
|
|
40
|
+
ctx.expect(typeof auth[name]).toBe('function');
|
|
41
|
+
}
|
|
42
|
+
for (const name of ['getCurrentUser', 'getResolvedPlan', 'getResolvedRoles', 'onAuthChange', 'handleAuthToken']) {
|
|
43
|
+
ctx.expect(auth[name]).toBeUndefined();
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: 'user is a signed-out User when nothing is signed in',
|
|
49
|
+
run: (ctx) => {
|
|
50
|
+
// The harness boots without auth; either firebase isn't loaded (no cloud.config
|
|
51
|
+
// in default config) or it is and there's no user. Either way, no renderer has
|
|
52
|
+
// pushed an account, so `user` is the signed-out User.
|
|
53
|
+
const user = ctx.omega.auth.user;
|
|
54
|
+
ctx.expect(user).toBeInstanceOf(User);
|
|
55
|
+
ctx.expect(user.authenticated).toBe(false);
|
|
56
|
+
ctx.expect(user.uid).toBeNull();
|
|
57
|
+
ctx.expect(user.plan).toBe('basic');
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: 'getIdToken returns null when nothing is signed in',
|
|
62
|
+
run: async (ctx) => {
|
|
63
|
+
// Same no-auth harness as the user case above: signed-in token
|
|
64
|
+
// round-trips are the integration suite's domain.
|
|
65
|
+
ctx.expect(await ctx.omega.auth.getIdToken()).toBeNull();
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: 'handleToken returns no-op result when firebase not loaded',
|
|
70
|
+
run: async (ctx) => {
|
|
71
|
+
// Default config has empty cloud.config → firebase fails to init → _firebaseAuth=null.
|
|
72
|
+
if (ctx.omega.auth._firebaseAuth) {
|
|
73
|
+
ctx.skip('firebase did load (cloud.config was set) — covered by integration tests');
|
|
74
|
+
}
|
|
75
|
+
const r = await ctx.omega.auth.handleToken('whatever');
|
|
76
|
+
ctx.expect(r.success).toBe(false);
|
|
77
|
+
ctx.expect(r.reason).toBe('firebase-not-loaded');
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: 'handleToken with empty token returns no-token failure',
|
|
82
|
+
run: async (ctx) => {
|
|
83
|
+
// Stub _firebaseAuth so we hit the "no token" branch instead of "firebase-not-loaded."
|
|
84
|
+
const origAuth = ctx.omega.auth._firebaseAuth;
|
|
85
|
+
ctx.omega.auth._firebaseAuth = { currentUser: null }; // truthy so we pass the firebase check
|
|
86
|
+
try {
|
|
87
|
+
const r = await ctx.omega.auth.handleToken('');
|
|
88
|
+
ctx.expect(r.success).toBe(false);
|
|
89
|
+
ctx.expect(r.reason).toBe('no-token');
|
|
90
|
+
} finally {
|
|
91
|
+
ctx.omega.auth._firebaseAuth = origAuth;
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
name: 'sync-request: same UID → no sync needed',
|
|
97
|
+
run: async (ctx) => {
|
|
98
|
+
// Stub the auth so we control bgUid.
|
|
99
|
+
const origAuth = ctx.omega.auth._firebaseAuth;
|
|
100
|
+
ctx.omega.auth._firebaseAuth = { currentUser: { uid: 'abc' } };
|
|
101
|
+
try {
|
|
102
|
+
const result = await ctx.omega.ipc.invoke('desktop:auth:sync-request', { contextUid: 'abc' });
|
|
103
|
+
ctx.expect(result.needsSync).toBe(false);
|
|
104
|
+
} finally {
|
|
105
|
+
ctx.omega.auth._firebaseAuth = origAuth;
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
name: 'sync-request: main signed out, renderer signed in → tells renderer to sign out',
|
|
111
|
+
run: async (ctx) => {
|
|
112
|
+
const origAuth = ctx.omega.auth._firebaseAuth;
|
|
113
|
+
ctx.omega.auth._firebaseAuth = { currentUser: null };
|
|
114
|
+
try {
|
|
115
|
+
const result = await ctx.omega.ipc.invoke('desktop:auth:sync-request', { contextUid: 'someone' });
|
|
116
|
+
ctx.expect(result.needsSync).toBe(true);
|
|
117
|
+
ctx.expect(result.signOut).toBe(true);
|
|
118
|
+
} finally {
|
|
119
|
+
ctx.omega.auth._firebaseAuth = origAuth;
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
name: 'sync-request: firebase not loaded → no sync',
|
|
125
|
+
run: async (ctx) => {
|
|
126
|
+
const origAuth = ctx.omega.auth._firebaseAuth;
|
|
127
|
+
ctx.omega.auth._firebaseAuth = null;
|
|
128
|
+
try {
|
|
129
|
+
const result = await ctx.omega.ipc.invoke('desktop:auth:sync-request', { contextUid: null });
|
|
130
|
+
ctx.expect(result.needsSync).toBe(false);
|
|
131
|
+
ctx.expect(result.reason).toBe('firebase-not-loaded');
|
|
132
|
+
} finally {
|
|
133
|
+
ctx.omega.auth._firebaseAuth = origAuth;
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
name: 'sign-out IPC succeeds when nothing is signed in',
|
|
139
|
+
run: async (ctx) => {
|
|
140
|
+
const result = await ctx.omega.ipc.invoke('desktop:auth:sign-out');
|
|
141
|
+
ctx.expect(result.success).toBe(true);
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
name: 'get-user IPC answers the signed-out account and no identity when no current user',
|
|
146
|
+
run: async (ctx) => {
|
|
147
|
+
const result = await ctx.omega.ipc.invoke('desktop:auth:get-user');
|
|
148
|
+
ctx.expect(result.uid).toBeNull();
|
|
149
|
+
ctx.expect(result.identity).toBeNull();
|
|
150
|
+
ctx.expect(result.document).toEqual(ctx.omega.auth.user.toJSON());
|
|
151
|
+
ctx.expect(new User(result.document).authenticated).toBe(false);
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
// A renderer's `omega-signin` trigger lands here: main's own sign-in flow.
|
|
156
|
+
// openAuthFlow is stubbed because the real one opens the user's browser.
|
|
157
|
+
name: 'open-flow IPC runs omega.openAuthFlow()',
|
|
158
|
+
run: async (ctx) => {
|
|
159
|
+
let flows = 0;
|
|
160
|
+
ctx.omega.openAuthFlow = async () => { flows++; return { url: 'https://localhost:4000/signin' }; };
|
|
161
|
+
try {
|
|
162
|
+
const result = await ctx.omega.ipc.invoke('desktop:auth:open-flow');
|
|
163
|
+
ctx.expect(flows).toBe(1);
|
|
164
|
+
ctx.expect(result).toEqual({ url: 'https://localhost:4000/signin' });
|
|
165
|
+
} finally {
|
|
166
|
+
delete ctx.omega.openAuthFlow;
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
// A renderer's `omega-account` trigger: the website's /account page, on the
|
|
172
|
+
// host getWebsiteUrl() answers (the staged dev origin in this testing run)
|
|
173
|
+
name: 'open-account IPC opens <website>/account in the user\'s browser',
|
|
174
|
+
run: async (ctx) => {
|
|
175
|
+
const electron = require('electron');
|
|
176
|
+
const opened = [];
|
|
177
|
+
const origOpen = electron.shell.openExternal;
|
|
178
|
+
const origDev = ctx.omega.config.dev;
|
|
179
|
+
electron.shell.openExternal = async (url) => { opened.push(url); };
|
|
180
|
+
ctx.omega.config.dev = { origin: 'https://localhost:4000' };
|
|
181
|
+
try {
|
|
182
|
+
await ctx.omega.ipc.invoke('desktop:auth:open-account');
|
|
183
|
+
ctx.expect(opened).toEqual(['https://localhost:4000/account']);
|
|
184
|
+
} finally {
|
|
185
|
+
electron.shell.openExternal = origOpen;
|
|
186
|
+
if (origDev !== undefined) ctx.omega.config.dev = origDev; else delete ctx.omega.config.dev;
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
name: 'listen: a catch-up with the current state after it returns, then every landing, until unsubscribed',
|
|
192
|
+
run: async (ctx) => {
|
|
193
|
+
const auth = ctx.omega.auth;
|
|
194
|
+
const heard = [];
|
|
195
|
+
const off = auth.listen((state) => heard.push(state.user));
|
|
196
|
+
|
|
197
|
+
// The catch-up is async: nothing is heard before listen() returns
|
|
198
|
+
ctx.expect(heard.length).toBe(0);
|
|
199
|
+
await Promise.resolve();
|
|
200
|
+
ctx.expect(heard.length).toBe(1);
|
|
201
|
+
ctx.expect(heard[0]).toBe(auth.user);
|
|
202
|
+
|
|
203
|
+
const landed = new User({}, { uid: 'u-listen', email: 'l@x.y' });
|
|
204
|
+
auth._land(landed);
|
|
205
|
+
ctx.expect(heard.length).toBe(2);
|
|
206
|
+
ctx.expect(heard[1]).toBe(landed);
|
|
207
|
+
|
|
208
|
+
off();
|
|
209
|
+
auth._land(new User());
|
|
210
|
+
ctx.expect(heard.length).toBe(2);
|
|
211
|
+
ctx.expect(auth.user.authenticated).toBe(false);
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
name: '_identity returns the sign-in identity shape (no token)',
|
|
216
|
+
run: (ctx) => {
|
|
217
|
+
const snap = ctx.omega.auth._identity({
|
|
218
|
+
uid: 'u1',
|
|
219
|
+
email: 'a@b.com',
|
|
220
|
+
displayName: 'Bob',
|
|
221
|
+
photoURL: 'http://x/p.png',
|
|
222
|
+
emailVerified: true,
|
|
223
|
+
// sensitive stuff that should NOT be exposed
|
|
224
|
+
stsTokenManager: { accessToken: 'SECRET' },
|
|
225
|
+
providerData: ['xxx'],
|
|
226
|
+
});
|
|
227
|
+
ctx.expect(snap).toEqual({
|
|
228
|
+
uid: 'u1',
|
|
229
|
+
email: 'a@b.com',
|
|
230
|
+
displayName: 'Bob',
|
|
231
|
+
photoURL: 'http://x/p.png',
|
|
232
|
+
emailVerified: true,
|
|
233
|
+
});
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
// The emulator gate (#46). _getFirebaseAuth resolves firebase through the
|
|
238
|
+
// auth's OWN seams (_firebase / _firebaseModule, filled by
|
|
239
|
+
// _tryLoadFirebase) — swapping those recording namespaces in drives the real
|
|
240
|
+
// method, no stubbing of the module under test. The omega instance is an input too:
|
|
241
|
+
// isTesting() is the whole gate.
|
|
242
|
+
name: 'auth emulator: a testing run connects, dev/production never do',
|
|
243
|
+
run: (ctx) => {
|
|
244
|
+
const auth = ctx.omega.auth;
|
|
245
|
+
const saved = {
|
|
246
|
+
firebase: auth._firebase,
|
|
247
|
+
module: auth._firebaseModule,
|
|
248
|
+
auth: auth._firebaseAuth,
|
|
249
|
+
omega: auth._omega,
|
|
250
|
+
port: process.env.OMEGA_AUTH_PORT,
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
// One recording firebase namespace pair, reused per run
|
|
254
|
+
const connects = [];
|
|
255
|
+
const authInstance = { __auth: true };
|
|
256
|
+
auth._firebase = {
|
|
257
|
+
getApp: () => { throw new Error('no app'); },
|
|
258
|
+
initializeApp: () => ({ __app: true }),
|
|
259
|
+
};
|
|
260
|
+
auth._firebaseModule = {
|
|
261
|
+
getAuth: () => authInstance,
|
|
262
|
+
connectAuthEmulator: (auth, url, opts) => connects.push({ auth, url, opts }),
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
const run = (isTesting, dev) => {
|
|
266
|
+
auth._firebaseAuth = null;
|
|
267
|
+
auth._omega = {
|
|
268
|
+
config: { cloud: { config: { apiKey: 'AIza-test', projectId: 'demo-desktop' } }, ...(dev ? { dev } : {}) },
|
|
269
|
+
isTesting: () => isTesting,
|
|
270
|
+
};
|
|
271
|
+
return auth._getFirebaseAuth(null);
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
try {
|
|
275
|
+
delete process.env.OMEGA_AUTH_PORT;
|
|
276
|
+
|
|
277
|
+
// production / dev shape — no emulator, ever
|
|
278
|
+
ctx.expect(run(false)).toBe(authInstance);
|
|
279
|
+
ctx.expect(connects.length).toBe(0);
|
|
280
|
+
|
|
281
|
+
// testing shape: the port comes from the map the bundle baked, which
|
|
282
|
+
// carries @omega.js/config's classic 9099 as its floor
|
|
283
|
+
// ([#834](https://github.com/Omega-JS-Stack/omega/issues/834)).
|
|
284
|
+
ctx.expect(run(true, { ports: { auth: 9099 } })).toBe(authInstance);
|
|
285
|
+
ctx.expect(connects.length).toBe(1);
|
|
286
|
+
ctx.expect(connects[0].auth).toBe(authInstance);
|
|
287
|
+
ctx.expect(connects[0].url).toBe('http://localhost:9099');
|
|
288
|
+
|
|
289
|
+
// a bumped port arrives on OMEGA_AUTH_PORT (N7)
|
|
290
|
+
process.env.OMEGA_AUTH_PORT = '9199';
|
|
291
|
+
run(true, { ports: { auth: 9099 } });
|
|
292
|
+
ctx.expect(connects.length).toBe(2);
|
|
293
|
+
ctx.expect(connects[1].url).toBe('http://localhost:9199');
|
|
294
|
+
|
|
295
|
+
// Neither channel is a broken artifact, and it says so by name
|
|
296
|
+
// rather than dialling a port nothing identity-checks (#834).
|
|
297
|
+
delete process.env.OMEGA_AUTH_PORT;
|
|
298
|
+
let threw;
|
|
299
|
+
try { run(true); } catch (e) { threw = e; }
|
|
300
|
+
ctx.expect(threw).toBeDefined();
|
|
301
|
+
ctx.expect(threw.message).toMatch(/dev port for `auth`/);
|
|
302
|
+
ctx.expect(threw.message).toMatch(/bundle task/);
|
|
303
|
+
ctx.expect(connects.length).toBe(2);
|
|
304
|
+
} finally {
|
|
305
|
+
auth._firebase = saved.firebase;
|
|
306
|
+
auth._firebaseModule = saved.module;
|
|
307
|
+
auth._firebaseAuth = saved.auth;
|
|
308
|
+
auth._omega = saved.omega;
|
|
309
|
+
if (saved.port === undefined) delete process.env.OMEGA_AUTH_PORT;
|
|
310
|
+
else process.env.OMEGA_AUTH_PORT = saved.port;
|
|
311
|
+
}
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
name: 'deep-link auth/token route is wired to handleToken',
|
|
316
|
+
run: async (ctx) => {
|
|
317
|
+
// We've already tested the deep-link side in deep-link.test.js. Here we verify
|
|
318
|
+
// the integration is actually live: dispatching the route triggers our spy.
|
|
319
|
+
let received = null;
|
|
320
|
+
const orig = ctx.omega.auth.handleToken;
|
|
321
|
+
ctx.omega.auth.handleToken = async (token) => {
|
|
322
|
+
received = token;
|
|
323
|
+
return { success: true };
|
|
324
|
+
};
|
|
325
|
+
try {
|
|
326
|
+
ctx.omega.deepLink.dispatch('myapp://auth/token?authToken=BRIDGE-TEST-TOKEN');
|
|
327
|
+
// Built-in handler is sync up to the await — give it a tick.
|
|
328
|
+
await new Promise((r) => setImmediate(r));
|
|
329
|
+
ctx.expect(received).toBe('BRIDGE-TEST-TOKEN');
|
|
330
|
+
} finally {
|
|
331
|
+
ctx.omega.auth.handleToken = orig;
|
|
332
|
+
}
|
|
333
|
+
},
|
|
334
|
+
},
|
|
335
|
+
],
|
|
336
|
+
});
|