@agent-native/dispatch 0.40.13 → 0.40.14-nightly-20261006033736
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/CHANGELOG.md +26 -0
- package/dist/actions/provider-api-register.d.ts +10 -10
- package/dist/components/connected-app-card.d.ts.map +1 -1
- package/dist/components/connected-app-card.js +23 -4
- package/dist/components/connected-app-card.js.map +1 -1
- package/dist/components/layout/Layout.d.ts.map +1 -1
- package/dist/components/layout/Layout.js +116 -60
- package/dist/components/layout/Layout.js.map +1 -1
- package/dist/components/layout/workspace-apps-rail.d.ts.map +1 -1
- package/dist/components/layout/workspace-apps-rail.js +35 -9
- package/dist/components/layout/workspace-apps-rail.js.map +1 -1
- package/dist/lib/other-apps.d.ts +1 -0
- package/dist/lib/other-apps.d.ts.map +1 -1
- package/dist/lib/other-apps.js +29 -1
- package/dist/lib/other-apps.js.map +1 -1
- package/dist/lib/workspace-apps.d.ts +2 -1
- package/dist/lib/workspace-apps.d.ts.map +1 -1
- package/dist/lib/workspace-apps.js +15 -5
- package/dist/lib/workspace-apps.js.map +1 -1
- package/dist/routes/pages/apps.d.ts.map +1 -1
- package/dist/routes/pages/apps.js +17 -4
- package/dist/routes/pages/apps.js.map +1 -1
- package/dist/server/plugins/auth.js +2 -2
- package/dist/server/plugins/auth.js.map +1 -1
- package/package.json +4 -4
- package/src/components/connected-app-card.spec.tsx +100 -0
- package/src/components/connected-app-card.tsx +38 -9
- package/src/components/layout/Layout.spec.tsx +397 -6
- package/src/components/layout/Layout.tsx +173 -85
- package/src/components/layout/workspace-apps-rail.spec.tsx +69 -7
- package/src/components/layout/workspace-apps-rail.tsx +49 -7
- package/src/lib/other-apps.spec.ts +84 -2
- package/src/lib/other-apps.ts +39 -1
- package/src/lib/workspace-apps.spec.ts +53 -0
- package/src/lib/workspace-apps.ts +15 -7
- package/src/routes/pages/apps.spec.tsx +132 -0
- package/src/routes/pages/apps.tsx +46 -10
- package/src/server/plugins/auth.ts +2 -2
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import { emitChatFirstOpenApp } from "@agent-native/core/client/agent-chat";
|
|
1
2
|
import { isSettingsPathname } from "@agent-native/toolkit/app/settings";
|
|
2
3
|
// @vitest-environment happy-dom
|
|
3
4
|
import React, { act } from "react";
|
|
4
5
|
import { createRoot, type Root } from "react-dom/client";
|
|
5
|
-
import { MemoryRouter, useLocation } from "react-router";
|
|
6
|
+
import { MemoryRouter, useLocation, useNavigate } from "react-router";
|
|
6
7
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
7
8
|
|
|
9
|
+
import { CHAT_FIRST_PANE_STATE_KEY } from "../../shared/chat-first-pane";
|
|
8
10
|
import { AdminShell } from "../admin-navigation";
|
|
9
11
|
import { Tooltip, TooltipProvider, TooltipTrigger } from "../ui/tooltip";
|
|
10
12
|
import {
|
|
@@ -26,11 +28,26 @@ const clientState = vi.hoisted(() => ({
|
|
|
26
28
|
switchThread: vi.fn(),
|
|
27
29
|
threads: [] as Array<Record<string, unknown>>,
|
|
28
30
|
workspaceApps: [] as Array<Record<string, unknown>>,
|
|
31
|
+
workspaceAppsError: null as Error | null,
|
|
32
|
+
workspaceAppsLoading: false,
|
|
33
|
+
connectedApps: [] as Array<Record<string, unknown>>,
|
|
34
|
+
connectedAppsError: null as Error | null,
|
|
35
|
+
connectedAppsLoading: false,
|
|
36
|
+
appState: {} as Record<string, unknown>,
|
|
37
|
+
appStatePromises: {} as Record<string, Promise<unknown>>,
|
|
29
38
|
basePath: "",
|
|
30
39
|
createEmbedSessionMutateAsync: vi
|
|
31
40
|
.fn()
|
|
32
41
|
.mockResolvedValue({ startUrl: "about:blank" }),
|
|
33
42
|
}));
|
|
43
|
+
const workspaceAppNavigation = vi.hoisted(() => ({
|
|
44
|
+
navigateToWorkspaceApp: vi.fn((_href: string) => true),
|
|
45
|
+
}));
|
|
46
|
+
|
|
47
|
+
vi.mock("../../lib/workspace-apps", async (importOriginal) => ({
|
|
48
|
+
...(await importOriginal<typeof import("../../lib/workspace-apps")>()),
|
|
49
|
+
navigateToWorkspaceApp: workspaceAppNavigation.navigateToWorkspaceApp,
|
|
50
|
+
}));
|
|
34
51
|
|
|
35
52
|
vi.mock("@agent-native/core/client/agent-chat", async (importOriginal) => ({
|
|
36
53
|
...(await importOriginal<
|
|
@@ -99,16 +116,51 @@ vi.mock("@agent-native/core/client/api-path", () => ({
|
|
|
99
116
|
|
|
100
117
|
vi.mock("@agent-native/core/client/hooks", async (importOriginal) => ({
|
|
101
118
|
...(await importOriginal<typeof import("@agent-native/core/client/hooks")>()),
|
|
102
|
-
useActionQuery: (action: string) =>
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
119
|
+
useActionQuery: (action: string) => {
|
|
120
|
+
const workspaceAppsQuery = action === "list-workspace-apps";
|
|
121
|
+
const connectedAppsQuery = action === "list-connected-agents";
|
|
122
|
+
const error = workspaceAppsQuery
|
|
123
|
+
? clientState.workspaceAppsError
|
|
124
|
+
: connectedAppsQuery
|
|
125
|
+
? clientState.connectedAppsError
|
|
126
|
+
: null;
|
|
127
|
+
return {
|
|
128
|
+
data: workspaceAppsQuery
|
|
129
|
+
? clientState.workspaceApps
|
|
130
|
+
: connectedAppsQuery
|
|
131
|
+
? clientState.connectedApps
|
|
132
|
+
: undefined,
|
|
133
|
+
error,
|
|
134
|
+
isError: Boolean(error),
|
|
135
|
+
isLoading: workspaceAppsQuery
|
|
136
|
+
? clientState.workspaceAppsLoading
|
|
137
|
+
: connectedAppsQuery
|
|
138
|
+
? clientState.connectedAppsLoading
|
|
139
|
+
: false,
|
|
140
|
+
};
|
|
141
|
+
},
|
|
107
142
|
useActionMutation: () => ({
|
|
108
143
|
mutateAsync: clientState.createEmbedSessionMutateAsync,
|
|
109
144
|
}),
|
|
110
145
|
}));
|
|
111
146
|
|
|
147
|
+
vi.mock(
|
|
148
|
+
"@agent-native/core/client/application-state",
|
|
149
|
+
async (importOriginal) => ({
|
|
150
|
+
...(await importOriginal<
|
|
151
|
+
typeof import("@agent-native/core/client/application-state")
|
|
152
|
+
>()),
|
|
153
|
+
readClientAppState: async (key: string) =>
|
|
154
|
+
(await clientState.appStatePromises[key]) ??
|
|
155
|
+
clientState.appState[key] ??
|
|
156
|
+
null,
|
|
157
|
+
writeClientAppState: async (key: string, value: unknown) => {
|
|
158
|
+
clientState.appState[key] = value;
|
|
159
|
+
return value;
|
|
160
|
+
},
|
|
161
|
+
}),
|
|
162
|
+
);
|
|
163
|
+
|
|
112
164
|
vi.mock("@agent-native/core/client/feature-flags", () => ({
|
|
113
165
|
useFeatureFlag: () => false,
|
|
114
166
|
useFeatureFlagState: () => ({ enabled: false, status: "ready" }),
|
|
@@ -171,6 +223,15 @@ function LocationProbe({ onChange }: { onChange: (path: string) => void }) {
|
|
|
171
223
|
return null;
|
|
172
224
|
}
|
|
173
225
|
|
|
226
|
+
function ChatRouteSwitcher({ target }: { target: string }) {
|
|
227
|
+
const navigate = useNavigate();
|
|
228
|
+
return (
|
|
229
|
+
<button type="button" onClick={() => navigate(target)}>
|
|
230
|
+
Switch chat
|
|
231
|
+
</button>
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
|
|
174
235
|
describe("Dispatch navigation paths", () => {
|
|
175
236
|
afterEach(() => {
|
|
176
237
|
clientState.basePath = "";
|
|
@@ -304,6 +365,14 @@ describe("Dispatch NavContent", () => {
|
|
|
304
365
|
},
|
|
305
366
|
];
|
|
306
367
|
clientState.workspaceApps = [];
|
|
368
|
+
clientState.workspaceAppsError = null;
|
|
369
|
+
clientState.workspaceAppsLoading = false;
|
|
370
|
+
clientState.connectedApps = [];
|
|
371
|
+
clientState.connectedAppsError = null;
|
|
372
|
+
clientState.connectedAppsLoading = false;
|
|
373
|
+
clientState.appState = {};
|
|
374
|
+
clientState.appStatePromises = {};
|
|
375
|
+
workspaceAppNavigation.navigateToWorkspaceApp.mockClear();
|
|
307
376
|
container = document.createElement("div");
|
|
308
377
|
document.body.appendChild(container);
|
|
309
378
|
root = createRoot(container);
|
|
@@ -359,6 +428,328 @@ describe("Dispatch NavContent", () => {
|
|
|
359
428
|
}
|
|
360
429
|
});
|
|
361
430
|
|
|
431
|
+
it("opens mounted apps when optional connected-app discovery fails", async () => {
|
|
432
|
+
clientState.workspaceApps = [
|
|
433
|
+
{
|
|
434
|
+
id: "mail",
|
|
435
|
+
name: "Mail",
|
|
436
|
+
path: "/mail",
|
|
437
|
+
url: "/mail",
|
|
438
|
+
status: "ready",
|
|
439
|
+
},
|
|
440
|
+
];
|
|
441
|
+
clientState.connectedAppsError = new Error("Connected apps unavailable");
|
|
442
|
+
|
|
443
|
+
await act(async () => {
|
|
444
|
+
root.render(
|
|
445
|
+
<MemoryRouter initialEntries={["/chat/mounted-optional-error"]}>
|
|
446
|
+
<Layout extensions={{ chatFirst: true }}>
|
|
447
|
+
<div />
|
|
448
|
+
</Layout>
|
|
449
|
+
</MemoryRouter>,
|
|
450
|
+
);
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
await act(async () => {
|
|
454
|
+
emitChatFirstOpenApp({ app: "mail" });
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
expect(
|
|
458
|
+
container.querySelector("[data-chat-first-app-pane]"),
|
|
459
|
+
).not.toBeNull();
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
it("opens a loaded mounted app while optional built-in discovery is loading", async () => {
|
|
463
|
+
clientState.workspaceApps = [
|
|
464
|
+
{
|
|
465
|
+
id: "mail",
|
|
466
|
+
name: "Mail",
|
|
467
|
+
path: "/mail",
|
|
468
|
+
url: "/mail",
|
|
469
|
+
status: "ready",
|
|
470
|
+
},
|
|
471
|
+
];
|
|
472
|
+
clientState.connectedAppsLoading = true;
|
|
473
|
+
|
|
474
|
+
await act(async () => {
|
|
475
|
+
root.render(
|
|
476
|
+
<MemoryRouter initialEntries={["/chat/mounted-while-loading"]}>
|
|
477
|
+
<Layout extensions={{ chatFirst: true }}>
|
|
478
|
+
<div />
|
|
479
|
+
</Layout>
|
|
480
|
+
</MemoryRouter>,
|
|
481
|
+
);
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
await act(async () => {
|
|
485
|
+
emitChatFirstOpenApp({ app: "mail" });
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
expect(
|
|
489
|
+
container.querySelector("[data-chat-first-app-pane]"),
|
|
490
|
+
).not.toBeNull();
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
it("opens a connected built-in when mounted workspace-app discovery fails", async () => {
|
|
494
|
+
clientState.workspaceAppsError = new Error("Workspace apps unavailable");
|
|
495
|
+
clientState.connectedApps = [
|
|
496
|
+
{
|
|
497
|
+
id: "clips",
|
|
498
|
+
name: "Clips",
|
|
499
|
+
url: "https://clips.agent-native.com",
|
|
500
|
+
source: "builtin",
|
|
501
|
+
},
|
|
502
|
+
];
|
|
503
|
+
|
|
504
|
+
await act(async () => {
|
|
505
|
+
root.render(
|
|
506
|
+
<MemoryRouter initialEntries={["/chat/builtin-mounted-error"]}>
|
|
507
|
+
<Layout extensions={{ chatFirst: true }}>
|
|
508
|
+
<div />
|
|
509
|
+
</Layout>
|
|
510
|
+
</MemoryRouter>,
|
|
511
|
+
);
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
await act(async () => {
|
|
515
|
+
emitChatFirstOpenApp({ app: "clips" });
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
expect(
|
|
519
|
+
container.querySelector("[data-chat-first-app-pane]"),
|
|
520
|
+
).not.toBeNull();
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
it("retries an app open after connected built-in discovery recovers", async () => {
|
|
524
|
+
clientState.workspaceApps = [
|
|
525
|
+
{
|
|
526
|
+
id: "mail",
|
|
527
|
+
name: "Mail",
|
|
528
|
+
path: "/mail",
|
|
529
|
+
url: "/mail",
|
|
530
|
+
status: "ready",
|
|
531
|
+
},
|
|
532
|
+
];
|
|
533
|
+
clientState.connectedAppsError = new Error("Connected apps unavailable");
|
|
534
|
+
|
|
535
|
+
await act(async () => {
|
|
536
|
+
root.render(
|
|
537
|
+
<MemoryRouter initialEntries={["/chat/discovery-retry"]}>
|
|
538
|
+
<Layout extensions={{ chatFirst: true }}>
|
|
539
|
+
<div />
|
|
540
|
+
</Layout>
|
|
541
|
+
</MemoryRouter>,
|
|
542
|
+
);
|
|
543
|
+
});
|
|
544
|
+
await act(async () => {
|
|
545
|
+
emitChatFirstOpenApp({ app: "clips" });
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
expect(container.querySelector("[data-chat-first-app-pane]")).toBeNull();
|
|
549
|
+
|
|
550
|
+
clientState.connectedAppsError = null;
|
|
551
|
+
clientState.connectedApps = [
|
|
552
|
+
{
|
|
553
|
+
id: "clips",
|
|
554
|
+
name: "Clips",
|
|
555
|
+
url: "https://clips.agent-native.com",
|
|
556
|
+
source: "builtin",
|
|
557
|
+
},
|
|
558
|
+
];
|
|
559
|
+
await act(async () => {
|
|
560
|
+
root.render(
|
|
561
|
+
<MemoryRouter initialEntries={["/chat/review-fixture"]}>
|
|
562
|
+
<Layout extensions={{ chatFirst: true }}>
|
|
563
|
+
<div />
|
|
564
|
+
</Layout>
|
|
565
|
+
</MemoryRouter>,
|
|
566
|
+
);
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
expect(
|
|
570
|
+
container.querySelector("[data-chat-first-app-pane]"),
|
|
571
|
+
).not.toBeNull();
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
it("keeps hidden Dispatch registered for agent app targets", async () => {
|
|
575
|
+
clientState.workspaceApps = [
|
|
576
|
+
{
|
|
577
|
+
id: "dispatch",
|
|
578
|
+
name: "Dispatch",
|
|
579
|
+
path: "/dispatch",
|
|
580
|
+
url: "https://dispatch.agent-native.com",
|
|
581
|
+
isDispatch: true,
|
|
582
|
+
status: "ready",
|
|
583
|
+
},
|
|
584
|
+
];
|
|
585
|
+
|
|
586
|
+
await act(async () => {
|
|
587
|
+
root.render(
|
|
588
|
+
<MemoryRouter initialEntries={["/chat/review-fixture"]}>
|
|
589
|
+
<Layout extensions={{ chatFirst: true }}>
|
|
590
|
+
<div />
|
|
591
|
+
</Layout>
|
|
592
|
+
</MemoryRouter>,
|
|
593
|
+
);
|
|
594
|
+
});
|
|
595
|
+
await act(async () => {
|
|
596
|
+
emitChatFirstOpenApp({ app: "dispatch" });
|
|
597
|
+
});
|
|
598
|
+
|
|
599
|
+
expect(container.querySelector(".dispatch-chat-first-notice")).toBeNull();
|
|
600
|
+
});
|
|
601
|
+
|
|
602
|
+
it("does not restore a deferred pane after switching chats", async () => {
|
|
603
|
+
clientState.connectedAppsLoading = true;
|
|
604
|
+
clientState.appState[CHAT_FIRST_PANE_STATE_KEY] = {
|
|
605
|
+
appId: "clips",
|
|
606
|
+
path: "/inbox",
|
|
607
|
+
};
|
|
608
|
+
const onPathChange = vi.fn();
|
|
609
|
+
const renderLayout = () => (
|
|
610
|
+
<MemoryRouter initialEntries={["/chat/pane-restore"]}>
|
|
611
|
+
<Layout extensions={{ chatFirst: true }}>
|
|
612
|
+
<ChatRouteSwitcher target="/chat/next-chat" />
|
|
613
|
+
</Layout>
|
|
614
|
+
<LocationProbe onChange={onPathChange} />
|
|
615
|
+
</MemoryRouter>
|
|
616
|
+
);
|
|
617
|
+
|
|
618
|
+
await act(async () => {
|
|
619
|
+
root.render(renderLayout());
|
|
620
|
+
});
|
|
621
|
+
expect(container.querySelector("[data-chat-first-app-pane]")).toBeNull();
|
|
622
|
+
|
|
623
|
+
await act(async () => {
|
|
624
|
+
[...container.querySelectorAll("button")]
|
|
625
|
+
.find((button) => button.textContent === "Switch chat")
|
|
626
|
+
?.click();
|
|
627
|
+
});
|
|
628
|
+
expect(onPathChange).toHaveBeenLastCalledWith("/chat/next-chat");
|
|
629
|
+
|
|
630
|
+
clientState.connectedAppsLoading = false;
|
|
631
|
+
clientState.connectedApps = [
|
|
632
|
+
{
|
|
633
|
+
id: "clips",
|
|
634
|
+
name: "Clips",
|
|
635
|
+
url: "https://clips.agent-native.com",
|
|
636
|
+
source: "builtin",
|
|
637
|
+
},
|
|
638
|
+
];
|
|
639
|
+
await act(async () => {
|
|
640
|
+
root.render(renderLayout());
|
|
641
|
+
});
|
|
642
|
+
|
|
643
|
+
expect(container.querySelector("[data-chat-first-app-pane]")).toBeNull();
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
it("ignores pane hydration that finishes after switching chats", async () => {
|
|
647
|
+
let resolvePaneState!: (value: unknown) => void;
|
|
648
|
+
clientState.appStatePromises[CHAT_FIRST_PANE_STATE_KEY] = new Promise(
|
|
649
|
+
(resolve) => {
|
|
650
|
+
resolvePaneState = resolve;
|
|
651
|
+
},
|
|
652
|
+
);
|
|
653
|
+
clientState.connectedApps = [
|
|
654
|
+
{
|
|
655
|
+
id: "clips",
|
|
656
|
+
name: "Clips",
|
|
657
|
+
url: "https://clips.agent-native.com",
|
|
658
|
+
source: "builtin",
|
|
659
|
+
},
|
|
660
|
+
];
|
|
661
|
+
const onPathChange = vi.fn();
|
|
662
|
+
const renderLayout = () => (
|
|
663
|
+
<MemoryRouter initialEntries={["/chat/pane-read-hydration"]}>
|
|
664
|
+
<Layout extensions={{ chatFirst: true }}>
|
|
665
|
+
<ChatRouteSwitcher target="/chat/new-scope" />
|
|
666
|
+
</Layout>
|
|
667
|
+
<LocationProbe onChange={onPathChange} />
|
|
668
|
+
</MemoryRouter>
|
|
669
|
+
);
|
|
670
|
+
|
|
671
|
+
await act(async () => {
|
|
672
|
+
root.render(renderLayout());
|
|
673
|
+
});
|
|
674
|
+
await act(async () => {
|
|
675
|
+
[...container.querySelectorAll("button")]
|
|
676
|
+
.find((button) => button.textContent === "Switch chat")
|
|
677
|
+
?.click();
|
|
678
|
+
});
|
|
679
|
+
expect(onPathChange).toHaveBeenLastCalledWith("/chat/new-scope");
|
|
680
|
+
|
|
681
|
+
await act(async () => {
|
|
682
|
+
resolvePaneState({ appId: "clips", path: "/inbox" });
|
|
683
|
+
});
|
|
684
|
+
|
|
685
|
+
expect(container.querySelector("[data-chat-first-app-pane]")).toBeNull();
|
|
686
|
+
});
|
|
687
|
+
|
|
688
|
+
it("opens connected built-ins from the chat-first app rail", async () => {
|
|
689
|
+
clientState.connectedApps = [
|
|
690
|
+
{
|
|
691
|
+
id: "clips",
|
|
692
|
+
name: "Clips",
|
|
693
|
+
url: "https://clips.agent-native.com",
|
|
694
|
+
source: "builtin",
|
|
695
|
+
},
|
|
696
|
+
];
|
|
697
|
+
|
|
698
|
+
await act(async () => {
|
|
699
|
+
root.render(
|
|
700
|
+
<MemoryRouter initialEntries={["/chat/rail-built-in"]}>
|
|
701
|
+
<Layout extensions={{ chatFirst: true }}>
|
|
702
|
+
<div />
|
|
703
|
+
</Layout>
|
|
704
|
+
</MemoryRouter>,
|
|
705
|
+
);
|
|
706
|
+
});
|
|
707
|
+
await act(async () => {
|
|
708
|
+
const clipsApp = container.querySelector<HTMLElement>(
|
|
709
|
+
'[data-chat-first-app][data-app-id="clips"]',
|
|
710
|
+
);
|
|
711
|
+
const openButton =
|
|
712
|
+
clipsApp?.querySelector<HTMLButtonElement>("button") ??
|
|
713
|
+
(clipsApp as HTMLButtonElement | null);
|
|
714
|
+
openButton?.click();
|
|
715
|
+
});
|
|
716
|
+
|
|
717
|
+
expect(workspaceAppNavigation.navigateToWorkspaceApp).toHaveBeenCalledWith(
|
|
718
|
+
"https://clips.agent-native.com/home",
|
|
719
|
+
);
|
|
720
|
+
});
|
|
721
|
+
|
|
722
|
+
it("restores a mounted pane without waiting for optional built-in discovery", async () => {
|
|
723
|
+
clientState.workspaceApps = [
|
|
724
|
+
{
|
|
725
|
+
id: "mail",
|
|
726
|
+
name: "Mail",
|
|
727
|
+
path: "/mail",
|
|
728
|
+
url: "/mail",
|
|
729
|
+
status: "ready",
|
|
730
|
+
},
|
|
731
|
+
];
|
|
732
|
+
clientState.connectedAppsLoading = true;
|
|
733
|
+
clientState.appState[CHAT_FIRST_PANE_STATE_KEY] = {
|
|
734
|
+
appId: "mail",
|
|
735
|
+
path: "/inbox",
|
|
736
|
+
};
|
|
737
|
+
|
|
738
|
+
await act(async () => {
|
|
739
|
+
root.render(
|
|
740
|
+
<MemoryRouter initialEntries={["/chat/review-fixture"]}>
|
|
741
|
+
<Layout extensions={{ chatFirst: true }}>
|
|
742
|
+
<div />
|
|
743
|
+
</Layout>
|
|
744
|
+
</MemoryRouter>,
|
|
745
|
+
);
|
|
746
|
+
});
|
|
747
|
+
|
|
748
|
+
expect(
|
|
749
|
+
container.querySelector("[data-chat-first-app-pane]"),
|
|
750
|
+
).not.toBeNull();
|
|
751
|
+
});
|
|
752
|
+
|
|
362
753
|
it("puts Overview before Chat in the primary navigation", async () => {
|
|
363
754
|
await act(async () => {
|
|
364
755
|
root.render(
|