@omega.js/desktop 0.51.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 +18 -13
- 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 +145 -48
- 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/.github/workflows/build.yml +2 -0
- 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/runner/job-started.js +1 -1
- 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 +612 -5
- 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 +13 -12
- package/dist/vendor/config/load.js +1 -2
- package/dist/vendor/config/platforms.js +1 -1
- package/dist/vendor/config/repo.js +24 -0
- 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/brand-version.js +162 -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/deploy.js +64 -4
- package/dist/vendor/devkit/git-remote.js +78 -1
- package/dist/vendor/devkit/local.js +53 -3
- package/dist/vendor/devkit/lockfile.js +127 -0
- package/dist/vendor/devkit/merge-line-files.js +2 -3
- package/dist/vendor/devkit/pack-local.js +4 -7
- package/dist/vendor/devkit/preludes/origin-heal.js +35 -49
- package/dist/vendor/devkit/target-secrets.js +34 -45
- 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 +39 -28
- 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/releasing.md +4 -2
- package/docs/remote-config.md +9 -9
- package/docs/remote-scripts.md +12 -12
- package/docs/restart-manager.md +8 -8
- package/docs/runner.md +12 -10
- package/docs/sentry.md +4 -4
- package/docs/shared/analytics.md +1 -1
- package/docs/shared/brands.md +1 -1
- package/docs/shared/breaking-changes.md +79 -13
- package/docs/shared/config.md +24 -21
- package/docs/shared/deploys.md +30 -7
- package/docs/shared/local-dev.md +5 -3
- 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/signing.md +1 -1
- 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,89 +1,128 @@
|
|
|
1
|
-
// Build-layer tests for renderer
|
|
1
|
+
// Build-layer tests for the renderer's auth bridge (`_wireAuthBridge`) against
|
|
2
|
+
// main's REAL lib/auth.js handlers.
|
|
2
3
|
//
|
|
3
|
-
// The bridge is pure JS
|
|
4
|
-
//
|
|
5
|
-
// bodies run inside a BrowserWindow with no require).
|
|
4
|
+
// The bridge is pure JS (ipc in, ipc out, no DOM), so it runs in plain Node here on
|
|
5
|
+
// a REAL renderer instance, the @omega.js/client base class included (a renderer-
|
|
6
|
+
// layer suite can't: those bodies run inside a BrowserWindow with no require).
|
|
6
7
|
//
|
|
7
|
-
// What's pinned:
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
8
|
+
// What's pinned:
|
|
9
|
+
// - the sync-request payload carries the signed-in UID, read off the client's
|
|
10
|
+
// Firebase session. A drift here is silent (null → "signed out"), which is
|
|
11
|
+
// exactly how #103 shipped: every renderer boot claimed "signed out" and forced
|
|
12
|
+
// main into a full custom-token round-trip it could have skipped.
|
|
13
|
+
// - every signed-in state pushes `{ uid, document, identity }` to main, and main
|
|
14
|
+
// builds its `auth.user` from that WHOLE document, so its plan reads from it.
|
|
15
|
+
// - the `omega-signin` / `omega-account` click triggers the extension's pages
|
|
16
|
+
// carry route to main's open-flow / open-account channels. Pinned here, not in
|
|
17
|
+
// a renderer-layer page: a real click would open the user's browser.
|
|
18
|
+
// - the client's `omega-signout` trigger routes to main's sign-out channel, and
|
|
19
|
+
// the window signs itself out only on main's broadcast.
|
|
20
|
+
//
|
|
21
|
+
// Two seams, both named: the backend (`omega.request`, whose wakeup would reach the
|
|
22
|
+
// network) and the client's auth state source (`omega.auth.listen`), because a
|
|
23
|
+
// real signed-in renderer needs the auth emulator, which the e2e-desktop lane drives.
|
|
12
24
|
|
|
13
25
|
const path = require('path');
|
|
14
26
|
|
|
27
|
+
const { User } = require('../../../vendor/account/index.js');
|
|
15
28
|
const { WAKEUP_ROUTE } = require('@omega.js/client/modules/request.js');
|
|
16
29
|
const defineCases = require('../../../vendor/devkit/test/define-cases.js');
|
|
17
30
|
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
//
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
async function makeClientAuth(user) {
|
|
25
|
-
const { default: Auth } = await import('@omega.js/client/modules/auth.js');
|
|
26
|
-
return new Auth({
|
|
27
|
-
firebaseAuth: { currentUser: user },
|
|
28
|
-
_resolveFirebaseConfig: () => ({}),
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
+
const ROOT = path.join(__dirname, '..', '..', '..');
|
|
32
|
+
const mainAuth = require(path.join(ROOT, 'lib', 'auth.js'));
|
|
33
|
+
|
|
34
|
+
// A signed-in renderer's account: the stored document with an active paid plan
|
|
35
|
+
const IDENTITY = { uid: 'uid-abc', email: 'a@b.co', displayName: 'Abc', photoURL: 'https://example.com/a.png', emailVerified: true };
|
|
36
|
+
const DOCUMENT = { subscription: { product: { id: 'premium' }, status: 'active' } };
|
|
31
37
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
/**
|
|
39
|
+
* A fresh renderer instance on a recording bridge. `handle(channel, payload)`
|
|
40
|
+
* answers each ipc.invoke. Returns the instance, the recorded invokes and
|
|
41
|
+
* backend requests, the `timeline` of both in the order the bridge produced
|
|
42
|
+
* them (the wakeup ping's whole point is that it is FIRST), and `deliver`, the
|
|
43
|
+
* client's auth listener the bridge registered.
|
|
44
|
+
* @param {{ uid: string }|null} firebaseUser - the client's Firebase session user.
|
|
45
|
+
* @param {Function} handle - the ipc.invoke answerer.
|
|
46
|
+
* @returns {object} the renderer and its recordings.
|
|
47
|
+
*/
|
|
48
|
+
function makeRenderer(firebaseUser, handle) {
|
|
39
49
|
const invokes = [];
|
|
40
50
|
const requests = [];
|
|
41
51
|
const timeline = [];
|
|
52
|
+
const listeners = [];
|
|
42
53
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
54
|
+
const desktop = {
|
|
55
|
+
ipc: {
|
|
56
|
+
on: () => () => {},
|
|
57
|
+
invoke: async (channel, payload) => {
|
|
58
|
+
invokes.push({ channel, payload });
|
|
59
|
+
timeline.push(channel);
|
|
60
|
+
return handle(channel, payload);
|
|
61
|
+
},
|
|
49
62
|
},
|
|
50
63
|
};
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
},
|
|
64
|
+
|
|
65
|
+
const saved = globalThis.window;
|
|
66
|
+
globalThis.window = { desktop };
|
|
67
|
+
let omega;
|
|
68
|
+
try {
|
|
69
|
+
const { Omega } = require(path.join(ROOT, 'renderer.js'));
|
|
70
|
+
omega = new Omega();
|
|
71
|
+
} finally {
|
|
72
|
+
if (saved === undefined) delete globalThis.window;
|
|
73
|
+
else globalThis.window = saved;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// The client's Firebase session, as its `firebaseAuth` getter reads it
|
|
77
|
+
omega._firebaseAuth = { currentUser: firebaseUser };
|
|
78
|
+
omega.request = async (url, options = {}) => {
|
|
79
|
+
requests.push({ url, options });
|
|
80
|
+
timeline.push(options.wakeup ? 'wakeup' : url);
|
|
57
81
|
};
|
|
82
|
+
omega.auth.listen = (callback) => {
|
|
83
|
+
listeners.push(callback);
|
|
84
|
+
return () => {};
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const deliver = (state) => listeners.forEach((callback) => callback(state));
|
|
58
88
|
|
|
59
|
-
return {
|
|
89
|
+
return { omega, invokes, requests, timeline, deliver };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* A click inside an element carrying `className`, handed to the registry's one
|
|
94
|
+
* delegated listener. closest() answers only when the registry's selector names
|
|
95
|
+
* that class, so the class is the registered one.
|
|
96
|
+
* @param {object} omega - the renderer instance.
|
|
97
|
+
* @param {string} className - the trigger class clicked.
|
|
98
|
+
*/
|
|
99
|
+
function clickTrigger(omega, className) {
|
|
100
|
+
omega.triggers._handleClick({
|
|
101
|
+
target: {
|
|
102
|
+
closest: (selector) => (selector.split(',').includes(`.${className}`)
|
|
103
|
+
? { classList: { contains: (name) => name === className } }
|
|
104
|
+
: null),
|
|
105
|
+
},
|
|
106
|
+
preventDefault: () => {},
|
|
107
|
+
stopPropagation: () => {},
|
|
108
|
+
});
|
|
60
109
|
}
|
|
61
110
|
|
|
62
111
|
module.exports = defineCases({
|
|
63
112
|
type: 'suite',
|
|
64
113
|
layer: 'build',
|
|
65
|
-
description: 'renderer auth bridge
|
|
114
|
+
description: 'renderer auth bridge: sync-request context UID + the account push main builds its user from',
|
|
66
115
|
tests: [
|
|
67
|
-
{
|
|
68
|
-
name: 'the client auth handle exposes getUser() (and no user() accessor)',
|
|
69
|
-
run: async (ctx) => {
|
|
70
|
-
const auth = await makeClientAuth({ uid: 'uid-abc', email: 'a@b.co' });
|
|
71
|
-
ctx.expect(typeof auth.getUser).toBe('function');
|
|
72
|
-
ctx.expect(auth.getUser().uid).toBe('uid-abc');
|
|
73
|
-
ctx.expect(auth.user).toBeUndefined();
|
|
74
|
-
},
|
|
75
|
-
},
|
|
76
116
|
{
|
|
77
117
|
// #644: main answers a sync-request that needs a token by POSTing
|
|
78
|
-
// /omega/user/token
|
|
118
|
+
// /omega/user/token, the app's first backend call, on a function that is
|
|
79
119
|
// cold at every launch. The ping goes out before the bridge waits on
|
|
80
120
|
// anything, so the cold start burns down while auth settles.
|
|
81
121
|
name: 'the bridge warms the backend first, then syncs',
|
|
82
122
|
run: async (ctx) => {
|
|
83
|
-
const
|
|
84
|
-
const { manager, requests, timeline } = makeRenderer(auth, () => ({ needsSync: false }));
|
|
123
|
+
const { omega, requests, timeline } = makeRenderer({ uid: 'uid-abc' }, () => ({ needsSync: false }));
|
|
85
124
|
|
|
86
|
-
await
|
|
125
|
+
await omega._wireAuthBridge();
|
|
87
126
|
|
|
88
127
|
ctx.expect(requests.length).toBe(1);
|
|
89
128
|
ctx.expect(requests[0].url).toBe(WAKEUP_ROUTE);
|
|
@@ -95,10 +134,9 @@ module.exports = defineCases({
|
|
|
95
134
|
{
|
|
96
135
|
name: 'sync-request carries the signed-in UID as contextUid',
|
|
97
136
|
run: async (ctx) => {
|
|
98
|
-
const
|
|
99
|
-
const { manager, invokes } = makeRenderer(auth, () => ({ needsSync: false }));
|
|
137
|
+
const { omega, invokes } = makeRenderer({ uid: 'uid-abc' }, () => ({ needsSync: false }));
|
|
100
138
|
|
|
101
|
-
await
|
|
139
|
+
await omega._wireAuthBridge();
|
|
102
140
|
|
|
103
141
|
const sync = invokes.find((i) => i.channel === 'desktop:auth:sync-request');
|
|
104
142
|
ctx.expect(sync).toBeDefined();
|
|
@@ -108,49 +146,144 @@ module.exports = defineCases({
|
|
|
108
146
|
{
|
|
109
147
|
name: 'sync-request carries null when nobody is signed in',
|
|
110
148
|
run: async (ctx) => {
|
|
111
|
-
const
|
|
112
|
-
const { manager, invokes } = makeRenderer(auth, () => ({ needsSync: false }));
|
|
149
|
+
const { omega, invokes } = makeRenderer(null, () => ({ needsSync: false }));
|
|
113
150
|
|
|
114
|
-
await
|
|
151
|
+
await omega._wireAuthBridge();
|
|
115
152
|
|
|
116
153
|
const sync = invokes.find((i) => i.channel === 'desktop:auth:sync-request');
|
|
117
154
|
ctx.expect(sync.payload.contextUid).toBeNull();
|
|
118
155
|
},
|
|
119
156
|
},
|
|
120
157
|
{
|
|
121
|
-
name: 'matching UIDs short-circuit against the real main-side handler
|
|
158
|
+
name: 'matching UIDs short-circuit against the real main-side handler: no token round-trip',
|
|
122
159
|
run: async (ctx) => {
|
|
123
|
-
// Main's side is the REAL
|
|
160
|
+
// Main's side is the REAL lib/auth.js handler with its session stubbed to the
|
|
124
161
|
// same user; the only thing under test is whether the renderer's claim matches.
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
bridge._firebaseAuth = { currentUser: { uid: 'uid-abc' } };
|
|
162
|
+
const origAuth = mainAuth._firebaseAuth;
|
|
163
|
+
mainAuth._firebaseAuth = { currentUser: { uid: 'uid-abc' } };
|
|
128
164
|
|
|
129
165
|
try {
|
|
130
|
-
const auth = await makeClientAuth({ uid: 'uid-abc', email: 'a@b.co' });
|
|
131
|
-
let signIns = 0;
|
|
132
|
-
let signOuts = 0;
|
|
133
|
-
auth.signInWithCustomToken = async () => { signIns++; };
|
|
134
|
-
auth.signOut = async () => { signOuts++; };
|
|
135
|
-
|
|
136
166
|
let result = null;
|
|
137
|
-
const {
|
|
167
|
+
const { omega } = makeRenderer({ uid: 'uid-abc' }, async (channel, payload) => {
|
|
138
168
|
if (channel !== 'desktop:auth:sync-request') return null;
|
|
139
|
-
result = await
|
|
169
|
+
result = await mainAuth._handleSyncRequest(payload.contextUid);
|
|
140
170
|
return result;
|
|
141
171
|
});
|
|
172
|
+
let signIns = 0;
|
|
173
|
+
let signOuts = 0;
|
|
174
|
+
omega.auth.signInWithCustomToken = async () => { signIns++; };
|
|
175
|
+
omega.auth.signOut = async () => { signOuts++; };
|
|
142
176
|
|
|
143
|
-
await
|
|
177
|
+
await omega._wireAuthBridge();
|
|
144
178
|
|
|
145
179
|
ctx.expect(result.needsSync).toBe(false);
|
|
146
180
|
// The handler's catch ALSO returns needsSync:false (with an error field), so a
|
|
147
|
-
// null contextUid falling through to the token fetch would pass the line above
|
|
181
|
+
// null contextUid falling through to the token fetch would pass the line above;
|
|
148
182
|
// the absent error is what proves the uid match short-circuited.
|
|
149
183
|
ctx.expect(result.error).toBeUndefined();
|
|
150
184
|
ctx.expect(signIns).toBe(0);
|
|
151
185
|
ctx.expect(signOuts).toBe(0);
|
|
152
186
|
} finally {
|
|
153
|
-
|
|
187
|
+
mainAuth._firebaseAuth = origAuth;
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
name: 'the signin and account triggers route a click to main\'s open-flow and open-account channels',
|
|
193
|
+
run: async (ctx) => {
|
|
194
|
+
const { omega, invokes } = makeRenderer(null, () => ({ needsSync: false }));
|
|
195
|
+
|
|
196
|
+
await omega._wireAuthBridge();
|
|
197
|
+
|
|
198
|
+
clickTrigger(omega, 'omega-signin');
|
|
199
|
+
clickTrigger(omega, 'omega-account');
|
|
200
|
+
|
|
201
|
+
const opens = invokes.map((i) => i.channel).filter((channel) => channel.startsWith('desktop:auth:open-'));
|
|
202
|
+
ctx.expect(opens).toEqual(['desktop:auth:open-flow', 'desktop:auth:open-account']);
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
// The client registers `omega-signout` (the one registration, at
|
|
207
|
+
// initialize); on desktop it signs MAIN out, and this window's own
|
|
208
|
+
// sign-out is the broadcast listener's, so nothing signs out twice.
|
|
209
|
+
// `confirm` is the one seam: Node has no dialog.
|
|
210
|
+
name: 'the client\'s signout trigger invokes main\'s sign-out channel, and the window does not sign itself out',
|
|
211
|
+
run: async (ctx) => {
|
|
212
|
+
const { omega, invokes } = makeRenderer({ uid: 'uid-abc' }, (channel) => (channel === 'desktop:auth:sign-out' ? { success: true } : { needsSync: false }));
|
|
213
|
+
let localSignOuts = 0;
|
|
214
|
+
const notices = [];
|
|
215
|
+
omega.auth.signOut = async () => { localSignOuts++; };
|
|
216
|
+
omega.utilities.showNotification = (message, type) => notices.push([message, type]);
|
|
217
|
+
|
|
218
|
+
await omega._wireAuthBridge();
|
|
219
|
+
omega.auth.setupEventListeners();
|
|
220
|
+
|
|
221
|
+
globalThis.confirm = () => true;
|
|
222
|
+
try {
|
|
223
|
+
clickTrigger(omega, 'omega-signout');
|
|
224
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
225
|
+
} finally {
|
|
226
|
+
delete globalThis.confirm;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
ctx.expect(invokes.filter((i) => i.channel === 'desktop:auth:sign-out').length).toBe(1);
|
|
230
|
+
ctx.expect(localSignOuts).toBe(0);
|
|
231
|
+
ctx.expect(notices).toEqual([['Successfully signed out.', 'success']]);
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
name: 'a signed-out state pushes nothing',
|
|
236
|
+
run: async (ctx) => {
|
|
237
|
+
const { omega, invokes, deliver } = makeRenderer(null, () => ({ needsSync: false }));
|
|
238
|
+
|
|
239
|
+
await omega._wireAuthBridge();
|
|
240
|
+
deliver({ user: new User(), denied: false });
|
|
241
|
+
await Promise.resolve();
|
|
242
|
+
|
|
243
|
+
ctx.expect(invokes.some((i) => i.channel === 'desktop:auth:account-resolved')).toBe(false);
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
name: 'a signed-in state pushes { uid, document, identity }, and main\'s auth.user is built from it',
|
|
248
|
+
run: async (ctx) => {
|
|
249
|
+
// Main's side is the REAL lib/auth.js intake, on a session holding the same uid
|
|
250
|
+
const saved = { firebaseAuth: mainAuth._firebaseAuth, omega: mainAuth._omega, user: mainAuth.user, state: mainAuth.state };
|
|
251
|
+
const broadcasts = [];
|
|
252
|
+
mainAuth._firebaseAuth = { currentUser: { uid: IDENTITY.uid } };
|
|
253
|
+
mainAuth._omega = { ipc: { broadcast: (channel, payload) => broadcasts.push({ channel, payload }) } };
|
|
254
|
+
mainAuth._land(new User());
|
|
255
|
+
|
|
256
|
+
try {
|
|
257
|
+
let pushed = null;
|
|
258
|
+
const { omega, deliver } = makeRenderer({ uid: IDENTITY.uid }, (channel, payload) => {
|
|
259
|
+
if (channel === 'desktop:auth:sync-request') return { needsSync: false };
|
|
260
|
+
if (channel === 'desktop:auth:account-resolved') {
|
|
261
|
+
pushed = payload;
|
|
262
|
+
return mainAuth._handleAccountResolved(payload);
|
|
263
|
+
}
|
|
264
|
+
return null;
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
await omega._wireAuthBridge();
|
|
268
|
+
ctx.expect(mainAuth.user.authenticated).toBe(false);
|
|
269
|
+
ctx.expect(mainAuth.user.plan).toBe('basic');
|
|
270
|
+
|
|
271
|
+
const rendererUser = new User(DOCUMENT, IDENTITY);
|
|
272
|
+
deliver({ user: rendererUser, denied: false });
|
|
273
|
+
await Promise.resolve();
|
|
274
|
+
|
|
275
|
+
ctx.expect(pushed).toEqual({ uid: IDENTITY.uid, document: rendererUser.toJSON(), identity: IDENTITY });
|
|
276
|
+
ctx.expect(mainAuth.user.uid).toBe(IDENTITY.uid);
|
|
277
|
+
ctx.expect(mainAuth.user.plan).toBe('premium');
|
|
278
|
+
ctx.expect(mainAuth.user.active).toBe(true);
|
|
279
|
+
ctx.expect(mainAuth.user.profile.displayName).toBe('Abc');
|
|
280
|
+
ctx.expect(mainAuth.user.toJSON()).toEqual(rendererUser.toJSON());
|
|
281
|
+
ctx.expect(broadcasts).toEqual([{ channel: 'desktop:auth:plan-changed', payload: { document: rendererUser.toJSON() } }]);
|
|
282
|
+
} finally {
|
|
283
|
+
mainAuth._firebaseAuth = saved.firebaseAuth;
|
|
284
|
+
mainAuth._omega = saved.omega;
|
|
285
|
+
mainAuth.user = saved.user;
|
|
286
|
+
mainAuth.state = saved.state;
|
|
154
287
|
}
|
|
155
288
|
},
|
|
156
289
|
},
|