@peers-app/peers-ui 0.27.2 → 0.27.4
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/dist/screens/network-viewer/network-viewer-ipc.d.ts +3 -1
- package/dist/screens/network-viewer/network-viewer-ipc.js +6 -0
- package/dist/screens/network-viewer/sync-recovery.js +103 -1
- package/dist/screens/variables/variable-details.js +2 -1
- package/dist/tabs-layout/network-status-indicator.js +26 -12
- package/dist/tabs-layout/use-network-status.d.ts +6 -1
- package/dist/tabs-layout/use-network-status.js +27 -4
- package/package.json +9 -3
- package/.claude/settings.local.json +0 -34
- package/.github/README.md +0 -52
- package/.github/workflows/delete-all-artifacts.yml +0 -49
- package/.github/workflows/publish.yml +0 -51
- package/babel.config.js +0 -7
- package/biome.json +0 -198
- package/dist/app-updates/app-updates-consumer.test.d.ts +0 -1
- package/dist/app-updates/app-updates-consumer.test.js +0 -56
- package/dist/app-updates/app-updates-settings.test.d.ts +0 -1
- package/dist/app-updates/app-updates-settings.test.js +0 -93
- package/dist/app-updates/remote-app-update-panel.test.d.ts +0 -1
- package/dist/app-updates/remote-app-update-panel.test.js +0 -165
- package/dist/components/access-level-field.test.d.ts +0 -1
- package/dist/components/access-level-field.test.js +0 -28
- package/dist/components/message-logs/tool-access-approval-card.test.d.ts +0 -1
- package/dist/components/message-logs/tool-access-approval-card.test.js +0 -102
- package/dist/components/responsive-section-nav.test.d.ts +0 -1
- package/dist/components/responsive-section-nav.test.js +0 -45
- package/dist/globals-hash.test.d.ts +0 -1
- package/dist/globals-hash.test.js +0 -16
- package/dist/hooks/use-observable-state.test.d.ts +0 -1
- package/dist/hooks/use-observable-state.test.js +0 -64
- package/dist/hooks/use-observable.test.d.ts +0 -1
- package/dist/hooks/use-observable.test.js +0 -191
- package/dist/hooks/use-rows.test.d.ts +0 -1
- package/dist/hooks/use-rows.test.js +0 -175
- package/dist/hooks/use-tool.test.d.ts +0 -1
- package/dist/hooks/use-tool.test.js +0 -190
- package/dist/host-shell/host-shell-consumer.test.d.ts +0 -1
- package/dist/host-shell/host-shell-consumer.test.js +0 -28
- package/dist/root-layout/root-layout-host.test.d.ts +0 -1
- package/dist/root-layout/root-layout-host.test.js +0 -86
- package/dist/screens/account/account-screen.test.d.ts +0 -1
- package/dist/screens/account/account-screen.test.js +0 -51
- package/dist/screens/assistants/assistant-config.test.d.ts +0 -1
- package/dist/screens/assistants/assistant-config.test.js +0 -57
- package/dist/screens/contacts/contact-list.test.d.ts +0 -1
- package/dist/screens/contacts/contact-list.test.js +0 -48
- package/dist/screens/device-pairing/device-pairing.test.d.ts +0 -1
- package/dist/screens/device-pairing/device-pairing.test.js +0 -119
- package/dist/screens/devices/devices-list.test.d.ts +0 -1
- package/dist/screens/devices/devices-list.test.js +0 -53
- package/dist/screens/groups/group-list.test.d.ts +0 -1
- package/dist/screens/groups/group-list.test.js +0 -38
- package/dist/screens/identity/identity-routes.test.d.ts +0 -1
- package/dist/screens/identity/identity-routes.test.js +0 -51
- package/dist/screens/identity/identity-screen.test.d.ts +0 -1
- package/dist/screens/identity/identity-screen.test.js +0 -103
- package/dist/screens/invites/accept-invite.test.d.ts +0 -1
- package/dist/screens/invites/accept-invite.test.js +0 -103
- package/dist/screens/invites/activity-view.test.d.ts +0 -1
- package/dist/screens/invites/activity-view.test.js +0 -108
- package/dist/screens/invites/invite-classify.test.d.ts +0 -1
- package/dist/screens/invites/invite-classify.test.js +0 -115
- package/dist/screens/network-viewer/network-viewer-ipc.test.d.ts +0 -1
- package/dist/screens/network-viewer/network-viewer-ipc.test.js +0 -61
- package/dist/screens/network-viewer/network-viewer.section.test.d.ts +0 -1
- package/dist/screens/network-viewer/network-viewer.section.test.js +0 -63
- package/dist/screens/network-viewer/sync-recovery.test.d.ts +0 -1
- package/dist/screens/network-viewer/sync-recovery.test.js +0 -104
- package/dist/screens/packages/package-helpers.test.d.ts +0 -1
- package/dist/screens/packages/package-helpers.test.js +0 -53
- package/dist/screens/packages/package-runtime-status.test.d.ts +0 -1
- package/dist/screens/packages/package-runtime-status.test.js +0 -50
- package/dist/screens/packages/packages-ipc.test.d.ts +0 -1
- package/dist/screens/packages/packages-ipc.test.js +0 -43
- package/dist/screens/settings/settings-page.test.d.ts +0 -1
- package/dist/screens/settings/settings-page.test.js +0 -19
- package/dist/screens/tools/tool-access-ipc.test.d.ts +0 -1
- package/dist/screens/tools/tool-access-ipc.test.js +0 -40
- package/dist/screens/tools/tool-catalog-ipc.test.d.ts +0 -1
- package/dist/screens/tools/tool-catalog-ipc.test.js +0 -52
- package/dist/tabs-layout/network-status-indicator.test.d.ts +0 -1
- package/dist/tabs-layout/network-status-indicator.test.js +0 -665
- package/dist/tabs-layout/tabs-state.test.d.ts +0 -1
- package/dist/tabs-layout/tabs-state.test.js +0 -110
- package/dist/tabs-layout/use-network-status.test.d.ts +0 -1
- package/dist/tabs-layout/use-network-status.test.js +0 -45
- package/dist/ui-router/ui-loader.test.d.ts +0 -1
- package/dist/ui-router/ui-loader.test.js +0 -91
- package/jest.config.js +0 -25
- package/release-guard.js +0 -10
- package/src/app-updates/app-update-controls.tsx +0 -73
- package/src/app-updates/app-updates-consumer.test.ts +0 -83
- package/src/app-updates/app-updates-consumer.ts +0 -121
- package/src/app-updates/app-updates-settings.test.tsx +0 -109
- package/src/app-updates/app-updates-settings.tsx +0 -136
- package/src/app-updates/remote-app-update-panel.test.tsx +0 -205
- package/src/app-updates/remote-app-update-panel.tsx +0 -210
- package/src/app-updates/use-app-update-status.ts +0 -16
- package/src/command-palette/command-palette-ui.tsx +0 -564
- package/src/command-palette/command-palette.ts +0 -242
- package/src/components/access-level-field.test.tsx +0 -32
- package/src/components/access-level-field.tsx +0 -68
- package/src/components/checkbox.tsx +0 -25
- package/src/components/group-switcher.tsx +0 -526
- package/src/components/input-date.tsx +0 -29
- package/src/components/input-number.tsx +0 -83
- package/src/components/input.tsx +0 -25
- package/src/components/inverse-lazy-list.tsx +0 -107
- package/src/components/io-schema-values.tsx +0 -103
- package/src/components/io-schema.tsx +0 -259
- package/src/components/lazy-list.tsx +0 -115
- package/src/components/list-screen.tsx +0 -126
- package/src/components/loading-indicator.tsx +0 -7
- package/src/components/markdown-editor/autolink-plugin.tsx +0 -29
- package/src/components/markdown-editor/editor-inline.tsx +0 -9
- package/src/components/markdown-editor/editor.tsx +0 -158
- package/src/components/markdown-editor/markdown-plugin.tsx +0 -202
- package/src/components/markdown-editor/mention-node.ts +0 -204
- package/src/components/markdown-editor/mentions-plugin.tsx +0 -354
- package/src/components/markdown-editor/move-line-plugin.tsx +0 -186
- package/src/components/markdown-editor/select-line-boundary-plugin.tsx +0 -95
- package/src/components/markdown-editor/theme.ts +0 -46
- package/src/components/markdown-editor/toolbar.tsx +0 -269
- package/src/components/markdown-with-mentions.tsx +0 -198
- package/src/components/message-logs/message-logs.tsx +0 -523
- package/src/components/message-logs/tool-access-approval-card.test.tsx +0 -127
- package/src/components/message-logs/tool-access-approval-card.tsx +0 -178
- package/src/components/messages/avatar.tsx +0 -171
- package/src/components/messages/channel-message-list.tsx +0 -189
- package/src/components/messages/channel-view.tsx +0 -92
- package/src/components/messages/message-compose.tsx +0 -192
- package/src/components/messages/message-display.tsx +0 -231
- package/src/components/messages/thread-message-list.tsx +0 -135
- package/src/components/qr-scanner.tsx +0 -180
- package/src/components/responsive-section-nav.test.tsx +0 -88
- package/src/components/responsive-section-nav.tsx +0 -92
- package/src/components/router.tsx +0 -175
- package/src/components/save-button.tsx +0 -134
- package/src/components/sortable-list.tsx +0 -130
- package/src/components/tabs.tsx +0 -76
- package/src/components/tooltip.tsx +0 -43
- package/src/components/trust-level-badge.tsx +0 -44
- package/src/components/trust-level-dropdown.tsx +0 -136
- package/src/components/typeahead.tsx +0 -357
- package/src/globals-hash.test.ts +0 -19
- package/src/globals.tsx +0 -226
- package/src/hooks/index.ts +0 -8
- package/src/hooks/use-host-contract.ts +0 -75
- package/src/hooks/use-observable-state.test.tsx +0 -101
- package/src/hooks/use-observable-state.ts +0 -29
- package/src/hooks/use-observable.test.tsx +0 -258
- package/src/hooks/use-observable.ts +0 -67
- package/src/hooks/use-on-screen.ts +0 -24
- package/src/hooks/use-promise.ts +0 -34
- package/src/hooks/use-rows.test.tsx +0 -196
- package/src/hooks/use-rows.ts +0 -120
- package/src/hooks/use-subscription.ts +0 -24
- package/src/hooks/use-tool.test.tsx +0 -225
- package/src/hooks/use-tool.ts +0 -116
- package/src/host-shell/host-shell-consumer.test.ts +0 -32
- package/src/host-shell/host-shell-consumer.ts +0 -53
- package/src/index.tsx +0 -42
- package/src/mention-configs.ts +0 -185
- package/src/operator-console/operator-console-state.ts +0 -119
- package/src/operator-console/operator-console.tsx +0 -233
- package/src/peers-services-registration.ts +0 -6
- package/src/root-layout/global-overlays.ts +0 -50
- package/src/root-layout/layout-picker.tsx +0 -47
- package/src/root-layout/layouts/full-screen-layout.tsx +0 -144
- package/src/root-layout/layouts/tabs-with-console-layout.tsx +0 -260
- package/src/root-layout/root-layout-host.test.tsx +0 -108
- package/src/root-layout/root-layout-host.tsx +0 -147
- package/src/root-layout/root-layout-registry.ts +0 -51
- package/src/root-layout/root-layout-state.ts +0 -55
- package/src/root-layout/root-layout.ts +0 -32
- package/src/screens/account/account-screen.test.tsx +0 -65
- package/src/screens/account/account-screen.tsx +0 -942
- package/src/screens/assistants/assistant-config.test.tsx +0 -54
- package/src/screens/assistants/assistant-config.tsx +0 -121
- package/src/screens/assistants/assistant-details.tsx +0 -89
- package/src/screens/assistants/assistant-info.tsx +0 -66
- package/src/screens/assistants/assistant-list.tsx +0 -145
- package/src/screens/assistants/assistant-tools.tsx +0 -82
- package/src/screens/console-logs/console-logs-list.tsx +0 -374
- package/src/screens/console-logs/log-display.tsx +0 -137
- package/src/screens/console-logs/log-filters.tsx +0 -64
- package/src/screens/console-logs/mobile-log-card.tsx +0 -161
- package/src/screens/console-logs/resizable-table-header.tsx +0 -110
- package/src/screens/contacts/contact-details.tsx +0 -123
- package/src/screens/contacts/contact-list.test.tsx +0 -59
- package/src/screens/contacts/contact-list.tsx +0 -286
- package/src/screens/contacts/index.ts +0 -2
- package/src/screens/data-explorer/data-explorer.tsx +0 -633
- package/src/screens/data-explorer/index.ts +0 -6
- package/src/screens/data-explorer/query-executor.tsx +0 -520
- package/src/screens/device-pairing/device-pairing.test.tsx +0 -143
- package/src/screens/device-pairing/device-pairing.tsx +0 -461
- package/src/screens/device-pairing/identity-ipc.ts +0 -25
- package/src/screens/device-pairing/index.ts +0 -2
- package/src/screens/device-pairing/use-device-pairing-state.ts +0 -15
- package/src/screens/devices/devices-list.test.tsx +0 -68
- package/src/screens/devices/devices-list.tsx +0 -365
- package/src/screens/devices/index.ts +0 -1
- package/src/screens/groups/group-details.tsx +0 -160
- package/src/screens/groups/group-invite-panel.tsx +0 -311
- package/src/screens/groups/group-list.test.tsx +0 -44
- package/src/screens/groups/group-list.tsx +0 -317
- package/src/screens/groups/group-members.tsx +0 -343
- package/src/screens/groups/index.ts +0 -3
- package/src/screens/identity/identity-routes.test.ts +0 -70
- package/src/screens/identity/identity-routes.ts +0 -301
- package/src/screens/identity/identity-screen.test.tsx +0 -138
- package/src/screens/identity/identity-screen.tsx +0 -282
- package/src/screens/identity/index.ts +0 -2
- package/src/screens/identity/invite-contact-panel.tsx +0 -45
- package/src/screens/identity/profile-invite.tsx +0 -93
- package/src/screens/invites/accept-invite.test.tsx +0 -115
- package/src/screens/invites/accept-invite.tsx +0 -318
- package/src/screens/invites/activity-view.test.tsx +0 -127
- package/src/screens/invites/activity-view.tsx +0 -162
- package/src/screens/invites/index.ts +0 -6
- package/src/screens/invites/invite-capture.ts +0 -104
- package/src/screens/invites/invite-classify.test.ts +0 -129
- package/src/screens/invites/invite-share.tsx +0 -104
- package/src/screens/invites/invites-ipc.ts +0 -25
- package/src/screens/invites/pending-invites-list.tsx +0 -256
- package/src/screens/network-viewer/connection-troubleshooter.tsx +0 -395
- package/src/screens/network-viewer/cpu-usage-graph.tsx +0 -294
- package/src/screens/network-viewer/device-details-modal.tsx +0 -339
- package/src/screens/network-viewer/group-details-modal.tsx +0 -421
- package/src/screens/network-viewer/index.ts +0 -8
- package/src/screens/network-viewer/network-viewer-ipc.test.ts +0 -72
- package/src/screens/network-viewer/network-viewer-ipc.ts +0 -39
- package/src/screens/network-viewer/network-viewer-section.ts +0 -12
- package/src/screens/network-viewer/network-viewer.section.test.tsx +0 -68
- package/src/screens/network-viewer/network-viewer.tsx +0 -708
- package/src/screens/network-viewer/remote-logs-panel.tsx +0 -190
- package/src/screens/network-viewer/sync-recovery.test.tsx +0 -114
- package/src/screens/network-viewer/sync-recovery.tsx +0 -461
- package/src/screens/network-viewer/usage-graph.tsx +0 -455
- package/src/screens/packages/local-folder-grants-panel.tsx +0 -290
- package/src/screens/packages/local-folders-ipc.ts +0 -28
- package/src/screens/packages/package-details.tsx +0 -166
- package/src/screens/packages/package-helpers.test.ts +0 -57
- package/src/screens/packages/package-helpers.ts +0 -137
- package/src/screens/packages/package-info.tsx +0 -354
- package/src/screens/packages/package-list.tsx +0 -519
- package/src/screens/packages/package-network-panel.tsx +0 -82
- package/src/screens/packages/package-new-local.tsx +0 -100
- package/src/screens/packages/package-runtime-status.test.tsx +0 -58
- package/src/screens/packages/package-runtime-status.tsx +0 -68
- package/src/screens/packages/package-versions.tsx +0 -298
- package/src/screens/packages/packages-ipc.test.ts +0 -47
- package/src/screens/packages/packages-ipc.ts +0 -125
- package/src/screens/peer-types/peer-type-details.tsx +0 -172
- package/src/screens/peer-types/peer-type-list.tsx +0 -64
- package/src/screens/search/global-search.tsx +0 -406
- package/src/screens/settings/color-mode-dropdown.tsx +0 -82
- package/src/screens/settings/settings-page.test.tsx +0 -24
- package/src/screens/settings/settings-page.tsx +0 -426
- package/src/screens/setup-user.tsx +0 -355
- package/src/screens/tools/tool-access-ipc.test.ts +0 -55
- package/src/screens/tools/tool-access-ipc.ts +0 -27
- package/src/screens/tools/tool-catalog-ipc.test.ts +0 -52
- package/src/screens/tools/tool-catalog-ipc.ts +0 -51
- package/src/screens/tools/tool-details.tsx +0 -52
- package/src/screens/tools/tool-info.tsx +0 -45
- package/src/screens/tools/tool-list.tsx +0 -106
- package/src/screens/tools/tool-schema.tsx +0 -44
- package/src/screens/tools/tool-test-details.tsx +0 -89
- package/src/screens/tools/tool-test-list.tsx +0 -73
- package/src/screens/variables/variable-details.tsx +0 -289
- package/src/screens/variables/variable-list.tsx +0 -110
- package/src/screens/welcome-modal.tsx +0 -294
- package/src/screens/workflows/workflow-details.tsx +0 -115
- package/src/screens/workflows/workflow-info.tsx +0 -22
- package/src/screens/workflows/workflow-instructions.tsx +0 -134
- package/src/screens/workflows/workflow-list.tsx +0 -117
- package/src/setupTests.ts +0 -38
- package/src/system-apps/assistants.app.ts +0 -7
- package/src/system-apps/console-logs.app.ts +0 -7
- package/src/system-apps/data-explorer.app.ts +0 -8
- package/src/system-apps/identity.app.ts +0 -9
- package/src/system-apps/index.ts +0 -77
- package/src/system-apps/mobile-settings.app.ts +0 -7
- package/src/system-apps/network-viewer.app.ts +0 -8
- package/src/system-apps/packages.app.ts +0 -7
- package/src/system-apps/search.app.ts +0 -8
- package/src/system-apps/settings.app.ts +0 -7
- package/src/system-apps/threads.app.ts +0 -7
- package/src/system-apps/tools.app.ts +0 -7
- package/src/system-apps/types.app.ts +0 -7
- package/src/system-apps/variables.app.ts +0 -7
- package/src/system-apps/workflows.app.ts +0 -7
- package/src/tabs-layout/network-status-indicator.test.tsx +0 -799
- package/src/tabs-layout/network-status-indicator.tsx +0 -756
- package/src/tabs-layout/tabs-layout.tsx +0 -857
- package/src/tabs-layout/tabs-state.test.ts +0 -152
- package/src/tabs-layout/tabs-state.ts +0 -587
- package/src/tabs-layout/use-network-status.test.tsx +0 -58
- package/src/tabs-layout/use-network-status.ts +0 -68
- package/src/ui-defaults/index.ts +0 -2
- package/src/ui-defaults/list-screen.tsx +0 -94
- package/src/ui-defaults/markdown-field.tsx +0 -87
- package/src/ui-router/routes-loader.ts +0 -193
- package/src/ui-router/ui-loader.test.tsx +0 -108
- package/src/ui-router/ui-loader.tsx +0 -606
- package/src/utils.ts +0 -95
- package/tsconfig.json +0 -18
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
|
-
const react_1 = require("@testing-library/react");
|
|
8
|
-
const user_event_1 = __importDefault(require("@testing-library/user-event"));
|
|
9
|
-
const responsive_section_nav_1 = require("./responsive-section-nav");
|
|
10
|
-
jest.mock("../globals", () => {
|
|
11
|
-
const { observable: createObservable } = jest.requireActual("@peers-app/peers-sdk");
|
|
12
|
-
return { isDesktop: createObservable(true) };
|
|
13
|
-
});
|
|
14
|
-
const globals_1 = require("../globals");
|
|
15
|
-
const sections = [
|
|
16
|
-
{ id: "activity", label: "Activity", iconClassName: "bi-inbox", badge: 2 },
|
|
17
|
-
{ id: "people", label: "People", iconClassName: "bi-person" },
|
|
18
|
-
{ id: "groups", label: "Groups" },
|
|
19
|
-
{ id: "devices", label: "Devices" },
|
|
20
|
-
];
|
|
21
|
-
describe("ResponsiveSectionNav", () => {
|
|
22
|
-
beforeEach(() => {
|
|
23
|
-
(0, globals_1.isDesktop)(true);
|
|
24
|
-
});
|
|
25
|
-
it("uses a vertical sidebar on desktop and marks the selected section", () => {
|
|
26
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(responsive_section_nav_1.ResponsiveSectionNav, { label: "Identity", sections: sections, activeSectionId: "people", onSelect: () => undefined, toolbar: (0, jsx_runtime_1.jsx)("div", { children: "Quick actions" }), children: (0, jsx_runtime_1.jsx)("div", { children: "People body" }) }));
|
|
27
|
-
expect(react_1.screen.getByRole("navigation", { name: "Identity" }).querySelector("ul")).toHaveClass("nav-pills", "flex-column");
|
|
28
|
-
expect(react_1.screen.getByRole("button", { name: /People/ })).toHaveAttribute("aria-current", "page");
|
|
29
|
-
expect(react_1.screen.getByText("People body")).toBeInTheDocument();
|
|
30
|
-
expect(react_1.screen.getByText("Quick actions")).toBeInTheDocument();
|
|
31
|
-
expect(react_1.screen.getByText("Quick actions").closest("[data-section-scroll-container]")).toBeNull();
|
|
32
|
-
expect(react_1.screen.getByText("People body").closest("[data-section-scroll-container]")).toHaveClass("overflow-auto");
|
|
33
|
-
});
|
|
34
|
-
it("uses a non-wrapping horizontal strip on a narrow screen", () => {
|
|
35
|
-
(0, globals_1.isDesktop)(false);
|
|
36
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(responsive_section_nav_1.ResponsiveSectionNav, { label: "Identity", sections: sections, activeSectionId: "activity", onSelect: () => undefined, children: (0, jsx_runtime_1.jsx)("div", { children: "Activity body" }) }));
|
|
37
|
-
expect(react_1.screen.getByRole("navigation", { name: "Identity" }).querySelector("ul")).toHaveClass("nav-tabs", "flex-nowrap", "overflow-x-auto", "overflow-y-hidden");
|
|
38
|
-
});
|
|
39
|
-
it("reports the section chosen from the keyboard-focusable button", async () => {
|
|
40
|
-
const onSelect = jest.fn();
|
|
41
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(responsive_section_nav_1.ResponsiveSectionNav, { label: "Identity", sections: sections, activeSectionId: "activity", onSelect: onSelect, children: (0, jsx_runtime_1.jsx)("div", { children: "Activity body" }) }));
|
|
42
|
-
await user_event_1.default.click(react_1.screen.getByRole("button", { name: /Groups/ }));
|
|
43
|
-
expect(onSelect).toHaveBeenCalledWith("groups");
|
|
44
|
-
});
|
|
45
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
jest.mock("./tabs-layout/tabs-state", () => ({
|
|
4
|
-
handleMainPathChanged: (_oldPath, newPath, storage) => storage(newPath),
|
|
5
|
-
openNewTab: jest.fn(),
|
|
6
|
-
}));
|
|
7
|
-
const globals_1 = require("./globals");
|
|
8
|
-
describe("initial hash navigation", () => {
|
|
9
|
-
it("lets an incoming legacy deep link win and canonicalizes it", () => {
|
|
10
|
-
(0, globals_1.mainContentPath)("identity/activity");
|
|
11
|
-
window.history.replaceState(null, "", "/#contacts/abcdefghijklmnopqrstuvwxy?from=link");
|
|
12
|
-
(0, globals_1.initializeHashNavigation)();
|
|
13
|
-
expect((0, globals_1.mainContentPath)()).toBe("identity/people/abcdefghijklmnopqrstuvwxy?from=link");
|
|
14
|
-
expect(window.location.hash).toBe("#identity/people/abcdefghijklmnopqrstuvwxy?from=link");
|
|
15
|
-
});
|
|
16
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
4
|
-
const react_1 = require("@testing-library/react");
|
|
5
|
-
const use_observable_1 = require("./use-observable");
|
|
6
|
-
const use_observable_state_1 = require("./use-observable-state");
|
|
7
|
-
// Helper component to test useObservableState
|
|
8
|
-
function ObservableStateTestComponent({ initialValue }) {
|
|
9
|
-
const obs = (0, use_observable_state_1.useObservableState)(initialValue);
|
|
10
|
-
const [value] = (0, use_observable_1.useObservable)(obs);
|
|
11
|
-
return ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("span", { "data-testid": "state-value", children: value }), (0, jsx_runtime_1.jsx)("button", { type: "button", "data-testid": "increment", onClick: () => obs(obs() + 1), children: "Increment" })] }));
|
|
12
|
-
}
|
|
13
|
-
describe("useObservableState", () => {
|
|
14
|
-
it("should create an observable with the initial value", () => {
|
|
15
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(ObservableStateTestComponent, { initialValue: 42 }));
|
|
16
|
-
expect(react_1.screen.getByTestId("state-value")).toHaveTextContent("42");
|
|
17
|
-
});
|
|
18
|
-
it("should re-render when the observable is updated", async () => {
|
|
19
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(ObservableStateTestComponent, { initialValue: 0 }));
|
|
20
|
-
expect(react_1.screen.getByTestId("state-value")).toHaveTextContent("0");
|
|
21
|
-
(0, react_1.act)(() => {
|
|
22
|
-
react_1.screen.getByTestId("increment").click();
|
|
23
|
-
});
|
|
24
|
-
await (0, react_1.waitFor)(() => {
|
|
25
|
-
expect(react_1.screen.getByTestId("state-value")).toHaveTextContent("1");
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
it("should maintain the same observable instance across re-renders", async () => {
|
|
29
|
-
let capturedObs = null;
|
|
30
|
-
function CaptureObsComponent() {
|
|
31
|
-
const obs = (0, use_observable_state_1.useObservableState)(0);
|
|
32
|
-
if (!capturedObs) {
|
|
33
|
-
capturedObs = obs;
|
|
34
|
-
}
|
|
35
|
-
const [value] = (0, use_observable_1.useObservable)(obs);
|
|
36
|
-
return ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("span", { "data-testid": "value", children: value }), (0, jsx_runtime_1.jsx)("span", { "data-testid": "same-obs", children: obs === capturedObs ? "same" : "different" }), (0, jsx_runtime_1.jsx)("button", { type: "button", "data-testid": "update", onClick: () => obs(obs() + 1), children: "Update" })] }));
|
|
37
|
-
}
|
|
38
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(CaptureObsComponent, {}));
|
|
39
|
-
expect(react_1.screen.getByTestId("same-obs")).toHaveTextContent("same");
|
|
40
|
-
// Trigger a re-render by updating the observable
|
|
41
|
-
(0, react_1.act)(() => {
|
|
42
|
-
react_1.screen.getByTestId("update").click();
|
|
43
|
-
});
|
|
44
|
-
await (0, react_1.waitFor)(() => {
|
|
45
|
-
expect(react_1.screen.getByTestId("value")).toHaveTextContent("1");
|
|
46
|
-
expect(react_1.screen.getByTestId("same-obs")).toHaveTextContent("same");
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
it("should not subscribe when doNotSubscribe is true", () => {
|
|
50
|
-
function NoSubscribeComponent() {
|
|
51
|
-
const obs = (0, use_observable_state_1.useObservableState)(0, true); // doNotSubscribe = true
|
|
52
|
-
return ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("span", { "data-testid": "value", children: obs() }), (0, jsx_runtime_1.jsx)("button", { type: "button", "data-testid": "update", onClick: () => obs(obs() + 1), children: "Update" })] }));
|
|
53
|
-
}
|
|
54
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(NoSubscribeComponent, {}));
|
|
55
|
-
expect(react_1.screen.getByTestId("value")).toHaveTextContent("0");
|
|
56
|
-
// Update won't cause re-render since we're not subscribed
|
|
57
|
-
(0, react_1.act)(() => {
|
|
58
|
-
react_1.screen.getByTestId("update").click();
|
|
59
|
-
});
|
|
60
|
-
// Value in DOM should still show 0 since component didn't re-render
|
|
61
|
-
// But the observable itself has been updated
|
|
62
|
-
expect(react_1.screen.getByTestId("value")).toHaveTextContent("0");
|
|
63
|
-
});
|
|
64
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
4
|
-
const peers_sdk_1 = require("@peers-app/peers-sdk");
|
|
5
|
-
const react_1 = require("@testing-library/react");
|
|
6
|
-
const use_observable_1 = require("./use-observable");
|
|
7
|
-
// Helper component to test useObservable
|
|
8
|
-
function TestComponent({ obs, testId = "value" }) {
|
|
9
|
-
const [value, setValue] = (0, use_observable_1.useObservable)(obs);
|
|
10
|
-
return ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("span", { "data-testid": testId, children: JSON.stringify(value) }), (0, jsx_runtime_1.jsx)("button", { type: "button", "data-testid": "setter", onClick: () => setValue("new-value"), children: "Set" })] }));
|
|
11
|
-
}
|
|
12
|
-
// Helper component to test array behavior
|
|
13
|
-
function ArrayTestComponent({ obs }) {
|
|
14
|
-
const [value] = (0, use_observable_1.useObservable)(obs);
|
|
15
|
-
return ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("span", { "data-testid": "array-value", children: JSON.stringify(value) }), (0, jsx_runtime_1.jsx)("span", { "data-testid": "array-length", children: value.length })] }));
|
|
16
|
-
}
|
|
17
|
-
describe("useObservable", () => {
|
|
18
|
-
it("reads and follows a read-only observable without allowing typed writes", () => {
|
|
19
|
-
const source = (0, peers_sdk_1.observable)(1);
|
|
20
|
-
const view = source;
|
|
21
|
-
const { result } = (0, react_1.renderHook)(() => (0, use_observable_1.useObservable)(view));
|
|
22
|
-
const checkReadonly = () => {
|
|
23
|
-
// @ts-expect-error the read-only hook's setter accepts no values
|
|
24
|
-
result.current[1](2);
|
|
25
|
-
if ((0, peers_sdk_1.isSubscribable)(view)) {
|
|
26
|
-
// @ts-expect-error testing subscribability must not make a read-only view writable
|
|
27
|
-
view(2);
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
void checkReadonly;
|
|
31
|
-
const initial = result.current[0];
|
|
32
|
-
expect(initial).toBe(1);
|
|
33
|
-
(0, react_1.act)(() => source(3));
|
|
34
|
-
expect(result.current[0]).toBe(3);
|
|
35
|
-
});
|
|
36
|
-
describe("basic functionality", () => {
|
|
37
|
-
it("should return the current value of an observable", () => {
|
|
38
|
-
const obs = (0, peers_sdk_1.observable)("hello");
|
|
39
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(TestComponent, { obs: obs }));
|
|
40
|
-
expect(react_1.screen.getByTestId("value")).toHaveTextContent('"hello"');
|
|
41
|
-
});
|
|
42
|
-
it("should return the value when passed a plain value (non-observable)", () => {
|
|
43
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(TestComponent, { obs: "plain-value" }));
|
|
44
|
-
expect(react_1.screen.getByTestId("value")).toHaveTextContent('"plain-value"');
|
|
45
|
-
});
|
|
46
|
-
it("should re-render when observable value changes", async () => {
|
|
47
|
-
const obs = (0, peers_sdk_1.observable)("initial");
|
|
48
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(TestComponent, { obs: obs }));
|
|
49
|
-
expect(react_1.screen.getByTestId("value")).toHaveTextContent('"initial"');
|
|
50
|
-
(0, react_1.act)(() => {
|
|
51
|
-
obs("updated");
|
|
52
|
-
});
|
|
53
|
-
await (0, react_1.waitFor)(() => {
|
|
54
|
-
expect(react_1.screen.getByTestId("value")).toHaveTextContent('"updated"');
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
it("should update the observable when setter is called", async () => {
|
|
58
|
-
const obs = (0, peers_sdk_1.observable)("initial");
|
|
59
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(TestComponent, { obs: obs }));
|
|
60
|
-
(0, react_1.act)(() => {
|
|
61
|
-
react_1.screen.getByTestId("setter").click();
|
|
62
|
-
});
|
|
63
|
-
await (0, react_1.waitFor)(() => {
|
|
64
|
-
expect(obs()).toBe("new-value");
|
|
65
|
-
expect(react_1.screen.getByTestId("value")).toHaveTextContent('"new-value"');
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
it("should handle undefined values", () => {
|
|
69
|
-
const obs = (0, peers_sdk_1.observable)(undefined);
|
|
70
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(TestComponent, { obs: obs }));
|
|
71
|
-
// undefined serializes to empty string in JSON.stringify, but actually shows as nothing
|
|
72
|
-
expect(react_1.screen.getByTestId("value")).toHaveTextContent("");
|
|
73
|
-
});
|
|
74
|
-
it("should handle object values", async () => {
|
|
75
|
-
const obs = (0, peers_sdk_1.observable)({ name: "test", count: 5 });
|
|
76
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(TestComponent, { obs: obs }));
|
|
77
|
-
expect(react_1.screen.getByTestId("value")).toHaveTextContent('{"name":"test","count":5}');
|
|
78
|
-
(0, react_1.act)(() => {
|
|
79
|
-
obs({ name: "updated", count: 10 });
|
|
80
|
-
});
|
|
81
|
-
await (0, react_1.waitFor)(() => {
|
|
82
|
-
expect(react_1.screen.getByTestId("value")).toHaveTextContent('{"name":"updated","count":10}');
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
describe("array handling", () => {
|
|
87
|
-
it("should handle array values", () => {
|
|
88
|
-
const obs = (0, peers_sdk_1.observable)(["a", "b", "c"]);
|
|
89
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(ArrayTestComponent, { obs: obs }));
|
|
90
|
-
expect(react_1.screen.getByTestId("array-value")).toHaveTextContent('["a","b","c"]');
|
|
91
|
-
expect(react_1.screen.getByTestId("array-length")).toHaveTextContent("3");
|
|
92
|
-
});
|
|
93
|
-
it("should re-render when array is replaced with new reference", async () => {
|
|
94
|
-
const obs = (0, peers_sdk_1.observable)(["a", "b"]);
|
|
95
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(ArrayTestComponent, { obs: obs }));
|
|
96
|
-
expect(react_1.screen.getByTestId("array-length")).toHaveTextContent("2");
|
|
97
|
-
(0, react_1.act)(() => {
|
|
98
|
-
obs(["a", "b", "c"]); // New array reference
|
|
99
|
-
});
|
|
100
|
-
await (0, react_1.waitFor)(() => {
|
|
101
|
-
expect(react_1.screen.getByTestId("array-length")).toHaveTextContent("3");
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
it("should NOT re-render when array is mutated in place (requires immutable updates)", async () => {
|
|
105
|
-
// This tests the case where an array is mutated in place and notifySubscribers is called.
|
|
106
|
-
//
|
|
107
|
-
// IMPORTANT BEHAVIORAL NOTE:
|
|
108
|
-
// The OLD implementation (useState + useEffect) had special handling that would
|
|
109
|
-
// spread the array when it detected same-reference mutation:
|
|
110
|
-
// if (isArray(newData) && newData === data) setData([...newData])
|
|
111
|
-
//
|
|
112
|
-
// The NEW implementation (useSyncExternalStore) does NOT do this.
|
|
113
|
-
// useSyncExternalStore uses Object.is() comparison on getSnapshot results.
|
|
114
|
-
// If the reference is the same, React won't re-render.
|
|
115
|
-
//
|
|
116
|
-
// This is actually the CORRECT behavior - it encourages immutable data patterns
|
|
117
|
-
// which are required for React 18 concurrent rendering to work correctly.
|
|
118
|
-
// Mutating data in place can cause tearing in concurrent mode.
|
|
119
|
-
const obs = (0, peers_sdk_1.observable)(["a", "b"]);
|
|
120
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(ArrayTestComponent, { obs: obs }));
|
|
121
|
-
expect(react_1.screen.getByTestId("array-length")).toHaveTextContent("2");
|
|
122
|
-
(0, react_1.act)(() => {
|
|
123
|
-
// Mutate the array in place (BAD PRACTICE - don't do this!)
|
|
124
|
-
const arr = obs();
|
|
125
|
-
arr.push("c");
|
|
126
|
-
obs.notifySubscribers();
|
|
127
|
-
});
|
|
128
|
-
// The observable itself has the mutated value
|
|
129
|
-
expect(obs()).toEqual(["a", "b", "c"]);
|
|
130
|
-
// But the component did NOT re-render because the reference didn't change
|
|
131
|
-
// This is expected with useSyncExternalStore - it requires immutable updates
|
|
132
|
-
expect(react_1.screen.getByTestId("array-length")).toHaveTextContent("2");
|
|
133
|
-
});
|
|
134
|
-
it("should re-render when array is properly updated with spread", async () => {
|
|
135
|
-
// This is the recommended pattern for updating arrays
|
|
136
|
-
const obs = (0, peers_sdk_1.observable)(["a", "b"]);
|
|
137
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(ArrayTestComponent, { obs: obs }));
|
|
138
|
-
expect(react_1.screen.getByTestId("array-length")).toHaveTextContent("2");
|
|
139
|
-
(0, react_1.act)(() => {
|
|
140
|
-
obs([...obs(), "c"]); // Proper immutable update
|
|
141
|
-
});
|
|
142
|
-
await (0, react_1.waitFor)(() => {
|
|
143
|
-
expect(react_1.screen.getByTestId("array-length")).toHaveTextContent("3");
|
|
144
|
-
expect(react_1.screen.getByTestId("array-value")).toHaveTextContent('["a","b","c"]');
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
});
|
|
148
|
-
describe("subscription management", () => {
|
|
149
|
-
it("should unsubscribe when component unmounts", () => {
|
|
150
|
-
const obs = (0, peers_sdk_1.observable)("test");
|
|
151
|
-
const initialSubscriberCount = obs.subscriberCount();
|
|
152
|
-
const { unmount } = (0, react_1.render)((0, jsx_runtime_1.jsx)(TestComponent, { obs: obs }));
|
|
153
|
-
// Should have subscribed
|
|
154
|
-
expect(obs.subscriberCount()).toBeGreaterThan(initialSubscriberCount);
|
|
155
|
-
unmount();
|
|
156
|
-
// Should have unsubscribed
|
|
157
|
-
expect(obs.subscriberCount()).toBe(initialSubscriberCount);
|
|
158
|
-
});
|
|
159
|
-
it("should handle multiple components subscribing to same observable", async () => {
|
|
160
|
-
const obs = (0, peers_sdk_1.observable)("shared");
|
|
161
|
-
(0, react_1.render)((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(TestComponent, { obs: obs, testId: "value1" }), (0, jsx_runtime_1.jsx)(TestComponent, { obs: obs, testId: "value2" })] }));
|
|
162
|
-
expect(react_1.screen.getByTestId("value1")).toHaveTextContent('"shared"');
|
|
163
|
-
expect(react_1.screen.getByTestId("value2")).toHaveTextContent('"shared"');
|
|
164
|
-
(0, react_1.act)(() => {
|
|
165
|
-
obs("updated");
|
|
166
|
-
});
|
|
167
|
-
await (0, react_1.waitFor)(() => {
|
|
168
|
-
expect(react_1.screen.getByTestId("value1")).toHaveTextContent('"updated"');
|
|
169
|
-
expect(react_1.screen.getByTestId("value2")).toHaveTextContent('"updated"');
|
|
170
|
-
});
|
|
171
|
-
});
|
|
172
|
-
});
|
|
173
|
-
describe("rapid updates", () => {
|
|
174
|
-
it("should handle rapid sequential updates correctly", async () => {
|
|
175
|
-
const obs = (0, peers_sdk_1.observable)(0);
|
|
176
|
-
function CounterComponent() {
|
|
177
|
-
const [value] = (0, use_observable_1.useObservable)(obs);
|
|
178
|
-
return (0, jsx_runtime_1.jsx)("span", { "data-testid": "counter", children: value });
|
|
179
|
-
}
|
|
180
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(CounterComponent, {}));
|
|
181
|
-
(0, react_1.act)(() => {
|
|
182
|
-
for (let i = 1; i <= 10; i++) {
|
|
183
|
-
obs(i);
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
await (0, react_1.waitFor)(() => {
|
|
187
|
-
expect(react_1.screen.getByTestId("counter")).toHaveTextContent("10");
|
|
188
|
-
});
|
|
189
|
-
});
|
|
190
|
-
});
|
|
191
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
4
|
-
const react_1 = require("@testing-library/react");
|
|
5
|
-
const use_rows_1 = require("./use-rows");
|
|
6
|
-
/** A table whose reads are answered by the test, one at a time. */
|
|
7
|
-
function fakeTable(answer) {
|
|
8
|
-
const listeners = new Set();
|
|
9
|
-
const reads = [];
|
|
10
|
-
const table = {
|
|
11
|
-
list: jest.fn(async (filter) => {
|
|
12
|
-
reads.push(filter);
|
|
13
|
-
return answer(filter);
|
|
14
|
-
}),
|
|
15
|
-
dataChanged: {
|
|
16
|
-
subscribe: (handler, options) => {
|
|
17
|
-
const listener = { handler: () => handler({}), options };
|
|
18
|
-
listeners.add(listener);
|
|
19
|
-
return { unsubscribe: () => listeners.delete(listener) };
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
};
|
|
23
|
-
return {
|
|
24
|
-
table,
|
|
25
|
-
reads,
|
|
26
|
-
listeners,
|
|
27
|
-
change: () => {
|
|
28
|
-
for (const listener of listeners)
|
|
29
|
-
listener.handler();
|
|
30
|
-
},
|
|
31
|
-
reconnect: () => {
|
|
32
|
-
for (const listener of listeners)
|
|
33
|
-
listener.options?.onReconnect?.();
|
|
34
|
-
},
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
function Rows({ table, filter }) {
|
|
38
|
-
const { rows, loading, error } = (0, use_rows_1.useRows)(table, filter);
|
|
39
|
-
return ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("span", { "data-testid": "rows", children: rows.map((row) => row.id).join(",") }), (0, jsx_runtime_1.jsx)("span", { "data-testid": "loading", children: String(loading) }), (0, jsx_runtime_1.jsx)("span", { "data-testid": "error", children: error?.message ?? "" })] }));
|
|
40
|
-
}
|
|
41
|
-
const text = (id) => react_1.screen.getByTestId(id).textContent;
|
|
42
|
-
describe("useRows", () => {
|
|
43
|
-
test("reads on mount and again when the table changes", async () => {
|
|
44
|
-
let rows = [{ id: "a" }];
|
|
45
|
-
const fake = fakeTable(() => rows);
|
|
46
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(Rows, { table: fake.table }));
|
|
47
|
-
expect(text("loading")).toBe("true");
|
|
48
|
-
await (0, react_1.waitFor)(() => expect(text("rows")).toBe("a"));
|
|
49
|
-
expect(text("loading")).toBe("false");
|
|
50
|
-
rows = [{ id: "a" }, { id: "b" }];
|
|
51
|
-
(0, react_1.act)(() => fake.change());
|
|
52
|
-
await (0, react_1.waitFor)(() => expect(text("rows")).toBe("a,b"));
|
|
53
|
-
});
|
|
54
|
-
test("changes during a read cause one more read, not one per change", async () => {
|
|
55
|
-
let release;
|
|
56
|
-
let n = 0;
|
|
57
|
-
const fake = fakeTable(() => new Promise((resolve) => {
|
|
58
|
-
const id = String(++n);
|
|
59
|
-
release = () => resolve([{ id }]);
|
|
60
|
-
}));
|
|
61
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(Rows, { table: fake.table }));
|
|
62
|
-
await (0, react_1.waitFor)(() => expect(fake.reads).toHaveLength(1));
|
|
63
|
-
(0, react_1.act)(() => {
|
|
64
|
-
fake.change();
|
|
65
|
-
fake.change();
|
|
66
|
-
fake.change();
|
|
67
|
-
});
|
|
68
|
-
await (0, react_1.act)(async () => release?.());
|
|
69
|
-
await (0, react_1.waitFor)(() => expect(fake.reads).toHaveLength(2));
|
|
70
|
-
await (0, react_1.act)(async () => release?.());
|
|
71
|
-
await (0, react_1.waitFor)(() => expect(text("rows")).toBe("2"));
|
|
72
|
-
expect(fake.reads).toHaveLength(2);
|
|
73
|
-
});
|
|
74
|
-
test("reads again after a reconnect", async () => {
|
|
75
|
-
let rows = [{ id: "a" }];
|
|
76
|
-
const fake = fakeTable(() => rows);
|
|
77
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(Rows, { table: fake.table }));
|
|
78
|
-
await (0, react_1.waitFor)(() => expect(text("rows")).toBe("a"));
|
|
79
|
-
rows = [{ id: "missed" }];
|
|
80
|
-
(0, react_1.act)(() => fake.reconnect());
|
|
81
|
-
await (0, react_1.waitFor)(() => expect(text("rows")).toBe("missed"));
|
|
82
|
-
});
|
|
83
|
-
test("reports a failed read and keeps the last rows", async () => {
|
|
84
|
-
let fail = false;
|
|
85
|
-
const fake = fakeTable(() => {
|
|
86
|
-
if (fail)
|
|
87
|
-
throw new Error("host is down");
|
|
88
|
-
return [{ id: "a" }];
|
|
89
|
-
});
|
|
90
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(Rows, { table: fake.table }));
|
|
91
|
-
await (0, react_1.waitFor)(() => expect(text("rows")).toBe("a"));
|
|
92
|
-
fail = true;
|
|
93
|
-
(0, react_1.act)(() => fake.change());
|
|
94
|
-
await (0, react_1.waitFor)(() => expect(text("error")).toBe("host is down"));
|
|
95
|
-
expect(text("rows")).toBe("a");
|
|
96
|
-
fail = false;
|
|
97
|
-
(0, react_1.act)(() => fake.change());
|
|
98
|
-
await (0, react_1.waitFor)(() => expect(text("error")).toBe(""));
|
|
99
|
-
});
|
|
100
|
-
test("reads again when the filter changes, and unsubscribes on unmount", async () => {
|
|
101
|
-
const fake = fakeTable((filter) => [{ id: JSON.stringify(filter) }]);
|
|
102
|
-
const { rerender, unmount } = (0, react_1.render)((0, jsx_runtime_1.jsx)(Rows, { table: fake.table, filter: { id: "x" } }));
|
|
103
|
-
await (0, react_1.waitFor)(() => expect(text("rows")).toBe('{"id":"x"}'));
|
|
104
|
-
// An equal filter in a new object doesn't read again.
|
|
105
|
-
rerender((0, jsx_runtime_1.jsx)(Rows, { table: fake.table, filter: { id: "x" } }));
|
|
106
|
-
rerender((0, jsx_runtime_1.jsx)(Rows, { table: fake.table, filter: { id: "y" } }));
|
|
107
|
-
await (0, react_1.waitFor)(() => expect(text("rows")).toBe('{"id":"y"}'));
|
|
108
|
-
expect(fake.reads).toEqual([{ id: "x" }, { id: "y" }]);
|
|
109
|
-
expect(fake.listeners.size).toBe(1);
|
|
110
|
-
unmount();
|
|
111
|
-
expect(fake.listeners.size).toBe(0);
|
|
112
|
-
});
|
|
113
|
-
test("reads again once an asynchronous subscription is live", async () => {
|
|
114
|
-
let rows = [{ id: "before" }];
|
|
115
|
-
const fake = fakeTable(() => rows);
|
|
116
|
-
let release;
|
|
117
|
-
const ready = new Promise((resolve) => {
|
|
118
|
-
release = resolve;
|
|
119
|
-
});
|
|
120
|
-
const subscribe = fake.table.dataChanged.subscribe;
|
|
121
|
-
fake.table.dataChanged.subscribe = (handler, options) => ({
|
|
122
|
-
...subscribe(handler, options),
|
|
123
|
-
ready,
|
|
124
|
-
});
|
|
125
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(Rows, { table: fake.table }));
|
|
126
|
-
await (0, react_1.waitFor)(() => expect(text("rows")).toBe("before"));
|
|
127
|
-
// No notification can be delivered while the remote subscription is still attaching.
|
|
128
|
-
rows = [{ id: "during setup" }];
|
|
129
|
-
await (0, react_1.act)(async () => release(true));
|
|
130
|
-
await (0, react_1.waitFor)(() => expect(text("rows")).toBe("during setup"));
|
|
131
|
-
});
|
|
132
|
-
test("a synchronous list failure can be retried", async () => {
|
|
133
|
-
const fake = fakeTable(() => [{ id: "recovered" }]);
|
|
134
|
-
const list = fake.table.list;
|
|
135
|
-
fake.table.list = jest.fn(() => {
|
|
136
|
-
throw new Error("offline");
|
|
137
|
-
});
|
|
138
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(Rows, { table: fake.table }));
|
|
139
|
-
await (0, react_1.waitFor)(() => expect(text("error")).toBe("offline"));
|
|
140
|
-
fake.table.list = list;
|
|
141
|
-
(0, react_1.act)(() => fake.change());
|
|
142
|
-
await (0, react_1.waitFor)(() => expect(text("rows")).toBe("recovered"));
|
|
143
|
-
});
|
|
144
|
-
test("reload retries a failed subscription", async () => {
|
|
145
|
-
const fake = fakeTable(() => [{ id: "recovered" }]);
|
|
146
|
-
const subscribe = fake.table.dataChanged.subscribe;
|
|
147
|
-
fake.table.dataChanged.subscribe = () => {
|
|
148
|
-
throw new Error("subscription unavailable");
|
|
149
|
-
};
|
|
150
|
-
const { result } = (0, react_1.renderHook)(() => (0, use_rows_1.useRows)(fake.table));
|
|
151
|
-
await (0, react_1.waitFor)(() => expect(result.current.error?.message).toBe("subscription unavailable"));
|
|
152
|
-
fake.table.dataChanged.subscribe = subscribe;
|
|
153
|
-
await (0, react_1.act)(async () => result.current.reload());
|
|
154
|
-
expect(result.current.rows).toEqual([{ id: "recovered" }]);
|
|
155
|
-
expect(result.current.error).toBeUndefined();
|
|
156
|
-
expect(fake.listeners.size).toBe(1);
|
|
157
|
-
});
|
|
158
|
-
test("reload resolves once the rows are current", async () => {
|
|
159
|
-
let rows = [{ id: "a" }];
|
|
160
|
-
const fake = fakeTable(() => rows);
|
|
161
|
-
let reload;
|
|
162
|
-
function Reloading() {
|
|
163
|
-
const result = (0, use_rows_1.useRows)(fake.table);
|
|
164
|
-
reload = result.reload;
|
|
165
|
-
return (0, jsx_runtime_1.jsx)("span", { "data-testid": "rows", children: result.rows.map((row) => row.id).join(",") });
|
|
166
|
-
}
|
|
167
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(Reloading, {}));
|
|
168
|
-
await (0, react_1.waitFor)(() => expect(text("rows")).toBe("a"));
|
|
169
|
-
rows = [{ id: "b" }];
|
|
170
|
-
await (0, react_1.act)(async () => {
|
|
171
|
-
await reload?.();
|
|
172
|
-
});
|
|
173
|
-
expect(text("rows")).toBe("b");
|
|
174
|
-
});
|
|
175
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|